@m6d/cortex-server 1.1.1 → 1.1.2

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 (42) hide show
  1. package/README.md +38 -38
  2. package/dist/src/factory.d.ts +13 -1
  3. package/dist/src/ws/index.d.ts +1 -1
  4. package/package.json +54 -54
  5. package/src/adapters/database.ts +21 -28
  6. package/src/adapters/minio.ts +69 -69
  7. package/src/adapters/mssql.ts +171 -195
  8. package/src/adapters/storage.ts +4 -4
  9. package/src/ai/fetch.ts +31 -31
  10. package/src/ai/helpers.ts +18 -22
  11. package/src/ai/index.ts +101 -113
  12. package/src/ai/interceptors/resolve-captured-files.ts +42 -49
  13. package/src/ai/prompt.ts +80 -83
  14. package/src/ai/tools/call-endpoint.tool.ts +75 -82
  15. package/src/ai/tools/capture-files.tool.ts +15 -17
  16. package/src/ai/tools/execute-code.tool.ts +73 -80
  17. package/src/ai/tools/query-graph.tool.ts +17 -17
  18. package/src/auth/middleware.ts +51 -51
  19. package/src/cli/extract-endpoints.ts +436 -474
  20. package/src/config.ts +124 -134
  21. package/src/db/migrate.ts +13 -13
  22. package/src/db/migrations/20260309012148_cloudy_maria_hill/snapshot.json +303 -303
  23. package/src/db/schema.ts +46 -58
  24. package/src/factory.ts +136 -139
  25. package/src/graph/generate-cypher.ts +97 -97
  26. package/src/graph/helpers.ts +37 -37
  27. package/src/graph/index.ts +20 -20
  28. package/src/graph/neo4j.ts +82 -89
  29. package/src/graph/resolver.ts +201 -211
  30. package/src/graph/seed.ts +101 -114
  31. package/src/graph/types.ts +88 -88
  32. package/src/graph/validate.ts +55 -57
  33. package/src/index.ts +5 -5
  34. package/src/routes/chat.ts +23 -23
  35. package/src/routes/files.ts +75 -80
  36. package/src/routes/threads.ts +52 -54
  37. package/src/routes/ws.ts +22 -22
  38. package/src/types.ts +30 -30
  39. package/src/ws/connections.ts +11 -11
  40. package/src/ws/events.ts +2 -2
  41. package/src/ws/index.ts +1 -5
  42. package/src/ws/notify.ts +4 -4
package/README.md CHANGED
@@ -8,50 +8,50 @@ Multi-agent AI chat server built on Hono + Bun. Supports MSSQL persistence, MinI
8
8
  import { createCortex } from "@m6d/cortex-server";
9
9
 
10
10
  const cortex = createCortex({
11
- database: {
12
- type: "mssql",
13
- connectionString: process.env.DB_CONNECTION_STRING!,
14
- },
15
- storage: {
16
- endPoint: "localhost",
17
- port: 9000,
18
- useSSL: false,
19
- accessKey: "minioadmin",
20
- secretKey: "minioadmin",
21
- },
22
- auth: {
23
- jwksUri: "https://your-auth-provider/.well-known/jwks.json",
24
- issuer: "https://your-auth-provider/",
25
- },
26
- model: {
27
- baseURL: "https://api.openai.com/v1",
28
- apiKey: process.env.MODEL_KEY!,
29
- modelName: "gpt-4o",
30
- },
31
- embedding: {
32
- baseURL: "https://api.openai.com/v1",
33
- apiKey: process.env.EMBEDDING_KEY!,
34
- modelName: "text-embedding-3-small",
35
- dimension: 1536,
36
- },
37
- neo4j: {
38
- url: "bolt://localhost:7687",
39
- user: "neo4j",
40
- password: "password",
41
- },
42
- agents: {
43
- assistant: {
44
- systemPrompt: "You are a helpful assistant.",
45
- tools: {},
11
+ database: {
12
+ type: "mssql",
13
+ connectionString: process.env.DB_CONNECTION_STRING!,
14
+ },
15
+ storage: {
16
+ endPoint: "localhost",
17
+ port: 9000,
18
+ useSSL: false,
19
+ accessKey: "minioadmin",
20
+ secretKey: "minioadmin",
21
+ },
22
+ auth: {
23
+ jwksUri: "https://your-auth-provider/.well-known/jwks.json",
24
+ issuer: "https://your-auth-provider/",
25
+ },
26
+ model: {
27
+ baseURL: "https://api.openai.com/v1",
28
+ apiKey: process.env.MODEL_KEY!,
29
+ modelName: "gpt-4o",
30
+ },
31
+ embedding: {
32
+ baseURL: "https://api.openai.com/v1",
33
+ apiKey: process.env.EMBEDDING_KEY!,
34
+ modelName: "text-embedding-3-small",
35
+ dimension: 1536,
36
+ },
37
+ neo4j: {
38
+ url: "bolt://localhost:7687",
39
+ user: "neo4j",
40
+ password: "password",
41
+ },
42
+ agents: {
43
+ assistant: {
44
+ systemPrompt: "You are a helpful assistant.",
45
+ tools: {},
46
+ },
46
47
  },
47
- },
48
48
  });
49
49
 
50
50
  const server = await cortex.serve();
51
51
 
52
52
  export default {
53
- fetch: server.fetch,
54
- websocket: server.websocket,
53
+ fetch: server.fetch,
54
+ websocket: server.websocket,
55
55
  };
56
56
  ```
57
57
 
@@ -15,4 +15,16 @@ export type CortexInstance = {
15
15
  write?: boolean;
16
16
  }): Promise<void>;
17
17
  };
18
- export declare function createCortex(config: CortexConfig): CortexInstance;
18
+ export declare function createCortex(config: CortexConfig): {
19
+ serve(): Promise<{
20
+ app: Hono<AppEnv, import("hono/types").BlankSchema, "/">;
21
+ port: number;
22
+ fetch: (request: Request, Env?: {} | undefined, executionCtx?: import("hono").ExecutionContext) => Response | Promise<Response>;
23
+ websocket: import("hono/bun").BunWebSocketHandler<import("hono/bun").BunWebSocketData>;
24
+ }>;
25
+ seedGraph(): Promise<void>;
26
+ extractEndpoints(options: {
27
+ domainsDir: string;
28
+ write?: boolean;
29
+ }): Promise<void>;
30
+ };
@@ -1,3 +1,3 @@
1
- export { addConnection, removeConnection, getConnections, } from "./connections.ts";
1
+ export { addConnection, removeConnection, getConnections } from "./connections.ts";
2
2
  export { notify } from "./notify.ts";
3
3
  export type { WsEvent, ThreadTitleUpdatedEvent } from "./events.ts";
package/package.json CHANGED
@@ -1,57 +1,57 @@
1
1
  {
2
- "name": "@m6d/cortex-server",
3
- "version": "1.1.1",
4
- "description": "Reusable AI agent chat server library for Hono + Bun",
5
- "license": "MIT",
6
- "type": "module",
7
- "exports": {
8
- ".": {
9
- "types": "./dist/index.d.ts",
10
- "bun": "./index.ts",
11
- "default": "./index.ts"
2
+ "name": "@m6d/cortex-server",
3
+ "version": "1.1.2",
4
+ "description": "Reusable AI agent chat server library for Hono + Bun",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "bun": "./index.ts",
11
+ "default": "./index.ts"
12
+ }
13
+ },
14
+ "main": "./index.ts",
15
+ "types": "./dist/index.d.ts",
16
+ "files": [
17
+ "dist",
18
+ "src",
19
+ "index.ts",
20
+ "README.md"
21
+ ],
22
+ "scripts": {
23
+ "build": "tsc -p tsconfig.build.json",
24
+ "db:generate": "drizzle-kit generate",
25
+ "db:migrate": "drizzle-kit migrate"
26
+ },
27
+ "dependencies": {
28
+ "@ai-sdk/provider": "^3.0.0",
29
+ "@hono/zod-validator": "^0.5.0",
30
+ "drizzle-orm": "^1.0.0-beta.15-859cf75",
31
+ "minio": "^8.0.7",
32
+ "mssql": "^12.2.0"
33
+ },
34
+ "devDependencies": {
35
+ "@ai-sdk/openai-compatible": "^2.0.0",
36
+ "@types/bun": "latest",
37
+ "@types/minio": "^7.1.1",
38
+ "@types/mssql": "^9.1.5",
39
+ "ai": "^6.0.104",
40
+ "drizzle-kit": "^1.0.0-beta.15-859cf75",
41
+ "hono": "^4.12.3",
42
+ "typescript": "^5"
43
+ },
44
+ "peerDependencies": {
45
+ "@ai-sdk/openai-compatible": "^2.0.0",
46
+ "ai": "^6.0.0",
47
+ "hono": "^4.12.3",
48
+ "jose": "^6.1.3",
49
+ "zod": "^3.24.0"
50
+ },
51
+ "engines": {
52
+ "bun": ">=1.0.0"
53
+ },
54
+ "publishConfig": {
55
+ "access": "public"
12
56
  }
13
- },
14
- "main": "./index.ts",
15
- "types": "./dist/index.d.ts",
16
- "files": [
17
- "dist",
18
- "src",
19
- "index.ts",
20
- "README.md"
21
- ],
22
- "scripts": {
23
- "build": "tsc -p tsconfig.build.json",
24
- "db:generate": "drizzle-kit generate",
25
- "db:migrate": "drizzle-kit migrate"
26
- },
27
- "dependencies": {
28
- "@ai-sdk/provider": "^3.0.0",
29
- "@hono/zod-validator": "^0.5.0",
30
- "drizzle-orm": "^1.0.0-beta.15-859cf75",
31
- "minio": "^8.0.7",
32
- "mssql": "^12.2.0"
33
- },
34
- "devDependencies": {
35
- "@ai-sdk/openai-compatible": "^2.0.0",
36
- "@types/bun": "latest",
37
- "@types/minio": "^7.1.1",
38
- "@types/mssql": "^9.1.5",
39
- "ai": "^6.0.104",
40
- "drizzle-kit": "^1.0.0-beta.15-859cf75",
41
- "hono": "^4.12.3",
42
- "typescript": "^5"
43
- },
44
- "peerDependencies": {
45
- "@ai-sdk/openai-compatible": "^2.0.0",
46
- "ai": "^6.0.0",
47
- "hono": "^4.12.3",
48
- "jose": "^6.1.3",
49
- "zod": "^3.24.0"
50
- },
51
- "engines": {
52
- "bun": ">=1.0.0"
53
- },
54
- "publishConfig": {
55
- "access": "public"
56
- }
57
57
  }
@@ -2,32 +2,25 @@ import type { ToolUIPart, UIMessage } from "ai";
2
2
  import type { Thread, StoredMessage, CapturedFileInput } from "../types";
3
3
 
4
4
  export type DatabaseAdapter = {
5
- threads: {
6
- list(userId: string, agentId: string): Promise<Thread[]>;
7
- getById(userId: string, threadId: string): Promise<Thread | null>;
8
- create(userId: string, agentId: string): Promise<Thread>;
9
- delete(userId: string, threadId: string): Promise<void>;
10
- updateTitle(threadId: string, title: string): Promise<void>;
11
- updateSession(
12
- threadId: string,
13
- session: Record<string, unknown>,
14
- ): Promise<void>;
15
- };
16
- messages: {
17
- list(
18
- userId: string,
19
- threadId: string,
20
- opts?: { limit?: number },
21
- ): Promise<StoredMessage[]>;
22
- upsert(threadId: string, messages: UIMessage[]): Promise<void>;
23
- };
24
- capturedFiles: {
25
- create(
26
- userId: string,
27
- messageId: string,
28
- toolPart: ToolUIPart,
29
- files: CapturedFileInput[],
30
- ): Promise<{ id: string; uploadId: string }[]>;
31
- getById(id: string, userId: string): Promise<{ name: string } | null>;
32
- };
5
+ threads: {
6
+ list(userId: string, agentId: string): Promise<Thread[]>;
7
+ getById(userId: string, threadId: string): Promise<Thread | null>;
8
+ create(userId: string, agentId: string): Promise<Thread>;
9
+ delete(userId: string, threadId: string): Promise<void>;
10
+ updateTitle(threadId: string, title: string): Promise<void>;
11
+ updateSession(threadId: string, session: Record<string, unknown>): Promise<void>;
12
+ };
13
+ messages: {
14
+ list(userId: string, threadId: string, opts?: { limit?: number }): Promise<StoredMessage[]>;
15
+ upsert(threadId: string, messages: UIMessage[]): Promise<void>;
16
+ };
17
+ capturedFiles: {
18
+ create(
19
+ userId: string,
20
+ messageId: string,
21
+ toolPart: ToolUIPart,
22
+ files: CapturedFileInput[],
23
+ ): Promise<{ id: string; uploadId: string }[]>;
24
+ getById(id: string, userId: string): Promise<{ name: string } | null>;
25
+ };
33
26
  };
@@ -3,87 +3,87 @@ import { Readable } from "node:stream";
3
3
  import type { StorageAdapter } from "./storage";
4
4
 
5
5
  export type MinioConfig = {
6
- endPoint: string;
7
- port: number;
8
- useSSL: boolean;
9
- accessKey: string;
10
- secretKey: string;
11
- bucketName?: string;
6
+ endPoint: string;
7
+ port: number;
8
+ useSSL: boolean;
9
+ accessKey: string;
10
+ secretKey: string;
11
+ bucketName?: string;
12
12
  };
13
13
 
14
14
  export function createMinioAdapter(config: MinioConfig) {
15
- if (!config.endPoint) {
16
- throw new Error("MinIO adapter: endPoint is required");
17
- }
15
+ if (!config.endPoint) {
16
+ throw new Error("MinIO adapter: endPoint is required");
17
+ }
18
18
 
19
- const client = new Minio.Client({
20
- endPoint: config.endPoint,
21
- port: config.port,
22
- useSSL: config.useSSL,
23
- accessKey: config.accessKey,
24
- secretKey: config.secretKey,
25
- });
19
+ const client = new Minio.Client({
20
+ endPoint: config.endPoint,
21
+ port: config.port,
22
+ useSSL: config.useSSL,
23
+ accessKey: config.accessKey,
24
+ secretKey: config.secretKey,
25
+ });
26
26
 
27
- const bucketName = config.bucketName ?? "ai-storage";
28
- let bucketReady = false;
27
+ const bucketName = config.bucketName ?? "ai-storage";
28
+ let bucketReady = false;
29
29
 
30
- async function ensureBucket() {
31
- if (bucketReady) return;
32
- if (!(await client.bucketExists(bucketName))) {
33
- await client.makeBucket(bucketName);
30
+ async function ensureBucket() {
31
+ if (bucketReady) return;
32
+ if (!(await client.bucketExists(bucketName))) {
33
+ await client.makeBucket(bucketName);
34
+ }
35
+ bucketReady = true;
34
36
  }
35
- bucketReady = true;
36
- }
37
37
 
38
- const adapter: StorageAdapter = {
39
- async put(path: string, data: string) {
40
- try {
41
- await ensureBucket();
42
- await client.putObject(bucketName, path, Buffer.from(data, "base64"));
43
- return true;
44
- } catch {
45
- return false;
46
- }
47
- },
38
+ const adapter: StorageAdapter = {
39
+ async put(path: string, data: string) {
40
+ try {
41
+ await ensureBucket();
42
+ await client.putObject(bucketName, path, Buffer.from(data, "base64"));
43
+ return true;
44
+ } catch {
45
+ return false;
46
+ }
47
+ },
48
48
 
49
- async get(path: string) {
50
- try {
51
- const stream = await client.getObject(bucketName, path);
52
- return await new Promise<string>((resolve, reject) => {
53
- const chunks: Uint8Array[] = [];
49
+ async get(path: string) {
50
+ try {
51
+ const stream = await client.getObject(bucketName, path);
52
+ return await new Promise<string>((resolve, reject) => {
53
+ const chunks: Uint8Array[] = [];
54
54
 
55
- stream.on("error", () => {
56
- reject();
57
- });
55
+ stream.on("error", () => {
56
+ reject();
57
+ });
58
58
 
59
- stream.on("data", (chunk) => chunks.push(chunk));
60
- stream.on("end", () => {
61
- const buffer = Buffer.concat(chunks);
62
- resolve(buffer.toString("base64"));
63
- });
64
- });
65
- } catch {
66
- return false;
67
- }
68
- },
59
+ stream.on("data", (chunk) => chunks.push(chunk));
60
+ stream.on("end", () => {
61
+ const buffer = Buffer.concat(chunks);
62
+ resolve(buffer.toString("base64"));
63
+ });
64
+ });
65
+ } catch {
66
+ return false;
67
+ }
68
+ },
69
69
 
70
- async delete(paths: string[]) {
71
- try {
72
- await client.removeObjects(
73
- bucketName,
74
- paths.map((x) => ({ name: x })),
75
- );
76
- return true;
77
- } catch {
78
- return false;
79
- }
80
- },
70
+ async delete(paths: string[]) {
71
+ try {
72
+ await client.removeObjects(
73
+ bucketName,
74
+ paths.map((x) => ({ name: x })),
75
+ );
76
+ return true;
77
+ } catch {
78
+ return false;
79
+ }
80
+ },
81
81
 
82
- async stream(path: string) {
83
- const nodeStream = await client.getObject(bucketName, path);
84
- return Readable.toWeb(nodeStream) as unknown as ReadableStream;
85
- },
86
- };
82
+ async stream(path: string) {
83
+ const nodeStream = await client.getObject(bucketName, path);
84
+ return Readable.toWeb(nodeStream) as unknown as ReadableStream;
85
+ },
86
+ };
87
87
 
88
- return adapter;
88
+ return adapter;
89
89
  }