@multiplayer-app/ai-agent-node 0.1.0-beta.7 → 0.1.0-beta.70
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 +2 -2
- package/dist/cjs/config.cjs +87 -45
- package/dist/cjs/config.cjs.map +1 -1
- package/dist/cjs/config.d.ts +60 -29
- package/dist/cjs/config.d.ts.map +1 -1
- package/dist/cjs/helpers/AIHelper.cjs +127 -65
- package/dist/cjs/helpers/AIHelper.cjs.map +1 -1
- package/dist/cjs/helpers/AIHelper.d.ts +22 -16
- 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 +15 -6
- package/dist/cjs/helpers/ConfigHelper.cjs.map +1 -1
- package/dist/cjs/helpers/ConfigHelper.d.ts.map +1 -1
- package/dist/cjs/helpers/FileHelper.cjs +131 -151
- 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 +0 -1
- package/dist/cjs/helpers/index.cjs.map +1 -1
- package/dist/cjs/helpers/index.d.ts +0 -1
- package/dist/cjs/helpers/index.d.ts.map +1 -1
- package/dist/cjs/index.cjs +120 -26
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.ts +43 -10
- package/dist/cjs/index.d.ts.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 +173 -186
- 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 +39 -0
- package/dist/cjs/processors/ActivityProcessor.cjs.map +1 -0
- package/dist/cjs/processors/ActivityProcessor.d.ts +32 -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/AgentProcessor.cjs +46 -0
- package/dist/cjs/processors/AgentProcessor.cjs.map +1 -0
- package/dist/cjs/processors/AgentProcessor.d.ts +25 -0
- package/dist/cjs/processors/AgentProcessor.d.ts.map +1 -0
- package/dist/cjs/processors/AgentProcessor.test.cjs +103 -0
- package/dist/cjs/processors/AgentProcessor.test.cjs.map +1 -0
- package/dist/cjs/processors/AgentProcessor.test.d.ts +2 -0
- package/dist/cjs/processors/AgentProcessor.test.d.ts.map +1 -0
- package/dist/cjs/processors/ChatProcessor.cjs +348 -126
- package/dist/cjs/processors/ChatProcessor.cjs.map +1 -1
- package/dist/cjs/processors/ChatProcessor.d.ts +70 -11
- package/dist/cjs/processors/ChatProcessor.d.ts.map +1 -1
- package/dist/cjs/processors/ChatProcessor.test.cjs +762 -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/index.cjs +2 -0
- package/dist/cjs/processors/index.cjs.map +1 -1
- package/dist/cjs/processors/index.d.ts +2 -0
- package/dist/cjs/processors/index.d.ts.map +1 -1
- package/dist/cjs/services/AIService.cjs +87 -21
- package/dist/cjs/services/AIService.cjs.map +1 -1
- package/dist/cjs/services/AIService.d.ts +19 -7
- package/dist/cjs/services/AIService.d.ts.map +1 -1
- package/dist/cjs/services/InternalEventsHandler.cjs +3 -3
- 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 +2 -8
- 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 +20 -16
- 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 +7 -7
- 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/store/AgentStore.cjs +3 -4
- 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/ConfigStore.cjs +7 -3
- package/dist/cjs/store/ConfigStore.cjs.map +1 -1
- package/dist/cjs/store/ConfigStore.d.ts +1 -0
- package/dist/cjs/store/ConfigStore.d.ts.map +1 -1
- package/dist/cjs/tools/generateChartTool.d.ts +2 -2
- package/dist/cjs/tools/proposeFormValuesTool.d.ts +2 -2
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/config.d.ts +60 -29
- package/dist/esm/config.d.ts.map +1 -1
- package/dist/esm/config.js +87 -43
- package/dist/esm/config.js.map +1 -1
- package/dist/esm/helpers/AIHelper.d.ts +22 -16
- package/dist/esm/helpers/AIHelper.d.ts.map +1 -1
- package/dist/esm/helpers/AIHelper.js +134 -70
- package/dist/esm/helpers/AIHelper.js.map +1 -1
- package/dist/esm/helpers/AIHelper.test.js +22 -15
- 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 +15 -6
- package/dist/esm/helpers/ConfigHelper.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 +131 -146
- package/dist/esm/helpers/FileHelper.js.map +1 -1
- package/dist/esm/helpers/index.d.ts +0 -1
- package/dist/esm/helpers/index.d.ts.map +1 -1
- package/dist/esm/helpers/index.js +0 -1
- package/dist/esm/helpers/index.js.map +1 -1
- package/dist/esm/index.d.ts +43 -10
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +92 -10
- package/dist/esm/index.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 +177 -172
- package/dist/esm/libs/s3/s3.lib.js.map +1 -1
- package/dist/esm/processors/ActivityProcessor.d.ts +32 -0
- package/dist/esm/processors/ActivityProcessor.d.ts.map +1 -0
- package/dist/esm/processors/ActivityProcessor.js +36 -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/AgentProcessor.d.ts +25 -0
- package/dist/esm/processors/AgentProcessor.d.ts.map +1 -0
- package/dist/esm/processors/AgentProcessor.js +43 -0
- package/dist/esm/processors/AgentProcessor.js.map +1 -0
- package/dist/esm/processors/AgentProcessor.test.d.ts +2 -0
- package/dist/esm/processors/AgentProcessor.test.d.ts.map +1 -0
- package/dist/esm/processors/AgentProcessor.test.js +101 -0
- package/dist/esm/processors/AgentProcessor.test.js.map +1 -0
- package/dist/esm/processors/ChatProcessor.d.ts +70 -11
- package/dist/esm/processors/ChatProcessor.d.ts.map +1 -1
- package/dist/esm/processors/ChatProcessor.js +359 -130
- 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 +760 -0
- package/dist/esm/processors/ChatProcessor.test.js.map +1 -0
- package/dist/esm/processors/index.d.ts +2 -0
- package/dist/esm/processors/index.d.ts.map +1 -1
- package/dist/esm/processors/index.js +2 -0
- package/dist/esm/processors/index.js.map +1 -1
- package/dist/esm/services/AIService.d.ts +19 -7
- package/dist/esm/services/AIService.d.ts.map +1 -1
- package/dist/esm/services/AIService.js +91 -24
- 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 +4 -3
- 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 +2 -8
- 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 +21 -14
- 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 +9 -5
- package/dist/esm/services/SocketService.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 +4 -2
- package/dist/esm/store/AgentStore.js.map +1 -1
- package/dist/esm/store/ConfigStore.d.ts +1 -0
- package/dist/esm/store/ConfigStore.d.ts.map +1 -1
- package/dist/esm/store/ConfigStore.js +7 -3
- package/dist/esm/store/ConfigStore.js.map +1 -1
- package/dist/esm/tools/generateChartTool.d.ts +2 -2
- package/dist/esm/tools/proposeFormValuesTool.d.ts +2 -2
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/package.json +12 -11
- package/dist/cjs/helpers/SetupHelper.cjs +0 -34
- package/dist/cjs/helpers/SetupHelper.cjs.map +0 -1
- package/dist/cjs/helpers/SetupHelper.d.ts +0 -4
- package/dist/cjs/helpers/SetupHelper.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 -8
- package/dist/cjs/libs/s3/config.cjs.map +0 -1
- package/dist/cjs/libs/s3/config.d.ts +0 -4
- package/dist/cjs/libs/s3/config.d.ts.map +0 -1
- package/dist/esm/helpers/SetupHelper.d.ts +0 -4
- package/dist/esm/helpers/SetupHelper.d.ts.map +0 -1
- package/dist/esm/helpers/SetupHelper.js +0 -29
- package/dist/esm/helpers/SetupHelper.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 -4
- package/dist/esm/libs/s3/config.d.ts.map +0 -1
- package/dist/esm/libs/s3/config.js +0 -5
- package/dist/esm/libs/s3/config.js.map +0 -1
|
@@ -2,20 +2,26 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ChatProcessor = void 0;
|
|
4
4
|
const ai_agent_types_1 = require("@multiplayer-app/ai-agent-types");
|
|
5
|
-
const
|
|
5
|
+
const zod_1 = require("zod");
|
|
6
6
|
const helpers_1 = require("../helpers/index.cjs");
|
|
7
7
|
const store_1 = require("../store/index.cjs");
|
|
8
8
|
const helpers_2 = require("../helpers/index.cjs");
|
|
9
|
-
const config_1 = require("../config.cjs");
|
|
10
9
|
const stream_1 = require("stream");
|
|
11
|
-
const util_1 = require("util");
|
|
12
10
|
const logger_1 = require("../libs/logger/index.cjs");
|
|
13
|
-
const
|
|
11
|
+
const store_2 = require("../store/index.cjs");
|
|
14
12
|
class ChatProcessor {
|
|
15
|
-
constructor(
|
|
16
|
-
this.chatRepository = chatRepository;
|
|
17
|
-
this.messageRepository = messageRepository;
|
|
18
|
-
this.artifactStore = artifactStore;
|
|
13
|
+
constructor(params) {
|
|
14
|
+
this.chatRepository = params.chatRepository;
|
|
15
|
+
this.messageRepository = params.messageRepository;
|
|
16
|
+
this.artifactStore = params.artifactStore;
|
|
17
|
+
this.config = params.config;
|
|
18
|
+
this.socketService = params.socketService;
|
|
19
|
+
this.agentStore = params.agentStore;
|
|
20
|
+
this.activityRepository = params.activityRepository;
|
|
21
|
+
this.agentConfigRepository = params.agentConfigRepository;
|
|
22
|
+
const fileHelper = new helpers_1.FileHelper(params.s3Lib, this.config);
|
|
23
|
+
this.aiHelper = new helpers_1.AIHelper(fileHelper, this.config);
|
|
24
|
+
this.debug = this.config.debug;
|
|
19
25
|
}
|
|
20
26
|
getTemporaryTitle(contextKey) {
|
|
21
27
|
return `${contextKey} session ${new Date().toISOString()}`;
|
|
@@ -27,6 +33,79 @@ class ChatProcessor {
|
|
|
27
33
|
const pattern = /^.+ session \d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/;
|
|
28
34
|
return pattern.test(title);
|
|
29
35
|
}
|
|
36
|
+
isPlainObject(value) {
|
|
37
|
+
return !!value && typeof value === 'object' && !Array.isArray(value);
|
|
38
|
+
}
|
|
39
|
+
mergeMissingUsageFields(target, source) {
|
|
40
|
+
for (const [key, sourceValue] of Object.entries(source)) {
|
|
41
|
+
const targetValue = target[key];
|
|
42
|
+
if (targetValue === undefined) {
|
|
43
|
+
target[key] = sourceValue;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (this.isPlainObject(targetValue) && this.isPlainObject(sourceValue)) {
|
|
47
|
+
this.mergeMissingUsageFields(targetValue, sourceValue);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
extractCostUsageFields(source) {
|
|
52
|
+
const extracted = {};
|
|
53
|
+
for (const [key, value] of Object.entries(source)) {
|
|
54
|
+
const normalizedKey = key.toLowerCase();
|
|
55
|
+
if (normalizedKey.includes('cost')) {
|
|
56
|
+
extracted[key] = value;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (this.isPlainObject(value)) {
|
|
60
|
+
const nestedCostFields = this.extractCostUsageFields(value);
|
|
61
|
+
if (Object.keys(nestedCostFields).length > 0) {
|
|
62
|
+
extracted[key] = nestedCostFields;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return extracted;
|
|
67
|
+
}
|
|
68
|
+
mergeUsageWithProviderMetadata(stepUsage, providerMetadata) {
|
|
69
|
+
const mergedUsage = this.isPlainObject(stepUsage) ? { ...stepUsage } : {};
|
|
70
|
+
let hasProviderUsage = false;
|
|
71
|
+
if (this.isPlainObject(providerMetadata)) {
|
|
72
|
+
for (const providerEntry of Object.values(providerMetadata)) {
|
|
73
|
+
if (!this.isPlainObject(providerEntry) || !this.isPlainObject(providerEntry.usage)) {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const providerCostUsage = this.extractCostUsageFields(providerEntry.usage);
|
|
77
|
+
if (Object.keys(providerCostUsage).length === 0) {
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
hasProviderUsage = true;
|
|
81
|
+
this.mergeMissingUsageFields(mergedUsage, providerCostUsage);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
if (this.isPlainObject(stepUsage)) {
|
|
85
|
+
return mergedUsage;
|
|
86
|
+
}
|
|
87
|
+
if (hasProviderUsage) {
|
|
88
|
+
return mergedUsage;
|
|
89
|
+
}
|
|
90
|
+
return stepUsage;
|
|
91
|
+
}
|
|
92
|
+
async validateToolCallInput(params) {
|
|
93
|
+
const agentOptions = await this.aiHelper.getAgentOptions({
|
|
94
|
+
agentName: params.agentName,
|
|
95
|
+
});
|
|
96
|
+
const tool = agentOptions.tools?.[params.toolName] ?? undefined;
|
|
97
|
+
const schema = tool?.inputSchema;
|
|
98
|
+
if (!schema) {
|
|
99
|
+
throw new Error(`Tool "${params.toolName}" schema not found`);
|
|
100
|
+
}
|
|
101
|
+
if (!(schema instanceof zod_1.z.ZodType)) {
|
|
102
|
+
throw new Error(`Tool "${params.toolName}" inputSchema must be a Zod schema`);
|
|
103
|
+
}
|
|
104
|
+
const result = schema.safeParse(params.input);
|
|
105
|
+
if (!result.success) {
|
|
106
|
+
throw new Error(`Invalid tool input for "${params.toolName}": ${result.error.message}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
30
109
|
async listChats(params) {
|
|
31
110
|
// Build filter object from params
|
|
32
111
|
const filter = {};
|
|
@@ -36,33 +115,56 @@ class ChatProcessor {
|
|
|
36
115
|
if (params?.contextKey) {
|
|
37
116
|
filter.contextKey = params.contextKey;
|
|
38
117
|
}
|
|
39
|
-
// Build query options for sort and limit with defaults
|
|
118
|
+
// Build query options for sort and limit with defaults.
|
|
40
119
|
const options = {
|
|
41
120
|
sort: {
|
|
42
121
|
field: params?.sortField ?? 'updatedAt',
|
|
43
122
|
order: params?.sortOrder ?? ai_agent_types_1.SortOrder.Desc
|
|
44
123
|
},
|
|
124
|
+
skip: params?.skip,
|
|
45
125
|
limit: params?.limit
|
|
46
126
|
};
|
|
47
|
-
|
|
48
|
-
|
|
127
|
+
const [total, data] = await Promise.all([
|
|
128
|
+
this.chatRepository.count(filter),
|
|
129
|
+
this.chatRepository.find(filter, options)
|
|
130
|
+
]);
|
|
131
|
+
return {
|
|
132
|
+
cursor: {
|
|
133
|
+
...(params?.skip != null ? { skip: params.skip } : {}),
|
|
134
|
+
...(params?.limit != null ? { limit: params.limit } : {}),
|
|
135
|
+
total
|
|
136
|
+
},
|
|
137
|
+
data
|
|
138
|
+
};
|
|
49
139
|
}
|
|
50
140
|
async getChat(chatId) {
|
|
51
141
|
const chat = await this.chatRepository.findById(chatId);
|
|
52
142
|
if (!chat) {
|
|
53
143
|
throw new Error('Chat not found');
|
|
54
144
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
145
|
+
return chat;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Get messages for a chat with optional cursor pagination.
|
|
149
|
+
* When limit is omitted, returns all messages (backward compatible).
|
|
150
|
+
* Messages are returned in chronological order (oldest → newest).
|
|
151
|
+
*/
|
|
152
|
+
async getMessages(chatId, options) {
|
|
153
|
+
const chat = await this.chatRepository.findById(chatId);
|
|
154
|
+
if (!chat) {
|
|
155
|
+
throw new Error('Chat not found');
|
|
156
|
+
}
|
|
157
|
+
return this.messageRepository.findByChatIdPaginated(chatId, options);
|
|
60
158
|
}
|
|
61
159
|
async deleteChat(chatId) {
|
|
62
160
|
const deleted = await this.chatRepository.delete(chatId);
|
|
63
161
|
if (!deleted) {
|
|
64
162
|
throw new Error('Chat not found');
|
|
65
163
|
}
|
|
164
|
+
await Promise.all([
|
|
165
|
+
this.messageRepository.deleteByChatId(chatId),
|
|
166
|
+
this.activityRepository.deleteByGroupId(chatId), // todo: discuss if this is needed
|
|
167
|
+
]);
|
|
66
168
|
this.artifactStore.deleteArtifacts(chatId);
|
|
67
169
|
}
|
|
68
170
|
async upsertAndGetChat(payload, excludeSocketId) {
|
|
@@ -98,7 +200,7 @@ class ChatProcessor {
|
|
|
98
200
|
if (!content) {
|
|
99
201
|
return this.getTemporaryTitle(payload.contextKey);
|
|
100
202
|
}
|
|
101
|
-
return
|
|
203
|
+
return this.aiHelper.generateTitleForMessage(payload.contextKey, [{
|
|
102
204
|
role: ai_agent_types_1.MessageRole.User,
|
|
103
205
|
content: content
|
|
104
206
|
}]);
|
|
@@ -114,7 +216,7 @@ class ChatProcessor {
|
|
|
114
216
|
toolCalls: []
|
|
115
217
|
});
|
|
116
218
|
if (chat.userId) {
|
|
117
|
-
|
|
219
|
+
this.socketService.emitMessageUpdate(chat.userId, message, excludeSocketId);
|
|
118
220
|
}
|
|
119
221
|
return message;
|
|
120
222
|
}
|
|
@@ -131,12 +233,7 @@ class ChatProcessor {
|
|
|
131
233
|
metadata,
|
|
132
234
|
...(payload.model ? { model: payload.model } : {})
|
|
133
235
|
});
|
|
134
|
-
|
|
135
|
-
const initialChatResponse = {
|
|
136
|
-
...chat,
|
|
137
|
-
messages: []
|
|
138
|
-
};
|
|
139
|
-
services_1.socketService.emitChatUpdate(targetUserId, initialChatResponse, excludeSocketId);
|
|
236
|
+
this.socketService.emitChatUpdate(targetUserId, chat, excludeSocketId);
|
|
140
237
|
return chat;
|
|
141
238
|
}
|
|
142
239
|
/**
|
|
@@ -191,33 +288,75 @@ class ChatProcessor {
|
|
|
191
288
|
await this.messageRepository.update(message.id, { toolCalls });
|
|
192
289
|
// Bump chat updatedAt so listChats ordering reflects the action.
|
|
193
290
|
await this.chatRepository.update(chat.id, { updatedAt: now });
|
|
194
|
-
|
|
291
|
+
this.socketService.emitMessageUpdate(chat.userId, updatedMessage, params.excludeSocketId);
|
|
195
292
|
if (params.systemMessage) {
|
|
196
293
|
//todo discuss support for system messages
|
|
197
294
|
//await this.createMessage(chat, MessageRole.System, params.systemMessage, undefined, params.excludeSocketId);
|
|
198
295
|
}
|
|
199
296
|
return { ok: true };
|
|
200
297
|
}
|
|
298
|
+
/**
|
|
299
|
+
* Update selected fields (input/output/status) on a specific tool call.
|
|
300
|
+
*/
|
|
301
|
+
async updateToolCall(params) {
|
|
302
|
+
if (params.input === undefined && params.output === undefined && params.status === undefined) {
|
|
303
|
+
throw new Error('At least one of input, output, or status must be provided');
|
|
304
|
+
}
|
|
305
|
+
const chat = await this.chatRepository.findById(params.chatId);
|
|
306
|
+
if (!chat) {
|
|
307
|
+
throw new Error('Chat not found');
|
|
308
|
+
}
|
|
309
|
+
if (params.userId && chat.userId !== params.userId) {
|
|
310
|
+
throw new Error('Chat does not belong to this user');
|
|
311
|
+
}
|
|
312
|
+
const message = await this.messageRepository.findById(params.messageId);
|
|
313
|
+
if (!message || message.chat !== params.chatId) {
|
|
314
|
+
throw new Error('Message not found or does not belong to this chat');
|
|
315
|
+
}
|
|
316
|
+
const targetToolCall = (message.toolCalls ?? []).find((tc) => tc.id === params.toolCallId);
|
|
317
|
+
if (!targetToolCall) {
|
|
318
|
+
throw new Error('Tool call not found in message');
|
|
319
|
+
}
|
|
320
|
+
if (params.input !== undefined) {
|
|
321
|
+
await this.validateToolCallInput({
|
|
322
|
+
agentName: message.agentName,
|
|
323
|
+
toolName: targetToolCall.name,
|
|
324
|
+
input: params.input,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
const updatedMessage = await this.messageRepository.updateToolCall(params.messageId, params.toolCallId, {
|
|
328
|
+
...(params.input !== undefined ? { input: params.input } : {}),
|
|
329
|
+
...(params.output !== undefined ? { output: params.output } : {}),
|
|
330
|
+
...(params.status !== undefined ? { status: params.status } : {}),
|
|
331
|
+
});
|
|
332
|
+
if (!updatedMessage) {
|
|
333
|
+
throw new Error('Tool call not found in message');
|
|
334
|
+
}
|
|
335
|
+
const now = new Date().toISOString();
|
|
336
|
+
await this.chatRepository.update(chat.id, { updatedAt: now });
|
|
337
|
+
this.socketService.emitMessageUpdate(chat.userId, updatedMessage, params.excludeSocketId);
|
|
338
|
+
return updatedMessage;
|
|
339
|
+
}
|
|
201
340
|
async streamMessageStep(params) {
|
|
202
341
|
const { chat, assistantMessage, existingMessages, signal, excludeSocketId, agentOptions } = params;
|
|
203
342
|
if (signal.aborted) {
|
|
204
343
|
return;
|
|
205
344
|
}
|
|
206
|
-
const result = await
|
|
345
|
+
const result = await this.aiHelper.streamAssistantResponse(existingMessages, signal, agentOptions);
|
|
207
346
|
try {
|
|
208
347
|
for await (const chunk of result.fullStream) {
|
|
209
348
|
if (chunk.type === 'error') {
|
|
210
|
-
await
|
|
349
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Error, data: chunk.error });
|
|
211
350
|
assistantMessage.content = chunk.error.message || 'Sorry, I cannot process you request due to the error';
|
|
212
351
|
await this.messageRepository.update(assistantMessage.id, assistantMessage);
|
|
213
352
|
await this.chatRepository.update(chat.id, { status: ai_agent_types_1.AgentStatus.Error });
|
|
214
353
|
continue;
|
|
215
354
|
}
|
|
216
355
|
if (chunk.type === 'abort') {
|
|
217
|
-
await
|
|
356
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Aborted, data: undefined });
|
|
218
357
|
await this.chatRepository.update(chat.id, { status: ai_agent_types_1.AgentStatus.Aborted });
|
|
219
358
|
await this.messageRepository.update(assistantMessage.id, assistantMessage);
|
|
220
|
-
|
|
359
|
+
this.socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
|
|
221
360
|
continue;
|
|
222
361
|
}
|
|
223
362
|
if (chunk.type === 'finish') {
|
|
@@ -235,42 +374,39 @@ class ChatProcessor {
|
|
|
235
374
|
}
|
|
236
375
|
await this.messageRepository.update(assistantMessage.id, { ...assistantMessage });
|
|
237
376
|
if (chunk.finishReason === 'stop') {
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
services_1.socketService.emitChatUpdate(chat.userId, { ...chat, title, messages: [] });
|
|
253
|
-
}
|
|
377
|
+
await this.chatRepository.update(chat.id, { status: ai_agent_types_1.AgentStatus.Finished });
|
|
378
|
+
if (chat.title && this.isTemporaryTitle(chat.title)) {
|
|
379
|
+
const title = await this.aiHelper.generateTitleForMessage(chat.contextKey, existingMessages.filter(m => m.role === ai_agent_types_1.MessageRole.User), (stepResult) => {
|
|
380
|
+
return this.storeStepActivity({
|
|
381
|
+
chat,
|
|
382
|
+
stepResult,
|
|
383
|
+
name: ai_agent_types_1.ActivityOperationName.TITLE_GENERATION,
|
|
384
|
+
sourceId: chat.id,
|
|
385
|
+
sourceType: 'Chat',
|
|
386
|
+
tenants: params.tenants || {},
|
|
387
|
+
});
|
|
388
|
+
});
|
|
389
|
+
await this.chatRepository.update(chat.id, { title });
|
|
390
|
+
this.socketService.emitChatUpdate(chat.userId, { ...chat, title });
|
|
254
391
|
}
|
|
255
|
-
await store_1.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Finished, data: assistantMessage });
|
|
256
|
-
continue;
|
|
257
392
|
}
|
|
258
393
|
if (chunk.finishReason === 'tool-calls') {
|
|
259
394
|
if (assistantMessage.toolCalls?.some(toolCall => toolCall.requiresConfirmation && toolCall.approvalId && !toolCall.output)) {
|
|
260
395
|
await this.chatRepository.update(chat.id, { status: ai_agent_types_1.AgentStatus.WaitingForUserAction });
|
|
261
|
-
await
|
|
262
|
-
|
|
263
|
-
else {
|
|
264
|
-
await store_1.agentStore.shareAgentProcessEvent(chat.id, {
|
|
265
|
-
type: store_1.AgentProcessEventType.Update,
|
|
266
|
-
data: assistantMessage
|
|
267
|
-
});
|
|
268
|
-
await this.streamMessageStep(params);
|
|
396
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Finished, data: assistantMessage });
|
|
397
|
+
continue;
|
|
269
398
|
}
|
|
270
|
-
continue;
|
|
271
399
|
}
|
|
272
400
|
//todo: Handle other finish reasons // length, content, error, other, undefined
|
|
273
|
-
await
|
|
401
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Finished, data: assistantMessage });
|
|
402
|
+
if (assistantMessage.activity) {
|
|
403
|
+
const groupedMeta = await this.activityRepository.getGroupedMetadataByParentId(assistantMessage.activity);
|
|
404
|
+
await this.activityRepository.updateMetadata(assistantMessage.activity, {
|
|
405
|
+
usage: groupedMeta,
|
|
406
|
+
finishReason: chunk.finishReason,
|
|
407
|
+
responseTimestamp: new Date().toISOString(),
|
|
408
|
+
});
|
|
409
|
+
}
|
|
274
410
|
continue;
|
|
275
411
|
}
|
|
276
412
|
if (chunk.type === 'text-delta') {
|
|
@@ -279,8 +415,8 @@ class ChatProcessor {
|
|
|
279
415
|
...assistantMessage,
|
|
280
416
|
content: assistantMessage.content
|
|
281
417
|
};
|
|
282
|
-
|
|
283
|
-
await
|
|
418
|
+
this.socketService.emitMessageUpdate(chat.userId, updatedMessage, excludeSocketId);
|
|
419
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Update, data: updatedMessage });
|
|
284
420
|
await this.messageRepository.update(assistantMessage.id, { content: assistantMessage.content });
|
|
285
421
|
continue;
|
|
286
422
|
}
|
|
@@ -295,7 +431,7 @@ class ChatProcessor {
|
|
|
295
431
|
});
|
|
296
432
|
continue;
|
|
297
433
|
}
|
|
298
|
-
if (chunk.type === 'tool-call') {
|
|
434
|
+
if (chunk.type === 'tool-call') {
|
|
299
435
|
const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
|
|
300
436
|
if (toolCall) {
|
|
301
437
|
toolCall.status = ai_agent_types_1.AgentToolCallStatus.Running;
|
|
@@ -307,7 +443,7 @@ class ChatProcessor {
|
|
|
307
443
|
const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
|
|
308
444
|
if (toolCall) {
|
|
309
445
|
toolCall.status = ai_agent_types_1.AgentToolCallStatus.Failed;
|
|
310
|
-
toolCall.error = JSON.stringify(chunk.error);
|
|
446
|
+
toolCall.error = chunk.error.message || JSON.stringify(chunk.error);
|
|
311
447
|
}
|
|
312
448
|
continue;
|
|
313
449
|
}
|
|
@@ -316,13 +452,16 @@ class ChatProcessor {
|
|
|
316
452
|
if (toolCall) {
|
|
317
453
|
toolCall.requiresConfirmation = true;
|
|
318
454
|
toolCall.approvalId = chunk.approvalId;
|
|
455
|
+
if (toolCall.name === ai_agent_types_1.AgentToolType.REQUEST_CLARIFICATION) {
|
|
456
|
+
toolCall.requiresUserAction = true;
|
|
457
|
+
}
|
|
319
458
|
}
|
|
320
459
|
continue;
|
|
321
460
|
}
|
|
322
461
|
if (chunk.type === 'tool-result') {
|
|
323
462
|
const toolCall = assistantMessage.toolCalls?.find(toolCall => toolCall.id === chunk.toolCallId);
|
|
324
463
|
if (toolCall) {
|
|
325
|
-
if (chunk.output
|
|
464
|
+
if (chunk.output?.requiresApproval) {
|
|
326
465
|
toolCall.requiresConfirmation = true;
|
|
327
466
|
continue;
|
|
328
467
|
}
|
|
@@ -335,9 +474,9 @@ class ChatProcessor {
|
|
|
335
474
|
if (!assistantMessage.reasoning)
|
|
336
475
|
assistantMessage.reasoning = '';
|
|
337
476
|
assistantMessage.reasoning += chunk.text;
|
|
338
|
-
|
|
477
|
+
this.socketService.emitMessageUpdate(chat.userId, assistantMessage, excludeSocketId);
|
|
339
478
|
await this.messageRepository.update(assistantMessage.id, { reasoning: assistantMessage.reasoning });
|
|
340
|
-
await
|
|
479
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Update, data: assistantMessage });
|
|
341
480
|
continue;
|
|
342
481
|
}
|
|
343
482
|
}
|
|
@@ -346,7 +485,7 @@ class ChatProcessor {
|
|
|
346
485
|
if (streamError instanceof Error && streamError.name === 'AbortError') {
|
|
347
486
|
return;
|
|
348
487
|
}
|
|
349
|
-
await
|
|
488
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Error, data: streamError });
|
|
350
489
|
throw streamError;
|
|
351
490
|
}
|
|
352
491
|
}
|
|
@@ -358,7 +497,7 @@ class ChatProcessor {
|
|
|
358
497
|
if (!assistantMessage || assistantMessage.chat !== chat.id) {
|
|
359
498
|
throw new Error(`Assistant message with id ${payload.messageId} not found`);
|
|
360
499
|
}
|
|
361
|
-
const agentOptions = await
|
|
500
|
+
const agentOptions = await this.aiHelper.getAgentOptions({
|
|
362
501
|
agentName: assistantMessage.agentName,
|
|
363
502
|
context: payload.context
|
|
364
503
|
});
|
|
@@ -371,14 +510,20 @@ class ChatProcessor {
|
|
|
371
510
|
};
|
|
372
511
|
}
|
|
373
512
|
toolCall.approved = payload.approved;
|
|
374
|
-
toolCall.
|
|
513
|
+
toolCall.userResponse = payload.userResponse;
|
|
375
514
|
if (!toolCall.approved) {
|
|
376
515
|
toolCall.output = {
|
|
377
516
|
type: 'execution-denied',
|
|
378
|
-
reason: toolCall.
|
|
517
|
+
reason: toolCall.userResponse
|
|
379
518
|
};
|
|
380
519
|
toolCall.status = ai_agent_types_1.AgentToolCallStatus.Failed;
|
|
381
520
|
}
|
|
521
|
+
else if (toolCall.requiresUserAction) {
|
|
522
|
+
toolCall.output = {
|
|
523
|
+
userResponse: toolCall.userResponse
|
|
524
|
+
};
|
|
525
|
+
toolCall.status = ai_agent_types_1.AgentToolCallStatus.Succeeded;
|
|
526
|
+
}
|
|
382
527
|
else {
|
|
383
528
|
const executeFunction = agentOptions.tools?.[toolCall.name]?.execute;
|
|
384
529
|
if (executeFunction) {
|
|
@@ -411,32 +556,105 @@ class ChatProcessor {
|
|
|
411
556
|
}
|
|
412
557
|
async processNewUserMessage(chat, payload, prevMessages, excludeSocketId) {
|
|
413
558
|
const userMessage = await this.createMessage(chat, ai_agent_types_1.MessageRole.User, { content: payload.content, agentName: undefined }, payload.attachments);
|
|
414
|
-
await
|
|
415
|
-
|
|
559
|
+
await this.agentStore.shareAgentProcessEvent(chat.id, { type: store_1.AgentProcessEventType.Update, data: userMessage });
|
|
560
|
+
let assistantMessage = await this.createMessage(chat, ai_agent_types_1.MessageRole.Assistant, { content: '', agentName: undefined }, undefined, excludeSocketId);
|
|
561
|
+
const parentActivity = await this.activityRepository.create({
|
|
562
|
+
ownerId: chat.userId,
|
|
563
|
+
groupId: chat.id,
|
|
564
|
+
name: ai_agent_types_1.ActivityOperationName.MESSAGE_PROCESSING,
|
|
565
|
+
tenants: payload.tenants ?? {},
|
|
566
|
+
sourceId: userMessage.id,
|
|
567
|
+
sourceType: 'AgentMessage',
|
|
568
|
+
metadata: {
|
|
569
|
+
contextKey: chat.contextKey,
|
|
570
|
+
modelId: this.aiHelper.getLanguageModelId(chat.model),
|
|
571
|
+
},
|
|
572
|
+
});
|
|
573
|
+
const agentOptions = await this.aiHelper.getAgentOptions({
|
|
416
574
|
contextKey: chat.contextKey,
|
|
417
|
-
messages:
|
|
575
|
+
messages: [...prevMessages, userMessage],
|
|
418
576
|
context: payload.context,
|
|
419
577
|
agentName: undefined,
|
|
420
578
|
modelId: chat.model,
|
|
579
|
+
}, {
|
|
580
|
+
onStepFinish: async (stepResult) => {
|
|
581
|
+
await this.storeStepActivity({
|
|
582
|
+
chat,
|
|
583
|
+
parentId: parentActivity.id,
|
|
584
|
+
stepResult,
|
|
585
|
+
name: ai_agent_types_1.ActivityOperationName.AGENT_SELECTION,
|
|
586
|
+
sourceId: userMessage.id,
|
|
587
|
+
sourceType: 'AgentMessage',
|
|
588
|
+
tenants: payload.tenants || {},
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
});
|
|
592
|
+
const updatedAssistantMessage = await this.messageRepository.update(assistantMessage.id, {
|
|
593
|
+
agentName: agentOptions.name,
|
|
594
|
+
activity: parentActivity.id
|
|
421
595
|
});
|
|
422
|
-
|
|
423
|
-
|
|
596
|
+
await this.activityRepository.update(parentActivity.id, {
|
|
597
|
+
metadata: {
|
|
598
|
+
...parentActivity.metadata,
|
|
599
|
+
agentOptions: {
|
|
600
|
+
name: agentOptions.name,
|
|
601
|
+
modelId: this.aiHelper.getLanguageModelId(agentOptions.model),
|
|
602
|
+
temperature: agentOptions.temperature,
|
|
603
|
+
maxOutputTokens: agentOptions.maxOutputTokens,
|
|
604
|
+
topP: agentOptions.topP,
|
|
605
|
+
topK: agentOptions.topK,
|
|
606
|
+
presencePenalty: agentOptions.presencePenalty,
|
|
607
|
+
frequencyPenalty: agentOptions.frequencyPenalty,
|
|
608
|
+
stopSequences: agentOptions.stopSequences,
|
|
609
|
+
seed: agentOptions.seed,
|
|
610
|
+
},
|
|
611
|
+
},
|
|
612
|
+
});
|
|
613
|
+
if (!updatedAssistantMessage) {
|
|
614
|
+
throw new Error(`Assistant message with id ${assistantMessage.id} not found after update`);
|
|
615
|
+
}
|
|
616
|
+
assistantMessage = updatedAssistantMessage;
|
|
424
617
|
return {
|
|
425
618
|
userMessage,
|
|
426
619
|
assistantMessage,
|
|
427
620
|
agentOptions,
|
|
428
621
|
};
|
|
429
622
|
}
|
|
623
|
+
async storeStepActivity(params) {
|
|
624
|
+
try {
|
|
625
|
+
const stepResult = params.stepResult;
|
|
626
|
+
const mergedUsage = this.mergeUsageWithProviderMetadata(stepResult.usage, stepResult.providerMetadata);
|
|
627
|
+
const activity = await this.activityRepository.create({
|
|
628
|
+
ownerId: params.chat.userId,
|
|
629
|
+
groupId: params.chat.id,
|
|
630
|
+
name: params.name,
|
|
631
|
+
tenants: params.tenants || {},
|
|
632
|
+
sourceId: params.sourceId,
|
|
633
|
+
sourceType: params.sourceType,
|
|
634
|
+
metadata: {
|
|
635
|
+
finishReason: stepResult.finishReason,
|
|
636
|
+
usage: mergedUsage,
|
|
637
|
+
responseTimestamp: stepResult.response.timestamp,
|
|
638
|
+
modelId: stepResult.response.modelId,
|
|
639
|
+
messages: this.debug ? stepResult.request?.body?.messages : undefined,
|
|
640
|
+
},
|
|
641
|
+
parentId: params.parentId,
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
catch (error) {
|
|
645
|
+
logger_1.logger.error({ error, chatId: params.chat.id, parentId: params.parentId }, 'Failed to store step activity');
|
|
646
|
+
}
|
|
647
|
+
}
|
|
430
648
|
async streamMessage(chat, payload, excludeSocketId, onAgentStart) {
|
|
431
649
|
try {
|
|
432
|
-
const abortController =
|
|
650
|
+
const abortController = this.agentStore.registerAgentProcess(chat.id);
|
|
433
651
|
onAgentStart?.();
|
|
434
652
|
let assistantMessage;
|
|
435
653
|
let agentOptions;
|
|
436
654
|
const existingMessages = await this.messageRepository.findByChatId(chat.id);
|
|
437
655
|
// Limit context to prevent exceeding token limits
|
|
438
656
|
const limitedMessages = helpers_2.ContextLimiter.limitContext(existingMessages, {
|
|
439
|
-
maxMessages:
|
|
657
|
+
maxMessages: this.config.ai.maxContextMessages,
|
|
440
658
|
keepFirstUserMessage: true,
|
|
441
659
|
keepSystemMessages: true,
|
|
442
660
|
});
|
|
@@ -458,6 +676,19 @@ class ChatProcessor {
|
|
|
458
676
|
agentOptions = result.agentOptions;
|
|
459
677
|
limitedMessages.push(result.userMessage);
|
|
460
678
|
}
|
|
679
|
+
agentOptions.onStepFinish = (stepResult) => {
|
|
680
|
+
return this.storeStepActivity({
|
|
681
|
+
chat,
|
|
682
|
+
parentId: assistantMessage.activity,
|
|
683
|
+
stepResult,
|
|
684
|
+
name: ai_agent_types_1.ActivityOperationName.STEP_FINISHED,
|
|
685
|
+
sourceId: assistantMessage.id,
|
|
686
|
+
sourceType: 'AgentMessage',
|
|
687
|
+
tenants: payload.tenants || {},
|
|
688
|
+
});
|
|
689
|
+
};
|
|
690
|
+
const userPreferences = await this.agentConfigRepository.findByUserIdAndAgentName(chat.userId, agentOptions.name);
|
|
691
|
+
agentOptions.activeTools = this.getAvailableTools(agentOptions, userPreferences);
|
|
461
692
|
await this.streamMessageStep({
|
|
462
693
|
chat,
|
|
463
694
|
existingMessages: limitedMessages,
|
|
@@ -465,12 +696,28 @@ class ChatProcessor {
|
|
|
465
696
|
agentOptions,
|
|
466
697
|
excludeSocketId: excludeSocketId,
|
|
467
698
|
signal: abortController.signal,
|
|
699
|
+
tenants: payload.tenants || {},
|
|
468
700
|
});
|
|
469
701
|
}
|
|
470
702
|
catch (error) {
|
|
471
703
|
throw error;
|
|
472
704
|
}
|
|
473
705
|
}
|
|
706
|
+
getAvailableTools(agentOptions, userPreferences) {
|
|
707
|
+
const toolNames = Object.keys(agentOptions.tools || {});
|
|
708
|
+
const availableToolsMap = Object.fromEntries(toolNames.map(key => [key, true]));
|
|
709
|
+
const agentsConfiguration = store_2.ConfigStore.getInstance().getAgentConfigByName(agentOptions.name);
|
|
710
|
+
agentsConfiguration.tools.forEach((tool) => {
|
|
711
|
+
const toolTitle = tool.data?.title || tool.type;
|
|
712
|
+
if (tool.disabledByDefault) {
|
|
713
|
+
availableToolsMap[toolTitle] = false;
|
|
714
|
+
}
|
|
715
|
+
if (tool.userConfigurable && userPreferences?.tools?.[toolTitle] !== undefined) {
|
|
716
|
+
availableToolsMap[toolTitle] = userPreferences.tools[toolTitle];
|
|
717
|
+
}
|
|
718
|
+
});
|
|
719
|
+
return Object.keys(availableToolsMap).filter(key => availableToolsMap[key]);
|
|
720
|
+
}
|
|
474
721
|
listArtifacts(chatId) {
|
|
475
722
|
return this.artifactStore.listArtifacts(chatId);
|
|
476
723
|
}
|
|
@@ -501,7 +748,7 @@ class ChatProcessor {
|
|
|
501
748
|
return null;
|
|
502
749
|
}
|
|
503
750
|
}
|
|
504
|
-
getMessageStream(chatId) {
|
|
751
|
+
getMessageStream(chatId, signal) {
|
|
505
752
|
const stream = new stream_1.PassThrough();
|
|
506
753
|
let ended = false;
|
|
507
754
|
const endStream = (error) => {
|
|
@@ -522,13 +769,15 @@ class ChatProcessor {
|
|
|
522
769
|
}
|
|
523
770
|
};
|
|
524
771
|
const pushChunk = (chunk) => {
|
|
525
|
-
if (ended || stream.destroyed || stream.writableEnded)
|
|
772
|
+
if (ended || stream.destroyed || stream.writableEnded || signal?.aborted)
|
|
526
773
|
return;
|
|
527
774
|
stream.write(`data: ${JSON.stringify(chunk)}\n\n`);
|
|
528
775
|
};
|
|
529
776
|
const listener = (event) => {
|
|
530
|
-
if (
|
|
777
|
+
if (signal?.aborted) {
|
|
778
|
+
endStream();
|
|
531
779
|
return;
|
|
780
|
+
}
|
|
532
781
|
try {
|
|
533
782
|
const chunk = this.eventToChunk(event);
|
|
534
783
|
if (chunk) {
|
|
@@ -538,7 +787,6 @@ class ChatProcessor {
|
|
|
538
787
|
event.type === store_1.AgentProcessEventType.Error ||
|
|
539
788
|
event.type === store_1.AgentProcessEventType.Aborted) {
|
|
540
789
|
endStream();
|
|
541
|
-
store_1.agentStore.removeListener(chatId, listener);
|
|
542
790
|
}
|
|
543
791
|
}
|
|
544
792
|
catch (err) {
|
|
@@ -547,21 +795,18 @@ class ChatProcessor {
|
|
|
547
795
|
error: err instanceof Error ? err.message : 'Unknown error occurred',
|
|
548
796
|
});
|
|
549
797
|
endStream(err);
|
|
550
|
-
store_1.agentStore.removeListener(chatId, listener);
|
|
551
798
|
}
|
|
552
799
|
};
|
|
553
|
-
// Cleanup on consumer side closing
|
|
554
800
|
const closeHandler = () => {
|
|
555
|
-
|
|
801
|
+
this.agentStore.removeListener(chatId, listener);
|
|
556
802
|
};
|
|
557
803
|
const errorHandler = (err) => {
|
|
558
|
-
|
|
559
|
-
store_1.agentStore.removeListener(chatId, listener);
|
|
804
|
+
signal?.removeEventListener('abort', endStream);
|
|
560
805
|
endStream(err);
|
|
561
806
|
};
|
|
562
807
|
stream.on('close', closeHandler);
|
|
563
808
|
stream.on('error', errorHandler);
|
|
564
|
-
const listenerAttached =
|
|
809
|
+
const listenerAttached = this.agentStore.addListener(chatId, listener);
|
|
565
810
|
if (!listenerAttached) {
|
|
566
811
|
// Remove stream listeners if listener attachment failed to prevent memory leak
|
|
567
812
|
stream.removeListener('close', closeHandler);
|
|
@@ -570,51 +815,28 @@ class ChatProcessor {
|
|
|
570
815
|
}
|
|
571
816
|
return stream;
|
|
572
817
|
}
|
|
573
|
-
async createMessageStream(payload, excludeSocketId) {
|
|
818
|
+
async createMessageStream(payload, excludeSocketId, signal) {
|
|
574
819
|
const stream = new stream_1.PassThrough();
|
|
575
|
-
(
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
// Send chat metadata first
|
|
579
|
-
if (!('chatId' in payload) && !('messageId' in payload) && chat) {
|
|
580
|
-
stream.write(`data: ${JSON.stringify({
|
|
581
|
-
type: ai_agent_types_1.StreamChunkType.Chat,
|
|
582
|
-
chatId: chat.id,
|
|
583
|
-
chat,
|
|
584
|
-
})}\n\n`);
|
|
585
|
-
}
|
|
586
|
-
await this.streamMessage(chat, payload, excludeSocketId, async () => {
|
|
587
|
-
if (stream.destroyed || stream.writableEnded) {
|
|
588
|
-
return;
|
|
589
|
-
}
|
|
590
|
-
const messageStream = this.getMessageStream(chat.id);
|
|
591
|
-
// If client disconnects, destroy inner stream
|
|
592
|
-
stream.on('close', () => {
|
|
593
|
-
if (!messageStream.destroyed) {
|
|
594
|
-
messageStream.destroy();
|
|
595
|
-
}
|
|
596
|
-
});
|
|
597
|
-
await pipelineAsync(messageStream, stream);
|
|
598
|
-
});
|
|
599
|
-
}
|
|
600
|
-
catch (error) {
|
|
601
|
-
logger_1.logger.error({ error }, 'createMessageStream failed');
|
|
602
|
-
if (!stream.destroyed && !stream.writableEnded) {
|
|
603
|
-
stream.write(`data: ${JSON.stringify({
|
|
604
|
-
type: ai_agent_types_1.StreamChunkType.Error,
|
|
605
|
-
error: error instanceof Error ? error.message : 'Unknown error occurred',
|
|
606
|
-
})}\n\n`);
|
|
607
|
-
stream.write('data: [DONE]\n\n');
|
|
608
|
-
stream.end();
|
|
609
|
-
}
|
|
610
|
-
}
|
|
611
|
-
})().catch((err) => {
|
|
612
|
-
logger_1.logger.error({ err }, 'Unhandled stream task error');
|
|
613
|
-
if (!stream.destroyed)
|
|
614
|
-
stream.destroy(err);
|
|
820
|
+
this.runMessageStream(stream, payload, excludeSocketId, signal)
|
|
821
|
+
.catch(err => {
|
|
822
|
+
logger_1.logger.error({ err }, 'Stream task failed');
|
|
615
823
|
});
|
|
616
824
|
return stream;
|
|
617
825
|
}
|
|
826
|
+
async runMessageStream(stream, payload, excludeSocketId, signal) {
|
|
827
|
+
const chat = await this.upsertAndGetChat(payload, excludeSocketId);
|
|
828
|
+
if (!('chatId' in payload) && !('messageId' in payload) && chat) {
|
|
829
|
+
stream.write(`data: ${JSON.stringify({
|
|
830
|
+
type: ai_agent_types_1.StreamChunkType.Chat,
|
|
831
|
+
chatId: chat.id,
|
|
832
|
+
chat,
|
|
833
|
+
})}\n\n`);
|
|
834
|
+
}
|
|
835
|
+
await this.streamMessage(chat, payload, excludeSocketId, () => {
|
|
836
|
+
const messageStream = this.getMessageStream(chat.id, signal);
|
|
837
|
+
messageStream.pipe(stream);
|
|
838
|
+
});
|
|
839
|
+
}
|
|
618
840
|
}
|
|
619
841
|
exports.ChatProcessor = ChatProcessor;
|
|
620
842
|
//# sourceMappingURL=ChatProcessor.js.map
|