@m6d/cortex-server 2.1.0 → 2.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/README.md +23 -9
- package/contracts/README.md +22 -8
- package/contracts/src/client-tools/index.ts +56 -0
- package/contracts/src/graph/index.ts +30 -0
- package/contracts/{runtime.ts → src/runtime/index.ts} +7 -12
- package/contracts/{wire.ts → src/wire/index.ts} +25 -13
- package/dist/contracts/{graph.d.ts → src/graph/index.d.ts} +8 -8
- package/dist/contracts/{runtime.d.ts → src/runtime/index.d.ts} +9 -43
- package/dist/contracts/{wire.d.ts → src/wire/index.d.ts} +23 -13
- package/dist/src/lib/adapters/database/index.d.ts +0 -7
- package/dist/src/lib/adapters/database/message-content.d.ts +1 -2
- package/dist/src/lib/adapters/database/mssql/index.d.ts +0 -1
- package/dist/src/lib/adapters/database/mssql/messages.d.ts +0 -1
- package/dist/src/lib/adapters/database/postgres/index.d.ts +0 -1
- package/dist/src/lib/adapters/database/postgres/messages.d.ts +0 -1
- package/dist/src/lib/ai/cc-runtime.d.ts +2 -3
- package/dist/src/lib/ai/client-tools.d.ts +84 -0
- package/dist/src/lib/ai/tools/query-graph.tool.d.ts +1 -1
- package/dist/src/lib/ai/turn-tools.d.ts +8 -6
- package/dist/src/lib/cc/client.d.ts +4 -11
- package/dist/src/lib/cc/config-cache.d.ts +0 -1
- package/dist/src/lib/cc/registry.d.ts +6 -6
- package/dist/src/lib/cc/types.d.ts +1 -1
- package/dist/src/lib/config.d.ts +9 -4
- package/dist/src/lib/graph/index.d.ts +1 -1
- package/dist/src/lib/graph/resolver.d.ts +1 -1
- package/dist/src/lib/index.d.ts +2 -1
- package/dist/src/lib/types.d.ts +2 -2
- package/dist/src/lib/ws/connections.d.ts +1 -1
- package/package.json +2 -2
- package/src/lib/adapters/database/index.ts +0 -12
- package/src/lib/adapters/database/mssql/messages.ts +1 -28
- package/src/lib/adapters/database/postgres/messages.ts +1 -22
- package/src/lib/ai/cc-runtime.ts +7 -7
- package/src/lib/ai/client-tools.ts +288 -0
- package/src/lib/ai/index.ts +60 -47
- package/src/lib/ai/tools/search-tools.tool.ts +2 -2
- package/src/lib/ai/turn-tools.ts +7 -8
- package/src/lib/cc/client.ts +1 -1
- package/src/lib/cc/format.ts +2 -6
- package/src/lib/cc/registry.ts +7 -7
- package/src/lib/cc/types.ts +1 -1
- package/src/lib/config.ts +8 -3
- package/src/lib/index.ts +4 -0
- package/src/lib/routes/chat.ts +5 -5
- package/tsconfig.json +1 -1
- package/contracts/graph.ts +0 -36
- package/contracts/interactive.ts +0 -53
- package/dist/contracts/interactive.d.ts +0 -39
- package/dist/src/lib/ai/interactive.d.ts +0 -62
- package/src/lib/ai/interactive.ts +0 -364
- /package/contracts/{graph → src/graph/clients}/embed.ts +0 -0
- /package/contracts/{graph → src/graph/clients}/neo4j.ts +0 -0
- /package/contracts/{graph → src/graph}/helpers.ts +0 -0
- /package/contracts/{graph → src/graph}/schema.ts +0 -0
- /package/contracts/{graph → src/graph}/types.ts +0 -0
- /package/contracts/{rich-text.ts → src/rich-text/index.ts} +0 -0
- /package/dist/contracts/{graph → src/graph/clients}/embed.d.ts +0 -0
- /package/dist/contracts/{graph → src/graph/clients}/neo4j.d.ts +0 -0
- /package/dist/contracts/{graph → src/graph}/helpers.d.ts +0 -0
- /package/dist/contracts/{graph → src/graph}/schema.d.ts +0 -0
- /package/dist/contracts/{graph → src/graph}/types.d.ts +0 -0
- /package/dist/contracts/{rich-text.d.ts → src/rich-text/index.d.ts} +0 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { ClientToolAnswer } from "../../../contracts/src/wire";
|
|
2
|
+
import type { ResolvedCortexAgentConfig } from "../config";
|
|
3
|
+
import type { ChatMessage, Thread } from "../types";
|
|
4
|
+
import { ControlCenterClient } from "../cc/client";
|
|
5
|
+
import type { CcRuntime } from "../cc/registry";
|
|
6
|
+
/**
|
|
7
|
+
* The wire-shape bindings stamped on the turn's final assistant message, so a
|
|
8
|
+
* parked client tool call can be initiated after any restart. Only names that
|
|
9
|
+
* actually won declaration merging are stamped — a call to a colliding
|
|
10
|
+
* consumer-owned tool must never be treated as a client tool. Undefined when
|
|
11
|
+
* nothing qualifies, keeping metadata lean.
|
|
12
|
+
*/
|
|
13
|
+
export declare function clientToolBindings(cc: CcRuntime | undefined, takenNames: ReadonlySet<string>): {
|
|
14
|
+
[k: string]: {
|
|
15
|
+
surface: "inline" | "modal";
|
|
16
|
+
embedOrigin: string;
|
|
17
|
+
toolId: string;
|
|
18
|
+
};
|
|
19
|
+
} | undefined;
|
|
20
|
+
/** Null when the agent has no Control Center — every caller treats that as "skip". */
|
|
21
|
+
export declare function createCcClient(config: ResolvedCortexAgentConfig): ControlCenterClient | null;
|
|
22
|
+
/**
|
|
23
|
+
* The `clientToolAnswers` a continuation request carried under
|
|
24
|
+
* `forwardedProps`, validated structurally — the widget is not the only
|
|
25
|
+
* possible author of a request body. All-or-nothing: `[]` means the request
|
|
26
|
+
* carried no answers at all, while `null` means it carried a payload with any
|
|
27
|
+
* malformed entry — the caller must not act on such a request, neither by
|
|
28
|
+
* settling its valid remainder nor by running a turn for it.
|
|
29
|
+
*/
|
|
30
|
+
export declare function clientToolAnswersFrom(forwardedProps: Record<string, unknown>): {
|
|
31
|
+
toolCallId: string;
|
|
32
|
+
output: unknown;
|
|
33
|
+
state: "complete" | "error";
|
|
34
|
+
}[] | null;
|
|
35
|
+
/**
|
|
36
|
+
* Applies client tool answers to the stored messages carrying their calls,
|
|
37
|
+
* mirroring the SDK's own settle shape (call part gains output + state, a
|
|
38
|
+
* tool-result part is appended). Already-settled calls are skipped, so a
|
|
39
|
+
* replayed continuation is a no-op. Returns only the messages that changed.
|
|
40
|
+
*/
|
|
41
|
+
export declare function answerStoredToolCalls(stored: ChatMessage[], answers: ClientToolAnswer[]): {
|
|
42
|
+
parts: import("@tanstack/ai").MessagePart[];
|
|
43
|
+
id: string;
|
|
44
|
+
role: "system" | "user" | "assistant";
|
|
45
|
+
metadata?: import("../types").MessageMetadata;
|
|
46
|
+
}[];
|
|
47
|
+
/**
|
|
48
|
+
* The server-authoritative half of a client tool continuation: the widget
|
|
49
|
+
* sends `messages: []` plus the answers, and the transcript is updated in
|
|
50
|
+
* place — the answered assistant message never round-trips, so the id the
|
|
51
|
+
* SDK's park-boundary snapshot failed to preserve no longer matters.
|
|
52
|
+
* `settled` is how many messages the answers changed; with `replied` it lets
|
|
53
|
+
* the caller tell a true replay (nothing settled, reply already stored) from
|
|
54
|
+
* a retry after a continuation that died before replying.
|
|
55
|
+
*/
|
|
56
|
+
export declare function applyClientToolAnswers(config: ResolvedCortexAgentConfig, userId: string, threadId: string, answers: ClientToolAnswer[]): Promise<{
|
|
57
|
+
settled: number;
|
|
58
|
+
replied: boolean;
|
|
59
|
+
}>;
|
|
60
|
+
/**
|
|
61
|
+
* `POST /chat/:chatId/tools/:toolCallId/initiate` — runs the interactive
|
|
62
|
+
* tool's initiate call (the tool's own endpoint) and hands the widget its
|
|
63
|
+
* embed payload. The model never sees this payload. The idempotency key is
|
|
64
|
+
* pinned to the tool call, so a reload mid-flow reuses the created session
|
|
65
|
+
* instead of opening a second one. The result the page later posts back is
|
|
66
|
+
* relayed to the agent as-is — verifying it is the integrating backend's job.
|
|
67
|
+
*/
|
|
68
|
+
export declare function initiateClientTool(options: {
|
|
69
|
+
config: ResolvedCortexAgentConfig;
|
|
70
|
+
thread: Thread;
|
|
71
|
+
userId: string;
|
|
72
|
+
token: string;
|
|
73
|
+
toolCallId: string;
|
|
74
|
+
}): Promise<{
|
|
75
|
+
embed: false;
|
|
76
|
+
embedUrl?: undefined;
|
|
77
|
+
surface?: undefined;
|
|
78
|
+
embedOrigin?: undefined;
|
|
79
|
+
} | {
|
|
80
|
+
embed: true;
|
|
81
|
+
embedUrl: string;
|
|
82
|
+
surface: "inline" | "modal";
|
|
83
|
+
embedOrigin: string;
|
|
84
|
+
}>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import z from "zod";
|
|
2
|
-
import type { Neo4jClient } from "../../../../contracts/graph";
|
|
2
|
+
import type { Neo4jClient } from "../../../../contracts/src/graph";
|
|
3
3
|
export declare function createQueryGraphTool(neo4j: Neo4jClient): import("@tanstack/ai").ServerTool<z.ZodObject<{
|
|
4
4
|
query: z.ZodString;
|
|
5
5
|
parameters: z.ZodOptional<z.ZodString>;
|
|
@@ -2,7 +2,7 @@ import type { AnyServerTool } from "@tanstack/ai";
|
|
|
2
2
|
import type { ResolvedCortexAgentConfig } from "../config";
|
|
3
3
|
import type { Attachment, Thread } from "../types";
|
|
4
4
|
import type { CcRuntime } from "../cc/registry";
|
|
5
|
-
import type { Neo4jClient } from "../../../contracts/graph";
|
|
5
|
+
import type { Neo4jClient } from "../../../contracts/src/graph";
|
|
6
6
|
type TurnToolsOptions = {
|
|
7
7
|
config: ResolvedCortexAgentConfig;
|
|
8
8
|
cc: CcRuntime | undefined;
|
|
@@ -19,9 +19,11 @@ type TurnToolsOptions = {
|
|
|
19
19
|
* configured, then the agent's own tools.
|
|
20
20
|
*
|
|
21
21
|
* User tools are appended last and deliberately win on name collision — an agent
|
|
22
|
-
* must be able to replace a built-in it doesn't want.
|
|
22
|
+
* must be able to replace a built-in it doesn't want. A user tool without an
|
|
23
|
+
* `execute` function is a static client tool: it passes through to the model
|
|
24
|
+
* declaration untouched, and the runtime streams its calls to the widget.
|
|
23
25
|
*/
|
|
24
|
-
export declare function buildTurnTools(options: TurnToolsOptions): AnyServerTool[];
|
|
26
|
+
export declare function buildTurnTools(options: TurnToolsOptions): (AnyServerTool | import("@tanstack/ai").AnyClientTool)[];
|
|
25
27
|
/**
|
|
26
28
|
* Instruments tool calls for the callbacks an agent configured. Returns
|
|
27
29
|
* `undefined` when nothing is listening, so the caller can skip the middleware
|
|
@@ -36,15 +38,15 @@ export declare function createToolInstrumentation(options: TurnToolsOptions & {
|
|
|
36
38
|
onAfterToolCall(_ctx: import("@tanstack/ai").ChatMiddlewareContext<unknown>, { toolName, toolCallId }: import("@tanstack/ai").AfterToolCallInfo): void;
|
|
37
39
|
} | undefined;
|
|
38
40
|
/**
|
|
39
|
-
*
|
|
41
|
+
* CC client tools are declared like the request's client tools: no
|
|
40
42
|
* executor, so the call streams to the widget as a tool-call part and the run
|
|
41
43
|
* parks until the widget answers. The declaration carries the tool's published
|
|
42
44
|
* input schema — function-calling models ignore schemas described only in
|
|
43
45
|
* prose — with a permissive object as the fallback for older Control Centers.
|
|
44
46
|
* Names the consumer already claimed are skipped: those calls belong to the
|
|
45
|
-
* consumer's tool, and must neither be declared nor stamped as
|
|
47
|
+
* consumer's tool, and must neither be declared nor stamped as client tools.
|
|
46
48
|
*/
|
|
47
|
-
export declare function
|
|
49
|
+
export declare function clientToolDeclarations(cc: CcRuntime | undefined, takenNames: ReadonlySet<string>): {
|
|
48
50
|
name: string;
|
|
49
51
|
description: string;
|
|
50
52
|
parameters: Record<string, unknown>;
|
|
@@ -9,7 +9,7 @@ export type ExecuteOptions = {
|
|
|
9
9
|
stepIndex: number;
|
|
10
10
|
callIndex: number;
|
|
11
11
|
/** Overrides the composed key — used where stability must outlive the turn
|
|
12
|
-
* counters, e.g. one
|
|
12
|
+
* counters, e.g. one initiate per tool call across reloads. */
|
|
13
13
|
idempotencyKey?: string;
|
|
14
14
|
timeoutMs?: number;
|
|
15
15
|
abortSignal?: AbortSignal;
|
|
@@ -34,7 +34,6 @@ export declare class ControlCenterClient {
|
|
|
34
34
|
agentId: string;
|
|
35
35
|
systemPrompt: string;
|
|
36
36
|
promptVariables: ("userName" | "channel" | "locale" | "utcTime" | "timezone")[];
|
|
37
|
-
catalogBlurb: string;
|
|
38
37
|
defaultLocale: "ar" | "en";
|
|
39
38
|
metaTools: {
|
|
40
39
|
searchKnowledge: boolean;
|
|
@@ -77,11 +76,9 @@ export declare class ControlCenterClient {
|
|
|
77
76
|
signature: string;
|
|
78
77
|
score: number | null;
|
|
79
78
|
pinned: boolean;
|
|
80
|
-
|
|
79
|
+
embed?: {
|
|
81
80
|
surface: "inline" | "modal";
|
|
82
81
|
embedOrigin: string;
|
|
83
|
-
hasVerify: boolean;
|
|
84
|
-
resultDelivery: "agent" | "endpoint" | "both";
|
|
85
82
|
} | undefined;
|
|
86
83
|
inputSchema?: Record<string, unknown> | undefined;
|
|
87
84
|
}[];
|
|
@@ -113,11 +110,9 @@ export declare class ControlCenterClient {
|
|
|
113
110
|
signature: string;
|
|
114
111
|
score: number | null;
|
|
115
112
|
pinned: boolean;
|
|
116
|
-
|
|
113
|
+
embed?: {
|
|
117
114
|
surface: "inline" | "modal";
|
|
118
115
|
embedOrigin: string;
|
|
119
|
-
hasVerify: boolean;
|
|
120
|
-
resultDelivery: "agent" | "endpoint" | "both";
|
|
121
116
|
} | undefined;
|
|
122
117
|
inputSchema?: Record<string, unknown> | undefined;
|
|
123
118
|
}[];
|
|
@@ -144,11 +139,9 @@ export declare class ControlCenterClient {
|
|
|
144
139
|
signature: string;
|
|
145
140
|
score: number | null;
|
|
146
141
|
pinned: boolean;
|
|
147
|
-
|
|
142
|
+
embed?: {
|
|
148
143
|
surface: "inline" | "modal";
|
|
149
144
|
embedOrigin: string;
|
|
150
|
-
hasVerify: boolean;
|
|
151
|
-
resultDelivery: "agent" | "endpoint" | "both";
|
|
152
145
|
} | undefined;
|
|
153
146
|
inputSchema?: Record<string, unknown> | undefined;
|
|
154
147
|
}[];
|
|
@@ -3,7 +3,6 @@ export declare function getControlCenterConfig(cc: ControlCenterClient, agentId:
|
|
|
3
3
|
agentId: string;
|
|
4
4
|
systemPrompt: string;
|
|
5
5
|
promptVariables: ("userName" | "channel" | "locale" | "utcTime" | "timezone")[];
|
|
6
|
-
catalogBlurb: string;
|
|
7
6
|
defaultLocale: "ar" | "en";
|
|
8
7
|
metaTools: {
|
|
9
8
|
searchKnowledge: boolean;
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import type { ControlCenterClient } from "./client";
|
|
2
|
-
import type { RuntimeAgentConfig,
|
|
2
|
+
import type { RuntimeAgentConfig, ToolEmbed } from "./types";
|
|
3
3
|
export type CcToolBinding = {
|
|
4
4
|
toolId: string;
|
|
5
5
|
readOnly: boolean;
|
|
6
6
|
};
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* A client tool resolved for this turn. Declared to the model as a real
|
|
9
9
|
* client-executed tool — never a sandbox binding — so its call streams to the
|
|
10
10
|
* widget as a tool-call part and parks the run until the flow settles.
|
|
11
11
|
*/
|
|
12
|
-
export type
|
|
12
|
+
export type CcClientTool = {
|
|
13
13
|
toolId: string;
|
|
14
14
|
signature: string;
|
|
15
|
-
|
|
15
|
+
embed: ToolEmbed;
|
|
16
16
|
inputSchema?: Record<string, unknown>;
|
|
17
17
|
};
|
|
18
18
|
/**
|
|
@@ -24,7 +24,7 @@ export declare function registerCcTools(registry: CcToolRegistry, tools: {
|
|
|
24
24
|
name: string;
|
|
25
25
|
toolId: string;
|
|
26
26
|
readOnly: boolean;
|
|
27
|
-
|
|
27
|
+
embed?: ToolEmbed;
|
|
28
28
|
}[]): void;
|
|
29
29
|
export declare function recordRecentCcTool(threadId: string, name: string): void;
|
|
30
30
|
export declare function getRecentCcTools(threadId: string): string[];
|
|
@@ -34,7 +34,7 @@ export type CcRuntime = {
|
|
|
34
34
|
agentId: string;
|
|
35
35
|
config: RuntimeAgentConfig;
|
|
36
36
|
registry: CcToolRegistry;
|
|
37
|
-
|
|
37
|
+
clientTools: Map<string, CcClientTool>;
|
|
38
38
|
threadId: string;
|
|
39
39
|
turnKey: string;
|
|
40
40
|
userId: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import z from "zod";
|
|
2
|
-
export { AGENT_SLUG_PATTERN, executeResponseSchema, resolveResponseSchema, runtimeAgentConfigSchema, searchKnowledgeResponseSchema, searchServicesResponseSchema, searchToolsResponseSchema, type ExecuteRequest, type ResolveRequest, type ResolveResponse, type RuntimeAgentConfig, type SearchRequest, type
|
|
2
|
+
export { AGENT_SLUG_PATTERN, executeResponseSchema, resolveResponseSchema, runtimeAgentConfigSchema, searchKnowledgeResponseSchema, searchServicesResponseSchema, searchToolsResponseSchema, type ExecuteRequest, type ResolveRequest, type ResolveResponse, type RuntimeAgentConfig, type SearchRequest, type ToolEmbed, } from "../../../contracts/src/runtime";
|
|
3
3
|
/**
|
|
4
4
|
* The contract's error envelope, hardened for this consumer: a newer runtime may
|
|
5
5
|
* answer with an error kind this build has never heard of, which must degrade to a
|
package/dist/src/lib/config.d.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
-
import type { AnyServerTool } from "@tanstack/ai";
|
|
1
|
+
import type { AnyClientTool, AnyServerTool } from "@tanstack/ai";
|
|
2
2
|
import type { DatabaseAdapter } from "./adapters/database/index";
|
|
3
3
|
import type { StorageAdapter } from "./adapters/storage/index";
|
|
4
|
-
import type { DomainDef } from "../../contracts/graph";
|
|
4
|
+
import type { DomainDef } from "../../contracts/src/graph";
|
|
5
5
|
import type { RequestInterceptorOptions } from "./ai/interceptors/request-interceptor";
|
|
6
6
|
import type { ContextConfig } from "./ai/context/types";
|
|
7
7
|
import type { ChatMessage, Thread } from "./types";
|
|
8
|
-
/**
|
|
9
|
-
|
|
8
|
+
/**
|
|
9
|
+
* An agent's tools, as `chat()` takes them. A tool with an `execute` function
|
|
10
|
+
* runs on the server; one without is a static client tool — declared to the
|
|
11
|
+
* model, streamed to the widget as a tool-call part, and answered by the host
|
|
12
|
+
* app (`hooks.onToolCall` or a `toolComponents` entry with `setOutput`).
|
|
13
|
+
*/
|
|
14
|
+
export type ToolSet = ReadonlyArray<AnyServerTool | AnyClientTool>;
|
|
10
15
|
type ModelConfig = {
|
|
11
16
|
baseURL: string;
|
|
12
17
|
apiKey: string;
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* re-exported here so authoring a project's domains still needs exactly one
|
|
6
6
|
* import path — nothing about the public surface moved.
|
|
7
7
|
*/
|
|
8
|
-
export * from "../../../contracts/graph";
|
|
8
|
+
export * from "../../../contracts/src/graph";
|
|
9
9
|
export type { RerankerConfig, ResolverConfig, ResolvedEndpoint, ResolvedService, ResolvedContext, } from "./resolver";
|
|
10
10
|
export { resolveFromGraph } from "./resolver";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* All configuration is passed explicitly — no hardcoded model references
|
|
6
6
|
* or environment variables.
|
|
7
7
|
*/
|
|
8
|
-
import { type EmbedFn, type Neo4jClient } from "../../../contracts/graph";
|
|
8
|
+
import { type EmbedFn, type Neo4jClient } from "../../../contracts/src/graph";
|
|
9
9
|
export type RerankerConfig = {
|
|
10
10
|
url: string;
|
|
11
11
|
apiKey: string;
|
package/dist/src/lib/index.d.ts
CHANGED
|
@@ -7,7 +7,8 @@ export type { CortexInstance } from "./factory";
|
|
|
7
7
|
export { createCortex } from "./factory";
|
|
8
8
|
export type { ResolvedFile, RequestInterceptorOptions, } from "./ai/interceptors/request-interceptor";
|
|
9
9
|
export { createRequestInterceptor } from "./ai/interceptors/request-interceptor";
|
|
10
|
+
export { toolDefinition } from "@tanstack/ai";
|
|
10
11
|
export { createQueryGraphTool } from "./ai/tools/query-graph.tool";
|
|
11
12
|
export { createExecuteCodeTool } from "./ai/tools/execute-code.tool";
|
|
12
13
|
export * from "./graph/index";
|
|
13
|
-
export * from "../../contracts/wire";
|
|
14
|
+
export * from "../../contracts/src/wire";
|
package/dist/src/lib/types.d.ts
CHANGED
|
@@ -2,8 +2,8 @@ import type { MessagePart } from "@tanstack/ai";
|
|
|
2
2
|
import type { ResolvedCortexAgentConfig } from "./config";
|
|
3
3
|
import type { InferSelectModel } from "drizzle-orm";
|
|
4
4
|
import type { attachments, messages, threads } from "./db/schema.mssql";
|
|
5
|
-
export type { CortexMessage, MessageMetadata, ThreadSummary, TokenUsage, } from "../../contracts/wire";
|
|
6
|
-
import type { CortexMessage } from "../../contracts/wire";
|
|
5
|
+
export type { CortexMessage, MessageMetadata, ThreadSummary, TokenUsage, } from "../../contracts/src/wire";
|
|
6
|
+
import type { CortexMessage } from "../../contracts/src/wire";
|
|
7
7
|
/** A message as cortex persists and serves it: SDK parts plus cortex's envelope. */
|
|
8
8
|
export type ChatMessage = CortexMessage<MessagePart>;
|
|
9
9
|
export type Thread = InferSelectModel<typeof threads>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { WSContext } from "hono/ws";
|
|
2
|
-
import type { WsEvent } from "../../../contracts/wire";
|
|
2
|
+
import type { WsEvent } from "../../../contracts/src/wire";
|
|
3
3
|
export declare function addConnection(userId: string, agentId: string, ws: WSContext): void;
|
|
4
4
|
export declare function removeConnection(userId: string, agentId: string, ws: WSContext): void;
|
|
5
5
|
export declare function notify(userId: string, agentId: string, event: WsEvent): void;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@m6d/cortex-server",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"description": "Reusable AI agent chat server library for Hono + Bun",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"!src/**/*.mock.ts"
|
|
25
25
|
],
|
|
26
26
|
"scripts": {
|
|
27
|
-
"build": "bun run vendor && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && rm -rf contracts",
|
|
27
|
+
"build": "bun run vendor && rm -rf dist && tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && rm -rf contracts",
|
|
28
28
|
"check": "tsc --noEmit",
|
|
29
29
|
"db:generate:mssql": "drizzle-kit generate --config=src/lib/db/drizzle.config.mssql.ts",
|
|
30
30
|
"db:generate:pg": "drizzle-kit generate --config=src/lib/db/drizzle.config.pg.ts",
|
|
@@ -42,18 +42,6 @@ export type DatabaseAdapter = {
|
|
|
42
42
|
messages: ChatMessage[],
|
|
43
43
|
options?: { replaceAttachments?: boolean },
|
|
44
44
|
): Promise<void>;
|
|
45
|
-
/**
|
|
46
|
-
* Atomically merges one anchored interactive reference into the
|
|
47
|
-
* message's metadata as a single-statement JSON merge — safe under
|
|
48
|
-
* concurrent writers across replicas, unlike a read-modify-write of
|
|
49
|
-
* the whole message.
|
|
50
|
-
*/
|
|
51
|
-
mergeInteractiveReference(
|
|
52
|
-
threadId: string,
|
|
53
|
-
messageId: string,
|
|
54
|
-
toolCallId: string,
|
|
55
|
-
reference: string,
|
|
56
|
-
): Promise<void>;
|
|
57
45
|
};
|
|
58
46
|
llmRequests: {
|
|
59
47
|
insert(
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// fallow-ignore-file duplicate-export -- mssql twin of the postgres repository, same factory name by design
|
|
2
|
-
import { and, desc, eq, getColumns, inArray,
|
|
2
|
+
import { and, desc, eq, getColumns, inArray, type InferInsertModel } from "drizzle-orm";
|
|
3
3
|
import { threads, messages } from "@/db/schema.mssql";
|
|
4
4
|
import type { ChatMessage } from "@/types";
|
|
5
5
|
import type { DatabaseAdapter } from "@/adapters/database/index";
|
|
@@ -88,32 +88,5 @@ export function createMessagesRepository(db: MssqlDb) {
|
|
|
88
88
|
.execute();
|
|
89
89
|
}
|
|
90
90
|
},
|
|
91
|
-
|
|
92
|
-
async mergeInteractiveReference(threadId, messageId, toolCallId, reference) {
|
|
93
|
-
// JSON path keys are quoted strings; the id lands inside one.
|
|
94
|
-
const escapedKey = toolCallId.replaceAll("\\", "\\\\").replaceAll('"', '\\"');
|
|
95
|
-
const anchorPath = `lax $.metadata.interactiveReferences."${escapedKey}"`;
|
|
96
|
-
await db
|
|
97
|
-
.update(messages)
|
|
98
|
-
.set({
|
|
99
|
-
// All JSON_QUERY reads see the row's pre-update value, so
|
|
100
|
-
// the statement is one atomic merge.
|
|
101
|
-
content: sql`JSON_MODIFY(
|
|
102
|
-
JSON_MODIFY(
|
|
103
|
-
JSON_MODIFY(
|
|
104
|
-
${messages.content},
|
|
105
|
-
'lax $.metadata',
|
|
106
|
-
JSON_QUERY(COALESCE(JSON_QUERY(${messages.content}, '$.metadata'), '{}'))
|
|
107
|
-
),
|
|
108
|
-
'lax $.metadata.interactiveReferences',
|
|
109
|
-
JSON_QUERY(COALESCE(JSON_QUERY(${messages.content}, '$.metadata.interactiveReferences'), '{}'))
|
|
110
|
-
),
|
|
111
|
-
${anchorPath},
|
|
112
|
-
${reference}
|
|
113
|
-
)`,
|
|
114
|
-
})
|
|
115
|
-
.where(and(eq(messages.id, messageId), eq(messages.threadId, threadId)))
|
|
116
|
-
.execute();
|
|
117
|
-
},
|
|
118
91
|
} satisfies DatabaseAdapter["messages"];
|
|
119
92
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// fallow-ignore-file code-duplication -- mirrors ../mssql/messages.ts by design;
|
|
2
2
|
// Drizzle types query builders per dialect. See DatabaseAdapter in ../index.ts.
|
|
3
|
-
import { and, desc, eq, getColumns, inArray,
|
|
3
|
+
import { and, desc, eq, getColumns, inArray, type InferInsertModel } from "drizzle-orm";
|
|
4
4
|
import { threads, messages } from "@/db/schema.pg";
|
|
5
5
|
import type { ChatMessage } from "@/types";
|
|
6
6
|
import type { DatabaseAdapter } from "@/adapters/database/index";
|
|
@@ -88,26 +88,5 @@ export function createMessagesRepository(db: PostgresDb) {
|
|
|
88
88
|
.execute();
|
|
89
89
|
}
|
|
90
90
|
},
|
|
91
|
-
|
|
92
|
-
async mergeInteractiveReference(threadId, messageId, toolCallId, reference) {
|
|
93
|
-
await db
|
|
94
|
-
.update(messages)
|
|
95
|
-
.set({
|
|
96
|
-
content: sql`jsonb_set(
|
|
97
|
-
jsonb_set(
|
|
98
|
-
${messages.content},
|
|
99
|
-
'{metadata}',
|
|
100
|
-
coalesce(${messages.content}->'metadata', '{}'::jsonb),
|
|
101
|
-
true
|
|
102
|
-
),
|
|
103
|
-
'{metadata,interactiveReferences}',
|
|
104
|
-
coalesce(${messages.content}->'metadata'->'interactiveReferences', '{}'::jsonb)
|
|
105
|
-
|| jsonb_build_object(${toolCallId}::text, ${reference}::text),
|
|
106
|
-
true
|
|
107
|
-
)`,
|
|
108
|
-
})
|
|
109
|
-
.where(and(eq(messages.id, messageId), eq(messages.threadId, threadId)))
|
|
110
|
-
.execute();
|
|
111
|
-
},
|
|
112
91
|
} satisfies DatabaseAdapter["messages"];
|
|
113
92
|
}
|
package/src/lib/ai/cc-runtime.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ResolvedCortexAgentConfig } from "@/config";
|
|
2
2
|
import type { Thread } from "@/types";
|
|
3
3
|
import type { ControlCenterClient } from "@/cc/client";
|
|
4
|
-
import type {
|
|
4
|
+
import type { CcClientTool, CcRuntime, CcToolRegistry } from "@/cc/registry";
|
|
5
5
|
import { registerCcTools } from "@/cc/registry";
|
|
6
6
|
import type { ResolveResponse, RuntimeAgentConfig } from "@/cc/types";
|
|
7
7
|
|
|
@@ -35,16 +35,16 @@ export function createCcRuntime(options: CcRuntimeOptions) {
|
|
|
35
35
|
const registry: CcToolRegistry = new Map();
|
|
36
36
|
if (ccResolved) registerCcTools(registry, ccResolved.tools);
|
|
37
37
|
|
|
38
|
-
//
|
|
38
|
+
// Client tools resolved at turn start become client-executed LLM
|
|
39
39
|
// tools. Mid-turn search finds are excluded on purpose: the model's tool
|
|
40
40
|
// set is fixed once the turn starts, so declaring them is impossible.
|
|
41
|
-
const
|
|
41
|
+
const clientTools = new Map<string, CcClientTool>();
|
|
42
42
|
for (const tool of ccResolved?.tools ?? []) {
|
|
43
|
-
if (!tool.
|
|
44
|
-
|
|
43
|
+
if (!tool.embed) continue;
|
|
44
|
+
clientTools.set(tool.name, {
|
|
45
45
|
toolId: tool.toolId,
|
|
46
46
|
signature: tool.signature,
|
|
47
|
-
|
|
47
|
+
embed: tool.embed,
|
|
48
48
|
inputSchema: tool.inputSchema,
|
|
49
49
|
});
|
|
50
50
|
}
|
|
@@ -57,7 +57,7 @@ export function createCcRuntime(options: CcRuntimeOptions) {
|
|
|
57
57
|
agentId: config.agentId,
|
|
58
58
|
config: ccConfig,
|
|
59
59
|
registry,
|
|
60
|
-
|
|
60
|
+
clientTools,
|
|
61
61
|
threadId: thread.id,
|
|
62
62
|
turnKey: options.turnKey,
|
|
63
63
|
userId,
|