@m6d/cortex-server 2.3.0 → 2.4.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/contracts/src/runtime/index.ts +99 -3
- package/dist/contracts/src/graph/helpers.d.ts +5 -5
- package/dist/contracts/src/runtime/index.d.ts +175 -3
- package/dist/src/lib/adapters/database/index.d.ts +20 -2
- package/dist/src/lib/adapters/database/mssql/attachments.d.ts +9 -9
- package/dist/src/lib/adapters/database/mssql/index.d.ts +133 -28
- package/dist/src/lib/adapters/database/mssql/llm-requests.d.ts +3 -2
- package/dist/src/lib/adapters/database/mssql/messages.d.ts +6 -5
- package/dist/src/lib/adapters/database/mssql/outbox.d.ts +103 -0
- package/dist/src/lib/adapters/database/mssql/threads.d.ts +21 -14
- package/dist/src/lib/adapters/database/postgres/attachments.d.ts +9 -9
- package/dist/src/lib/adapters/database/postgres/index.d.ts +133 -28
- package/dist/src/lib/adapters/database/postgres/llm-requests.d.ts +3 -2
- package/dist/src/lib/adapters/database/postgres/messages.d.ts +6 -5
- package/dist/src/lib/adapters/database/postgres/outbox.d.ts +103 -0
- package/dist/src/lib/adapters/database/postgres/threads.d.ts +21 -14
- package/dist/src/lib/ai/attachments.d.ts +2 -2
- package/dist/src/lib/ai/client-tools.d.ts +1 -1
- package/dist/src/lib/auth/middleware.d.ts +2 -2
- package/dist/src/lib/auth/playground.d.ts +14 -0
- package/dist/src/lib/cc/client.d.ts +9 -1
- package/dist/src/lib/cc/flusher.d.ts +40 -0
- package/dist/src/lib/cc/sync-events.d.ts +45 -0
- package/dist/src/lib/cc/types.d.ts +1 -1
- package/dist/src/lib/config.d.ts +11 -0
- package/dist/src/lib/db/schema.mssql.d.ts +161 -0
- package/dist/src/lib/db/schema.pg.d.ts +199 -0
- package/dist/src/lib/factory.d.ts +3 -0
- package/dist/src/lib/routes/owned-thread.d.ts +5 -4
- package/package.json +1 -1
- package/src/lib/adapters/database/index.ts +15 -1
- package/src/lib/adapters/database/mssql/index.ts +13 -4
- package/src/lib/adapters/database/mssql/llm-requests.ts +35 -15
- package/src/lib/adapters/database/mssql/messages.ts +81 -30
- package/src/lib/adapters/database/mssql/outbox.ts +71 -0
- package/src/lib/adapters/database/mssql/threads.ts +42 -11
- package/src/lib/adapters/database/postgres/index.ts +13 -4
- package/src/lib/adapters/database/postgres/llm-requests.ts +35 -15
- package/src/lib/adapters/database/postgres/messages.ts +81 -30
- package/src/lib/adapters/database/postgres/outbox.ts +66 -0
- package/src/lib/adapters/database/postgres/threads.ts +39 -11
- package/src/lib/ai/finish-turn.ts +3 -1
- package/src/lib/ai/prompt.ts +3 -1
- package/src/lib/auth/middleware.ts +34 -8
- package/src/lib/auth/playground.ts +72 -0
- package/src/lib/cc/client.ts +21 -1
- package/src/lib/cc/flusher.ts +147 -0
- package/src/lib/cc/sync-events.ts +65 -0
- package/src/lib/cc/types.ts +3 -0
- package/src/lib/config.ts +11 -0
- package/src/lib/db/migrations/mssql/20260829050547_friendly_red_shift/migration.sql +8 -0
- package/src/lib/db/migrations/mssql/20260829050547_friendly_red_shift/snapshot.json +581 -0
- package/src/lib/db/migrations/mssql/20260830022424_easy_nicolaos/migration.sql +5 -0
- package/src/lib/db/migrations/mssql/20260830022424_easy_nicolaos/snapshot.json +614 -0
- package/src/lib/db/migrations/pg/20260829050547_perfect_wildside/migration.sql +7 -0
- package/src/lib/db/migrations/pg/20260829050547_perfect_wildside/snapshot.json +650 -0
- package/src/lib/db/migrations/pg/20260830022424_serious_deadpool/migration.sql +4 -0
- package/src/lib/db/migrations/pg/20260830022424_serious_deadpool/snapshot.json +690 -0
- package/src/lib/db/schema.mssql.ts +32 -1
- package/src/lib/db/schema.pg.ts +24 -0
- package/src/lib/factory.ts +22 -8
- package/src/lib/routes/threads.ts +5 -1
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
// fallow-ignore-file duplicate-export -- mssql twin of schema.pg; table exports intentionally share names so the adapters stay symmetric
|
|
2
2
|
import { ATTACHMENT_STATUSES } from "@cortex/contracts/wire";
|
|
3
3
|
import { sql } from "drizzle-orm";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
bigint,
|
|
6
|
+
bit,
|
|
7
|
+
customType,
|
|
8
|
+
datetime2,
|
|
9
|
+
index,
|
|
10
|
+
int,
|
|
11
|
+
mssqlSchema,
|
|
12
|
+
nvarchar,
|
|
13
|
+
} from "drizzle-orm/mssql-core";
|
|
14
|
+
import type { SyncEvent } from "@cortex/contracts/runtime";
|
|
5
15
|
import type { ChatMessage, TokenUsage } from "@/types";
|
|
6
16
|
import type { ThreadContextMeta } from "@/ai/context/types";
|
|
7
17
|
|
|
@@ -30,6 +40,7 @@ export const threads = aiSchema.table("threads", {
|
|
|
30
40
|
userId: nvarchar({ length: 255 }).notNull(),
|
|
31
41
|
agentId: nvarchar({ length: 128 }).notNull().default("default"),
|
|
32
42
|
title: nvarchar({ length: 256 }),
|
|
43
|
+
isTest: bit().notNull().default(false),
|
|
33
44
|
session: nvarchar({ mode: "json", length: "max" }).$type<Record<string, unknown>>(),
|
|
34
45
|
contextMeta: nvarchar({ mode: "json", length: "max" }).$type<ThreadContextMeta>(),
|
|
35
46
|
...auditColumns,
|
|
@@ -92,3 +103,23 @@ export const attachments = aiSchema.table(
|
|
|
92
103
|
},
|
|
93
104
|
(table) => [index("attachments_thread_id_index").on(table.threadId)],
|
|
94
105
|
);
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Events awaiting the cc sync flusher. Insertion order (the identity id) is
|
|
109
|
+
* flush order; `ack` deletes.
|
|
110
|
+
*/
|
|
111
|
+
/** Single row naming this database's generation. `epoch` is minted on first
|
|
112
|
+
* flush and changes only when the database is recreated, letting cc tell a
|
|
113
|
+
* reset outbox sequence from a stale sync batch. */
|
|
114
|
+
export const syncMeta = aiSchema.table("sync_meta", {
|
|
115
|
+
id: int().primaryKey(),
|
|
116
|
+
epoch: nvarchar({ length: 36 }).notNull(),
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
export const syncOutbox = aiSchema.table("sync_outbox", {
|
|
120
|
+
id: bigint({ mode: "number" }).identity().primaryKey(),
|
|
121
|
+
event: nvarchar({ mode: "json", length: "max" }).notNull().$type<SyncEvent>(),
|
|
122
|
+
createdAt: datetime2({ mode: "date" })
|
|
123
|
+
.$default(() => new Date())
|
|
124
|
+
.notNull(),
|
|
125
|
+
});
|
package/src/lib/db/schema.pg.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { ATTACHMENT_STATUSES } from "@cortex/contracts/wire";
|
|
2
2
|
import {
|
|
3
|
+
bigserial,
|
|
4
|
+
boolean,
|
|
3
5
|
index,
|
|
4
6
|
integer,
|
|
5
7
|
jsonb,
|
|
@@ -9,6 +11,7 @@ import {
|
|
|
9
11
|
uuid,
|
|
10
12
|
varchar,
|
|
11
13
|
} from "drizzle-orm/pg-core";
|
|
14
|
+
import type { SyncEvent } from "@cortex/contracts/runtime";
|
|
12
15
|
import type { ChatMessage, TokenUsage } from "@/types";
|
|
13
16
|
import type { ThreadContextMeta } from "@/ai/context/types";
|
|
14
17
|
|
|
@@ -35,6 +38,7 @@ export const threads = aiSchema.table("threads", {
|
|
|
35
38
|
userId: varchar({ length: 255 }).notNull(),
|
|
36
39
|
agentId: varchar({ length: 128 }).notNull().default("default"),
|
|
37
40
|
title: varchar({ length: 256 }),
|
|
41
|
+
isTest: boolean().notNull().default(false),
|
|
38
42
|
session: jsonb().$type<Record<string, unknown>>(),
|
|
39
43
|
contextMeta: jsonb().$type<ThreadContextMeta>(),
|
|
40
44
|
...auditColumns,
|
|
@@ -93,3 +97,23 @@ export const attachments = aiSchema.table(
|
|
|
93
97
|
},
|
|
94
98
|
(table) => [index("attachments_thread_id_index").on(table.threadId)],
|
|
95
99
|
);
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Events awaiting the cc sync flusher. Insertion order (the bigserial id) is
|
|
103
|
+
* flush order; `ack` deletes.
|
|
104
|
+
*/
|
|
105
|
+
/** Single row naming this database's generation. `epoch` is minted on first
|
|
106
|
+
* flush and changes only when the database is recreated, letting cc tell a
|
|
107
|
+
* reset outbox sequence from a stale sync batch. */
|
|
108
|
+
export const syncMeta = aiSchema.table("sync_meta", {
|
|
109
|
+
id: integer().primaryKey(),
|
|
110
|
+
epoch: varchar({ length: 36 }).notNull(),
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
export const syncOutbox = aiSchema.table("sync_outbox", {
|
|
114
|
+
id: bigserial({ mode: "number" }).primaryKey(),
|
|
115
|
+
event: jsonb().notNull().$type<SyncEvent>(),
|
|
116
|
+
createdAt: timestamp({ mode: "date", withTimezone: true })
|
|
117
|
+
.$default(() => new Date())
|
|
118
|
+
.notNull(),
|
|
119
|
+
});
|
package/src/lib/factory.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { createPostgresAdapter } from "./adapters/database/postgres/index";
|
|
|
18
18
|
import { createMinioAdapter } from "./adapters/storage/minio";
|
|
19
19
|
import { ControlCenterClient } from "./cc/client";
|
|
20
20
|
import { getControlCenterConfig } from "./cc/config-cache";
|
|
21
|
+
import { startSyncFlusher } from "./cc/flusher";
|
|
21
22
|
import { AGENT_SLUG_PATTERN } from "./cc/types";
|
|
22
23
|
|
|
23
24
|
export type CortexInstance = {
|
|
@@ -27,30 +28,39 @@ export type CortexInstance = {
|
|
|
27
28
|
fetch: Hono<AppEnv>["fetch"];
|
|
28
29
|
websocket: typeof websocket;
|
|
29
30
|
}>;
|
|
31
|
+
/** Stops the cc sync flusher (a no-op before `serve` or without cc). */
|
|
32
|
+
stop(): void;
|
|
30
33
|
};
|
|
31
34
|
|
|
32
35
|
export function createCortex(config: CortexConfig) {
|
|
36
|
+
let stopFlusher: (() => void) | undefined;
|
|
37
|
+
|
|
33
38
|
return {
|
|
34
39
|
async serve() {
|
|
35
40
|
const storage = config.storage ? createMinioAdapter(config.storage) : undefined;
|
|
36
|
-
const createAdapter =
|
|
37
|
-
config.database.type === "postgres" ? createPostgresAdapter : createMssqlAdapter;
|
|
38
|
-
const db = createAdapter(config.database.connectionString, storage);
|
|
39
41
|
const ccClient = config.controlCenter
|
|
40
42
|
? new ControlCenterClient(config.controlCenter)
|
|
41
43
|
: null;
|
|
44
|
+
const createAdapter =
|
|
45
|
+
config.database.type === "postgres" ? createPostgresAdapter : createMssqlAdapter;
|
|
46
|
+
const db = createAdapter(config.database.connectionString, storage, {
|
|
47
|
+
// Mirror events are only worth writing when a flusher exists
|
|
48
|
+
// to drain them to cc.
|
|
49
|
+
syncMirror: ccClient !== null,
|
|
50
|
+
});
|
|
42
51
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
);
|
|
52
|
+
const redis = config.redis ? getRedisConnections(config.redis.url) : undefined;
|
|
53
|
+
if (redis && config.redis) {
|
|
54
|
+
configureRunCoordination(createRedisRuns(redis, config.redis));
|
|
47
55
|
}
|
|
48
56
|
|
|
49
57
|
await runMigrations(config.database);
|
|
50
58
|
|
|
59
|
+
if (ccClient) stopFlusher = startSyncFlusher(db, ccClient, redis?.publisher);
|
|
60
|
+
|
|
51
61
|
const app = new Hono<AppEnv>();
|
|
52
62
|
|
|
53
|
-
const userLoader = createUserLoaderMiddleware(config.auth);
|
|
63
|
+
const userLoader = createUserLoaderMiddleware(config.auth, config.controlCenter);
|
|
54
64
|
app.use("*", userLoader);
|
|
55
65
|
|
|
56
66
|
// Compatibility WebSocket route
|
|
@@ -123,5 +133,9 @@ export function createCortex(config: CortexConfig) {
|
|
|
123
133
|
websocket,
|
|
124
134
|
};
|
|
125
135
|
},
|
|
136
|
+
|
|
137
|
+
stop() {
|
|
138
|
+
stopFlusher?.();
|
|
139
|
+
},
|
|
126
140
|
} satisfies CortexInstance;
|
|
127
141
|
}
|
|
@@ -3,6 +3,7 @@ import { zValidator } from "@hono/zod-validator";
|
|
|
3
3
|
import z from "zod";
|
|
4
4
|
import type { CortexAppEnv } from "@/types";
|
|
5
5
|
import { requireAuth } from "@/auth/middleware";
|
|
6
|
+
import { isPlaygroundRequest } from "@/auth/playground";
|
|
6
7
|
import { abortRun, runningThreadIds } from "@/ai/active-runs";
|
|
7
8
|
import { notify } from "@/ws/connections";
|
|
8
9
|
import { requireOwnedThread } from "./owned-thread";
|
|
@@ -27,7 +28,10 @@ export function createThreadRoutes() {
|
|
|
27
28
|
const config = c.get("agentConfig");
|
|
28
29
|
const agentId = c.get("agentId");
|
|
29
30
|
const userId = c.get("user").id;
|
|
30
|
-
|
|
31
|
+
// A verified cc-signed header marks the thread as playground test
|
|
32
|
+
// data — excluded from stats and badged in cc's browser.
|
|
33
|
+
const isTest = await isPlaygroundRequest(config.controlCenter, c.req.raw);
|
|
34
|
+
const thread = await config.db.threads.create(userId, agentId, { isTest });
|
|
31
35
|
|
|
32
36
|
notify(userId, agentId, {
|
|
33
37
|
type: "thread:created",
|