@xalia/agent 0.5.7 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -8
- package/dist/agent/src/agent/agent.js +176 -96
- package/dist/agent/src/agent/agentUtils.js +82 -59
- package/dist/agent/src/agent/compressingContextManager.js +102 -0
- package/dist/agent/src/agent/context.js +189 -0
- package/dist/agent/src/agent/dummyLLM.js +46 -5
- package/dist/agent/src/agent/mcpServerManager.js +23 -24
- package/dist/agent/src/agent/nullAgentEventHandler.js +21 -0
- package/dist/agent/src/agent/nullPlatform.js +14 -0
- package/dist/agent/src/agent/openAILLMStreaming.js +26 -14
- package/dist/agent/src/agent/promptProvider.js +63 -0
- package/dist/agent/src/agent/repeatLLM.js +5 -5
- package/dist/agent/src/agent/sudoMcpServerManager.js +23 -21
- package/dist/agent/src/agent/tokenAuth.js +7 -7
- package/dist/agent/src/agent/tools.js +1 -1
- package/dist/agent/src/chat/client/chatClient.js +733 -0
- package/dist/agent/src/chat/client/connection.js +209 -0
- package/dist/agent/src/chat/client/connection.test.js +188 -0
- package/dist/agent/src/chat/client/constants.js +5 -0
- package/dist/agent/src/chat/client/index.js +15 -0
- package/dist/agent/src/chat/client/interfaces.js +2 -0
- package/dist/agent/src/chat/client/responseHandler.js +105 -0
- package/dist/agent/src/chat/client/sessionClient.js +331 -0
- package/dist/agent/src/chat/client/teamManager.js +2 -0
- package/dist/agent/src/chat/{apiKeyManager.js → data/apiKeyManager.js} +4 -0
- package/dist/agent/src/chat/data/dataModels.js +2 -0
- package/dist/agent/src/chat/data/database.js +749 -0
- package/dist/agent/src/chat/data/dbMcpServerConfigs.js +47 -0
- package/dist/agent/src/chat/protocol/connectionMessages.js +5 -0
- package/dist/agent/src/chat/protocol/constants.js +50 -0
- package/dist/agent/src/chat/protocol/errors.js +22 -0
- package/dist/agent/src/chat/protocol/messages.js +110 -0
- package/dist/agent/src/chat/server/chatContextManager.js +405 -0
- package/dist/agent/src/chat/server/connectionManager.js +352 -0
- package/dist/agent/src/chat/server/connectionManager.test.js +159 -0
- package/dist/agent/src/chat/server/conversation.js +198 -0
- package/dist/agent/src/chat/server/errorUtils.js +23 -0
- package/dist/agent/src/chat/server/openSession.js +869 -0
- package/dist/agent/src/chat/server/server.js +177 -0
- package/dist/agent/src/chat/server/sessionFileManager.js +161 -0
- package/dist/agent/src/chat/server/sessionRegistry.js +700 -0
- package/dist/agent/src/chat/server/sessionRegistry.test.js +97 -0
- package/dist/agent/src/chat/server/test-utils/mockFactories.js +307 -0
- package/dist/agent/src/chat/server/tools.js +243 -0
- package/dist/agent/src/chat/utils/agentSessionMap.js +66 -0
- package/dist/agent/src/chat/utils/approvalManager.js +85 -0
- package/dist/agent/src/{utils → chat/utils}/asyncLock.js +3 -3
- package/dist/agent/src/chat/{asyncQueue.js → utils/asyncQueue.js} +12 -2
- package/dist/agent/src/chat/utils/htmlToText.js +84 -0
- package/dist/agent/src/chat/utils/multiAsyncQueue.js +42 -0
- package/dist/agent/src/chat/utils/search.js +145 -0
- package/dist/agent/src/chat/utils/userResolver.js +46 -0
- package/dist/agent/src/chat/utils/websocket.js +16 -0
- package/dist/agent/src/test/agent.test.js +332 -0
- package/dist/agent/src/test/approvalManager.test.js +58 -0
- package/dist/agent/src/test/chatContextManager.test.js +392 -0
- package/dist/agent/src/test/clientServerConnection.test.js +158 -0
- package/dist/agent/src/test/compressingContextManager.test.js +65 -0
- package/dist/agent/src/test/context.test.js +83 -0
- package/dist/agent/src/test/conversation.test.js +89 -0
- package/dist/agent/src/test/db.test.js +271 -83
- package/dist/agent/src/test/dbMcpServerConfigs.test.js +72 -0
- package/dist/agent/src/test/dbTestTools.js +99 -0
- package/dist/agent/src/test/imageLoad.test.js +8 -7
- package/dist/agent/src/test/mcpServerManager.test.js +23 -20
- package/dist/agent/src/test/multiAsyncQueue.test.js +101 -0
- package/dist/agent/src/test/openaiStreaming.test.js +64 -35
- package/dist/agent/src/test/prompt.test.js +5 -4
- package/dist/agent/src/test/promptProvider.test.js +28 -0
- package/dist/agent/src/test/responseHandler.test.js +61 -0
- package/dist/agent/src/test/sudoMcpServerManager.test.js +24 -25
- package/dist/agent/src/test/testTools.js +109 -0
- package/dist/agent/src/test/tools.test.js +31 -0
- package/dist/agent/src/tool/agentChat.js +21 -10
- package/dist/agent/src/tool/agentMain.js +1 -1
- package/dist/agent/src/tool/chatMain.js +241 -58
- package/dist/agent/src/tool/commandPrompt.js +22 -17
- package/dist/agent/src/tool/files.js +20 -16
- package/dist/agent/src/tool/nodePlatform.js +47 -3
- package/dist/agent/src/tool/options.js +4 -4
- package/dist/agent/src/tool/prompt.js +19 -13
- package/eslint.config.mjs +14 -1
- package/package.json +14 -6
- package/scripts/chat_server +8 -0
- package/scripts/setup_chat +7 -2
- package/scripts/shutdown_chat_server +3 -0
- package/scripts/test_chat +135 -17
- package/src/agent/agent.ts +283 -138
- package/src/agent/agentUtils.ts +143 -108
- package/src/agent/compressingContextManager.ts +164 -0
- package/src/agent/context.ts +268 -0
- package/src/agent/dummyLLM.ts +76 -8
- package/src/agent/iAgentEventHandler.ts +54 -0
- package/src/agent/iplatform.ts +1 -0
- package/src/agent/mcpServerManager.ts +35 -31
- package/src/agent/nullAgentEventHandler.ts +20 -0
- package/src/agent/nullPlatform.ts +13 -0
- package/src/agent/openAILLMStreaming.ts +26 -13
- package/src/agent/promptProvider.ts +87 -0
- package/src/agent/repeatLLM.ts +5 -5
- package/src/agent/sudoMcpServerManager.ts +30 -29
- package/src/agent/tokenAuth.ts +7 -7
- package/src/agent/tools.ts +3 -1
- package/src/chat/client/chatClient.ts +900 -0
- package/src/chat/client/connection.test.ts +241 -0
- package/src/chat/client/connection.ts +276 -0
- package/src/chat/client/constants.ts +3 -0
- package/src/chat/client/index.ts +18 -0
- package/src/chat/client/interfaces.ts +34 -0
- package/src/chat/client/responseHandler.ts +131 -0
- package/src/chat/client/sessionClient.ts +443 -0
- package/src/chat/client/teamManager.ts +29 -0
- package/src/chat/{apiKeyManager.ts → data/apiKeyManager.ts} +6 -2
- package/src/chat/data/dataModels.ts +85 -0
- package/src/chat/data/database.ts +982 -0
- package/src/chat/data/dbMcpServerConfigs.ts +59 -0
- package/src/chat/protocol/connectionMessages.ts +49 -0
- package/src/chat/protocol/constants.ts +55 -0
- package/src/chat/protocol/errors.ts +16 -0
- package/src/chat/protocol/messages.ts +682 -0
- package/src/chat/server/README.md +127 -0
- package/src/chat/server/chatContextManager.ts +612 -0
- package/src/chat/server/connectionManager.test.ts +266 -0
- package/src/chat/server/connectionManager.ts +541 -0
- package/src/chat/server/conversation.ts +269 -0
- package/src/chat/server/errorUtils.ts +28 -0
- package/src/chat/server/openSession.ts +1332 -0
- package/src/chat/server/server.ts +177 -0
- package/src/chat/server/sessionFileManager.ts +239 -0
- package/src/chat/server/sessionRegistry.test.ts +138 -0
- package/src/chat/server/sessionRegistry.ts +1064 -0
- package/src/chat/server/test-utils/mockFactories.ts +422 -0
- package/src/chat/server/tools.ts +265 -0
- package/src/chat/utils/agentSessionMap.ts +76 -0
- package/src/chat/utils/approvalManager.ts +111 -0
- package/src/{utils → chat/utils}/asyncLock.ts +3 -3
- package/src/chat/{asyncQueue.ts → utils/asyncQueue.ts} +14 -3
- package/src/chat/utils/htmlToText.ts +61 -0
- package/src/chat/utils/multiAsyncQueue.ts +52 -0
- package/src/chat/utils/search.ts +139 -0
- package/src/chat/utils/userResolver.ts +48 -0
- package/src/chat/utils/websocket.ts +16 -0
- package/src/test/agent.test.ts +487 -0
- package/src/test/approvalManager.test.ts +73 -0
- package/src/test/chatContextManager.test.ts +521 -0
- package/src/test/clientServerConnection.test.ts +207 -0
- package/src/test/compressingContextManager.test.ts +82 -0
- package/src/test/context.test.ts +105 -0
- package/src/test/conversation.test.ts +109 -0
- package/src/test/db.test.ts +358 -89
- package/src/test/dbMcpServerConfigs.test.ts +112 -0
- package/src/test/dbTestTools.ts +153 -0
- package/src/test/imageLoad.test.ts +7 -6
- package/src/test/mcpServerManager.test.ts +21 -16
- package/src/test/multiAsyncQueue.test.ts +125 -0
- package/src/test/openaiStreaming.test.ts +71 -36
- package/src/test/prompt.test.ts +4 -3
- package/src/test/promptProvider.test.ts +33 -0
- package/src/test/responseHandler.test.ts +78 -0
- package/src/test/sudoMcpServerManager.test.ts +32 -30
- package/src/test/testTools.ts +146 -0
- package/src/test/tools.test.ts +39 -0
- package/src/tool/agentChat.ts +26 -12
- package/src/tool/agentMain.ts +1 -1
- package/src/tool/chatMain.ts +292 -100
- package/src/tool/commandPrompt.ts +28 -19
- package/src/tool/files.ts +25 -19
- package/src/tool/nodePlatform.ts +52 -3
- package/src/tool/options.ts +4 -2
- package/src/tool/prompt.ts +22 -15
- package/test_data/dummyllm_script_crash.json +32 -0
- package/test_data/frog.png.b64 +1 -0
- package/vitest.config.ts +39 -0
- package/dist/agent/src/chat/client.js +0 -349
- package/dist/agent/src/chat/conversationManager.js +0 -392
- package/dist/agent/src/chat/db.js +0 -209
- package/dist/agent/src/chat/frontendClient.js +0 -74
- package/dist/agent/src/chat/server.js +0 -158
- package/src/chat/client.ts +0 -455
- package/src/chat/conversationManager.ts +0 -595
- package/src/chat/db.ts +0 -290
- package/src/chat/frontendClient.ts +0 -123
- package/src/chat/messages.ts +0 -235
- package/src/chat/server.ts +0 -177
- /package/dist/agent/src/{chat/messages.js → agent/iAgentEventHandler.js} +0 -0
- /package/{frog.png → test_data/frog.png} +0 -0
|
@@ -0,0 +1,733 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChatClient = void 0;
|
|
4
|
+
const uuid_1 = require("uuid");
|
|
5
|
+
const sdk_1 = require("@xalia/xmcp/sdk");
|
|
6
|
+
const connection_1 = require("./connection");
|
|
7
|
+
const sessionClient_1 = require("./sessionClient");
|
|
8
|
+
const database_1 = require("../data/database");
|
|
9
|
+
const messages_1 = require("../protocol/messages");
|
|
10
|
+
const constants_1 = require("./constants");
|
|
11
|
+
const agentSessionMap_1 = require("../utils/agentSessionMap");
|
|
12
|
+
const logger = (0, sdk_1.getLogger)();
|
|
13
|
+
class ChatClient {
|
|
14
|
+
constructor(connection, eventHandler,
|
|
15
|
+
// agent_uuid -> agent session data
|
|
16
|
+
userAgentSessionMap = new Map(),
|
|
17
|
+
// team_uuid -> team info
|
|
18
|
+
teams = new Map(), closed = false, currentSessionId = undefined,
|
|
19
|
+
// note: currentTeamId will not be reset when swtiching to a user session.
|
|
20
|
+
currentTeamId = undefined,
|
|
21
|
+
// session_uuid -> session client
|
|
22
|
+
activeSessions = new Map(),
|
|
23
|
+
// session_uuid -> true if there is a new message.
|
|
24
|
+
newMessage = new Map(),
|
|
25
|
+
// Track pending session join request, this should be a singleton
|
|
26
|
+
sessionJoinOrCreateRes = undefined) {
|
|
27
|
+
this.connection = connection;
|
|
28
|
+
this.eventHandler = eventHandler;
|
|
29
|
+
this.userAgentSessionMap = userAgentSessionMap;
|
|
30
|
+
this.teams = teams;
|
|
31
|
+
this.closed = closed;
|
|
32
|
+
this.currentSessionId = currentSessionId;
|
|
33
|
+
this.currentTeamId = currentTeamId;
|
|
34
|
+
this.activeSessions = activeSessions;
|
|
35
|
+
this.newMessage = newMessage;
|
|
36
|
+
this.sessionJoinOrCreateRes = sessionJoinOrCreateRes;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Connect to server and create ChatClient instance
|
|
40
|
+
*/
|
|
41
|
+
static async init(url, token, eventHandler) {
|
|
42
|
+
const connection = new connection_1.Connection({
|
|
43
|
+
url,
|
|
44
|
+
token,
|
|
45
|
+
});
|
|
46
|
+
return new Promise((resolveClient, reject) => {
|
|
47
|
+
let client = undefined;
|
|
48
|
+
const clientMessageId = (0, uuid_1.v4)();
|
|
49
|
+
// Register session_info handler for initialization
|
|
50
|
+
connection.on("control_session_list", (msg) => {
|
|
51
|
+
// get user sessions, user agents, and team sessions
|
|
52
|
+
const userSessions = new Map();
|
|
53
|
+
msg.user_sessions.forEach((session) => {
|
|
54
|
+
userSessions.set(session.session_uuid, session);
|
|
55
|
+
});
|
|
56
|
+
const userAgents = new Map();
|
|
57
|
+
msg.user_agents.forEach((agent) => {
|
|
58
|
+
userAgents.set(agent.uuid, agent);
|
|
59
|
+
});
|
|
60
|
+
const userAgentSessionMap = (0, agentSessionMap_1.buildAgentSessionMap)(userSessions, userAgents);
|
|
61
|
+
logger.info(`[ChatClient.init] session list msg: ${JSON.stringify(msg)}`);
|
|
62
|
+
for (const agentSession of userAgentSessionMap.values()) {
|
|
63
|
+
logger.info(`[ChatClient.init] agent: ` +
|
|
64
|
+
agentSession.agent_profile.profile_name);
|
|
65
|
+
}
|
|
66
|
+
const teams = new Map();
|
|
67
|
+
msg.team_sessions.forEach((team) => {
|
|
68
|
+
teams.set(team.team_uuid, ChatClient.toClientTeamInfo(team));
|
|
69
|
+
});
|
|
70
|
+
if (!client) {
|
|
71
|
+
logger.info("Creating ChatClient");
|
|
72
|
+
client = new ChatClient(connection, eventHandler, userAgentSessionMap, teams);
|
|
73
|
+
resolveClient(client);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
client.userAgentSessionMap = userAgentSessionMap;
|
|
77
|
+
client.teams = teams;
|
|
78
|
+
void client.eventHandler.onMessage(msg, client);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
// Register general message handler for established client
|
|
82
|
+
connection.on("*", (msg) => {
|
|
83
|
+
if (!client) {
|
|
84
|
+
if (msg.type === "control_error") {
|
|
85
|
+
logger.error(`[ChatClient] client error (init): ${JSON.stringify(msg)}`);
|
|
86
|
+
reject(new Error(msg.message));
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
logger.error(`[ChatClient] invalid message (init): ${JSON.stringify(msg.type)}`);
|
|
90
|
+
}
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if ((0, messages_1.isServerControlMessage)(msg)) {
|
|
94
|
+
client.handleControlMessage(msg);
|
|
95
|
+
}
|
|
96
|
+
else if ((0, messages_1.isServerSessionScopedMessage)(msg)) {
|
|
97
|
+
client.handleSessionMessage(msg);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
logger.error(`[ChatClient] unhandled msg: ${JSON.stringify(msg)}`);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
// Register direct error callback for client-side errors.
|
|
104
|
+
connection.onError((errorMessage) => {
|
|
105
|
+
if (client) {
|
|
106
|
+
client.connection.close();
|
|
107
|
+
}
|
|
108
|
+
eventHandler.onError(`Connection error: ${errorMessage}`);
|
|
109
|
+
});
|
|
110
|
+
// Start connection
|
|
111
|
+
connection
|
|
112
|
+
.connect()
|
|
113
|
+
.then(() => {
|
|
114
|
+
connection.send({
|
|
115
|
+
type: "control_get_session_list",
|
|
116
|
+
client_message_id: clientMessageId,
|
|
117
|
+
});
|
|
118
|
+
})
|
|
119
|
+
.catch((error) => {
|
|
120
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
static toClientTeamInfo(teamInfo) {
|
|
125
|
+
const sessions = new Map(teamInfo.sessions.map((session) => [session.session_uuid, session]));
|
|
126
|
+
const agents = new Map(teamInfo.agents.map((agent) => [agent.uuid, agent]));
|
|
127
|
+
const agentSessionMap = (0, agentSessionMap_1.buildAgentSessionMap)(sessions, agents);
|
|
128
|
+
return {
|
|
129
|
+
team_uuid: teamInfo.team_uuid,
|
|
130
|
+
team_name: teamInfo.team_name,
|
|
131
|
+
owner_uuid: teamInfo.owner_uuid,
|
|
132
|
+
participants: new Map(teamInfo.participants.map((participant) => [
|
|
133
|
+
participant.user_uuid,
|
|
134
|
+
participant,
|
|
135
|
+
])),
|
|
136
|
+
agentSessionMap,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Get the current session.
|
|
141
|
+
* Will throw an error if the current session is not set.
|
|
142
|
+
* @param location - The location of the caller.
|
|
143
|
+
* @returns The current session client.
|
|
144
|
+
*/
|
|
145
|
+
getCurrentSession(location) {
|
|
146
|
+
const session = this.getCurrentSessionMaybe();
|
|
147
|
+
if (!session) {
|
|
148
|
+
throw new Error(`[${location}]: No current session`);
|
|
149
|
+
}
|
|
150
|
+
return session;
|
|
151
|
+
}
|
|
152
|
+
getCurrentSessionMaybe() {
|
|
153
|
+
if (!this.currentSessionId) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
return this.activeSessions.get(this.currentSessionId);
|
|
157
|
+
}
|
|
158
|
+
getCurrentAgentUuid() {
|
|
159
|
+
const session = this.getCurrentSessionMaybe();
|
|
160
|
+
if (!session) {
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
return session.getAgentUuid();
|
|
164
|
+
}
|
|
165
|
+
getUserAgentSessionMap() {
|
|
166
|
+
return this.userAgentSessionMap;
|
|
167
|
+
}
|
|
168
|
+
getClientTeamInfo(teamUuid) {
|
|
169
|
+
return this.teams.get(teamUuid);
|
|
170
|
+
}
|
|
171
|
+
// ITeamManager -> getCurrentTeamInfo
|
|
172
|
+
getCurrentTeamInfo() {
|
|
173
|
+
if (!this.currentTeamId) {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
return this.teams.get(this.currentTeamId);
|
|
177
|
+
}
|
|
178
|
+
// ITeamManager -> getTeams
|
|
179
|
+
getTeams() {
|
|
180
|
+
return this.teams;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Get the currently active session ID
|
|
184
|
+
*/
|
|
185
|
+
getCurrentSessionId() {
|
|
186
|
+
return this.currentSessionId;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Get the currently team ID
|
|
190
|
+
*/
|
|
191
|
+
getCurrentTeamId() {
|
|
192
|
+
return this.currentTeamId;
|
|
193
|
+
}
|
|
194
|
+
// ITeamManager -> setCurrentTeamId
|
|
195
|
+
setCurrentTeamId(teamUuid) {
|
|
196
|
+
if (!this.teams.has(teamUuid)) {
|
|
197
|
+
throw new Error(`Team ${teamUuid} not found`);
|
|
198
|
+
}
|
|
199
|
+
this.currentTeamId = teamUuid;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Check if client is connected and operational
|
|
203
|
+
*/
|
|
204
|
+
isClosed() {
|
|
205
|
+
return this.closed;
|
|
206
|
+
}
|
|
207
|
+
shutdown() {
|
|
208
|
+
this.connection.close();
|
|
209
|
+
this.closed = true;
|
|
210
|
+
this.activeSessions.clear();
|
|
211
|
+
this.newMessage.clear();
|
|
212
|
+
this.teams.clear();
|
|
213
|
+
this.currentSessionId = undefined;
|
|
214
|
+
this.currentTeamId = undefined;
|
|
215
|
+
this.sessionJoinOrCreateRes = undefined;
|
|
216
|
+
}
|
|
217
|
+
async createNewSession(newTitle, agentProfileId, teamId) {
|
|
218
|
+
if (this.closed) {
|
|
219
|
+
throw new Error("ChatClient is closed");
|
|
220
|
+
}
|
|
221
|
+
if (this.sessionJoinOrCreateRes) {
|
|
222
|
+
logger.error(`[ChatClient] creating new session with ` +
|
|
223
|
+
`profile id ${JSON.stringify(agentProfileId)}`);
|
|
224
|
+
throw new Error("Session join/create is already in progress");
|
|
225
|
+
}
|
|
226
|
+
return new Promise((resolve, reject) => {
|
|
227
|
+
const clientMessageId = (0, uuid_1.v4)();
|
|
228
|
+
// Set up timeout for the request
|
|
229
|
+
const timeoutId = setTimeout(() => {
|
|
230
|
+
this.sessionJoinOrCreateRes = undefined;
|
|
231
|
+
reject(new Error(`Session join timeout for creating new session`));
|
|
232
|
+
}, constants_1.SESSION_CREATE_TIMEOUT);
|
|
233
|
+
// Track this pending request
|
|
234
|
+
this.sessionJoinOrCreateRes = {
|
|
235
|
+
resolve: (sessionClient, sessionInfo) => {
|
|
236
|
+
const sessionId = this.sessionJoinOrCreateRes?.sessionId;
|
|
237
|
+
if (!sessionId) {
|
|
238
|
+
throw new Error("Session id is not set in resolving.");
|
|
239
|
+
}
|
|
240
|
+
if (sessionId !== sessionInfo.session_id) {
|
|
241
|
+
throw new Error("SessionInfo id mismatch");
|
|
242
|
+
}
|
|
243
|
+
clearTimeout(timeoutId);
|
|
244
|
+
this.activeSessions.set(sessionId, sessionClient);
|
|
245
|
+
this.currentSessionId = sessionId;
|
|
246
|
+
if (sessionInfo.team_uuid) {
|
|
247
|
+
this.currentTeamId = sessionInfo.team_uuid;
|
|
248
|
+
}
|
|
249
|
+
this.sessionJoinOrCreateRes = undefined;
|
|
250
|
+
this.addSessionToAgentSessionMap(sessionInfo);
|
|
251
|
+
resolve(sessionClient);
|
|
252
|
+
},
|
|
253
|
+
reject: (error) => {
|
|
254
|
+
clearTimeout(timeoutId);
|
|
255
|
+
this.sessionJoinOrCreateRes = undefined;
|
|
256
|
+
reject(error);
|
|
257
|
+
},
|
|
258
|
+
sessionId: "",
|
|
259
|
+
clientMessageId,
|
|
260
|
+
};
|
|
261
|
+
// Send session_create message
|
|
262
|
+
try {
|
|
263
|
+
this.connection.send({
|
|
264
|
+
type: "control_session_create",
|
|
265
|
+
client_message_id: clientMessageId,
|
|
266
|
+
title: newTitle,
|
|
267
|
+
agent_profile_id: agentProfileId,
|
|
268
|
+
team_id: teamId,
|
|
269
|
+
});
|
|
270
|
+
logger.info(`[ChatClient] Sent session_create for session ${newTitle}` +
|
|
271
|
+
` client message id: ${clientMessageId}`);
|
|
272
|
+
}
|
|
273
|
+
catch (error) {
|
|
274
|
+
this.sessionJoinOrCreateRes = undefined;
|
|
275
|
+
clearTimeout(timeoutId);
|
|
276
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Connect to an existing session by sending session_join message
|
|
282
|
+
* and waiting for session_info response from server
|
|
283
|
+
*/
|
|
284
|
+
async connectToSession(sessionId) {
|
|
285
|
+
if (this.closed) {
|
|
286
|
+
throw new Error("ChatClient is closed");
|
|
287
|
+
}
|
|
288
|
+
if (this.sessionJoinOrCreateRes) {
|
|
289
|
+
logger.error(`[ChatClient] connecting to session ${sessionId}`);
|
|
290
|
+
throw new Error("Session join/create is already in progress");
|
|
291
|
+
}
|
|
292
|
+
// TODO: we can directly return a session client if we cache conversation.
|
|
293
|
+
// For now, we go through the join process.
|
|
294
|
+
return new Promise((resolve, reject) => {
|
|
295
|
+
const clientMessageId = (0, uuid_1.v4)();
|
|
296
|
+
// Set up timeout for the request
|
|
297
|
+
const timeoutId = setTimeout(() => {
|
|
298
|
+
this.sessionJoinOrCreateRes = undefined;
|
|
299
|
+
reject(new Error(`Session join timeout for session ${sessionId}`));
|
|
300
|
+
}, constants_1.SESSION_JOIN_TIMEOUT);
|
|
301
|
+
// Track this pending request
|
|
302
|
+
this.sessionJoinOrCreateRes = {
|
|
303
|
+
resolve: (sessionClient, sessionInfo) => {
|
|
304
|
+
clearTimeout(timeoutId);
|
|
305
|
+
this.activeSessions.set(sessionId, sessionClient);
|
|
306
|
+
this.currentSessionId = sessionId;
|
|
307
|
+
if (sessionInfo.team_uuid) {
|
|
308
|
+
this.currentTeamId = sessionInfo.team_uuid;
|
|
309
|
+
}
|
|
310
|
+
this.sessionJoinOrCreateRes = undefined;
|
|
311
|
+
this.updateSessionInfo(sessionInfo);
|
|
312
|
+
logger.info(`[ChatClient] joined session ${sessionId}`);
|
|
313
|
+
resolve(sessionClient);
|
|
314
|
+
},
|
|
315
|
+
reject: (error) => {
|
|
316
|
+
clearTimeout(timeoutId);
|
|
317
|
+
this.sessionJoinOrCreateRes = undefined;
|
|
318
|
+
logger.error(`[ChatClient] failed to join session` +
|
|
319
|
+
` ${sessionId}: ${error.message}`);
|
|
320
|
+
reject(error);
|
|
321
|
+
},
|
|
322
|
+
sessionId,
|
|
323
|
+
clientMessageId,
|
|
324
|
+
};
|
|
325
|
+
// Send session_join message
|
|
326
|
+
try {
|
|
327
|
+
this.connection.send({
|
|
328
|
+
type: "control_session_join",
|
|
329
|
+
client_message_id: clientMessageId,
|
|
330
|
+
target_session_id: sessionId,
|
|
331
|
+
});
|
|
332
|
+
logger.debug(`[ChatClient] Sent session_join for session ${sessionId}`);
|
|
333
|
+
}
|
|
334
|
+
catch (error) {
|
|
335
|
+
this.sessionJoinOrCreateRes = undefined;
|
|
336
|
+
clearTimeout(timeoutId);
|
|
337
|
+
reject(error instanceof Error ? error : new Error(String(error)));
|
|
338
|
+
}
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Fetch the session list from the server
|
|
343
|
+
*/
|
|
344
|
+
fetchSessionList() {
|
|
345
|
+
this.connection.send({
|
|
346
|
+
type: "control_get_session_list",
|
|
347
|
+
client_message_id: (0, uuid_1.v4)(),
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Delete a session by sending session_delete_request message
|
|
352
|
+
* and waiting for session_deleted response from server
|
|
353
|
+
* @param sessionId
|
|
354
|
+
* @returns void
|
|
355
|
+
*/
|
|
356
|
+
deleteSession(sessionId) {
|
|
357
|
+
if (this.closed) {
|
|
358
|
+
throw new Error("ChatClient is closed");
|
|
359
|
+
}
|
|
360
|
+
this.connection.send({
|
|
361
|
+
type: "control_session_delete",
|
|
362
|
+
client_message_id: (0, uuid_1.v4)(),
|
|
363
|
+
target_session_id: sessionId,
|
|
364
|
+
});
|
|
365
|
+
logger.debug(`[ChatClient] Sent session_delete_request for` + ` session ${sessionId}`);
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Create a new team with initial members
|
|
369
|
+
* @param teamName
|
|
370
|
+
* @param initialMembers could be UUIDs or emails
|
|
371
|
+
*/
|
|
372
|
+
createNewTeam(teamName, initialMembers) {
|
|
373
|
+
if (this.closed) {
|
|
374
|
+
throw new Error("ChatClient is closed");
|
|
375
|
+
}
|
|
376
|
+
// send team_create_request message
|
|
377
|
+
try {
|
|
378
|
+
this.connection.send({
|
|
379
|
+
type: "control_team_create",
|
|
380
|
+
client_message_id: (0, uuid_1.v4)(),
|
|
381
|
+
team_name: teamName,
|
|
382
|
+
initial_members: initialMembers,
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
this.eventHandler.onError(String(error));
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Add a user to a team
|
|
391
|
+
* @param teamId - UUID of the team
|
|
392
|
+
* @param userId - UUID of the user to add
|
|
393
|
+
*/
|
|
394
|
+
addTeamMember(teamId, userId) {
|
|
395
|
+
if (this.closed) {
|
|
396
|
+
throw new Error("ChatClient is closed");
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
this.connection.send({
|
|
400
|
+
type: "control_add_team_user",
|
|
401
|
+
client_message_id: (0, uuid_1.v4)(),
|
|
402
|
+
target_team_id: teamId,
|
|
403
|
+
user_uuid_or_email: userId,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
catch (error) {
|
|
407
|
+
this.eventHandler.onError(String(error));
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Remove a user from a team
|
|
412
|
+
* @param teamId - UUID of the team
|
|
413
|
+
* @param userId - UUID of the user to remove
|
|
414
|
+
*/
|
|
415
|
+
removeTeamMember(teamId, userId) {
|
|
416
|
+
if (this.closed) {
|
|
417
|
+
throw new Error("ChatClient is closed");
|
|
418
|
+
}
|
|
419
|
+
try {
|
|
420
|
+
this.connection.send({
|
|
421
|
+
type: "control_remove_team_user",
|
|
422
|
+
client_message_id: (0, uuid_1.v4)(),
|
|
423
|
+
target_team_id: teamId,
|
|
424
|
+
user_uuid_or_email: userId,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
catch (error) {
|
|
428
|
+
this.eventHandler.onError(String(error));
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* Create a new agent
|
|
433
|
+
* @param agentName - the agent name
|
|
434
|
+
* @param templateName - the template name
|
|
435
|
+
* @param teamUuid - the team uuid
|
|
436
|
+
*/
|
|
437
|
+
createNewAgent(agentName, templateName, teamUuid) {
|
|
438
|
+
if (this.closed) {
|
|
439
|
+
throw new Error("ChatClient is closed");
|
|
440
|
+
}
|
|
441
|
+
try {
|
|
442
|
+
this.connection.send({
|
|
443
|
+
type: "control_agent_profile_create",
|
|
444
|
+
title: agentName,
|
|
445
|
+
template_name: templateName,
|
|
446
|
+
team_uuid: teamUuid,
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
catch (error) {
|
|
450
|
+
this.eventHandler.onError(String(error));
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Delete a session from the agent session map
|
|
455
|
+
* @param agentSessionMap - the agent session map
|
|
456
|
+
* @param agentUuid - the agent uuid
|
|
457
|
+
* @param sessionId - the session id
|
|
458
|
+
* @returns true if the session is deleted, false otherwise
|
|
459
|
+
*/
|
|
460
|
+
static deleteSessionFromAgentSessionMap(agentSessionMap, agentUuid, sessionId) {
|
|
461
|
+
const agentSession = agentSessionMap.get(agentUuid);
|
|
462
|
+
if (!agentSession) {
|
|
463
|
+
return false;
|
|
464
|
+
}
|
|
465
|
+
const size = agentSession.sessions.length;
|
|
466
|
+
agentSession.sessions = agentSession.sessions.filter((session) => session.session_uuid !== sessionId);
|
|
467
|
+
return size > agentSession.sessions.length;
|
|
468
|
+
}
|
|
469
|
+
handleSessionDeleted(msg) {
|
|
470
|
+
const sessionId = msg.session_id;
|
|
471
|
+
const agentUuid = msg.agent_profile_uuid;
|
|
472
|
+
logger.info(`[ChatClient] Session deleted: ${JSON.stringify(msg)}`);
|
|
473
|
+
let deleted = false;
|
|
474
|
+
if (msg.team_uuid) {
|
|
475
|
+
deleted = ChatClient.deleteSessionFromAgentSessionMap(this.teams.get(msg.team_uuid)?.agentSessionMap ??
|
|
476
|
+
new Map(), agentUuid, sessionId);
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
deleted = ChatClient.deleteSessionFromAgentSessionMap(this.userAgentSessionMap, agentUuid, sessionId);
|
|
480
|
+
}
|
|
481
|
+
if (!deleted) {
|
|
482
|
+
// could be a race condition, we fetch the session list from the server
|
|
483
|
+
logger.warn(`[ChatClient] Session ${sessionId} is not in session map`);
|
|
484
|
+
this.connection.send({
|
|
485
|
+
type: "control_get_session_list",
|
|
486
|
+
client_message_id: (0, uuid_1.v4)(),
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
this.activeSessions.delete(sessionId);
|
|
490
|
+
this.newMessage.delete(sessionId);
|
|
491
|
+
void this.eventHandler.onMessage(msg, this);
|
|
492
|
+
}
|
|
493
|
+
handleControlMessage(msg) {
|
|
494
|
+
switch (msg.type) {
|
|
495
|
+
case "control_session_left":
|
|
496
|
+
this.activeSessions.delete(msg.session_id);
|
|
497
|
+
break;
|
|
498
|
+
case "control_agent_profile_created":
|
|
499
|
+
this.handleAgentProfileCreated(msg);
|
|
500
|
+
break;
|
|
501
|
+
case "control_agent_profile_deleted":
|
|
502
|
+
this.handleAgentProfileDeleted(msg);
|
|
503
|
+
break;
|
|
504
|
+
case "control_error":
|
|
505
|
+
this.handleControlError(msg);
|
|
506
|
+
break;
|
|
507
|
+
case "control_session_deleted":
|
|
508
|
+
this.handleSessionDeleted(msg);
|
|
509
|
+
break;
|
|
510
|
+
case "control_session_list":
|
|
511
|
+
logger.warn(`[ChatClient] Unexpected message in runtime: ${msg.type} `);
|
|
512
|
+
break;
|
|
513
|
+
case "control_team_created":
|
|
514
|
+
this.handleTeamCreatedMessage(msg);
|
|
515
|
+
break;
|
|
516
|
+
default: {
|
|
517
|
+
const _exhaustive = msg;
|
|
518
|
+
throw new Error(`unexpected control msg: ${JSON.stringify(msg)}`);
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
void this.eventHandler.onMessage(msg, this);
|
|
522
|
+
}
|
|
523
|
+
handleAgentProfileCreated(msg) {
|
|
524
|
+
logger.debug(`[ChatClient.handleAgentProfileCreated] msg: ${JSON.stringify(msg)}`);
|
|
525
|
+
const teamId = msg.profile.team_uuid;
|
|
526
|
+
const profileId = msg.profile.uuid;
|
|
527
|
+
const newAgentSession = {
|
|
528
|
+
agent_profile: msg.profile,
|
|
529
|
+
sessions: [],
|
|
530
|
+
updated_at: Date.now(),
|
|
531
|
+
};
|
|
532
|
+
if (teamId) {
|
|
533
|
+
const team = this.teams.get(teamId);
|
|
534
|
+
if (!team) {
|
|
535
|
+
throw new Error(`[handleAgentProfileCreated] no such team ${teamId}`);
|
|
536
|
+
}
|
|
537
|
+
team.agentSessionMap.set(profileId, newAgentSession);
|
|
538
|
+
}
|
|
539
|
+
else {
|
|
540
|
+
this.userAgentSessionMap.set(profileId, newAgentSession);
|
|
541
|
+
}
|
|
542
|
+
void this.eventHandler.onMessage(msg, this);
|
|
543
|
+
}
|
|
544
|
+
handleAgentProfileDeleted(_msg) {
|
|
545
|
+
throw new Error("handleAgentProfileDeleted not implemented");
|
|
546
|
+
}
|
|
547
|
+
handleSessionMessage(msg) {
|
|
548
|
+
const sessionId = msg.session_id;
|
|
549
|
+
// TODO: we need to handle create new session case here, previously create
|
|
550
|
+
// new session's param are passed by URL, this is no longer an option
|
|
551
|
+
// since we are not creating a new connection for each session.
|
|
552
|
+
// Handle session_info message for pending session joins
|
|
553
|
+
if (msg.type === "session_info") {
|
|
554
|
+
this.handleSessionInfoMessage(msg);
|
|
555
|
+
// notify the event handler, i.e. UI that the session info update
|
|
556
|
+
void this.eventHandler.onMessage(msg, this);
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
// Handle messages for existing active sessions
|
|
560
|
+
if (this.activeSessions.has(sessionId)) {
|
|
561
|
+
const sessionClient = this.activeSessions.get(sessionId);
|
|
562
|
+
if (sessionClient) {
|
|
563
|
+
sessionClient.handleMessage(msg);
|
|
564
|
+
// we are only calling the onMessage for session scoped message for now.
|
|
565
|
+
void this.eventHandler.onMessage(msg, this);
|
|
566
|
+
}
|
|
567
|
+
else {
|
|
568
|
+
throw new Error(`Session client not found for session ${sessionId}`);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
else {
|
|
572
|
+
// Session not active yet, mark as having new messages
|
|
573
|
+
this.newMessage.set(sessionId, true);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
handleTeamCreatedMessage(msg) {
|
|
577
|
+
const teamInfo = {
|
|
578
|
+
team_uuid: msg.team_uuid,
|
|
579
|
+
team_name: msg.team_name,
|
|
580
|
+
owner_uuid: msg.team_owner_uuid,
|
|
581
|
+
participants: msg.members,
|
|
582
|
+
sessions: [],
|
|
583
|
+
agents: [],
|
|
584
|
+
};
|
|
585
|
+
this.teams.set(teamInfo.team_uuid, ChatClient.toClientTeamInfo(teamInfo));
|
|
586
|
+
this.currentTeamId = teamInfo.team_uuid;
|
|
587
|
+
void this.eventHandler.onMessage(msg, this);
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Handle session_info message which can be for:
|
|
592
|
+
* 1. A pending session join/create request
|
|
593
|
+
* 2. An update to an existing active session
|
|
594
|
+
* We update the session list here as well.
|
|
595
|
+
*/
|
|
596
|
+
handleSessionInfoMessage(msg) {
|
|
597
|
+
const sessionId = msg.session_id;
|
|
598
|
+
// There is a pending request, check if this is the response
|
|
599
|
+
if (this.sessionJoinOrCreateRes &&
|
|
600
|
+
msg.client_message_id === this.sessionJoinOrCreateRes.clientMessageId) {
|
|
601
|
+
const { resolve, reject } = this.sessionJoinOrCreateRes;
|
|
602
|
+
try {
|
|
603
|
+
logger.info(`[ChatClient] Creating SessionClient for session ${sessionId}`);
|
|
604
|
+
logger.info(`[ChatClient] msg: ${JSON.stringify(msg)}`);
|
|
605
|
+
const sessionClient = new sessionClient_1.SessionClient(sessionId, msg.saved_agent_profile, this.connection, msg.mcp_server_briefs, (0, database_1.createSessionParticipantMap)(msg.participants));
|
|
606
|
+
// we need to pass the session id if this is a new session
|
|
607
|
+
if (this.sessionJoinOrCreateRes.sessionId === "") {
|
|
608
|
+
this.sessionJoinOrCreateRes.sessionId = sessionId;
|
|
609
|
+
}
|
|
610
|
+
else if (this.sessionJoinOrCreateRes.sessionId !== sessionId) {
|
|
611
|
+
throw new Error(`[ChatClient] session id mismatch: ` +
|
|
612
|
+
`${this.sessionJoinOrCreateRes.sessionId} !== ${sessionId}`);
|
|
613
|
+
}
|
|
614
|
+
resolve(sessionClient, msg);
|
|
615
|
+
}
|
|
616
|
+
catch (error) {
|
|
617
|
+
const errorMsg = error instanceof Error ? error : new Error(String(error));
|
|
618
|
+
logger.error(`[ChatClient] Failed to create SessionClient: ${errorMsg.message}`);
|
|
619
|
+
reject(errorMsg);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
this.updateSessionInfo(msg);
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
handleControlError(msg) {
|
|
627
|
+
// reject the pending session join/create request if message id matches
|
|
628
|
+
if (this.sessionJoinOrCreateRes &&
|
|
629
|
+
msg.client_message_id === this.sessionJoinOrCreateRes.clientMessageId) {
|
|
630
|
+
this.sessionJoinOrCreateRes.reject(new Error(msg.message));
|
|
631
|
+
}
|
|
632
|
+
this.eventHandler.onError(`Server error: ${msg.message}`);
|
|
633
|
+
}
|
|
634
|
+
/**
|
|
635
|
+
* Update the session list. This is called when a session is updated.
|
|
636
|
+
* An error is thrown if the session id is not found.
|
|
637
|
+
* TODO: we might want to resync session map, for now, throw error to
|
|
638
|
+
* expose problems in the code.
|
|
639
|
+
*/
|
|
640
|
+
updateAgentSessionMap(sessionInfo) {
|
|
641
|
+
const sessionId = sessionInfo.session_id;
|
|
642
|
+
if (sessionInfo.team_uuid) {
|
|
643
|
+
const teamInfo = this.teams.get(sessionInfo.team_uuid);
|
|
644
|
+
if (!teamInfo) {
|
|
645
|
+
throw new Error(`Team ${sessionInfo.team_uuid} not found in team list`);
|
|
646
|
+
}
|
|
647
|
+
//teamInfo.sessions.set(sessionId, ChatClient.toSessionData(sessionInfo));
|
|
648
|
+
const agentSessionMap = teamInfo.agentSessionMap;
|
|
649
|
+
if (!doUpdateAgentSessionMap(agentSessionMap, sessionInfo)) {
|
|
650
|
+
throw new Error(`[updateAgentSessionMap] team session ${sessionId}` +
|
|
651
|
+
` not found in agent session map`);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
else {
|
|
655
|
+
const agentSessionMap = this.userAgentSessionMap;
|
|
656
|
+
if (!doUpdateAgentSessionMap(agentSessionMap, sessionInfo)) {
|
|
657
|
+
throw new Error(`[updateAgentSessionMap] user session ${sessionId}` +
|
|
658
|
+
` not found in agent session map`);
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
/**
|
|
663
|
+
* Update the session info for an existing session. This passes the session
|
|
664
|
+
* info to the session client. An error is thrown if the session client is not
|
|
665
|
+
* found.
|
|
666
|
+
*/
|
|
667
|
+
updateSessionInfo(msg) {
|
|
668
|
+
const sessionId = msg.session_id;
|
|
669
|
+
const sessionClient = this.activeSessions.get(sessionId);
|
|
670
|
+
this.updateAgentSessionMap(msg);
|
|
671
|
+
if (sessionClient) {
|
|
672
|
+
sessionClient.updateSessionInfo(msg);
|
|
673
|
+
}
|
|
674
|
+
else {
|
|
675
|
+
throw new Error(`Session client not found for session ${sessionId}`);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
addSessionToAgentSessionMap(msg) {
|
|
679
|
+
// get the correct agent session map
|
|
680
|
+
const agentSessionMap = msg.team_uuid
|
|
681
|
+
? this.teams.get(msg.team_uuid)?.agentSessionMap
|
|
682
|
+
: this.userAgentSessionMap;
|
|
683
|
+
if (!agentSessionMap) {
|
|
684
|
+
throw new Error(`Invalid team uuid ${JSON.stringify(msg.team_uuid)}`);
|
|
685
|
+
}
|
|
686
|
+
// update the agent session map
|
|
687
|
+
const agentUuid = msg.saved_agent_profile.uuid;
|
|
688
|
+
const agentSession = agentSessionMap.get(agentUuid);
|
|
689
|
+
if (!agentSession) {
|
|
690
|
+
throw new Error(`[addSessionToAgentSessionMap] Agent ${agentUuid}` +
|
|
691
|
+
` not found in agent session map`);
|
|
692
|
+
}
|
|
693
|
+
agentSession.sessions.push(sessionInfoToSessionData(msg));
|
|
694
|
+
agentSession.updated_at = new Date(msg.updated_at).getTime();
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
exports.ChatClient = ChatClient;
|
|
698
|
+
function sessionInfoToSessionData(msg) {
|
|
699
|
+
return {
|
|
700
|
+
session_uuid: msg.session_id,
|
|
701
|
+
title: msg.title,
|
|
702
|
+
team_uuid: msg.team_uuid,
|
|
703
|
+
agent_profile_uuid: msg.saved_agent_profile.uuid,
|
|
704
|
+
workspace: msg.workspace,
|
|
705
|
+
updated_at: msg.updated_at,
|
|
706
|
+
user_uuid: msg.owner_uuid,
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Update the agent session map
|
|
711
|
+
* @param agentSessionMap - the agent session map
|
|
712
|
+
* @param sessionInfo - the session info
|
|
713
|
+
* @returns true if the session is updated, false otherwise
|
|
714
|
+
*/
|
|
715
|
+
function doUpdateAgentSessionMap(agentSessionMap, sessionInfo) {
|
|
716
|
+
const sessionId = sessionInfo.session_id;
|
|
717
|
+
const agentUuid = sessionInfo.saved_agent_profile.uuid;
|
|
718
|
+
const agent = agentSessionMap.get(agentUuid);
|
|
719
|
+
if (!agent) {
|
|
720
|
+
return false;
|
|
721
|
+
}
|
|
722
|
+
let updated = false;
|
|
723
|
+
agent.sessions.map((session) => {
|
|
724
|
+
if (session.session_uuid === sessionId) {
|
|
725
|
+
updated = true;
|
|
726
|
+
return sessionInfoToSessionData(sessionInfo);
|
|
727
|
+
}
|
|
728
|
+
else {
|
|
729
|
+
return session;
|
|
730
|
+
}
|
|
731
|
+
});
|
|
732
|
+
return updated;
|
|
733
|
+
}
|