@soulcraft/sdk 1.6.2 → 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/dist/client/create-client-sdk.d.ts +16 -2
- package/dist/client/create-client-sdk.d.ts.map +1 -1
- package/dist/client/create-client-sdk.js +2 -7
- package/dist/client/create-client-sdk.js.map +1 -1
- package/dist/client/index.d.ts +48 -37
- package/dist/client/index.d.ts.map +1 -1
- package/dist/client/index.js +61 -42
- package/dist/client/index.js.map +1 -1
- package/dist/client/namespace-proxy.d.ts +108 -0
- package/dist/client/namespace-proxy.d.ts.map +1 -0
- package/dist/client/namespace-proxy.js +151 -0
- package/dist/client/namespace-proxy.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/app-context/index.d.ts +214 -0
- package/dist/modules/app-context/index.d.ts.map +1 -0
- package/dist/modules/app-context/index.js +569 -0
- package/dist/modules/app-context/index.js.map +1 -0
- package/dist/modules/auth/products.d.ts +208 -0
- package/dist/modules/auth/products.d.ts.map +1 -0
- package/dist/modules/auth/products.js +165 -0
- package/dist/modules/auth/products.js.map +1 -0
- package/dist/namespaces.d.ts +2942 -0
- package/dist/namespaces.d.ts.map +1 -0
- package/dist/namespaces.js +37 -0
- package/dist/namespaces.js.map +1 -0
- package/dist/rpc.d.ts +156 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +26 -0
- package/dist/rpc.js.map +1 -0
- package/dist/server/create-sdk.d.ts.map +1 -1
- package/dist/server/create-sdk.js +3 -13
- package/dist/server/create-sdk.js.map +1 -1
- package/dist/server/handlers/annotations.d.ts +52 -0
- package/dist/server/handlers/annotations.d.ts.map +1 -0
- package/dist/server/handlers/annotations.js +204 -0
- package/dist/server/handlers/annotations.js.map +1 -0
- package/dist/server/handlers/auth.d.ts +53 -0
- package/dist/server/handlers/auth.d.ts.map +1 -0
- package/dist/server/handlers/auth.js +66 -0
- package/dist/server/handlers/auth.js.map +1 -0
- package/dist/server/handlers/certification.d.ts +32 -0
- package/dist/server/handlers/certification.d.ts.map +1 -0
- package/dist/server/handlers/certification.js +253 -0
- package/dist/server/handlers/certification.js.map +1 -0
- package/dist/server/handlers/chat/conversations.d.ts +91 -0
- package/dist/server/handlers/chat/conversations.d.ts.map +1 -0
- package/dist/server/handlers/chat/conversations.js +314 -0
- package/dist/server/handlers/chat/conversations.js.map +1 -0
- package/dist/server/handlers/chat/delegator.d.ts +144 -0
- package/dist/server/handlers/chat/delegator.d.ts.map +1 -0
- package/dist/server/handlers/chat/delegator.js +431 -0
- package/dist/server/handlers/chat/delegator.js.map +1 -0
- package/dist/server/handlers/chat/engine.d.ts +81 -0
- package/dist/server/handlers/chat/engine.d.ts.map +1 -0
- package/dist/server/handlers/chat/engine.js +442 -0
- package/dist/server/handlers/chat/engine.js.map +1 -0
- package/dist/server/handlers/chat/executor.d.ts +65 -0
- package/dist/server/handlers/chat/executor.d.ts.map +1 -0
- package/dist/server/handlers/chat/executor.js +375 -0
- package/dist/server/handlers/chat/executor.js.map +1 -0
- package/dist/server/handlers/chat/index.d.ts +62 -0
- package/dist/server/handlers/chat/index.d.ts.map +1 -0
- package/dist/server/handlers/chat/index.js +182 -0
- package/dist/server/handlers/chat/index.js.map +1 -0
- package/dist/server/handlers/chat/memory.d.ts +91 -0
- package/dist/server/handlers/chat/memory.d.ts.map +1 -0
- package/dist/server/handlers/chat/memory.js +293 -0
- package/dist/server/handlers/chat/memory.js.map +1 -0
- package/dist/server/handlers/chat/models.d.ts +180 -0
- package/dist/server/handlers/chat/models.d.ts.map +1 -0
- package/dist/server/handlers/chat/models.js +304 -0
- package/dist/server/handlers/chat/models.js.map +1 -0
- package/dist/server/handlers/chat/planner.d.ts +116 -0
- package/dist/server/handlers/chat/planner.d.ts.map +1 -0
- package/dist/server/handlers/chat/planner.js +344 -0
- package/dist/server/handlers/chat/planner.js.map +1 -0
- package/dist/server/handlers/chat/types.d.ts +500 -0
- package/dist/server/handlers/chat/types.d.ts.map +1 -0
- package/dist/server/handlers/chat/types.js +11 -0
- package/dist/server/handlers/chat/types.js.map +1 -0
- package/dist/server/handlers/collections.d.ts +67 -0
- package/dist/server/handlers/collections.d.ts.map +1 -0
- package/dist/server/handlers/collections.js +484 -0
- package/dist/server/handlers/collections.js.map +1 -0
- package/dist/server/handlers/commerce.d.ts +106 -0
- package/dist/server/handlers/commerce.d.ts.map +1 -0
- package/dist/server/handlers/commerce.js +62 -0
- package/dist/server/handlers/commerce.js.map +1 -0
- package/dist/server/handlers/config.d.ts +112 -0
- package/dist/server/handlers/config.d.ts.map +1 -0
- package/dist/server/handlers/config.js +122 -0
- package/dist/server/handlers/config.js.map +1 -0
- package/dist/server/handlers/export.d.ts +72 -0
- package/dist/server/handlers/export.d.ts.map +1 -0
- package/dist/server/handlers/export.js +175 -0
- package/dist/server/handlers/export.js.map +1 -0
- package/dist/server/handlers/formats.d.ts +77 -0
- package/dist/server/handlers/formats.d.ts.map +1 -0
- package/dist/server/handlers/formats.js +65 -0
- package/dist/server/handlers/formats.js.map +1 -0
- package/dist/server/handlers/graph.d.ts +31 -0
- package/dist/server/handlers/graph.d.ts.map +1 -0
- package/dist/server/handlers/graph.js +490 -0
- package/dist/server/handlers/graph.js.map +1 -0
- package/dist/server/handlers/import.d.ts +96 -0
- package/dist/server/handlers/import.d.ts.map +1 -0
- package/dist/server/handlers/import.js +108 -0
- package/dist/server/handlers/import.js.map +1 -0
- package/dist/server/handlers/index.d.ts +68 -0
- package/dist/server/handlers/index.d.ts.map +1 -0
- package/dist/server/handlers/index.js +71 -0
- package/dist/server/handlers/index.js.map +1 -0
- package/dist/server/handlers/media.d.ts +76 -0
- package/dist/server/handlers/media.d.ts.map +1 -0
- package/dist/server/handlers/media.js +53 -0
- package/dist/server/handlers/media.js.map +1 -0
- package/dist/server/handlers/project.d.ts +45 -0
- package/dist/server/handlers/project.d.ts.map +1 -0
- package/dist/server/handlers/project.js +181 -0
- package/dist/server/handlers/project.js.map +1 -0
- package/dist/server/handlers/publish.d.ts +102 -0
- package/dist/server/handlers/publish.d.ts.map +1 -0
- package/dist/server/handlers/publish.js +130 -0
- package/dist/server/handlers/publish.js.map +1 -0
- package/dist/server/handlers/pulse.d.ts +39 -0
- package/dist/server/handlers/pulse.d.ts.map +1 -0
- package/dist/server/handlers/pulse.js +78 -0
- package/dist/server/handlers/pulse.js.map +1 -0
- package/dist/server/handlers/realtime.d.ts +55 -0
- package/dist/server/handlers/realtime.d.ts.map +1 -0
- package/dist/server/handlers/realtime.js +49 -0
- package/dist/server/handlers/realtime.js.map +1 -0
- package/dist/server/handlers/search.d.ts +21 -0
- package/dist/server/handlers/search.d.ts.map +1 -0
- package/dist/server/handlers/search.js +237 -0
- package/dist/server/handlers/search.js.map +1 -0
- package/dist/server/handlers/session.d.ts +47 -0
- package/dist/server/handlers/session.d.ts.map +1 -0
- package/dist/server/handlers/session.js +286 -0
- package/dist/server/handlers/session.js.map +1 -0
- package/dist/server/handlers/settings.d.ts +97 -0
- package/dist/server/handlers/settings.d.ts.map +1 -0
- package/dist/server/handlers/settings.js +131 -0
- package/dist/server/handlers/settings.js.map +1 -0
- package/dist/server/handlers/workspace.d.ts +78 -0
- package/dist/server/handlers/workspace.d.ts.map +1 -0
- package/dist/server/handlers/workspace.js +270 -0
- package/dist/server/handlers/workspace.js.map +1 -0
- package/dist/server/hono-router.d.ts +66 -0
- package/dist/server/hono-router.d.ts.map +1 -0
- package/dist/server/hono-router.js +203 -0
- package/dist/server/hono-router.js.map +1 -0
- package/dist/server/index.d.ts +29 -19
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +33 -19
- package/dist/server/index.js.map +1 -1
- package/dist/server/namespace-router.d.ts +204 -0
- package/dist/server/namespace-router.d.ts.map +1 -0
- package/dist/server/namespace-router.js +262 -0
- package/dist/server/namespace-router.js.map +1 -0
- package/dist/transports/http-namespace.d.ts +210 -0
- package/dist/transports/http-namespace.d.ts.map +1 -0
- package/dist/transports/http-namespace.js +514 -0
- package/dist/transports/http-namespace.js.map +1 -0
- package/dist/transports/workshop.d.ts +173 -0
- package/dist/transports/workshop.d.ts.map +1 -0
- package/dist/transports/workshop.js +307 -0
- package/dist/transports/workshop.js.map +1 -0
- package/dist/types.d.ts +65 -67
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +7 -3
- package/dist/types.js.map +1 -1
- package/docs/ADR-004-product-registry.md +108 -0
- package/package.json +1 -1
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/handlers/chat/conversations
|
|
3
|
+
* @description Conversation and message CRUD operations using Brainy entities.
|
|
4
|
+
*
|
|
5
|
+
* Conversations are stored as `collection` entities with `_aiDataType: 'conversation'`.
|
|
6
|
+
* Messages are `message` entities linked to conversations via `contains` edges.
|
|
7
|
+
* Temporal ordering uses `precedes` edges between consecutive messages.
|
|
8
|
+
*
|
|
9
|
+
* All operations are universal — Workshop, Venue, Academy, and Pulse share
|
|
10
|
+
* the same conversation storage model.
|
|
11
|
+
*/
|
|
12
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
// Constants
|
|
14
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
/** Metadata field used to identify AI-managed conversation entities. */
|
|
16
|
+
const AI_DATA_TYPE = '_aiDataType';
|
|
17
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
// Conversation CRUD
|
|
19
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
/**
|
|
21
|
+
* Create a new conversation entity.
|
|
22
|
+
*
|
|
23
|
+
* @param brain - Brainy instance.
|
|
24
|
+
* @param userId - User who owns the conversation.
|
|
25
|
+
* @param title - Optional initial title.
|
|
26
|
+
* @returns The conversation ID.
|
|
27
|
+
*/
|
|
28
|
+
export async function createConversation(brain, userId, title) {
|
|
29
|
+
const conversationId = await brain.add({
|
|
30
|
+
type: 'collection',
|
|
31
|
+
data: {
|
|
32
|
+
title: title || 'New Conversation',
|
|
33
|
+
userId,
|
|
34
|
+
startedAt: new Date().toISOString(),
|
|
35
|
+
},
|
|
36
|
+
metadata: {
|
|
37
|
+
name: title || 'New Conversation',
|
|
38
|
+
isAIManaged: true,
|
|
39
|
+
[AI_DATA_TYPE]: 'conversation',
|
|
40
|
+
conversationType: 'chat',
|
|
41
|
+
active: true,
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
return conversationId;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* List all conversations for a user.
|
|
48
|
+
*
|
|
49
|
+
* @param brain - Brainy instance.
|
|
50
|
+
* @param userId - User to list conversations for.
|
|
51
|
+
* @returns Array of conversation summaries sorted by most recent first.
|
|
52
|
+
*/
|
|
53
|
+
export async function listConversations(brain, userId) {
|
|
54
|
+
const entities = await brain.find({
|
|
55
|
+
where: { [AI_DATA_TYPE]: { equals: 'conversation' } },
|
|
56
|
+
limit: 200,
|
|
57
|
+
});
|
|
58
|
+
// Filter to this user's active conversations
|
|
59
|
+
const userConversations = entities.filter((e) => {
|
|
60
|
+
const data = e.data || {};
|
|
61
|
+
const meta = e.metadata || {};
|
|
62
|
+
return data.userId === userId && meta.active !== false;
|
|
63
|
+
});
|
|
64
|
+
// Build conversation summaries with message counts
|
|
65
|
+
const conversations = await Promise.all(userConversations.map(async (entity) => {
|
|
66
|
+
const rels = await brain.getRelations({ from: entity.id });
|
|
67
|
+
const messageRels = rels.filter((r) => r.type === 'contains' || r.verb === 'contains');
|
|
68
|
+
// Get latest message timestamp
|
|
69
|
+
let updatedAt = entity.data?.startedAt || new Date().toISOString();
|
|
70
|
+
if (messageRels.length > 0) {
|
|
71
|
+
const lastRel = messageRels[messageRels.length - 1];
|
|
72
|
+
try {
|
|
73
|
+
const lastMsg = await brain.get(lastRel.to);
|
|
74
|
+
if (lastMsg?.data?.timestamp) {
|
|
75
|
+
updatedAt = lastMsg.data.timestamp;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
catch { /* message may not exist */ }
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
id: entity.id,
|
|
82
|
+
title: entity.data?.title || 'Untitled Conversation',
|
|
83
|
+
createdAt: entity.data?.startedAt || new Date().toISOString(),
|
|
84
|
+
updatedAt,
|
|
85
|
+
messageCount: messageRels.length,
|
|
86
|
+
};
|
|
87
|
+
}));
|
|
88
|
+
// Sort by most recent first
|
|
89
|
+
conversations.sort((a, b) => new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime());
|
|
90
|
+
return conversations;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get a conversation with its full message history.
|
|
94
|
+
*
|
|
95
|
+
* @param brain - Brainy instance.
|
|
96
|
+
* @param conversationId - Conversation to retrieve.
|
|
97
|
+
* @returns Full conversation with messages, or null if not found.
|
|
98
|
+
*/
|
|
99
|
+
export async function getConversation(brain, conversationId) {
|
|
100
|
+
const entity = await brain.get(conversationId);
|
|
101
|
+
if (!entity)
|
|
102
|
+
return null;
|
|
103
|
+
const meta = entity.metadata || {};
|
|
104
|
+
if (meta[AI_DATA_TYPE] !== 'conversation')
|
|
105
|
+
return null;
|
|
106
|
+
// Load all messages
|
|
107
|
+
const rels = await brain.getRelations({ from: conversationId });
|
|
108
|
+
const messageRels = rels.filter((r) => r.type === 'contains' || r.verb === 'contains');
|
|
109
|
+
const messages = [];
|
|
110
|
+
for (const rel of messageRels) {
|
|
111
|
+
try {
|
|
112
|
+
const msg = await brain.get(rel.to);
|
|
113
|
+
if (msg?.data?.role && msg?.data?.content) {
|
|
114
|
+
messages.push({
|
|
115
|
+
role: msg.data.role,
|
|
116
|
+
content: msg.data.content,
|
|
117
|
+
timestamp: msg.data.timestamp || '',
|
|
118
|
+
...(msg.data.model ? { model: msg.data.model } : {}),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch { /* skip missing messages */ }
|
|
123
|
+
}
|
|
124
|
+
// Sort by timestamp
|
|
125
|
+
messages.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
126
|
+
return {
|
|
127
|
+
id: entity.id,
|
|
128
|
+
title: entity.data?.title || 'Untitled Conversation',
|
|
129
|
+
createdAt: entity.data?.startedAt || new Date().toISOString(),
|
|
130
|
+
updatedAt: messages.length > 0
|
|
131
|
+
? messages[messages.length - 1].timestamp
|
|
132
|
+
: entity.data?.startedAt || new Date().toISOString(),
|
|
133
|
+
messageCount: messages.length,
|
|
134
|
+
messages,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Delete a conversation and all its messages (soft delete).
|
|
139
|
+
*
|
|
140
|
+
* @param brain - Brainy instance.
|
|
141
|
+
* @param conversationId - Conversation to delete.
|
|
142
|
+
*/
|
|
143
|
+
export async function deleteConversation(brain, conversationId) {
|
|
144
|
+
const entity = await brain.get(conversationId);
|
|
145
|
+
if (!entity)
|
|
146
|
+
return;
|
|
147
|
+
// Soft delete: mark inactive
|
|
148
|
+
await brain.update({
|
|
149
|
+
id: conversationId,
|
|
150
|
+
metadata: { ...entity.metadata, active: false },
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Rename a conversation.
|
|
155
|
+
*
|
|
156
|
+
* @param brain - Brainy instance.
|
|
157
|
+
* @param conversationId - Conversation to rename.
|
|
158
|
+
* @param title - New title.
|
|
159
|
+
*/
|
|
160
|
+
export async function renameConversation(brain, conversationId, title) {
|
|
161
|
+
const entity = await brain.get(conversationId);
|
|
162
|
+
if (!entity)
|
|
163
|
+
throw new Error('Conversation not found');
|
|
164
|
+
await brain.update({
|
|
165
|
+
id: conversationId,
|
|
166
|
+
data: { ...entity.data, title },
|
|
167
|
+
metadata: { ...entity.metadata, name: title },
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
171
|
+
// Message Storage
|
|
172
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
173
|
+
/**
|
|
174
|
+
* Store a message in a conversation.
|
|
175
|
+
*
|
|
176
|
+
* Creates the message entity, links it to the conversation via `contains`,
|
|
177
|
+
* and establishes temporal ordering via `precedes`.
|
|
178
|
+
*
|
|
179
|
+
* @param brain - Brainy instance.
|
|
180
|
+
* @param conversationId - Conversation to add the message to.
|
|
181
|
+
* @param role - Message role ('user' or 'assistant').
|
|
182
|
+
* @param content - Message text content.
|
|
183
|
+
* @param events - Optional event emitter for real-time updates.
|
|
184
|
+
* @returns The message entity ID.
|
|
185
|
+
*/
|
|
186
|
+
export async function storeMessage(brain, conversationId, role, content, events) {
|
|
187
|
+
// Ensure conversation exists
|
|
188
|
+
const conversationExists = await brain.get(conversationId);
|
|
189
|
+
if (!conversationExists) {
|
|
190
|
+
await brain.add({
|
|
191
|
+
id: conversationId,
|
|
192
|
+
type: 'collection',
|
|
193
|
+
data: {
|
|
194
|
+
title: 'Chat Conversation',
|
|
195
|
+
startedAt: new Date().toISOString(),
|
|
196
|
+
},
|
|
197
|
+
metadata: {
|
|
198
|
+
name: 'Chat Conversation',
|
|
199
|
+
isAIManaged: true,
|
|
200
|
+
[AI_DATA_TYPE]: 'conversation',
|
|
201
|
+
conversationType: 'chat',
|
|
202
|
+
active: true,
|
|
203
|
+
},
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
const preview = content.length > 50 ? content.slice(0, 50) + '...' : content;
|
|
207
|
+
const messageId = await brain.add({
|
|
208
|
+
type: 'message',
|
|
209
|
+
data: {
|
|
210
|
+
role,
|
|
211
|
+
content,
|
|
212
|
+
timestamp: new Date().toISOString(),
|
|
213
|
+
},
|
|
214
|
+
metadata: {
|
|
215
|
+
name: preview,
|
|
216
|
+
isAIManaged: true,
|
|
217
|
+
[AI_DATA_TYPE]: 'message',
|
|
218
|
+
conversationId,
|
|
219
|
+
wordCount: content.split(' ').length,
|
|
220
|
+
charCount: content.length,
|
|
221
|
+
messageType: role === 'user' ? 'question' : 'response',
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
// Link message → conversation
|
|
225
|
+
await brain.relate({
|
|
226
|
+
from: conversationId,
|
|
227
|
+
to: messageId,
|
|
228
|
+
type: 'contains',
|
|
229
|
+
});
|
|
230
|
+
// Temporal ordering: link to previous message via `precedes`
|
|
231
|
+
const previousRels = await brain.getRelations({ from: conversationId });
|
|
232
|
+
const messageRels = previousRels.filter((r) => (r.type === 'contains' || r.verb === 'contains') && r.to !== messageId);
|
|
233
|
+
if (messageRels.length > 0) {
|
|
234
|
+
const lastMessageRel = messageRels[messageRels.length - 1];
|
|
235
|
+
await brain.relate({
|
|
236
|
+
from: lastMessageRel.to,
|
|
237
|
+
to: messageId,
|
|
238
|
+
type: 'precedes',
|
|
239
|
+
}).catch(() => { });
|
|
240
|
+
// If assistant response, link as describing the user's question
|
|
241
|
+
if (role === 'assistant') {
|
|
242
|
+
await brain.relate({
|
|
243
|
+
from: messageId,
|
|
244
|
+
to: lastMessageRel.to,
|
|
245
|
+
type: 'describes',
|
|
246
|
+
}).catch(() => { });
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
// Emit activity event
|
|
250
|
+
events?.emit('activity_message_new', {
|
|
251
|
+
id: messageId,
|
|
252
|
+
activityType: role === 'user' ? 'user_message' : 'assistant_message',
|
|
253
|
+
title: role === 'user' ? 'User message' : 'Assistant response',
|
|
254
|
+
preview: content.substring(0, 300),
|
|
255
|
+
conversationId,
|
|
256
|
+
});
|
|
257
|
+
return messageId;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Load conversation history — recent messages in chronological order.
|
|
261
|
+
*
|
|
262
|
+
* @param brain - Brainy instance.
|
|
263
|
+
* @param conversationId - Conversation to load.
|
|
264
|
+
* @param limit - Maximum messages to return (most recent).
|
|
265
|
+
* @returns Array of role/content pairs.
|
|
266
|
+
*/
|
|
267
|
+
export async function loadConversationHistory(brain, conversationId, limit = 20) {
|
|
268
|
+
const rels = await brain.getRelations({ from: conversationId });
|
|
269
|
+
const containsRels = rels.filter((r) => r.type === 'contains' || r.verb === 'contains');
|
|
270
|
+
const messages = await Promise.all(containsRels.slice(-limit).map(async (rel) => {
|
|
271
|
+
try {
|
|
272
|
+
const msg = await brain.get(rel.to);
|
|
273
|
+
return {
|
|
274
|
+
role: msg?.data?.role || 'user',
|
|
275
|
+
content: msg?.data?.content || '',
|
|
276
|
+
timestamp: msg?.data?.timestamp || '',
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
}));
|
|
283
|
+
return messages
|
|
284
|
+
.filter((m) => m !== null && m.content !== '')
|
|
285
|
+
.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime())
|
|
286
|
+
.map(({ role, content }) => ({ role, content }));
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Auto-title a conversation from the first user message.
|
|
290
|
+
*
|
|
291
|
+
* Fire-and-forget — errors are logged but don't propagate.
|
|
292
|
+
*
|
|
293
|
+
* @param brain - Brainy instance.
|
|
294
|
+
* @param conversationId - Conversation to title.
|
|
295
|
+
* @param message - The first user message.
|
|
296
|
+
*/
|
|
297
|
+
export async function autoTitleConversation(brain, conversationId, message) {
|
|
298
|
+
try {
|
|
299
|
+
const entity = await brain.get(conversationId);
|
|
300
|
+
const genericTitles = ['New Conversation', 'Chat Conversation'];
|
|
301
|
+
if (entity && genericTitles.includes(entity.data?.title) && message.length > 0) {
|
|
302
|
+
const autoTitle = message.substring(0, 50) + (message.length > 50 ? '...' : '');
|
|
303
|
+
await brain.update({
|
|
304
|
+
id: conversationId,
|
|
305
|
+
data: { ...entity.data, title: autoTitle },
|
|
306
|
+
metadata: { ...entity.metadata, name: autoTitle },
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
// Non-fatal — auto-titling is best-effort
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
//# sourceMappingURL=conversations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversations.js","sourceRoot":"","sources":["../../../../src/server/handlers/chat/conversations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module server/handlers/chat/delegator
|
|
3
|
+
* @description Tiered model delegation: Sonnet triage → Haiku execute → Sonnet synthesize.
|
|
4
|
+
*
|
|
5
|
+
* The delegator handles normal (non-plan-mode) chat by:
|
|
6
|
+
* 1. **Triage** — Sonnet analyzes the user message and decides: answer directly,
|
|
7
|
+
* delegate specific tasks to Haiku, or recommend Plan Mode for complex work.
|
|
8
|
+
* 2. **Execute** — Haiku runs each delegated task (tool calls). If a task fails,
|
|
9
|
+
* auto-escalates to Sonnet (the fallback model).
|
|
10
|
+
* 3. **Synthesize** — Sonnet combines task results into a coherent response.
|
|
11
|
+
*
|
|
12
|
+
* The delegator uses the injected {@link ChatAIClient} and {@link ToolExecutor},
|
|
13
|
+
* so it works with any product's tool set (Workshop, Venue, Academy).
|
|
14
|
+
*/
|
|
15
|
+
import type { ChatAIClient, ToolDefinition, ToolExecutor, ToolExecutionContext, DelegatedTask, TriageResult, TaskExecutionResult, DelegationResult } from './types.js';
|
|
16
|
+
/**
|
|
17
|
+
* Options for the triage phase.
|
|
18
|
+
*/
|
|
19
|
+
export interface TriageOptions {
|
|
20
|
+
/** The user's message. */
|
|
21
|
+
message: string;
|
|
22
|
+
/** Recent conversation history. */
|
|
23
|
+
conversationHistory: Array<{
|
|
24
|
+
role: string;
|
|
25
|
+
content: string;
|
|
26
|
+
}>;
|
|
27
|
+
/** AI client for calling Claude. */
|
|
28
|
+
aiClient: ChatAIClient;
|
|
29
|
+
/** Available tools (used to populate the triage prompt). */
|
|
30
|
+
tools: ToolDefinition[];
|
|
31
|
+
/** Model to use for triage. Defaults to Sonnet. */
|
|
32
|
+
triageModel?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Triage a user message — Sonnet decides how to handle it.
|
|
36
|
+
*
|
|
37
|
+
* Parses Claude's JSON response into a {@link RoutingDecision}. If parsing
|
|
38
|
+
* fails, falls back to treating the response as a direct answer.
|
|
39
|
+
*
|
|
40
|
+
* @param options - Triage configuration.
|
|
41
|
+
* @returns The routing decision and token usage.
|
|
42
|
+
*/
|
|
43
|
+
export declare function triageMessage(options: TriageOptions): Promise<TriageResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Options for executing a single delegated task.
|
|
46
|
+
*/
|
|
47
|
+
export interface ExecuteTaskOptions {
|
|
48
|
+
/** The task to execute. */
|
|
49
|
+
task: DelegatedTask;
|
|
50
|
+
/** AI client for calling Claude. */
|
|
51
|
+
aiClient: ChatAIClient;
|
|
52
|
+
/** Tool executor for running tool calls. */
|
|
53
|
+
toolExecutor: ToolExecutor;
|
|
54
|
+
/** Tool definitions available to the executor model. */
|
|
55
|
+
tools: ToolDefinition[];
|
|
56
|
+
/** Execution context for tool calls. */
|
|
57
|
+
toolContext: ToolExecutionContext;
|
|
58
|
+
/** Primary executor model. Defaults to Haiku. */
|
|
59
|
+
executeModel?: string;
|
|
60
|
+
/** Fallback model for auto-escalation. Defaults to Sonnet. */
|
|
61
|
+
fallbackModel?: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Execute a single delegated task using the executor model.
|
|
65
|
+
*
|
|
66
|
+
* If the task has explicit `tool` and `input` fields (from triage), executes
|
|
67
|
+
* the tool directly without an AI call. Otherwise, sends the task description
|
|
68
|
+
* to the executor model and lets it choose tools.
|
|
69
|
+
*
|
|
70
|
+
* Auto-escalates to the fallback model on failure.
|
|
71
|
+
*
|
|
72
|
+
* @param options - Task execution configuration.
|
|
73
|
+
* @returns Execution result with token usage.
|
|
74
|
+
*/
|
|
75
|
+
export declare function executeTask(options: ExecuteTaskOptions): Promise<TaskExecutionResult>;
|
|
76
|
+
/**
|
|
77
|
+
* Options for the synthesis phase.
|
|
78
|
+
*/
|
|
79
|
+
export interface SynthesizeOptions {
|
|
80
|
+
/** The original user message. */
|
|
81
|
+
userMessage: string;
|
|
82
|
+
/** Results from executed tasks. */
|
|
83
|
+
taskResults: TaskExecutionResult[];
|
|
84
|
+
/** AI client for calling Claude. */
|
|
85
|
+
aiClient: ChatAIClient;
|
|
86
|
+
/** Model to use for synthesis. Defaults to Sonnet. */
|
|
87
|
+
synthesizeModel?: string;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Synthesize task results into a coherent response using Sonnet.
|
|
91
|
+
*
|
|
92
|
+
* Takes the raw task outputs and composes a user-facing answer that
|
|
93
|
+
* addresses the original request.
|
|
94
|
+
*
|
|
95
|
+
* @param options - Synthesis configuration.
|
|
96
|
+
* @returns The synthesized response text and token usage.
|
|
97
|
+
*/
|
|
98
|
+
export declare function synthesizeResults(options: SynthesizeOptions): Promise<{
|
|
99
|
+
response: string;
|
|
100
|
+
inputTokens: number;
|
|
101
|
+
outputTokens: number;
|
|
102
|
+
}>;
|
|
103
|
+
/**
|
|
104
|
+
* Options for the complete delegation flow.
|
|
105
|
+
*/
|
|
106
|
+
export interface DelegateOptions {
|
|
107
|
+
/** The user's message. */
|
|
108
|
+
message: string;
|
|
109
|
+
/** Recent conversation history. */
|
|
110
|
+
conversationHistory: Array<{
|
|
111
|
+
role: string;
|
|
112
|
+
content: string;
|
|
113
|
+
}>;
|
|
114
|
+
/** AI client for calling Claude. */
|
|
115
|
+
aiClient: ChatAIClient;
|
|
116
|
+
/** Available tool definitions. */
|
|
117
|
+
tools: ToolDefinition[];
|
|
118
|
+
/** Tool executor for running tool calls. */
|
|
119
|
+
toolExecutor: ToolExecutor;
|
|
120
|
+
/** Execution context for tool calls. */
|
|
121
|
+
toolContext: ToolExecutionContext;
|
|
122
|
+
/** Model for triage/synthesis. */
|
|
123
|
+
triageModel?: string;
|
|
124
|
+
/** Model for task execution. */
|
|
125
|
+
executeModel?: string;
|
|
126
|
+
/** Fallback model for escalation. */
|
|
127
|
+
fallbackModel?: string;
|
|
128
|
+
/** Called when a task starts. */
|
|
129
|
+
onTaskStart?: (task: DelegatedTask) => Promise<void>;
|
|
130
|
+
/** Called when a task completes. */
|
|
131
|
+
onTaskComplete?: (result: TaskExecutionResult) => Promise<void>;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Execute the full Sonnet → Haiku → Sonnet delegation flow.
|
|
135
|
+
*
|
|
136
|
+
* 1. Triage with Sonnet → routing decision
|
|
137
|
+
* 2. Execute tasks with Haiku (auto-escalate on failure)
|
|
138
|
+
* 3. Synthesize with Sonnet
|
|
139
|
+
*
|
|
140
|
+
* @param options - Delegation configuration.
|
|
141
|
+
* @returns The delegation result with synthesized response.
|
|
142
|
+
*/
|
|
143
|
+
export declare function delegateAndExecute(options: DelegateOptions): Promise<DelegationResult>;
|
|
144
|
+
//# sourceMappingURL=delegator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delegator.d.ts","sourceRoot":"","sources":["../../../../src/server/handlers/chat/delegator.ts"],"names":[],"mappings":"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"}
|