@m6d/cortex-server 1.1.2 → 1.3.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/src/ai/index.d.ts +1 -1
- package/dist/src/ai/interceptors/{resolve-captured-files.d.ts → request-interceptor.d.ts} +3 -2
- package/dist/src/config.d.ts +6 -3
- package/dist/src/index.d.ts +2 -0
- package/dist/src/ws/events.d.ts +7 -1
- package/dist/src/ws/index.d.ts +1 -1
- package/package.json +3 -2
- package/src/adapters/mssql.ts +9 -13
- package/src/ai/index.ts +51 -6
- package/src/ai/interceptors/{resolve-captured-files.ts → request-interceptor.ts} +7 -3
- package/src/ai/tools/execute-code.tool.ts +79 -27
- package/src/config.ts +6 -3
- package/src/index.ts +7 -0
- package/src/routes/chat.ts +1 -1
- package/src/ws/events.ts +6 -1
- package/src/ws/index.ts +1 -1
package/dist/src/ai/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ResolvedCortexAgentConfig } from "../config.ts";
|
|
2
2
|
import type { Thread } from "../types.ts";
|
|
3
|
-
export declare function stream(messages: unknown[], thread: Thread, userId: string, token: string, config: ResolvedCortexAgentConfig): Promise<Response>;
|
|
3
|
+
export declare function stream(messages: unknown[], thread: Thread, userId: string, token: string, config: ResolvedCortexAgentConfig, abortSignal?: AbortSignal): Promise<Response>;
|
|
4
4
|
export declare function generateTitle(threadId: string, prompt: string, userId: string, config: ResolvedCortexAgentConfig): Promise<void>;
|
|
@@ -4,8 +4,9 @@ export type ResolvedFile = {
|
|
|
4
4
|
name: string;
|
|
5
5
|
bytes: string;
|
|
6
6
|
};
|
|
7
|
-
export
|
|
7
|
+
export type RequestInterceptorOptions = {
|
|
8
8
|
transformFile?: (file: ResolvedFile) => unknown;
|
|
9
|
-
}
|
|
9
|
+
};
|
|
10
|
+
export declare function createRequestInterceptor(db: DatabaseAdapter, storage: StorageAdapter, options?: RequestInterceptorOptions): (body: Record<string, unknown>, context: {
|
|
10
11
|
token: string;
|
|
11
12
|
}) => Promise<Record<string, unknown>>;
|
package/dist/src/config.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { UIMessage } from "ai";
|
|
1
|
+
import type { ToolSet, UIMessage } from "ai";
|
|
2
2
|
import type { DatabaseAdapter } from "./adapters/database";
|
|
3
3
|
import type { StorageAdapter } from "./adapters/storage";
|
|
4
4
|
import type { DomainDef } from "./graph/types.ts";
|
|
5
|
+
import type { RequestInterceptorOptions } from "./ai/interceptors/request-interceptor.ts";
|
|
5
6
|
export type KnowledgeConfig = {
|
|
6
7
|
swagger?: {
|
|
7
8
|
url: string;
|
|
@@ -22,7 +23,7 @@ export type StorageConfig = {
|
|
|
22
23
|
};
|
|
23
24
|
export type CortexAgentDefinition = {
|
|
24
25
|
systemPrompt: string | ((session: Record<string, unknown> | null) => string | Promise<string>);
|
|
25
|
-
tools?:
|
|
26
|
+
tools?: ToolSet;
|
|
26
27
|
backendFetch?: {
|
|
27
28
|
baseUrl: string;
|
|
28
29
|
apiKey: string;
|
|
@@ -30,6 +31,7 @@ export type CortexAgentDefinition = {
|
|
|
30
31
|
transformRequestBody?: (body: Record<string, unknown>, context: {
|
|
31
32
|
token: string;
|
|
32
33
|
}) => Promise<Record<string, unknown>>;
|
|
34
|
+
interceptor?: RequestInterceptorOptions;
|
|
33
35
|
};
|
|
34
36
|
loadSessionData?: (token: string) => Promise<Record<string, unknown>>;
|
|
35
37
|
onToolCall?: (toolCall: {
|
|
@@ -89,7 +91,7 @@ export type ResolvedCortexAgentConfig = {
|
|
|
89
91
|
apiKey: string;
|
|
90
92
|
};
|
|
91
93
|
systemPrompt: string | ((session: Record<string, unknown> | null) => string | Promise<string>);
|
|
92
|
-
tools?:
|
|
94
|
+
tools?: ToolSet;
|
|
93
95
|
backendFetch?: {
|
|
94
96
|
baseUrl: string;
|
|
95
97
|
apiKey: string;
|
|
@@ -97,6 +99,7 @@ export type ResolvedCortexAgentConfig = {
|
|
|
97
99
|
transformRequestBody?: (body: Record<string, unknown>, context: {
|
|
98
100
|
token: string;
|
|
99
101
|
}) => Promise<Record<string, unknown>>;
|
|
102
|
+
interceptor?: RequestInterceptorOptions;
|
|
100
103
|
};
|
|
101
104
|
loadSessionData?: (token: string) => Promise<Record<string, unknown>>;
|
|
102
105
|
onToolCall?: (toolCall: {
|
package/dist/src/index.d.ts
CHANGED
|
@@ -2,6 +2,8 @@ export type { CortexConfig, CortexAgentDefinition, KnowledgeConfig, DatabaseConf
|
|
|
2
2
|
export type { Thread, AppEnv } from "./types";
|
|
3
3
|
export type { CortexInstance } from "./factory";
|
|
4
4
|
export { createCortex } from "./factory";
|
|
5
|
+
export type { ResolvedFile, RequestInterceptorOptions, } from "./ai/interceptors/request-interceptor";
|
|
6
|
+
export { createRequestInterceptor } from "./ai/interceptors/request-interceptor";
|
|
5
7
|
export { captureFilesTool } from "./ai/tools/capture-files.tool";
|
|
6
8
|
export { createQueryGraphTool } from "./ai/tools/query-graph.tool";
|
|
7
9
|
export { createCallEndpointTool } from "./ai/tools/call-endpoint.tool";
|
package/dist/src/ws/events.d.ts
CHANGED
|
@@ -5,4 +5,10 @@ export type ThreadTitleUpdatedEvent = {
|
|
|
5
5
|
title: string;
|
|
6
6
|
};
|
|
7
7
|
};
|
|
8
|
-
export type
|
|
8
|
+
export type ThreadMessagesUpdatedEvent = {
|
|
9
|
+
type: "thread:messages-updated";
|
|
10
|
+
payload: {
|
|
11
|
+
threadId: string;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
export type WsEvent = ThreadTitleUpdatedEvent | ThreadMessagesUpdatedEvent;
|
package/dist/src/ws/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { addConnection, removeConnection, getConnections } from "./connections.ts";
|
|
2
2
|
export { notify } from "./notify.ts";
|
|
3
|
-
export type { WsEvent, ThreadTitleUpdatedEvent } from "./events.ts";
|
|
3
|
+
export type { WsEvent, ThreadTitleUpdatedEvent, ThreadMessagesUpdatedEvent } from "./events.ts";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m6d/cortex-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Reusable AI agent chat server library for Hono + Bun",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -29,7 +29,8 @@
|
|
|
29
29
|
"@hono/zod-validator": "^0.5.0",
|
|
30
30
|
"drizzle-orm": "^1.0.0-beta.15-859cf75",
|
|
31
31
|
"minio": "^8.0.7",
|
|
32
|
-
"mssql": "^12.2.0"
|
|
32
|
+
"mssql": "^12.2.0",
|
|
33
|
+
"quickjs-emscripten": "^0.32.0"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
35
36
|
"@ai-sdk/openai-compatible": "^2.0.0",
|
package/src/adapters/mssql.ts
CHANGED
|
@@ -109,19 +109,15 @@ export function createMssqlAdapter(connectionString: string, storage: StorageAda
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
const existingMessages = messagesToInsert.filter((x) => existingIds.includes(x.id));
|
|
112
|
-
|
|
113
|
-
await db
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
.where(eq(messages.id, message.id))
|
|
122
|
-
.execute();
|
|
123
|
-
}
|
|
124
|
-
});
|
|
112
|
+
for (const message of existingMessages) {
|
|
113
|
+
await db
|
|
114
|
+
.update(messages)
|
|
115
|
+
.set({
|
|
116
|
+
content: message,
|
|
117
|
+
text: message.parts.find((x) => x.type === "text")?.text,
|
|
118
|
+
})
|
|
119
|
+
.where(eq(messages.id, message.id))
|
|
120
|
+
.execute();
|
|
125
121
|
}
|
|
126
122
|
},
|
|
127
123
|
},
|
package/src/ai/index.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
type UIMessage,
|
|
2
3
|
type ToolSet,
|
|
4
|
+
consumeStream,
|
|
3
5
|
convertToModelMessages,
|
|
4
6
|
generateId,
|
|
5
7
|
generateText,
|
|
@@ -15,7 +17,7 @@ import { createQueryGraphTool } from "./tools/query-graph.tool.ts";
|
|
|
15
17
|
import { createCallEndpointTool } from "./tools/call-endpoint.tool.ts";
|
|
16
18
|
import { createExecuteCodeTool } from "./tools/execute-code.tool.ts";
|
|
17
19
|
import { captureFilesTool } from "./tools/capture-files.tool.ts";
|
|
18
|
-
import {
|
|
20
|
+
import { createRequestInterceptor } from "./interceptors/request-interceptor.ts";
|
|
19
21
|
import { createNeo4jClient } from "../graph/neo4j.ts";
|
|
20
22
|
import { resolveFromGraph } from "../graph/resolver.ts";
|
|
21
23
|
import { notify } from "../ws/index.ts";
|
|
@@ -26,6 +28,7 @@ export async function stream(
|
|
|
26
28
|
userId: string,
|
|
27
29
|
token: string,
|
|
28
30
|
config: ResolvedCortexAgentConfig,
|
|
31
|
+
abortSignal?: AbortSignal,
|
|
29
32
|
) {
|
|
30
33
|
const validationResult = await safeValidateUIMessages({ messages });
|
|
31
34
|
if (!validationResult.success) {
|
|
@@ -69,7 +72,11 @@ export async function stream(
|
|
|
69
72
|
...config.backendFetch,
|
|
70
73
|
transformRequestBody:
|
|
71
74
|
config.backendFetch.transformRequestBody ??
|
|
72
|
-
|
|
75
|
+
createRequestInterceptor(
|
|
76
|
+
config.db,
|
|
77
|
+
config.storage,
|
|
78
|
+
config.backendFetch.interceptor,
|
|
79
|
+
),
|
|
73
80
|
};
|
|
74
81
|
|
|
75
82
|
builtInTools["callEndpoint"] = createCallEndpointTool(backendFetchWithInterceptor, token);
|
|
@@ -88,20 +95,30 @@ export async function stream(
|
|
|
88
95
|
system: systemPrompt,
|
|
89
96
|
tools,
|
|
90
97
|
messages: recentMessages,
|
|
91
|
-
|
|
92
|
-
console.log("Stream aborted");
|
|
93
|
-
},
|
|
98
|
+
abortSignal,
|
|
94
99
|
});
|
|
95
100
|
|
|
96
101
|
return result.toUIMessageStreamResponse({
|
|
97
102
|
originalMessages,
|
|
98
103
|
generateMessageId: generateId,
|
|
104
|
+
consumeSseStream: consumeStream,
|
|
99
105
|
onFinish: async ({ messages: finishedMessages, isAborted }) => {
|
|
100
106
|
if (isAborted) {
|
|
101
|
-
|
|
107
|
+
finalizeAbortedMessages(finishedMessages);
|
|
102
108
|
}
|
|
103
109
|
await config.db.messages.upsert(thread.id, finishedMessages);
|
|
104
110
|
config.onStreamFinish?.({ messages: finishedMessages, isAborted });
|
|
111
|
+
|
|
112
|
+
// XXX: we need to notify the user so that the client can
|
|
113
|
+
// fetch new messages. The client can't fetch messages
|
|
114
|
+
// immediately after abort because messages may not have been
|
|
115
|
+
// saved yet.
|
|
116
|
+
if (isAborted) {
|
|
117
|
+
notify(userId, {
|
|
118
|
+
type: "thread:messages-updated",
|
|
119
|
+
payload: { threadId: thread.id },
|
|
120
|
+
});
|
|
121
|
+
}
|
|
105
122
|
},
|
|
106
123
|
});
|
|
107
124
|
}
|
|
@@ -131,3 +148,31 @@ going to do so or any other speech. Spit out only the title.`,
|
|
|
131
148
|
payload: { threadId, title: output ?? "" },
|
|
132
149
|
});
|
|
133
150
|
}
|
|
151
|
+
|
|
152
|
+
const TERMINAL_TOOL_STATES = new Set(["output-available", "output-error", "output-denied"]);
|
|
153
|
+
|
|
154
|
+
function finalizeAbortedMessages(messages: UIMessage[]) {
|
|
155
|
+
const lastMessage = messages.at(-1);
|
|
156
|
+
if (!lastMessage || lastMessage.role !== "assistant") return;
|
|
157
|
+
|
|
158
|
+
lastMessage.parts = lastMessage.parts.map((part) => {
|
|
159
|
+
if ((part.type === "text" || part.type === "reasoning") && part.state === "streaming") {
|
|
160
|
+
return { ...part, state: "done" as const };
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if ("toolCallId" in part && "state" in part) {
|
|
164
|
+
const toolState = part.state;
|
|
165
|
+
if (!TERMINAL_TOOL_STATES.has(toolState)) {
|
|
166
|
+
const { approval: _, ...rest } = part;
|
|
167
|
+
return {
|
|
168
|
+
...rest,
|
|
169
|
+
state: "output-error" as const,
|
|
170
|
+
errorText: "Generation was aborted",
|
|
171
|
+
output: undefined,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return part;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
@@ -7,14 +7,18 @@ export type ResolvedFile = {
|
|
|
7
7
|
bytes: string;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
export
|
|
10
|
+
export type RequestInterceptorOptions = {
|
|
11
|
+
transformFile?: (file: ResolvedFile) => unknown;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function createRequestInterceptor(
|
|
11
15
|
db: DatabaseAdapter,
|
|
12
16
|
storage: StorageAdapter,
|
|
13
|
-
options?:
|
|
17
|
+
options?: RequestInterceptorOptions,
|
|
14
18
|
) {
|
|
15
19
|
const transformFile = options?.transformFile ?? ((file: ResolvedFile) => file);
|
|
16
20
|
|
|
17
|
-
return async function
|
|
21
|
+
return async function resolveRequestBody(
|
|
18
22
|
body: Record<string, unknown>,
|
|
19
23
|
context: { token: string },
|
|
20
24
|
) {
|
|
@@ -2,13 +2,7 @@ import { tool } from "ai";
|
|
|
2
2
|
import z from "zod";
|
|
3
3
|
import type { ResolvedCortexAgentConfig } from "../../config.ts";
|
|
4
4
|
import { fetchBackend } from "../fetch.ts";
|
|
5
|
-
|
|
6
|
-
type ApiHelper = {
|
|
7
|
-
get: (path: string, queryParams?: Record<string, unknown>) => Promise<unknown>;
|
|
8
|
-
post: (path: string, body?: unknown) => Promise<unknown>;
|
|
9
|
-
put: (path: string, body?: unknown) => Promise<unknown>;
|
|
10
|
-
del: (path: string) => Promise<unknown>;
|
|
11
|
-
};
|
|
5
|
+
import { getQuickJS, Scope, shouldInterruptAfterDeadline } from "quickjs-emscripten";
|
|
12
6
|
|
|
13
7
|
function buildQueryString(params: Record<string, unknown>) {
|
|
14
8
|
const searchParams = new URLSearchParams();
|
|
@@ -26,7 +20,8 @@ function buildQueryString(params: Record<string, unknown>) {
|
|
|
26
20
|
return qs ? `?${qs}` : "";
|
|
27
21
|
}
|
|
28
22
|
|
|
29
|
-
function
|
|
23
|
+
async function runInSandbox(
|
|
24
|
+
code: string,
|
|
30
25
|
backendFetch: NonNullable<ResolvedCortexAgentConfig["backendFetch"]>,
|
|
31
26
|
token: string,
|
|
32
27
|
) {
|
|
@@ -53,22 +48,82 @@ function createApiHelper(
|
|
|
53
48
|
return response.json();
|
|
54
49
|
}
|
|
55
50
|
|
|
56
|
-
return {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
51
|
+
return await Scope.withScopeAsync(async (scope) => {
|
|
52
|
+
const QuickJS = await getQuickJS();
|
|
53
|
+
|
|
54
|
+
const runtime = scope.manage(QuickJS.newRuntime());
|
|
55
|
+
runtime.setMemoryLimit(1024 * 1024 * 20); // 20MB
|
|
56
|
+
runtime.setInterruptHandler(shouldInterruptAfterDeadline(Date.now() + 10_000)); // 60 seconds;
|
|
57
|
+
|
|
58
|
+
const vm = scope.manage(runtime.newContext());
|
|
59
|
+
|
|
60
|
+
function drainJobs() {
|
|
61
|
+
vm.runtime.executePendingJobs();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function makeApiFunction(fn: (...args: unknown[]) => Promise<unknown>) {
|
|
65
|
+
return scope.manage(
|
|
66
|
+
vm.newFunction(fn.name, (...argHandles) => {
|
|
67
|
+
const args = argHandles.map(vm.dump.bind(vm));
|
|
68
|
+
const promise = scope.manage(
|
|
69
|
+
vm.newPromise(
|
|
70
|
+
fn(...args).then((result) =>
|
|
71
|
+
scope.manage(
|
|
72
|
+
vm.unwrapResult(vm.evalCode(`(${JSON.stringify(result)})`)),
|
|
73
|
+
),
|
|
74
|
+
),
|
|
75
|
+
),
|
|
76
|
+
);
|
|
66
77
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
|
|
78
|
+
promise.settled.finally(() => {
|
|
79
|
+
drainJobs();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
return promise.handle;
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const apiHandle = scope.manage(vm.newObject());
|
|
88
|
+
vm.setProp(
|
|
89
|
+
apiHandle,
|
|
90
|
+
"get",
|
|
91
|
+
makeApiFunction(async (path, queryParams?) => {
|
|
92
|
+
const fullPath = queryParams
|
|
93
|
+
? path + buildQueryString(queryParams as Record<string, unknown>)
|
|
94
|
+
: path;
|
|
95
|
+
return await request("GET", fullPath as string);
|
|
96
|
+
}),
|
|
97
|
+
);
|
|
98
|
+
vm.setProp(
|
|
99
|
+
apiHandle,
|
|
100
|
+
"post",
|
|
101
|
+
makeApiFunction(async (path, body) => await request("POST", path as string, body)),
|
|
102
|
+
);
|
|
103
|
+
vm.setProp(
|
|
104
|
+
apiHandle,
|
|
105
|
+
"put",
|
|
106
|
+
makeApiFunction(async (path, body) => await request("PUT", path as string, body)),
|
|
107
|
+
);
|
|
108
|
+
vm.setProp(
|
|
109
|
+
apiHandle,
|
|
110
|
+
"del",
|
|
111
|
+
makeApiFunction(async (path) => await request("DELETE", path as string)),
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
vm.setProp(vm.global, "api", apiHandle);
|
|
115
|
+
|
|
116
|
+
const runResult = vm.evalCode(`(async () => {
|
|
117
|
+
${code}
|
|
118
|
+
})()`);
|
|
119
|
+
const resultHandle = scope.manage(vm.unwrapResult(runResult));
|
|
120
|
+
const pending = vm.resolvePromise(resultHandle);
|
|
121
|
+
drainJobs();
|
|
122
|
+
const resolvedResult = await pending;
|
|
123
|
+
const result = scope.manage(vm.unwrapResult(resolvedResult));
|
|
124
|
+
return vm.dump(result);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
72
127
|
|
|
73
128
|
export function createExecuteCodeTool(
|
|
74
129
|
backendFetch: NonNullable<ResolvedCortexAgentConfig["backendFetch"]>,
|
|
@@ -86,11 +141,8 @@ export function createExecuteCodeTool(
|
|
|
86
141
|
),
|
|
87
142
|
}),
|
|
88
143
|
execute: async ({ code }) => {
|
|
89
|
-
const apiHelper = createApiHelper(backendFetch, token);
|
|
90
|
-
|
|
91
144
|
try {
|
|
92
|
-
const
|
|
93
|
-
const result = await fn(apiHelper);
|
|
145
|
+
const result = await runInSandbox(code, backendFetch, token);
|
|
94
146
|
return JSON.stringify(result);
|
|
95
147
|
} catch (e) {
|
|
96
148
|
const message = e instanceof Error ? e.message : String(e);
|
package/src/config.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { UIMessage } from "ai";
|
|
1
|
+
import type { Tool, ToolSet, UIMessage } from "ai";
|
|
2
2
|
import type { DatabaseAdapter } from "./adapters/database";
|
|
3
3
|
import type { StorageAdapter } from "./adapters/storage";
|
|
4
4
|
import type { DomainDef } from "./graph/types.ts";
|
|
5
|
+
import type { RequestInterceptorOptions } from "./ai/interceptors/request-interceptor.ts";
|
|
5
6
|
|
|
6
7
|
export type KnowledgeConfig = {
|
|
7
8
|
swagger?: { url: string };
|
|
@@ -24,7 +25,7 @@ export type StorageConfig = {
|
|
|
24
25
|
|
|
25
26
|
export type CortexAgentDefinition = {
|
|
26
27
|
systemPrompt: string | ((session: Record<string, unknown> | null) => string | Promise<string>);
|
|
27
|
-
tools?:
|
|
28
|
+
tools?: ToolSet;
|
|
28
29
|
backendFetch?: {
|
|
29
30
|
baseUrl: string;
|
|
30
31
|
apiKey: string;
|
|
@@ -33,6 +34,7 @@ export type CortexAgentDefinition = {
|
|
|
33
34
|
body: Record<string, unknown>,
|
|
34
35
|
context: { token: string },
|
|
35
36
|
) => Promise<Record<string, unknown>>;
|
|
37
|
+
interceptor?: RequestInterceptorOptions;
|
|
36
38
|
};
|
|
37
39
|
loadSessionData?: (token: string) => Promise<Record<string, unknown>>;
|
|
38
40
|
onToolCall?: (toolCall: {
|
|
@@ -90,7 +92,7 @@ export type ResolvedCortexAgentConfig = {
|
|
|
90
92
|
apiKey: string;
|
|
91
93
|
};
|
|
92
94
|
systemPrompt: string | ((session: Record<string, unknown> | null) => string | Promise<string>);
|
|
93
|
-
tools?:
|
|
95
|
+
tools?: ToolSet;
|
|
94
96
|
backendFetch?: {
|
|
95
97
|
baseUrl: string;
|
|
96
98
|
apiKey: string;
|
|
@@ -99,6 +101,7 @@ export type ResolvedCortexAgentConfig = {
|
|
|
99
101
|
body: Record<string, unknown>,
|
|
100
102
|
context: { token: string },
|
|
101
103
|
) => Promise<Record<string, unknown>>;
|
|
104
|
+
interceptor?: RequestInterceptorOptions;
|
|
102
105
|
};
|
|
103
106
|
loadSessionData?: (token: string) => Promise<Record<string, unknown>>;
|
|
104
107
|
onToolCall?: (toolCall: {
|
package/src/index.ts
CHANGED
|
@@ -14,6 +14,13 @@ export type { Thread, AppEnv } from "./types";
|
|
|
14
14
|
export type { CortexInstance } from "./factory";
|
|
15
15
|
export { createCortex } from "./factory";
|
|
16
16
|
|
|
17
|
+
// Request interceptor (consumers may customize or replace the default)
|
|
18
|
+
export type {
|
|
19
|
+
ResolvedFile,
|
|
20
|
+
RequestInterceptorOptions,
|
|
21
|
+
} from "./ai/interceptors/request-interceptor";
|
|
22
|
+
export { createRequestInterceptor } from "./ai/interceptors/request-interceptor";
|
|
23
|
+
|
|
17
24
|
// Tools (consumers may register custom tools or use built-in ones)
|
|
18
25
|
export { captureFilesTool } from "./ai/tools/capture-files.tool";
|
|
19
26
|
export { createQueryGraphTool } from "./ai/tools/query-graph.tool";
|
package/src/routes/chat.ts
CHANGED
package/src/ws/events.ts
CHANGED
|
@@ -3,4 +3,9 @@ export type ThreadTitleUpdatedEvent = {
|
|
|
3
3
|
payload: { threadId: string; title: string };
|
|
4
4
|
};
|
|
5
5
|
|
|
6
|
-
export type
|
|
6
|
+
export type ThreadMessagesUpdatedEvent = {
|
|
7
|
+
type: "thread:messages-updated";
|
|
8
|
+
payload: { threadId: string };
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type WsEvent = ThreadTitleUpdatedEvent | ThreadMessagesUpdatedEvent;
|
package/src/ws/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export { addConnection, removeConnection, getConnections } from "./connections.ts";
|
|
2
2
|
export { notify } from "./notify.ts";
|
|
3
|
-
export type { WsEvent, ThreadTitleUpdatedEvent } from "./events.ts";
|
|
3
|
+
export type { WsEvent, ThreadTitleUpdatedEvent, ThreadMessagesUpdatedEvent } from "./events.ts";
|