@cloudbase/agent-adapter-adp 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 +53 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +211 -164
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +211 -164
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -8
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@ npm install @cloudbase/agent-agents @cloudbase/agent-adapter-adp
|
|
|
15
15
|
- **Thinking Events**: Support for thinking/reasoning process events from the model
|
|
16
16
|
- **Workflow Integration**: Support for ADP workflows with tool call events
|
|
17
17
|
- **Custom Variables**: Pass custom parameters to workflows and knowledge base
|
|
18
|
+
- **File Upload**: Upload images and documents to COS for multimodal conversations (**requires `enableUpload: true`**)
|
|
18
19
|
|
|
19
20
|
## Environment Variables
|
|
20
21
|
|
|
@@ -121,6 +122,55 @@ observable.subscribe({
|
|
|
121
122
|
});
|
|
122
123
|
```
|
|
123
124
|
|
|
125
|
+
### With File Upload (Images and Documents)
|
|
126
|
+
|
|
127
|
+
When `enableUpload` is **set to `true`**, you can send images and documents in messages. Files are automatically uploaded to Tencent Cloud COS and processed by ADP.
|
|
128
|
+
|
|
129
|
+
**Note:** File upload requires Tencent Cloud credentials (`TENCENTCLOUD_SECRETID` and `TENCENTCLOUD_SECRETKEY`).
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { AdpAgent } from "@cloudbase/agent-adapter-adp";
|
|
133
|
+
import { randomUUID } from "crypto";
|
|
134
|
+
import * as fs from "fs";
|
|
135
|
+
|
|
136
|
+
const agent = new AdpAgent({
|
|
137
|
+
name: "my-adp-agent",
|
|
138
|
+
adpConfig: {
|
|
139
|
+
appKey: "your-app-key",
|
|
140
|
+
enableUpload: true, // Enable file upload
|
|
141
|
+
credential: {
|
|
142
|
+
secretId: "your-secret-id",
|
|
143
|
+
secretKey: "your-secret-key",
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
const observable = agent.run({
|
|
149
|
+
runId: randomUUID(),
|
|
150
|
+
threadId: randomUUID(),
|
|
151
|
+
messages: [
|
|
152
|
+
{
|
|
153
|
+
id: randomUUID(),
|
|
154
|
+
role: "user",
|
|
155
|
+
content: [
|
|
156
|
+
{ type: "text", text: "What's in this image?" },
|
|
157
|
+
{
|
|
158
|
+
type: "binary",
|
|
159
|
+
mimeType: "image/png",
|
|
160
|
+
filename: "screenshot.png",
|
|
161
|
+
data: fs.readFileSync("./screenshot.png"),
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**Supported file types:**
|
|
170
|
+
|
|
171
|
+
- **Images**: `image/png`, `image/jpeg`, `image/bmp`
|
|
172
|
+
- **Documents**: `application/pdf`, `application/msword`, `application/vnd.openxmlformats-officedocument.wordprocessingml.document`, `application/vnd.ms-powerpoint`, `application/vnd.openxmlformats-officedocument.presentationml.presentation`, `text/plain`
|
|
173
|
+
|
|
124
174
|
## API Reference
|
|
125
175
|
|
|
126
176
|
### AdpAgent
|
|
@@ -146,9 +196,11 @@ interface AdpConfig {
|
|
|
146
196
|
token?: string; // Session token (optional if TENCENTCLOUD_SESSIONTOKEN env is set)
|
|
147
197
|
};
|
|
148
198
|
historyCount?: number; // Number of history messages to retrieve (reserved)
|
|
199
|
+
enableUpload?: boolean; // Enable file upload for images and documents (default: false)
|
|
149
200
|
request?: {
|
|
150
201
|
baseUrl?: string; // Base URL for ADP API (default: https://wss.lke.cloud.tencent.com)
|
|
151
202
|
endpoint?: string; // API endpoint (default: /v1/qbot/chat/sse)
|
|
203
|
+
docParseEndpoint?: string; // Document parse API endpoint (default: /v1/qbot/chat/docParse)
|
|
152
204
|
body?: Partial<AdpChatRequest>; // Additional request body options
|
|
153
205
|
};
|
|
154
206
|
}
|
|
@@ -187,6 +239,7 @@ The adapter emits the following AG-UI events:
|
|
|
187
239
|
- `axios`: HTTP client for API requests
|
|
188
240
|
- `rxjs`: Reactive extensions for JavaScript
|
|
189
241
|
- `tencentcloud-sdk-nodejs-lke`: Tencent Cloud LKE SDK
|
|
242
|
+
- `cos-nodejs-sdk-v5`: Tencent Cloud COS SDK (for file upload)
|
|
190
243
|
|
|
191
244
|
## Related Resources
|
|
192
245
|
|
package/dist/index.d.mts
CHANGED
|
@@ -59,8 +59,10 @@ type AdpConfig = {
|
|
|
59
59
|
baseUrl?: string;
|
|
60
60
|
endpoint?: string;
|
|
61
61
|
body?: Partial<AdpChatRequest>;
|
|
62
|
+
docParseEndpoint?: string;
|
|
62
63
|
};
|
|
63
64
|
historyCount?: number;
|
|
65
|
+
enableUpload?: boolean;
|
|
64
66
|
appKey?: string;
|
|
65
67
|
credential?: {
|
|
66
68
|
secretId?: string;
|
|
@@ -282,6 +284,7 @@ declare class AdpAgent extends AbstractAgent {
|
|
|
282
284
|
private reqLkeClient;
|
|
283
285
|
protected adpConfig: AdpConfig;
|
|
284
286
|
private finalAppKey;
|
|
287
|
+
private finalCloudCredential;
|
|
285
288
|
constructor(config: AgentConfig & {
|
|
286
289
|
adpConfig: AdpConfig;
|
|
287
290
|
});
|
package/dist/index.d.ts
CHANGED
|
@@ -59,8 +59,10 @@ type AdpConfig = {
|
|
|
59
59
|
baseUrl?: string;
|
|
60
60
|
endpoint?: string;
|
|
61
61
|
body?: Partial<AdpChatRequest>;
|
|
62
|
+
docParseEndpoint?: string;
|
|
62
63
|
};
|
|
63
64
|
historyCount?: number;
|
|
65
|
+
enableUpload?: boolean;
|
|
64
66
|
appKey?: string;
|
|
65
67
|
credential?: {
|
|
66
68
|
secretId?: string;
|
|
@@ -282,6 +284,7 @@ declare class AdpAgent extends AbstractAgent {
|
|
|
282
284
|
private reqLkeClient;
|
|
283
285
|
protected adpConfig: AdpConfig;
|
|
284
286
|
private finalAppKey;
|
|
287
|
+
private finalCloudCredential;
|
|
285
288
|
constructor(config: AgentConfig & {
|
|
286
289
|
adpConfig: AdpConfig;
|
|
287
290
|
});
|
package/dist/index.js
CHANGED
|
@@ -129,18 +129,20 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
129
129
|
constructor(config) {
|
|
130
130
|
super(config);
|
|
131
131
|
this.finalAppKey = "";
|
|
132
|
+
this.finalCloudCredential = {};
|
|
132
133
|
this.adpConfig = config.adpConfig;
|
|
133
134
|
this.finalAppKey = this.adpConfig.appKey || this.adpConfig.request?.body?.botAppKey || process.env.ADP_APP_KEY || "";
|
|
134
135
|
this.reqAppClient = import_axios.default.create({
|
|
135
136
|
baseURL: this.adpConfig.request?.baseUrl || "https://wss.lke.cloud.tencent.com"
|
|
136
137
|
});
|
|
137
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
|
+
};
|
|
138
144
|
this.reqLkeClient = new LkeClient({
|
|
139
|
-
credential:
|
|
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
|
-
}
|
|
145
|
+
credential: this.finalCloudCredential
|
|
144
146
|
});
|
|
145
147
|
}
|
|
146
148
|
generateRequestBody({
|
|
@@ -169,9 +171,11 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
169
171
|
});
|
|
170
172
|
}
|
|
171
173
|
async _run(subscriber, input) {
|
|
174
|
+
let thinkingMessageSet = /* @__PURE__ */ new Set();
|
|
175
|
+
let thinkFinishedMessageSet = /* @__PURE__ */ new Set();
|
|
172
176
|
try {
|
|
173
|
-
const { runId
|
|
174
|
-
const threadId =
|
|
177
|
+
const { runId } = input;
|
|
178
|
+
const threadId = input.threadId || (0, import_crypto.randomUUID)();
|
|
175
179
|
subscriber.next({
|
|
176
180
|
type: import_client.EventType.RUN_STARTED,
|
|
177
181
|
runId,
|
|
@@ -183,19 +187,26 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
183
187
|
"MISSING_APP_KEY"
|
|
184
188
|
);
|
|
185
189
|
}
|
|
186
|
-
const
|
|
187
|
-
|
|
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);
|
|
188
199
|
if (!message) {
|
|
189
200
|
throw new AdpAgentError(
|
|
190
201
|
"Message content format error, or empty content",
|
|
191
202
|
"INVALID_MESSAGE_FORMAT"
|
|
192
203
|
);
|
|
193
204
|
}
|
|
194
|
-
if (
|
|
205
|
+
if (input.messages.length > 1) {
|
|
195
206
|
subscriber.next({
|
|
196
207
|
type: import_client.EventType.RAW,
|
|
197
208
|
rawEvent: {
|
|
198
|
-
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.`,
|
|
199
210
|
type: "warn"
|
|
200
211
|
}
|
|
201
212
|
});
|
|
@@ -214,7 +225,6 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
214
225
|
let buffer = "";
|
|
215
226
|
let interruptRequested = false;
|
|
216
227
|
let thinkingStart = false;
|
|
217
|
-
let thinkingMessageSet = /* @__PURE__ */ new Set();
|
|
218
228
|
for await (const chunk of sseStream) {
|
|
219
229
|
buffer += chunk.toString();
|
|
220
230
|
const parts = buffer.split("\n\n");
|
|
@@ -241,6 +251,22 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
241
251
|
}
|
|
242
252
|
switch (data.type) {
|
|
243
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
|
+
}
|
|
244
270
|
if (data.payload.is_from_self) {
|
|
245
271
|
if (data.payload.is_evil) {
|
|
246
272
|
throw new AdpAgentError(
|
|
@@ -251,8 +277,6 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
251
277
|
continue;
|
|
252
278
|
}
|
|
253
279
|
}
|
|
254
|
-
const messageId = data.payload.record_id;
|
|
255
|
-
const isFinal = data.payload.is_final;
|
|
256
280
|
data.payload.content = data.payload.content.replace(
|
|
257
281
|
/\\n/g,
|
|
258
282
|
"\n\n"
|
|
@@ -332,51 +356,47 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
332
356
|
});
|
|
333
357
|
}
|
|
334
358
|
data.payload.procedures.forEach((procedure) => {
|
|
335
|
-
|
|
336
|
-
|
|
359
|
+
const index = procedure.index.toString();
|
|
360
|
+
if (!thinkingMessageSet.has(index) && !thinkFinishedMessageSet.has(index)) {
|
|
361
|
+
thinkingMessageSet.add(index);
|
|
337
362
|
subscriber.next({
|
|
338
363
|
type: import_client.EventType.THINKING_TEXT_MESSAGE_START,
|
|
339
|
-
messageId
|
|
364
|
+
messageId: `${messageId}-think-${index}`,
|
|
340
365
|
delta: procedure.debugging.content
|
|
341
366
|
});
|
|
342
367
|
} else {
|
|
343
368
|
if (procedure.status === "processing") {
|
|
344
369
|
subscriber.next({
|
|
345
370
|
type: import_client.EventType.THINKING_TEXT_MESSAGE_CONTENT,
|
|
346
|
-
messageId
|
|
371
|
+
messageId: `${messageId}-think-${index}`,
|
|
347
372
|
delta: procedure.debugging.content
|
|
348
373
|
});
|
|
349
374
|
} else {
|
|
350
|
-
thinkingMessageSet.delete(
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
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
|
+
}
|
|
355
383
|
}
|
|
356
384
|
}
|
|
357
385
|
});
|
|
358
|
-
const allFinished = data.payload.procedures.every(
|
|
359
|
-
(procedure) => procedure.status !== "processing"
|
|
360
|
-
);
|
|
361
|
-
if (allFinished) {
|
|
362
|
-
thinkingStart = false;
|
|
363
|
-
thinkingMessageSet.clear();
|
|
364
|
-
subscriber.next({
|
|
365
|
-
type: import_client.EventType.THINKING_END,
|
|
366
|
-
messageId
|
|
367
|
-
});
|
|
368
|
-
}
|
|
369
386
|
break;
|
|
370
387
|
}
|
|
371
388
|
case "error": {
|
|
372
|
-
console.error(
|
|
389
|
+
console.error(
|
|
390
|
+
"[ERROR] ADP throws error: ",
|
|
391
|
+
JSON.stringify(data)
|
|
392
|
+
);
|
|
373
393
|
throw new AdpAgentError(
|
|
374
394
|
data.error.message,
|
|
375
395
|
data.error.code ? `ADP_ERROR_${data.error.code}` : "ADP_ERROR_-1"
|
|
376
396
|
);
|
|
377
397
|
}
|
|
378
398
|
case "token_stat": {
|
|
379
|
-
console.debug(JSON.stringify(data));
|
|
399
|
+
console.debug("[DEBUG] ADP token stat: ", JSON.stringify(data));
|
|
380
400
|
break;
|
|
381
401
|
}
|
|
382
402
|
case "reference": {
|
|
@@ -406,7 +426,7 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
406
426
|
}
|
|
407
427
|
subscriber.complete();
|
|
408
428
|
} catch (e) {
|
|
409
|
-
console.error(JSON.stringify(e));
|
|
429
|
+
console.error("[ERROR] Uncaught error: ", JSON.stringify(e));
|
|
410
430
|
let code = "UNKNOWN_ERROR";
|
|
411
431
|
let message = JSON.stringify(e);
|
|
412
432
|
if (e instanceof import_axios.AxiosError) {
|
|
@@ -422,21 +442,33 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
422
442
|
message: `Sorry, an error occurred while running the agent: Error code ${code}, ${message}`
|
|
423
443
|
});
|
|
424
444
|
subscriber.complete();
|
|
445
|
+
} finally {
|
|
446
|
+
thinkingMessageSet.clear();
|
|
447
|
+
thinkFinishedMessageSet.clear();
|
|
425
448
|
}
|
|
426
449
|
}
|
|
427
|
-
async convertAGUIMessagesToAdpMessages(
|
|
450
|
+
async convertAGUIMessagesToAdpMessages(message) {
|
|
428
451
|
let result = "";
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
if (message.
|
|
432
|
-
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
452
|
+
if (message.role === "user") {
|
|
453
|
+
let content = "";
|
|
454
|
+
if (typeof message.content === "string") {
|
|
455
|
+
content = message.content;
|
|
456
|
+
} else {
|
|
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
|
+
}
|
|
471
|
+
}
|
|
440
472
|
const imageMap = /* @__PURE__ */ new Map();
|
|
441
473
|
const imagesToUpload = [];
|
|
442
474
|
message.content.forEach((item) => {
|
|
@@ -479,143 +511,158 @@ var AdpAgent = class extends import_client.AbstractAgent {
|
|
|
479
511
|
}
|
|
480
512
|
}, "").trim();
|
|
481
513
|
}
|
|
482
|
-
|
|
514
|
+
}
|
|
515
|
+
result = `${message.role}: ${content}
|
|
483
516
|
${result}`;
|
|
484
|
-
|
|
485
|
-
|
|
517
|
+
} else {
|
|
518
|
+
result = `${message.role}: ${message.content}
|
|
486
519
|
${result}`;
|
|
487
|
-
}
|
|
488
520
|
}
|
|
489
|
-
return
|
|
521
|
+
return result.trim();
|
|
490
522
|
}
|
|
491
|
-
async extractDocuments(
|
|
492
|
-
const { messages, runId, threadId } = input;
|
|
523
|
+
async extractDocuments(message, threadId, subscriber) {
|
|
493
524
|
const documentFiles = [];
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
525
|
+
let newMessage;
|
|
526
|
+
if (message.role === "user" && Array.isArray(message.content)) {
|
|
527
|
+
let newContent = [];
|
|
528
|
+
message.content.forEach((item) => {
|
|
529
|
+
if (item.type === "text") {
|
|
530
|
+
newContent.push(item);
|
|
531
|
+
} else if (item.type === "binary") {
|
|
532
|
+
if (Object.keys(DOCUMENT_MIME_TYPES).includes(item.mimeType)) {
|
|
533
|
+
documentFiles.push(item);
|
|
534
|
+
} else {
|
|
499
535
|
newContent.push(item);
|
|
500
|
-
} else if (item.type === "binary") {
|
|
501
|
-
if (Object.keys(DOCUMENT_MIME_TYPES).includes(item.mimeType)) {
|
|
502
|
-
documentFiles.push(item);
|
|
503
|
-
} else {
|
|
504
|
-
newContent.push(item);
|
|
505
|
-
}
|
|
506
536
|
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
}
|
|
513
|
-
}
|
|
537
|
+
}
|
|
538
|
+
});
|
|
539
|
+
newMessage = {
|
|
540
|
+
...message,
|
|
541
|
+
content: newContent
|
|
542
|
+
};
|
|
543
|
+
} else newMessage = message;
|
|
514
544
|
const fileInfos = [];
|
|
515
545
|
const successedFiles = [];
|
|
516
546
|
const failedFiles = [];
|
|
517
|
-
if (
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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
|
+
}
|
|
529
561
|
}
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
fileType: extName,
|
|
540
|
-
fileName: file.filename,
|
|
541
|
-
cosUrl: cosParams.UploadPath,
|
|
542
|
-
cosHash: cosData.headers?.["x-cos-hash-crc64ecma"] || "",
|
|
543
|
-
eTag: cosData.ETag,
|
|
544
|
-
size: file.data?.length.toString() || "0"
|
|
545
|
-
};
|
|
546
|
-
const response = await this.reqAppClient.post(
|
|
547
|
-
this.adpConfig.request?.endpoint || "/v1/qbot/chat/docParse",
|
|
548
|
-
camelToSnakeKeys(requestBody),
|
|
549
|
-
{ responseType: "stream" }
|
|
550
|
-
);
|
|
551
|
-
const sseStream = response.data;
|
|
552
|
-
let buffer = "";
|
|
553
|
-
for await (const chunk of sseStream) {
|
|
554
|
-
buffer += chunk.toString();
|
|
555
|
-
const parts = buffer.split("\n\n");
|
|
556
|
-
buffer = parts.pop() || "";
|
|
557
|
-
for (const part of parts) {
|
|
558
|
-
if (!part.trim()) continue;
|
|
559
|
-
const event = { data: "", event: "" };
|
|
560
|
-
for (const line of part.split("\n")) {
|
|
561
|
-
if (line.startsWith("data:")) {
|
|
562
|
-
event.data += line.slice(5);
|
|
563
|
-
} else if (line.startsWith("event:")) {
|
|
564
|
-
event.event = line.slice(6);
|
|
565
|
-
}
|
|
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 });
|
|
566
571
|
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
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
|
+
}
|
|
576
612
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
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
|
+
}
|
|
604
651
|
}
|
|
652
|
+
break;
|
|
653
|
+
}
|
|
654
|
+
default: {
|
|
655
|
+
break;
|
|
605
656
|
}
|
|
606
|
-
break;
|
|
607
|
-
}
|
|
608
|
-
default: {
|
|
609
|
-
break;
|
|
610
657
|
}
|
|
611
658
|
}
|
|
612
659
|
}
|
|
613
660
|
}
|
|
614
661
|
}
|
|
615
|
-
}
|
|
662
|
+
}
|
|
616
663
|
}
|
|
617
664
|
return {
|
|
618
|
-
|
|
665
|
+
message: newMessage,
|
|
619
666
|
fileInfos,
|
|
620
667
|
failedFiles
|
|
621
668
|
};
|