@cloudbase/agent-adapter-adp 0.0.15 → 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 +53 -0
- package/dist/index.d.mts +39 -5
- package/dist/index.d.ts +39 -5
- package/dist/index.js +338 -87
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +338 -87
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -8
- package/CHANGELOG.md +0 -48
package/dist/index.js
CHANGED
|
@@ -65,7 +65,7 @@ function camelToSnakeKeys(obj) {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// src/constant.ts
|
|
68
|
-
var
|
|
68
|
+
var DOCUMENT_MIME_TYPES = {
|
|
69
69
|
"text/plain": "txt",
|
|
70
70
|
"application/msword": "doc",
|
|
71
71
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
|
|
@@ -73,6 +73,15 @@ var MIME_TYPES = {
|
|
|
73
73
|
"application/vnd.ms-powerpoint": "ppt",
|
|
74
74
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx"
|
|
75
75
|
};
|
|
76
|
+
var IMAGE_MIME_TYPES = {
|
|
77
|
+
"image/png": "png",
|
|
78
|
+
"image/jpeg": "jpg",
|
|
79
|
+
"image/bmp": "bmp"
|
|
80
|
+
};
|
|
81
|
+
var MIME_TYPES = {
|
|
82
|
+
...DOCUMENT_MIME_TYPES,
|
|
83
|
+
...IMAGE_MIME_TYPES
|
|
84
|
+
};
|
|
76
85
|
|
|
77
86
|
// src/types.ts
|
|
78
87
|
var ReplyMethod = /* @__PURE__ */ ((ReplyMethod2) => {
|
|
@@ -108,6 +117,7 @@ var CurrentNodeStatus = /* @__PURE__ */ ((CurrentNodeStatus2) => {
|
|
|
108
117
|
// src/agent.ts
|
|
109
118
|
var import_crypto = require("crypto");
|
|
110
119
|
var import_tencentcloud_sdk_nodejs_lke = require("tencentcloud-sdk-nodejs-lke");
|
|
120
|
+
var import_cos_nodejs_sdk_v5 = __toESM(require("cos-nodejs-sdk-v5"));
|
|
111
121
|
var AdpAgentError = class extends Error {
|
|
112
122
|
constructor(message, code) {
|
|
113
123
|
super(message);
|
|
@@ -118,73 +128,85 @@ var AdpAgentError = class extends Error {
|
|
|
118
128
|
var AdpAgent = class extends import_client.AbstractAgent {
|
|
119
129
|
constructor(config) {
|
|
120
130
|
super(config);
|
|
131
|
+
this.finalAppKey = "";
|
|
132
|
+
this.finalCloudCredential = {};
|
|
121
133
|
this.adpConfig = config.adpConfig;
|
|
134
|
+
this.finalAppKey = this.adpConfig.appKey || this.adpConfig.request?.body?.botAppKey || process.env.ADP_APP_KEY || "";
|
|
122
135
|
this.reqAppClient = import_axios.default.create({
|
|
123
136
|
baseURL: this.adpConfig.request?.baseUrl || "https://wss.lke.cloud.tencent.com"
|
|
124
137
|
});
|
|
125
138
|
const LkeClient = import_tencentcloud_sdk_nodejs_lke.lke.v20231130.Client;
|
|
139
|
+
this.finalCloudCredential = {
|
|
140
|
+
secretId: this.adpConfig.credential?.secretId || process.env.TENCENTCLOUD_SECRETID,
|
|
141
|
+
secretKey: this.adpConfig.credential?.secretKey || process.env.TENCENTCLOUD_SECRETKEY,
|
|
142
|
+
token: this.adpConfig.credential?.token || process.env.TENCENTCLOUD_SESSIONTOKEN
|
|
143
|
+
};
|
|
126
144
|
this.reqLkeClient = new LkeClient({
|
|
127
|
-
credential:
|
|
128
|
-
secretId: this.adpConfig.credential?.secretId || process.env.TENCENTCLOUD_SECRETID,
|
|
129
|
-
secretKey: this.adpConfig.credential?.secretKey || process.env.TENCENTCLOUD_SECRETKEY,
|
|
130
|
-
token: this.adpConfig.credential?.token || process.env.TENCENTCLOUD_SESSIONTOKEN
|
|
131
|
-
}
|
|
145
|
+
credential: this.finalCloudCredential
|
|
132
146
|
});
|
|
133
147
|
}
|
|
134
148
|
generateRequestBody({
|
|
135
149
|
message,
|
|
136
150
|
fileInfos,
|
|
137
|
-
|
|
138
|
-
threadId,
|
|
139
|
-
forwardedProps
|
|
151
|
+
input
|
|
140
152
|
}) {
|
|
153
|
+
const { state, runId, threadId, forwardedProps } = input;
|
|
141
154
|
const requestBody = {
|
|
142
155
|
incremental: true,
|
|
143
156
|
stream: "enable",
|
|
144
157
|
...this.adpConfig.request?.body || {},
|
|
145
158
|
...forwardedProps || {},
|
|
146
|
-
botAppKey: this.
|
|
147
|
-
visitorBizId: forwardedProps?.visitorBizId || (0, import_crypto.randomUUID)(),
|
|
159
|
+
botAppKey: this.finalAppKey,
|
|
160
|
+
visitorBizId: state?.__request_context__?.id || forwardedProps?.visitorBizId || (0, import_crypto.randomUUID)(),
|
|
148
161
|
requestId: runId,
|
|
149
|
-
sessionId: threadId
|
|
162
|
+
sessionId: threadId,
|
|
150
163
|
content: message,
|
|
151
164
|
fileInfos
|
|
152
165
|
};
|
|
153
166
|
return requestBody;
|
|
154
167
|
}
|
|
155
|
-
// @ts-ignore
|
|
156
168
|
run(input) {
|
|
157
169
|
return new import_rxjs.Observable((subscriber) => {
|
|
158
170
|
this._run(subscriber, input);
|
|
159
171
|
});
|
|
160
172
|
}
|
|
161
173
|
async _run(subscriber, input) {
|
|
174
|
+
let thinkingMessageSet = /* @__PURE__ */ new Set();
|
|
175
|
+
let thinkFinishedMessageSet = /* @__PURE__ */ new Set();
|
|
162
176
|
try {
|
|
163
|
-
const {
|
|
177
|
+
const { runId } = input;
|
|
178
|
+
const threadId = input.threadId || (0, import_crypto.randomUUID)();
|
|
164
179
|
subscriber.next({
|
|
165
180
|
type: import_client.EventType.RUN_STARTED,
|
|
166
181
|
runId,
|
|
167
182
|
threadId
|
|
168
183
|
});
|
|
169
|
-
if (!this.
|
|
184
|
+
if (!this.finalAppKey) {
|
|
170
185
|
throw new AdpAgentError(
|
|
171
|
-
"
|
|
186
|
+
"ADP_APP_KEY is required, check your env variables or config passed with the adapter",
|
|
172
187
|
"MISSING_APP_KEY"
|
|
173
188
|
);
|
|
174
189
|
}
|
|
175
|
-
const
|
|
176
|
-
|
|
190
|
+
const latestUserMessage = input.messages.filter((m) => m.role === "user").pop();
|
|
191
|
+
if (!latestUserMessage) {
|
|
192
|
+
throw new AdpAgentError(
|
|
193
|
+
"Message content format error, or empty content",
|
|
194
|
+
"INVALID_MESSAGE_FORMAT"
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
const { message: docExtractedMessage, fileInfos } = await this.extractDocuments(latestUserMessage, threadId, subscriber);
|
|
198
|
+
const message = await this.convertAGUIMessagesToAdpMessages(docExtractedMessage);
|
|
177
199
|
if (!message) {
|
|
178
200
|
throw new AdpAgentError(
|
|
179
201
|
"Message content format error, or empty content",
|
|
180
|
-
"
|
|
202
|
+
"INVALID_MESSAGE_FORMAT"
|
|
181
203
|
);
|
|
182
204
|
}
|
|
183
|
-
if (
|
|
205
|
+
if (input.messages.length > 1) {
|
|
184
206
|
subscriber.next({
|
|
185
207
|
type: import_client.EventType.RAW,
|
|
186
208
|
rawEvent: {
|
|
187
|
-
message: `ADP handles message history itself, so that a total of ${
|
|
209
|
+
message: `ADP handles message history itself, so that a total of ${input.messages.length - 1} messages before and including last assistant message will be trimmed.`,
|
|
188
210
|
type: "warn"
|
|
189
211
|
}
|
|
190
212
|
});
|
|
@@ -192,9 +214,7 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
192
214
|
const requestBody = this.generateRequestBody({
|
|
193
215
|
message,
|
|
194
216
|
fileInfos,
|
|
195
|
-
|
|
196
|
-
threadId,
|
|
197
|
-
forwardedProps
|
|
217
|
+
input
|
|
198
218
|
});
|
|
199
219
|
const response = await this.reqAppClient.post(
|
|
200
220
|
this.adpConfig.request?.endpoint || "/v1/qbot/chat/sse",
|
|
@@ -205,7 +225,6 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
205
225
|
let buffer = "";
|
|
206
226
|
let interruptRequested = false;
|
|
207
227
|
let thinkingStart = false;
|
|
208
|
-
let thinkingMessageSet = /* @__PURE__ */ new Set();
|
|
209
228
|
for await (const chunk of sseStream) {
|
|
210
229
|
buffer += chunk.toString();
|
|
211
230
|
const parts = buffer.split("\n\n");
|
|
@@ -232,6 +251,22 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
232
251
|
}
|
|
233
252
|
switch (data.type) {
|
|
234
253
|
case "reply": {
|
|
254
|
+
const messageId = data.payload.record_id;
|
|
255
|
+
const isFinal = data.payload.is_final;
|
|
256
|
+
if (thinkingStart) {
|
|
257
|
+
thinkingStart = false;
|
|
258
|
+
for (const index of thinkingMessageSet) {
|
|
259
|
+
subscriber.next({
|
|
260
|
+
type: import_client.EventType.THINKING_TEXT_MESSAGE_END,
|
|
261
|
+
messageId: `${messageId}-think-${index}`
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
thinkingMessageSet.clear();
|
|
265
|
+
subscriber.next({
|
|
266
|
+
type: import_client.EventType.THINKING_END,
|
|
267
|
+
messageId
|
|
268
|
+
});
|
|
269
|
+
}
|
|
235
270
|
if (data.payload.is_from_self) {
|
|
236
271
|
if (data.payload.is_evil) {
|
|
237
272
|
throw new AdpAgentError(
|
|
@@ -242,8 +277,6 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
242
277
|
continue;
|
|
243
278
|
}
|
|
244
279
|
}
|
|
245
|
-
const messageId = data.payload.record_id;
|
|
246
|
-
const isFinal = data.payload.is_final;
|
|
247
280
|
data.payload.content = data.payload.content.replace(
|
|
248
281
|
/\\n/g,
|
|
249
282
|
"\n\n"
|
|
@@ -323,51 +356,47 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
323
356
|
});
|
|
324
357
|
}
|
|
325
358
|
data.payload.procedures.forEach((procedure) => {
|
|
326
|
-
|
|
327
|
-
|
|
359
|
+
const index = procedure.index.toString();
|
|
360
|
+
if (!thinkingMessageSet.has(index) && !thinkFinishedMessageSet.has(index)) {
|
|
361
|
+
thinkingMessageSet.add(index);
|
|
328
362
|
subscriber.next({
|
|
329
363
|
type: import_client.EventType.THINKING_TEXT_MESSAGE_START,
|
|
330
|
-
messageId
|
|
364
|
+
messageId: `${messageId}-think-${index}`,
|
|
331
365
|
delta: procedure.debugging.content
|
|
332
366
|
});
|
|
333
367
|
} else {
|
|
334
368
|
if (procedure.status === "processing") {
|
|
335
369
|
subscriber.next({
|
|
336
370
|
type: import_client.EventType.THINKING_TEXT_MESSAGE_CONTENT,
|
|
337
|
-
messageId
|
|
371
|
+
messageId: `${messageId}-think-${index}`,
|
|
338
372
|
delta: procedure.debugging.content
|
|
339
373
|
});
|
|
340
374
|
} else {
|
|
341
|
-
thinkingMessageSet.delete(
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
375
|
+
thinkingMessageSet.delete(index);
|
|
376
|
+
if (!thinkFinishedMessageSet.has(index)) {
|
|
377
|
+
thinkFinishedMessageSet.add(index);
|
|
378
|
+
subscriber.next({
|
|
379
|
+
type: import_client.EventType.THINKING_TEXT_MESSAGE_END,
|
|
380
|
+
messageId: `${messageId}-think-${index}`
|
|
381
|
+
});
|
|
382
|
+
}
|
|
346
383
|
}
|
|
347
384
|
}
|
|
348
385
|
});
|
|
349
|
-
const allFinished = data.payload.procedures.every(
|
|
350
|
-
(procedure) => procedure.status !== "processing"
|
|
351
|
-
);
|
|
352
|
-
if (allFinished) {
|
|
353
|
-
thinkingStart = false;
|
|
354
|
-
thinkingMessageSet.clear();
|
|
355
|
-
subscriber.next({
|
|
356
|
-
type: import_client.EventType.THINKING_END,
|
|
357
|
-
messageId
|
|
358
|
-
});
|
|
359
|
-
}
|
|
360
386
|
break;
|
|
361
387
|
}
|
|
362
388
|
case "error": {
|
|
363
|
-
console.error(
|
|
389
|
+
console.error(
|
|
390
|
+
"[ERROR] ADP throws error: ",
|
|
391
|
+
JSON.stringify(data)
|
|
392
|
+
);
|
|
364
393
|
throw new AdpAgentError(
|
|
365
394
|
data.error.message,
|
|
366
|
-
`ADP_ERROR_${data.error.code}`
|
|
395
|
+
data.error.code ? `ADP_ERROR_${data.error.code}` : "ADP_ERROR_-1"
|
|
367
396
|
);
|
|
368
397
|
}
|
|
369
398
|
case "token_stat": {
|
|
370
|
-
console.debug(JSON.stringify(data));
|
|
399
|
+
console.debug("[DEBUG] ADP token stat: ", JSON.stringify(data));
|
|
371
400
|
break;
|
|
372
401
|
}
|
|
373
402
|
case "reference": {
|
|
@@ -397,7 +426,7 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
397
426
|
}
|
|
398
427
|
subscriber.complete();
|
|
399
428
|
} catch (e) {
|
|
400
|
-
console.error(JSON.stringify(e));
|
|
429
|
+
console.error("[ERROR] Uncaught error: ", JSON.stringify(e));
|
|
401
430
|
let code = "UNKNOWN_ERROR";
|
|
402
431
|
let message = JSON.stringify(e);
|
|
403
432
|
if (e instanceof import_axios.AxiosError) {
|
|
@@ -413,31 +442,75 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
413
442
|
message: `Sorry, an error occurred while running the agent: Error code ${code}, ${message}`
|
|
414
443
|
});
|
|
415
444
|
subscriber.complete();
|
|
445
|
+
} finally {
|
|
446
|
+
thinkingMessageSet.clear();
|
|
447
|
+
thinkFinishedMessageSet.clear();
|
|
416
448
|
}
|
|
417
449
|
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
let result = "";
|
|
421
|
-
let trimmed = messages.length;
|
|
422
|
-
for (const message of messages.reverse()) {
|
|
423
|
-
if (message.role === "assistant") {
|
|
424
|
-
break;
|
|
425
|
-
}
|
|
450
|
+
async convertAGUIMessagesToAdpMessages(message) {
|
|
451
|
+
let result = "";
|
|
426
452
|
if (message.role === "user") {
|
|
427
|
-
trimmed--;
|
|
428
453
|
let content = "";
|
|
429
454
|
if (typeof message.content === "string") {
|
|
430
455
|
content = message.content;
|
|
431
456
|
} else {
|
|
432
|
-
|
|
433
|
-
if (
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
457
|
+
if (this.adpConfig.enableUpload) {
|
|
458
|
+
if (!this.finalCloudCredential.token) {
|
|
459
|
+
if (!this.finalCloudCredential.secretId) {
|
|
460
|
+
throw new AdpAgentError(
|
|
461
|
+
"TENCENTCLOUD_SECRETID is required, check your env variables or config passed with the adapter",
|
|
462
|
+
"MISSING_SECRET_ID"
|
|
463
|
+
);
|
|
464
|
+
}
|
|
465
|
+
if (!this.finalCloudCredential.secretKey) {
|
|
466
|
+
throw new AdpAgentError(
|
|
467
|
+
"TENCENTCLOUD_SECRETKEY is required, check your env variables or config passed with the adapter",
|
|
468
|
+
"MISSING_SECRET_KEY"
|
|
469
|
+
);
|
|
470
|
+
}
|
|
439
471
|
}
|
|
440
|
-
|
|
472
|
+
const imageMap = /* @__PURE__ */ new Map();
|
|
473
|
+
const imagesToUpload = [];
|
|
474
|
+
message.content.forEach((item) => {
|
|
475
|
+
if (item.type === "binary") {
|
|
476
|
+
if (Object.keys(IMAGE_MIME_TYPES).includes(item.mimeType)) {
|
|
477
|
+
imagesToUpload.push(item);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
});
|
|
481
|
+
if (imagesToUpload.length) {
|
|
482
|
+
await this.uploadToCos(
|
|
483
|
+
imagesToUpload,
|
|
484
|
+
(data, _, file) => {
|
|
485
|
+
imageMap.set(
|
|
486
|
+
file.id || file.filename,
|
|
487
|
+
`https://${data.Location}`
|
|
488
|
+
);
|
|
489
|
+
},
|
|
490
|
+
(fileName, error) => {
|
|
491
|
+
throw new AdpAgentError(
|
|
492
|
+
`Upload image ${fileName} failed: ${error}`,
|
|
493
|
+
"UPLOAD_IMAGE_FAILED"
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
);
|
|
497
|
+
}
|
|
498
|
+
content = message.content.reduce((acc, cur) => {
|
|
499
|
+
if (cur.type === "text") {
|
|
500
|
+
return acc + `${cur.text} `;
|
|
501
|
+
} else if (cur.type === "binary") {
|
|
502
|
+
if (Object.keys(IMAGE_MIME_TYPES).includes(cur.mimeType)) {
|
|
503
|
+
if (imageMap.has(cur.id || cur.filename)) {
|
|
504
|
+
return acc + `}) `;
|
|
505
|
+
} else {
|
|
506
|
+
return acc;
|
|
507
|
+
}
|
|
508
|
+
} else return acc;
|
|
509
|
+
} else {
|
|
510
|
+
return acc;
|
|
511
|
+
}
|
|
512
|
+
}, "").trim();
|
|
513
|
+
}
|
|
441
514
|
}
|
|
442
515
|
result = `${message.role}: ${content}
|
|
443
516
|
${result}`;
|
|
@@ -445,36 +518,214 @@ ${result}`;
|
|
|
445
518
|
result = `${message.role}: ${message.content}
|
|
446
519
|
${result}`;
|
|
447
520
|
}
|
|
521
|
+
return result.trim();
|
|
448
522
|
}
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
const newMessages = messages.map((msg) => {
|
|
454
|
-
if (msg.role === "user" && Array.isArray(msg.content)) {
|
|
523
|
+
async extractDocuments(message, threadId, subscriber) {
|
|
524
|
+
const documentFiles = [];
|
|
525
|
+
let newMessage;
|
|
526
|
+
if (message.role === "user" && Array.isArray(message.content)) {
|
|
455
527
|
let newContent = [];
|
|
456
|
-
|
|
528
|
+
message.content.forEach((item) => {
|
|
457
529
|
if (item.type === "text") {
|
|
458
530
|
newContent.push(item);
|
|
459
531
|
} else if (item.type === "binary") {
|
|
460
|
-
if (Object.keys(
|
|
532
|
+
if (Object.keys(DOCUMENT_MIME_TYPES).includes(item.mimeType)) {
|
|
461
533
|
documentFiles.push(item);
|
|
534
|
+
} else {
|
|
535
|
+
newContent.push(item);
|
|
462
536
|
}
|
|
463
537
|
}
|
|
464
538
|
});
|
|
465
|
-
|
|
466
|
-
...
|
|
539
|
+
newMessage = {
|
|
540
|
+
...message,
|
|
467
541
|
content: newContent
|
|
468
542
|
};
|
|
469
|
-
} else
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
543
|
+
} else newMessage = message;
|
|
544
|
+
const fileInfos = [];
|
|
545
|
+
const successedFiles = [];
|
|
546
|
+
const failedFiles = [];
|
|
547
|
+
if (this.adpConfig.enableUpload) {
|
|
548
|
+
if (!this.finalCloudCredential.token) {
|
|
549
|
+
if (!this.finalCloudCredential.secretId) {
|
|
550
|
+
throw new AdpAgentError(
|
|
551
|
+
"TENCENTCLOUD_SECRETID is required, check your env variables or config passed with the adapter",
|
|
552
|
+
"MISSING_SECRET_ID"
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
if (!this.finalCloudCredential.secretKey) {
|
|
556
|
+
throw new AdpAgentError(
|
|
557
|
+
"TENCENTCLOUD_SECRETKEY is required, check your env variables or config passed with the adapter",
|
|
558
|
+
"MISSING_SECRET_KEY"
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
if (documentFiles.length) {
|
|
563
|
+
try {
|
|
564
|
+
await this.uploadToCos(
|
|
565
|
+
documentFiles,
|
|
566
|
+
(data, cosParams, file) => {
|
|
567
|
+
successedFiles.push({ data, cosParams, file });
|
|
568
|
+
},
|
|
569
|
+
(fileName, error) => {
|
|
570
|
+
failedFiles.push({ fileName, error });
|
|
571
|
+
}
|
|
572
|
+
);
|
|
573
|
+
} catch (e) {
|
|
574
|
+
console.error("Document upload failed: ", JSON.stringify(e));
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
if (successedFiles.length) {
|
|
578
|
+
for (const { data: cosData, cosParams, file } of successedFiles) {
|
|
579
|
+
const extName = MIME_TYPES[file.mimeType];
|
|
580
|
+
const requestBody = {
|
|
581
|
+
sessionId: threadId,
|
|
582
|
+
botAppKey: this.finalAppKey,
|
|
583
|
+
requestId: (0, import_crypto.randomUUID)(),
|
|
584
|
+
cosBucket: cosParams.Bucket,
|
|
585
|
+
fileType: extName,
|
|
586
|
+
fileName: file.filename,
|
|
587
|
+
cosUrl: cosParams.UploadPath,
|
|
588
|
+
cosHash: cosData.headers?.["x-cos-hash-crc64ecma"] || "",
|
|
589
|
+
eTag: cosData.ETag,
|
|
590
|
+
size: file.data?.length.toString() || "0"
|
|
591
|
+
};
|
|
592
|
+
const response = await this.reqAppClient.post(
|
|
593
|
+
this.adpConfig.request?.docParseEndpoint || "/v1/qbot/chat/docParse",
|
|
594
|
+
camelToSnakeKeys(requestBody),
|
|
595
|
+
{ responseType: "stream" }
|
|
596
|
+
);
|
|
597
|
+
const sseStream = response.data;
|
|
598
|
+
let buffer = "";
|
|
599
|
+
for await (const chunk of sseStream) {
|
|
600
|
+
buffer += chunk.toString();
|
|
601
|
+
const parts = buffer.split("\n\n");
|
|
602
|
+
buffer = parts.pop() || "";
|
|
603
|
+
for (const part of parts) {
|
|
604
|
+
if (!part.trim()) continue;
|
|
605
|
+
const event = { data: "", event: "" };
|
|
606
|
+
for (const line of part.split("\n")) {
|
|
607
|
+
if (line.startsWith("data:")) {
|
|
608
|
+
event.data += line.slice(5);
|
|
609
|
+
} else if (line.startsWith("event:")) {
|
|
610
|
+
event.event = line.slice(6);
|
|
611
|
+
}
|
|
612
|
+
}
|
|
613
|
+
if (event.data) {
|
|
614
|
+
let data;
|
|
615
|
+
try {
|
|
616
|
+
data = JSON.parse(event.data);
|
|
617
|
+
} catch (e) {
|
|
618
|
+
throw new AdpAgentError(
|
|
619
|
+
`ADP returned invalid data: ${event.data}`,
|
|
620
|
+
"INVALID_DATA"
|
|
621
|
+
);
|
|
622
|
+
}
|
|
623
|
+
switch (data.type) {
|
|
624
|
+
case "parsing": {
|
|
625
|
+
subscriber.next({
|
|
626
|
+
type: import_client.EventType.RAW,
|
|
627
|
+
rawEvent: {
|
|
628
|
+
message: `Parsing document ${file.filename}: ${data.payload.process}%`,
|
|
629
|
+
type: "info"
|
|
630
|
+
}
|
|
631
|
+
});
|
|
632
|
+
if (data.payload.is_final) {
|
|
633
|
+
if (data.payload.error_message) {
|
|
634
|
+
subscriber.next({
|
|
635
|
+
type: import_client.EventType.RAW,
|
|
636
|
+
rawEvent: {
|
|
637
|
+
message: `Parsing document ${file.filename} failed: ${data.payload.error_message}`,
|
|
638
|
+
type: "error"
|
|
639
|
+
}
|
|
640
|
+
});
|
|
641
|
+
} else {
|
|
642
|
+
const fileNameNoExt = file.filename.split(".").splice(0, -1).join(".");
|
|
643
|
+
fileInfos.push({
|
|
644
|
+
docId: data.payload.doc_id,
|
|
645
|
+
fileName: fileNameNoExt,
|
|
646
|
+
fileType: extName,
|
|
647
|
+
fileSize: file.data?.length.toString() || "0",
|
|
648
|
+
fileUrl: `https://${cosData.Location}`
|
|
649
|
+
});
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
break;
|
|
653
|
+
}
|
|
654
|
+
default: {
|
|
655
|
+
break;
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return {
|
|
665
|
+
message: newMessage,
|
|
666
|
+
fileInfos,
|
|
667
|
+
failedFiles
|
|
668
|
+
};
|
|
669
|
+
}
|
|
670
|
+
async getCosParams(mimeType) {
|
|
671
|
+
const extName = MIME_TYPES?.[mimeType];
|
|
672
|
+
if (!extName) {
|
|
673
|
+
throw new Error(`Unsupported mime type: ${mimeType}`);
|
|
674
|
+
}
|
|
675
|
+
const isPicture = Object.keys(IMAGE_MIME_TYPES).includes(mimeType);
|
|
676
|
+
const bizIdRes = await this.reqLkeClient.DescribeRobotBizIDByAppKey({
|
|
677
|
+
AppKey: this.finalAppKey
|
|
678
|
+
});
|
|
679
|
+
const storageRes = await this.reqLkeClient.DescribeStorageCredential({
|
|
680
|
+
BotBizId: bizIdRes.BotBizId,
|
|
681
|
+
FileType: extName,
|
|
682
|
+
IsPublic: isPicture,
|
|
683
|
+
TypeKey: "realtime"
|
|
684
|
+
});
|
|
685
|
+
return storageRes;
|
|
686
|
+
}
|
|
687
|
+
async uploadToCos(files, onSuccess, onError) {
|
|
688
|
+
const promises = [];
|
|
689
|
+
for (const file of files) {
|
|
690
|
+
const extName = MIME_TYPES?.[file.mimeType];
|
|
691
|
+
if (!extName) {
|
|
692
|
+
onError(file.filename || "unknown-file", "Unsupported file type");
|
|
693
|
+
continue;
|
|
694
|
+
}
|
|
695
|
+
const cosParams = await this.getCosParams(file.mimeType);
|
|
696
|
+
const cosClient = new import_cos_nodejs_sdk_v5.default({
|
|
697
|
+
SecretId: cosParams.Credentials?.TmpSecretId,
|
|
698
|
+
SecretKey: cosParams.Credentials?.TmpSecretKey,
|
|
699
|
+
SecurityToken: cosParams.Credentials?.Token
|
|
700
|
+
});
|
|
701
|
+
if (!cosParams.Bucket || !cosParams.Region || !cosParams.UploadPath) {
|
|
702
|
+
onError(file.filename || "unknown-file", "Failed to get COS params");
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
const promise = new Promise((resolve, reject) => {
|
|
706
|
+
cosClient.putObject(
|
|
707
|
+
{
|
|
708
|
+
Bucket: cosParams.Bucket,
|
|
709
|
+
Region: cosParams.Region,
|
|
710
|
+
Key: cosParams.UploadPath,
|
|
711
|
+
Body: file.data
|
|
712
|
+
},
|
|
713
|
+
(err, data) => {
|
|
714
|
+
if (err) {
|
|
715
|
+
onError(file.filename || "unknown-file", err.message);
|
|
716
|
+
reject();
|
|
717
|
+
} else {
|
|
718
|
+
onSuccess(data, cosParams, file);
|
|
719
|
+
resolve();
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
);
|
|
723
|
+
});
|
|
724
|
+
promises.push(promise);
|
|
725
|
+
}
|
|
726
|
+
await Promise.allSettled(promises);
|
|
727
|
+
}
|
|
728
|
+
};
|
|
478
729
|
// Annotate the CommonJS export names for ESM import in node:
|
|
479
730
|
0 && (module.exports = {
|
|
480
731
|
AdpAgent,
|