@m6d/cortex-server 1.7.0 → 2.0.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 +8 -3
- package/contracts/README.md +23 -0
- package/contracts/graph/embed.ts +50 -0
- package/{src → contracts}/graph/helpers.ts +4 -10
- package/{src → contracts}/graph/neo4j.ts +14 -27
- package/contracts/graph/schema.ts +65 -0
- package/{src → contracts}/graph/types.ts +2 -29
- package/contracts/graph.ts +36 -0
- package/contracts/runtime.ts +208 -0
- package/contracts/wire.ts +143 -0
- package/dist/contracts/graph/embed.d.ts +22 -0
- package/dist/{src → contracts}/graph/helpers.d.ts +14 -12
- package/dist/{src → contracts}/graph/neo4j.d.ts +5 -5
- package/dist/contracts/graph/schema.d.ts +62 -0
- package/dist/{src → contracts}/graph/types.d.ts +1 -1
- package/dist/contracts/graph.d.ts +14 -0
- package/dist/contracts/runtime.d.ts +278 -0
- package/dist/contracts/wire.d.ts +120 -0
- package/dist/index.d.ts +1 -1
- package/dist/src/lib/adapters/database/index.d.ts +61 -0
- package/dist/src/lib/adapters/database/message-content.d.ts +30 -0
- package/dist/src/lib/adapters/database/mssql/attachments.d.ts +100 -0
- package/dist/src/lib/adapters/database/mssql/client.d.ts +8 -0
- package/dist/src/lib/adapters/database/mssql/index.d.ts +194 -0
- package/dist/src/lib/adapters/database/mssql/llm-requests.d.ts +17 -0
- package/dist/src/lib/adapters/database/mssql/messages.d.ts +37 -0
- package/dist/src/lib/adapters/database/mssql/threads.d.ts +50 -0
- package/dist/src/lib/adapters/database/postgres/attachments.d.ts +113 -0
- package/dist/src/lib/adapters/database/postgres/client.d.ts +8 -0
- package/dist/src/lib/adapters/database/postgres/index.d.ts +207 -0
- package/dist/src/lib/adapters/database/postgres/llm-requests.d.ts +17 -0
- package/dist/src/lib/adapters/database/postgres/messages.d.ts +37 -0
- package/dist/src/lib/adapters/database/postgres/threads.d.ts +50 -0
- package/{src/adapters/storage.ts → dist/src/lib/adapters/storage/index.d.ts} +1 -1
- package/dist/src/{adapters → lib/adapters/storage}/minio.d.ts +1 -1
- package/dist/src/lib/ai/active-runs.d.ts +63 -0
- package/dist/src/lib/ai/attachments.d.ts +30 -0
- package/dist/src/lib/ai/backend-url.d.ts +16 -0
- package/dist/src/lib/ai/cc-runtime.d.ts +61 -0
- package/dist/src/lib/ai/commit-gate.d.ts +21 -0
- package/dist/src/{ai → lib/ai}/context/builder.d.ts +6 -7
- package/dist/src/lib/ai/context/compression-middleware.d.ts +15 -0
- package/dist/src/lib/ai/context/compressor.d.ts +7 -0
- package/dist/src/lib/ai/context/intra-turn-compressor.d.ts +24 -0
- package/dist/src/lib/ai/context/optimize-thread-context.d.ts +9 -0
- package/dist/src/lib/ai/context/summarizer.d.ts +5 -0
- package/dist/src/{ai → lib/ai}/context/token-estimator.d.ts +5 -8
- package/dist/src/{ai → lib/ai}/context/types.d.ts +2 -0
- package/dist/src/{ai → lib/ai}/fetch.d.ts +1 -1
- package/dist/src/lib/ai/finish-turn.d.ts +23 -0
- package/dist/src/lib/ai/helpers.d.ts +38 -0
- package/dist/src/lib/ai/index.d.ts +7 -0
- package/dist/src/lib/ai/inspector.d.ts +41 -0
- package/dist/src/lib/ai/interceptors/request-interceptor.d.ts +13 -0
- package/dist/src/{ai → lib/ai}/prompt.d.ts +5 -4
- package/dist/src/lib/ai/redis-runs.d.ts +41 -0
- package/dist/src/lib/ai/redis-stream-log.d.ts +39 -0
- package/dist/src/lib/ai/tools/execute-code.tool.d.ts +18 -0
- package/dist/src/lib/ai/tools/query-graph.tool.d.ts +13 -0
- package/dist/src/lib/ai/tools/read-attachment.tool.d.ts +21 -0
- package/dist/src/lib/ai/tools/search-common.d.ts +17 -0
- package/dist/src/lib/ai/tools/search-knowledge.tool.d.ts +15 -0
- package/dist/src/lib/ai/tools/search-services.tool.d.ts +12 -0
- package/dist/src/lib/ai/tools/search-tools.tool.d.ts +12 -0
- package/dist/src/lib/ai/turn-tools.d.ts +39 -0
- package/dist/src/lib/ai/vision/rasterize-pdf.d.ts +26 -0
- package/dist/src/lib/ai/vision/rasterize-pdf.worker.d.ts +1 -0
- package/dist/src/lib/ai/vision/vision-reader.d.ts +45 -0
- package/dist/src/lib/cc/client.d.ts +183 -0
- package/dist/src/lib/cc/config-cache.d.ts +20 -0
- package/dist/src/lib/cc/format.d.ts +23 -0
- package/dist/src/lib/cc/registry.d.ts +34 -0
- package/dist/src/lib/cc/types.d.ts +27 -0
- package/dist/src/lib/config.d.ts +170 -0
- package/dist/src/lib/db/drizzle.config.mssql.d.ts +2 -0
- package/dist/src/lib/db/drizzle.config.pg.d.ts +2 -0
- package/dist/src/lib/db/migrate.d.ts +7 -0
- package/dist/src/{db/schema.d.ts → lib/db/schema.mssql.d.ts} +236 -24
- package/dist/src/lib/db/schema.pg.d.ts +546 -0
- package/dist/src/{factory.d.ts → lib/factory.d.ts} +2 -12
- package/dist/src/lib/graph/index.d.ts +10 -0
- package/dist/src/{graph → lib/graph}/resolver.d.ts +2 -3
- package/dist/src/{index.d.ts → lib/index.d.ts} +3 -4
- package/dist/src/lib/redis.d.ts +19 -0
- package/dist/src/{routes → lib/routes}/chat.d.ts +1 -1
- package/dist/src/{routes → lib/routes}/files.d.ts +1 -1
- package/dist/src/lib/routes/owned-thread.d.ts +17 -0
- package/dist/src/{routes → lib/routes}/threads.d.ts +1 -1
- package/dist/src/{routes → lib/routes}/ws.d.ts +1 -1
- package/dist/src/lib/types.d.ts +58 -0
- package/dist/src/{ws → lib/ws}/connections.d.ts +2 -1
- package/index.ts +1 -1
- package/package.json +35 -15
- package/src/lib/adapters/database/index.ts +78 -0
- package/src/lib/adapters/database/message-content.ts +39 -0
- package/src/lib/adapters/database/mssql/attachments.ts +90 -0
- package/src/lib/adapters/database/mssql/client.ts +11 -0
- package/src/lib/adapters/database/mssql/index.ts +23 -0
- package/src/lib/adapters/database/mssql/llm-requests.ts +43 -0
- package/src/lib/adapters/database/mssql/messages.ts +92 -0
- package/src/lib/adapters/database/mssql/threads.ts +83 -0
- package/src/lib/adapters/database/postgres/attachments.ts +88 -0
- package/src/lib/adapters/database/postgres/client.ts +11 -0
- package/src/lib/adapters/database/postgres/index.ts +23 -0
- package/src/lib/adapters/database/postgres/llm-requests.ts +45 -0
- package/src/lib/adapters/database/postgres/messages.ts +92 -0
- package/src/lib/adapters/database/postgres/threads.ts +84 -0
- package/{dist/src/adapters/storage.d.ts → src/lib/adapters/storage/index.ts} +1 -1
- package/src/{adapters → lib/adapters/storage}/minio.ts +7 -6
- package/src/lib/ai/active-runs.ts +157 -0
- package/src/lib/ai/attachments.ts +144 -0
- package/src/lib/ai/backend-url.ts +27 -0
- package/src/lib/ai/cc-runtime.ts +63 -0
- package/src/lib/ai/commit-gate.ts +116 -0
- package/src/{ai → lib/ai}/context/builder.ts +12 -14
- package/src/lib/ai/context/compression-middleware.ts +44 -0
- package/src/lib/ai/context/compressor.ts +267 -0
- package/src/lib/ai/context/intra-turn-compressor.ts +181 -0
- package/src/lib/ai/context/optimize-thread-context.ts +50 -0
- package/src/lib/ai/context/summarizer.ts +48 -0
- package/src/lib/ai/context/token-estimator.ts +65 -0
- package/src/{ai → lib/ai}/context/types.ts +4 -1
- package/src/{ai → lib/ai}/fetch.ts +10 -5
- package/src/lib/ai/finish-turn.ts +75 -0
- package/src/lib/ai/helpers.ts +100 -0
- package/src/lib/ai/index.ts +408 -0
- package/src/lib/ai/inspector.ts +112 -0
- package/src/lib/ai/interceptors/request-interceptor.ts +89 -0
- package/src/lib/ai/prompt.ts +355 -0
- package/src/lib/ai/redis-runs.ts +167 -0
- package/src/lib/ai/redis-stream-log.ts +219 -0
- package/src/lib/ai/tools/execute-code.tool.ts +267 -0
- package/src/{ai → lib/ai}/tools/query-graph.tool.ts +7 -8
- package/src/lib/ai/tools/read-attachment.tool.ts +59 -0
- package/src/lib/ai/tools/search-common.ts +15 -0
- package/src/lib/ai/tools/search-knowledge.tool.ts +33 -0
- package/src/lib/ai/tools/search-services.tool.ts +31 -0
- package/src/lib/ai/tools/search-tools.tool.ts +29 -0
- package/src/lib/ai/turn-tools.ts +154 -0
- package/src/lib/ai/vision/rasterize-pdf.ts +69 -0
- package/src/lib/ai/vision/rasterize-pdf.worker.ts +81 -0
- package/src/lib/ai/vision/vision-reader.ts +130 -0
- package/src/{auth → lib/auth}/middleware.ts +12 -3
- package/src/lib/cc/client.ts +273 -0
- package/src/lib/cc/config-cache.ts +32 -0
- package/src/lib/cc/format.ts +96 -0
- package/src/lib/cc/registry.ts +62 -0
- package/src/lib/cc/types.ts +44 -0
- package/src/lib/config.ts +212 -0
- package/src/lib/db/drizzle.config.mssql.ts +9 -0
- package/src/lib/db/drizzle.config.pg.ts +9 -0
- package/src/lib/db/migrate.ts +56 -0
- package/src/{db/migrations/20260309012148_cloudy_maria_hill → lib/db/migrations/mssql/20260326231647_nice_speedball}/migration.sql +12 -0
- package/src/{db/migrations/20260309012148_cloudy_maria_hill → lib/db/migrations/mssql/20260326231647_nice_speedball}/snapshot.json +106 -1
- package/src/lib/db/migrations/mssql/20260729092726_talented_wilson_fisk/migration.sql +20 -0
- package/src/lib/db/migrations/mssql/20260729092726_talented_wilson_fisk/snapshot.json +497 -0
- package/src/lib/db/migrations/mssql/20260801003652_perpetual_blue_shield/migration.sql +1 -0
- package/src/lib/db/migrations/mssql/20260801003652_perpetual_blue_shield/snapshot.json +516 -0
- package/src/lib/db/migrations/mssql/20260812174642_user_id_text/migration.sql +2 -0
- package/src/lib/db/migrations/mssql/20260812174642_user_id_text/snapshot.json +516 -0
- package/src/lib/db/migrations/pg/20260801084117_thick_ben_grimm/migration.sql +53 -0
- package/src/lib/db/migrations/pg/20260801084117_thick_ben_grimm/snapshot.json +584 -0
- package/src/lib/db/migrations/pg/20260812174622_user_id_text/migration.sql +2 -0
- package/src/lib/db/migrations/pg/20260812174622_user_id_text/snapshot.json +584 -0
- package/src/lib/db/schema.mssql.ts +94 -0
- package/src/lib/db/schema.pg.ts +95 -0
- package/src/lib/factory.ts +127 -0
- package/src/lib/graph/index.ts +19 -0
- package/src/lib/graph/resolver.ts +387 -0
- package/src/{index.ts → lib/index.ts} +13 -5
- package/src/lib/redis.ts +44 -0
- package/src/lib/routes/chat.ts +115 -0
- package/src/lib/routes/files.ts +129 -0
- package/src/lib/routes/owned-thread.ts +17 -0
- package/src/{routes → lib/routes}/threads.ts +22 -31
- package/src/{routes → lib/routes}/ws.ts +9 -3
- package/src/lib/types.ts +76 -0
- package/src/{ws → lib/ws}/connections.ts +9 -1
- package/tsconfig.json +48 -0
- package/dist/src/adapters/database.d.ts +0 -30
- package/dist/src/adapters/mssql.d.ts +0 -3
- package/dist/src/ai/active-streams.d.ts +0 -14
- package/dist/src/ai/context/compressor.d.ts +0 -7
- package/dist/src/ai/context/index.d.ts +0 -15
- package/dist/src/ai/context/summarizer.d.ts +0 -5
- package/dist/src/ai/helpers.d.ts +0 -5
- package/dist/src/ai/index.d.ts +0 -4
- package/dist/src/ai/interceptors/request-interceptor.d.ts +0 -12
- package/dist/src/ai/tools/call-endpoint.tool.d.ts +0 -7
- package/dist/src/ai/tools/capture-files.tool.d.ts +0 -6
- package/dist/src/ai/tools/execute-code.tool.d.ts +0 -4
- package/dist/src/ai/tools/query-graph.tool.d.ts +0 -5
- package/dist/src/cli/extract-endpoints.d.ts +0 -6
- package/dist/src/config.d.ts +0 -165
- package/dist/src/db/migrate.d.ts +0 -1
- package/dist/src/graph/expand-domains.d.ts +0 -2
- package/dist/src/graph/generate-cypher.d.ts +0 -22
- package/dist/src/graph/index.d.ts +0 -11
- package/dist/src/graph/seed.d.ts +0 -19
- package/dist/src/graph/validate.d.ts +0 -2
- package/dist/src/routes/index.d.ts +0 -4
- package/dist/src/types.d.ts +0 -74
- package/dist/src/ws/events.d.ts +0 -39
- package/dist/src/ws/index.d.ts +0 -3
- package/dist/src/ws/notify.d.ts +0 -2
- package/src/adapters/database.ts +0 -29
- package/src/adapters/mssql.ts +0 -195
- package/src/ai/active-streams.ts +0 -123
- package/src/ai/context/compressor.ts +0 -47
- package/src/ai/context/index.ts +0 -75
- package/src/ai/context/summarizer.ts +0 -50
- package/src/ai/context/token-estimator.ts +0 -60
- package/src/ai/helpers.ts +0 -32
- package/src/ai/index.ts +0 -277
- package/src/ai/interceptors/request-interceptor.ts +0 -61
- package/src/ai/prompt.ts +0 -126
- package/src/ai/tools/call-endpoint.tool.ts +0 -89
- package/src/ai/tools/capture-files.tool.ts +0 -20
- package/src/ai/tools/execute-code.tool.ts +0 -153
- package/src/cli/extract-endpoints.ts +0 -550
- package/src/config.ts +0 -182
- package/src/db/migrate.ts +0 -21
- package/src/db/migrations/20260315000000_add_context_meta/migration.sql +0 -1
- package/src/db/schema.ts +0 -70
- package/src/factory.ts +0 -171
- package/src/graph/expand-domains.ts +0 -276
- package/src/graph/generate-cypher.ts +0 -192
- package/src/graph/index.ts +0 -47
- package/src/graph/resolver.ts +0 -357
- package/src/graph/seed.ts +0 -162
- package/src/graph/validate.ts +0 -78
- package/src/routes/chat.ts +0 -86
- package/src/routes/files.ts +0 -100
- package/src/routes/index.ts +0 -4
- package/src/types.ts +0 -74
- package/src/ws/events.ts +0 -39
- package/src/ws/index.ts +0 -11
- package/src/ws/notify.ts +0 -9
- /package/dist/src/{auth → lib/auth}/middleware.d.ts +0 -0
package/src/graph/resolver.ts
DELETED
|
@@ -1,357 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pre-resolves relevant API endpoints from the Neo4j knowledge graph
|
|
3
|
-
* using vector similarity search on concept descriptions.
|
|
4
|
-
*
|
|
5
|
-
* All configuration is passed explicitly — no hardcoded model references
|
|
6
|
-
* or environment variables.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { EmbeddingModel } from "ai";
|
|
10
|
-
import { embed } from "ai";
|
|
11
|
-
import type { Neo4jClient } from "./neo4j.ts";
|
|
12
|
-
import type { ConceptDef } from "./types.ts";
|
|
13
|
-
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
|
-
// Config
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
|
-
|
|
18
|
-
export type RerankerConfig = {
|
|
19
|
-
url: string;
|
|
20
|
-
apiKey: string;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export type ResolverConfig = {
|
|
24
|
-
neo4j: Neo4jClient;
|
|
25
|
-
embeddingModel: EmbeddingModel;
|
|
26
|
-
reranker?: RerankerConfig;
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
// ---------------------------------------------------------------------------
|
|
30
|
-
// Result types
|
|
31
|
-
// ---------------------------------------------------------------------------
|
|
32
|
-
|
|
33
|
-
type EndpointDependency = {
|
|
34
|
-
depPath: string;
|
|
35
|
-
depMethod: string;
|
|
36
|
-
paramName: string;
|
|
37
|
-
fromField: string;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
type EndpointRelation = "read" | "write";
|
|
41
|
-
|
|
42
|
-
export type ResolvedEndpoint = {
|
|
43
|
-
concept: string;
|
|
44
|
-
relation: EndpointRelation;
|
|
45
|
-
name: string;
|
|
46
|
-
path: string;
|
|
47
|
-
method: string;
|
|
48
|
-
params: string;
|
|
49
|
-
body: string;
|
|
50
|
-
response: string;
|
|
51
|
-
dependencies: EndpointDependency[];
|
|
52
|
-
rules: string[];
|
|
53
|
-
metadata: string;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
export type ResolvedService = {
|
|
57
|
-
concept: string;
|
|
58
|
-
serviceName: string;
|
|
59
|
-
builtInId: string;
|
|
60
|
-
description: string;
|
|
61
|
-
rules: string[];
|
|
62
|
-
metadata: string;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
export type ResolvedContext = {
|
|
66
|
-
readEndpoints: ResolvedEndpoint[];
|
|
67
|
-
writeEndpoints: ResolvedEndpoint[];
|
|
68
|
-
services: ResolvedService[];
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
// ---------------------------------------------------------------------------
|
|
72
|
-
// Internal row types
|
|
73
|
-
// ---------------------------------------------------------------------------
|
|
74
|
-
|
|
75
|
-
type EndpointRow = {
|
|
76
|
-
concept: string;
|
|
77
|
-
relationType: "QUERIED_VIA" | "MUTATED_VIA";
|
|
78
|
-
name: string;
|
|
79
|
-
path: string;
|
|
80
|
-
method: string;
|
|
81
|
-
params: string | null;
|
|
82
|
-
body: string | null;
|
|
83
|
-
response: string | null;
|
|
84
|
-
metadata: string | null;
|
|
85
|
-
dependencies: (EndpointDependency | { depPath: null })[];
|
|
86
|
-
rules: (string | null)[];
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
type ServiceRow = {
|
|
90
|
-
concept: string;
|
|
91
|
-
serviceName: string;
|
|
92
|
-
builtInId: string;
|
|
93
|
-
description: string | null;
|
|
94
|
-
metadata: string | null;
|
|
95
|
-
rules: (string | null)[];
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
// ---------------------------------------------------------------------------
|
|
99
|
-
// Public API
|
|
100
|
-
// ---------------------------------------------------------------------------
|
|
101
|
-
|
|
102
|
-
export async function resolveFromGraph(prompt: string, config: ResolverConfig) {
|
|
103
|
-
const empty: ResolvedContext = {
|
|
104
|
-
readEndpoints: [],
|
|
105
|
-
writeEndpoints: [],
|
|
106
|
-
services: [],
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
try {
|
|
110
|
-
const { embedding } = await embed({
|
|
111
|
-
model: config.embeddingModel,
|
|
112
|
-
value: prompt,
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
const conceptsRaw = await config.neo4j.query(
|
|
116
|
-
`CALL db.index.vector.queryNodes('concept_embeddings', 10, $embedding)
|
|
117
|
-
YIELD node, score
|
|
118
|
-
WHERE score > 0.3
|
|
119
|
-
RETURN node.name AS name, node.description AS description, score
|
|
120
|
-
ORDER BY score DESC`,
|
|
121
|
-
{ embedding },
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
let concepts = JSON.parse(conceptsRaw) as (Pick<ConceptDef, "name" | "description"> & {
|
|
125
|
-
score: number;
|
|
126
|
-
})[];
|
|
127
|
-
|
|
128
|
-
if (!Array.isArray(concepts) || concepts.length === 0) {
|
|
129
|
-
return empty;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (config.reranker) {
|
|
133
|
-
concepts = await computeRelevanceScores(prompt, concepts, config.reranker);
|
|
134
|
-
} else {
|
|
135
|
-
concepts = concepts.slice(0, 3);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const conceptNames = concepts.map((c) => c.name);
|
|
139
|
-
|
|
140
|
-
const endpointsRaw = await config.neo4j.query(
|
|
141
|
-
`UNWIND $names AS conceptName
|
|
142
|
-
MATCH (c:Concept {name: conceptName})-[:SPECIALIZES*0..3]->(ancestor:Concept)
|
|
143
|
-
WITH conceptName, collect(DISTINCT ancestor) AS family
|
|
144
|
-
UNWIND family AS related
|
|
145
|
-
MATCH (related)-[rel:QUERIED_VIA|MUTATED_VIA]->(e:Endpoint)
|
|
146
|
-
WITH conceptName, related, rel, e
|
|
147
|
-
OPTIONAL MATCH (e)-[d:DEPENDS_ON]->(dep:Endpoint)
|
|
148
|
-
WITH conceptName, related, rel, e,
|
|
149
|
-
collect(DISTINCT {
|
|
150
|
-
depPath: dep.path,
|
|
151
|
-
depMethod: dep.method,
|
|
152
|
-
paramName: d.paramName,
|
|
153
|
-
fromField: d.fromField
|
|
154
|
-
}) AS dependencies
|
|
155
|
-
OPTIONAL MATCH (rEndpoint:Rule)-[:GOVERNS]->(e)
|
|
156
|
-
OPTIONAL MATCH (rConcept:Rule)-[:GOVERNS]->(related)
|
|
157
|
-
RETURN conceptName AS concept,
|
|
158
|
-
type(rel) AS relationType,
|
|
159
|
-
e.name AS name,
|
|
160
|
-
e.path AS path,
|
|
161
|
-
e.method AS method,
|
|
162
|
-
e.params AS params,
|
|
163
|
-
e.body AS body,
|
|
164
|
-
e.response AS response,
|
|
165
|
-
e.metadata AS metadata,
|
|
166
|
-
dependencies,
|
|
167
|
-
collect(DISTINCT rEndpoint.description) +
|
|
168
|
-
collect(DISTINCT rConcept.description) AS rules`,
|
|
169
|
-
{ names: conceptNames },
|
|
170
|
-
);
|
|
171
|
-
|
|
172
|
-
const endpointRows = asArray<EndpointRow>(JSON.parse(endpointsRaw));
|
|
173
|
-
const allEndpoints = dedupeEndpoints(
|
|
174
|
-
endpointRows.map(function (row) {
|
|
175
|
-
return {
|
|
176
|
-
concept: row.concept,
|
|
177
|
-
relation:
|
|
178
|
-
row.relationType === "MUTATED_VIA" ? ("write" as const) : ("read" as const),
|
|
179
|
-
name: row.name,
|
|
180
|
-
path: row.path,
|
|
181
|
-
method: row.method,
|
|
182
|
-
params: row.params ?? "[]",
|
|
183
|
-
body: row.body ?? "[]",
|
|
184
|
-
response: row.response ?? "[]",
|
|
185
|
-
metadata: row.metadata ?? "{}",
|
|
186
|
-
dependencies: row.dependencies.filter(
|
|
187
|
-
(dep): dep is EndpointDependency => dep.depPath != null,
|
|
188
|
-
),
|
|
189
|
-
rules: row.rules.filter((rule): rule is string => Boolean(rule)),
|
|
190
|
-
};
|
|
191
|
-
}),
|
|
192
|
-
);
|
|
193
|
-
|
|
194
|
-
const servicesRaw = await config.neo4j.query(
|
|
195
|
-
`UNWIND $names AS conceptName
|
|
196
|
-
MATCH (c:Concept {name: conceptName})-[:SPECIALIZES*0..3]->(ancestor:Concept)
|
|
197
|
-
WITH conceptName, collect(DISTINCT ancestor) AS family
|
|
198
|
-
UNWIND family AS related
|
|
199
|
-
MATCH (related)-[:REQUESTED_VIA]->(svc:Service)
|
|
200
|
-
WITH conceptName, related, svc
|
|
201
|
-
OPTIONAL MATCH (rService:Rule)-[:GOVERNS]->(svc)
|
|
202
|
-
OPTIONAL MATCH (rConcept:Rule)-[:GOVERNS]->(related)
|
|
203
|
-
RETURN conceptName AS concept,
|
|
204
|
-
svc.name AS serviceName,
|
|
205
|
-
svc.builtInId AS builtInId,
|
|
206
|
-
svc.description AS description,
|
|
207
|
-
svc.metadata AS metadata,
|
|
208
|
-
collect(DISTINCT rService.description) +
|
|
209
|
-
collect(DISTINCT rConcept.description) AS rules`,
|
|
210
|
-
{ names: conceptNames },
|
|
211
|
-
);
|
|
212
|
-
|
|
213
|
-
const services = dedupeServices(
|
|
214
|
-
asArray<ServiceRow>(JSON.parse(servicesRaw)).map(function (row) {
|
|
215
|
-
return {
|
|
216
|
-
concept: row.concept,
|
|
217
|
-
serviceName: row.serviceName,
|
|
218
|
-
builtInId: row.builtInId,
|
|
219
|
-
description: row.description ?? "",
|
|
220
|
-
metadata: row.metadata ?? "{}",
|
|
221
|
-
rules: row.rules.filter((rule): rule is string => Boolean(rule)),
|
|
222
|
-
};
|
|
223
|
-
}),
|
|
224
|
-
);
|
|
225
|
-
|
|
226
|
-
// Service-to-Servicing bridge: if any services were resolved, pull in
|
|
227
|
-
// the generic Servicing endpoints
|
|
228
|
-
let servicingEndpoints: ResolvedEndpoint[] = [];
|
|
229
|
-
if (services.length > 0) {
|
|
230
|
-
const servicingRaw = await config.neo4j.query(
|
|
231
|
-
`MATCH (c:Concept {name: 'ServiceRequest'})-[rel:QUERIED_VIA|MUTATED_VIA]->(e:Endpoint)
|
|
232
|
-
OPTIONAL MATCH (e)-[d:DEPENDS_ON]->(dep:Endpoint)
|
|
233
|
-
WITH c, rel, e,
|
|
234
|
-
collect(DISTINCT {
|
|
235
|
-
depPath: dep.path,
|
|
236
|
-
depMethod: dep.method,
|
|
237
|
-
paramName: d.paramName,
|
|
238
|
-
fromField: d.fromField
|
|
239
|
-
}) AS dependencies
|
|
240
|
-
OPTIONAL MATCH (rEndpoint:Rule)-[:GOVERNS]->(e)
|
|
241
|
-
OPTIONAL MATCH (rConcept:Rule)-[:GOVERNS]->(c)
|
|
242
|
-
RETURN 'ServiceRequest' AS concept,
|
|
243
|
-
type(rel) AS relationType,
|
|
244
|
-
e.name AS name,
|
|
245
|
-
e.path AS path,
|
|
246
|
-
e.method AS method,
|
|
247
|
-
e.params AS params,
|
|
248
|
-
e.body AS body,
|
|
249
|
-
e.response AS response,
|
|
250
|
-
e.metadata AS metadata,
|
|
251
|
-
dependencies,
|
|
252
|
-
collect(DISTINCT rEndpoint.description) +
|
|
253
|
-
collect(DISTINCT rConcept.description) AS rules`,
|
|
254
|
-
{},
|
|
255
|
-
);
|
|
256
|
-
|
|
257
|
-
servicingEndpoints = dedupeEndpoints(
|
|
258
|
-
asArray<EndpointRow>(JSON.parse(servicingRaw)).map(function (row) {
|
|
259
|
-
return {
|
|
260
|
-
concept: row.concept,
|
|
261
|
-
relation:
|
|
262
|
-
row.relationType === "MUTATED_VIA"
|
|
263
|
-
? ("write" as const)
|
|
264
|
-
: ("read" as const),
|
|
265
|
-
name: row.name,
|
|
266
|
-
path: row.path,
|
|
267
|
-
method: row.method,
|
|
268
|
-
params: row.params ?? "[]",
|
|
269
|
-
body: row.body ?? "[]",
|
|
270
|
-
response: row.response ?? "[]",
|
|
271
|
-
metadata: row.metadata ?? "{}",
|
|
272
|
-
dependencies: row.dependencies.filter(
|
|
273
|
-
(dep): dep is EndpointDependency => dep.depPath != null,
|
|
274
|
-
),
|
|
275
|
-
rules: row.rules.filter((rule): rule is string => Boolean(rule)),
|
|
276
|
-
};
|
|
277
|
-
}),
|
|
278
|
-
);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
const combinedEndpoints = dedupeEndpoints([...allEndpoints, ...servicingEndpoints]);
|
|
282
|
-
|
|
283
|
-
return {
|
|
284
|
-
readEndpoints: combinedEndpoints.filter((ep) => ep.relation === "read"),
|
|
285
|
-
writeEndpoints: combinedEndpoints.filter((ep) => ep.relation === "write"),
|
|
286
|
-
services,
|
|
287
|
-
} satisfies ResolvedContext;
|
|
288
|
-
} catch (error) {
|
|
289
|
-
console.error("Graph resolution failed:", error);
|
|
290
|
-
return empty;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
// ---------------------------------------------------------------------------
|
|
295
|
-
// Internal helpers
|
|
296
|
-
// ---------------------------------------------------------------------------
|
|
297
|
-
|
|
298
|
-
function asArray<T>(value: unknown) {
|
|
299
|
-
return Array.isArray(value) ? (value as T[]) : ([] as T[]);
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
function dedupeEndpoints(endpoints: ResolvedEndpoint[]) {
|
|
303
|
-
const seen = new Set<string>();
|
|
304
|
-
const deduped: ResolvedEndpoint[] = [];
|
|
305
|
-
|
|
306
|
-
for (const ep of endpoints) {
|
|
307
|
-
const key = `${ep.relation}|${ep.concept}|${ep.method}|${ep.path}`;
|
|
308
|
-
if (seen.has(key)) continue;
|
|
309
|
-
seen.add(key);
|
|
310
|
-
deduped.push(ep);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
return deduped;
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
function dedupeServices(services: ResolvedService[]) {
|
|
317
|
-
const seen = new Set<string>();
|
|
318
|
-
const deduped: ResolvedService[] = [];
|
|
319
|
-
|
|
320
|
-
for (const svc of services) {
|
|
321
|
-
const key = `${svc.concept}|${svc.builtInId}`;
|
|
322
|
-
if (seen.has(key)) continue;
|
|
323
|
-
seen.add(key);
|
|
324
|
-
deduped.push(svc);
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
return deduped;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
async function computeRelevanceScores(
|
|
331
|
-
prompt: string,
|
|
332
|
-
concepts: (Pick<ConceptDef, "name" | "description"> & { score: number })[],
|
|
333
|
-
reranker: RerankerConfig,
|
|
334
|
-
) {
|
|
335
|
-
const response = await fetch(reranker.url, {
|
|
336
|
-
method: "POST",
|
|
337
|
-
headers: {
|
|
338
|
-
Authorization: `Bearer ${reranker.apiKey}`,
|
|
339
|
-
"Content-Type": "application/json",
|
|
340
|
-
},
|
|
341
|
-
body: JSON.stringify({
|
|
342
|
-
queries: [prompt],
|
|
343
|
-
documents: concepts.map((x) => x.description),
|
|
344
|
-
}),
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
const data = (await response.json()) as { scores: number[] };
|
|
348
|
-
const scores = data.scores;
|
|
349
|
-
|
|
350
|
-
const scoredConcepts = concepts.map((c, idx) => ({
|
|
351
|
-
...c,
|
|
352
|
-
score: scores[idx]!,
|
|
353
|
-
}));
|
|
354
|
-
|
|
355
|
-
scoredConcepts.sort((a, b) => b.score - a.score);
|
|
356
|
-
return scoredConcepts.slice(0, 3);
|
|
357
|
-
}
|
package/src/graph/seed.ts
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Seed orchestrator for the knowledge graph.
|
|
3
|
-
*
|
|
4
|
-
* Validates domains, generates Cypher, executes against Neo4j,
|
|
5
|
-
* and generates concept embeddings. All configuration is passed
|
|
6
|
-
* explicitly — no environment variables or Convex dependencies.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { EmbeddingModel } from "ai";
|
|
10
|
-
import { embed } from "ai";
|
|
11
|
-
import type { Neo4jClient, Neo4jConfig } from "./neo4j.ts";
|
|
12
|
-
import { createNeo4jClient } from "./neo4j.ts";
|
|
13
|
-
import { expandDomains } from "./expand-domains.ts";
|
|
14
|
-
import { generateCypher, type GeneratedCypher } from "./generate-cypher.ts";
|
|
15
|
-
import type { DomainDef } from "./types.ts";
|
|
16
|
-
import { validateDomain } from "./validate.ts";
|
|
17
|
-
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
// Config
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
|
|
22
|
-
export type EmbeddingConfig = {
|
|
23
|
-
model: EmbeddingModel;
|
|
24
|
-
dimension: number;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
export type SeedGraphConfig = {
|
|
28
|
-
neo4j: Neo4jConfig;
|
|
29
|
-
embedding: EmbeddingConfig;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
// ---------------------------------------------------------------------------
|
|
33
|
-
// Internal helpers
|
|
34
|
-
// ---------------------------------------------------------------------------
|
|
35
|
-
|
|
36
|
-
async function runStatements(client: Neo4jClient, label: string, statements: string[]) {
|
|
37
|
-
console.log(`\n--- ${label} (${statements.length} statements) ---`);
|
|
38
|
-
|
|
39
|
-
let success = 0;
|
|
40
|
-
let failed = 0;
|
|
41
|
-
|
|
42
|
-
for (const stmt of statements) {
|
|
43
|
-
try {
|
|
44
|
-
const result = await client.query(stmt);
|
|
45
|
-
const parsed = JSON.parse(result);
|
|
46
|
-
if (parsed.error) {
|
|
47
|
-
console.error(` ✗ Failed: ${parsed.message}`);
|
|
48
|
-
console.error(` Statement: ${stmt.substring(0, 120)}...`);
|
|
49
|
-
failed++;
|
|
50
|
-
} else {
|
|
51
|
-
success++;
|
|
52
|
-
}
|
|
53
|
-
} catch (e) {
|
|
54
|
-
console.error(` ✗ Exception: ${e}`);
|
|
55
|
-
console.error(` Statement: ${stmt.substring(0, 120)}...`);
|
|
56
|
-
failed++;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
console.log(` ✓ ${success} succeeded, ${failed} failed`);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
async function generateEmbeddings(client: Neo4jClient, embeddingConfig: EmbeddingConfig) {
|
|
64
|
-
console.log("Seeding concept embeddings...");
|
|
65
|
-
|
|
66
|
-
// 1. Create the vector index (idempotent)
|
|
67
|
-
await client.query(
|
|
68
|
-
`CREATE VECTOR INDEX concept_embeddings IF NOT EXISTS
|
|
69
|
-
FOR (c:Concept) ON (c.embedding)
|
|
70
|
-
OPTIONS {indexConfig: {
|
|
71
|
-
\`vector.dimensions\`: ${embeddingConfig.dimension},
|
|
72
|
-
\`vector.similarity_function\`: 'cosine'
|
|
73
|
-
}}`,
|
|
74
|
-
);
|
|
75
|
-
console.log("Vector index created (or already exists)");
|
|
76
|
-
|
|
77
|
-
// 2. Fetch all concepts
|
|
78
|
-
const conceptsRaw = await client.query(
|
|
79
|
-
"MATCH (c:Concept) RETURN c.name AS name, c.description AS description",
|
|
80
|
-
);
|
|
81
|
-
const concepts: { name: string; description: string }[] = JSON.parse(conceptsRaw);
|
|
82
|
-
|
|
83
|
-
if (!Array.isArray(concepts) || concepts.length === 0) {
|
|
84
|
-
console.log("No concepts found in Neo4j");
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
console.log(`Found ${concepts.length} concepts, generating embeddings...`);
|
|
89
|
-
|
|
90
|
-
// 3. Generate and store embeddings for each concept
|
|
91
|
-
const embeddingResults = await Promise.all(
|
|
92
|
-
concepts.map(async (concept) => ({
|
|
93
|
-
concept,
|
|
94
|
-
embedding: (
|
|
95
|
-
await embed({
|
|
96
|
-
model: embeddingConfig.model,
|
|
97
|
-
value: concept.description,
|
|
98
|
-
})
|
|
99
|
-
).embedding,
|
|
100
|
-
})),
|
|
101
|
-
);
|
|
102
|
-
|
|
103
|
-
// 4. Store the embeddings in the graph
|
|
104
|
-
await Promise.all(
|
|
105
|
-
embeddingResults.map(
|
|
106
|
-
async (result) =>
|
|
107
|
-
await client.query(
|
|
108
|
-
`MATCH (c:Concept {name: $name})
|
|
109
|
-
SET c.embedding = $embedding`,
|
|
110
|
-
{
|
|
111
|
-
name: result.concept.name,
|
|
112
|
-
embedding: result.embedding,
|
|
113
|
-
},
|
|
114
|
-
),
|
|
115
|
-
),
|
|
116
|
-
);
|
|
117
|
-
|
|
118
|
-
console.log("Embedding seeding complete!");
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// ---------------------------------------------------------------------------
|
|
122
|
-
// Public API
|
|
123
|
-
// ---------------------------------------------------------------------------
|
|
124
|
-
|
|
125
|
-
export async function seedGraph(config: SeedGraphConfig, domains: Record<string, DomainDef>) {
|
|
126
|
-
const expandedDomains = expandDomains(domains);
|
|
127
|
-
|
|
128
|
-
// Validate all domains
|
|
129
|
-
const validationErrors = Object.entries(expandedDomains).flatMap(([name, domain]) =>
|
|
130
|
-
validateDomain(domain).map((err) => `[${name}] ${err}`),
|
|
131
|
-
);
|
|
132
|
-
|
|
133
|
-
if (validationErrors.length) {
|
|
134
|
-
validationErrors.forEach((err) => console.error(err));
|
|
135
|
-
throw new Error(`Validation failed with ${validationErrors.length} error(s)`);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const client = createNeo4jClient(config.neo4j, config.embedding.model);
|
|
139
|
-
const targets = Object.entries(expandedDomains);
|
|
140
|
-
|
|
141
|
-
console.log(`Seeding ${targets.length} domain(s)...`);
|
|
142
|
-
|
|
143
|
-
// Generate Cypher for all target domains
|
|
144
|
-
const allCypher: [string, GeneratedCypher][] = targets.map(([name, data]) => [
|
|
145
|
-
name,
|
|
146
|
-
generateCypher(data),
|
|
147
|
-
]);
|
|
148
|
-
|
|
149
|
-
// Phase 1: Create all nodes across every domain first.
|
|
150
|
-
// This ensures cross-domain references resolve correctly.
|
|
151
|
-
const allNodes = allCypher.flatMap(([, c]) => c.nodes);
|
|
152
|
-
await runStatements(client, "Phase 1: Nodes", allNodes);
|
|
153
|
-
|
|
154
|
-
// Phase 2: Create all edges now that every node exists.
|
|
155
|
-
const allEdges = allCypher.flatMap(([, c]) => c.edges);
|
|
156
|
-
await runStatements(client, "Phase 2: Edges", allEdges);
|
|
157
|
-
|
|
158
|
-
console.log("\nGraph seeding complete!");
|
|
159
|
-
|
|
160
|
-
// Phase 3: Generate embeddings for concepts
|
|
161
|
-
await generateEmbeddings(client, config.embedding);
|
|
162
|
-
}
|
package/src/graph/validate.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import type { DomainDef } from "./types.ts";
|
|
2
|
-
|
|
3
|
-
export function validateDomain(data: DomainDef) {
|
|
4
|
-
const errors: string[] = [];
|
|
5
|
-
|
|
6
|
-
const seenConceptNames = new Set<string>();
|
|
7
|
-
for (const c of data.concepts ?? []) {
|
|
8
|
-
if (seenConceptNames.has(c.name)) {
|
|
9
|
-
errors.push(`Duplicate concept name: "${c.name}"`);
|
|
10
|
-
}
|
|
11
|
-
seenConceptNames.add(c.name);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
const seenEndpointNames = new Set<string>();
|
|
15
|
-
for (const e of data.endpoints ?? []) {
|
|
16
|
-
if (seenEndpointNames.has(e.name)) {
|
|
17
|
-
errors.push(`Duplicate endpoint name: "${e.name}"`);
|
|
18
|
-
}
|
|
19
|
-
seenEndpointNames.add(e.name);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
const seenServiceNames = new Set<string>();
|
|
23
|
-
for (const s of data.services ?? []) {
|
|
24
|
-
if (seenServiceNames.has(s.name)) {
|
|
25
|
-
errors.push(`Duplicate service name: "${s.name}"`);
|
|
26
|
-
}
|
|
27
|
-
seenServiceNames.add(s.name);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const seenRuleNames = new Set<string>();
|
|
31
|
-
for (const r of data.rules ?? []) {
|
|
32
|
-
if (seenRuleNames.has(r.name)) {
|
|
33
|
-
errors.push(`Duplicate rule name: "${r.name}"`);
|
|
34
|
-
}
|
|
35
|
-
seenRuleNames.add(r.name);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Cross-domain references are allowed (concepts/endpoints/services may
|
|
39
|
-
// be defined in another domain), so we do not enforce local membership.
|
|
40
|
-
|
|
41
|
-
const referencedConcepts = new Set<string>();
|
|
42
|
-
const referencedRules = new Set<string>();
|
|
43
|
-
|
|
44
|
-
for (const ep of data.endpoints ?? []) {
|
|
45
|
-
ep.queries?.forEach((c) => referencedConcepts.add(c.name));
|
|
46
|
-
ep.mutates?.forEach((c) => referencedConcepts.add(c.name));
|
|
47
|
-
ep.returns?.forEach((r) => referencedConcepts.add(r.concept.name));
|
|
48
|
-
ep.governedBy?.forEach((r) => referencedRules.add(r.name));
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
for (const svc of data.services ?? []) {
|
|
52
|
-
referencedConcepts.add(svc.belongsTo.name);
|
|
53
|
-
svc.governedBy?.forEach((r) => referencedRules.add(r.name));
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
for (const c of data.concepts ?? []) {
|
|
57
|
-
c.governedBy?.forEach((r) => referencedRules.add(r.name));
|
|
58
|
-
if (c.parentConcept) {
|
|
59
|
-
referencedConcepts.add(c.parentConcept.name);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
for (const c of data.concepts ?? []) {
|
|
64
|
-
if (!referencedConcepts.has(c.name)) {
|
|
65
|
-
errors.push(`Concept "${c.name}" is never referenced by any endpoint, or service`);
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
for (const r of data.rules ?? []) {
|
|
70
|
-
if (!referencedRules.has(r.name)) {
|
|
71
|
-
errors.push(
|
|
72
|
-
`Rule "${r.name}" is never referenced by any endpoint, service, or concept`,
|
|
73
|
-
);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return errors;
|
|
78
|
-
}
|
package/src/routes/chat.ts
DELETED
|
@@ -1,86 +0,0 @@
|
|
|
1
|
-
import { Hono } from "hono";
|
|
2
|
-
import { zValidator } from "@hono/zod-validator";
|
|
3
|
-
import z from "zod";
|
|
4
|
-
import { HTTPException } from "hono/http-exception";
|
|
5
|
-
import type { CortexAppEnv } from "../types.ts";
|
|
6
|
-
import { requireAuth } from "../auth/middleware.ts";
|
|
7
|
-
import { stream } from "../ai/index.ts";
|
|
8
|
-
import { subscribe, abortStream } from "../ai/active-streams.ts";
|
|
9
|
-
import { notify } from "../ws/index.ts";
|
|
10
|
-
import { toThreadSummary } from "../types.ts";
|
|
11
|
-
|
|
12
|
-
export function createChatRoutes() {
|
|
13
|
-
const app = new Hono<CortexAppEnv>();
|
|
14
|
-
|
|
15
|
-
app.post(
|
|
16
|
-
"/chat",
|
|
17
|
-
requireAuth,
|
|
18
|
-
zValidator(
|
|
19
|
-
"json",
|
|
20
|
-
z.object({
|
|
21
|
-
id: z.string(),
|
|
22
|
-
messages: z.array(z.unknown()),
|
|
23
|
-
}),
|
|
24
|
-
),
|
|
25
|
-
async function (c) {
|
|
26
|
-
const config = c.get("agentConfig");
|
|
27
|
-
const agentId = c.get("agentId");
|
|
28
|
-
const { id: userId, token } = c.get("user");
|
|
29
|
-
const { messages, id: threadId } = c.req.valid("json");
|
|
30
|
-
const requestContext = config.resolveRequestContext
|
|
31
|
-
? await config.resolveRequestContext(c.req.raw)
|
|
32
|
-
: {};
|
|
33
|
-
|
|
34
|
-
const thread = await config.db.threads.getById(userId, threadId);
|
|
35
|
-
|
|
36
|
-
if (!thread || thread.agentId !== agentId) {
|
|
37
|
-
throw new HTTPException(404, { message: "Not found" });
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return stream(messages, thread, userId, token, requestContext, config);
|
|
41
|
-
},
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
app.get("/chat/:chatId/stream", requireAuth, async function (c) {
|
|
45
|
-
const config = c.get("agentConfig");
|
|
46
|
-
const agentId = c.get("agentId");
|
|
47
|
-
const chatId = c.req.param("chatId");
|
|
48
|
-
const thread = await config.db.threads.getById(c.get("user").id, chatId);
|
|
49
|
-
if (!thread || thread.agentId !== agentId) {
|
|
50
|
-
throw new HTTPException(404, { message: "Not found" });
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const subscriberStream = subscribe(chatId);
|
|
54
|
-
if (!subscriberStream) {
|
|
55
|
-
return c.body(null, 204);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
return new Response(subscriberStream.pipeThrough(new TextEncoderStream()), {
|
|
59
|
-
headers: {
|
|
60
|
-
"Content-Type": "text/event-stream",
|
|
61
|
-
"Cache-Control": "no-cache",
|
|
62
|
-
Connection: "keep-alive",
|
|
63
|
-
},
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
app.post("/chat/:chatId/abort", requireAuth, async function (c) {
|
|
68
|
-
const config = c.get("agentConfig");
|
|
69
|
-
const agentId = c.get("agentId");
|
|
70
|
-
const userId = c.get("user").id;
|
|
71
|
-
const chatId = c.req.param("chatId");
|
|
72
|
-
const thread = await config.db.threads.getById(userId, chatId);
|
|
73
|
-
if (!thread || thread.agentId !== agentId) {
|
|
74
|
-
throw new HTTPException(404, { message: "Not found" });
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
abortStream(chatId);
|
|
78
|
-
notify(userId, agentId, {
|
|
79
|
-
type: "thread:run-finished",
|
|
80
|
-
payload: { thread: toThreadSummary(thread, false) },
|
|
81
|
-
});
|
|
82
|
-
return c.body(null, 204);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
return app;
|
|
86
|
-
}
|