@cloudbase/agent-adapter-yuanqi 0.0.16 → 0.0.18
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 +243 -9
- package/dist/index.d.mts +187 -8
- package/dist/index.d.ts +187 -8
- package/dist/index.js +476 -27
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +467 -25
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.mjs
CHANGED
|
@@ -3,6 +3,8 @@ import {
|
|
|
3
3
|
AbstractAgent,
|
|
4
4
|
EventType as EventType2
|
|
5
5
|
} from "@ag-ui/client";
|
|
6
|
+
import tcb from "@cloudbase/node-sdk";
|
|
7
|
+
import managedTcb from "@cloudbase/manager-node";
|
|
6
8
|
import OpenAI from "openai";
|
|
7
9
|
import { randomUUID } from "crypto";
|
|
8
10
|
|
|
@@ -27,6 +29,14 @@ function camelToSnakeKeys(obj) {
|
|
|
27
29
|
}
|
|
28
30
|
return obj;
|
|
29
31
|
}
|
|
32
|
+
function genRandomStr(length) {
|
|
33
|
+
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
34
|
+
let result = "";
|
|
35
|
+
for (let i = 0; i < length; i++) {
|
|
36
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
30
40
|
|
|
31
41
|
// src/stream.ts
|
|
32
42
|
import { EventType } from "@ag-ui/client";
|
|
@@ -45,6 +55,28 @@ async function* processYuanqiStream(stream, context) {
|
|
|
45
55
|
for await (const chunk of stream) {
|
|
46
56
|
const delta = chunk.choices[0]?.delta;
|
|
47
57
|
if (!delta) continue;
|
|
58
|
+
if (delta.role === "tool") {
|
|
59
|
+
const toolCallId = delta.tool_call_id;
|
|
60
|
+
if (toolCallId) {
|
|
61
|
+
if (state.toolCallsMap.has(toolCallId)) {
|
|
62
|
+
yield {
|
|
63
|
+
type: EventType.TOOL_CALL_END,
|
|
64
|
+
threadId,
|
|
65
|
+
runId,
|
|
66
|
+
toolCallId
|
|
67
|
+
};
|
|
68
|
+
state.toolCallsMap.delete(toolCallId);
|
|
69
|
+
}
|
|
70
|
+
yield {
|
|
71
|
+
type: EventType.TOOL_CALL_RESULT,
|
|
72
|
+
threadId,
|
|
73
|
+
runId,
|
|
74
|
+
toolCallId,
|
|
75
|
+
content: delta.content || ""
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
48
80
|
if (delta.content) {
|
|
49
81
|
if (reasoningState.hasStarted) {
|
|
50
82
|
reasoningState.hasStarted = false;
|
|
@@ -117,6 +149,15 @@ async function* processYuanqiStream(stream, context) {
|
|
|
117
149
|
toolCallId,
|
|
118
150
|
toolCallName: toolCall.function.name
|
|
119
151
|
};
|
|
152
|
+
if (toolCall.function.arguments) {
|
|
153
|
+
yield {
|
|
154
|
+
type: EventType.TOOL_CALL_ARGS,
|
|
155
|
+
threadId,
|
|
156
|
+
runId,
|
|
157
|
+
toolCallId,
|
|
158
|
+
delta: toolCall.function.arguments
|
|
159
|
+
};
|
|
160
|
+
}
|
|
120
161
|
state.toolCallsMap.set(toolCallId, {
|
|
121
162
|
name: toolCall.function.name,
|
|
122
163
|
args: toolCall.function.arguments || ""
|
|
@@ -145,6 +186,20 @@ async function* processYuanqiStream(stream, context) {
|
|
|
145
186
|
messageId
|
|
146
187
|
};
|
|
147
188
|
}
|
|
189
|
+
if (reasoningState.hasStarted) {
|
|
190
|
+
yield {
|
|
191
|
+
type: EventType.THINKING_TEXT_MESSAGE_END,
|
|
192
|
+
threadId,
|
|
193
|
+
runId,
|
|
194
|
+
messageId
|
|
195
|
+
};
|
|
196
|
+
yield {
|
|
197
|
+
type: EventType.THINKING_END,
|
|
198
|
+
threadId,
|
|
199
|
+
runId,
|
|
200
|
+
messageId
|
|
201
|
+
};
|
|
202
|
+
}
|
|
148
203
|
for (const [toolCallId] of state.toolCallsMap) {
|
|
149
204
|
yield {
|
|
150
205
|
type: EventType.TOOL_CALL_END,
|
|
@@ -153,24 +208,217 @@ async function* processYuanqiStream(stream, context) {
|
|
|
153
208
|
toolCallId
|
|
154
209
|
};
|
|
155
210
|
}
|
|
156
|
-
yield {
|
|
157
|
-
type: EventType.RUN_FINISHED,
|
|
158
|
-
threadId,
|
|
159
|
-
runId
|
|
160
|
-
};
|
|
161
211
|
}
|
|
162
212
|
|
|
163
213
|
// src/agent.ts
|
|
164
214
|
import { Observable } from "rxjs";
|
|
215
|
+
|
|
216
|
+
// src/constant.ts
|
|
217
|
+
var CHAT_HISTORY_DATA_SOURCE = "ai_bot_chat_history_5hobd2b";
|
|
218
|
+
|
|
219
|
+
// src/chat_history.ts
|
|
220
|
+
function genRecordId() {
|
|
221
|
+
return "record-" + genRandomStr(8);
|
|
222
|
+
}
|
|
223
|
+
async function createChatHistory({
|
|
224
|
+
tcbClient,
|
|
225
|
+
chatHistoryEntity
|
|
226
|
+
}) {
|
|
227
|
+
try {
|
|
228
|
+
const recordId = chatHistoryEntity.recordId || genRecordId();
|
|
229
|
+
const data = {
|
|
230
|
+
record_id: recordId,
|
|
231
|
+
bot_id: chatHistoryEntity.botId,
|
|
232
|
+
role: chatHistoryEntity.role,
|
|
233
|
+
content: chatHistoryEntity.content,
|
|
234
|
+
sender: chatHistoryEntity.sender,
|
|
235
|
+
conversation: chatHistoryEntity.conversation,
|
|
236
|
+
type: chatHistoryEntity.type,
|
|
237
|
+
image: chatHistoryEntity.image,
|
|
238
|
+
trigger_src: chatHistoryEntity.triggerSrc,
|
|
239
|
+
origin_msg: chatHistoryEntity.originMsg,
|
|
240
|
+
reply_to: chatHistoryEntity.replyTo,
|
|
241
|
+
reply: chatHistoryEntity.reply,
|
|
242
|
+
trace_id: chatHistoryEntity.traceId,
|
|
243
|
+
need_async_reply: chatHistoryEntity.needAsyncReply,
|
|
244
|
+
async_reply: chatHistoryEntity.asyncReply,
|
|
245
|
+
createdAt: Date.now(),
|
|
246
|
+
updatedAt: Date.now()
|
|
247
|
+
};
|
|
248
|
+
const db = tcbClient.database();
|
|
249
|
+
const collection = db.collection(CHAT_HISTORY_DATA_SOURCE);
|
|
250
|
+
const result = await collection.add(data);
|
|
251
|
+
return recordId;
|
|
252
|
+
} catch (error) {
|
|
253
|
+
console.error("Failed to create chat history record, error:", error);
|
|
254
|
+
return void 0;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
async function updateChatHistoryByRecordId({
|
|
258
|
+
tcbClient,
|
|
259
|
+
recordId,
|
|
260
|
+
chatHistoryEntity
|
|
261
|
+
}) {
|
|
262
|
+
try {
|
|
263
|
+
const db = tcbClient.database();
|
|
264
|
+
const _ = db.command;
|
|
265
|
+
const collection = db.collection(CHAT_HISTORY_DATA_SOURCE);
|
|
266
|
+
const result = await collection.where({ record_id: _.eq(recordId) }).update({
|
|
267
|
+
content: chatHistoryEntity.content,
|
|
268
|
+
image: chatHistoryEntity.image,
|
|
269
|
+
async_reply: chatHistoryEntity.asyncReply,
|
|
270
|
+
recommend_questions: chatHistoryEntity.recommendQuestions,
|
|
271
|
+
status: chatHistoryEntity.status,
|
|
272
|
+
origin_msg: chatHistoryEntity.originMsg,
|
|
273
|
+
updatedAt: Date.now()
|
|
274
|
+
});
|
|
275
|
+
return chatHistoryEntity.recordId;
|
|
276
|
+
} catch (error) {
|
|
277
|
+
console.error("Failed to update chat history, error:", error);
|
|
278
|
+
return void 0;
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
async function describeChatHistory({
|
|
282
|
+
tcbClient,
|
|
283
|
+
botId,
|
|
284
|
+
sort,
|
|
285
|
+
pageSize = 10,
|
|
286
|
+
pageNumber = 1,
|
|
287
|
+
conversation,
|
|
288
|
+
startCreatedAt,
|
|
289
|
+
triggerSrc
|
|
290
|
+
}) {
|
|
291
|
+
if (!sort || sort.length === 0) {
|
|
292
|
+
sort = "desc";
|
|
293
|
+
}
|
|
294
|
+
try {
|
|
295
|
+
const db = tcbClient.database();
|
|
296
|
+
const _ = db.command;
|
|
297
|
+
const collection = db.collection(CHAT_HISTORY_DATA_SOURCE);
|
|
298
|
+
const whereConditions = {
|
|
299
|
+
bot_id: _.eq(botId)
|
|
300
|
+
};
|
|
301
|
+
if (conversation) {
|
|
302
|
+
whereConditions.conversation = _.eq(conversation);
|
|
303
|
+
}
|
|
304
|
+
if (startCreatedAt !== void 0) {
|
|
305
|
+
whereConditions.createdAt = _.gt(startCreatedAt);
|
|
306
|
+
}
|
|
307
|
+
if (triggerSrc) {
|
|
308
|
+
whereConditions.trigger_src = _.eq(triggerSrc);
|
|
309
|
+
}
|
|
310
|
+
const skip = (pageNumber - 1) * pageSize;
|
|
311
|
+
const result = await collection.where(whereConditions).orderBy("createdAt", sort).skip(skip).limit(pageSize).get();
|
|
312
|
+
const countResult = await collection.where(whereConditions).count();
|
|
313
|
+
const total = countResult.total || 0;
|
|
314
|
+
const records = result?.data || [];
|
|
315
|
+
const entityList = records.map(
|
|
316
|
+
(item) => transDataToChatEntity(item)
|
|
317
|
+
);
|
|
318
|
+
return [entityList, total];
|
|
319
|
+
} catch (error) {
|
|
320
|
+
console.error("Failed to query chat history, error:", error);
|
|
321
|
+
return [[], 0];
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function transDataToChatEntity(item) {
|
|
325
|
+
if (!item) {
|
|
326
|
+
return new ChatHistoryEntity();
|
|
327
|
+
}
|
|
328
|
+
const chatEntity = new ChatHistoryEntity();
|
|
329
|
+
chatEntity.botId = item.bot_id;
|
|
330
|
+
chatEntity.recordId = item.record_id;
|
|
331
|
+
chatEntity.role = item.role;
|
|
332
|
+
chatEntity.status = item.status;
|
|
333
|
+
chatEntity.content = item.content;
|
|
334
|
+
chatEntity.sender = item.sender;
|
|
335
|
+
chatEntity.conversation = item.conversation;
|
|
336
|
+
chatEntity.type = item.type;
|
|
337
|
+
chatEntity.triggerSrc = item.trigger_src;
|
|
338
|
+
chatEntity.originMsg = item.origin_msg;
|
|
339
|
+
chatEntity.replyTo = item.reply_to;
|
|
340
|
+
chatEntity.reply = item.reply;
|
|
341
|
+
chatEntity.traceId = item.trace_id;
|
|
342
|
+
chatEntity.needAsyncReply = item.need_async_reply;
|
|
343
|
+
chatEntity.asyncReply = item.async_reply;
|
|
344
|
+
chatEntity.createdAt = item.createdAt;
|
|
345
|
+
chatEntity.updatedAt = item.updatedAt;
|
|
346
|
+
return chatEntity;
|
|
347
|
+
}
|
|
348
|
+
async function queryForLLM({
|
|
349
|
+
tcbClient,
|
|
350
|
+
botId,
|
|
351
|
+
pageSize = 10,
|
|
352
|
+
startCreatedAt,
|
|
353
|
+
triggerSrc
|
|
354
|
+
}) {
|
|
355
|
+
if (startCreatedAt === void 0) {
|
|
356
|
+
startCreatedAt = Date.now() - 24 * 60 * 60 * 1e3;
|
|
357
|
+
}
|
|
358
|
+
const recordEntityList = [];
|
|
359
|
+
const [recordList] = await describeChatHistory({
|
|
360
|
+
tcbClient,
|
|
361
|
+
botId,
|
|
362
|
+
sort: "desc",
|
|
363
|
+
pageSize,
|
|
364
|
+
startCreatedAt,
|
|
365
|
+
triggerSrc
|
|
366
|
+
});
|
|
367
|
+
recordEntityList.push(...recordList.reverse());
|
|
368
|
+
const entityMap = /* @__PURE__ */ new Map();
|
|
369
|
+
recordEntityList.filter((item) => {
|
|
370
|
+
if (item.needAsyncReply === true) {
|
|
371
|
+
return !!item.asyncReply;
|
|
372
|
+
} else {
|
|
373
|
+
return !!item.content;
|
|
374
|
+
}
|
|
375
|
+
}).forEach((item) => {
|
|
376
|
+
entityMap.set(item.recordId, item);
|
|
377
|
+
});
|
|
378
|
+
const result = [];
|
|
379
|
+
recordEntityList.forEach((item) => {
|
|
380
|
+
const { role, content, reply } = item;
|
|
381
|
+
if (role === "user" && content?.length !== 0) {
|
|
382
|
+
if (entityMap.has(reply)) {
|
|
383
|
+
result.push({ role, content });
|
|
384
|
+
result.push({
|
|
385
|
+
role: entityMap.get(reply).role,
|
|
386
|
+
content: entityMap.get(reply).content
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
if (result.length % 2 === 1) {
|
|
392
|
+
result.splice(-1, 1);
|
|
393
|
+
}
|
|
394
|
+
return result;
|
|
395
|
+
}
|
|
396
|
+
var ChatHistoryEntity = class {
|
|
397
|
+
};
|
|
398
|
+
|
|
399
|
+
// src/agent.ts
|
|
400
|
+
var YuanqiAgentError = class extends Error {
|
|
401
|
+
constructor(message, code) {
|
|
402
|
+
super(message);
|
|
403
|
+
this.name = "YuanqiAgentError";
|
|
404
|
+
if (code) this.code = code;
|
|
405
|
+
}
|
|
406
|
+
};
|
|
165
407
|
var YuanqiAgent = class extends AbstractAgent {
|
|
166
408
|
constructor(config) {
|
|
167
409
|
super(config);
|
|
410
|
+
this.finalCloudCredential = {};
|
|
168
411
|
this.yuanqiConfig = config.yuanqiConfig;
|
|
169
412
|
this.model = new OpenAI({
|
|
170
413
|
apiKey: "",
|
|
171
414
|
baseURL: this.yuanqiConfig.request?.baseUrl || "https://yuanqi.tencent.com/openapi/v1/agent"
|
|
172
415
|
});
|
|
173
416
|
this.finalAppId = this.yuanqiConfig.appId || this.yuanqiConfig.request?.body?.assistantId || process.env.YUANQI_APP_ID || "";
|
|
417
|
+
this.finalCloudCredential = {
|
|
418
|
+
secretId: this.yuanqiConfig.credential?.secretId || process.env.TENCENTCLOUD_SECRETID,
|
|
419
|
+
secretKey: this.yuanqiConfig.credential?.secretKey || process.env.TENCENTCLOUD_SECRETKEY,
|
|
420
|
+
token: this.yuanqiConfig.credential?.token || process.env.TENCENTCLOUD_SESSIONTOKEN
|
|
421
|
+
};
|
|
174
422
|
}
|
|
175
423
|
generateRequestBody({
|
|
176
424
|
messages,
|
|
@@ -194,27 +442,49 @@ var YuanqiAgent = class extends AbstractAgent {
|
|
|
194
442
|
}
|
|
195
443
|
async _run(subscriber, input) {
|
|
196
444
|
try {
|
|
197
|
-
const { messages, runId
|
|
198
|
-
const
|
|
445
|
+
const { messages, runId } = input;
|
|
446
|
+
const openai = this.model;
|
|
447
|
+
const threadId = input.threadId || randomUUID();
|
|
199
448
|
subscriber.next({
|
|
200
449
|
type: EventType2.RUN_STARTED,
|
|
201
450
|
threadId,
|
|
202
451
|
runId
|
|
203
452
|
});
|
|
204
453
|
if (!this.finalAppId) {
|
|
205
|
-
throw new
|
|
206
|
-
"YUANQI_APP_ID is required, check your env variables or config passed with the adapter"
|
|
454
|
+
throw new YuanqiAgentError(
|
|
455
|
+
"YUANQI_APP_ID is required, check your env variables or config passed with the adapter",
|
|
456
|
+
"MISSING_YUANQI_APP_ID"
|
|
207
457
|
);
|
|
208
458
|
}
|
|
209
459
|
if (!this.yuanqiConfig.appKey && !process.env.YUANQI_APP_KEY) {
|
|
210
|
-
throw new
|
|
211
|
-
"YUANQI_APP_KEY is required, check your env variables or config passed with the adapter"
|
|
460
|
+
throw new YuanqiAgentError(
|
|
461
|
+
"YUANQI_APP_KEY is required, check your env variables or config passed with the adapter",
|
|
462
|
+
"MISSING_YUANQI_APP_KEY"
|
|
212
463
|
);
|
|
213
464
|
}
|
|
214
|
-
const
|
|
215
|
-
|
|
465
|
+
const trimmedCount = messages.length - 1;
|
|
466
|
+
if (trimmedCount > 0) {
|
|
467
|
+
subscriber.next({
|
|
468
|
+
type: EventType2.RAW,
|
|
469
|
+
rawEvent: {
|
|
470
|
+
message: `Yuanqi handles message history itself, so that a total of ${trimmedCount} messages before the last user message will be trimmed.`,
|
|
471
|
+
type: "warn"
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
const latestUserMessage = messages.filter((m) => m.role === "user").pop();
|
|
476
|
+
if (!latestUserMessage) {
|
|
477
|
+
throw new YuanqiAgentError(
|
|
478
|
+
"No user message found, please send a message first.",
|
|
479
|
+
"MESSAGE_FORMAT_ERROR"
|
|
480
|
+
);
|
|
481
|
+
}
|
|
482
|
+
const allMessages = await this.getChatHistory(
|
|
483
|
+
subscriber,
|
|
484
|
+
latestUserMessage
|
|
485
|
+
);
|
|
216
486
|
const body = this.generateRequestBody({
|
|
217
|
-
messages:
|
|
487
|
+
messages: allMessages,
|
|
218
488
|
input
|
|
219
489
|
});
|
|
220
490
|
const stream = await openai.chat.completions.create(
|
|
@@ -231,27 +501,192 @@ var YuanqiAgent = class extends AbstractAgent {
|
|
|
231
501
|
}
|
|
232
502
|
}
|
|
233
503
|
);
|
|
234
|
-
const
|
|
235
|
-
const
|
|
504
|
+
const userRecordId = `record-${randomUUID().slice(0, 8)}`;
|
|
505
|
+
const assistantRecordId = `record-${randomUUID().slice(0, 8)}`;
|
|
506
|
+
const context = { threadId, runId, messageId: userRecordId };
|
|
507
|
+
let fullAssistantContent = "";
|
|
236
508
|
for await (const event of processYuanqiStream(stream, context)) {
|
|
237
509
|
subscriber.next(event);
|
|
510
|
+
if (event.type === EventType2.TEXT_MESSAGE_CONTENT && event.delta) {
|
|
511
|
+
fullAssistantContent += event.delta;
|
|
512
|
+
}
|
|
238
513
|
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
514
|
+
const userContent = typeof latestUserMessage?.content === "string" ? latestUserMessage.content : latestUserMessage?.content?.filter((c) => c.type === "text").map((c) => c.text).join("") || "";
|
|
515
|
+
await this.saveChatHistory(
|
|
516
|
+
subscriber,
|
|
517
|
+
input,
|
|
518
|
+
userRecordId,
|
|
519
|
+
assistantRecordId,
|
|
520
|
+
userContent,
|
|
521
|
+
fullAssistantContent
|
|
522
|
+
);
|
|
523
|
+
subscriber.next({
|
|
524
|
+
type: EventType2.RUN_FINISHED,
|
|
525
|
+
threadId,
|
|
526
|
+
runId
|
|
527
|
+
});
|
|
528
|
+
} catch (e) {
|
|
529
|
+
console.error("[ERROR] Uncaught error: ", JSON.stringify(e));
|
|
530
|
+
let code = "UNKNOWN_ERROR";
|
|
531
|
+
let message = JSON.stringify(e);
|
|
532
|
+
if (e instanceof YuanqiAgentError) {
|
|
533
|
+
code = e.code || "AGENT_ERROR";
|
|
534
|
+
message = e.message;
|
|
535
|
+
} else if (e instanceof Error) {
|
|
536
|
+
code = e.name || "ERROR";
|
|
537
|
+
message = e.message;
|
|
244
538
|
}
|
|
245
539
|
subscriber.next({
|
|
246
540
|
type: EventType2.RUN_ERROR,
|
|
247
|
-
|
|
248
|
-
|
|
541
|
+
code,
|
|
542
|
+
message: `Sorry, an error occurred while running the agent: Error code ${code}, ${message}`
|
|
249
543
|
});
|
|
250
544
|
} finally {
|
|
251
545
|
subscriber.complete();
|
|
252
546
|
}
|
|
253
547
|
}
|
|
548
|
+
// Can be override by subclasses
|
|
549
|
+
async getChatHistory(subscriber, latestUserMessage) {
|
|
550
|
+
const botId = `bot-yuanqi-${this.finalAppId}`;
|
|
551
|
+
const tcbClient = this.getTcbClient();
|
|
552
|
+
const isDBReady = await this.checkIsDatabaseReady();
|
|
553
|
+
if (!isDBReady) {
|
|
554
|
+
subscriber.next({
|
|
555
|
+
type: EventType2.RAW,
|
|
556
|
+
rawEvent: {
|
|
557
|
+
message: `Chat history database is not ready, skip history loading.`,
|
|
558
|
+
type: "warn"
|
|
559
|
+
}
|
|
560
|
+
});
|
|
561
|
+
return convertMessagesToOpenAI([latestUserMessage]);
|
|
562
|
+
}
|
|
563
|
+
let historyMessages = [];
|
|
564
|
+
const historyCount = this.yuanqiConfig.historyCount ?? 10;
|
|
565
|
+
const historyRecords = await queryForLLM({
|
|
566
|
+
tcbClient,
|
|
567
|
+
botId,
|
|
568
|
+
pageSize: historyCount
|
|
569
|
+
});
|
|
570
|
+
historyMessages = historyRecords.map((record) => ({
|
|
571
|
+
role: record.role,
|
|
572
|
+
content: [{ type: "text", text: record.content }]
|
|
573
|
+
}));
|
|
574
|
+
const allMessages = historyMessages.concat(
|
|
575
|
+
convertMessagesToOpenAI([latestUserMessage])
|
|
576
|
+
);
|
|
577
|
+
return allMessages;
|
|
578
|
+
}
|
|
579
|
+
// Can be override by subclasses
|
|
580
|
+
async saveChatHistory(subscriber, input, userRecordId, assistantRecordId, userContent, assistantContent) {
|
|
581
|
+
const botId = `bot-yuanqi-${this.finalAppId}`;
|
|
582
|
+
const { threadId, runId } = input;
|
|
583
|
+
const tcbClient = this.getTcbClient();
|
|
584
|
+
const isDBReady = await this.checkIsDatabaseReady();
|
|
585
|
+
if (!isDBReady) {
|
|
586
|
+
subscriber.next({
|
|
587
|
+
type: EventType2.RAW,
|
|
588
|
+
rawEvent: {
|
|
589
|
+
message: `Chat history database is not ready, skip history saving.`,
|
|
590
|
+
type: "warn"
|
|
591
|
+
}
|
|
592
|
+
});
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
const userEntity = new ChatHistoryEntity();
|
|
596
|
+
userEntity.recordId = userRecordId;
|
|
597
|
+
userEntity.botId = botId;
|
|
598
|
+
userEntity.role = "user";
|
|
599
|
+
userEntity.content = userContent;
|
|
600
|
+
userEntity.conversation = threadId;
|
|
601
|
+
userEntity.reply = assistantRecordId;
|
|
602
|
+
userEntity.triggerSrc = "";
|
|
603
|
+
userEntity.traceId = randomUUID();
|
|
604
|
+
await createChatHistory({ tcbClient, chatHistoryEntity: userEntity });
|
|
605
|
+
const assistantEntity = new ChatHistoryEntity();
|
|
606
|
+
assistantEntity.recordId = assistantRecordId;
|
|
607
|
+
assistantEntity.botId = botId;
|
|
608
|
+
assistantEntity.role = "assistant";
|
|
609
|
+
assistantEntity.content = assistantContent;
|
|
610
|
+
assistantEntity.conversation = threadId;
|
|
611
|
+
assistantEntity.replyTo = userRecordId;
|
|
612
|
+
assistantEntity.triggerSrc = "";
|
|
613
|
+
assistantEntity.traceId = runId;
|
|
614
|
+
assistantEntity.status = "done";
|
|
615
|
+
await createChatHistory({
|
|
616
|
+
tcbClient,
|
|
617
|
+
chatHistoryEntity: assistantEntity
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
getTcbClient() {
|
|
621
|
+
const envId = this.yuanqiConfig.envId || getCloudbaseEnvId();
|
|
622
|
+
const tcbClient = tcb.init({
|
|
623
|
+
env: envId,
|
|
624
|
+
secretId: this.finalCloudCredential.secretId,
|
|
625
|
+
secretKey: this.finalCloudCredential.secretKey,
|
|
626
|
+
sessionToken: this.finalCloudCredential.token
|
|
627
|
+
});
|
|
628
|
+
return tcbClient;
|
|
629
|
+
}
|
|
630
|
+
async checkIsDatabaseReady() {
|
|
631
|
+
try {
|
|
632
|
+
const envId = this.yuanqiConfig.envId || getCloudbaseEnvId();
|
|
633
|
+
if (!envId) {
|
|
634
|
+
throw new YuanqiAgentError(
|
|
635
|
+
"When saving chat history to CloudBase, CLOUDBASE_ENV_ID is required, check your env variables or config passed with the adapter",
|
|
636
|
+
"MISSING_CLOUDBASE_ENV_ID"
|
|
637
|
+
);
|
|
638
|
+
}
|
|
639
|
+
if (!this.finalCloudCredential.token) {
|
|
640
|
+
if (!this.finalCloudCredential.secretId) {
|
|
641
|
+
throw new YuanqiAgentError(
|
|
642
|
+
"When saving chat history to CloudBase, TENCENTCLOUD_SECRETID is required, check your env variables or config passed with the adapter",
|
|
643
|
+
"MISSING_SECRET_ID"
|
|
644
|
+
);
|
|
645
|
+
}
|
|
646
|
+
if (!this.finalCloudCredential.secretKey) {
|
|
647
|
+
throw new YuanqiAgentError(
|
|
648
|
+
"When saving chat history to CloudBase, TENCENTCLOUD_SECRETKEY is required, check your env variables or config passed with the adapter",
|
|
649
|
+
"MISSING_SECRET_KEY"
|
|
650
|
+
);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
const managedTcbClient = managedTcb.init({
|
|
654
|
+
envId,
|
|
655
|
+
secretId: this.finalCloudCredential.secretId,
|
|
656
|
+
secretKey: this.finalCloudCredential.secretKey,
|
|
657
|
+
token: this.finalCloudCredential.token
|
|
658
|
+
});
|
|
659
|
+
const checkDBRes = await managedTcbClient.database.checkCollectionExists(
|
|
660
|
+
CHAT_HISTORY_DATA_SOURCE
|
|
661
|
+
);
|
|
662
|
+
if (checkDBRes && checkDBRes.Exists) {
|
|
663
|
+
return true;
|
|
664
|
+
} else if (checkDBRes && !checkDBRes.Exists) {
|
|
665
|
+
await managedTcbClient.database.createCollection(
|
|
666
|
+
CHAT_HISTORY_DATA_SOURCE
|
|
667
|
+
);
|
|
668
|
+
return true;
|
|
669
|
+
} else {
|
|
670
|
+
throw new Error("Check database exists failed");
|
|
671
|
+
}
|
|
672
|
+
} catch (dbError) {
|
|
673
|
+
console.error(
|
|
674
|
+
"[ERROR] Failed to check/create chat history collection:",
|
|
675
|
+
JSON.stringify(dbError)
|
|
676
|
+
);
|
|
677
|
+
return false;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
254
680
|
};
|
|
681
|
+
function getCloudbaseEnvId() {
|
|
682
|
+
if (process.env.CBR_ENV_ID) {
|
|
683
|
+
return process.env.CBR_ENV_ID;
|
|
684
|
+
} else if (process.env.SCF_NAMESPACE) {
|
|
685
|
+
return process.env.SCF_NAMESPACE;
|
|
686
|
+
} else {
|
|
687
|
+
return process.env.CLOUDBASE_ENV_ID || "";
|
|
688
|
+
}
|
|
689
|
+
}
|
|
255
690
|
function convertMessagesToOpenAI(messages, systemPrompt) {
|
|
256
691
|
const openaiMessages = [];
|
|
257
692
|
if (systemPrompt) {
|
|
@@ -299,8 +734,15 @@ function convertMessagesToOpenAI(messages, systemPrompt) {
|
|
|
299
734
|
return openaiMessages;
|
|
300
735
|
}
|
|
301
736
|
export {
|
|
737
|
+
ChatHistoryEntity,
|
|
302
738
|
YuanqiAgent,
|
|
303
|
-
|
|
304
|
-
convertMessagesToOpenAI
|
|
739
|
+
YuanqiAgentError,
|
|
740
|
+
convertMessagesToOpenAI,
|
|
741
|
+
createChatHistory,
|
|
742
|
+
describeChatHistory,
|
|
743
|
+
processYuanqiStream,
|
|
744
|
+
queryForLLM,
|
|
745
|
+
transDataToChatEntity,
|
|
746
|
+
updateChatHistoryByRecordId
|
|
305
747
|
};
|
|
306
748
|
//# sourceMappingURL=index.mjs.map
|