@xalia/agent 0.6.0 → 0.6.2
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/agent/src/agent/agent.js +103 -54
- package/dist/agent/src/agent/agentUtils.js +22 -21
- package/dist/agent/src/agent/compressingContextManager.js +3 -2
- package/dist/agent/src/agent/dummyLLM.js +1 -3
- package/dist/agent/src/agent/imageGenLLM.js +67 -0
- package/dist/agent/src/agent/imageGenerator.js +43 -0
- package/dist/agent/src/agent/llm.js +27 -0
- package/dist/agent/src/agent/mcpServerManager.js +18 -6
- package/dist/agent/src/agent/nullAgentEventHandler.js +6 -0
- package/dist/agent/src/agent/openAILLM.js +3 -3
- package/dist/agent/src/agent/openAILLMStreaming.js +41 -6
- package/dist/agent/src/chat/client/chatClient.js +84 -13
- package/dist/agent/src/chat/client/sessionClient.js +47 -6
- package/dist/agent/src/chat/client/sessionFiles.js +102 -0
- package/dist/agent/src/chat/data/apiKeyManager.js +38 -7
- package/dist/agent/src/chat/data/database.js +83 -70
- package/dist/agent/src/chat/data/dbSessionFileModels.js +49 -0
- package/dist/agent/src/chat/data/dbSessionFiles.js +76 -0
- package/dist/agent/src/chat/data/dbSessionMessages.js +57 -0
- package/dist/agent/src/chat/data/mimeTypes.js +44 -0
- package/dist/agent/src/chat/protocol/messages.js +21 -0
- package/dist/agent/src/chat/server/chatContextManager.js +14 -7
- package/dist/agent/src/chat/server/connectionManager.js +14 -36
- package/dist/agent/src/chat/server/connectionManager.test.js +2 -16
- package/dist/agent/src/chat/server/conversation.js +69 -45
- package/dist/agent/src/chat/server/imageGeneratorTools.js +111 -0
- package/dist/agent/src/chat/server/openSession.js +205 -43
- package/dist/agent/src/chat/server/server.js +5 -8
- package/dist/agent/src/chat/server/sessionFileManager.js +171 -38
- package/dist/agent/src/chat/server/sessionRegistry.js +199 -32
- package/dist/agent/src/chat/server/test-utils/mockFactories.js +12 -11
- package/dist/agent/src/chat/server/tools.js +27 -6
- package/dist/agent/src/chat/utils/multiAsyncQueue.js +9 -1
- package/dist/agent/src/test/agent.test.js +15 -11
- package/dist/agent/src/test/chatContextManager.test.js +4 -0
- package/dist/agent/src/test/clientServerConnection.test.js +2 -2
- package/dist/agent/src/test/db.test.js +33 -70
- package/dist/agent/src/test/dbSessionFiles.test.js +179 -0
- package/dist/agent/src/test/dbSessionMessages.test.js +67 -0
- package/dist/agent/src/test/dbTestTools.js +6 -5
- package/dist/agent/src/test/imageLoad.test.js +1 -1
- package/dist/agent/src/test/mcpServerManager.test.js +1 -1
- package/dist/agent/src/test/multiAsyncQueue.test.js +50 -0
- package/dist/agent/src/test/testTools.js +12 -0
- package/dist/agent/src/tool/agentChat.js +25 -6
- package/dist/agent/src/tool/agentMain.js +1 -1
- package/dist/agent/src/tool/chatMain.js +113 -4
- package/dist/agent/src/tool/commandPrompt.js +7 -3
- package/dist/agent/src/tool/files.js +23 -15
- package/dist/agent/src/tool/options.js +2 -2
- package/package.json +1 -1
- package/scripts/test_chat +124 -66
- package/src/agent/agent.ts +145 -38
- package/src/agent/agentUtils.ts +27 -21
- package/src/agent/compressingContextManager.ts +5 -4
- package/src/agent/context.ts +1 -1
- package/src/agent/dummyLLM.ts +1 -3
- package/src/agent/iAgentEventHandler.ts +15 -2
- package/src/agent/imageGenLLM.ts +99 -0
- package/src/agent/imageGenerator.ts +60 -0
- package/src/agent/llm.ts +128 -4
- package/src/agent/mcpServerManager.ts +26 -7
- package/src/agent/nullAgentEventHandler.ts +6 -0
- package/src/agent/openAILLM.ts +3 -8
- package/src/agent/openAILLMStreaming.ts +60 -14
- package/src/chat/client/chatClient.ts +119 -14
- package/src/chat/client/sessionClient.ts +75 -9
- package/src/chat/client/sessionFiles.ts +145 -0
- package/src/chat/data/apiKeyManager.ts +55 -7
- package/src/chat/data/dataModels.ts +16 -7
- package/src/chat/data/database.ts +107 -92
- package/src/chat/data/dbSessionFileModels.ts +91 -0
- package/src/chat/data/dbSessionFiles.ts +99 -0
- package/src/chat/data/dbSessionMessages.ts +68 -0
- package/src/chat/data/mimeTypes.ts +58 -0
- package/src/chat/protocol/messages.ts +127 -13
- package/src/chat/server/chatContextManager.ts +36 -13
- package/src/chat/server/connectionManager.test.ts +1 -22
- package/src/chat/server/connectionManager.ts +18 -53
- package/src/chat/server/conversation.ts +96 -57
- package/src/chat/server/imageGeneratorTools.ts +138 -0
- package/src/chat/server/openSession.ts +287 -49
- package/src/chat/server/server.ts +5 -11
- package/src/chat/server/sessionFileManager.ts +223 -63
- package/src/chat/server/sessionRegistry.ts +285 -41
- package/src/chat/server/test-utils/mockFactories.ts +13 -13
- package/src/chat/server/tools.ts +43 -8
- package/src/chat/utils/agentSessionMap.ts +2 -2
- package/src/chat/utils/multiAsyncQueue.ts +11 -1
- package/src/test/agent.test.ts +23 -14
- package/src/test/chatContextManager.test.ts +7 -2
- package/src/test/clientServerConnection.test.ts +3 -3
- package/src/test/compressingContextManager.test.ts +1 -1
- package/src/test/context.test.ts +2 -1
- package/src/test/conversation.test.ts +1 -1
- package/src/test/db.test.ts +41 -83
- package/src/test/dbSessionFiles.test.ts +258 -0
- package/src/test/dbSessionMessages.test.ts +85 -0
- package/src/test/dbTestTools.ts +9 -5
- package/src/test/imageLoad.test.ts +2 -2
- package/src/test/mcpServerManager.test.ts +3 -1
- package/src/test/multiAsyncQueue.test.ts +58 -0
- package/src/test/testTools.ts +15 -1
- package/src/tool/agentChat.ts +35 -7
- package/src/tool/agentMain.ts +7 -7
- package/src/tool/chatMain.ts +126 -5
- package/src/tool/commandPrompt.ts +10 -5
- package/src/tool/files.ts +30 -13
- package/src/tool/options.ts +1 -1
- package/test_data/dummyllm_script_image_gen.json +19 -0
- package/test_data/dummyllm_script_invoke_image_gen_tool.json +30 -0
- package/test_data/image_gen_test_profile.json +5 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import OpenAI from "openai";
|
|
1
2
|
import { strict as assert } from "assert";
|
|
2
3
|
import { Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
3
4
|
|
|
@@ -11,20 +12,16 @@ import {
|
|
|
11
12
|
SavedAgentProfile,
|
|
12
13
|
} from "@xalia/xmcp/sdk";
|
|
13
14
|
|
|
15
|
+
import { Agent, createUserMessage } from "../../agent/agent";
|
|
14
16
|
import {
|
|
15
|
-
Agent,
|
|
16
17
|
ChatCompletionAssistantMessageParam,
|
|
17
18
|
ChatCompletionMessageToolCall,
|
|
18
19
|
ChatCompletionToolMessageParam,
|
|
19
|
-
|
|
20
|
-
} from "../../agent/agent";
|
|
20
|
+
} from "../../agent/llm";
|
|
21
21
|
import { SkillManager } from "../../agent/sudoMcpServerManager";
|
|
22
22
|
import { McpServerInfo } from "../../agent/mcpServerManager";
|
|
23
23
|
import { IAgentEventHandler } from "../../agent/iAgentEventHandler";
|
|
24
|
-
import {
|
|
25
|
-
createAgentWithoutSkills,
|
|
26
|
-
DEFAULT_LLM_MODEL,
|
|
27
|
-
} from "../../agent/agentUtils";
|
|
24
|
+
import { createAgentWithoutSkills } from "../../agent/agentUtils";
|
|
28
25
|
import { IPlatform } from "../../agent/iplatform";
|
|
29
26
|
|
|
30
27
|
import type {
|
|
@@ -45,7 +42,12 @@ import type {
|
|
|
45
42
|
ServerSessionInfo,
|
|
46
43
|
ServerSessionUpdate,
|
|
47
44
|
ClientSetWorkspace,
|
|
45
|
+
ClientToServer,
|
|
46
|
+
ServerSessionFileContent,
|
|
48
47
|
ClientSetMcpServerConfig,
|
|
48
|
+
ClientShareSession,
|
|
49
|
+
ClientSessionMessageBase,
|
|
50
|
+
ServerAgentPaused,
|
|
49
51
|
} from "../protocol/messages";
|
|
50
52
|
import { AsyncQueue } from "../utils/asyncQueue";
|
|
51
53
|
import { MultiAsyncQueue } from "../utils/multiAsyncQueue";
|
|
@@ -57,6 +59,7 @@ import {
|
|
|
57
59
|
TeamParticipant,
|
|
58
60
|
SessionCreateData,
|
|
59
61
|
UserMessageData,
|
|
62
|
+
SessionDescriptor,
|
|
60
63
|
} from "../data/dataModels";
|
|
61
64
|
import {
|
|
62
65
|
Database,
|
|
@@ -71,17 +74,32 @@ import {
|
|
|
71
74
|
llmUserMessageToUserMessageData,
|
|
72
75
|
MESSAGE_INDEX_START_VALUE,
|
|
73
76
|
} from "./conversation";
|
|
74
|
-
import {
|
|
77
|
+
import {
|
|
78
|
+
ChatSessionFileManager,
|
|
79
|
+
ISessionFileManager,
|
|
80
|
+
ISessionFileManagerEventHandler,
|
|
81
|
+
} from "./sessionFileManager";
|
|
75
82
|
import { IUserConnectionManager } from "./connectionManager";
|
|
76
83
|
import { getErrorString } from "./errorUtils";
|
|
77
84
|
import { NODE_PLATFORM } from "../../tool/nodePlatform";
|
|
78
85
|
import { DbMcpServerConfigs } from "../data/dbMcpServerConfigs";
|
|
86
|
+
import { SessionFileEntry } from "../data/dbSessionFileModels";
|
|
87
|
+
import { ApiKeyManager } from "../data/apiKeyManager";
|
|
88
|
+
import { DbSessionMessages } from "../data/dbSessionMessages";
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* The model to use when the AgentProfile does not specify one.
|
|
92
|
+
*/
|
|
93
|
+
const DEFAULT_CHAT_LLM_MODEL =
|
|
94
|
+
process.env["DEFAULT_LLM_MODEL"] || "anthropic/claude-sonnet-4.5";
|
|
79
95
|
|
|
80
96
|
/**
|
|
81
97
|
* Num messages to load at conversation startup.
|
|
82
98
|
*/
|
|
83
99
|
export const DEFAULT_NUM_MESSGAES = 500;
|
|
84
100
|
|
|
101
|
+
export const GUEST_TOKEN_PREFIX = "guest";
|
|
102
|
+
|
|
85
103
|
const logger = getLogger();
|
|
86
104
|
|
|
87
105
|
type QueuedClientMessage<
|
|
@@ -119,7 +137,9 @@ class DBCheckpointWriter implements ICheckpointWriter {
|
|
|
119
137
|
* be seen until user messages had been fully processed, which could block
|
|
120
138
|
* tool approvals and other interactions).
|
|
121
139
|
*/
|
|
122
|
-
export class OpenSession
|
|
140
|
+
export class OpenSession
|
|
141
|
+
implements IAgentEventHandler, ISessionFileManagerEventHandler, IPlatform
|
|
142
|
+
{
|
|
123
143
|
private readonly db: Database;
|
|
124
144
|
private /* readonly */ agent: Agent;
|
|
125
145
|
private readonly sessionUUID: string;
|
|
@@ -135,9 +155,12 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
135
155
|
private readonly contextManager: ChatContextManager;
|
|
136
156
|
private readonly approvalManager: ApprovalManager;
|
|
137
157
|
private readonly savedAgentProfile: SavedAgentProfile;
|
|
158
|
+
private readonly sessionFileManager: ISessionFileManager;
|
|
138
159
|
private isPersisted: boolean;
|
|
160
|
+
private accessToken: string | undefined;
|
|
139
161
|
private sessionTitle: string;
|
|
140
162
|
private sessionUpdatedAt: string;
|
|
163
|
+
private agentPaused: boolean;
|
|
141
164
|
|
|
142
165
|
private constructor(
|
|
143
166
|
db: Database,
|
|
@@ -150,7 +173,8 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
150
173
|
skillManager: SkillManager,
|
|
151
174
|
contextManager: ChatContextManager,
|
|
152
175
|
connectionManager: IUserConnectionManager<ServerToClient>,
|
|
153
|
-
approvalManager: ApprovalManager
|
|
176
|
+
approvalManager: ApprovalManager,
|
|
177
|
+
fileManager: ISessionFileManager
|
|
154
178
|
) {
|
|
155
179
|
this.db = db;
|
|
156
180
|
this.agent = agent;
|
|
@@ -158,6 +182,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
158
182
|
this.teamUUID = sessionData.team_uuid;
|
|
159
183
|
this.userUUID = sessionData.user_uuid;
|
|
160
184
|
this.agentProfileUUID = sessionData.agent_profile_uuid;
|
|
185
|
+
this.accessToken = sessionData.access_token;
|
|
161
186
|
this.sessionParticipants = sessionParticipants;
|
|
162
187
|
this.agentProfilePreferences = agentProfilePreferences;
|
|
163
188
|
this.skillManager = skillManager;
|
|
@@ -172,13 +197,18 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
172
197
|
this.contextManager = contextManager;
|
|
173
198
|
this.approvalManager = approvalManager;
|
|
174
199
|
this.savedAgentProfile = savedAgentProfile;
|
|
200
|
+
this.sessionFileManager = fileManager;
|
|
175
201
|
this.isPersisted = isPersisted;
|
|
176
202
|
this.sessionTitle = sessionData.title;
|
|
177
203
|
this.sessionUpdatedAt = sessionData.updated_at;
|
|
204
|
+
this.agentPaused = sessionData.agent_paused;
|
|
205
|
+
|
|
206
|
+
fileManager.addEventHandler(this);
|
|
178
207
|
}
|
|
179
208
|
|
|
180
209
|
private static async init(
|
|
181
210
|
db: Database,
|
|
211
|
+
isPersisted: boolean,
|
|
182
212
|
sessionData: SessionData,
|
|
183
213
|
savedAgentProfile: SavedAgentProfile,
|
|
184
214
|
sessionMessages: SessionMessage[],
|
|
@@ -191,7 +221,8 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
191
221
|
connectionManager: IUserConnectionManager<ServerToClient>
|
|
192
222
|
): Promise<OpenSession> {
|
|
193
223
|
const sessionId = sessionData.session_uuid;
|
|
194
|
-
|
|
224
|
+
|
|
225
|
+
const fileManager = await ChatSessionFileManager.init(db, sessionId);
|
|
195
226
|
const contextManager = new ChatContextManager(
|
|
196
227
|
savedAgentProfile.profile.system_prompt,
|
|
197
228
|
sessionMessages,
|
|
@@ -199,7 +230,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
199
230
|
ownerData.uuid,
|
|
200
231
|
sessionCheckpoint,
|
|
201
232
|
llmUrl,
|
|
202
|
-
savedAgentProfile.profile.model ||
|
|
233
|
+
savedAgentProfile.profile.model || DEFAULT_CHAT_LLM_MODEL,
|
|
203
234
|
ownerApiKey,
|
|
204
235
|
new DBCheckpointWriter(db, sessionId),
|
|
205
236
|
fileManager
|
|
@@ -214,12 +245,14 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
214
245
|
{} as Agent, // Placeholder - will be replaced after agent creation
|
|
215
246
|
sessionData,
|
|
216
247
|
savedAgentProfile,
|
|
217
|
-
|
|
248
|
+
isPersisted,
|
|
218
249
|
sessionParticipants,
|
|
219
250
|
savedAgentProfile.preferences,
|
|
220
251
|
{} as SkillManager, // Placeholder - will be replaced after agent creation
|
|
221
252
|
contextManager,
|
|
222
|
-
connectionManager
|
|
253
|
+
connectionManager,
|
|
254
|
+
new ApprovalManager(),
|
|
255
|
+
fileManager
|
|
223
256
|
);
|
|
224
257
|
|
|
225
258
|
// Initialize an empty agent (to ensure there are no callbacks before
|
|
@@ -229,6 +262,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
229
262
|
const [agent, skillManager] = await createAgentWithoutSkills(
|
|
230
263
|
llmUrl,
|
|
231
264
|
savedAgentProfile.profile,
|
|
265
|
+
DEFAULT_CHAT_LLM_MODEL,
|
|
232
266
|
openSession,
|
|
233
267
|
openSession,
|
|
234
268
|
contextManager,
|
|
@@ -237,7 +271,14 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
237
271
|
undefined,
|
|
238
272
|
true
|
|
239
273
|
);
|
|
240
|
-
await addDefaultChatTools(
|
|
274
|
+
await addDefaultChatTools(
|
|
275
|
+
agent,
|
|
276
|
+
ownerData.timezone,
|
|
277
|
+
openSession,
|
|
278
|
+
fileManager,
|
|
279
|
+
llmUrl,
|
|
280
|
+
ownerApiKey
|
|
281
|
+
);
|
|
241
282
|
|
|
242
283
|
// Update OpenSession with real agent and skillManager
|
|
243
284
|
openSession.agent = agent;
|
|
@@ -279,6 +320,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
279
320
|
|
|
280
321
|
return OpenSession.init(
|
|
281
322
|
db,
|
|
323
|
+
false /* isPersisted */,
|
|
282
324
|
sessionData,
|
|
283
325
|
savedAgentProfile,
|
|
284
326
|
sessionMessages,
|
|
@@ -311,6 +353,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
311
353
|
} = await loadSessionData(db, sessionId);
|
|
312
354
|
return OpenSession.init(
|
|
313
355
|
db,
|
|
356
|
+
true /* isPersisted */,
|
|
314
357
|
sessionData,
|
|
315
358
|
savedAgentProfile,
|
|
316
359
|
sessionMessages,
|
|
@@ -328,6 +371,23 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
328
371
|
logger.info(`[OpenSession.onEmpty] session ${this.sessionUUID}`);
|
|
329
372
|
}
|
|
330
373
|
|
|
374
|
+
getDescriptor(): SessionDescriptor {
|
|
375
|
+
assert(
|
|
376
|
+
typeof this.accessToken === "string" ||
|
|
377
|
+
typeof this.accessToken === "undefined"
|
|
378
|
+
);
|
|
379
|
+
return {
|
|
380
|
+
session_uuid: this.sessionUUID,
|
|
381
|
+
title: this.sessionTitle,
|
|
382
|
+
agent_profile_uuid: this.agentProfileUUID,
|
|
383
|
+
user_uuid: this.userUUID,
|
|
384
|
+
team_uuid: this.teamUUID,
|
|
385
|
+
access_token: this.accessToken,
|
|
386
|
+
updated_at: this.sessionUpdatedAt,
|
|
387
|
+
agent_paused: this.agentPaused,
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
|
|
331
391
|
getParticipants(): SessionParticipantMap {
|
|
332
392
|
return this.sessionParticipants;
|
|
333
393
|
}
|
|
@@ -340,6 +400,17 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
340
400
|
const sessionInfo = this.serverSessionInfo(clientMessageId);
|
|
341
401
|
this.connectionManager.sendToConnection(connectionId, sessionInfo);
|
|
342
402
|
|
|
403
|
+
// send session file info
|
|
404
|
+
const fileDescriptors = this.sessionFileManager.listFiles();
|
|
405
|
+
fileDescriptors.forEach((descriptor) => {
|
|
406
|
+
this.connectionManager.sendToConnection(connectionId, {
|
|
407
|
+
type: "session_file_changed",
|
|
408
|
+
session_id: this.sessionUUID,
|
|
409
|
+
descriptor,
|
|
410
|
+
new_file: false,
|
|
411
|
+
});
|
|
412
|
+
});
|
|
413
|
+
|
|
343
414
|
// send conversation history
|
|
344
415
|
const conversationMessages = this.contextManager.getConversationMessages();
|
|
345
416
|
conversationMessages.forEach((message) => {
|
|
@@ -522,6 +593,12 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
522
593
|
this.contextManager.processAgentResponse(result);
|
|
523
594
|
}
|
|
524
595
|
|
|
596
|
+
// IAgentEventHandler.onImage
|
|
597
|
+
onImage(image: OpenAI.Chat.Completions.ChatCompletionContentPartImage): void {
|
|
598
|
+
logger.debug(`[OpenSession.onImage] : ${image.image_url.url}`);
|
|
599
|
+
throw new Error("[OpenSession.onImage] unimplemented");
|
|
600
|
+
}
|
|
601
|
+
|
|
525
602
|
// IAgentEventHandler.onToolCallResult
|
|
526
603
|
onToolCallResult(result: ChatCompletionToolMessageParam): void {
|
|
527
604
|
logger.debug(`[onToolCallResult] : ${JSON.stringify(result)}`);
|
|
@@ -614,6 +691,44 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
614
691
|
this.broadcast(agentMsgChunk);
|
|
615
692
|
}
|
|
616
693
|
|
|
694
|
+
// IAgentEventHandler.onReasoning
|
|
695
|
+
onReasoning(reasoning: string): Promise<void> {
|
|
696
|
+
return new Promise<void>((r) => {
|
|
697
|
+
logger.debug(`[OpenSession.onReasoning]${reasoning}`);
|
|
698
|
+
if (reasoning.length > 0) {
|
|
699
|
+
this.broadcast({
|
|
700
|
+
type: "agent_reasoning_chunk",
|
|
701
|
+
reasoning,
|
|
702
|
+
session_id: this.sessionUUID,
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
r();
|
|
706
|
+
});
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
// ISessionFileManagerEventHandler.onFileDeleted
|
|
710
|
+
onFileDeleted(name: string): void {
|
|
711
|
+
this.broadcast({
|
|
712
|
+
type: "session_file_deleted",
|
|
713
|
+
session_id: this.sessionUUID,
|
|
714
|
+
name,
|
|
715
|
+
});
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// ISessionFileManagerEventHandler.onFileChanged
|
|
719
|
+
onFileChanged(entry: SessionFileEntry, new_file: boolean): void {
|
|
720
|
+
this.broadcast({
|
|
721
|
+
type: "session_file_changed",
|
|
722
|
+
session_id: this.sessionUUID,
|
|
723
|
+
descriptor: {
|
|
724
|
+
name: entry.name,
|
|
725
|
+
mime_type: entry.mime_type,
|
|
726
|
+
summary: entry.summary,
|
|
727
|
+
},
|
|
728
|
+
new_file,
|
|
729
|
+
});
|
|
730
|
+
}
|
|
731
|
+
|
|
617
732
|
/**
|
|
618
733
|
* Handle incoming session-related message from client.
|
|
619
734
|
* These messages include tool calls, MCP changes, etc.
|
|
@@ -693,34 +808,38 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
693
808
|
undefined;
|
|
694
809
|
switch (msg.type) {
|
|
695
810
|
case "msg":
|
|
696
|
-
broadcastMsg = this.
|
|
811
|
+
broadcastMsg = this.handleUserMessage(msg, queuedMessage.from);
|
|
697
812
|
break;
|
|
698
813
|
case "add_mcp_server":
|
|
699
|
-
broadcastMsg = await this.
|
|
814
|
+
broadcastMsg = await this.handleAddMcpServer(
|
|
700
815
|
msg.server_name,
|
|
701
816
|
msg.enable_all
|
|
702
817
|
);
|
|
703
818
|
break;
|
|
704
819
|
case "remove_mcp_server":
|
|
705
|
-
broadcastMsg = await this.
|
|
820
|
+
broadcastMsg = await this.handleRemoveMcpServer(msg.server_name);
|
|
706
821
|
break;
|
|
707
822
|
case "enable_mcp_server_tool":
|
|
708
|
-
broadcastMsg = await this.
|
|
823
|
+
broadcastMsg = await this.handleEnableMcpServerTool(
|
|
709
824
|
msg.server_name,
|
|
710
825
|
msg.tool
|
|
711
826
|
);
|
|
712
827
|
break;
|
|
713
828
|
case "disable_mcp_server_tool":
|
|
714
|
-
broadcastMsg = await this.
|
|
829
|
+
broadcastMsg = await this.handleDisableMcpServerTool(
|
|
715
830
|
msg.server_name,
|
|
716
831
|
msg.tool
|
|
717
832
|
);
|
|
718
833
|
break;
|
|
719
834
|
case "enable_all_mcp_server_tools":
|
|
720
|
-
broadcastMsg = await this.
|
|
835
|
+
broadcastMsg = await this.handleEnableAllMcpServerTools(
|
|
836
|
+
msg.server_name
|
|
837
|
+
);
|
|
721
838
|
break;
|
|
722
839
|
case "disable_all_mcp_server_tools":
|
|
723
|
-
broadcastMsg = await this.
|
|
840
|
+
broadcastMsg = await this.handleDisableAllMcpServerTools(
|
|
841
|
+
msg.server_name
|
|
842
|
+
);
|
|
724
843
|
break;
|
|
725
844
|
case "tool_call_approval_result":
|
|
726
845
|
if (
|
|
@@ -738,6 +857,15 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
738
857
|
};
|
|
739
858
|
}
|
|
740
859
|
break;
|
|
860
|
+
case "session_file_get_content":
|
|
861
|
+
void this.handleSessionFileGetContent(msg, queuedMessage.from);
|
|
862
|
+
break;
|
|
863
|
+
case "session_file_delete":
|
|
864
|
+
await this.handleSessionFileDelete(msg);
|
|
865
|
+
break;
|
|
866
|
+
case "session_file_put_content":
|
|
867
|
+
await this.handleSessionFilePutContent(msg);
|
|
868
|
+
break;
|
|
741
869
|
case "set_auto_approval":
|
|
742
870
|
broadcastMsg = await this.onSetAutoApproval(
|
|
743
871
|
msg.server_name,
|
|
@@ -746,17 +874,23 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
746
874
|
);
|
|
747
875
|
break;
|
|
748
876
|
case "set_system_prompt":
|
|
749
|
-
broadcastMsg = await this.
|
|
877
|
+
broadcastMsg = await this.handleSetSystemPrompt(msg.system_prompt);
|
|
750
878
|
break;
|
|
751
879
|
case "set_model":
|
|
752
|
-
broadcastMsg = await this.
|
|
880
|
+
broadcastMsg = await this.handleSetModel(msg.model);
|
|
881
|
+
break;
|
|
882
|
+
case "set_agent_paused":
|
|
883
|
+
broadcastMsg = await this.handleSetAgentPaused(msg.paused);
|
|
753
884
|
break;
|
|
754
885
|
case "set_workspace":
|
|
755
|
-
await this.
|
|
886
|
+
await this.handleSetWorkspace(msg, queuedMessage.from);
|
|
756
887
|
break;
|
|
757
888
|
case "set_mcp_server_config":
|
|
758
889
|
await this.handleSetMcpServerConfig(msg, queuedMessage.from);
|
|
759
890
|
break;
|
|
891
|
+
case "share_session":
|
|
892
|
+
await this.handleShareSession(msg, queuedMessage.from);
|
|
893
|
+
break;
|
|
760
894
|
default: {
|
|
761
895
|
const exhaustive: never = msg; // Error => non-exhaustive switch-case.
|
|
762
896
|
return exhaustive;
|
|
@@ -779,7 +913,28 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
779
913
|
}
|
|
780
914
|
}
|
|
781
915
|
|
|
782
|
-
private async
|
|
916
|
+
private async handleShareSession(
|
|
917
|
+
msg: ClientShareSession & ClientSessionMessageBase,
|
|
918
|
+
from: string
|
|
919
|
+
) {
|
|
920
|
+
if (!this.accessToken) {
|
|
921
|
+
const accessToken = ApiKeyManager.createApiKeyWithPayload(
|
|
922
|
+
GUEST_TOKEN_PREFIX,
|
|
923
|
+
this.sessionUUID
|
|
924
|
+
);
|
|
925
|
+
await this.db.sessionUpdateAccessToken(this.sessionUUID, accessToken);
|
|
926
|
+
this.accessToken = accessToken;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
this.sendTo(from, {
|
|
930
|
+
type: "session_shared",
|
|
931
|
+
access_token: this.accessToken,
|
|
932
|
+
client_message_id: msg.client_message_id,
|
|
933
|
+
session_id: this.sessionUUID,
|
|
934
|
+
});
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
private async handleSetWorkspace(
|
|
783
938
|
msg: ClientSetWorkspace,
|
|
784
939
|
sender: string
|
|
785
940
|
): Promise<void> {
|
|
@@ -799,18 +954,32 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
799
954
|
assert(this.isPersisted);
|
|
800
955
|
}
|
|
801
956
|
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
957
|
+
/**
|
|
958
|
+
* `processUserMessage` logic when agent is paused. Trigger the context,
|
|
959
|
+
* add the user messages and then extract the new DB messages.
|
|
960
|
+
*/
|
|
961
|
+
private processUserMessagePaused(
|
|
962
|
+
msgs: ServerUserMessage[]
|
|
963
|
+
): SessionMessage[] {
|
|
964
|
+
const { llmUserMessages } = this.contextManager.startAgentResponse(msgs);
|
|
965
|
+
|
|
966
|
+
// Just send the user LLM messages direct to the ContextManager, so they
|
|
967
|
+
// are available to the LLM once it is restarted.
|
|
807
968
|
|
|
808
|
-
|
|
969
|
+
this.contextManager.addMessages(llmUserMessages);
|
|
970
|
+
return this.contextManager.endAgentResponse();
|
|
971
|
+
}
|
|
809
972
|
|
|
973
|
+
/**
|
|
974
|
+
* `processUserMessage` logic when agent is active. Start the Agent loop,
|
|
975
|
+
* adding all agent messages to the context. Extract the new DB messages.
|
|
976
|
+
*/
|
|
977
|
+
private async processUserMessagesActive(
|
|
978
|
+
msgs: ServerUserMessage[]
|
|
979
|
+
): Promise<SessionMessage[]> {
|
|
810
980
|
const { llmUserMessages, agentFirstChunk } =
|
|
811
981
|
this.contextManager.startAgentResponse(msgs);
|
|
812
982
|
this.broadcast(agentFirstChunk);
|
|
813
|
-
|
|
814
983
|
try {
|
|
815
984
|
await this.agent.userMessagesRaw(llmUserMessages);
|
|
816
985
|
} catch (e) {
|
|
@@ -824,10 +993,16 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
824
993
|
await this.onAgentMessage(errMsg, true);
|
|
825
994
|
const err = this.contextManager.revertAgentResponse(errMsg);
|
|
826
995
|
this.broadcast(err);
|
|
827
|
-
|
|
996
|
+
|
|
997
|
+
// return await this.processuserMessagesActive(msgs);
|
|
828
998
|
}
|
|
999
|
+
return this.contextManager.endAgentResponse();
|
|
1000
|
+
}
|
|
829
1001
|
|
|
830
|
-
|
|
1002
|
+
private async processUserMessages(msgs: ServerUserMessage[]): Promise<void> {
|
|
1003
|
+
const newSessionMessages = this.agentPaused
|
|
1004
|
+
? this.processUserMessagePaused(msgs)
|
|
1005
|
+
: await this.processUserMessagesActive(msgs);
|
|
831
1006
|
|
|
832
1007
|
logger.debug(
|
|
833
1008
|
"[processUserMessages] newSessionMessages: " +
|
|
@@ -836,7 +1011,8 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
836
1011
|
|
|
837
1012
|
try {
|
|
838
1013
|
// Append to in-memory conversation and write to the DB
|
|
839
|
-
|
|
1014
|
+
const dbsm = this.db.createTypedClient(DbSessionMessages);
|
|
1015
|
+
await dbsm.append(this.sessionUUID, newSessionMessages);
|
|
840
1016
|
} catch (e) {
|
|
841
1017
|
if (!this.handleError(e)) {
|
|
842
1018
|
throw e;
|
|
@@ -844,7 +1020,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
844
1020
|
}
|
|
845
1021
|
}
|
|
846
1022
|
|
|
847
|
-
private
|
|
1023
|
+
private handleUserMessage(
|
|
848
1024
|
msg: ClientUserMessage,
|
|
849
1025
|
from: string
|
|
850
1026
|
): ServerUserMessage | undefined {
|
|
@@ -858,7 +1034,9 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
858
1034
|
// Assign the user message_idx and attempt to enqueue.
|
|
859
1035
|
|
|
860
1036
|
const userMessage = this.contextManager.processUserMessage(msg, from);
|
|
861
|
-
|
|
1037
|
+
if (!userMessage) {
|
|
1038
|
+
return;
|
|
1039
|
+
}
|
|
862
1040
|
// Special case for the first message of the session
|
|
863
1041
|
|
|
864
1042
|
if (userMessage.message_idx === MESSAGE_INDEX_START_VALUE) {
|
|
@@ -893,14 +1071,20 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
893
1071
|
title: this.sessionTitle,
|
|
894
1072
|
team_uuid: this.teamUUID,
|
|
895
1073
|
agent_profile_uuid: this.agentProfileUUID,
|
|
896
|
-
workspace: this.workspaceUserMessageData(),
|
|
897
1074
|
user_uuid: this.userUUID,
|
|
1075
|
+
agent_paused: false,
|
|
898
1076
|
};
|
|
899
1077
|
logger.info(
|
|
900
1078
|
`[OpenSession.onFirstMessage] writing session ${this.sessionUUID}`
|
|
901
1079
|
);
|
|
902
1080
|
|
|
903
1081
|
await this.db.sessionCreate(sessionCreateData);
|
|
1082
|
+
|
|
1083
|
+
const workspace = this.workspaceUserMessageData();
|
|
1084
|
+
if (workspace) {
|
|
1085
|
+
await this.db.sessionUpdateWorkspace(this.sessionUUID, workspace);
|
|
1086
|
+
}
|
|
1087
|
+
|
|
904
1088
|
this.isPersisted = true;
|
|
905
1089
|
}
|
|
906
1090
|
|
|
@@ -929,7 +1113,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
929
1113
|
this.broadcast(msg);
|
|
930
1114
|
}
|
|
931
1115
|
|
|
932
|
-
private async
|
|
1116
|
+
private async handleAddMcpServer(
|
|
933
1117
|
serverName: string,
|
|
934
1118
|
enableAll: boolean
|
|
935
1119
|
): Promise<ServerMcpServerAdded> {
|
|
@@ -967,7 +1151,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
967
1151
|
};
|
|
968
1152
|
}
|
|
969
1153
|
|
|
970
|
-
private async
|
|
1154
|
+
private async handleRemoveMcpServer(
|
|
971
1155
|
server_name: string
|
|
972
1156
|
): Promise<ServerMcpServerRemoved> {
|
|
973
1157
|
logger.info(`[onRemoveMcpServer]: Removing server ${server_name}`);
|
|
@@ -986,7 +1170,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
986
1170
|
};
|
|
987
1171
|
}
|
|
988
1172
|
|
|
989
|
-
private async
|
|
1173
|
+
private async handleEnableMcpServerTool(
|
|
990
1174
|
server_name: string,
|
|
991
1175
|
tool: string
|
|
992
1176
|
): Promise<ServerMcpServerToolEnabled> {
|
|
@@ -1003,7 +1187,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
1003
1187
|
};
|
|
1004
1188
|
}
|
|
1005
1189
|
|
|
1006
|
-
private async
|
|
1190
|
+
private async handleDisableMcpServerTool(
|
|
1007
1191
|
server_name: string,
|
|
1008
1192
|
tool: string
|
|
1009
1193
|
): Promise<ServerMcpServerToolDisabled> {
|
|
@@ -1020,7 +1204,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
1020
1204
|
};
|
|
1021
1205
|
}
|
|
1022
1206
|
|
|
1023
|
-
private async
|
|
1207
|
+
private async handleEnableAllMcpServerTools(
|
|
1024
1208
|
server_name: string
|
|
1025
1209
|
): Promise<ServerMcpServerToolEnabled[]> {
|
|
1026
1210
|
// We reimplement the logic to enable any disabled tools so we can
|
|
@@ -1046,7 +1230,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
1046
1230
|
return msgs;
|
|
1047
1231
|
}
|
|
1048
1232
|
|
|
1049
|
-
private async
|
|
1233
|
+
private async handleDisableAllMcpServerTools(
|
|
1050
1234
|
server_name: string
|
|
1051
1235
|
): Promise<ServerMcpServerToolDisabled[]> {
|
|
1052
1236
|
// We reimplement the logic to disable all enabled tools so we can
|
|
@@ -1070,7 +1254,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
1070
1254
|
return msgs;
|
|
1071
1255
|
}
|
|
1072
1256
|
|
|
1073
|
-
private async
|
|
1257
|
+
private async handleSetSystemPrompt(
|
|
1074
1258
|
system_prompt: string
|
|
1075
1259
|
): Promise<ServerSystemPromptUpdated> {
|
|
1076
1260
|
this.agent.setSystemPrompt(system_prompt);
|
|
@@ -1082,12 +1266,20 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
1082
1266
|
};
|
|
1083
1267
|
}
|
|
1084
1268
|
|
|
1085
|
-
private async
|
|
1269
|
+
private async handleSetModel(model: string): Promise<ServerModelUpdated> {
|
|
1086
1270
|
this.agent.setModel(model);
|
|
1087
1271
|
await this.updateAgentProfile();
|
|
1088
1272
|
return { type: "model_updated", model, session_id: this.sessionUUID };
|
|
1089
1273
|
}
|
|
1090
1274
|
|
|
1275
|
+
private async handleSetAgentPaused(
|
|
1276
|
+
paused: boolean
|
|
1277
|
+
): Promise<ServerAgentPaused> {
|
|
1278
|
+
this.agentPaused = paused;
|
|
1279
|
+
await this.db.sessionSetAgentPaused(this.sessionUUID, paused);
|
|
1280
|
+
return { type: "agent_paused", session_id: this.sessionUUID, paused };
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1091
1283
|
private async handleSetMcpServerConfig(
|
|
1092
1284
|
msg: ClientSetMcpServerConfig,
|
|
1093
1285
|
from: string
|
|
@@ -1120,6 +1312,50 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
1120
1312
|
// TODO: Do we want to braodcast an "mcp_server_config_updated" message?
|
|
1121
1313
|
}
|
|
1122
1314
|
|
|
1315
|
+
private async handleSessionFileGetContent(
|
|
1316
|
+
msg: Extract<ClientToServer, { type: "session_file_get_content" }>,
|
|
1317
|
+
from: string
|
|
1318
|
+
): Promise<void> {
|
|
1319
|
+
const data_url = await this.sessionFileManager.getFileContent(msg.name);
|
|
1320
|
+
const contentMsg: ServerSessionFileContent = {
|
|
1321
|
+
type: "session_file_content",
|
|
1322
|
+
session_id: this.sessionUUID,
|
|
1323
|
+
client_message_id: msg.client_message_id,
|
|
1324
|
+
name: msg.name,
|
|
1325
|
+
data_url,
|
|
1326
|
+
};
|
|
1327
|
+
this.sendTo(from, contentMsg);
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
private async handleSessionFileDelete(
|
|
1331
|
+
msg: Extract<ClientToServer, { type: "session_file_delete" }>
|
|
1332
|
+
): Promise<void> {
|
|
1333
|
+
await this.sessionFileManager.deleteFile(msg.name);
|
|
1334
|
+
// Note, the SessionFileManager will call us back via
|
|
1335
|
+
// `ISessionFileManagerEventHandler.onFileDeleted` if the deletion
|
|
1336
|
+
// succeeds. We broadcast in that callback.
|
|
1337
|
+
}
|
|
1338
|
+
|
|
1339
|
+
private async handleSessionFilePutContent(
|
|
1340
|
+
msg: Extract<ClientToServer, { type: "session_file_put_content" }>
|
|
1341
|
+
): Promise<void> {
|
|
1342
|
+
// If the session hasn't been persisted, it must be written to the DB,
|
|
1343
|
+
// (otherwise the sessionId in the SessionFiles entry will not be
|
|
1344
|
+
// considered valid byt he DB).
|
|
1345
|
+
|
|
1346
|
+
if (!this.isPersisted) {
|
|
1347
|
+
await this.createSessionInDB();
|
|
1348
|
+
}
|
|
1349
|
+
await this.sessionFileManager.putFileContent(
|
|
1350
|
+
msg.name,
|
|
1351
|
+
msg.summary,
|
|
1352
|
+
msg.data_url
|
|
1353
|
+
);
|
|
1354
|
+
// Note, the SessionFileManager will call us back via
|
|
1355
|
+
// `ISessionFileManagerEventHandler.onFileChanged` if the deletion
|
|
1356
|
+
// succeeds. We broadcast in that callback.
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1123
1359
|
private async onSetAutoApproval(
|
|
1124
1360
|
serverName: string,
|
|
1125
1361
|
tool: string,
|
|
@@ -1239,6 +1475,7 @@ export class OpenSession implements IAgentEventHandler, IPlatform {
|
|
|
1239
1475
|
client_message_id: clientMessageId,
|
|
1240
1476
|
session_id: this.sessionUUID,
|
|
1241
1477
|
team_uuid: this.teamUUID,
|
|
1478
|
+
agent_paused: this.agentPaused,
|
|
1242
1479
|
};
|
|
1243
1480
|
}
|
|
1244
1481
|
|
|
@@ -1302,10 +1539,11 @@ async function loadSessionData(
|
|
|
1302
1539
|
ownerApiKey: string;
|
|
1303
1540
|
sessionParticipants: SessionParticipantMap;
|
|
1304
1541
|
}> {
|
|
1542
|
+
const dbsm = db.createTypedClient(DbSessionMessages);
|
|
1305
1543
|
const [sessionData, sessionMessages, sessionParticipants, sessionCheckpoint] =
|
|
1306
1544
|
await Promise.all([
|
|
1307
|
-
db.
|
|
1308
|
-
|
|
1545
|
+
db.sessionGetDescriptorById(sessionId),
|
|
1546
|
+
dbsm.getConversation(sessionId, DEFAULT_NUM_MESSGAES, 0),
|
|
1309
1547
|
db.sessionGetParticipants(sessionId),
|
|
1310
1548
|
db.sessionCheckpointGet(sessionId),
|
|
1311
1549
|
]);
|