@xalia/agent 0.6.1 → 0.6.3

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.
Files changed (127) hide show
  1. package/dist/agent/src/agent/agent.js +109 -57
  2. package/dist/agent/src/agent/agentUtils.js +24 -26
  3. package/dist/agent/src/agent/compressingContextManager.js +3 -2
  4. package/dist/agent/src/agent/dummyLLM.js +1 -3
  5. package/dist/agent/src/agent/imageGenLLM.js +67 -0
  6. package/dist/agent/src/agent/imageGenerator.js +43 -0
  7. package/dist/agent/src/agent/llm.js +27 -0
  8. package/dist/agent/src/agent/mcpServerManager.js +18 -6
  9. package/dist/agent/src/agent/nullAgentEventHandler.js +6 -0
  10. package/dist/agent/src/agent/openAILLM.js +3 -3
  11. package/dist/agent/src/agent/openAILLMStreaming.js +41 -6
  12. package/dist/agent/src/chat/client/chatClient.js +154 -235
  13. package/dist/agent/src/chat/client/constants.js +1 -2
  14. package/dist/agent/src/chat/client/sessionClient.js +47 -15
  15. package/dist/agent/src/chat/client/sessionFiles.js +102 -0
  16. package/dist/agent/src/chat/data/apiKeyManager.js +38 -7
  17. package/dist/agent/src/chat/data/database.js +83 -70
  18. package/dist/agent/src/chat/data/dbSessionFileModels.js +49 -0
  19. package/dist/agent/src/chat/data/dbSessionFiles.js +76 -0
  20. package/dist/agent/src/chat/data/dbSessionMessages.js +57 -0
  21. package/dist/agent/src/chat/data/mimeTypes.js +44 -0
  22. package/dist/agent/src/chat/protocol/messages.js +21 -1
  23. package/dist/agent/src/chat/server/chatContextManager.js +19 -16
  24. package/dist/agent/src/chat/server/connectionManager.js +14 -36
  25. package/dist/agent/src/chat/server/connectionManager.test.js +3 -16
  26. package/dist/agent/src/chat/server/conversation.js +73 -44
  27. package/dist/agent/src/chat/server/imageGeneratorTools.js +111 -0
  28. package/dist/agent/src/chat/server/openSession.js +398 -233
  29. package/dist/agent/src/chat/server/openSessionMessageSender.js +2 -0
  30. package/dist/agent/src/chat/server/server.js +5 -8
  31. package/dist/agent/src/chat/server/sessionFileManager.js +171 -38
  32. package/dist/agent/src/chat/server/sessionRegistry.js +214 -42
  33. package/dist/agent/src/chat/server/test-utils/mockFactories.js +12 -11
  34. package/dist/agent/src/chat/server/tools.js +27 -6
  35. package/dist/agent/src/chat/utils/approvalManager.js +82 -64
  36. package/dist/agent/src/chat/utils/multiAsyncQueue.js +9 -1
  37. package/dist/agent/src/chat/{client/responseHandler.js → utils/responseAwaiter.js} +41 -18
  38. package/dist/agent/src/test/agent.test.js +104 -63
  39. package/dist/agent/src/test/approvalManager.test.js +79 -35
  40. package/dist/agent/src/test/chatContextManager.test.js +16 -17
  41. package/dist/agent/src/test/clientServerConnection.test.js +2 -2
  42. package/dist/agent/src/test/db.test.js +33 -70
  43. package/dist/agent/src/test/dbSessionFiles.test.js +179 -0
  44. package/dist/agent/src/test/dbSessionMessages.test.js +67 -0
  45. package/dist/agent/src/test/dbTestTools.js +6 -5
  46. package/dist/agent/src/test/imageLoad.test.js +1 -1
  47. package/dist/agent/src/test/mcpServerManager.test.js +1 -1
  48. package/dist/agent/src/test/multiAsyncQueue.test.js +50 -0
  49. package/dist/agent/src/test/responseAwaiter.test.js +74 -0
  50. package/dist/agent/src/test/testTools.js +12 -0
  51. package/dist/agent/src/tool/agentChat.js +25 -6
  52. package/dist/agent/src/tool/agentMain.js +1 -1
  53. package/dist/agent/src/tool/chatMain.js +115 -6
  54. package/dist/agent/src/tool/commandPrompt.js +7 -3
  55. package/dist/agent/src/tool/files.js +23 -15
  56. package/dist/agent/src/tool/options.js +2 -2
  57. package/package.json +1 -1
  58. package/scripts/setup_chat +2 -2
  59. package/scripts/test_chat +95 -36
  60. package/src/agent/agent.ts +152 -41
  61. package/src/agent/agentUtils.ts +34 -41
  62. package/src/agent/compressingContextManager.ts +5 -4
  63. package/src/agent/context.ts +1 -1
  64. package/src/agent/dummyLLM.ts +1 -3
  65. package/src/agent/iAgentEventHandler.ts +15 -2
  66. package/src/agent/imageGenLLM.ts +99 -0
  67. package/src/agent/imageGenerator.ts +60 -0
  68. package/src/agent/llm.ts +128 -4
  69. package/src/agent/mcpServerManager.ts +26 -7
  70. package/src/agent/nullAgentEventHandler.ts +6 -0
  71. package/src/agent/openAILLM.ts +3 -8
  72. package/src/agent/openAILLMStreaming.ts +60 -14
  73. package/src/chat/client/chatClient.ts +262 -286
  74. package/src/chat/client/constants.ts +0 -2
  75. package/src/chat/client/sessionClient.ts +82 -20
  76. package/src/chat/client/sessionFiles.ts +142 -0
  77. package/src/chat/data/apiKeyManager.ts +55 -7
  78. package/src/chat/data/dataModels.ts +17 -7
  79. package/src/chat/data/database.ts +107 -92
  80. package/src/chat/data/dbSessionFileModels.ts +91 -0
  81. package/src/chat/data/dbSessionFiles.ts +99 -0
  82. package/src/chat/data/dbSessionMessages.ts +68 -0
  83. package/src/chat/data/mimeTypes.ts +58 -0
  84. package/src/chat/protocol/messages.ts +136 -25
  85. package/src/chat/server/chatContextManager.ts +42 -24
  86. package/src/chat/server/connectionManager.test.ts +2 -22
  87. package/src/chat/server/connectionManager.ts +18 -53
  88. package/src/chat/server/conversation.ts +106 -59
  89. package/src/chat/server/imageGeneratorTools.ts +138 -0
  90. package/src/chat/server/openSession.ts +606 -325
  91. package/src/chat/server/openSessionMessageSender.ts +4 -0
  92. package/src/chat/server/server.ts +5 -11
  93. package/src/chat/server/sessionFileManager.ts +223 -63
  94. package/src/chat/server/sessionRegistry.ts +317 -52
  95. package/src/chat/server/test-utils/mockFactories.ts +13 -13
  96. package/src/chat/server/tools.ts +43 -8
  97. package/src/chat/utils/agentSessionMap.ts +2 -2
  98. package/src/chat/utils/approvalManager.ts +153 -81
  99. package/src/chat/utils/multiAsyncQueue.ts +11 -1
  100. package/src/chat/{client/responseHandler.ts → utils/responseAwaiter.ts} +73 -23
  101. package/src/test/agent.test.ts +152 -75
  102. package/src/test/approvalManager.test.ts +108 -40
  103. package/src/test/chatContextManager.test.ts +26 -22
  104. package/src/test/clientServerConnection.test.ts +3 -3
  105. package/src/test/compressingContextManager.test.ts +1 -1
  106. package/src/test/context.test.ts +2 -1
  107. package/src/test/conversation.test.ts +1 -1
  108. package/src/test/db.test.ts +41 -83
  109. package/src/test/dbSessionFiles.test.ts +258 -0
  110. package/src/test/dbSessionMessages.test.ts +85 -0
  111. package/src/test/dbTestTools.ts +9 -5
  112. package/src/test/imageLoad.test.ts +2 -2
  113. package/src/test/mcpServerManager.test.ts +3 -1
  114. package/src/test/multiAsyncQueue.test.ts +58 -0
  115. package/src/test/responseAwaiter.test.ts +103 -0
  116. package/src/test/testTools.ts +15 -1
  117. package/src/tool/agentChat.ts +36 -8
  118. package/src/tool/agentMain.ts +7 -7
  119. package/src/tool/chatMain.ts +128 -7
  120. package/src/tool/commandPrompt.ts +10 -5
  121. package/src/tool/files.ts +30 -13
  122. package/src/tool/options.ts +1 -1
  123. package/test_data/dummyllm_script_image_gen.json +19 -0
  124. package/test_data/dummyllm_script_invoke_image_gen_tool.json +30 -0
  125. package/test_data/image_gen_test_profile.json +5 -0
  126. package/dist/agent/src/test/responseHandler.test.js +0 -61
  127. package/src/test/responseHandler.test.ts +0 -78
@@ -1,9 +1,3 @@
1
- import {
2
- ChatCompletionMessageParam,
3
- ChatCompletionAssistantMessageParam,
4
- ChatCompletionToolMessageParam,
5
- ChatCompletionMessageToolCall,
6
- } from "openai/resources.mjs";
7
1
  import { Tool } from "@modelcontextprotocol/sdk/types.js";
8
2
 
9
3
  import {
@@ -12,21 +6,29 @@ import {
12
6
  McpServerConfiguration,
13
7
  SavedAgentProfile,
14
8
  } from "@xalia/xmcp/sdk";
9
+
15
10
  import {
16
11
  TeamRole,
17
- SessionData,
18
12
  TeamInfo,
19
13
  TeamParticipant,
20
14
  UserMessageData,
15
+ SessionDescriptor,
21
16
  } from "../data/dataModels";
17
+ import { SessionFileDescriptor } from "../data/dbSessionFileModels";
18
+ import {
19
+ ChatCompletionAssistantMessageParam,
20
+ ChatCompletionMessageParam,
21
+ ChatCompletionMessageToolCall,
22
+ ChatCompletionToolMessageParam,
23
+ } from "../../agent/llm";
22
24
 
23
- interface ClientToServerBase {
25
+ export interface ClientToServerBase {
24
26
  type: string;
25
27
  client_message_id: string; // TODO: hide by putting on ClientToServer?
26
28
  }
27
29
 
28
30
  // Session-level messages all have a `session_id`
29
- interface ClientSessionMessageBase extends ClientToServerBase {
31
+ export interface ClientSessionMessageBase extends ClientToServerBase {
30
32
  session_id: string;
31
33
  }
32
34
 
@@ -127,6 +129,7 @@ export type ClientControlMessage =
127
129
 
128
130
  export type ClientUserMessage = {
129
131
  type: "msg";
132
+ race_mode?: boolean;
130
133
  } & UserMessageData;
131
134
 
132
135
  export type ClientSetWorkspace = {
@@ -173,6 +176,23 @@ export type ClientToolCallApprovalResult = {
173
176
  auto_approve: boolean;
174
177
  };
175
178
 
179
+ export type ClientSessionFileGetContent = {
180
+ type: "session_file_get_content";
181
+ name: string;
182
+ };
183
+
184
+ export type ClientSessionFileDelete = {
185
+ type: "session_file_delete";
186
+ name: string;
187
+ };
188
+
189
+ export type ClientSessionFilePutContent = {
190
+ type: "session_file_put_content";
191
+ name?: string;
192
+ summary?: string;
193
+ data_url: string;
194
+ };
195
+
176
196
  export type ClientSetAutoApproval = {
177
197
  type: "set_auto_approval";
178
198
  server_name: string;
@@ -190,12 +210,27 @@ export type ClientSetModel = {
190
210
  model: string;
191
211
  };
192
212
 
213
+ export type ClientSetAgentPaused = {
214
+ type: "set_agent_paused";
215
+ paused: boolean;
216
+ };
217
+
193
218
  export type ClientSetMcpServerConfig = {
194
219
  type: "set_mcp_server_config";
195
220
  server_name: string;
196
221
  config?: McpServerConfiguration;
197
222
  };
198
223
 
224
+ export type ClientShareSession = {
225
+ type: "share_session";
226
+ };
227
+
228
+ export type ClientRaceModeResult = {
229
+ type: "race_mode_result";
230
+ message_id: string;
231
+ result: string;
232
+ } & UserMessageData;
233
+
199
234
  export type ClientSessionMessageData =
200
235
  | ClientUserMessage
201
236
  | ClientSetWorkspace
@@ -206,10 +241,15 @@ export type ClientSessionMessageData =
206
241
  | ClientEnableAllMcpServerTools
207
242
  | ClientDisableAllMcpServerTools
208
243
  | ClientToolCallApprovalResult
244
+ | ClientSessionFileGetContent
245
+ | ClientSessionFileDelete
246
+ | ClientSessionFilePutContent
209
247
  | ClientSetAutoApproval
210
248
  | ClientSetSystemPrompt
211
249
  | ClientSetModel
212
- | ClientSetMcpServerConfig;
250
+ | ClientSetAgentPaused
251
+ | ClientSetMcpServerConfig
252
+ | ClientShareSession;
213
253
 
214
254
  export type ClientSessionMessage = ClientSessionMessageBase &
215
255
  ClientSessionMessageData;
@@ -288,6 +328,7 @@ export type ServerSessionInfo = {
288
328
  agent_preferences: AgentPreferences;
289
329
  client_message_id: string;
290
330
  team_uuid: string | undefined;
331
+ agent_paused: boolean;
291
332
  } & ServerSessionMessage;
292
333
 
293
334
  /**
@@ -307,6 +348,7 @@ export type ServerHistory = {
307
348
  export type ServerUserMessage = {
308
349
  type: "user_msg";
309
350
  user_uuid: string;
351
+ user_nickname: string;
310
352
  message_idx: number;
311
353
  } & UserMessageData &
312
354
  ServerSessionMessage;
@@ -321,9 +363,15 @@ export type ServerAgentMessageChunk = {
321
363
  type: "agent_msg_chunk";
322
364
  message: string;
323
365
  message_idx: number;
366
+ alternative?: string;
324
367
  end: boolean;
325
368
  } & ServerSessionMessage;
326
369
 
370
+ export type ServerReasoningChunk = {
371
+ type: "agent_reasoning_chunk";
372
+ reasoning: string;
373
+ } & ServerSessionMessage;
374
+
327
375
  //
328
376
  // Notifications
329
377
  ///
@@ -339,11 +387,6 @@ export type ServerUserLeft = {
339
387
  user_uuid: string;
340
388
  } & ServerSessionMessage;
341
389
 
342
- export type ServerSessionUpdate = {
343
- type: "session_update";
344
- title?: string;
345
- participants?: TeamParticipant[];
346
- } & ServerSessionMessage;
347
390
 
348
391
  // Note: ChatCompletionMessageToolCall contains the tool call id so we don't
349
392
  // need an extra id field.
@@ -394,7 +437,6 @@ export type ServerUserTyping = {
394
437
  export type ServerToClientNotifications =
395
438
  | ServerUserJoined
396
439
  | ServerUserLeft
397
- | ServerSessionUpdate
398
440
  | ServerToolAutoApprovalSet
399
441
  | ServerToolCall
400
442
  | ServerToolCallApprovalResult
@@ -404,14 +446,35 @@ export type ServerToClientNotifications =
404
446
  | ServerUserTyping;
405
447
 
406
448
  //
407
- // state updates
449
+ // session-file related messages
408
450
  //
409
451
 
410
- /**
411
- * A new team has been created.
412
- * The members array contains the members of the team.
413
- * The members array contains undefined for failed lookups.
414
- */
452
+ export type ServerSessionFileChanged = {
453
+ type: "session_file_changed";
454
+ descriptor: SessionFileDescriptor;
455
+ new_file: boolean;
456
+ } & ServerSessionMessage;
457
+
458
+ export type ServerSessionFileDeleted = {
459
+ type: "session_file_deleted";
460
+ name: string;
461
+ } & ServerSessionMessage;
462
+
463
+ export type ServerSessionFileContent = {
464
+ type: "session_file_content";
465
+ name: string;
466
+ data_url: string;
467
+ client_message_id: string;
468
+ } & ServerSessionMessage;
469
+
470
+ export type ServerSessionFileMessage =
471
+ | ServerSessionFileChanged
472
+ | ServerSessionFileDeleted
473
+ | ServerSessionFileContent;
474
+
475
+ //
476
+ // state updates
477
+ //
415
478
  export type ServerMcpServerAdded = {
416
479
  type: "mcp_server_added";
417
480
  server_name: string;
@@ -446,6 +509,11 @@ export type ServerModelUpdated = {
446
509
  model: string;
447
510
  } & ServerSessionMessage;
448
511
 
512
+ export type ServerAgentPaused = {
513
+ type: "agent_paused";
514
+ paused: boolean;
515
+ } & ServerSessionMessage;
516
+
449
517
  export type ServerUserAdded = {
450
518
  type: "user_added";
451
519
  user_uuid: string;
@@ -459,6 +527,12 @@ export type ServerUserRemoved = {
459
527
  user_uuid: string;
460
528
  } & ServerSessionMessage;
461
529
 
530
+ export type ServerSessionShared = {
531
+ type: "session_shared";
532
+ access_token: string;
533
+ client_message_id: string;
534
+ } & ServerSessionMessage;
535
+
462
536
  export type ServerToClientStateUpdate =
463
537
  | ServerMcpServerAdded
464
538
  | ServerMcpServerRemoved
@@ -466,8 +540,10 @@ export type ServerToClientStateUpdate =
466
540
  | ServerMcpServerToolDisabled
467
541
  | ServerSystemPromptUpdated
468
542
  | ServerModelUpdated
543
+ | ServerAgentPaused
469
544
  | ServerUserAdded
470
- | ServerUserRemoved;
545
+ | ServerUserRemoved
546
+ | ServerSessionShared;
471
547
 
472
548
  //
473
549
  // actions
@@ -523,12 +599,21 @@ export type ServerControlTeamCreated = {
523
599
  failed_lookups: Array<string>;
524
600
  };
525
601
 
602
+ /**
603
+ * Team members have been updated (added or removed).
604
+ */
605
+ export type ServerControlTeamMembersUpdated = {
606
+ type: "control_team_members_updated";
607
+ team_uuid: string;
608
+ members: Array<TeamParticipant>;
609
+ };
610
+
526
611
  /**
527
612
  * List of available sessions for user
528
613
  */
529
614
  export type ServerControlSessionList = {
530
615
  type: "control_session_list";
531
- user_sessions: Array<SessionData>;
616
+ user_sessions: Array<SessionDescriptor>;
532
617
  user_agents: Array<SavedAgentProfile>;
533
618
  team_sessions: Array<TeamInfo>;
534
619
  } & ControlResponseMessage;
@@ -570,6 +655,7 @@ export type ServerControlMessage =
570
655
  | ServerControlAgentProfileCreated
571
656
  | ServerControlAgentProfileDeleted
572
657
  | ServerControlTeamCreated
658
+ | ServerControlTeamMembersUpdated
573
659
  | ServerControlError;
574
660
 
575
661
  export type ServerSessionScopedMessage =
@@ -578,7 +664,9 @@ export type ServerSessionScopedMessage =
578
664
  | ServerUserMessage
579
665
  | ServerAgentMessage
580
666
  | ServerAgentMessageChunk
667
+ | ServerReasoningChunk
581
668
  | ServerToClientNotifications
669
+ | ServerSessionFileMessage
582
670
  | ServerToClientStateUpdate
583
671
  | ServerToClientActions;
584
672
 
@@ -599,6 +687,7 @@ export function isServerControlMessage(
599
687
  case "control_session_left":
600
688
  case "control_session_deleted":
601
689
  case "control_team_created":
690
+ case "control_team_members_updated":
602
691
  case "control_error":
603
692
  return true;
604
693
  default: {
@@ -608,6 +697,22 @@ export function isServerControlMessage(
608
697
  }
609
698
  }
610
699
 
700
+ export function isServerSessionFileMessage(
701
+ message: ServerToClient
702
+ ): message is ServerSessionFileMessage {
703
+ const msg = message as ServerSessionFileMessage;
704
+ switch (msg.type) {
705
+ case "session_file_changed":
706
+ case "session_file_deleted":
707
+ case "session_file_content":
708
+ return true;
709
+ default: {
710
+ const _: never = msg;
711
+ return false;
712
+ }
713
+ }
714
+ }
715
+
611
716
  /**
612
717
  * Type guard to check if a ServerToClient message is a session-scoped message
613
718
  */
@@ -621,9 +726,9 @@ export function isServerSessionScopedMessage(
621
726
  case "user_msg":
622
727
  case "agent_msg":
623
728
  case "agent_msg_chunk":
729
+ case "agent_reasoning_chunk":
624
730
  case "user_joined":
625
731
  case "user_left":
626
- case "session_update":
627
732
  case "tool_auto_approval_set":
628
733
  case "tool_call":
629
734
  case "tool_call_approval_result":
@@ -631,18 +736,24 @@ export function isServerSessionScopedMessage(
631
736
  case "authentication_started":
632
737
  case "authentication_finished":
633
738
  case "user_typing":
739
+ case "session_file_changed":
740
+ case "session_file_deleted":
741
+ case "session_file_content":
634
742
  case "mcp_server_added":
635
743
  case "mcp_server_removed":
636
744
  case "mcp_server_tool_enabled":
637
745
  case "mcp_server_tool_disabled":
638
746
  case "system_prompt_updated":
639
747
  case "model_updated":
748
+ case "agent_paused":
640
749
  case "user_added":
641
750
  case "user_removed":
642
751
  case "authenticate":
643
752
  case "approve_tool_call":
644
753
  case "render_html":
754
+ case "session_shared":
645
755
  return true;
756
+
646
757
  default: {
647
758
  const _: never = msg;
648
759
  return false;
@@ -2,13 +2,13 @@ import { strict as assert } from "assert";
2
2
 
3
3
  import { getLogger } from "@xalia/xmcp/sdk";
4
4
 
5
+ import { createUserMessage } from "../../agent/agent";
5
6
  import {
6
7
  ChatCompletionAssistantMessageParam,
7
8
  ChatCompletionMessageParam,
8
9
  ChatCompletionToolMessageParam,
9
10
  ChatCompletionUserMessageParam,
10
- createUserMessage,
11
- } from "../../agent/agent";
11
+ } from "../../agent/llm";
12
12
  import { IContextManager } from "../../agent/context";
13
13
  import {
14
14
  CompressingContextManager,
@@ -19,7 +19,6 @@ import {
19
19
  ClientUserMessage,
20
20
  ServerAgentMessage,
21
21
  ServerAgentMessageChunk,
22
- ServerSessionError,
23
22
  ServerToolCallResult,
24
23
  ServerUserMessage,
25
24
  } from "../protocol/messages";
@@ -28,16 +27,18 @@ import {
28
27
  MESSAGE_INDEX_FULL_INCREMENT,
29
28
  MESSAGE_INDEX_SUB_INCREMENT,
30
29
  chatMessagesToSessionMessages,
31
- sessionMessagesToChatMessages,
30
+ sessionMessagesToConversationMessages,
32
31
  sessionMessagesToNextIndex,
33
32
  } from "./conversation";
34
33
  import {
35
34
  ISessionFileManager,
36
35
  ISessionFileManagerEventHandler,
37
- SessionFileDescriptor,
38
- SessionFileEntry,
39
36
  listFilesForLLM,
40
37
  } from "./sessionFileManager";
38
+ import {
39
+ SessionFileDescriptor,
40
+ SessionFileEntry,
41
+ } from "../data/dbSessionFileModels";
41
42
 
42
43
  const logger = getLogger();
43
44
 
@@ -115,7 +116,7 @@ export class ChatContextManager
115
116
  // Insert a system message placeholder into the context
116
117
 
117
118
  this.sessionUUID = sessionUUID;
118
- this.conversationMessages = sessionMessagesToChatMessages(
119
+ this.conversationMessages = sessionMessagesToConversationMessages(
119
120
  sessionMessages,
120
121
  defaultUserName,
121
122
  sessionUUID
@@ -135,7 +136,7 @@ export class ChatContextManager
135
136
  this.pendingCompression = false;
136
137
  this.checkpointWriter = checkpointWriter;
137
138
  this.fileManager = fileManager;
138
- fileManager.setEventHandler(this);
139
+ fileManager.addEventHandler(this);
139
140
  this.fileManagerDescriptionsDirty = true;
140
141
  }
141
142
 
@@ -188,7 +189,11 @@ export class ChatContextManager
188
189
  }
189
190
 
190
191
  // ISessionFileManagerEventHandler.onFileChange
191
- onFileChange(_entry: SessionFileEntry): void {
192
+ onFileChanged(_entry: SessionFileEntry): void {
193
+ this.fileManagerDescriptionsDirty = true;
194
+ }
195
+
196
+ onFileDeleted(_name: string): void {
192
197
  this.fileManagerDescriptionsDirty = true;
193
198
  }
194
199
 
@@ -205,17 +210,27 @@ export class ChatContextManager
205
210
  return this.conversationMessages.concat(this.pendingUserMessages);
206
211
  }
207
212
 
208
- processUserMessage(msg: ClientUserMessage, from: string): ServerUserMessage {
213
+ processUserMessage(
214
+ msg: ClientUserMessage,
215
+ from_uuid: string,
216
+ from_nickname: string
217
+ ): ServerUserMessage | undefined {
209
218
  // TODO: maintain a queue internally instead of relying on the caller to
210
219
  // pass in our generated messages back into `startAgentResponse`.
211
220
 
221
+ // Filter out null messages immediately.
222
+ if (!msg.imageB64 && !msg.message) {
223
+ return undefined;
224
+ }
225
+
212
226
  const message_idx = this.getNextMessageIdx();
213
227
  const userMessage: ServerUserMessage = {
214
228
  type: "user_msg",
215
229
  session_id: this.sessionUUID,
216
230
  message_idx,
217
231
  message: msg.message,
218
- user_uuid: from,
232
+ user_uuid: from_uuid,
233
+ user_nickname: from_nickname,
219
234
  };
220
235
  if (msg.imageB64) {
221
236
  userMessage.imageB64 = msg.imageB64;
@@ -274,7 +289,7 @@ export class ChatContextManager
274
289
  const userMsg = createUserMessage(
275
290
  msg.message,
276
291
  msg.imageB64,
277
- msg.user_uuid
292
+ msg.user_nickname
278
293
  );
279
294
  if (userMsg) {
280
295
  llmUserMessages.push(userMsg);
@@ -294,12 +309,21 @@ export class ChatContextManager
294
309
  }
295
310
 
296
311
  endAgentResponse(): SessionMessage[] {
297
- assert(typeof this.startingLLMContextLength !== "undefined");
298
- assert(typeof this.pendingMessages !== "undefined");
299
- assert(typeof this.curAgentMsgIdx !== "undefined");
312
+ assert(
313
+ typeof this.startingLLMContextLength !== "undefined",
314
+ "agent response not started (startingLLMContextLength)"
315
+ );
316
+ assert(
317
+ typeof this.pendingMessages !== "undefined",
318
+ "agent response not started (pendingMessages)"
319
+ );
320
+ assert(
321
+ typeof this.curAgentMsgIdx !== "undefined",
322
+ "agent response not started (curAgentMsgIdx)"
323
+ );
300
324
 
301
325
  const numPending = this.pendingMessages.length;
302
- assert(numPending > 1); // 1 user + 1 agent message
326
+ assert(numPending > 0, "no pending"); // at least 1 user message
303
327
 
304
328
  // Compute DB messages
305
329
 
@@ -343,7 +367,7 @@ export class ChatContextManager
343
367
  if (JSON.stringify(sMsg.content) !== JSON.stringify(lMsg)) {
344
368
  messageListError(
345
369
  `newSessionMessages[${String(i)}].content !== ` +
346
- `newLLMMessages[${String(i)}].content`
370
+ `newLLMMessages[${String(i)}]`
347
371
  );
348
372
  }
349
373
  if (sMsg.message_idx !== pMsg.message_idx) {
@@ -376,7 +400,7 @@ export class ChatContextManager
376
400
  * This function checks that nothing has been entered into the LLM context,
377
401
  * and drops any new user messages or responses before the error.
378
402
  */
379
- revertAgentResponse(errMsg: string): ServerSessionError {
403
+ revertAgentResponse(errMsg: string): void {
380
404
  logger.warn(`[ChatContextManager.revertAgentResponse] error: ${errMsg}`);
381
405
 
382
406
  assert(typeof this.startingLLMContextLength !== "undefined");
@@ -402,12 +426,6 @@ export class ChatContextManager
402
426
  this.startingLLMContextLength = undefined;
403
427
  this.pendingMessages = undefined;
404
428
  this.curAgentMsgIdx = undefined;
405
-
406
- return {
407
- type: "session_error",
408
- session_id: this.sessionUUID,
409
- message: errMsg,
410
- };
411
429
  }
412
430
 
413
431
  processAgentMessage(msg: string, end: boolean): ServerAgentMessageChunk {
@@ -43,7 +43,6 @@ describe("ConnectionManager", () => {
43
43
  // we need to use type assertion
44
44
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
45
45
  connectionManager = new (ConnectionManager as any)(
46
- mockApiKeyManager.mock,
47
46
  mockSessionRegistry.mock
48
47
  );
49
48
  });
@@ -63,7 +62,7 @@ describe("ConnectionManager", () => {
63
62
  // Wait for deferred send
64
63
  await new Promise((resolve) => setImmediate(resolve));
65
64
 
66
- expect(mockApiKeyManager.spies.verifyApiKey).toHaveBeenCalledWith(
65
+ expect(mockSessionRegistry.spies.authenticate).toHaveBeenCalledWith(
67
66
  "valid-api-key"
68
67
  );
69
68
  expect(mockWebSocket.spies.send).toHaveBeenCalledWith(
@@ -118,6 +117,7 @@ describe("ConnectionManager", () => {
118
117
  d: {
119
118
  type: "user_msg",
120
119
  user_uuid: "user_1",
120
+ user_nickname: "User 1",
121
121
  session_id: "session_1",
122
122
  message: "message text",
123
123
  message_idx: 12,
@@ -136,18 +136,6 @@ describe("ConnectionManager", () => {
136
136
  JSON.stringify(testMessage)
137
137
  );
138
138
  });
139
-
140
- it("should return API key for connected user", () => {
141
- const apiKey = connectionManager.getLiveUserApiKey(MOCK_USERS.owner.uuid);
142
- expect(apiKey).toBe("valid-api-key");
143
- });
144
-
145
- it("should return undefined for non-existent user", () => {
146
- const apiKey = connectionManager.getLiveUserApiKey(
147
- MOCK_USERS.nonExistent.uuid
148
- );
149
- expect(apiKey).toBeUndefined();
150
- });
151
139
  });
152
140
 
153
141
  describe("connection cleanup", () => {
@@ -169,10 +157,6 @@ describe("ConnectionManager", () => {
169
157
  const closeHandler = closeHandlerCall[1];
170
158
  closeHandler();
171
159
  }
172
-
173
- // After cleanup, API key should no longer be available
174
- const apiKey = connectionManager.getLiveUserApiKey(MOCK_USERS.owner.uuid);
175
- expect(apiKey).toBeUndefined();
176
160
  });
177
161
 
178
162
  it("should clean up connection state on error", () => {
@@ -186,10 +170,6 @@ describe("ConnectionManager", () => {
186
170
  const errorHandler = errorHandlerCall[1];
187
171
  errorHandler(new Error("WebSocket error"));
188
172
  }
189
-
190
- // After cleanup, API key should no longer be available
191
- const apiKey = connectionManager.getLiveUserApiKey(MOCK_USERS.owner.uuid);
192
- expect(apiKey).toBeUndefined();
193
173
  });
194
174
  });
195
175