@multiplayer-app/ai-agent-node 0.1.0-beta.4 → 0.1.0-beta.41
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/cjs/config.cjs +88 -38
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/config.d.ts +57 -23
- package/dist/cjs/config.d.ts.map +1 -1
- package/dist/cjs/helpers/AIHelper.cjs +160 -101
- package/dist/cjs/helpers/AIHelper.cjs.map +1 -1
- package/dist/cjs/helpers/AIHelper.d.ts +21 -13
- package/dist/cjs/helpers/AIHelper.d.ts.map +1 -1
- package/dist/cjs/helpers/AIHelper.test.cjs +22 -15
- package/dist/cjs/helpers/AIHelper.test.cjs.map +1 -1
- package/dist/cjs/helpers/ConfigHelper.cjs +19 -11
- package/dist/cjs/helpers/ConfigHelper.cjs.map +1 -1
- package/dist/cjs/helpers/ConfigHelper.d.ts.map +1 -1
- package/dist/cjs/helpers/ContextLimiter.cjs +2 -3
- package/dist/cjs/helpers/ContextLimiter.cjs.map +1 -1
- package/dist/cjs/helpers/FileHelper.cjs +132 -154
- package/dist/cjs/helpers/FileHelper.cjs.map +1 -1
- package/dist/cjs/helpers/FileHelper.d.ts +19 -25
- package/dist/cjs/helpers/FileHelper.d.ts.map +1 -1
- package/dist/cjs/helpers/index.cjs +4 -5
- package/dist/cjs/helpers/index.cjs.map +1 -1
- package/dist/cjs/helpers/index.d.ts +4 -5
- package/dist/cjs/helpers/index.d.ts.map +1 -1
- package/dist/cjs/index.cjs +118 -31
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +42 -13
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/libs/index.cjs +2 -3
- package/dist/cjs/libs/index.cjs.map +1 -1
- package/dist/cjs/libs/index.d.ts +2 -3
- package/dist/cjs/libs/index.d.ts.map +1 -1
- package/dist/cjs/libs/logger/index.cjs +5 -5
- package/dist/cjs/libs/logger/index.cjs.map +1 -1
- package/dist/cjs/libs/logger/index.d.ts +2 -2
- package/dist/cjs/libs/logger/index.d.ts.map +1 -1
- package/dist/cjs/libs/logger/kafkajs-logger-creator.cjs +2 -2
- package/dist/cjs/libs/logger/kafkajs-logger-creator.cjs.map +1 -1
- package/dist/cjs/libs/s3/index.cjs +3 -39
- package/dist/cjs/libs/s3/index.cjs.map +1 -1
- package/dist/cjs/libs/s3/index.d.ts +1 -2
- package/dist/cjs/libs/s3/index.d.ts.map +1 -1
- package/dist/cjs/libs/s3/s3.lib.cjs +174 -191
- package/dist/cjs/libs/s3/s3.lib.cjs.map +1 -1
- package/dist/cjs/libs/s3/s3.lib.d.ts +29 -22
- package/dist/cjs/libs/s3/s3.lib.d.ts.map +1 -1
- package/dist/cjs/processors/ActivityProcessor.cjs +36 -0
- package/dist/cjs/processors/ActivityProcessor.cjs.map +1 -0
- package/dist/cjs/processors/ActivityProcessor.d.ts +27 -0
- package/dist/cjs/processors/ActivityProcessor.d.ts.map +1 -0
- package/dist/cjs/processors/ActivityProcessor.test.cjs +84 -0
- package/dist/cjs/processors/ActivityProcessor.test.cjs.map +1 -0
- package/dist/cjs/processors/ActivityProcessor.test.d.ts +2 -0
- package/dist/cjs/processors/ActivityProcessor.test.d.ts.map +1 -0
- package/dist/cjs/processors/ChatProcessor.cjs +335 -163
- package/dist/cjs/processors/ChatProcessor.cjs.map +1 -1
- package/dist/cjs/processors/ChatProcessor.d.ts +56 -9
- package/dist/cjs/processors/ChatProcessor.d.ts.map +1 -1
- package/dist/cjs/processors/ChatProcessor.test.cjs +450 -0
- package/dist/cjs/processors/ChatProcessor.test.cjs.map +1 -0
- package/dist/cjs/processors/ChatProcessor.test.d.ts +2 -0
- package/dist/cjs/processors/ChatProcessor.test.d.ts.map +1 -0
- package/dist/cjs/processors/ModelsProcessor.cjs +2 -2
- package/dist/cjs/processors/ModelsProcessor.cjs.map +1 -1
- package/dist/cjs/processors/index.cjs +3 -2
- package/dist/cjs/processors/index.cjs.map +1 -1
- package/dist/cjs/processors/index.d.ts +3 -2
- package/dist/cjs/processors/index.d.ts.map +1 -1
- package/dist/cjs/services/AIService.cjs +50 -31
- package/dist/cjs/services/AIService.cjs.map +1 -1
- package/dist/cjs/services/AIService.d.ts +16 -5
- package/dist/cjs/services/AIService.d.ts.map +1 -1
- package/dist/cjs/services/InternalEventsHandler.cjs +5 -5
- package/dist/cjs/services/InternalEventsHandler.cjs.map +1 -1
- package/dist/cjs/services/InternalEventsHandler.d.ts +3 -1
- package/dist/cjs/services/InternalEventsHandler.d.ts.map +1 -1
- package/dist/cjs/services/ModelFetcher.cjs +9 -15
- package/dist/cjs/services/ModelFetcher.cjs.map +1 -1
- package/dist/cjs/services/ModelFetcher.d.ts +2 -7
- package/dist/cjs/services/ModelFetcher.d.ts.map +1 -1
- package/dist/cjs/services/RedisService.cjs +35 -32
- package/dist/cjs/services/RedisService.cjs.map +1 -1
- package/dist/cjs/services/RedisService.d.ts +5 -2
- package/dist/cjs/services/RedisService.d.ts.map +1 -1
- package/dist/cjs/services/SocketService.cjs +19 -20
- package/dist/cjs/services/SocketService.cjs.map +1 -1
- package/dist/cjs/services/SocketService.d.ts +9 -6
- package/dist/cjs/services/SocketService.d.ts.map +1 -1
- package/dist/cjs/services/index.cjs +5 -6
- package/dist/cjs/services/index.cjs.map +1 -1
- package/dist/cjs/services/index.d.ts +5 -6
- package/dist/cjs/services/index.d.ts.map +1 -1
- package/dist/cjs/store/AgentStore.cjs +4 -5
- package/dist/cjs/store/AgentStore.cjs.map +1 -1
- package/dist/cjs/store/AgentStore.d.ts +2 -1
- package/dist/cjs/store/AgentStore.d.ts.map +1 -1
- package/dist/cjs/store/ArtifactStore.cjs +2 -4
- package/dist/cjs/store/ArtifactStore.cjs.map +1 -1
- package/dist/cjs/store/ConfigStore.cjs +8 -11
- package/dist/cjs/store/ConfigStore.cjs.map +1 -1
- package/dist/cjs/store/ConfigStore.d.ts.map +1 -1
- package/dist/cjs/store/ConfigStore.test.cjs +2 -2
- package/dist/cjs/store/ConfigStore.test.cjs.map +1 -1
- package/dist/cjs/store/ModelStore.cjs +4 -4
- package/dist/cjs/store/ModelStore.cjs.map +1 -1
- package/dist/cjs/store/ModelStore.test.cjs +17 -17
- package/dist/cjs/store/ModelStore.test.cjs.map +1 -1
- package/dist/cjs/store/index.cjs +4 -4
- package/dist/cjs/store/index.cjs.map +1 -1
- package/dist/cjs/store/index.d.ts +4 -4
- package/dist/cjs/store/index.d.ts.map +1 -1
- package/dist/cjs/tools/proposeFormValuesTool.d.ts +2 -2
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/esm/config.d.ts +57 -23
- package/dist/esm/config.d.ts.map +1 -1
- package/dist/esm/config.js +88 -36
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/helpers/AIHelper.d.ts +21 -13
- package/dist/esm/helpers/AIHelper.d.ts.map +1 -1
- package/dist/esm/helpers/AIHelper.js +159 -98
- package/dist/esm/helpers/AIHelper.js.map +1 -1
- package/dist/esm/helpers/AIHelper.test.js +21 -14
- package/dist/esm/helpers/AIHelper.test.js.map +1 -1
- package/dist/esm/helpers/ConfigHelper.d.ts.map +1 -1
- package/dist/esm/helpers/ConfigHelper.js +17 -9
- package/dist/esm/helpers/ConfigHelper.js.map +1 -1
- package/dist/esm/helpers/ContextLimiter.js +2 -3
- package/dist/esm/helpers/ContextLimiter.js.map +1 -1
- package/dist/esm/helpers/FileHelper.d.ts +19 -25
- package/dist/esm/helpers/FileHelper.d.ts.map +1 -1
- package/dist/esm/helpers/FileHelper.js +132 -149
- package/dist/esm/helpers/FileHelper.js.map +1 -1
- package/dist/esm/helpers/index.d.ts +4 -5
- package/dist/esm/helpers/index.d.ts.map +1 -1
- package/dist/esm/helpers/index.js +4 -5
- package/dist/esm/helpers/index.js.map +1 -1
- package/dist/esm/index.d.ts +42 -13
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +87 -12
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/libs/index.d.ts +2 -3
- package/dist/esm/libs/index.d.ts.map +1 -1
- package/dist/esm/libs/index.js +2 -3
- package/dist/esm/libs/index.js.map +1 -1
- package/dist/esm/libs/logger/index.d.ts +2 -2
- package/dist/esm/libs/logger/index.d.ts.map +1 -1
- package/dist/esm/libs/logger/index.js +2 -2
- package/dist/esm/libs/logger/index.js.map +1 -1
- package/dist/esm/libs/logger/kafkajs-logger-creator.js +1 -1
- package/dist/esm/libs/logger/kafkajs-logger-creator.js.map +1 -1
- package/dist/esm/libs/s3/index.d.ts +1 -2
- package/dist/esm/libs/s3/index.d.ts.map +1 -1
- package/dist/esm/libs/s3/index.js +1 -2
- package/dist/esm/libs/s3/index.js.map +1 -1
- package/dist/esm/libs/s3/s3.lib.d.ts +29 -22
- package/dist/esm/libs/s3/s3.lib.d.ts.map +1 -1
- package/dist/esm/libs/s3/s3.lib.js +178 -177
- package/dist/esm/libs/s3/s3.lib.js.map +1 -1
- package/dist/esm/processors/ActivityProcessor.d.ts +27 -0
- package/dist/esm/processors/ActivityProcessor.d.ts.map +1 -0
- package/dist/esm/processors/ActivityProcessor.js +33 -0
- package/dist/esm/processors/ActivityProcessor.js.map +1 -0
- package/dist/esm/processors/ActivityProcessor.test.d.ts +2 -0
- package/dist/esm/processors/ActivityProcessor.test.d.ts.map +1 -0
- package/dist/esm/processors/ActivityProcessor.test.js +82 -0
- package/dist/esm/processors/ActivityProcessor.test.js.map +1 -0
- package/dist/esm/processors/ChatProcessor.d.ts +56 -9
- package/dist/esm/processors/ChatProcessor.d.ts.map +1 -1
- package/dist/esm/processors/ChatProcessor.js +334 -153
- package/dist/esm/processors/ChatProcessor.js.map +1 -1
- package/dist/esm/processors/ChatProcessor.test.d.ts +2 -0
- package/dist/esm/processors/ChatProcessor.test.d.ts.map +1 -0
- package/dist/esm/processors/ChatProcessor.test.js +448 -0
- package/dist/esm/processors/ChatProcessor.test.js.map +1 -0
- package/dist/esm/processors/ModelsProcessor.js +1 -1
- package/dist/esm/processors/ModelsProcessor.js.map +1 -1
- package/dist/esm/processors/index.d.ts +3 -2
- package/dist/esm/processors/index.d.ts.map +1 -1
- package/dist/esm/processors/index.js +3 -2
- package/dist/esm/processors/index.js.map +1 -1
- package/dist/esm/services/AIService.d.ts +16 -5
- package/dist/esm/services/AIService.d.ts.map +1 -1
- package/dist/esm/services/AIService.js +53 -32
- package/dist/esm/services/AIService.js.map +1 -1
- package/dist/esm/services/InternalEventsHandler.d.ts +3 -1
- package/dist/esm/services/InternalEventsHandler.d.ts.map +1 -1
- package/dist/esm/services/InternalEventsHandler.js +10 -8
- package/dist/esm/services/InternalEventsHandler.js.map +1 -1
- package/dist/esm/services/ModelFetcher.d.ts +2 -7
- package/dist/esm/services/ModelFetcher.d.ts.map +1 -1
- package/dist/esm/services/ModelFetcher.js +4 -9
- package/dist/esm/services/ModelFetcher.js.map +1 -1
- package/dist/esm/services/RedisService.d.ts +5 -2
- package/dist/esm/services/RedisService.d.ts.map +1 -1
- package/dist/esm/services/RedisService.js +25 -21
- package/dist/esm/services/RedisService.js.map +1 -1
- package/dist/esm/services/SocketService.d.ts +9 -6
- package/dist/esm/services/SocketService.d.ts.map +1 -1
- package/dist/esm/services/SocketService.js +15 -13
- package/dist/esm/services/SocketService.js.map +1 -1
- package/dist/esm/services/index.d.ts +5 -6
- package/dist/esm/services/index.d.ts.map +1 -1
- package/dist/esm/services/index.js +5 -6
- package/dist/esm/services/index.js.map +1 -1
- package/dist/esm/store/AgentStore.d.ts +2 -1
- package/dist/esm/store/AgentStore.d.ts.map +1 -1
- package/dist/esm/store/AgentStore.js +5 -5
- package/dist/esm/store/AgentStore.js.map +1 -1
- package/dist/esm/store/ArtifactStore.js +3 -7
- package/dist/esm/store/ArtifactStore.js.map +1 -1
- package/dist/esm/store/ConfigStore.d.ts.map +1 -1
- package/dist/esm/store/ConfigStore.js +16 -19
- package/dist/esm/store/ConfigStore.js.map +1 -1
- package/dist/esm/store/ConfigStore.test.js +1 -1
- package/dist/esm/store/ConfigStore.test.js.map +1 -1
- package/dist/esm/store/ModelStore.js +6 -6
- package/dist/esm/store/ModelStore.js.map +1 -1
- package/dist/esm/store/ModelStore.test.js +12 -12
- package/dist/esm/store/ModelStore.test.js.map +1 -1
- package/dist/esm/store/index.d.ts +4 -4
- package/dist/esm/store/index.d.ts.map +1 -1
- package/dist/esm/store/index.js +4 -4
- package/dist/esm/store/index.js.map +1 -1
- package/dist/esm/tools/proposeFormValuesTool.d.ts +2 -2
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -0
- package/package.json +15 -15
- package/dist/cjs/helpers/SetupHelper.cjs +0 -37
- package/dist/cjs/helpers/SetupHelper.cjs.map +0 -1
- package/dist/cjs/helpers/SetupHelper.d.ts +0 -5
- package/dist/cjs/helpers/SetupHelper.d.ts.map +0 -1
- package/dist/cjs/libs/kafka/config.cjs +0 -8
- package/dist/cjs/libs/kafka/config.cjs.map +0 -1
- package/dist/cjs/libs/kafka/config.d.ts +0 -5
- package/dist/cjs/libs/kafka/config.d.ts.map +0 -1
- package/dist/cjs/libs/kafka/consumer.cjs +0 -133
- package/dist/cjs/libs/kafka/consumer.cjs.map +0 -1
- package/dist/cjs/libs/kafka/consumer.d.ts +0 -16
- package/dist/cjs/libs/kafka/consumer.d.ts.map +0 -1
- package/dist/cjs/libs/kafka/index.cjs +0 -19
- package/dist/cjs/libs/kafka/index.cjs.map +0 -1
- package/dist/cjs/libs/kafka/index.d.ts +0 -3
- package/dist/cjs/libs/kafka/index.d.ts.map +0 -1
- package/dist/cjs/libs/kafka/kafka.cjs +0 -27
- package/dist/cjs/libs/kafka/kafka.cjs.map +0 -1
- package/dist/cjs/libs/kafka/kafka.d.ts +0 -3
- package/dist/cjs/libs/kafka/kafka.d.ts.map +0 -1
- package/dist/cjs/libs/kafka/producer.cjs +0 -48
- package/dist/cjs/libs/kafka/producer.cjs.map +0 -1
- package/dist/cjs/libs/kafka/producer.d.ts +0 -11
- package/dist/cjs/libs/kafka/producer.d.ts.map +0 -1
- package/dist/cjs/libs/logger/config.cjs +0 -9
- package/dist/cjs/libs/logger/config.cjs.map +0 -1
- package/dist/cjs/libs/logger/config.d.ts +0 -5
- package/dist/cjs/libs/logger/config.d.ts.map +0 -1
- package/dist/cjs/libs/s3/config.cjs +0 -10
- package/dist/cjs/libs/s3/config.cjs.map +0 -1
- package/dist/cjs/libs/s3/config.d.ts +0 -7
- package/dist/cjs/libs/s3/config.d.ts.map +0 -1
- package/dist/cjs/services/KafkaService.cjs +0 -123
- package/dist/cjs/services/KafkaService.cjs.map +0 -1
- package/dist/cjs/services/KafkaService.d.ts +0 -35
- package/dist/cjs/services/KafkaService.d.ts.map +0 -1
- package/dist/esm/helpers/SetupHelper.d.ts +0 -5
- package/dist/esm/helpers/SetupHelper.d.ts.map +0 -1
- package/dist/esm/helpers/SetupHelper.js +0 -32
- package/dist/esm/helpers/SetupHelper.js.map +0 -1
- package/dist/esm/libs/kafka/config.d.ts +0 -5
- package/dist/esm/libs/kafka/config.d.ts.map +0 -1
- package/dist/esm/libs/kafka/config.js +0 -5
- package/dist/esm/libs/kafka/config.js.map +0 -1
- package/dist/esm/libs/kafka/consumer.d.ts +0 -16
- package/dist/esm/libs/kafka/consumer.d.ts.map +0 -1
- package/dist/esm/libs/kafka/consumer.js +0 -126
- package/dist/esm/libs/kafka/consumer.js.map +0 -1
- package/dist/esm/libs/kafka/index.d.ts +0 -3
- package/dist/esm/libs/kafka/index.d.ts.map +0 -1
- package/dist/esm/libs/kafka/index.js +0 -3
- package/dist/esm/libs/kafka/index.js.map +0 -1
- package/dist/esm/libs/kafka/kafka.d.ts +0 -3
- package/dist/esm/libs/kafka/kafka.d.ts.map +0 -1
- package/dist/esm/libs/kafka/kafka.js +0 -24
- package/dist/esm/libs/kafka/kafka.js.map +0 -1
- package/dist/esm/libs/kafka/producer.d.ts +0 -11
- package/dist/esm/libs/kafka/producer.d.ts.map +0 -1
- package/dist/esm/libs/kafka/producer.js +0 -44
- package/dist/esm/libs/kafka/producer.js.map +0 -1
- package/dist/esm/libs/logger/config.d.ts +0 -5
- package/dist/esm/libs/logger/config.d.ts.map +0 -1
- package/dist/esm/libs/logger/config.js +0 -6
- package/dist/esm/libs/logger/config.js.map +0 -1
- package/dist/esm/libs/s3/config.d.ts +0 -7
- package/dist/esm/libs/s3/config.d.ts.map +0 -1
- package/dist/esm/libs/s3/config.js +0 -7
- package/dist/esm/libs/s3/config.js.map +0 -1
- package/dist/esm/services/KafkaService.d.ts +0 -35
- package/dist/esm/services/KafkaService.d.ts.map +0 -1
- package/dist/esm/services/KafkaService.js +0 -120
- package/dist/esm/services/KafkaService.js.map +0 -1
- package/dist/tsconfig.cjs.tsbuildinfo +0 -1
- package/dist/tsconfig.esm.tsbuildinfo +0 -1
|
@@ -1,65 +1,192 @@
|
|
|
1
|
-
import { AgentStatus, AgentToolCallStatus, ChatType, MessageRole, SortOrder, StreamChunkType } from '@multiplayer-app/ai-agent-types';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { config } from '../config.js';
|
|
8
|
-
import { PassThrough, pipeline } from 'stream';
|
|
9
|
-
import { promisify } from 'util';
|
|
10
|
-
import { logger } from '../libs/logger/index.js';
|
|
11
|
-
const pipelineAsync = promisify(pipeline);
|
|
1
|
+
import { AgentStatus, AgentToolCallStatus, ChatType, MessageRole, SortOrder, StreamChunkType, ActivityOperationName } from '@multiplayer-app/ai-agent-types';
|
|
2
|
+
import { AIHelper, FileHelper } from '../helpers';
|
|
3
|
+
import { AgentProcessEventType } from '../store';
|
|
4
|
+
import { ContextLimiter } from '../helpers';
|
|
5
|
+
import { PassThrough } from 'stream';
|
|
6
|
+
import { logger } from '../libs/logger';
|
|
12
7
|
export class ChatProcessor {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
8
|
+
aiHelper;
|
|
9
|
+
chatRepository;
|
|
10
|
+
messageRepository;
|
|
11
|
+
artifactStore;
|
|
12
|
+
activityRepository;
|
|
13
|
+
config;
|
|
14
|
+
socketService;
|
|
15
|
+
agentStore;
|
|
16
|
+
debug;
|
|
17
|
+
constructor(params) {
|
|
18
|
+
this.chatRepository = params.chatRepository;
|
|
19
|
+
this.messageRepository = params.messageRepository;
|
|
20
|
+
this.artifactStore = params.artifactStore;
|
|
21
|
+
this.config = params.config;
|
|
22
|
+
this.socketService = params.socketService;
|
|
23
|
+
this.agentStore = params.agentStore;
|
|
24
|
+
this.activityRepository = params.activityRepository;
|
|
25
|
+
const fileHelper = new FileHelper(params.s3Lib, this.config);
|
|
26
|
+
this.aiHelper = new AIHelper(fileHelper, this.config);
|
|
27
|
+
this.debug = this.config.debug;
|
|
17
28
|
}
|
|
18
29
|
getTemporaryTitle(contextKey) {
|
|
19
30
|
return `${contextKey} session ${new Date().toISOString()}`;
|
|
20
31
|
}
|
|
32
|
+
isTemporaryTitle(title) {
|
|
33
|
+
// Matches pattern: "{contextKey} session {ISO_DATE_STRING}"
|
|
34
|
+
// Example: "default session 2026-01-23T10:30:45.123Z"
|
|
35
|
+
// toISOString() always includes milliseconds, so we require them
|
|
36
|
+
const pattern = /^.+ session \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
37
|
+
return pattern.test(title);
|
|
38
|
+
}
|
|
39
|
+
sanitizeProviderMetadata(providerMetadata) {
|
|
40
|
+
return this.stripReasoningMetadata(providerMetadata);
|
|
41
|
+
}
|
|
42
|
+
isPlainObject(value) {
|
|
43
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
44
|
+
}
|
|
45
|
+
mergeMissingUsageFields(target, source) {
|
|
46
|
+
for (const [key, sourceValue] of Object.entries(source)) {
|
|
47
|
+
const targetValue = target[key];
|
|
48
|
+
if (targetValue === undefined) {
|
|
49
|
+
target[key] = sourceValue;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (this.isPlainObject(targetValue) && this.isPlainObject(sourceValue)) {
|
|
53
|
+
this.mergeMissingUsageFields(targetValue, sourceValue);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
extractCostUsageFields(source) {
|
|
58
|
+
const extracted = {};
|
|
59
|
+
for (const [key, value] of Object.entries(source)) {
|
|
60
|
+
const normalizedKey = key.toLowerCase();
|
|
61
|
+
if (normalizedKey.includes('cost')) {
|
|
62
|
+
extracted[key] = value;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (this.isPlainObject(value)) {
|
|
66
|
+
const nestedCostFields = this.extractCostUsageFields(value);
|
|
67
|
+
if (Object.keys(nestedCostFields).length > 0) {
|
|
68
|
+
extracted[key] = nestedCostFields;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return extracted;
|
|
73
|
+
}
|
|
74
|
+
mergeUsageWithProviderMetadata(stepUsage, providerMetadata) {
|
|
75
|
+
const mergedUsage = this.isPlainObject(stepUsage) ? { ...stepUsage } : {};
|
|
76
|
+
let hasProviderUsage = false;
|
|
77
|
+
if (this.isPlainObject(providerMetadata)) {
|
|
78
|
+
for (const providerEntry of Object.values(providerMetadata)) {
|
|
79
|
+
if (!this.isPlainObject(providerEntry) || !this.isPlainObject(providerEntry.usage)) {
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
const providerCostUsage = this.extractCostUsageFields(providerEntry.usage);
|
|
83
|
+
if (Object.keys(providerCostUsage).length === 0) {
|
|
84
|
+
continue;
|
|
85
|
+
}
|
|
86
|
+
hasProviderUsage = true;
|
|
87
|
+
this.mergeMissingUsageFields(mergedUsage, providerCostUsage);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (this.isPlainObject(stepUsage)) {
|
|
91
|
+
return mergedUsage;
|
|
92
|
+
}
|
|
93
|
+
if (hasProviderUsage) {
|
|
94
|
+
return mergedUsage;
|
|
95
|
+
}
|
|
96
|
+
return stepUsage;
|
|
97
|
+
}
|
|
98
|
+
stripReasoningMetadata(value) {
|
|
99
|
+
if (Array.isArray(value)) {
|
|
100
|
+
return value
|
|
101
|
+
.map((entry) => this.stripReasoningMetadata(entry))
|
|
102
|
+
.filter((entry) => entry !== undefined);
|
|
103
|
+
}
|
|
104
|
+
if (!value || typeof value !== 'object') {
|
|
105
|
+
return value;
|
|
106
|
+
}
|
|
107
|
+
const record = value;
|
|
108
|
+
const entryType = record.type;
|
|
109
|
+
if (typeof entryType === 'string' && entryType.startsWith('reasoning.')) {
|
|
110
|
+
return undefined;
|
|
111
|
+
}
|
|
112
|
+
const sanitized = {};
|
|
113
|
+
for (const [key, entryValue] of Object.entries(record)) {
|
|
114
|
+
const normalizedKey = key.toLowerCase();
|
|
115
|
+
if (normalizedKey === 'reasoning_details' ||
|
|
116
|
+
normalizedKey === 'reasoningdetails' ||
|
|
117
|
+
normalizedKey === 'reasoning') {
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
const sanitizedValue = this.stripReasoningMetadata(entryValue);
|
|
121
|
+
if (sanitizedValue !== undefined) {
|
|
122
|
+
sanitized[key] = sanitizedValue;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return sanitized;
|
|
126
|
+
}
|
|
21
127
|
async listChats(params) {
|
|
22
|
-
var _a, _b;
|
|
23
128
|
// Build filter object from params
|
|
24
129
|
const filter = {};
|
|
25
|
-
if (params
|
|
130
|
+
if (params?.userId) {
|
|
26
131
|
filter.userId = params.userId;
|
|
27
132
|
}
|
|
28
|
-
if (params
|
|
133
|
+
if (params?.contextKey) {
|
|
29
134
|
filter.contextKey = params.contextKey;
|
|
30
135
|
}
|
|
31
|
-
// Build query options for sort and limit with defaults
|
|
136
|
+
// Build query options for sort and limit with defaults.
|
|
32
137
|
const options = {
|
|
33
138
|
sort: {
|
|
34
|
-
field:
|
|
35
|
-
order:
|
|
139
|
+
field: params?.sortField ?? 'updatedAt',
|
|
140
|
+
order: params?.sortOrder ?? SortOrder.Desc
|
|
36
141
|
},
|
|
37
|
-
|
|
142
|
+
skip: params?.skip,
|
|
143
|
+
limit: params?.limit
|
|
144
|
+
};
|
|
145
|
+
const [total, data] = await Promise.all([
|
|
146
|
+
this.chatRepository.count(filter),
|
|
147
|
+
this.chatRepository.find(filter, options)
|
|
148
|
+
]);
|
|
149
|
+
return {
|
|
150
|
+
cursor: {
|
|
151
|
+
...(params?.skip != null ? { skip: params.skip } : {}),
|
|
152
|
+
...(params?.limit != null ? { limit: params.limit } : {}),
|
|
153
|
+
total
|
|
154
|
+
},
|
|
155
|
+
data
|
|
38
156
|
};
|
|
39
|
-
// Use aggregation to fetch chats with related messages
|
|
40
|
-
return this.chatRepository.findWithMessages(filter, options);
|
|
41
157
|
}
|
|
42
158
|
async getChat(chatId) {
|
|
43
159
|
const chat = await this.chatRepository.findById(chatId);
|
|
44
160
|
if (!chat) {
|
|
45
161
|
throw new Error('Chat not found');
|
|
46
162
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
163
|
+
return chat;
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Get messages for a chat with optional cursor pagination.
|
|
167
|
+
* When limit is omitted, returns all messages (backward compatible).
|
|
168
|
+
* Messages are returned in chronological order (oldest → newest).
|
|
169
|
+
*/
|
|
170
|
+
async getMessages(chatId, options) {
|
|
171
|
+
const chat = await this.chatRepository.findById(chatId);
|
|
172
|
+
if (!chat) {
|
|
173
|
+
throw new Error('Chat not found');
|
|
174
|
+
}
|
|
175
|
+
return this.messageRepository.findByChatIdPaginated(chatId, options);
|
|
52
176
|
}
|
|
53
177
|
async deleteChat(chatId) {
|
|
54
178
|
const deleted = await this.chatRepository.delete(chatId);
|
|
55
179
|
if (!deleted) {
|
|
56
180
|
throw new Error('Chat not found');
|
|
57
181
|
}
|
|
182
|
+
await Promise.all([
|
|
183
|
+
this.messageRepository.deleteByChatId(chatId),
|
|
184
|
+
this.activityRepository.deleteByGroupId(chatId), // todo: discuss if this is needed
|
|
185
|
+
]);
|
|
58
186
|
this.artifactStore.deleteArtifacts(chatId);
|
|
59
187
|
}
|
|
60
188
|
async upsertAndGetChat(payload, excludeSocketId) {
|
|
61
|
-
|
|
62
|
-
const targetUserId = (_a = payload.userId) !== null && _a !== void 0 ? _a : 'guest';
|
|
189
|
+
const targetUserId = payload.userId ?? 'guest';
|
|
63
190
|
let chat = null;
|
|
64
191
|
if (payload.chatId) {
|
|
65
192
|
chat = await this.chatRepository.findById(payload.chatId);
|
|
@@ -91,7 +218,7 @@ export class ChatProcessor {
|
|
|
91
218
|
if (!content) {
|
|
92
219
|
return this.getTemporaryTitle(payload.contextKey);
|
|
93
220
|
}
|
|
94
|
-
return
|
|
221
|
+
return this.aiHelper.generateTitleForMessage(payload.contextKey, [{
|
|
95
222
|
role: MessageRole.User,
|
|
96
223
|
content: content
|
|
97
224
|
}]);
|
|
@@ -102,18 +229,17 @@ export class ChatProcessor {
|
|
|
102
229
|
role,
|
|
103
230
|
content: messageData.content,
|
|
104
231
|
agentName: messageData.agentName,
|
|
105
|
-
attachments: attachments
|
|
232
|
+
attachments: attachments ?? [],
|
|
106
233
|
reasoning: "",
|
|
107
234
|
toolCalls: []
|
|
108
235
|
});
|
|
109
236
|
if (chat.userId) {
|
|
110
|
-
socketService.emitMessageUpdate(chat.userId, message, excludeSocketId);
|
|
237
|
+
this.socketService.emitMessageUpdate(chat.userId, message, excludeSocketId);
|
|
111
238
|
}
|
|
112
239
|
return message;
|
|
113
240
|
}
|
|
114
241
|
async createChat(payload, excludeSocketId) {
|
|
115
|
-
|
|
116
|
-
const targetUserId = (_a = payload.userId) !== null && _a !== void 0 ? _a : 'guest';
|
|
242
|
+
const targetUserId = payload.userId ?? 'guest';
|
|
117
243
|
const contextKey = 'contextKey' in payload ? payload.contextKey : 'default';
|
|
118
244
|
const metadata = 'metadata' in payload ? payload.metadata : {};
|
|
119
245
|
const chat = await this.chatRepository.create({
|
|
@@ -125,12 +251,7 @@ export class ChatProcessor {
|
|
|
125
251
|
metadata,
|
|
126
252
|
...(payload.model ? { model: payload.model } : {})
|
|
127
253
|
});
|
|
128
|
-
|
|
129
|
-
const initialChatResponse = {
|
|
130
|
-
...chat,
|
|
131
|
-
messages: []
|
|
132
|
-
};
|
|
133
|
-
socketService.emitChatUpdate(targetUserId, initialChatResponse, excludeSocketId);
|
|
254
|
+
this.socketService.emitChatUpdate(targetUserId, chat, excludeSocketId);
|
|
134
255
|
return chat;
|
|
135
256
|
}
|
|
136
257
|
/**
|
|
@@ -138,23 +259,22 @@ export class ChatProcessor {
|
|
|
138
259
|
* This updates the message containing the tool call and optionally appends a System message.
|
|
139
260
|
*/
|
|
140
261
|
async recordToolCallAction(params) {
|
|
141
|
-
var _a, _b, _c, _d;
|
|
142
262
|
const chat = await this.chatRepository.findById(params.chatId);
|
|
143
263
|
if (!chat) {
|
|
144
264
|
throw new Error('Chat not found');
|
|
145
265
|
}
|
|
146
266
|
const messages = await this.messageRepository.findByChatId(params.chatId);
|
|
147
|
-
const message = messages.find((m) =>
|
|
267
|
+
const message = messages.find((m) => (m.toolCalls ?? []).some((c) => c.id === params.toolCallId));
|
|
148
268
|
if (!message) {
|
|
149
269
|
throw new Error('Tool call not found');
|
|
150
270
|
}
|
|
151
|
-
const toolCalls =
|
|
271
|
+
const toolCalls = message.toolCalls ?? [];
|
|
152
272
|
const target = toolCalls.find((c) => c.id === params.toolCallId);
|
|
153
273
|
if (!target) {
|
|
154
274
|
throw new Error('Tool call not found');
|
|
155
275
|
}
|
|
156
276
|
const now = new Date().toISOString();
|
|
157
|
-
const output = (
|
|
277
|
+
const output = (target.output ?? {});
|
|
158
278
|
const mp = (output['_mp'] && typeof output['_mp'] === 'object' && !Array.isArray(output['_mp']))
|
|
159
279
|
? output['_mp']
|
|
160
280
|
: {};
|
|
@@ -164,14 +284,14 @@ export class ChatProcessor {
|
|
|
164
284
|
lastAction: {
|
|
165
285
|
action: params.action,
|
|
166
286
|
at: now,
|
|
167
|
-
data:
|
|
287
|
+
data: params.data ?? {},
|
|
168
288
|
},
|
|
169
289
|
actions: [
|
|
170
290
|
...actions,
|
|
171
291
|
{
|
|
172
292
|
action: params.action,
|
|
173
293
|
at: now,
|
|
174
|
-
data:
|
|
294
|
+
data: params.data ?? {},
|
|
175
295
|
}
|
|
176
296
|
]
|
|
177
297
|
};
|
|
@@ -186,7 +306,7 @@ export class ChatProcessor {
|
|
|
186
306
|
await this.messageRepository.update(message.id, { toolCalls });
|
|
187
307
|
// Bump chat updatedAt so listChats ordering reflects the action.
|
|
188
308
|
await this.chatRepository.update(chat.id, { updatedAt: now });
|
|
189
|
-
socketService.emitMessageUpdate(chat.userId, updatedMessage, params.excludeSocketId);
|
|
309
|
+
this.socketService.emitMessageUpdate(chat.userId, updatedMessage, params.excludeSocketId);
|
|
190
310
|
if (params.systemMessage) {
|
|
191
311
|
//todo discuss support for system messages
|
|
192
312
|
//await this.createMessage(chat, MessageRole.System, params.systemMessage, undefined, params.excludeSocketId);
|
|
@@ -194,26 +314,25 @@ export class ChatProcessor {
|
|
|
194
314
|
return { ok: true };
|
|
195
315
|
}
|
|
196
316
|
async streamMessageStep(params) {
|
|
197
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
198
317
|
const { chat, assistantMessage, existingMessages, signal, excludeSocketId, agentOptions } = params;
|
|
199
318
|
if (signal.aborted) {
|
|
200
319
|
return;
|
|
201
320
|
}
|
|
202
|
-
const result = await
|
|
321
|
+
const result = await this.aiHelper.streamAssistantResponse(existingMessages, signal, agentOptions);
|
|
203
322
|
try {
|
|
204
323
|
for await (const chunk of result.fullStream) {
|
|
205
324
|
if (chunk.type === 'error') {
|
|
206
|
-
await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Error, data: chunk.error });
|
|
325
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Error, data: chunk.error });
|
|
207
326
|
assistantMessage.content = chunk.error.message || 'Sorry, I cannot process you request due to the error';
|
|
208
327
|
await this.messageRepository.update(assistantMessage.id, assistantMessage);
|
|
209
328
|
await this.chatRepository.update(chat.id, { status: AgentStatus.Error });
|
|
210
329
|
continue;
|
|
211
330
|
}
|
|
212
331
|
if (chunk.type === 'abort') {
|
|
213
|
-
await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Aborted, data: undefined });
|
|
332
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Aborted, data: undefined });
|
|
214
333
|
await this.chatRepository.update(chat.id, { status: AgentStatus.Aborted });
|
|
215
334
|
await this.messageRepository.update(assistantMessage.id, assistantMessage);
|
|
216
|
-
socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
|
|
335
|
+
this.socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
|
|
217
336
|
continue;
|
|
218
337
|
}
|
|
219
338
|
if (chunk.type === 'finish') {
|
|
@@ -226,41 +345,44 @@ export class ChatProcessor {
|
|
|
226
345
|
}
|
|
227
346
|
if (chunk.totalUsage && typeof chunk.totalUsage === 'object') {
|
|
228
347
|
const totalUsage = chunk.totalUsage;
|
|
229
|
-
assistantMessage.tokens =
|
|
348
|
+
assistantMessage.tokens = totalUsage.totalTokens ??
|
|
349
|
+
((totalUsage.promptTokens ?? 0) + (totalUsage.completionTokens ?? 0));
|
|
230
350
|
}
|
|
231
351
|
await this.messageRepository.update(assistantMessage.id, { ...assistantMessage });
|
|
232
352
|
if (chunk.finishReason === 'stop') {
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
353
|
+
await this.chatRepository.update(chat.id, { status: AgentStatus.Finished });
|
|
354
|
+
if (chat.title && this.isTemporaryTitle(chat.title)) {
|
|
355
|
+
const title = await this.aiHelper.generateTitleForMessage(chat.contextKey, existingMessages.filter(m => m.role === MessageRole.User), (stepResult) => {
|
|
356
|
+
return this.storeStepActivity({
|
|
357
|
+
chat,
|
|
358
|
+
stepResult,
|
|
359
|
+
name: ActivityOperationName.TITLE_GENERATION,
|
|
360
|
+
sourceId: chat.id,
|
|
361
|
+
sourceType: 'Chat',
|
|
362
|
+
tenants: params.tenants || {},
|
|
363
|
+
});
|
|
364
|
+
});
|
|
365
|
+
await this.chatRepository.update(chat.id, { title });
|
|
366
|
+
this.socketService.emitChatUpdate(chat.userId, { ...chat, title });
|
|
244
367
|
}
|
|
245
|
-
await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Finished, data: assistantMessage });
|
|
246
|
-
continue;
|
|
247
368
|
}
|
|
248
369
|
if (chunk.finishReason === 'tool-calls') {
|
|
249
|
-
if (
|
|
370
|
+
if (assistantMessage.toolCalls?.some(toolCall => toolCall.requiresConfirmation && toolCall.approvalId && !toolCall.output)) {
|
|
250
371
|
await this.chatRepository.update(chat.id, { status: AgentStatus.WaitingForUserAction });
|
|
251
|
-
await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Finished, data: assistantMessage });
|
|
252
|
-
|
|
253
|
-
else {
|
|
254
|
-
await agentStore.shareAgentProcessEvent(chat.id, {
|
|
255
|
-
type: AgentProcessEventType.Update,
|
|
256
|
-
data: assistantMessage
|
|
257
|
-
});
|
|
258
|
-
await this.streamMessageStep(params);
|
|
372
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Finished, data: assistantMessage });
|
|
373
|
+
continue;
|
|
259
374
|
}
|
|
260
|
-
continue;
|
|
261
375
|
}
|
|
262
376
|
//todo: Handle other finish reasons // length, content, error, other, undefined
|
|
263
|
-
await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Finished, data: assistantMessage });
|
|
377
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Finished, data: assistantMessage });
|
|
378
|
+
if (assistantMessage.activity) {
|
|
379
|
+
const groupedMeta = await this.activityRepository.getGroupedMetadataByParentId(assistantMessage.activity);
|
|
380
|
+
await this.activityRepository.updateMetadata(assistantMessage.activity, {
|
|
381
|
+
usage: groupedMeta,
|
|
382
|
+
finishReason: chunk.finishReason,
|
|
383
|
+
responseTimestamp: new Date().toISOString(),
|
|
384
|
+
});
|
|
385
|
+
}
|
|
264
386
|
continue;
|
|
265
387
|
}
|
|
266
388
|
if (chunk.type === 'text-delta') {
|
|
@@ -269,8 +391,8 @@ export class ChatProcessor {
|
|
|
269
391
|
...assistantMessage,
|
|
270
392
|
content: assistantMessage.content
|
|
271
393
|
};
|
|
272
|
-
socketService.emitMessageUpdate(chat.userId, updatedMessage, excludeSocketId);
|
|
273
|
-
await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: updatedMessage });
|
|
394
|
+
this.socketService.emitMessageUpdate(chat.userId, updatedMessage, excludeSocketId);
|
|
395
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: updatedMessage });
|
|
274
396
|
await this.messageRepository.update(assistantMessage.id, { content: assistantMessage.content });
|
|
275
397
|
continue;
|
|
276
398
|
}
|
|
@@ -285,8 +407,8 @@ export class ChatProcessor {
|
|
|
285
407
|
});
|
|
286
408
|
continue;
|
|
287
409
|
}
|
|
288
|
-
if (chunk.type === 'tool-call') {
|
|
289
|
-
const toolCall =
|
|
410
|
+
if (chunk.type === 'tool-call') {
|
|
411
|
+
const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
|
|
290
412
|
if (toolCall) {
|
|
291
413
|
toolCall.status = AgentToolCallStatus.Running;
|
|
292
414
|
toolCall.input = chunk.input;
|
|
@@ -294,15 +416,15 @@ export class ChatProcessor {
|
|
|
294
416
|
continue;
|
|
295
417
|
}
|
|
296
418
|
if (chunk.type === 'tool-error') {
|
|
297
|
-
const toolCall =
|
|
419
|
+
const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
|
|
298
420
|
if (toolCall) {
|
|
299
421
|
toolCall.status = AgentToolCallStatus.Failed;
|
|
300
|
-
toolCall.error = JSON.stringify(chunk.error);
|
|
422
|
+
toolCall.error = chunk.error.message || JSON.stringify(chunk.error);
|
|
301
423
|
}
|
|
302
424
|
continue;
|
|
303
425
|
}
|
|
304
426
|
if (chunk.type === 'tool-approval-request') {
|
|
305
|
-
const toolCall =
|
|
427
|
+
const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCall.toolCallId);
|
|
306
428
|
if (toolCall) {
|
|
307
429
|
toolCall.requiresConfirmation = true;
|
|
308
430
|
toolCall.approvalId = chunk.approvalId;
|
|
@@ -310,7 +432,7 @@ export class ChatProcessor {
|
|
|
310
432
|
continue;
|
|
311
433
|
}
|
|
312
434
|
if (chunk.type === 'tool-result') {
|
|
313
|
-
const toolCall =
|
|
435
|
+
const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
|
|
314
436
|
if (toolCall) {
|
|
315
437
|
if (chunk.output.requiresApproval) {
|
|
316
438
|
toolCall.requiresConfirmation = true;
|
|
@@ -325,9 +447,9 @@ export class ChatProcessor {
|
|
|
325
447
|
if (!assistantMessage.reasoning)
|
|
326
448
|
assistantMessage.reasoning = '';
|
|
327
449
|
assistantMessage.reasoning += chunk.text;
|
|
328
|
-
socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
|
|
450
|
+
this.socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
|
|
329
451
|
await this.messageRepository.update(assistantMessage.id, { reasoning: assistantMessage.reasoning });
|
|
330
|
-
await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: assistantMessage });
|
|
452
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: assistantMessage });
|
|
331
453
|
continue;
|
|
332
454
|
}
|
|
333
455
|
}
|
|
@@ -336,7 +458,7 @@ export class ChatProcessor {
|
|
|
336
458
|
if (streamError instanceof Error && streamError.name === 'AbortError') {
|
|
337
459
|
return;
|
|
338
460
|
}
|
|
339
|
-
await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Error, data: streamError });
|
|
461
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Error, data: streamError });
|
|
340
462
|
throw streamError;
|
|
341
463
|
}
|
|
342
464
|
}
|
|
@@ -344,16 +466,15 @@ export class ChatProcessor {
|
|
|
344
466
|
return 'approvalId' in payload;
|
|
345
467
|
}
|
|
346
468
|
async processApprovalPayload(chat, payload) {
|
|
347
|
-
var _a, _b, _c;
|
|
348
469
|
const assistantMessage = await this.messageRepository.findById(payload.messageId);
|
|
349
470
|
if (!assistantMessage || assistantMessage.chat !== chat.id) {
|
|
350
471
|
throw new Error(`Assistant message with id ${payload.messageId} not found`);
|
|
351
472
|
}
|
|
352
|
-
const agentOptions = await
|
|
473
|
+
const agentOptions = await this.aiHelper.getAgentOptions({
|
|
353
474
|
agentName: assistantMessage.agentName,
|
|
354
475
|
context: payload.context
|
|
355
476
|
});
|
|
356
|
-
const toolCall =
|
|
477
|
+
const toolCall = assistantMessage.toolCalls?.find(tc => tc.approvalId === payload.approvalId);
|
|
357
478
|
if (!toolCall) {
|
|
358
479
|
// continue, tool is not found
|
|
359
480
|
return {
|
|
@@ -371,7 +492,7 @@ export class ChatProcessor {
|
|
|
371
492
|
toolCall.status = AgentToolCallStatus.Failed;
|
|
372
493
|
}
|
|
373
494
|
else {
|
|
374
|
-
const executeFunction =
|
|
495
|
+
const executeFunction = agentOptions.tools?.[toolCall.name]?.execute;
|
|
375
496
|
if (executeFunction) {
|
|
376
497
|
try {
|
|
377
498
|
toolCall.output = await executeFunction(toolCall.input, { toolCallId: toolCall.id, messages: [] });
|
|
@@ -402,32 +523,105 @@ export class ChatProcessor {
|
|
|
402
523
|
}
|
|
403
524
|
async processNewUserMessage(chat, payload, prevMessages, excludeSocketId) {
|
|
404
525
|
const userMessage = await this.createMessage(chat, MessageRole.User, { content: payload.content, agentName: undefined }, payload.attachments);
|
|
405
|
-
await agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: userMessage });
|
|
406
|
-
|
|
526
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: AgentProcessEventType.Update, data: userMessage });
|
|
527
|
+
let assistantMessage = await this.createMessage(chat, MessageRole.Assistant, { content: '', agentName: undefined }, undefined, excludeSocketId);
|
|
528
|
+
const parentActivity = await this.activityRepository.create({
|
|
529
|
+
ownerId: chat.userId,
|
|
530
|
+
groupId: chat.id,
|
|
531
|
+
name: ActivityOperationName.MESSAGE_PROCESSING,
|
|
532
|
+
tenants: {}, //todo
|
|
533
|
+
sourceId: userMessage.id,
|
|
534
|
+
sourceType: 'AgentMessage',
|
|
535
|
+
metadata: {
|
|
536
|
+
contextKey: chat.contextKey,
|
|
537
|
+
modelId: this.aiHelper.getLanguageModelId(chat.model),
|
|
538
|
+
},
|
|
539
|
+
});
|
|
540
|
+
const agentOptions = await this.aiHelper.getAgentOptions({
|
|
407
541
|
contextKey: chat.contextKey,
|
|
408
|
-
messages:
|
|
542
|
+
messages: [...prevMessages, userMessage],
|
|
409
543
|
context: payload.context,
|
|
410
544
|
agentName: undefined,
|
|
411
545
|
modelId: chat.model,
|
|
546
|
+
}, {
|
|
547
|
+
onStepFinish: async (stepResult) => {
|
|
548
|
+
await this.storeStepActivity({
|
|
549
|
+
chat,
|
|
550
|
+
parentId: parentActivity.id,
|
|
551
|
+
stepResult,
|
|
552
|
+
name: ActivityOperationName.AGENT_SELECTION,
|
|
553
|
+
sourceId: userMessage.id,
|
|
554
|
+
sourceType: 'AgentMessage',
|
|
555
|
+
tenants: payload.tenants || {},
|
|
556
|
+
});
|
|
557
|
+
}
|
|
558
|
+
});
|
|
559
|
+
const updatedAssistantMessage = await this.messageRepository.update(assistantMessage.id, {
|
|
560
|
+
agentName: agentOptions.name,
|
|
561
|
+
activity: parentActivity.id
|
|
562
|
+
});
|
|
563
|
+
await this.activityRepository.update(parentActivity.id, {
|
|
564
|
+
metadata: {
|
|
565
|
+
...parentActivity.metadata,
|
|
566
|
+
agentOptions: {
|
|
567
|
+
name: agentOptions.name,
|
|
568
|
+
modelId: this.aiHelper.getLanguageModelId(agentOptions.model),
|
|
569
|
+
temperature: agentOptions.temperature,
|
|
570
|
+
maxOutputTokens: agentOptions.maxOutputTokens,
|
|
571
|
+
topP: agentOptions.topP,
|
|
572
|
+
topK: agentOptions.topK,
|
|
573
|
+
presencePenalty: agentOptions.presencePenalty,
|
|
574
|
+
frequencyPenalty: agentOptions.frequencyPenalty,
|
|
575
|
+
stopSequences: agentOptions.stopSequences,
|
|
576
|
+
seed: agentOptions.seed,
|
|
577
|
+
},
|
|
578
|
+
},
|
|
412
579
|
});
|
|
413
|
-
|
|
414
|
-
|
|
580
|
+
if (!updatedAssistantMessage) {
|
|
581
|
+
throw new Error(`Assistant message with id ${assistantMessage.id} not found after update`);
|
|
582
|
+
}
|
|
583
|
+
assistantMessage = updatedAssistantMessage;
|
|
415
584
|
return {
|
|
416
585
|
userMessage,
|
|
417
586
|
assistantMessage,
|
|
418
587
|
agentOptions,
|
|
419
588
|
};
|
|
420
589
|
}
|
|
590
|
+
async storeStepActivity(params) {
|
|
591
|
+
try {
|
|
592
|
+
const stepResult = params.stepResult;
|
|
593
|
+
const mergedUsage = this.mergeUsageWithProviderMetadata(stepResult.usage, stepResult.providerMetadata);
|
|
594
|
+
const activity = await this.activityRepository.create({
|
|
595
|
+
ownerId: params.chat.userId,
|
|
596
|
+
groupId: params.chat.id,
|
|
597
|
+
name: params.name,
|
|
598
|
+
tenants: params.tenants || {},
|
|
599
|
+
sourceId: params.sourceId,
|
|
600
|
+
sourceType: params.sourceType,
|
|
601
|
+
metadata: {
|
|
602
|
+
finishReason: stepResult.finishReason,
|
|
603
|
+
usage: mergedUsage,
|
|
604
|
+
responseTimestamp: stepResult.response.timestamp,
|
|
605
|
+
modelId: stepResult.response.modelId,
|
|
606
|
+
messages: this.debug ? stepResult.request?.body?.messages : undefined,
|
|
607
|
+
},
|
|
608
|
+
parentId: params.parentId,
|
|
609
|
+
});
|
|
610
|
+
}
|
|
611
|
+
catch (error) {
|
|
612
|
+
logger.error({ error, chatId: params.chat.id, parentId: params.parentId }, 'Failed to store step activity');
|
|
613
|
+
}
|
|
614
|
+
}
|
|
421
615
|
async streamMessage(chat, payload, excludeSocketId, onAgentStart) {
|
|
422
616
|
try {
|
|
423
|
-
const abortController = agentStore.registerAgentProcess(chat.id);
|
|
424
|
-
onAgentStart
|
|
617
|
+
const abortController = this.agentStore.registerAgentProcess(chat.id);
|
|
618
|
+
onAgentStart?.();
|
|
425
619
|
let assistantMessage;
|
|
426
620
|
let agentOptions;
|
|
427
621
|
const existingMessages = await this.messageRepository.findByChatId(chat.id);
|
|
428
622
|
// Limit context to prevent exceeding token limits
|
|
429
623
|
const limitedMessages = ContextLimiter.limitContext(existingMessages, {
|
|
430
|
-
maxMessages: config.ai.maxContextMessages,
|
|
624
|
+
maxMessages: this.config.ai.maxContextMessages,
|
|
431
625
|
keepFirstUserMessage: true,
|
|
432
626
|
keepSystemMessages: true,
|
|
433
627
|
});
|
|
@@ -449,6 +643,17 @@ export class ChatProcessor {
|
|
|
449
643
|
agentOptions = result.agentOptions;
|
|
450
644
|
limitedMessages.push(result.userMessage);
|
|
451
645
|
}
|
|
646
|
+
agentOptions.onStepFinish = (stepResult) => {
|
|
647
|
+
return this.storeStepActivity({
|
|
648
|
+
chat,
|
|
649
|
+
parentId: assistantMessage.activity,
|
|
650
|
+
stepResult,
|
|
651
|
+
name: ActivityOperationName.STEP_FINISHED,
|
|
652
|
+
sourceId: assistantMessage.id,
|
|
653
|
+
sourceType: 'AgentMessage',
|
|
654
|
+
tenants: payload.tenants || {},
|
|
655
|
+
});
|
|
656
|
+
};
|
|
452
657
|
await this.streamMessageStep({
|
|
453
658
|
chat,
|
|
454
659
|
existingMessages: limitedMessages,
|
|
@@ -456,6 +661,7 @@ export class ChatProcessor {
|
|
|
456
661
|
agentOptions,
|
|
457
662
|
excludeSocketId: excludeSocketId,
|
|
458
663
|
signal: abortController.signal,
|
|
664
|
+
tenants: payload.tenants || {},
|
|
459
665
|
});
|
|
460
666
|
}
|
|
461
667
|
catch (error) {
|
|
@@ -492,7 +698,7 @@ export class ChatProcessor {
|
|
|
492
698
|
return null;
|
|
493
699
|
}
|
|
494
700
|
}
|
|
495
|
-
getMessageStream(chatId) {
|
|
701
|
+
getMessageStream(chatId, signal) {
|
|
496
702
|
const stream = new PassThrough();
|
|
497
703
|
let ended = false;
|
|
498
704
|
const endStream = (error) => {
|
|
@@ -513,13 +719,15 @@ export class ChatProcessor {
|
|
|
513
719
|
}
|
|
514
720
|
};
|
|
515
721
|
const pushChunk = (chunk) => {
|
|
516
|
-
if (ended || stream.destroyed || stream.writableEnded)
|
|
722
|
+
if (ended || stream.destroyed || stream.writableEnded || signal?.aborted)
|
|
517
723
|
return;
|
|
518
724
|
stream.write(`data: ${JSON.stringify(chunk)}\n\n`);
|
|
519
725
|
};
|
|
520
726
|
const listener = (event) => {
|
|
521
|
-
if (
|
|
727
|
+
if (signal?.aborted) {
|
|
728
|
+
endStream();
|
|
522
729
|
return;
|
|
730
|
+
}
|
|
523
731
|
try {
|
|
524
732
|
const chunk = this.eventToChunk(event);
|
|
525
733
|
if (chunk) {
|
|
@@ -529,7 +737,6 @@ export class ChatProcessor {
|
|
|
529
737
|
event.type === AgentProcessEventType.Error ||
|
|
530
738
|
event.type === AgentProcessEventType.Aborted) {
|
|
531
739
|
endStream();
|
|
532
|
-
agentStore.removeListener(chatId, listener);
|
|
533
740
|
}
|
|
534
741
|
}
|
|
535
742
|
catch (err) {
|
|
@@ -538,21 +745,18 @@ export class ChatProcessor {
|
|
|
538
745
|
error: err instanceof Error ? err.message : 'Unknown error occurred',
|
|
539
746
|
});
|
|
540
747
|
endStream(err);
|
|
541
|
-
agentStore.removeListener(chatId, listener);
|
|
542
748
|
}
|
|
543
749
|
};
|
|
544
|
-
// Cleanup on consumer side closing
|
|
545
750
|
const closeHandler = () => {
|
|
546
|
-
agentStore.removeListener(chatId, listener);
|
|
751
|
+
this.agentStore.removeListener(chatId, listener);
|
|
547
752
|
};
|
|
548
753
|
const errorHandler = (err) => {
|
|
549
|
-
|
|
550
|
-
agentStore.removeListener(chatId, listener);
|
|
754
|
+
signal?.removeEventListener('abort', endStream);
|
|
551
755
|
endStream(err);
|
|
552
756
|
};
|
|
553
757
|
stream.on('close', closeHandler);
|
|
554
758
|
stream.on('error', errorHandler);
|
|
555
|
-
const listenerAttached = agentStore.addListener(chatId, listener);
|
|
759
|
+
const listenerAttached = this.agentStore.addListener(chatId, listener);
|
|
556
760
|
if (!listenerAttached) {
|
|
557
761
|
// Remove stream listeners if listener attachment failed to prevent memory leak
|
|
558
762
|
stream.removeListener('close', closeHandler);
|
|
@@ -561,50 +765,27 @@ export class ChatProcessor {
|
|
|
561
765
|
}
|
|
562
766
|
return stream;
|
|
563
767
|
}
|
|
564
|
-
async createMessageStream(payload, excludeSocketId) {
|
|
768
|
+
async createMessageStream(payload, excludeSocketId, signal) {
|
|
565
769
|
const stream = new PassThrough();
|
|
566
|
-
(
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
// Send chat metadata first
|
|
570
|
-
if (!('chatId' in payload) && !('messageId' in payload) && chat) {
|
|
571
|
-
stream.write(`data: ${JSON.stringify({
|
|
572
|
-
type: StreamChunkType.Chat,
|
|
573
|
-
chatId: chat.id,
|
|
574
|
-
chat,
|
|
575
|
-
})}\n\n`);
|
|
576
|
-
}
|
|
577
|
-
await this.streamMessage(chat, payload, excludeSocketId, async () => {
|
|
578
|
-
if (stream.destroyed || stream.writableEnded) {
|
|
579
|
-
return;
|
|
580
|
-
}
|
|
581
|
-
const messageStream = this.getMessageStream(chat.id);
|
|
582
|
-
// If client disconnects, destroy inner stream
|
|
583
|
-
stream.on('close', () => {
|
|
584
|
-
if (!messageStream.destroyed) {
|
|
585
|
-
messageStream.destroy();
|
|
586
|
-
}
|
|
587
|
-
});
|
|
588
|
-
await pipelineAsync(messageStream, stream);
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
catch (error) {
|
|
592
|
-
logger.error({ error }, 'createMessageStream failed');
|
|
593
|
-
if (!stream.destroyed && !stream.writableEnded) {
|
|
594
|
-
stream.write(`data: ${JSON.stringify({
|
|
595
|
-
type: StreamChunkType.Error,
|
|
596
|
-
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
597
|
-
})}\n\n`);
|
|
598
|
-
stream.write('data: [DONE]\n\n');
|
|
599
|
-
stream.end();
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
})().catch((err) => {
|
|
603
|
-
logger.error({ err }, 'Unhandled stream task error');
|
|
604
|
-
if (!stream.destroyed)
|
|
605
|
-
stream.destroy(err);
|
|
770
|
+
this.runMessageStream(stream, payload, excludeSocketId, signal)
|
|
771
|
+
.catch(err => {
|
|
772
|
+
logger.error({ err }, 'Stream task failed');
|
|
606
773
|
});
|
|
607
774
|
return stream;
|
|
608
775
|
}
|
|
776
|
+
async runMessageStream(stream, payload, excludeSocketId, signal) {
|
|
777
|
+
const chat = await this.upsertAndGetChat(payload, excludeSocketId);
|
|
778
|
+
if (!('chatId' in payload) && !('messageId' in payload) && chat) {
|
|
779
|
+
stream.write(`data: ${JSON.stringify({
|
|
780
|
+
type: StreamChunkType.Chat,
|
|
781
|
+
chatId: chat.id,
|
|
782
|
+
chat,
|
|
783
|
+
})}\n\n`);
|
|
784
|
+
}
|
|
785
|
+
await this.streamMessage(chat, payload, excludeSocketId, () => {
|
|
786
|
+
const messageStream = this.getMessageStream(chat.id, signal);
|
|
787
|
+
messageStream.pipe(stream);
|
|
788
|
+
});
|
|
789
|
+
}
|
|
609
790
|
}
|
|
610
791
|
//# sourceMappingURL=ChatProcessor.js.map
|