@baishuyun/coze-provider 2.0.46 → 2.0.47
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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +7 -0
- package/dist/index.js +126 -101
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +126 -101
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/coze-language-model.ts +8 -1
- package/src/stream-trasnformer/llm-part-transform-stream.ts +19 -2
- package/src/utils/accumulate-sse-response.ts +2 -5
- package/src/utils/mcp-to-llm-chunk.ts +30 -10
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @baishuyun/coze-provider@2.0.
|
|
2
|
+
> @baishuyun/coze-provider@2.0.47 build /home/runner/work/bs-chat-sdk/bs-chat-sdk/packages/coze-provider
|
|
3
3
|
> tsup --tsconfig tsconfig.json --clean
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
[34mCLI[39m Cleaning output folder
|
|
11
11
|
[34mCJS[39m Build start
|
|
12
12
|
[34mESM[39m Build start
|
|
13
|
-
[32mESM[39m [1mdist/index.mjs [22m[
|
|
14
|
-
[32mESM[39m [1mdist/index.mjs.map [22m[
|
|
15
|
-
[32mESM[39m ⚡️ Build success in
|
|
16
|
-
[32mCJS[39m [1mdist/index.js [22m[
|
|
17
|
-
[32mCJS[39m [1mdist/index.js.map [22m[
|
|
18
|
-
[32mCJS[39m ⚡️ Build success in
|
|
13
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m22.12 KB[39m
|
|
14
|
+
[32mESM[39m [1mdist/index.mjs.map [22m[32m46.83 KB[39m
|
|
15
|
+
[32mESM[39m ⚡️ Build success in 63ms
|
|
16
|
+
[32mCJS[39m [1mdist/index.js [22m[32m23.62 KB[39m
|
|
17
|
+
[32mCJS[39m [1mdist/index.js.map [22m[32m47.11 KB[39m
|
|
18
|
+
[32mCJS[39m ⚡️ Build success in 66ms
|
|
19
19
|
[34mDTS[39m Build start
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 3545ms
|
|
21
21
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m1.57 KB[39m
|
|
22
22
|
[32mDTS[39m [1mdist/index.d.mts [22m[32m1.57 KB[39m
|
package/CHANGELOG.md
CHANGED
package/dist/index.js
CHANGED
|
@@ -101,6 +101,109 @@ var convertPromptToMessages = (messages) => {
|
|
|
101
101
|
// src/utils/accumulate-sse-response.ts
|
|
102
102
|
var import_parse_sse = require("parse-sse");
|
|
103
103
|
var import_web = require("stream/web");
|
|
104
|
+
|
|
105
|
+
// src/utils/mcp-to-llm-chunk.ts
|
|
106
|
+
var import_api2 = require("@coze/api");
|
|
107
|
+
var mapCozeUsage = (usage) => {
|
|
108
|
+
const inputTokens = usage?.input_count || 0;
|
|
109
|
+
const outputTokens = usage?.output_count || 0;
|
|
110
|
+
const totalTokens = usage?.total_count ?? usage?.token_count ?? inputTokens + outputTokens;
|
|
111
|
+
return { inputTokens, outputTokens, totalTokens };
|
|
112
|
+
};
|
|
113
|
+
var extractUsageFromMsgMeta = (meta) => {
|
|
114
|
+
if (!meta) return null;
|
|
115
|
+
const totalTokens = Number(meta.token);
|
|
116
|
+
if (!totalTokens) return null;
|
|
117
|
+
return {
|
|
118
|
+
inputTokens: Number(meta.input_tokens) || 0,
|
|
119
|
+
outputTokens: Number(meta.output_tokens) || 0,
|
|
120
|
+
totalTokens
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
var mcp2llmChunk = (part) => {
|
|
124
|
+
const fullData = JSON.stringify(part);
|
|
125
|
+
switch (part.event) {
|
|
126
|
+
case import_api2.ChatEventType.CONVERSATION_CHAT_CREATED:
|
|
127
|
+
return {
|
|
128
|
+
type: "raw",
|
|
129
|
+
rawValue: part.data
|
|
130
|
+
};
|
|
131
|
+
break;
|
|
132
|
+
case import_api2.ChatEventType.CONVERSATION_CHAT_IN_PROGRESS:
|
|
133
|
+
return {
|
|
134
|
+
// type: "text-delta",
|
|
135
|
+
// id: part.data.conversation_id,
|
|
136
|
+
// delta: part.data.content || "",
|
|
137
|
+
// providerMetadata: {
|
|
138
|
+
// raw: { data: fullData },
|
|
139
|
+
// },
|
|
140
|
+
type: "raw",
|
|
141
|
+
rawValue: part.data
|
|
142
|
+
};
|
|
143
|
+
break;
|
|
144
|
+
case import_api2.ChatEventType.CONVERSATION_MESSAGE_DELTA:
|
|
145
|
+
const isReasoning = Boolean(part.data.reasoning_content);
|
|
146
|
+
return {
|
|
147
|
+
type: isReasoning ? "reasoning-delta" : "text-delta",
|
|
148
|
+
delta: isReasoning ? part.data.reasoning_content : part.data.content,
|
|
149
|
+
id: part.data.conversation_id,
|
|
150
|
+
providerMetadata: {}
|
|
151
|
+
};
|
|
152
|
+
break;
|
|
153
|
+
case import_api2.ChatEventType.CONVERSATION_MESSAGE_COMPLETED:
|
|
154
|
+
if (part.data && part.data.type === "follow_up") {
|
|
155
|
+
return {
|
|
156
|
+
type: "raw",
|
|
157
|
+
rawValue: part.data
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
if (part.status === "completed") {
|
|
161
|
+
return {
|
|
162
|
+
type: "text-end",
|
|
163
|
+
id: part.data.conversation_id,
|
|
164
|
+
// delta: part.data.content || part.data.reasoning_content || "",
|
|
165
|
+
providerMetadata: {}
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
type: "raw",
|
|
170
|
+
rawValue: part.data
|
|
171
|
+
};
|
|
172
|
+
break;
|
|
173
|
+
case import_api2.ChatEventType.CONVERSATION_CHAT_COMPLETED:
|
|
174
|
+
return {
|
|
175
|
+
type: "finish",
|
|
176
|
+
finishReason: "stop",
|
|
177
|
+
usage: mapCozeUsage(part.data.usage)
|
|
178
|
+
};
|
|
179
|
+
break;
|
|
180
|
+
case import_api2.ChatEventType.DONE:
|
|
181
|
+
return {
|
|
182
|
+
type: "finish",
|
|
183
|
+
finishReason: "stop",
|
|
184
|
+
usage: mapCozeUsage(part.data.usage)
|
|
185
|
+
};
|
|
186
|
+
break;
|
|
187
|
+
case import_api2.ChatEventType.ERROR:
|
|
188
|
+
console.error("[ERROR]", part.data);
|
|
189
|
+
return {
|
|
190
|
+
type: "error",
|
|
191
|
+
error: part.data
|
|
192
|
+
};
|
|
193
|
+
default:
|
|
194
|
+
console.warn("Unknown event type:", part.event);
|
|
195
|
+
return {
|
|
196
|
+
type: "error",
|
|
197
|
+
error: "Unknown event type" + part.event
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
return {
|
|
201
|
+
type: "error",
|
|
202
|
+
error: "unknown"
|
|
203
|
+
};
|
|
204
|
+
};
|
|
205
|
+
|
|
206
|
+
// src/utils/accumulate-sse-response.ts
|
|
104
207
|
async function accumulateSSEResponse(body) {
|
|
105
208
|
const sseStream = body.pipeThrough(
|
|
106
209
|
new import_web.TextDecoderStream()
|
|
@@ -131,11 +234,7 @@ async function accumulateSSEResponse(body) {
|
|
|
131
234
|
} else if (event === "conversation.chat.completed" || event === "done") {
|
|
132
235
|
finishReason = "stop";
|
|
133
236
|
if (evtData.usage) {
|
|
134
|
-
usage =
|
|
135
|
-
inputTokens: evtData.usage.input_count || 0,
|
|
136
|
-
outputTokens: evtData.usage.output_count || 0,
|
|
137
|
-
totalTokens: evtData.usage.total_count || 0
|
|
138
|
-
};
|
|
237
|
+
usage = mapCozeUsage(evtData.usage);
|
|
139
238
|
}
|
|
140
239
|
} else if (event === "error") {
|
|
141
240
|
finishReason = "error";
|
|
@@ -234,13 +333,13 @@ var LLMChunkInjectorTransformStream = class extends TransformStream {
|
|
|
234
333
|
};
|
|
235
334
|
|
|
236
335
|
// src/stream-trasnformer/mcp-chunk-filter-transform-stream.ts
|
|
237
|
-
var
|
|
336
|
+
var import_api3 = require("@coze/api");
|
|
238
337
|
var MCPChunkFilterTransformStream = class extends TransformStream {
|
|
239
338
|
isVisibleMsgPart(evtData, part, omitTextEndChunk) {
|
|
240
339
|
if (evtData.type === "knowledge" && evtData.role === "assistant") {
|
|
241
340
|
return false;
|
|
242
341
|
}
|
|
243
|
-
if (omitTextEndChunk && part.event ===
|
|
342
|
+
if (omitTextEndChunk && part.event === import_api3.ChatEventType.CONVERSATION_MESSAGE_COMPLETED && part.data.type !== "follow_up") {
|
|
244
343
|
return false;
|
|
245
344
|
}
|
|
246
345
|
if (part.event === "conversation.message.completed" && evtData.type == "verbose") {
|
|
@@ -264,101 +363,15 @@ var MCPChunkFilterTransformStream = class extends TransformStream {
|
|
|
264
363
|
}
|
|
265
364
|
};
|
|
266
365
|
|
|
267
|
-
// src/utils/mcp-to-llm-chunk.ts
|
|
268
|
-
var import_api3 = require("@coze/api");
|
|
269
|
-
var mcp2llmChunk = (part) => {
|
|
270
|
-
const fullData = JSON.stringify(part);
|
|
271
|
-
switch (part.event) {
|
|
272
|
-
case import_api3.ChatEventType.CONVERSATION_CHAT_CREATED:
|
|
273
|
-
return {
|
|
274
|
-
type: "raw",
|
|
275
|
-
rawValue: part.data
|
|
276
|
-
};
|
|
277
|
-
break;
|
|
278
|
-
case import_api3.ChatEventType.CONVERSATION_CHAT_IN_PROGRESS:
|
|
279
|
-
return {
|
|
280
|
-
// type: "text-delta",
|
|
281
|
-
// id: part.data.conversation_id,
|
|
282
|
-
// delta: part.data.content || "",
|
|
283
|
-
// providerMetadata: {
|
|
284
|
-
// raw: { data: fullData },
|
|
285
|
-
// },
|
|
286
|
-
type: "raw",
|
|
287
|
-
rawValue: part.data
|
|
288
|
-
};
|
|
289
|
-
break;
|
|
290
|
-
case import_api3.ChatEventType.CONVERSATION_MESSAGE_DELTA:
|
|
291
|
-
const isReasoning = Boolean(part.data.reasoning_content);
|
|
292
|
-
return {
|
|
293
|
-
type: isReasoning ? "reasoning-delta" : "text-delta",
|
|
294
|
-
delta: isReasoning ? part.data.reasoning_content : part.data.content,
|
|
295
|
-
id: part.data.conversation_id,
|
|
296
|
-
providerMetadata: {}
|
|
297
|
-
};
|
|
298
|
-
break;
|
|
299
|
-
case import_api3.ChatEventType.CONVERSATION_MESSAGE_COMPLETED:
|
|
300
|
-
if (part.data && part.data.type === "follow_up") {
|
|
301
|
-
return {
|
|
302
|
-
type: "raw",
|
|
303
|
-
rawValue: part.data
|
|
304
|
-
};
|
|
305
|
-
}
|
|
306
|
-
if (part.status === "completed") {
|
|
307
|
-
return {
|
|
308
|
-
type: "text-end",
|
|
309
|
-
id: part.data.conversation_id,
|
|
310
|
-
// delta: part.data.content || part.data.reasoning_content || "",
|
|
311
|
-
providerMetadata: {}
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
return {
|
|
315
|
-
type: "raw",
|
|
316
|
-
rawValue: part.data
|
|
317
|
-
};
|
|
318
|
-
break;
|
|
319
|
-
case import_api3.ChatEventType.CONVERSATION_CHAT_COMPLETED:
|
|
320
|
-
return {
|
|
321
|
-
type: "finish",
|
|
322
|
-
finishReason: "stop",
|
|
323
|
-
usage: {
|
|
324
|
-
inputTokens: part.data.usage?.input_count || 0,
|
|
325
|
-
outputTokens: part.data.usage?.output_count || 0,
|
|
326
|
-
totalTokens: part.data.usage?.total_count || 0
|
|
327
|
-
}
|
|
328
|
-
};
|
|
329
|
-
break;
|
|
330
|
-
case import_api3.ChatEventType.DONE:
|
|
331
|
-
return {
|
|
332
|
-
type: "finish",
|
|
333
|
-
finishReason: "stop",
|
|
334
|
-
usage: {
|
|
335
|
-
inputTokens: part.data.usage?.input_count || 0,
|
|
336
|
-
outputTokens: part.data.usage?.output_count || 0,
|
|
337
|
-
totalTokens: part.data.usage?.total_count || 0
|
|
338
|
-
}
|
|
339
|
-
};
|
|
340
|
-
break;
|
|
341
|
-
case import_api3.ChatEventType.ERROR:
|
|
342
|
-
console.error("[ERROR]", part.data);
|
|
343
|
-
return {
|
|
344
|
-
type: "error",
|
|
345
|
-
error: part.data
|
|
346
|
-
};
|
|
347
|
-
default:
|
|
348
|
-
console.warn("Unknown event type:", part.event);
|
|
349
|
-
return {
|
|
350
|
-
type: "error",
|
|
351
|
-
error: "Unknown event type" + part.event
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
return {
|
|
355
|
-
type: "error",
|
|
356
|
-
error: "unknown"
|
|
357
|
-
};
|
|
358
|
-
};
|
|
359
|
-
|
|
360
366
|
// src/stream-trasnformer/llm-part-transform-stream.ts
|
|
367
|
+
var import_api4 = require("@coze/api");
|
|
361
368
|
var LLMPartTrasnformStream = class extends TransformStream {
|
|
369
|
+
/**
|
|
370
|
+
* 本轮最近一条消息 meta_data 中携带的 token 用量。
|
|
371
|
+
* 旧版上游不在 conversation.chat.completed 事件中携带 usage,
|
|
372
|
+
* 发 finish chunk 时若事件 usage 缺失则用此兜底(事件已带则不覆盖)
|
|
373
|
+
*/
|
|
374
|
+
lastMsgUsage = null;
|
|
362
375
|
constructor() {
|
|
363
376
|
super({
|
|
364
377
|
transform: (part, controller) => {
|
|
@@ -368,8 +381,17 @@ var LLMPartTrasnformStream = class extends TransformStream {
|
|
|
368
381
|
return;
|
|
369
382
|
}
|
|
370
383
|
try {
|
|
384
|
+
if (part.event === import_api4.ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {
|
|
385
|
+
const usage = extractUsageFromMsgMeta(part.data?.meta_data);
|
|
386
|
+
if (usage) {
|
|
387
|
+
this.lastMsgUsage = usage;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
371
390
|
const chunk = mcp2llmChunk(part);
|
|
372
391
|
if (chunk) {
|
|
392
|
+
if (chunk.type === "finish" && !chunk.usage?.totalTokens && this.lastMsgUsage) {
|
|
393
|
+
chunk.usage = this.lastMsgUsage;
|
|
394
|
+
}
|
|
373
395
|
controller.enqueue(chunk);
|
|
374
396
|
}
|
|
375
397
|
} catch (error) {
|
|
@@ -488,13 +510,15 @@ var CozeLanguageModel = class {
|
|
|
488
510
|
path: `/chat${queryStr}`
|
|
489
511
|
});
|
|
490
512
|
const user_id = options.headers ? options.headers["x-user-id"] : "";
|
|
513
|
+
const operator_id = (options.headers ? options.headers["x-operator-id"] : "") ?? "";
|
|
491
514
|
const user_var = options.headers ? options.headers["x-user-var"] : "";
|
|
492
515
|
const user_param = (options.headers ? options.headers["x-user-param"] : "") ?? "";
|
|
493
516
|
const params = user_param ? (0, import_ai_feat_utils.safeParseJson)(user_param) : {};
|
|
494
517
|
console.log("params 2 workflow", params);
|
|
495
518
|
console.log("conversation id 2 workflow", conversation_id);
|
|
496
519
|
const chatCtx = options?.providerOptions?.chatCtx;
|
|
497
|
-
|
|
520
|
+
console.log("chatCtx", chatCtx);
|
|
521
|
+
const userId = operator_id || chatCtx?.user?._id || user_id || Date.now().toString();
|
|
498
522
|
const body = {
|
|
499
523
|
bot_id: this.config.botId,
|
|
500
524
|
auto_save_history: Boolean(conversation_id),
|
|
@@ -512,6 +536,7 @@ var CozeLanguageModel = class {
|
|
|
512
536
|
const abortSignal = options.abortSignal;
|
|
513
537
|
console.log("url", url);
|
|
514
538
|
console.log("body", JSON.stringify(body, null, 2));
|
|
539
|
+
console.log("operator_id", operator_id);
|
|
515
540
|
const response = await fetch(url, {
|
|
516
541
|
method: "POST",
|
|
517
542
|
headers,
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/coze-provider.ts","../src/const.ts","../src/coze-language-model.ts","../src/utils/prompt-to-model-msg.ts","../src/utils/accumulate-sse-response.ts","../src/utils/create-error-stream.ts","../src/evt-sample.ts","../src/stream-trasnformer/llm-chunk-injector-transform-stream.ts","../src/stream-trasnformer/mcp-chunk-filter-transform-stream.ts","../src/utils/mcp-to-llm-chunk.ts","../src/stream-trasnformer/llm-part-transform-stream.ts","../src/utils/build-generate-result-by-chat-res.ts","../src/stream-trasnformer/fields-json-transform-stream.ts","../src/utils/enqueue-text-info.ts","../src/stream-trasnformer/suggestion-transform-stream.ts"],"sourcesContent":["export { createCoze } from \"./coze-provider\";\nexport { createFieldsJsonTransformStream } from \"./stream-trasnformer/fields-json-transform-stream\";\nexport { default as SuggestionTransformStream } from \"./stream-trasnformer/suggestion-transform-stream\";\nexport { createTextInfoEnqueuer } from \"./utils/enqueue-text-info\";\n","import {\n LanguageModelV2,\n LanguageModelV2StreamPart,\n NoSuchModelError,\n ProviderV2,\n} from '@ai-sdk/provider';\n\nimport {\n FetchFunction,\n loadApiKey,\n withoutTrailingSlash,\n withUserAgentSuffix,\n} from '@ai-sdk/provider-utils';\nimport { CozeChatModelId } from './types';\nimport { VERSION } from './const';\nimport { CozeLanguageModel } from './coze-language-model';\n\nexport interface CozeProviderSettings {\n apiKey?: string;\n /**\nBase URL for the API calls.\n*/\n baseURL?: string;\n\n botId: string;\n\n /**\nCustom headers to include in the requests.\n*/\n headers?: Record<string, string>;\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n*/\n fetch?: FetchFunction;\n\n extraStreamTransformers?: (() => TransformStream<LanguageModelV2StreamPart, any>)[];\n}\n\nexport interface CozeProvider extends ProviderV2 {\n (modelId: CozeChatModelId): LanguageModelV2;\n\n languageModel(modelId: CozeChatModelId): LanguageModelV2;\n\n /**\nCreates a DeepSeek chat model for text generation.\n*/\n chat(modelId: CozeChatModelId): LanguageModelV2;\n}\n\nexport function createCoze(\n options: CozeProviderSettings = {\n botId: '',\n }\n): CozeProvider {\n const baseURL = withoutTrailingSlash(options.baseURL);\n\n const agentPartHeader = withUserAgentSuffix(options.headers || {}, `ai-sdk/coze/${VERSION}`);\n const authorizationHeader = `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'COZE_API_KEY',\n description: '',\n })}`;\n\n const getHeaders = () => ({\n ...agentPartHeader,\n Authorization: authorizationHeader,\n 'content-type': 'application/json',\n });\n\n const createLanguageModel = (modelId: CozeChatModelId) => {\n return new CozeLanguageModel(modelId, {\n botId: options.botId,\n provider: `coze.chat`,\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n extraStreamTransformers: options.extraStreamTransformers || [],\n });\n };\n\n const provider = (modelId: CozeChatModelId) => createLanguageModel(modelId);\n\n provider.specificationVersion = 'v3' as const;\n provider.languageModel = createLanguageModel;\n provider.chat = createLanguageModel;\n\n provider.embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });\n };\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'imageModel' });\n };\n provider.textEmbeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });\n };\n\n return provider;\n}\n","export const VERSION = \"0.0.1\";\n","import {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2CallWarning,\n LanguageModelV2Prompt,\n LanguageModelV2StreamPart,\n SharedV2Headers,\n} from '@ai-sdk/provider';\nimport { CozeChatConfig, IGenerateResult } from './types';\nimport { ServerSentEventTransformStream } from 'parse-sse';\nimport { TextDecoderStream } from 'stream/web';\nimport { convertPromptToMessages } from './utils/prompt-to-model-msg';\nimport { accumulateSSEResponse } from './utils/accumulate-sse-response';\nimport { createErrorStream } from './utils/create-error-stream';\nimport { LLMChunkInjectorTransformStream } from './stream-trasnformer/llm-chunk-injector-transform-stream';\nimport MCPChunkFilterTransformStream from './stream-trasnformer/mcp-chunk-filter-transform-stream';\nimport LLMPartTrasnformStream from './stream-trasnformer/llm-part-transform-stream';\nimport { BuildWarningGenerateResult } from './utils/build-generate-result-by-chat-res';\nimport { getChatCtxForHuman, getChatCtxForMcp, safeParseJson } from '@baishuyun/ai-feat-utils';\nimport { IChatCtx } from '@baishuyun/types';\n\nexport class CozeLanguageModel implements LanguageModelV2 {\n specificationVersion: 'v2' = 'v2';\n provider: string;\n modelId: string;\n supportedUrls: Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>>;\n\n private readonly config: CozeChatConfig;\n\n constructor(modelId: string, config: CozeChatConfig) {\n this.modelId = modelId;\n this.provider = config.provider || 'coze';\n this.supportedUrls = config.supportedUrls?.() || {};\n this.config = config;\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<IGenerateResult> {\n const messages = convertPromptToMessages(options.prompt);\n const warnings: LanguageModelV2CallWarning[] = [];\n\n const url = this.config.url({ path: '/chat' });\n\n const user_id = options.headers ? options.headers['x-user-id'] : '';\n const user_var = options.headers ? options.headers['x-user-var'] : '';\n\n let customVar;\n if (user_var) {\n try {\n customVar = JSON.parse(user_var);\n } catch (e) {\n console.warn('x-user-var parse error', e);\n }\n }\n\n const body = {\n bot_id: this.config.botId,\n auto_save_history: false,\n user_id: user_id || '7543191937730215936',\n stream: true,\n additional_messages: messages,\n };\n\n if (customVar) {\n (body as any).custom_variables = customVar;\n }\n\n const headers = this.config.headers();\n const abortSignal = options.abortSignal;\n\n const response = await fetch(url, {\n method: 'POST',\n headers: headers,\n credentials: 'include',\n body: JSON.stringify(body),\n signal: abortSignal,\n });\n\n if (!response.ok || !response.body) {\n const rawError = await response.text();\n let errorDetail;\n try {\n errorDetail = JSON.parse(rawError);\n } catch {\n errorDetail = rawError;\n }\n\n const errorMessage =\n typeof errorDetail === 'object' && errorDetail?.msg\n ? errorDetail.msg\n : `Coze API error: ${response.status} ${response.statusText}`;\n\n return BuildWarningGenerateResult(errorMessage);\n }\n\n const { content, finishReason, usage } = await accumulateSSEResponse(response.body);\n\n return {\n content,\n finishReason,\n usage,\n request: { body },\n response: { body: null },\n warnings,\n };\n }\n\n isVisibleMsgPart(evtData: any) {\n if (evtData.type === 'knowledge' && evtData.role === 'assistant') {\n return false;\n }\n\n return true;\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: SharedV2Headers };\n }> {\n const conversation_id = options.headers ? options.headers['x-conversation-id'] : '';\n\n // 有 conversation_id 时,服务端会话中已持有完整历史(含中断记录)。\n const prompt = conversation_id ? keepOnlyLastUserMessage(options.prompt) : options.prompt;\n\n const messages = convertPromptToMessages(prompt);\n const queryStr = conversation_id ? `?conversation_id=${conversation_id}` : '';\n\n const url = this.config.url({\n path: `/chat${queryStr}`,\n });\n\n const user_id = options.headers ? options.headers['x-user-id'] : '';\n\n const user_var = options.headers ? options.headers['x-user-var'] : '';\n const user_param = (options.headers ? options.headers['x-user-param'] : '') ?? '';\n\n const params = user_param ? safeParseJson(user_param) : {};\n\n console.log('params 2 workflow', params);\n console.log('conversation id 2 workflow', conversation_id);\n const chatCtx = options?.providerOptions?.chatCtx as unknown as IChatCtx;\n\n const userId = chatCtx?.user?._id || user_id || Date.now().toString();\n\n const body = {\n bot_id: this.config.botId,\n auto_save_history: Boolean(conversation_id),\n user_id: userId,\n stream: true,\n additional_messages: messages,\n parameters: params,\n custom_variables: user_var ? safeParseJson(user_var) : {},\n extra_params: {\n remark: getChatCtxForHuman(chatCtx),\n mcp_ctx: getChatCtxForMcp(chatCtx),\n },\n };\n\n const headers = this.config.headers();\n\n const abortSignal = options.abortSignal;\n\n console.log('url', url);\n console.log('body', JSON.stringify(body, null, 2));\n\n const response = await fetch(url, {\n method: 'POST',\n headers: headers,\n credentials: 'include',\n body: JSON.stringify(body),\n signal: abortSignal,\n });\n\n console.log('chat res status', response.status);\n\n if (!response.ok || !response.body) {\n // if (true) {\n const rawError = await response.text();\n let errorDetail;\n try {\n errorDetail = JSON.parse(rawError); // 尝试解析为 JSON\n } catch {\n errorDetail = rawError; // 非 JSON 直接使用\n }\n\n // 创建一个包含错误信息的流,让 UI 层处理\n const errorMessage =\n typeof errorDetail === 'object' && errorDetail?.msg\n ? errorDetail.msg\n : `Coze API error: ${response.status} ${response.statusText}`;\n\n console.error(errorMessage);\n\n return {\n stream: createErrorStream('会话异常,请重试'),\n };\n }\n\n let externalTransformers = (this.config.extraStreamTransformers || []).map((factory) =>\n factory()\n );\n\n /// 不同阶段,可能需要不同的流处理逻辑\n const stage = options.headers ? options.headers['x-user-stage'] : '';\n const isBuildStage = stage === 'build';\n const isFillStage = stage === 'fill';\n\n const result = response.body\n // 将字节流解码为文本流\n .pipeThrough(\n new TextDecoderStream() as ReadableWritablePair<\n string | undefined,\n Uint8Array<ArrayBufferLike>\n >\n )\n // 解析为 SSE 事件流\n .pipeThrough(new ServerSentEventTransformStream())\n .pipeThrough(new MCPChunkFilterTransformStream(isBuildStage || isFillStage))\n // 补充特殊 llm chunk\n .pipeThrough(new LLMChunkInjectorTransformStream())\n // 转换为 LanguageModelV2StreamPart 格式\n .pipeThrough(new LLMPartTrasnformStream());\n\n let finalResult = result;\n\n if (externalTransformers.length > 0) {\n finalResult = externalTransformers.reduce(\n (stream, transformer) => stream.pipeThrough(transformer),\n result // 初始累积值(原始流)\n );\n }\n\n return {\n stream: finalResult as ReadableStream<LanguageModelV2StreamPart>,\n };\n }\n}\n\n/**\n * 只保留最后一条 user 消息(含其内容),用于有 conversation_id 的场景:\n * 服务端会话中已持有完整历史,只需发送当前用户输入。\n */\nfunction keepOnlyLastUserMessage(prompt: LanguageModelV2Prompt): LanguageModelV2Prompt {\n for (let i = prompt.length - 1; i >= 0; i--) {\n if (prompt[i].role === 'user') {\n return [prompt[i]];\n }\n }\n return prompt;\n}\n","import {\n LanguageModelV2FilePart,\n LanguageModelV2Message,\n LanguageModelV2Prompt,\n LanguageModelV2TextPart,\n} from '@ai-sdk/provider';\nimport { RoleType } from '@coze/api';\nimport { Attachment } from '@baishuyun/types/src/chat';\nimport { excel2json } from './excel2json';\n\nconst decoder = new TextDecoder('utf-8');\n\nconst data2csvText = (data: Uint8Array) => {\n return decoder.decode(data);\n};\n\ntype userMsg = {\n role: 'user';\n content: Array<LanguageModelV2TextPart | LanguageModelV2FilePart>;\n};\n\nconst getPartType = (part: LanguageModelV2TextPart | LanguageModelV2FilePart) => {\n if (part.type === 'text') {\n return 'text';\n }\n\n const isImg = part.mediaType?.startsWith('image/');\n if (isImg) {\n return 'image';\n }\n\n const isAudio = part.mediaType?.startsWith('audio/');\n if (isAudio) {\n return 'audio';\n }\n\n return 'file';\n};\n\nconst parseMessageContent = (message: LanguageModelV2Message, isTextOnly?: boolean) => {\n if (isTextOnly) {\n return (message.content as Array<LanguageModelV2TextPart>)\n .map((part: LanguageModelV2TextPart) => part.text)\n .join('\\n');\n }\n\n const result = (message.content as Array<LanguageModelV2TextPart | LanguageModelV2FilePart>).map(\n (part) => {\n const meta = part.providerOptions?.uploadMetadata as Attachment;\n const url = meta?.url;\n\n return {\n type: getPartType(part),\n text: part.type === 'text' ? (part as LanguageModelV2TextPart).text : '',\n file_id: meta?.file_id,\n name: meta?.name,\n // 附件地址:模型需要在「附件上传」标准动作中引用(IAttachment.attachmentUrl)\n url,\n };\n }\n );\n\n return JSON.stringify(result);\n};\n\nconst isTextOnlyMsg = (message: userMsg) => message.content.every((part) => part.type === 'text');\n\nexport const convertPromptToMessages = (messages: LanguageModelV2Prompt) => {\n return messages.map((message) => {\n const isTextOnly = isTextOnlyMsg(message as userMsg);\n switch (message.role) {\n case 'user':\n return {\n role: RoleType.User,\n content: parseMessageContent(message, isTextOnly),\n content_type: isTextOnly ? 'text' : 'object_string',\n };\n break;\n\n case 'assistant':\n return {\n role: RoleType.Assistant,\n content: (message.content as Array<LanguageModelV2TextPart>)\n .map((part: LanguageModelV2TextPart) => (part.type === 'text' ? part.text : ''))\n .join(''),\n content_type: 'text',\n };\n break;\n }\n });\n};\n","import {\n LanguageModelV2Content,\n LanguageModelV2FinishReason,\n LanguageModelV2Usage,\n} from '@ai-sdk/provider';\nimport { ServerSentEventTransformStream } from 'parse-sse';\nimport { TextDecoderStream } from 'stream/web';\n\nexport interface AccumulatedSSEResponse {\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n}\n\n/**\n * 从字节流中解码 SSE 事件并累积完整响应内容\n */\nexport async function accumulateSSEResponse(\n body: ReadableStream<Uint8Array>\n): Promise<AccumulatedSSEResponse> {\n const sseStream = body\n .pipeThrough(\n new TextDecoderStream() as ReadableWritablePair<\n string | undefined,\n Uint8Array<ArrayBufferLike>\n >\n )\n .pipeThrough(new ServerSentEventTransformStream());\n\n let textContent = '';\n let reasoningContent = '';\n let finishReason: LanguageModelV2FinishReason = 'stop';\n let usage: LanguageModelV2Usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n\n const reader = sseStream.getReader();\n try {\n while (true) {\n const { done, value: evt } = await reader.read();\n if (done) break;\n if (!evt) continue;\n\n let evtData;\n try {\n evtData = JSON.parse(evt.data);\n } catch {\n continue;\n }\n\n const event = evt.type;\n\n if (event === 'conversation.message.delta') {\n if (evtData.reasoning_content) {\n reasoningContent += evtData.reasoning_content;\n } else if (evtData.content) {\n textContent += evtData.content;\n }\n } else if (event === 'conversation.chat.completed' || event === 'done') {\n finishReason = 'stop';\n if (evtData.usage) {\n usage = {\n inputTokens: evtData.usage.input_count || 0,\n outputTokens: evtData.usage.output_count || 0,\n totalTokens: evtData.usage.total_count || 0,\n };\n }\n } else if (event === 'error') {\n finishReason = 'error';\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n const content: LanguageModelV2Content[] = [];\n if (reasoningContent) {\n content.push({ type: 'reasoning', text: reasoningContent });\n }\n if (textContent) {\n content.push({ type: 'text', text: textContent });\n }\n\n return { content, finishReason, usage };\n}\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { generateId } from '@ai-sdk/provider-utils';\n\n/**\n * 创建一个包含错误信息的流\n * @param error 错误信息\n * @returns ReadableStream<LanguageModelV2StreamPart>\n */\nexport const createErrorStream = (error: string): ReadableStream<LanguageModelV2StreamPart> => {\n return new ReadableStream<LanguageModelV2StreamPart>({\n start(controller) {\n const id = generateId();\n controller.enqueue({\n id,\n type: 'text-start',\n });\n controller.enqueue({\n id,\n type: 'text-delta',\n providerMetadata: {\n raw: { data: { type: 'agent-error', error } },\n },\n delta: error,\n });\n controller.enqueue({\n type: 'text-end',\n id,\n });\n controller.close();\n },\n });\n};\n","/**\n * 事件数据取样,某些流 chunk 处理,需要用到前后的 chunk 信息,因此设计一个类缓存相邻 chunk,用于处理依据\n */\nexport class EvtSample {\n private _evtSampleMap: Map<string, any> = new Map();\n private _key1: string = \"1\";\n private _key2: string = \"2\";\n private _maxSample = 2;\n\n public addEventSample(evt: any) {\n if (this._evtSampleMap.size >= this._maxSample) {\n const evt2 = this._evtSampleMap.get(this._key2);\n this._evtSampleMap.set(this._key1, evt2);\n this._evtSampleMap.set(this._key2, evt);\n return;\n }\n\n this._evtSampleMap.set((this._evtSampleMap.size + 1).toString(), evt);\n }\n\n public getFirstSample() {\n return this._evtSampleMap.get(this._key1);\n }\n\n public getSecondSample() {\n return this._evtSampleMap.get(this._key2);\n }\n}\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { StreamChatData } from '@coze/api';\nimport { EvtSample } from '../evt-sample';\n\n/**\n * 补充特殊的 llm chunk, reasoning-end, text-start\n */\nexport class LLMChunkInjectorTransformStream extends TransformStream<\n StreamChatData,\n | StreamChatData\n | (LanguageModelV2StreamPart & {\n disableTransform: boolean;\n })\n> {\n private eventSampleMap = new EvtSample();\n\n constructor() {\n super({\n transform: (\n part: StreamChatData,\n controller: TransformStreamDefaultController<\n StreamChatData | (LanguageModelV2StreamPart & { disableTransform: boolean })\n >\n ) => {\n // 添加事件样本(原逻辑中的addEventSample)\n this.eventSampleMap.addEventSample(part);\n\n // 处理sample1/sample2特殊判断逻辑\n const sample1 = this.eventSampleMap.getFirstSample();\n const sample2 = this.eventSampleMap.getSecondSample();\n\n // handle reasoning end\n if (\n sample1 &&\n sample2 &&\n sample1.data.reasoning_content &&\n !sample2.data.reasoning_content\n ) {\n controller.enqueue({\n disableTransform: true,\n type: 'reasoning-end',\n id: sample1.data.conversation_id,\n });\n }\n\n // handle text-start\n if (sample1 && sample2 && !sample1.data.content && sample2.data.content) {\n controller.enqueue({\n disableTransform: true,\n type: 'text-start',\n id: sample2.data.conversation_id,\n });\n }\n\n // 传递part到下一个转换流\n controller.enqueue(part);\n },\n });\n }\n}\n","import { ChatEventType, StreamChatData } from '@coze/api';\nimport { ServerSentEvent } from 'parse-sse';\n\nexport default class MCPChunkFilterTransformStream extends TransformStream {\n isVisibleMsgPart(evtData: any, part: any, omitTextEndChunk?: boolean) {\n if (evtData.type === 'knowledge' && evtData.role === 'assistant') {\n return false;\n }\n\n // Omit text-end chunk if the flag is set\n if (\n omitTextEndChunk &&\n part.event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED &&\n part.data.type !== 'follow_up'\n ) {\n return false;\n }\n\n if (part.event === 'conversation.message.completed' && evtData.type == 'verbose') {\n return false;\n }\n\n return true;\n }\n\n constructor(omitTextEndChunk: boolean = false) {\n super({\n transform: (\n evt: ServerSentEvent,\n controller: TransformStreamDefaultController<StreamChatData>\n ) => {\n if (!evt) return;\n\n // 解析evt为part对象(原逻辑中的part构建)\n const part = {\n event: evt.type,\n data: JSON.parse(evt.data) || {},\n } as StreamChatData;\n\n // 过滤逻辑:仅传递满足条件的part\n if (this.isVisibleMsgPart(part.data, part, omitTextEndChunk)) {\n controller.enqueue(part);\n }\n },\n });\n }\n}\n","import { LanguageModelV2StreamPart, SharedV2ProviderMetadata } from '@ai-sdk/provider';\nimport { ChatEventType } from '@coze/api';\n\nexport const mcp2llmChunk = (part: any): LanguageModelV2StreamPart | null => {\n const fullData = JSON.stringify(part);\n\n switch (part.event) {\n case ChatEventType.CONVERSATION_CHAT_CREATED:\n return {\n type: 'raw',\n rawValue: part.data,\n };\n break;\n\n case ChatEventType.CONVERSATION_CHAT_IN_PROGRESS:\n return {\n // type: \"text-delta\",\n // id: part.data.conversation_id,\n // delta: part.data.content || \"\",\n // providerMetadata: {\n // raw: { data: fullData },\n // },\n type: 'raw',\n rawValue: part.data,\n };\n break;\n\n case ChatEventType.CONVERSATION_MESSAGE_DELTA:\n const isReasoning = Boolean(part.data.reasoning_content);\n return {\n type: isReasoning ? 'reasoning-delta' : 'text-delta',\n delta: isReasoning ? part.data.reasoning_content : part.data.content,\n id: part.data.conversation_id,\n providerMetadata: {},\n };\n break;\n\n case ChatEventType.CONVERSATION_MESSAGE_COMPLETED:\n if (part.data && part.data.type === 'follow_up') {\n return {\n type: 'raw',\n rawValue: part.data,\n };\n }\n\n if (part.status === 'completed') {\n return {\n type: 'text-end',\n id: part.data.conversation_id,\n // delta: part.data.content || part.data.reasoning_content || \"\",\n providerMetadata: {},\n };\n }\n\n return {\n type: 'raw',\n rawValue: part.data,\n };\n\n break;\n\n case ChatEventType.CONVERSATION_CHAT_COMPLETED:\n // Yield finish event with usage information\n return {\n type: 'finish',\n finishReason: 'stop',\n usage: {\n inputTokens: part.data.usage?.input_count || 0,\n outputTokens: part.data.usage?.output_count || 0,\n totalTokens: part.data.usage?.total_count || 0,\n },\n };\n break;\n\n case ChatEventType.DONE:\n // Stream completed successfully\n return {\n type: 'finish',\n finishReason: 'stop',\n usage: {\n inputTokens: part.data.usage?.input_count || 0,\n outputTokens: part.data.usage?.output_count || 0,\n totalTokens: part.data.usage?.total_count || 0,\n },\n };\n break;\n\n case ChatEventType.ERROR:\n // Handle errors\n console.error('[ERROR]', part.data);\n return {\n type: 'error',\n error: part.data,\n };\n\n default:\n // Handle unknown event types\n console.warn('Unknown event type:', part.event);\n return {\n type: 'error',\n error: 'Unknown event type' + part.event,\n };\n }\n\n return {\n type: 'error',\n error: 'unknown',\n };\n};\n","import { ChatEventType, StreamChatData } from '@coze/api';\nimport { mcp2llmChunk } from '../utils/mcp-to-llm-chunk';\nimport { LanguageModelV2StreamPart } from '@ai-sdk/provider';\n\nexport default class LLMPartTrasnformStream extends TransformStream {\n constructor() {\n super({\n transform: (\n part: StreamChatData | (LanguageModelV2StreamPart & { disableTransform: boolean }),\n controller: TransformStreamDefaultController<LanguageModelV2StreamPart | undefined>\n ) => {\n // Bypass transform if disableTransform flag is set\n const { disableTransform } = part as any;\n if (disableTransform) {\n controller.enqueue(part as any);\n return;\n }\n\n try {\n const chunk = mcp2llmChunk(part as any);\n if (chunk) {\n controller.enqueue(chunk as any);\n }\n } catch (error) {\n console.error('transform coze evt error');\n }\n },\n });\n }\n}\n","import { CreateChatRes } from '@coze/api';\nimport { CozeChatConfig, IGenerateResult } from '../types';\nimport { getCozeChatMsgDetail } from './get-coze-chat-msg-detail';\n\nexport const BuildWarningGenerateResult = (message: string): IGenerateResult => {\n return {\n content: [],\n finishReason: 'error',\n request: {\n body: null,\n },\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n },\n response: {\n body: null,\n },\n warnings: [\n {\n type: 'other',\n message,\n },\n ],\n };\n};\n\nexport const BuildGenerateResultByChatRes = async (\n response: Response,\n chatConfig: CozeChatConfig,\n reqBody?: unknown\n): Promise<IGenerateResult> => {\n if (!response.ok) {\n return Promise.reject(\n BuildWarningGenerateResult(`Coze API error: ${response.status} ${response.statusText}`)\n );\n }\n\n const res = (await response.json()) as CreateChatRes;\n if (res.code !== 0) {\n return Promise.reject(BuildWarningGenerateResult(`Coze API error: ${res.code} ${res.msg}`));\n }\n\n const msgRes = await getCozeChatMsgDetail(res.data.conversation_id, res.data.id, chatConfig);\n if (!msgRes.ok) {\n return Promise.reject(\n BuildWarningGenerateResult(\n `Failed to get message detail: ${msgRes.status} ${msgRes.statusText}`\n )\n );\n }\n const msgDetail = await msgRes.json();\n\n return {\n content: msgDetail.data.message.content,\n finishReason: msgDetail.data.message.status === 'finished' ? 'stop' : 'error',\n request: {\n body: reqBody,\n },\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n },\n response: {\n body: msgDetail,\n },\n warnings: [],\n };\n};\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { JSONParser } from '@streamparser/json';\nimport { createTextInfoEnqueuer, TextInfoEnqueuer } from '../utils/enqueue-text-info';\nimport { rebuildFieldsJsonStructure } from '@baishuyun/ai-feat-utils';\n\nexport const createFieldsJsonTransformStream = (enableJsonParser: boolean) => {\n let parser: JSONParser;\n let enqueueTextDelta: TextInfoEnqueuer;\n let id: string;\n let isFirstChunk = true;\n // 当 LLM 返回的不是 JSON 而是普通文本时,切换到直通模式\n let passthroughMode = false;\n\n const chunkGuard = (chunk: LanguageModelV2StreamPart): boolean => {\n if (!enableJsonParser || passthroughMode) {\n return false;\n }\n\n if (chunk.type !== 'text-delta' || !('delta' in chunk)) {\n return false;\n }\n\n return true;\n };\n\n const transformer = {\n flush: (controller: TransformStreamDefaultController<any>) => {\n try {\n // parser?.end();\n controller.terminate(); // 信号通知下游可读流已关闭\n } catch (e) {\n controller.error('stop error' + e);\n }\n },\n transform: (\n chunk: LanguageModelV2StreamPart,\n controller: TransformStreamDefaultController<LanguageModelV2StreamPart>\n ) => {\n if (!parser && !passthroughMode) {\n return;\n }\n\n try {\n if (chunkGuard(chunk)) {\n if ('id' in chunk && 'delta' in chunk) {\n id = chunk.id;\n let delta = chunk.delta;\n if (isFirstChunk) {\n delta = delta.replace(/^\\uFEFF/, '');\n isFirstChunk = false;\n }\n parser.write(delta);\n } else {\n console.warn('Unexpected chunk format for JSON parsing:', chunk);\n controller.enqueue(chunk);\n }\n } else {\n controller.enqueue(chunk);\n }\n } catch (e) {\n console.log('write or enqueue error', e);\n controller.error(e);\n }\n },\n start: (controller: TransformStreamDefaultController<any>) => {\n parser = new JSONParser({\n paths: ['$.*'],\n });\n\n enqueueTextDelta = enableJsonParser\n ? createTextInfoEnqueuer(controller)\n : (content: string) => {};\n\n parser.onValue = (parsedInfo: any) => {\n const value = parsedInfo.value;\n\n if (value.widget) {\n value.widget.widgetName = `_widget_${Date.now()}`;\n }\n\n enqueueTextDelta(\n JSON.stringify(value),\n JSON.stringify({\n type: 'mcp-fields-json',\n field: rebuildFieldsJsonStructure(value),\n }),\n id\n );\n };\n\n parser.onError = (err: any) => {\n console.error('JsonWidgetStream: JSON Parsing Error:', err);\n\n // LLM 返回的不是 JSON,切换到直通模式,后续 text-delta 直接透传\n passthroughMode = true;\n };\n\n parser.onEnd = () => {\n enqueueTextDelta(\n ' ',\n JSON.stringify({\n appendConfirm: 'save-fields',\n })\n );\n };\n },\n };\n\n return new TransformStream<LanguageModelV2StreamPart, any>(transformer);\n};\n","import { JSONValue, LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { generateId } from '@ai-sdk/provider-utils';\n\nexport type TextInfoEnqueuer = (textInfo: string, metaPayload?: JSONValue, id?: string) => void;\n\nexport const createTextInfoEnqueuer =\n (controller: TransformStreamDefaultController<LanguageModelV2StreamPart>) =>\n (\n textInfo: string,\n metaPayload?: JSONValue,\n id: string = generateId(),\n deltaOnly: boolean = false\n ) => {\n const i = id ?? generateId();\n\n const startPart: LanguageModelV2StreamPart = {\n type: 'text-start',\n id: i,\n };\n\n const deltaPart: LanguageModelV2StreamPart = {\n type: 'text-delta',\n id: i,\n delta: textInfo,\n providerMetadata: metaPayload\n ? {\n raw: { data: metaPayload },\n }\n : undefined,\n };\n\n const endPart: LanguageModelV2StreamPart = {\n type: 'text-end',\n id: i,\n };\n\n if (deltaOnly) {\n controller.enqueue(deltaPart);\n return;\n }\n\n controller.enqueue(startPart);\n controller.enqueue(deltaPart);\n controller.enqueue(endPart);\n };\n","import {\n createTextInfoEnqueuer,\n TextInfoEnqueuer,\n} from \"../utils/enqueue-text-info\";\n\nexport default class SuggestionTransformStream extends TransformStream<\n any,\n any\n> {\n constructor(enable: boolean) {\n let enqueuer: TextInfoEnqueuer;\n super({\n start(controller) {\n enqueuer = createTextInfoEnqueuer(controller);\n },\n transform(chunk, controller) {\n if (\n enable &&\n chunk.type === \"raw\" &&\n chunk.rawValue.type === \"follow_up\" &&\n enqueuer\n ) {\n enqueuer(\n chunk.rawValue.content,\n JSON.stringify({\n type: \"suggestion\",\n }),\n );\n } else {\n controller.enqueue(chunk);\n }\n },\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,sBAKO;AAEP,IAAAA,yBAKO;;;ACZA,IAAM,UAAU;;;ACSvB,IAAAC,oBAA+C;AAC/C,IAAAC,cAAkC;;;ACJlC,iBAAyB;AAIzB,IAAM,UAAU,IAAI,YAAY,OAAO;AAWvC,IAAM,cAAc,CAAC,SAA4D;AAC/E,MAAI,KAAK,SAAS,QAAQ;AACxB,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,KAAK,WAAW,WAAW,QAAQ;AACjD,MAAI,OAAO;AACT,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,KAAK,WAAW,WAAW,QAAQ;AACnD,MAAI,SAAS;AACX,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAEA,IAAM,sBAAsB,CAAC,SAAiC,eAAyB;AACrF,MAAI,YAAY;AACd,WAAQ,QAAQ,QACb,IAAI,CAAC,SAAkC,KAAK,IAAI,EAChD,KAAK,IAAI;AAAA,EACd;AAEA,QAAM,SAAU,QAAQ,QAAqE;AAAA,IAC3F,CAAC,SAAS;AACR,YAAM,OAAO,KAAK,iBAAiB;AACnC,YAAM,MAAM,MAAM;AAElB,aAAO;AAAA,QACL,MAAM,YAAY,IAAI;AAAA,QACtB,MAAM,KAAK,SAAS,SAAU,KAAiC,OAAO;AAAA,QACtE,SAAS,MAAM;AAAA,QACf,MAAM,MAAM;AAAA;AAAA,QAEZ;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,KAAK,UAAU,MAAM;AAC9B;AAEA,IAAM,gBAAgB,CAAC,YAAqB,QAAQ,QAAQ,MAAM,CAAC,SAAS,KAAK,SAAS,MAAM;AAEzF,IAAM,0BAA0B,CAAC,aAAoC;AAC1E,SAAO,SAAS,IAAI,CAAC,YAAY;AAC/B,UAAM,aAAa,cAAc,OAAkB;AACnD,YAAQ,QAAQ,MAAM;AAAA,MACpB,KAAK;AACH,eAAO;AAAA,UACL,MAAM,oBAAS;AAAA,UACf,SAAS,oBAAoB,SAAS,UAAU;AAAA,UAChD,cAAc,aAAa,SAAS;AAAA,QACtC;AACA;AAAA,MAEF,KAAK;AACH,eAAO;AAAA,UACL,MAAM,oBAAS;AAAA,UACf,SAAU,QAAQ,QACf,IAAI,CAAC,SAAmC,KAAK,SAAS,SAAS,KAAK,OAAO,EAAG,EAC9E,KAAK,EAAE;AAAA,UACV,cAAc;AAAA,QAChB;AACA;AAAA,IACJ;AAAA,EACF,CAAC;AACH;;;ACrFA,uBAA+C;AAC/C,iBAAkC;AAWlC,eAAsB,sBACpB,MACiC;AACjC,QAAM,YAAY,KACf;AAAA,IACC,IAAI,6BAAkB;AAAA,EAIxB,EACC,YAAY,IAAI,gDAA+B,CAAC;AAEnD,MAAI,cAAc;AAClB,MAAI,mBAAmB;AACvB,MAAI,eAA4C;AAChD,MAAI,QAA8B,EAAE,aAAa,GAAG,cAAc,GAAG,aAAa,EAAE;AAEpF,QAAM,SAAS,UAAU,UAAU;AACnC,MAAI;AACF,WAAO,MAAM;AACX,YAAM,EAAE,MAAM,OAAO,IAAI,IAAI,MAAM,OAAO,KAAK;AAC/C,UAAI,KAAM;AACV,UAAI,CAAC,IAAK;AAEV,UAAI;AACJ,UAAI;AACF,kBAAU,KAAK,MAAM,IAAI,IAAI;AAAA,MAC/B,QAAQ;AACN;AAAA,MACF;AAEA,YAAM,QAAQ,IAAI;AAElB,UAAI,UAAU,8BAA8B;AAC1C,YAAI,QAAQ,mBAAmB;AAC7B,8BAAoB,QAAQ;AAAA,QAC9B,WAAW,QAAQ,SAAS;AAC1B,yBAAe,QAAQ;AAAA,QACzB;AAAA,MACF,WAAW,UAAU,iCAAiC,UAAU,QAAQ;AACtE,uBAAe;AACf,YAAI,QAAQ,OAAO;AACjB,kBAAQ;AAAA,YACN,aAAa,QAAQ,MAAM,eAAe;AAAA,YAC1C,cAAc,QAAQ,MAAM,gBAAgB;AAAA,YAC5C,aAAa,QAAQ,MAAM,eAAe;AAAA,UAC5C;AAAA,QACF;AAAA,MACF,WAAW,UAAU,SAAS;AAC5B,uBAAe;AAAA,MACjB;AAAA,IACF;AAAA,EACF,UAAE;AACA,WAAO,YAAY;AAAA,EACrB;AAEA,QAAM,UAAoC,CAAC;AAC3C,MAAI,kBAAkB;AACpB,YAAQ,KAAK,EAAE,MAAM,aAAa,MAAM,iBAAiB,CAAC;AAAA,EAC5D;AACA,MAAI,aAAa;AACf,YAAQ,KAAK,EAAE,MAAM,QAAQ,MAAM,YAAY,CAAC;AAAA,EAClD;AAEA,SAAO,EAAE,SAAS,cAAc,MAAM;AACxC;;;ACjFA,4BAA2B;AAOpB,IAAM,oBAAoB,CAAC,UAA6D;AAC7F,SAAO,IAAI,eAA0C;AAAA,IACnD,MAAM,YAAY;AAChB,YAAM,SAAK,kCAAW;AACtB,iBAAW,QAAQ;AAAA,QACjB;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AACD,iBAAW,QAAQ;AAAA,QACjB;AAAA,QACA,MAAM;AAAA,QACN,kBAAkB;AAAA,UAChB,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,MAAM,EAAE;AAAA,QAC9C;AAAA,QACA,OAAO;AAAA,MACT,CAAC;AACD,iBAAW,QAAQ;AAAA,QACjB,MAAM;AAAA,QACN;AAAA,MACF,CAAC;AACD,iBAAW,MAAM;AAAA,IACnB;AAAA,EACF,CAAC;AACH;;;AC5BO,IAAM,YAAN,MAAgB;AAAA,EACb,gBAAkC,oBAAI,IAAI;AAAA,EAC1C,QAAgB;AAAA,EAChB,QAAgB;AAAA,EAChB,aAAa;AAAA,EAEd,eAAe,KAAU;AAC9B,QAAI,KAAK,cAAc,QAAQ,KAAK,YAAY;AAC9C,YAAM,OAAO,KAAK,cAAc,IAAI,KAAK,KAAK;AAC9C,WAAK,cAAc,IAAI,KAAK,OAAO,IAAI;AACvC,WAAK,cAAc,IAAI,KAAK,OAAO,GAAG;AACtC;AAAA,IACF;AAEA,SAAK,cAAc,KAAK,KAAK,cAAc,OAAO,GAAG,SAAS,GAAG,GAAG;AAAA,EACtE;AAAA,EAEO,iBAAiB;AACtB,WAAO,KAAK,cAAc,IAAI,KAAK,KAAK;AAAA,EAC1C;AAAA,EAEO,kBAAkB;AACvB,WAAO,KAAK,cAAc,IAAI,KAAK,KAAK;AAAA,EAC1C;AACF;;;ACpBO,IAAM,kCAAN,cAA8C,gBAMnD;AAAA,EACQ,iBAAiB,IAAI,UAAU;AAAA,EAEvC,cAAc;AACZ,UAAM;AAAA,MACJ,WAAW,CACT,MACA,eAGG;AAEH,aAAK,eAAe,eAAe,IAAI;AAGvC,cAAM,UAAU,KAAK,eAAe,eAAe;AACnD,cAAM,UAAU,KAAK,eAAe,gBAAgB;AAGpD,YACE,WACA,WACA,QAAQ,KAAK,qBACb,CAAC,QAAQ,KAAK,mBACd;AACA,qBAAW,QAAQ;AAAA,YACjB,kBAAkB;AAAA,YAClB,MAAM;AAAA,YACN,IAAI,QAAQ,KAAK;AAAA,UACnB,CAAC;AAAA,QACH;AAGA,YAAI,WAAW,WAAW,CAAC,QAAQ,KAAK,WAAW,QAAQ,KAAK,SAAS;AACvE,qBAAW,QAAQ;AAAA,YACjB,kBAAkB;AAAA,YAClB,MAAM;AAAA,YACN,IAAI,QAAQ,KAAK;AAAA,UACnB,CAAC;AAAA,QACH;AAGA,mBAAW,QAAQ,IAAI;AAAA,MACzB;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC3DA,IAAAC,cAA8C;AAG9C,IAAqB,gCAArB,cAA2D,gBAAgB;AAAA,EACzE,iBAAiB,SAAc,MAAW,kBAA4B;AACpE,QAAI,QAAQ,SAAS,eAAe,QAAQ,SAAS,aAAa;AAChE,aAAO;AAAA,IACT;AAGA,QACE,oBACA,KAAK,UAAU,0BAAc,kCAC7B,KAAK,KAAK,SAAS,aACnB;AACA,aAAO;AAAA,IACT;AAEA,QAAI,KAAK,UAAU,oCAAoC,QAAQ,QAAQ,WAAW;AAChF,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,mBAA4B,OAAO;AAC7C,UAAM;AAAA,MACJ,WAAW,CACT,KACA,eACG;AACH,YAAI,CAAC,IAAK;AAGV,cAAM,OAAO;AAAA,UACX,OAAO,IAAI;AAAA,UACX,MAAM,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC;AAAA,QACjC;AAGA,YAAI,KAAK,iBAAiB,KAAK,MAAM,MAAM,gBAAgB,GAAG;AAC5D,qBAAW,QAAQ,IAAI;AAAA,QACzB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC7CA,IAAAC,cAA8B;AAEvB,IAAM,eAAe,CAAC,SAAgD;AAC3E,QAAM,WAAW,KAAK,UAAU,IAAI;AAEpC,UAAQ,KAAK,OAAO;AAAA,IAClB,KAAK,0BAAc;AACjB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,KAAK;AAAA,MACjB;AACA;AAAA,IAEF,KAAK,0BAAc;AACjB,aAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAOL,MAAM;AAAA,QACN,UAAU,KAAK;AAAA,MACjB;AACA;AAAA,IAEF,KAAK,0BAAc;AACjB,YAAM,cAAc,QAAQ,KAAK,KAAK,iBAAiB;AACvD,aAAO;AAAA,QACL,MAAM,cAAc,oBAAoB;AAAA,QACxC,OAAO,cAAc,KAAK,KAAK,oBAAoB,KAAK,KAAK;AAAA,QAC7D,IAAI,KAAK,KAAK;AAAA,QACd,kBAAkB,CAAC;AAAA,MACrB;AACA;AAAA,IAEF,KAAK,0BAAc;AACjB,UAAI,KAAK,QAAQ,KAAK,KAAK,SAAS,aAAa;AAC/C,eAAO;AAAA,UACL,MAAM;AAAA,UACN,UAAU,KAAK;AAAA,QACjB;AAAA,MACF;AAEA,UAAI,KAAK,WAAW,aAAa;AAC/B,eAAO;AAAA,UACL,MAAM;AAAA,UACN,IAAI,KAAK,KAAK;AAAA;AAAA,UAEd,kBAAkB,CAAC;AAAA,QACrB;AAAA,MACF;AAEA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,KAAK;AAAA,MACjB;AAEA;AAAA,IAEF,KAAK,0BAAc;AAEjB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,cAAc;AAAA,QACd,OAAO;AAAA,UACL,aAAa,KAAK,KAAK,OAAO,eAAe;AAAA,UAC7C,cAAc,KAAK,KAAK,OAAO,gBAAgB;AAAA,UAC/C,aAAa,KAAK,KAAK,OAAO,eAAe;AAAA,QAC/C;AAAA,MACF;AACA;AAAA,IAEF,KAAK,0BAAc;AAEjB,aAAO;AAAA,QACL,MAAM;AAAA,QACN,cAAc;AAAA,QACd,OAAO;AAAA,UACL,aAAa,KAAK,KAAK,OAAO,eAAe;AAAA,UAC7C,cAAc,KAAK,KAAK,OAAO,gBAAgB;AAAA,UAC/C,aAAa,KAAK,KAAK,OAAO,eAAe;AAAA,QAC/C;AAAA,MACF;AACA;AAAA,IAEF,KAAK,0BAAc;AAEjB,cAAQ,MAAM,WAAW,KAAK,IAAI;AAClC,aAAO;AAAA,QACL,MAAM;AAAA,QACN,OAAO,KAAK;AAAA,MACd;AAAA,IAEF;AAEE,cAAQ,KAAK,uBAAuB,KAAK,KAAK;AAC9C,aAAO;AAAA,QACL,MAAM;AAAA,QACN,OAAO,uBAAuB,KAAK;AAAA,MACrC;AAAA,EACJ;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,EACT;AACF;;;ACxGA,IAAqB,yBAArB,cAAoD,gBAAgB;AAAA,EAClE,cAAc;AACZ,UAAM;AAAA,MACJ,WAAW,CACT,MACA,eACG;AAEH,cAAM,EAAE,iBAAiB,IAAI;AAC7B,YAAI,kBAAkB;AACpB,qBAAW,QAAQ,IAAW;AAC9B;AAAA,QACF;AAEA,YAAI;AACF,gBAAM,QAAQ,aAAa,IAAW;AACtC,cAAI,OAAO;AACT,uBAAW,QAAQ,KAAY;AAAA,UACjC;AAAA,QACF,SAAS,OAAO;AACd,kBAAQ,MAAM,0BAA0B;AAAA,QAC1C;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACzBO,IAAM,6BAA6B,CAAC,YAAqC;AAC9E,SAAO;AAAA,IACL,SAAS,CAAC;AAAA,IACV,cAAc;AAAA,IACd,SAAS;AAAA,MACP,MAAM;AAAA,IACR;AAAA,IACA,OAAO;AAAA,MACL,aAAa;AAAA,MACb,cAAc;AAAA,MACd,aAAa;AAAA,IACf;AAAA,IACA,UAAU;AAAA,MACR,MAAM;AAAA,IACR;AAAA,IACA,UAAU;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;ATRA,2BAAoE;AAG7D,IAAM,oBAAN,MAAmD;AAAA,EACxD,uBAA6B;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EAEiB;AAAA,EAEjB,YAAY,SAAiB,QAAwB;AACnD,SAAK,UAAU;AACf,SAAK,WAAW,OAAO,YAAY;AACnC,SAAK,gBAAgB,OAAO,gBAAgB,KAAK,CAAC;AAClD,SAAK,SAAS;AAAA,EAChB;AAAA,EAEA,MAAM,WAAW,SAA+D;AAC9E,UAAM,WAAW,wBAAwB,QAAQ,MAAM;AACvD,UAAM,WAAyC,CAAC;AAEhD,UAAM,MAAM,KAAK,OAAO,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE7C,UAAM,UAAU,QAAQ,UAAU,QAAQ,QAAQ,WAAW,IAAI;AACjE,UAAM,WAAW,QAAQ,UAAU,QAAQ,QAAQ,YAAY,IAAI;AAEnE,QAAI;AACJ,QAAI,UAAU;AACZ,UAAI;AACF,oBAAY,KAAK,MAAM,QAAQ;AAAA,MACjC,SAAS,GAAG;AACV,gBAAQ,KAAK,0BAA0B,CAAC;AAAA,MAC1C;AAAA,IACF;AAEA,UAAM,OAAO;AAAA,MACX,QAAQ,KAAK,OAAO;AAAA,MACpB,mBAAmB;AAAA,MACnB,SAAS,WAAW;AAAA,MACpB,QAAQ;AAAA,MACR,qBAAqB;AAAA,IACvB;AAEA,QAAI,WAAW;AACb,MAAC,KAAa,mBAAmB;AAAA,IACnC;AAEA,UAAM,UAAU,KAAK,OAAO,QAAQ;AACpC,UAAM,cAAc,QAAQ;AAE5B,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR;AAAA,MACA,aAAa;AAAA,MACb,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ;AAAA,IACV,CAAC;AAED,QAAI,CAAC,SAAS,MAAM,CAAC,SAAS,MAAM;AAClC,YAAM,WAAW,MAAM,SAAS,KAAK;AACrC,UAAI;AACJ,UAAI;AACF,sBAAc,KAAK,MAAM,QAAQ;AAAA,MACnC,QAAQ;AACN,sBAAc;AAAA,MAChB;AAEA,YAAM,eACJ,OAAO,gBAAgB,YAAY,aAAa,MAC5C,YAAY,MACZ,mBAAmB,SAAS,MAAM,IAAI,SAAS,UAAU;AAE/D,aAAO,2BAA2B,YAAY;AAAA,IAChD;AAEA,UAAM,EAAE,SAAS,cAAc,MAAM,IAAI,MAAM,sBAAsB,SAAS,IAAI;AAElF,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,EAAE,KAAK;AAAA,MAChB,UAAU,EAAE,MAAM,KAAK;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AAAA,EAEA,iBAAiB,SAAc;AAC7B,QAAI,QAAQ,SAAS,eAAe,QAAQ,SAAS,aAAa;AAChE,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,SAAS,SAIZ;AACD,UAAM,kBAAkB,QAAQ,UAAU,QAAQ,QAAQ,mBAAmB,IAAI;AAGjF,UAAM,SAAS,kBAAkB,wBAAwB,QAAQ,MAAM,IAAI,QAAQ;AAEnF,UAAM,WAAW,wBAAwB,MAAM;AAC/C,UAAM,WAAW,kBAAkB,oBAAoB,eAAe,KAAK;AAE3E,UAAM,MAAM,KAAK,OAAO,IAAI;AAAA,MAC1B,MAAM,QAAQ,QAAQ;AAAA,IACxB,CAAC;AAED,UAAM,UAAU,QAAQ,UAAU,QAAQ,QAAQ,WAAW,IAAI;AAEjE,UAAM,WAAW,QAAQ,UAAU,QAAQ,QAAQ,YAAY,IAAI;AACnE,UAAM,cAAc,QAAQ,UAAU,QAAQ,QAAQ,cAAc,IAAI,OAAO;AAE/E,UAAM,SAAS,iBAAa,oCAAc,UAAU,IAAI,CAAC;AAEzD,YAAQ,IAAI,qBAAqB,MAAM;AACvC,YAAQ,IAAI,8BAA8B,eAAe;AACzD,UAAM,UAAU,SAAS,iBAAiB;AAE1C,UAAM,SAAS,SAAS,MAAM,OAAO,WAAW,KAAK,IAAI,EAAE,SAAS;AAEpE,UAAM,OAAO;AAAA,MACX,QAAQ,KAAK,OAAO;AAAA,MACpB,mBAAmB,QAAQ,eAAe;AAAA,MAC1C,SAAS;AAAA,MACT,QAAQ;AAAA,MACR,qBAAqB;AAAA,MACrB,YAAY;AAAA,MACZ,kBAAkB,eAAW,oCAAc,QAAQ,IAAI,CAAC;AAAA,MACxD,cAAc;AAAA,QACZ,YAAQ,yCAAmB,OAAO;AAAA,QAClC,aAAS,uCAAiB,OAAO;AAAA,MACnC;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,OAAO,QAAQ;AAEpC,UAAM,cAAc,QAAQ;AAE5B,YAAQ,IAAI,OAAO,GAAG;AACtB,YAAQ,IAAI,QAAQ,KAAK,UAAU,MAAM,MAAM,CAAC,CAAC;AAEjD,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,QAAQ;AAAA,MACR;AAAA,MACA,aAAa;AAAA,MACb,MAAM,KAAK,UAAU,IAAI;AAAA,MACzB,QAAQ;AAAA,IACV,CAAC;AAED,YAAQ,IAAI,mBAAmB,SAAS,MAAM;AAE9C,QAAI,CAAC,SAAS,MAAM,CAAC,SAAS,MAAM;AAElC,YAAM,WAAW,MAAM,SAAS,KAAK;AACrC,UAAI;AACJ,UAAI;AACF,sBAAc,KAAK,MAAM,QAAQ;AAAA,MACnC,QAAQ;AACN,sBAAc;AAAA,MAChB;AAGA,YAAM,eACJ,OAAO,gBAAgB,YAAY,aAAa,MAC5C,YAAY,MACZ,mBAAmB,SAAS,MAAM,IAAI,SAAS,UAAU;AAE/D,cAAQ,MAAM,YAAY;AAE1B,aAAO;AAAA,QACL,QAAQ,kBAAkB,kDAAU;AAAA,MACtC;AAAA,IACF;AAEA,QAAI,wBAAwB,KAAK,OAAO,2BAA2B,CAAC,GAAG;AAAA,MAAI,CAAC,YAC1E,QAAQ;AAAA,IACV;AAGA,UAAM,QAAQ,QAAQ,UAAU,QAAQ,QAAQ,cAAc,IAAI;AAClE,UAAM,eAAe,UAAU;AAC/B,UAAM,cAAc,UAAU;AAE9B,UAAM,SAAS,SAAS,KAErB;AAAA,MACC,IAAI,8BAAkB;AAAA,IAIxB,EAEC,YAAY,IAAI,iDAA+B,CAAC,EAChD,YAAY,IAAI,8BAA8B,gBAAgB,WAAW,CAAC,EAE1E,YAAY,IAAI,gCAAgC,CAAC,EAEjD,YAAY,IAAI,uBAAuB,CAAC;AAE3C,QAAI,cAAc;AAElB,QAAI,qBAAqB,SAAS,GAAG;AACnC,oBAAc,qBAAqB;AAAA,QACjC,CAAC,QAAQ,gBAAgB,OAAO,YAAY,WAAW;AAAA,QACvD;AAAA;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,MACL,QAAQ;AAAA,IACV;AAAA,EACF;AACF;AAMA,SAAS,wBAAwB,QAAsD;AACrF,WAAS,IAAI,OAAO,SAAS,GAAG,KAAK,GAAG,KAAK;AAC3C,QAAI,OAAO,CAAC,EAAE,SAAS,QAAQ;AAC7B,aAAO,CAAC,OAAO,CAAC,CAAC;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;;;AFvMO,SAAS,WACd,UAAgC;AAAA,EAC9B,OAAO;AACT,GACc;AACd,QAAM,cAAU,6CAAqB,QAAQ,OAAO;AAEpD,QAAM,sBAAkB,4CAAoB,QAAQ,WAAW,CAAC,GAAG,eAAe,OAAO,EAAE;AAC3F,QAAM,sBAAsB,cAAU,mCAAW;AAAA,IAC/C,QAAQ,QAAQ;AAAA,IAChB,yBAAyB;AAAA,IACzB,aAAa;AAAA,EACf,CAAC,CAAC;AAEF,QAAM,aAAa,OAAO;AAAA,IACxB,GAAG;AAAA,IACH,eAAe;AAAA,IACf,gBAAgB;AAAA,EAClB;AAEA,QAAM,sBAAsB,CAAC,YAA6B;AACxD,WAAO,IAAI,kBAAkB,SAAS;AAAA,MACpC,OAAO,QAAQ;AAAA,MACf,UAAU;AAAA,MACV,KAAK,CAAC,EAAE,KAAK,MAAM,GAAG,OAAO,GAAG,IAAI;AAAA,MACpC,SAAS;AAAA,MACT,OAAO,QAAQ;AAAA,MACf,yBAAyB,QAAQ,2BAA2B,CAAC;AAAA,IAC/D,CAAC;AAAA,EACH;AAEA,QAAM,WAAW,CAAC,YAA6B,oBAAoB,OAAO;AAE1E,WAAS,uBAAuB;AAChC,WAAS,gBAAgB;AACzB,WAAS,OAAO;AAEhB,WAAS,iBAAiB,CAAC,YAAoB;AAC7C,UAAM,IAAI,iCAAiB,EAAE,SAAS,WAAW,qBAAqB,CAAC;AAAA,EACzE;AACA,WAAS,aAAa,CAAC,YAAoB;AACzC,UAAM,IAAI,iCAAiB,EAAE,SAAS,WAAW,aAAa,CAAC;AAAA,EACjE;AACA,WAAS,qBAAqB,CAAC,YAAoB;AACjD,UAAM,IAAI,iCAAiB,EAAE,SAAS,WAAW,qBAAqB,CAAC;AAAA,EACzE;AAEA,SAAO;AACT;;;AYjGA,kBAA2B;;;ACA3B,IAAAC,yBAA2B;AAIpB,IAAM,yBACX,CAAC,eACD,CACE,UACA,aACA,SAAa,mCAAW,GACxB,YAAqB,UAClB;AACH,QAAM,IAAI,UAAM,mCAAW;AAE3B,QAAM,YAAuC;AAAA,IAC3C,MAAM;AAAA,IACN,IAAI;AAAA,EACN;AAEA,QAAM,YAAuC;AAAA,IAC3C,MAAM;AAAA,IACN,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,kBAAkB,cACd;AAAA,MACE,KAAK,EAAE,MAAM,YAAY;AAAA,IAC3B,IACA;AAAA,EACN;AAEA,QAAM,UAAqC;AAAA,IACzC,MAAM;AAAA,IACN,IAAI;AAAA,EACN;AAEA,MAAI,WAAW;AACb,eAAW,QAAQ,SAAS;AAC5B;AAAA,EACF;AAEA,aAAW,QAAQ,SAAS;AAC5B,aAAW,QAAQ,SAAS;AAC5B,aAAW,QAAQ,OAAO;AAC5B;;;ADzCF,IAAAC,wBAA2C;AAEpC,IAAM,kCAAkC,CAAC,qBAA8B;AAC5E,MAAI;AACJ,MAAI;AACJ,MAAI;AACJ,MAAI,eAAe;AAEnB,MAAI,kBAAkB;AAEtB,QAAM,aAAa,CAAC,UAA8C;AAChE,QAAI,CAAC,oBAAoB,iBAAiB;AACxC,aAAO;AAAA,IACT;AAEA,QAAI,MAAM,SAAS,gBAAgB,EAAE,WAAW,QAAQ;AACtD,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAEA,QAAM,cAAc;AAAA,IAClB,OAAO,CAAC,eAAsD;AAC5D,UAAI;AAEF,mBAAW,UAAU;AAAA,MACvB,SAAS,GAAG;AACV,mBAAW,MAAM,eAAe,CAAC;AAAA,MACnC;AAAA,IACF;AAAA,IACA,WAAW,CACT,OACA,eACG;AACH,UAAI,CAAC,UAAU,CAAC,iBAAiB;AAC/B;AAAA,MACF;AAEA,UAAI;AACF,YAAI,WAAW,KAAK,GAAG;AACrB,cAAI,QAAQ,SAAS,WAAW,OAAO;AACrC,iBAAK,MAAM;AACX,gBAAI,QAAQ,MAAM;AAClB,gBAAI,cAAc;AAChB,sBAAQ,MAAM,QAAQ,WAAW,EAAE;AACnC,6BAAe;AAAA,YACjB;AACA,mBAAO,MAAM,KAAK;AAAA,UACpB,OAAO;AACL,oBAAQ,KAAK,6CAA6C,KAAK;AAC/D,uBAAW,QAAQ,KAAK;AAAA,UAC1B;AAAA,QACF,OAAO;AACL,qBAAW,QAAQ,KAAK;AAAA,QAC1B;AAAA,MACF,SAAS,GAAG;AACV,gBAAQ,IAAI,0BAA0B,CAAC;AACvC,mBAAW,MAAM,CAAC;AAAA,MACpB;AAAA,IACF;AAAA,IACA,OAAO,CAAC,eAAsD;AAC5D,eAAS,IAAI,uBAAW;AAAA,QACtB,OAAO,CAAC,KAAK;AAAA,MACf,CAAC;AAED,yBAAmB,mBACf,uBAAuB,UAAU,IACjC,CAAC,YAAoB;AAAA,MAAC;AAE1B,aAAO,UAAU,CAAC,eAAoB;AACpC,cAAM,QAAQ,WAAW;AAEzB,YAAI,MAAM,QAAQ;AAChB,gBAAM,OAAO,aAAa,WAAW,KAAK,IAAI,CAAC;AAAA,QACjD;AAEA;AAAA,UACE,KAAK,UAAU,KAAK;AAAA,UACpB,KAAK,UAAU;AAAA,YACb,MAAM;AAAA,YACN,WAAO,kDAA2B,KAAK;AAAA,UACzC,CAAC;AAAA,UACD;AAAA,QACF;AAAA,MACF;AAEA,aAAO,UAAU,CAAC,QAAa;AAC7B,gBAAQ,MAAM,yCAAyC,GAAG;AAG1D,0BAAkB;AAAA,MACpB;AAEA,aAAO,QAAQ,MAAM;AACnB;AAAA,UACE;AAAA,UACA,KAAK,UAAU;AAAA,YACb,eAAe;AAAA,UACjB,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,IAAI,gBAAgD,WAAW;AACxE;;;AExGA,IAAqB,4BAArB,cAAuD,gBAGrD;AAAA,EACA,YAAY,QAAiB;AAC3B,QAAI;AACJ,UAAM;AAAA,MACJ,MAAM,YAAY;AAChB,mBAAW,uBAAuB,UAAU;AAAA,MAC9C;AAAA,MACA,UAAU,OAAO,YAAY;AAC3B,YACE,UACA,MAAM,SAAS,SACf,MAAM,SAAS,SAAS,eACxB,UACA;AACA;AAAA,YACE,MAAM,SAAS;AAAA,YACf,KAAK,UAAU;AAAA,cACb,MAAM;AAAA,YACR,CAAC;AAAA,UACH;AAAA,QACF,OAAO;AACL,qBAAW,QAAQ,KAAK;AAAA,QAC1B;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AACF;","names":["import_provider_utils","import_parse_sse","import_web","import_api","import_api","import_provider_utils","import_ai_feat_utils"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/coze-provider.ts","../src/const.ts","../src/coze-language-model.ts","../src/utils/prompt-to-model-msg.ts","../src/utils/accumulate-sse-response.ts","../src/utils/mcp-to-llm-chunk.ts","../src/utils/create-error-stream.ts","../src/evt-sample.ts","../src/stream-trasnformer/llm-chunk-injector-transform-stream.ts","../src/stream-trasnformer/mcp-chunk-filter-transform-stream.ts","../src/stream-trasnformer/llm-part-transform-stream.ts","../src/utils/build-generate-result-by-chat-res.ts","../src/stream-trasnformer/fields-json-transform-stream.ts","../src/utils/enqueue-text-info.ts","../src/stream-trasnformer/suggestion-transform-stream.ts"],"sourcesContent":["export { createCoze } from \"./coze-provider\";\nexport { createFieldsJsonTransformStream } from \"./stream-trasnformer/fields-json-transform-stream\";\nexport { default as SuggestionTransformStream } from \"./stream-trasnformer/suggestion-transform-stream\";\nexport { createTextInfoEnqueuer } from \"./utils/enqueue-text-info\";\n","import {\n LanguageModelV2,\n LanguageModelV2StreamPart,\n NoSuchModelError,\n ProviderV2,\n} from '@ai-sdk/provider';\n\nimport {\n FetchFunction,\n loadApiKey,\n withoutTrailingSlash,\n withUserAgentSuffix,\n} from '@ai-sdk/provider-utils';\nimport { CozeChatModelId } from './types';\nimport { VERSION } from './const';\nimport { CozeLanguageModel } from './coze-language-model';\n\nexport interface CozeProviderSettings {\n apiKey?: string;\n /**\nBase URL for the API calls.\n*/\n baseURL?: string;\n\n botId: string;\n\n /**\nCustom headers to include in the requests.\n*/\n headers?: Record<string, string>;\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n*/\n fetch?: FetchFunction;\n\n extraStreamTransformers?: (() => TransformStream<LanguageModelV2StreamPart, any>)[];\n}\n\nexport interface CozeProvider extends ProviderV2 {\n (modelId: CozeChatModelId): LanguageModelV2;\n\n languageModel(modelId: CozeChatModelId): LanguageModelV2;\n\n /**\nCreates a DeepSeek chat model for text generation.\n*/\n chat(modelId: CozeChatModelId): LanguageModelV2;\n}\n\nexport function createCoze(\n options: CozeProviderSettings = {\n botId: '',\n }\n): CozeProvider {\n const baseURL = withoutTrailingSlash(options.baseURL);\n\n const agentPartHeader = withUserAgentSuffix(options.headers || {}, `ai-sdk/coze/${VERSION}`);\n const authorizationHeader = `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'COZE_API_KEY',\n description: '',\n })}`;\n\n const getHeaders = () => ({\n ...agentPartHeader,\n Authorization: authorizationHeader,\n 'content-type': 'application/json',\n });\n\n const createLanguageModel = (modelId: CozeChatModelId) => {\n return new CozeLanguageModel(modelId, {\n botId: options.botId,\n provider: `coze.chat`,\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n extraStreamTransformers: options.extraStreamTransformers || [],\n });\n };\n\n const provider = (modelId: CozeChatModelId) => createLanguageModel(modelId);\n\n provider.specificationVersion = 'v3' as const;\n provider.languageModel = createLanguageModel;\n provider.chat = createLanguageModel;\n\n provider.embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });\n };\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'imageModel' });\n };\n provider.textEmbeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });\n };\n\n return provider;\n}\n","export const VERSION = \"0.0.1\";\n","import {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2CallWarning,\n LanguageModelV2Prompt,\n LanguageModelV2StreamPart,\n SharedV2Headers,\n} from '@ai-sdk/provider';\nimport { CozeChatConfig, IGenerateResult } from './types';\nimport { ServerSentEventTransformStream } from 'parse-sse';\nimport { TextDecoderStream } from 'stream/web';\nimport { convertPromptToMessages } from './utils/prompt-to-model-msg';\nimport { accumulateSSEResponse } from './utils/accumulate-sse-response';\nimport { createErrorStream } from './utils/create-error-stream';\nimport { LLMChunkInjectorTransformStream } from './stream-trasnformer/llm-chunk-injector-transform-stream';\nimport MCPChunkFilterTransformStream from './stream-trasnformer/mcp-chunk-filter-transform-stream';\nimport LLMPartTrasnformStream from './stream-trasnformer/llm-part-transform-stream';\nimport { BuildWarningGenerateResult } from './utils/build-generate-result-by-chat-res';\nimport { getChatCtxForHuman, getChatCtxForMcp, safeParseJson } from '@baishuyun/ai-feat-utils';\nimport { IChatCtx } from '@baishuyun/types';\n\nexport class CozeLanguageModel implements LanguageModelV2 {\n specificationVersion: 'v2' = 'v2';\n provider: string;\n modelId: string;\n supportedUrls: Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>>;\n\n private readonly config: CozeChatConfig;\n\n constructor(modelId: string, config: CozeChatConfig) {\n this.modelId = modelId;\n this.provider = config.provider || 'coze';\n this.supportedUrls = config.supportedUrls?.() || {};\n this.config = config;\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<IGenerateResult> {\n const messages = convertPromptToMessages(options.prompt);\n const warnings: LanguageModelV2CallWarning[] = [];\n\n const url = this.config.url({ path: '/chat' });\n\n const user_id = options.headers ? options.headers['x-user-id'] : '';\n const user_var = options.headers ? options.headers['x-user-var'] : '';\n\n let customVar;\n if (user_var) {\n try {\n customVar = JSON.parse(user_var);\n } catch (e) {\n console.warn('x-user-var parse error', e);\n }\n }\n\n const body = {\n bot_id: this.config.botId,\n auto_save_history: false,\n user_id: user_id || '7543191937730215936',\n stream: true,\n additional_messages: messages,\n };\n\n if (customVar) {\n (body as any).custom_variables = customVar;\n }\n\n const headers = this.config.headers();\n const abortSignal = options.abortSignal;\n\n const response = await fetch(url, {\n method: 'POST',\n headers: headers,\n credentials: 'include',\n body: JSON.stringify(body),\n signal: abortSignal,\n });\n\n if (!response.ok || !response.body) {\n const rawError = await response.text();\n let errorDetail;\n try {\n errorDetail = JSON.parse(rawError);\n } catch {\n errorDetail = rawError;\n }\n\n const errorMessage =\n typeof errorDetail === 'object' && errorDetail?.msg\n ? errorDetail.msg\n : `Coze API error: ${response.status} ${response.statusText}`;\n\n return BuildWarningGenerateResult(errorMessage);\n }\n\n const { content, finishReason, usage } = await accumulateSSEResponse(response.body);\n\n return {\n content,\n finishReason,\n usage,\n request: { body },\n response: { body: null },\n warnings,\n };\n }\n\n isVisibleMsgPart(evtData: any) {\n if (evtData.type === 'knowledge' && evtData.role === 'assistant') {\n return false;\n }\n\n return true;\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: SharedV2Headers };\n }> {\n const conversation_id = options.headers ? options.headers['x-conversation-id'] : '';\n\n // 有 conversation_id 时,服务端会话中已持有完整历史(含中断记录)。\n const prompt = conversation_id ? keepOnlyLastUserMessage(options.prompt) : options.prompt;\n\n const messages = convertPromptToMessages(prompt);\n const queryStr = conversation_id ? `?conversation_id=${conversation_id}` : '';\n\n const url = this.config.url({\n path: `/chat${queryStr}`,\n });\n\n // 团队级别\n const user_id = options.headers ? options.headers['x-user-id'] : '';\n\n // 个人用户\n const operator_id = (options.headers ? options.headers['x-operator-id'] : '') ?? '';\n\n const user_var = options.headers ? options.headers['x-user-var'] : '';\n const user_param = (options.headers ? options.headers['x-user-param'] : '') ?? '';\n\n const params = user_param ? safeParseJson(user_param) : {};\n\n console.log('params 2 workflow', params);\n console.log('conversation id 2 workflow', conversation_id);\n const chatCtx = options?.providerOptions?.chatCtx as unknown as IChatCtx;\n\n console.log('chatCtx', chatCtx);\n\n const userId = operator_id || chatCtx?.user?._id || user_id || Date.now().toString();\n\n const body = {\n bot_id: this.config.botId,\n auto_save_history: Boolean(conversation_id),\n user_id: userId,\n stream: true,\n additional_messages: messages,\n parameters: params,\n custom_variables: user_var ? safeParseJson(user_var) : {},\n extra_params: {\n remark: getChatCtxForHuman(chatCtx),\n mcp_ctx: getChatCtxForMcp(chatCtx),\n },\n };\n\n const headers = this.config.headers();\n\n const abortSignal = options.abortSignal;\n\n console.log('url', url);\n console.log('body', JSON.stringify(body, null, 2));\n console.log('operator_id', operator_id);\n\n const response = await fetch(url, {\n method: 'POST',\n headers: headers,\n credentials: 'include',\n body: JSON.stringify(body),\n signal: abortSignal,\n });\n\n console.log('chat res status', response.status);\n\n if (!response.ok || !response.body) {\n // if (true) {\n const rawError = await response.text();\n let errorDetail;\n try {\n errorDetail = JSON.parse(rawError); // 尝试解析为 JSON\n } catch {\n errorDetail = rawError; // 非 JSON 直接使用\n }\n\n // 创建一个包含错误信息的流,让 UI 层处理\n const errorMessage =\n typeof errorDetail === 'object' && errorDetail?.msg\n ? errorDetail.msg\n : `Coze API error: ${response.status} ${response.statusText}`;\n\n console.error(errorMessage);\n\n return {\n stream: createErrorStream('会话异常,请重试'),\n };\n }\n\n let externalTransformers = (this.config.extraStreamTransformers || []).map((factory) =>\n factory()\n );\n\n /// 不同阶段,可能需要不同的流处理逻辑\n const stage = options.headers ? options.headers['x-user-stage'] : '';\n const isBuildStage = stage === 'build';\n const isFillStage = stage === 'fill';\n\n const result = response.body\n // 将字节流解码为文本流\n .pipeThrough(\n new TextDecoderStream() as ReadableWritablePair<\n string | undefined,\n Uint8Array<ArrayBufferLike>\n >\n )\n // 解析为 SSE 事件流\n .pipeThrough(new ServerSentEventTransformStream())\n .pipeThrough(new MCPChunkFilterTransformStream(isBuildStage || isFillStage))\n // 补充特殊 llm chunk\n .pipeThrough(new LLMChunkInjectorTransformStream())\n // 转换为 LanguageModelV2StreamPart 格式\n .pipeThrough(new LLMPartTrasnformStream());\n\n let finalResult = result;\n\n if (externalTransformers.length > 0) {\n finalResult = externalTransformers.reduce(\n (stream, transformer) => stream.pipeThrough(transformer),\n result // 初始累积值(原始流)\n );\n }\n\n return {\n stream: finalResult as ReadableStream<LanguageModelV2StreamPart>,\n };\n }\n}\n\n/**\n * 只保留最后一条 user 消息(含其内容),用于有 conversation_id 的场景:\n * 服务端会话中已持有完整历史,只需发送当前用户输入。\n */\nfunction keepOnlyLastUserMessage(prompt: LanguageModelV2Prompt): LanguageModelV2Prompt {\n for (let i = prompt.length - 1; i >= 0; i--) {\n if (prompt[i].role === 'user') {\n return [prompt[i]];\n }\n }\n return prompt;\n}\n","import {\n LanguageModelV2FilePart,\n LanguageModelV2Message,\n LanguageModelV2Prompt,\n LanguageModelV2TextPart,\n} from '@ai-sdk/provider';\nimport { RoleType } from '@coze/api';\nimport { Attachment } from '@baishuyun/types/src/chat';\nimport { excel2json } from './excel2json';\n\nconst decoder = new TextDecoder('utf-8');\n\nconst data2csvText = (data: Uint8Array) => {\n return decoder.decode(data);\n};\n\ntype userMsg = {\n role: 'user';\n content: Array<LanguageModelV2TextPart | LanguageModelV2FilePart>;\n};\n\nconst getPartType = (part: LanguageModelV2TextPart | LanguageModelV2FilePart) => {\n if (part.type === 'text') {\n return 'text';\n }\n\n const isImg = part.mediaType?.startsWith('image/');\n if (isImg) {\n return 'image';\n }\n\n const isAudio = part.mediaType?.startsWith('audio/');\n if (isAudio) {\n return 'audio';\n }\n\n return 'file';\n};\n\nconst parseMessageContent = (message: LanguageModelV2Message, isTextOnly?: boolean) => {\n if (isTextOnly) {\n return (message.content as Array<LanguageModelV2TextPart>)\n .map((part: LanguageModelV2TextPart) => part.text)\n .join('\\n');\n }\n\n const result = (message.content as Array<LanguageModelV2TextPart | LanguageModelV2FilePart>).map(\n (part) => {\n const meta = part.providerOptions?.uploadMetadata as Attachment;\n const url = meta?.url;\n\n return {\n type: getPartType(part),\n text: part.type === 'text' ? (part as LanguageModelV2TextPart).text : '',\n file_id: meta?.file_id,\n name: meta?.name,\n // 附件地址:模型需要在「附件上传」标准动作中引用(IAttachment.attachmentUrl)\n url,\n };\n }\n );\n\n return JSON.stringify(result);\n};\n\nconst isTextOnlyMsg = (message: userMsg) => message.content.every((part) => part.type === 'text');\n\nexport const convertPromptToMessages = (messages: LanguageModelV2Prompt) => {\n return messages.map((message) => {\n const isTextOnly = isTextOnlyMsg(message as userMsg);\n switch (message.role) {\n case 'user':\n return {\n role: RoleType.User,\n content: parseMessageContent(message, isTextOnly),\n content_type: isTextOnly ? 'text' : 'object_string',\n };\n break;\n\n case 'assistant':\n return {\n role: RoleType.Assistant,\n content: (message.content as Array<LanguageModelV2TextPart>)\n .map((part: LanguageModelV2TextPart) => (part.type === 'text' ? part.text : ''))\n .join(''),\n content_type: 'text',\n };\n break;\n }\n });\n};\n","import {\n LanguageModelV2Content,\n LanguageModelV2FinishReason,\n LanguageModelV2Usage,\n} from '@ai-sdk/provider';\nimport { ServerSentEventTransformStream } from 'parse-sse';\nimport { TextDecoderStream } from 'stream/web';\nimport { mapCozeUsage } from './mcp-to-llm-chunk';\n\nexport interface AccumulatedSSEResponse {\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n}\n\n/**\n * 从字节流中解码 SSE 事件并累积完整响应内容\n */\nexport async function accumulateSSEResponse(\n body: ReadableStream<Uint8Array>\n): Promise<AccumulatedSSEResponse> {\n const sseStream = body\n .pipeThrough(\n new TextDecoderStream() as ReadableWritablePair<\n string | undefined,\n Uint8Array<ArrayBufferLike>\n >\n )\n .pipeThrough(new ServerSentEventTransformStream());\n\n let textContent = '';\n let reasoningContent = '';\n let finishReason: LanguageModelV2FinishReason = 'stop';\n let usage: LanguageModelV2Usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n\n const reader = sseStream.getReader();\n try {\n while (true) {\n const { done, value: evt } = await reader.read();\n if (done) break;\n if (!evt) continue;\n\n let evtData;\n try {\n evtData = JSON.parse(evt.data);\n } catch {\n continue;\n }\n\n const event = evt.type;\n\n if (event === 'conversation.message.delta') {\n if (evtData.reasoning_content) {\n reasoningContent += evtData.reasoning_content;\n } else if (evtData.content) {\n textContent += evtData.content;\n }\n } else if (event === 'conversation.chat.completed' || event === 'done') {\n finishReason = 'stop';\n if (evtData.usage) {\n usage = mapCozeUsage(evtData.usage);\n }\n } else if (event === 'error') {\n finishReason = 'error';\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n const content: LanguageModelV2Content[] = [];\n if (reasoningContent) {\n content.push({ type: 'reasoning', text: reasoningContent });\n }\n if (textContent) {\n content.push({ type: 'text', text: textContent });\n }\n\n return { content, finishReason, usage };\n}\n","import { LanguageModelV2StreamPart, SharedV2ProviderMetadata } from '@ai-sdk/provider';\nimport { ChatEventType } from '@coze/api';\n\n/**\n * 上游 usage 字段兼容:官方 Coze v3 的 completed 事件为\n * token_count/input_count/output_count(无 total_count),\n * 总额按 total_count → token_count → input+output 的顺序取\n */\nexport const mapCozeUsage = (usage: any) => {\n const inputTokens = usage?.input_count || 0;\n const outputTokens = usage?.output_count || 0;\n const totalTokens = usage?.total_count ?? usage?.token_count ?? inputTokens + outputTokens;\n return { inputTokens, outputTokens, totalTokens };\n};\n\n/**\n * 从消息 meta_data 提取 token 用量。上游会把本轮模型用量写入 answer 消息\n * (含 workflow 用量消息)的 meta_data:token / input_tokens / output_tokens,\n * 是 chat.completed 事件不带 usage 时(旧版上游)的兜底来源\n */\nexport const extractUsageFromMsgMeta = (meta: any) => {\n if (!meta) return null;\n const totalTokens = Number(meta.token);\n if (!totalTokens) return null;\n return {\n inputTokens: Number(meta.input_tokens) || 0,\n outputTokens: Number(meta.output_tokens) || 0,\n totalTokens,\n };\n};\n\nexport const mcp2llmChunk = (part: any): LanguageModelV2StreamPart | null => {\n const fullData = JSON.stringify(part);\n\n switch (part.event) {\n case ChatEventType.CONVERSATION_CHAT_CREATED:\n return {\n type: 'raw',\n rawValue: part.data,\n };\n break;\n\n case ChatEventType.CONVERSATION_CHAT_IN_PROGRESS:\n return {\n // type: \"text-delta\",\n // id: part.data.conversation_id,\n // delta: part.data.content || \"\",\n // providerMetadata: {\n // raw: { data: fullData },\n // },\n type: 'raw',\n rawValue: part.data,\n };\n break;\n\n case ChatEventType.CONVERSATION_MESSAGE_DELTA:\n const isReasoning = Boolean(part.data.reasoning_content);\n return {\n type: isReasoning ? 'reasoning-delta' : 'text-delta',\n delta: isReasoning ? part.data.reasoning_content : part.data.content,\n id: part.data.conversation_id,\n providerMetadata: {},\n };\n break;\n\n case ChatEventType.CONVERSATION_MESSAGE_COMPLETED:\n if (part.data && part.data.type === 'follow_up') {\n return {\n type: 'raw',\n rawValue: part.data,\n };\n }\n\n if (part.status === 'completed') {\n return {\n type: 'text-end',\n id: part.data.conversation_id,\n // delta: part.data.content || part.data.reasoning_content || \"\",\n providerMetadata: {},\n };\n }\n\n return {\n type: 'raw',\n rawValue: part.data,\n };\n\n break;\n\n case ChatEventType.CONVERSATION_CHAT_COMPLETED:\n // Yield finish event with usage information\n return {\n type: 'finish',\n finishReason: 'stop',\n usage: mapCozeUsage(part.data.usage),\n };\n break;\n\n case ChatEventType.DONE:\n // Stream completed successfully\n return {\n type: 'finish',\n finishReason: 'stop',\n usage: mapCozeUsage(part.data.usage),\n };\n break;\n\n case ChatEventType.ERROR:\n // Handle errors\n console.error('[ERROR]', part.data);\n return {\n type: 'error',\n error: part.data,\n };\n\n default:\n // Handle unknown event types\n console.warn('Unknown event type:', part.event);\n return {\n type: 'error',\n error: 'Unknown event type' + part.event,\n };\n }\n\n return {\n type: 'error',\n error: 'unknown',\n };\n};\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { generateId } from '@ai-sdk/provider-utils';\n\n/**\n * 创建一个包含错误信息的流\n * @param error 错误信息\n * @returns ReadableStream<LanguageModelV2StreamPart>\n */\nexport const createErrorStream = (error: string): ReadableStream<LanguageModelV2StreamPart> => {\n return new ReadableStream<LanguageModelV2StreamPart>({\n start(controller) {\n const id = generateId();\n controller.enqueue({\n id,\n type: 'text-start',\n });\n controller.enqueue({\n id,\n type: 'text-delta',\n providerMetadata: {\n raw: { data: { type: 'agent-error', error } },\n },\n delta: error,\n });\n controller.enqueue({\n type: 'text-end',\n id,\n });\n controller.close();\n },\n });\n};\n","/**\n * 事件数据取样,某些流 chunk 处理,需要用到前后的 chunk 信息,因此设计一个类缓存相邻 chunk,用于处理依据\n */\nexport class EvtSample {\n private _evtSampleMap: Map<string, any> = new Map();\n private _key1: string = \"1\";\n private _key2: string = \"2\";\n private _maxSample = 2;\n\n public addEventSample(evt: any) {\n if (this._evtSampleMap.size >= this._maxSample) {\n const evt2 = this._evtSampleMap.get(this._key2);\n this._evtSampleMap.set(this._key1, evt2);\n this._evtSampleMap.set(this._key2, evt);\n return;\n }\n\n this._evtSampleMap.set((this._evtSampleMap.size + 1).toString(), evt);\n }\n\n public getFirstSample() {\n return this._evtSampleMap.get(this._key1);\n }\n\n public getSecondSample() {\n return this._evtSampleMap.get(this._key2);\n }\n}\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { StreamChatData } from '@coze/api';\nimport { EvtSample } from '../evt-sample';\n\n/**\n * 补充特殊的 llm chunk, reasoning-end, text-start\n */\nexport class LLMChunkInjectorTransformStream extends TransformStream<\n StreamChatData,\n | StreamChatData\n | (LanguageModelV2StreamPart & {\n disableTransform: boolean;\n })\n> {\n private eventSampleMap = new EvtSample();\n\n constructor() {\n super({\n transform: (\n part: StreamChatData,\n controller: TransformStreamDefaultController<\n StreamChatData | (LanguageModelV2StreamPart & { disableTransform: boolean })\n >\n ) => {\n // 添加事件样本(原逻辑中的addEventSample)\n this.eventSampleMap.addEventSample(part);\n\n // 处理sample1/sample2特殊判断逻辑\n const sample1 = this.eventSampleMap.getFirstSample();\n const sample2 = this.eventSampleMap.getSecondSample();\n\n // handle reasoning end\n if (\n sample1 &&\n sample2 &&\n sample1.data.reasoning_content &&\n !sample2.data.reasoning_content\n ) {\n controller.enqueue({\n disableTransform: true,\n type: 'reasoning-end',\n id: sample1.data.conversation_id,\n });\n }\n\n // handle text-start\n if (sample1 && sample2 && !sample1.data.content && sample2.data.content) {\n controller.enqueue({\n disableTransform: true,\n type: 'text-start',\n id: sample2.data.conversation_id,\n });\n }\n\n // 传递part到下一个转换流\n controller.enqueue(part);\n },\n });\n }\n}\n","import { ChatEventType, StreamChatData } from '@coze/api';\nimport { ServerSentEvent } from 'parse-sse';\n\nexport default class MCPChunkFilterTransformStream extends TransformStream {\n isVisibleMsgPart(evtData: any, part: any, omitTextEndChunk?: boolean) {\n if (evtData.type === 'knowledge' && evtData.role === 'assistant') {\n return false;\n }\n\n // Omit text-end chunk if the flag is set\n if (\n omitTextEndChunk &&\n part.event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED &&\n part.data.type !== 'follow_up'\n ) {\n return false;\n }\n\n if (part.event === 'conversation.message.completed' && evtData.type == 'verbose') {\n return false;\n }\n\n return true;\n }\n\n constructor(omitTextEndChunk: boolean = false) {\n super({\n transform: (\n evt: ServerSentEvent,\n controller: TransformStreamDefaultController<StreamChatData>\n ) => {\n if (!evt) return;\n\n // 解析evt为part对象(原逻辑中的part构建)\n const part = {\n event: evt.type,\n data: JSON.parse(evt.data) || {},\n } as StreamChatData;\n\n // 过滤逻辑:仅传递满足条件的part\n if (this.isVisibleMsgPart(part.data, part, omitTextEndChunk)) {\n controller.enqueue(part);\n }\n },\n });\n }\n}\n","import { ChatEventType, StreamChatData } from '@coze/api';\nimport { extractUsageFromMsgMeta, mcp2llmChunk } from '../utils/mcp-to-llm-chunk';\nimport { LanguageModelV2StreamPart, LanguageModelV2Usage } from '@ai-sdk/provider';\n\nexport default class LLMPartTrasnformStream extends TransformStream {\n /**\n * 本轮最近一条消息 meta_data 中携带的 token 用量。\n * 旧版上游不在 conversation.chat.completed 事件中携带 usage,\n * 发 finish chunk 时若事件 usage 缺失则用此兜底(事件已带则不覆盖)\n */\n private lastMsgUsage: LanguageModelV2Usage | null = null;\n\n constructor() {\n super({\n transform: (\n part: StreamChatData | (LanguageModelV2StreamPart & { disableTransform: boolean }),\n controller: TransformStreamDefaultController<LanguageModelV2StreamPart | undefined>\n ) => {\n // Bypass transform if disableTransform flag is set\n const { disableTransform } = part as any;\n if (disableTransform) {\n controller.enqueue(part as any);\n return;\n }\n\n try {\n if ((part as any).event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {\n const usage = extractUsageFromMsgMeta((part as any).data?.meta_data);\n if (usage) {\n this.lastMsgUsage = usage;\n }\n }\n\n const chunk = mcp2llmChunk(part as any);\n if (chunk) {\n if (chunk.type === 'finish' && !chunk.usage?.totalTokens && this.lastMsgUsage) {\n chunk.usage = this.lastMsgUsage;\n }\n controller.enqueue(chunk as any);\n }\n } catch (error) {\n console.error('transform coze evt error');\n }\n },\n });\n }\n}\n","import { CreateChatRes } from '@coze/api';\nimport { CozeChatConfig, IGenerateResult } from '../types';\nimport { getCozeChatMsgDetail } from './get-coze-chat-msg-detail';\n\nexport const BuildWarningGenerateResult = (message: string): IGenerateResult => {\n return {\n content: [],\n finishReason: 'error',\n request: {\n body: null,\n },\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n },\n response: {\n body: null,\n },\n warnings: [\n {\n type: 'other',\n message,\n },\n ],\n };\n};\n\nexport const BuildGenerateResultByChatRes = async (\n response: Response,\n chatConfig: CozeChatConfig,\n reqBody?: unknown\n): Promise<IGenerateResult> => {\n if (!response.ok) {\n return Promise.reject(\n BuildWarningGenerateResult(`Coze API error: ${response.status} ${response.statusText}`)\n );\n }\n\n const res = (await response.json()) as CreateChatRes;\n if (res.code !== 0) {\n return Promise.reject(BuildWarningGenerateResult(`Coze API error: ${res.code} ${res.msg}`));\n }\n\n const msgRes = await getCozeChatMsgDetail(res.data.conversation_id, res.data.id, chatConfig);\n if (!msgRes.ok) {\n return Promise.reject(\n BuildWarningGenerateResult(\n `Failed to get message detail: ${msgRes.status} ${msgRes.statusText}`\n )\n );\n }\n const msgDetail = await msgRes.json();\n\n return {\n content: msgDetail.data.message.content,\n finishReason: msgDetail.data.message.status === 'finished' ? 'stop' : 'error',\n request: {\n body: reqBody,\n },\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n },\n response: {\n body: msgDetail,\n },\n warnings: [],\n };\n};\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { JSONParser } from '@streamparser/json';\nimport { createTextInfoEnqueuer, TextInfoEnqueuer } from '../utils/enqueue-text-info';\nimport { rebuildFieldsJsonStructure } from '@baishuyun/ai-feat-utils';\n\nexport const createFieldsJsonTransformStream = (enableJsonParser: boolean) => {\n let parser: JSONParser;\n let enqueueTextDelta: TextInfoEnqueuer;\n let id: string;\n let isFirstChunk = true;\n // 当 LLM 返回的不是 JSON 而是普通文本时,切换到直通模式\n let passthroughMode = false;\n\n const chunkGuard = (chunk: LanguageModelV2StreamPart): boolean => {\n if (!enableJsonParser || passthroughMode) {\n return false;\n }\n\n if (chunk.type !== 'text-delta' || !('delta' in chunk)) {\n return false;\n }\n\n return true;\n };\n\n const transformer = {\n flush: (controller: TransformStreamDefaultController<any>) => {\n try {\n // parser?.end();\n controller.terminate(); // 信号通知下游可读流已关闭\n } catch (e) {\n controller.error('stop error' + e);\n }\n },\n transform: (\n chunk: LanguageModelV2StreamPart,\n controller: TransformStreamDefaultController<LanguageModelV2StreamPart>\n ) => {\n if (!parser && !passthroughMode) {\n return;\n }\n\n try {\n if (chunkGuard(chunk)) {\n if ('id' in chunk && 'delta' in chunk) {\n id = chunk.id;\n let delta = chunk.delta;\n if (isFirstChunk) {\n delta = delta.replace(/^\\uFEFF/, '');\n isFirstChunk = false;\n }\n parser.write(delta);\n } else {\n console.warn('Unexpected chunk format for JSON parsing:', chunk);\n controller.enqueue(chunk);\n }\n } else {\n controller.enqueue(chunk);\n }\n } catch (e) {\n console.log('write or enqueue error', e);\n controller.error(e);\n }\n },\n start: (controller: TransformStreamDefaultController<any>) => {\n parser = new JSONParser({\n paths: ['$.*'],\n });\n\n enqueueTextDelta = enableJsonParser\n ? createTextInfoEnqueuer(controller)\n : (content: string) => {};\n\n parser.onValue = (parsedInfo: any) => {\n const value = parsedInfo.value;\n\n if (value.widget) {\n value.widget.widgetName = `_widget_${Date.now()}`;\n }\n\n enqueueTextDelta(\n JSON.stringify(value),\n JSON.stringify({\n type: 'mcp-fields-json',\n field: rebuildFieldsJsonStructure(value),\n }),\n id\n );\n };\n\n parser.onError = (err: any) => {\n console.error('JsonWidgetStream: JSON Parsing Error:', err);\n\n // LLM 返回的不是 JSON,切换到直通模式,后续 text-delta 直接透传\n passthroughMode = true;\n };\n\n parser.onEnd = () => {\n enqueueTextDelta(\n ' ',\n JSON.stringify({\n appendConfirm: 'save-fields',\n })\n );\n };\n },\n };\n\n return new TransformStream<LanguageModelV2StreamPart, any>(transformer);\n};\n","import { JSONValue, LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { generateId } from '@ai-sdk/provider-utils';\n\nexport type TextInfoEnqueuer = (textInfo: string, metaPayload?: JSONValue, id?: string) => void;\n\nexport const createTextInfoEnqueuer =\n (controller: TransformStreamDefaultController<LanguageModelV2StreamPart>) =>\n (\n textInfo: string,\n metaPayload?: JSONValue,\n id: string = generateId(),\n deltaOnly: boolean = false\n ) => {\n const i = id ?? generateId();\n\n const startPart: LanguageModelV2StreamPart = {\n type: 'text-start',\n id: i,\n };\n\n const deltaPart: LanguageModelV2StreamPart = {\n type: 'text-delta',\n id: i,\n delta: textInfo,\n providerMetadata: metaPayload\n ? {\n raw: { data: metaPayload },\n }\n : undefined,\n };\n\n const endPart: LanguageModelV2StreamPart = {\n type: 'text-end',\n id: i,\n };\n\n if (deltaOnly) {\n controller.enqueue(deltaPart);\n return;\n }\n\n controller.enqueue(startPart);\n controller.enqueue(deltaPart);\n controller.enqueue(endPart);\n };\n","import {\n createTextInfoEnqueuer,\n TextInfoEnqueuer,\n} from \"../utils/enqueue-text-info\";\n\nexport default class SuggestionTransformStream extends TransformStream<\n any,\n any\n> {\n constructor(enable: boolean) {\n let enqueuer: TextInfoEnqueuer;\n super({\n start(controller) {\n enqueuer = createTextInfoEnqueuer(controller);\n },\n transform(chunk, controller) {\n if (\n enable &&\n chunk.type === \"raw\" &&\n chunk.rawValue.type === \"follow_up\" &&\n enqueuer\n ) {\n enqueuer(\n chunk.rawValue.content,\n JSON.stringify({\n type: \"suggestion\",\n }),\n );\n } else {\n controller.enqueue(chunk);\n }\n },\n });\n }\n}\n"],"mappings":"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","names":["import_provider_utils","import_parse_sse","import_web","import_api","import_api","import_api","import_provider_utils","import_ai_feat_utils"]}
|
package/dist/index.mjs
CHANGED
|
@@ -78,6 +78,109 @@ var convertPromptToMessages = (messages) => {
|
|
|
78
78
|
// src/utils/accumulate-sse-response.ts
|
|
79
79
|
import { ServerSentEventTransformStream } from "parse-sse";
|
|
80
80
|
import { TextDecoderStream } from "stream/web";
|
|
81
|
+
|
|
82
|
+
// src/utils/mcp-to-llm-chunk.ts
|
|
83
|
+
import { ChatEventType } from "@coze/api";
|
|
84
|
+
var mapCozeUsage = (usage) => {
|
|
85
|
+
const inputTokens = usage?.input_count || 0;
|
|
86
|
+
const outputTokens = usage?.output_count || 0;
|
|
87
|
+
const totalTokens = usage?.total_count ?? usage?.token_count ?? inputTokens + outputTokens;
|
|
88
|
+
return { inputTokens, outputTokens, totalTokens };
|
|
89
|
+
};
|
|
90
|
+
var extractUsageFromMsgMeta = (meta) => {
|
|
91
|
+
if (!meta) return null;
|
|
92
|
+
const totalTokens = Number(meta.token);
|
|
93
|
+
if (!totalTokens) return null;
|
|
94
|
+
return {
|
|
95
|
+
inputTokens: Number(meta.input_tokens) || 0,
|
|
96
|
+
outputTokens: Number(meta.output_tokens) || 0,
|
|
97
|
+
totalTokens
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
var mcp2llmChunk = (part) => {
|
|
101
|
+
const fullData = JSON.stringify(part);
|
|
102
|
+
switch (part.event) {
|
|
103
|
+
case ChatEventType.CONVERSATION_CHAT_CREATED:
|
|
104
|
+
return {
|
|
105
|
+
type: "raw",
|
|
106
|
+
rawValue: part.data
|
|
107
|
+
};
|
|
108
|
+
break;
|
|
109
|
+
case ChatEventType.CONVERSATION_CHAT_IN_PROGRESS:
|
|
110
|
+
return {
|
|
111
|
+
// type: "text-delta",
|
|
112
|
+
// id: part.data.conversation_id,
|
|
113
|
+
// delta: part.data.content || "",
|
|
114
|
+
// providerMetadata: {
|
|
115
|
+
// raw: { data: fullData },
|
|
116
|
+
// },
|
|
117
|
+
type: "raw",
|
|
118
|
+
rawValue: part.data
|
|
119
|
+
};
|
|
120
|
+
break;
|
|
121
|
+
case ChatEventType.CONVERSATION_MESSAGE_DELTA:
|
|
122
|
+
const isReasoning = Boolean(part.data.reasoning_content);
|
|
123
|
+
return {
|
|
124
|
+
type: isReasoning ? "reasoning-delta" : "text-delta",
|
|
125
|
+
delta: isReasoning ? part.data.reasoning_content : part.data.content,
|
|
126
|
+
id: part.data.conversation_id,
|
|
127
|
+
providerMetadata: {}
|
|
128
|
+
};
|
|
129
|
+
break;
|
|
130
|
+
case ChatEventType.CONVERSATION_MESSAGE_COMPLETED:
|
|
131
|
+
if (part.data && part.data.type === "follow_up") {
|
|
132
|
+
return {
|
|
133
|
+
type: "raw",
|
|
134
|
+
rawValue: part.data
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
if (part.status === "completed") {
|
|
138
|
+
return {
|
|
139
|
+
type: "text-end",
|
|
140
|
+
id: part.data.conversation_id,
|
|
141
|
+
// delta: part.data.content || part.data.reasoning_content || "",
|
|
142
|
+
providerMetadata: {}
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
type: "raw",
|
|
147
|
+
rawValue: part.data
|
|
148
|
+
};
|
|
149
|
+
break;
|
|
150
|
+
case ChatEventType.CONVERSATION_CHAT_COMPLETED:
|
|
151
|
+
return {
|
|
152
|
+
type: "finish",
|
|
153
|
+
finishReason: "stop",
|
|
154
|
+
usage: mapCozeUsage(part.data.usage)
|
|
155
|
+
};
|
|
156
|
+
break;
|
|
157
|
+
case ChatEventType.DONE:
|
|
158
|
+
return {
|
|
159
|
+
type: "finish",
|
|
160
|
+
finishReason: "stop",
|
|
161
|
+
usage: mapCozeUsage(part.data.usage)
|
|
162
|
+
};
|
|
163
|
+
break;
|
|
164
|
+
case ChatEventType.ERROR:
|
|
165
|
+
console.error("[ERROR]", part.data);
|
|
166
|
+
return {
|
|
167
|
+
type: "error",
|
|
168
|
+
error: part.data
|
|
169
|
+
};
|
|
170
|
+
default:
|
|
171
|
+
console.warn("Unknown event type:", part.event);
|
|
172
|
+
return {
|
|
173
|
+
type: "error",
|
|
174
|
+
error: "Unknown event type" + part.event
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
return {
|
|
178
|
+
type: "error",
|
|
179
|
+
error: "unknown"
|
|
180
|
+
};
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// src/utils/accumulate-sse-response.ts
|
|
81
184
|
async function accumulateSSEResponse(body) {
|
|
82
185
|
const sseStream = body.pipeThrough(
|
|
83
186
|
new TextDecoderStream()
|
|
@@ -108,11 +211,7 @@ async function accumulateSSEResponse(body) {
|
|
|
108
211
|
} else if (event === "conversation.chat.completed" || event === "done") {
|
|
109
212
|
finishReason = "stop";
|
|
110
213
|
if (evtData.usage) {
|
|
111
|
-
usage =
|
|
112
|
-
inputTokens: evtData.usage.input_count || 0,
|
|
113
|
-
outputTokens: evtData.usage.output_count || 0,
|
|
114
|
-
totalTokens: evtData.usage.total_count || 0
|
|
115
|
-
};
|
|
214
|
+
usage = mapCozeUsage(evtData.usage);
|
|
116
215
|
}
|
|
117
216
|
} else if (event === "error") {
|
|
118
217
|
finishReason = "error";
|
|
@@ -211,13 +310,13 @@ var LLMChunkInjectorTransformStream = class extends TransformStream {
|
|
|
211
310
|
};
|
|
212
311
|
|
|
213
312
|
// src/stream-trasnformer/mcp-chunk-filter-transform-stream.ts
|
|
214
|
-
import { ChatEventType } from "@coze/api";
|
|
313
|
+
import { ChatEventType as ChatEventType2 } from "@coze/api";
|
|
215
314
|
var MCPChunkFilterTransformStream = class extends TransformStream {
|
|
216
315
|
isVisibleMsgPart(evtData, part, omitTextEndChunk) {
|
|
217
316
|
if (evtData.type === "knowledge" && evtData.role === "assistant") {
|
|
218
317
|
return false;
|
|
219
318
|
}
|
|
220
|
-
if (omitTextEndChunk && part.event ===
|
|
319
|
+
if (omitTextEndChunk && part.event === ChatEventType2.CONVERSATION_MESSAGE_COMPLETED && part.data.type !== "follow_up") {
|
|
221
320
|
return false;
|
|
222
321
|
}
|
|
223
322
|
if (part.event === "conversation.message.completed" && evtData.type == "verbose") {
|
|
@@ -241,101 +340,15 @@ var MCPChunkFilterTransformStream = class extends TransformStream {
|
|
|
241
340
|
}
|
|
242
341
|
};
|
|
243
342
|
|
|
244
|
-
// src/utils/mcp-to-llm-chunk.ts
|
|
245
|
-
import { ChatEventType as ChatEventType2 } from "@coze/api";
|
|
246
|
-
var mcp2llmChunk = (part) => {
|
|
247
|
-
const fullData = JSON.stringify(part);
|
|
248
|
-
switch (part.event) {
|
|
249
|
-
case ChatEventType2.CONVERSATION_CHAT_CREATED:
|
|
250
|
-
return {
|
|
251
|
-
type: "raw",
|
|
252
|
-
rawValue: part.data
|
|
253
|
-
};
|
|
254
|
-
break;
|
|
255
|
-
case ChatEventType2.CONVERSATION_CHAT_IN_PROGRESS:
|
|
256
|
-
return {
|
|
257
|
-
// type: "text-delta",
|
|
258
|
-
// id: part.data.conversation_id,
|
|
259
|
-
// delta: part.data.content || "",
|
|
260
|
-
// providerMetadata: {
|
|
261
|
-
// raw: { data: fullData },
|
|
262
|
-
// },
|
|
263
|
-
type: "raw",
|
|
264
|
-
rawValue: part.data
|
|
265
|
-
};
|
|
266
|
-
break;
|
|
267
|
-
case ChatEventType2.CONVERSATION_MESSAGE_DELTA:
|
|
268
|
-
const isReasoning = Boolean(part.data.reasoning_content);
|
|
269
|
-
return {
|
|
270
|
-
type: isReasoning ? "reasoning-delta" : "text-delta",
|
|
271
|
-
delta: isReasoning ? part.data.reasoning_content : part.data.content,
|
|
272
|
-
id: part.data.conversation_id,
|
|
273
|
-
providerMetadata: {}
|
|
274
|
-
};
|
|
275
|
-
break;
|
|
276
|
-
case ChatEventType2.CONVERSATION_MESSAGE_COMPLETED:
|
|
277
|
-
if (part.data && part.data.type === "follow_up") {
|
|
278
|
-
return {
|
|
279
|
-
type: "raw",
|
|
280
|
-
rawValue: part.data
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
if (part.status === "completed") {
|
|
284
|
-
return {
|
|
285
|
-
type: "text-end",
|
|
286
|
-
id: part.data.conversation_id,
|
|
287
|
-
// delta: part.data.content || part.data.reasoning_content || "",
|
|
288
|
-
providerMetadata: {}
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
return {
|
|
292
|
-
type: "raw",
|
|
293
|
-
rawValue: part.data
|
|
294
|
-
};
|
|
295
|
-
break;
|
|
296
|
-
case ChatEventType2.CONVERSATION_CHAT_COMPLETED:
|
|
297
|
-
return {
|
|
298
|
-
type: "finish",
|
|
299
|
-
finishReason: "stop",
|
|
300
|
-
usage: {
|
|
301
|
-
inputTokens: part.data.usage?.input_count || 0,
|
|
302
|
-
outputTokens: part.data.usage?.output_count || 0,
|
|
303
|
-
totalTokens: part.data.usage?.total_count || 0
|
|
304
|
-
}
|
|
305
|
-
};
|
|
306
|
-
break;
|
|
307
|
-
case ChatEventType2.DONE:
|
|
308
|
-
return {
|
|
309
|
-
type: "finish",
|
|
310
|
-
finishReason: "stop",
|
|
311
|
-
usage: {
|
|
312
|
-
inputTokens: part.data.usage?.input_count || 0,
|
|
313
|
-
outputTokens: part.data.usage?.output_count || 0,
|
|
314
|
-
totalTokens: part.data.usage?.total_count || 0
|
|
315
|
-
}
|
|
316
|
-
};
|
|
317
|
-
break;
|
|
318
|
-
case ChatEventType2.ERROR:
|
|
319
|
-
console.error("[ERROR]", part.data);
|
|
320
|
-
return {
|
|
321
|
-
type: "error",
|
|
322
|
-
error: part.data
|
|
323
|
-
};
|
|
324
|
-
default:
|
|
325
|
-
console.warn("Unknown event type:", part.event);
|
|
326
|
-
return {
|
|
327
|
-
type: "error",
|
|
328
|
-
error: "Unknown event type" + part.event
|
|
329
|
-
};
|
|
330
|
-
}
|
|
331
|
-
return {
|
|
332
|
-
type: "error",
|
|
333
|
-
error: "unknown"
|
|
334
|
-
};
|
|
335
|
-
};
|
|
336
|
-
|
|
337
343
|
// src/stream-trasnformer/llm-part-transform-stream.ts
|
|
344
|
+
import { ChatEventType as ChatEventType3 } from "@coze/api";
|
|
338
345
|
var LLMPartTrasnformStream = class extends TransformStream {
|
|
346
|
+
/**
|
|
347
|
+
* 本轮最近一条消息 meta_data 中携带的 token 用量。
|
|
348
|
+
* 旧版上游不在 conversation.chat.completed 事件中携带 usage,
|
|
349
|
+
* 发 finish chunk 时若事件 usage 缺失则用此兜底(事件已带则不覆盖)
|
|
350
|
+
*/
|
|
351
|
+
lastMsgUsage = null;
|
|
339
352
|
constructor() {
|
|
340
353
|
super({
|
|
341
354
|
transform: (part, controller) => {
|
|
@@ -345,8 +358,17 @@ var LLMPartTrasnformStream = class extends TransformStream {
|
|
|
345
358
|
return;
|
|
346
359
|
}
|
|
347
360
|
try {
|
|
361
|
+
if (part.event === ChatEventType3.CONVERSATION_MESSAGE_COMPLETED) {
|
|
362
|
+
const usage = extractUsageFromMsgMeta(part.data?.meta_data);
|
|
363
|
+
if (usage) {
|
|
364
|
+
this.lastMsgUsage = usage;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
348
367
|
const chunk = mcp2llmChunk(part);
|
|
349
368
|
if (chunk) {
|
|
369
|
+
if (chunk.type === "finish" && !chunk.usage?.totalTokens && this.lastMsgUsage) {
|
|
370
|
+
chunk.usage = this.lastMsgUsage;
|
|
371
|
+
}
|
|
350
372
|
controller.enqueue(chunk);
|
|
351
373
|
}
|
|
352
374
|
} catch (error) {
|
|
@@ -465,13 +487,15 @@ var CozeLanguageModel = class {
|
|
|
465
487
|
path: `/chat${queryStr}`
|
|
466
488
|
});
|
|
467
489
|
const user_id = options.headers ? options.headers["x-user-id"] : "";
|
|
490
|
+
const operator_id = (options.headers ? options.headers["x-operator-id"] : "") ?? "";
|
|
468
491
|
const user_var = options.headers ? options.headers["x-user-var"] : "";
|
|
469
492
|
const user_param = (options.headers ? options.headers["x-user-param"] : "") ?? "";
|
|
470
493
|
const params = user_param ? safeParseJson(user_param) : {};
|
|
471
494
|
console.log("params 2 workflow", params);
|
|
472
495
|
console.log("conversation id 2 workflow", conversation_id);
|
|
473
496
|
const chatCtx = options?.providerOptions?.chatCtx;
|
|
474
|
-
|
|
497
|
+
console.log("chatCtx", chatCtx);
|
|
498
|
+
const userId = operator_id || chatCtx?.user?._id || user_id || Date.now().toString();
|
|
475
499
|
const body = {
|
|
476
500
|
bot_id: this.config.botId,
|
|
477
501
|
auto_save_history: Boolean(conversation_id),
|
|
@@ -489,6 +513,7 @@ var CozeLanguageModel = class {
|
|
|
489
513
|
const abortSignal = options.abortSignal;
|
|
490
514
|
console.log("url", url);
|
|
491
515
|
console.log("body", JSON.stringify(body, null, 2));
|
|
516
|
+
console.log("operator_id", operator_id);
|
|
492
517
|
const response = await fetch(url, {
|
|
493
518
|
method: "POST",
|
|
494
519
|
headers,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/coze-provider.ts","../src/const.ts","../src/coze-language-model.ts","../src/utils/prompt-to-model-msg.ts","../src/utils/accumulate-sse-response.ts","../src/utils/create-error-stream.ts","../src/evt-sample.ts","../src/stream-trasnformer/llm-chunk-injector-transform-stream.ts","../src/stream-trasnformer/mcp-chunk-filter-transform-stream.ts","../src/utils/mcp-to-llm-chunk.ts","../src/stream-trasnformer/llm-part-transform-stream.ts","../src/utils/build-generate-result-by-chat-res.ts","../src/stream-trasnformer/fields-json-transform-stream.ts","../src/utils/enqueue-text-info.ts","../src/stream-trasnformer/suggestion-transform-stream.ts"],"sourcesContent":["import {\n LanguageModelV2,\n LanguageModelV2StreamPart,\n NoSuchModelError,\n ProviderV2,\n} from '@ai-sdk/provider';\n\nimport {\n FetchFunction,\n loadApiKey,\n withoutTrailingSlash,\n withUserAgentSuffix,\n} from '@ai-sdk/provider-utils';\nimport { CozeChatModelId } from './types';\nimport { VERSION } from './const';\nimport { CozeLanguageModel } from './coze-language-model';\n\nexport interface CozeProviderSettings {\n apiKey?: string;\n /**\nBase URL for the API calls.\n*/\n baseURL?: string;\n\n botId: string;\n\n /**\nCustom headers to include in the requests.\n*/\n headers?: Record<string, string>;\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n*/\n fetch?: FetchFunction;\n\n extraStreamTransformers?: (() => TransformStream<LanguageModelV2StreamPart, any>)[];\n}\n\nexport interface CozeProvider extends ProviderV2 {\n (modelId: CozeChatModelId): LanguageModelV2;\n\n languageModel(modelId: CozeChatModelId): LanguageModelV2;\n\n /**\nCreates a DeepSeek chat model for text generation.\n*/\n chat(modelId: CozeChatModelId): LanguageModelV2;\n}\n\nexport function createCoze(\n options: CozeProviderSettings = {\n botId: '',\n }\n): CozeProvider {\n const baseURL = withoutTrailingSlash(options.baseURL);\n\n const agentPartHeader = withUserAgentSuffix(options.headers || {}, `ai-sdk/coze/${VERSION}`);\n const authorizationHeader = `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'COZE_API_KEY',\n description: '',\n })}`;\n\n const getHeaders = () => ({\n ...agentPartHeader,\n Authorization: authorizationHeader,\n 'content-type': 'application/json',\n });\n\n const createLanguageModel = (modelId: CozeChatModelId) => {\n return new CozeLanguageModel(modelId, {\n botId: options.botId,\n provider: `coze.chat`,\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n extraStreamTransformers: options.extraStreamTransformers || [],\n });\n };\n\n const provider = (modelId: CozeChatModelId) => createLanguageModel(modelId);\n\n provider.specificationVersion = 'v3' as const;\n provider.languageModel = createLanguageModel;\n provider.chat = createLanguageModel;\n\n provider.embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });\n };\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'imageModel' });\n };\n provider.textEmbeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });\n };\n\n return provider;\n}\n","export const VERSION = \"0.0.1\";\n","import {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2CallWarning,\n LanguageModelV2Prompt,\n LanguageModelV2StreamPart,\n SharedV2Headers,\n} from '@ai-sdk/provider';\nimport { CozeChatConfig, IGenerateResult } from './types';\nimport { ServerSentEventTransformStream } from 'parse-sse';\nimport { TextDecoderStream } from 'stream/web';\nimport { convertPromptToMessages } from './utils/prompt-to-model-msg';\nimport { accumulateSSEResponse } from './utils/accumulate-sse-response';\nimport { createErrorStream } from './utils/create-error-stream';\nimport { LLMChunkInjectorTransformStream } from './stream-trasnformer/llm-chunk-injector-transform-stream';\nimport MCPChunkFilterTransformStream from './stream-trasnformer/mcp-chunk-filter-transform-stream';\nimport LLMPartTrasnformStream from './stream-trasnformer/llm-part-transform-stream';\nimport { BuildWarningGenerateResult } from './utils/build-generate-result-by-chat-res';\nimport { getChatCtxForHuman, getChatCtxForMcp, safeParseJson } from '@baishuyun/ai-feat-utils';\nimport { IChatCtx } from '@baishuyun/types';\n\nexport class CozeLanguageModel implements LanguageModelV2 {\n specificationVersion: 'v2' = 'v2';\n provider: string;\n modelId: string;\n supportedUrls: Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>>;\n\n private readonly config: CozeChatConfig;\n\n constructor(modelId: string, config: CozeChatConfig) {\n this.modelId = modelId;\n this.provider = config.provider || 'coze';\n this.supportedUrls = config.supportedUrls?.() || {};\n this.config = config;\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<IGenerateResult> {\n const messages = convertPromptToMessages(options.prompt);\n const warnings: LanguageModelV2CallWarning[] = [];\n\n const url = this.config.url({ path: '/chat' });\n\n const user_id = options.headers ? options.headers['x-user-id'] : '';\n const user_var = options.headers ? options.headers['x-user-var'] : '';\n\n let customVar;\n if (user_var) {\n try {\n customVar = JSON.parse(user_var);\n } catch (e) {\n console.warn('x-user-var parse error', e);\n }\n }\n\n const body = {\n bot_id: this.config.botId,\n auto_save_history: false,\n user_id: user_id || '7543191937730215936',\n stream: true,\n additional_messages: messages,\n };\n\n if (customVar) {\n (body as any).custom_variables = customVar;\n }\n\n const headers = this.config.headers();\n const abortSignal = options.abortSignal;\n\n const response = await fetch(url, {\n method: 'POST',\n headers: headers,\n credentials: 'include',\n body: JSON.stringify(body),\n signal: abortSignal,\n });\n\n if (!response.ok || !response.body) {\n const rawError = await response.text();\n let errorDetail;\n try {\n errorDetail = JSON.parse(rawError);\n } catch {\n errorDetail = rawError;\n }\n\n const errorMessage =\n typeof errorDetail === 'object' && errorDetail?.msg\n ? errorDetail.msg\n : `Coze API error: ${response.status} ${response.statusText}`;\n\n return BuildWarningGenerateResult(errorMessage);\n }\n\n const { content, finishReason, usage } = await accumulateSSEResponse(response.body);\n\n return {\n content,\n finishReason,\n usage,\n request: { body },\n response: { body: null },\n warnings,\n };\n }\n\n isVisibleMsgPart(evtData: any) {\n if (evtData.type === 'knowledge' && evtData.role === 'assistant') {\n return false;\n }\n\n return true;\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: SharedV2Headers };\n }> {\n const conversation_id = options.headers ? options.headers['x-conversation-id'] : '';\n\n // 有 conversation_id 时,服务端会话中已持有完整历史(含中断记录)。\n const prompt = conversation_id ? keepOnlyLastUserMessage(options.prompt) : options.prompt;\n\n const messages = convertPromptToMessages(prompt);\n const queryStr = conversation_id ? `?conversation_id=${conversation_id}` : '';\n\n const url = this.config.url({\n path: `/chat${queryStr}`,\n });\n\n const user_id = options.headers ? options.headers['x-user-id'] : '';\n\n const user_var = options.headers ? options.headers['x-user-var'] : '';\n const user_param = (options.headers ? options.headers['x-user-param'] : '') ?? '';\n\n const params = user_param ? safeParseJson(user_param) : {};\n\n console.log('params 2 workflow', params);\n console.log('conversation id 2 workflow', conversation_id);\n const chatCtx = options?.providerOptions?.chatCtx as unknown as IChatCtx;\n\n const userId = chatCtx?.user?._id || user_id || Date.now().toString();\n\n const body = {\n bot_id: this.config.botId,\n auto_save_history: Boolean(conversation_id),\n user_id: userId,\n stream: true,\n additional_messages: messages,\n parameters: params,\n custom_variables: user_var ? safeParseJson(user_var) : {},\n extra_params: {\n remark: getChatCtxForHuman(chatCtx),\n mcp_ctx: getChatCtxForMcp(chatCtx),\n },\n };\n\n const headers = this.config.headers();\n\n const abortSignal = options.abortSignal;\n\n console.log('url', url);\n console.log('body', JSON.stringify(body, null, 2));\n\n const response = await fetch(url, {\n method: 'POST',\n headers: headers,\n credentials: 'include',\n body: JSON.stringify(body),\n signal: abortSignal,\n });\n\n console.log('chat res status', response.status);\n\n if (!response.ok || !response.body) {\n // if (true) {\n const rawError = await response.text();\n let errorDetail;\n try {\n errorDetail = JSON.parse(rawError); // 尝试解析为 JSON\n } catch {\n errorDetail = rawError; // 非 JSON 直接使用\n }\n\n // 创建一个包含错误信息的流,让 UI 层处理\n const errorMessage =\n typeof errorDetail === 'object' && errorDetail?.msg\n ? errorDetail.msg\n : `Coze API error: ${response.status} ${response.statusText}`;\n\n console.error(errorMessage);\n\n return {\n stream: createErrorStream('会话异常,请重试'),\n };\n }\n\n let externalTransformers = (this.config.extraStreamTransformers || []).map((factory) =>\n factory()\n );\n\n /// 不同阶段,可能需要不同的流处理逻辑\n const stage = options.headers ? options.headers['x-user-stage'] : '';\n const isBuildStage = stage === 'build';\n const isFillStage = stage === 'fill';\n\n const result = response.body\n // 将字节流解码为文本流\n .pipeThrough(\n new TextDecoderStream() as ReadableWritablePair<\n string | undefined,\n Uint8Array<ArrayBufferLike>\n >\n )\n // 解析为 SSE 事件流\n .pipeThrough(new ServerSentEventTransformStream())\n .pipeThrough(new MCPChunkFilterTransformStream(isBuildStage || isFillStage))\n // 补充特殊 llm chunk\n .pipeThrough(new LLMChunkInjectorTransformStream())\n // 转换为 LanguageModelV2StreamPart 格式\n .pipeThrough(new LLMPartTrasnformStream());\n\n let finalResult = result;\n\n if (externalTransformers.length > 0) {\n finalResult = externalTransformers.reduce(\n (stream, transformer) => stream.pipeThrough(transformer),\n result // 初始累积值(原始流)\n );\n }\n\n return {\n stream: finalResult as ReadableStream<LanguageModelV2StreamPart>,\n };\n }\n}\n\n/**\n * 只保留最后一条 user 消息(含其内容),用于有 conversation_id 的场景:\n * 服务端会话中已持有完整历史,只需发送当前用户输入。\n */\nfunction keepOnlyLastUserMessage(prompt: LanguageModelV2Prompt): LanguageModelV2Prompt {\n for (let i = prompt.length - 1; i >= 0; i--) {\n if (prompt[i].role === 'user') {\n return [prompt[i]];\n }\n }\n return prompt;\n}\n","import {\n LanguageModelV2FilePart,\n LanguageModelV2Message,\n LanguageModelV2Prompt,\n LanguageModelV2TextPart,\n} from '@ai-sdk/provider';\nimport { RoleType } from '@coze/api';\nimport { Attachment } from '@baishuyun/types/src/chat';\nimport { excel2json } from './excel2json';\n\nconst decoder = new TextDecoder('utf-8');\n\nconst data2csvText = (data: Uint8Array) => {\n return decoder.decode(data);\n};\n\ntype userMsg = {\n role: 'user';\n content: Array<LanguageModelV2TextPart | LanguageModelV2FilePart>;\n};\n\nconst getPartType = (part: LanguageModelV2TextPart | LanguageModelV2FilePart) => {\n if (part.type === 'text') {\n return 'text';\n }\n\n const isImg = part.mediaType?.startsWith('image/');\n if (isImg) {\n return 'image';\n }\n\n const isAudio = part.mediaType?.startsWith('audio/');\n if (isAudio) {\n return 'audio';\n }\n\n return 'file';\n};\n\nconst parseMessageContent = (message: LanguageModelV2Message, isTextOnly?: boolean) => {\n if (isTextOnly) {\n return (message.content as Array<LanguageModelV2TextPart>)\n .map((part: LanguageModelV2TextPart) => part.text)\n .join('\\n');\n }\n\n const result = (message.content as Array<LanguageModelV2TextPart | LanguageModelV2FilePart>).map(\n (part) => {\n const meta = part.providerOptions?.uploadMetadata as Attachment;\n const url = meta?.url;\n\n return {\n type: getPartType(part),\n text: part.type === 'text' ? (part as LanguageModelV2TextPart).text : '',\n file_id: meta?.file_id,\n name: meta?.name,\n // 附件地址:模型需要在「附件上传」标准动作中引用(IAttachment.attachmentUrl)\n url,\n };\n }\n );\n\n return JSON.stringify(result);\n};\n\nconst isTextOnlyMsg = (message: userMsg) => message.content.every((part) => part.type === 'text');\n\nexport const convertPromptToMessages = (messages: LanguageModelV2Prompt) => {\n return messages.map((message) => {\n const isTextOnly = isTextOnlyMsg(message as userMsg);\n switch (message.role) {\n case 'user':\n return {\n role: RoleType.User,\n content: parseMessageContent(message, isTextOnly),\n content_type: isTextOnly ? 'text' : 'object_string',\n };\n break;\n\n case 'assistant':\n return {\n role: RoleType.Assistant,\n content: (message.content as Array<LanguageModelV2TextPart>)\n .map((part: LanguageModelV2TextPart) => (part.type === 'text' ? part.text : ''))\n .join(''),\n content_type: 'text',\n };\n break;\n }\n });\n};\n","import {\n LanguageModelV2Content,\n LanguageModelV2FinishReason,\n LanguageModelV2Usage,\n} from '@ai-sdk/provider';\nimport { ServerSentEventTransformStream } from 'parse-sse';\nimport { TextDecoderStream } from 'stream/web';\n\nexport interface AccumulatedSSEResponse {\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n}\n\n/**\n * 从字节流中解码 SSE 事件并累积完整响应内容\n */\nexport async function accumulateSSEResponse(\n body: ReadableStream<Uint8Array>\n): Promise<AccumulatedSSEResponse> {\n const sseStream = body\n .pipeThrough(\n new TextDecoderStream() as ReadableWritablePair<\n string | undefined,\n Uint8Array<ArrayBufferLike>\n >\n )\n .pipeThrough(new ServerSentEventTransformStream());\n\n let textContent = '';\n let reasoningContent = '';\n let finishReason: LanguageModelV2FinishReason = 'stop';\n let usage: LanguageModelV2Usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n\n const reader = sseStream.getReader();\n try {\n while (true) {\n const { done, value: evt } = await reader.read();\n if (done) break;\n if (!evt) continue;\n\n let evtData;\n try {\n evtData = JSON.parse(evt.data);\n } catch {\n continue;\n }\n\n const event = evt.type;\n\n if (event === 'conversation.message.delta') {\n if (evtData.reasoning_content) {\n reasoningContent += evtData.reasoning_content;\n } else if (evtData.content) {\n textContent += evtData.content;\n }\n } else if (event === 'conversation.chat.completed' || event === 'done') {\n finishReason = 'stop';\n if (evtData.usage) {\n usage = {\n inputTokens: evtData.usage.input_count || 0,\n outputTokens: evtData.usage.output_count || 0,\n totalTokens: evtData.usage.total_count || 0,\n };\n }\n } else if (event === 'error') {\n finishReason = 'error';\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n const content: LanguageModelV2Content[] = [];\n if (reasoningContent) {\n content.push({ type: 'reasoning', text: reasoningContent });\n }\n if (textContent) {\n content.push({ type: 'text', text: textContent });\n }\n\n return { content, finishReason, usage };\n}\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { generateId } from '@ai-sdk/provider-utils';\n\n/**\n * 创建一个包含错误信息的流\n * @param error 错误信息\n * @returns ReadableStream<LanguageModelV2StreamPart>\n */\nexport const createErrorStream = (error: string): ReadableStream<LanguageModelV2StreamPart> => {\n return new ReadableStream<LanguageModelV2StreamPart>({\n start(controller) {\n const id = generateId();\n controller.enqueue({\n id,\n type: 'text-start',\n });\n controller.enqueue({\n id,\n type: 'text-delta',\n providerMetadata: {\n raw: { data: { type: 'agent-error', error } },\n },\n delta: error,\n });\n controller.enqueue({\n type: 'text-end',\n id,\n });\n controller.close();\n },\n });\n};\n","/**\n * 事件数据取样,某些流 chunk 处理,需要用到前后的 chunk 信息,因此设计一个类缓存相邻 chunk,用于处理依据\n */\nexport class EvtSample {\n private _evtSampleMap: Map<string, any> = new Map();\n private _key1: string = \"1\";\n private _key2: string = \"2\";\n private _maxSample = 2;\n\n public addEventSample(evt: any) {\n if (this._evtSampleMap.size >= this._maxSample) {\n const evt2 = this._evtSampleMap.get(this._key2);\n this._evtSampleMap.set(this._key1, evt2);\n this._evtSampleMap.set(this._key2, evt);\n return;\n }\n\n this._evtSampleMap.set((this._evtSampleMap.size + 1).toString(), evt);\n }\n\n public getFirstSample() {\n return this._evtSampleMap.get(this._key1);\n }\n\n public getSecondSample() {\n return this._evtSampleMap.get(this._key2);\n }\n}\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { StreamChatData } from '@coze/api';\nimport { EvtSample } from '../evt-sample';\n\n/**\n * 补充特殊的 llm chunk, reasoning-end, text-start\n */\nexport class LLMChunkInjectorTransformStream extends TransformStream<\n StreamChatData,\n | StreamChatData\n | (LanguageModelV2StreamPart & {\n disableTransform: boolean;\n })\n> {\n private eventSampleMap = new EvtSample();\n\n constructor() {\n super({\n transform: (\n part: StreamChatData,\n controller: TransformStreamDefaultController<\n StreamChatData | (LanguageModelV2StreamPart & { disableTransform: boolean })\n >\n ) => {\n // 添加事件样本(原逻辑中的addEventSample)\n this.eventSampleMap.addEventSample(part);\n\n // 处理sample1/sample2特殊判断逻辑\n const sample1 = this.eventSampleMap.getFirstSample();\n const sample2 = this.eventSampleMap.getSecondSample();\n\n // handle reasoning end\n if (\n sample1 &&\n sample2 &&\n sample1.data.reasoning_content &&\n !sample2.data.reasoning_content\n ) {\n controller.enqueue({\n disableTransform: true,\n type: 'reasoning-end',\n id: sample1.data.conversation_id,\n });\n }\n\n // handle text-start\n if (sample1 && sample2 && !sample1.data.content && sample2.data.content) {\n controller.enqueue({\n disableTransform: true,\n type: 'text-start',\n id: sample2.data.conversation_id,\n });\n }\n\n // 传递part到下一个转换流\n controller.enqueue(part);\n },\n });\n }\n}\n","import { ChatEventType, StreamChatData } from '@coze/api';\nimport { ServerSentEvent } from 'parse-sse';\n\nexport default class MCPChunkFilterTransformStream extends TransformStream {\n isVisibleMsgPart(evtData: any, part: any, omitTextEndChunk?: boolean) {\n if (evtData.type === 'knowledge' && evtData.role === 'assistant') {\n return false;\n }\n\n // Omit text-end chunk if the flag is set\n if (\n omitTextEndChunk &&\n part.event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED &&\n part.data.type !== 'follow_up'\n ) {\n return false;\n }\n\n if (part.event === 'conversation.message.completed' && evtData.type == 'verbose') {\n return false;\n }\n\n return true;\n }\n\n constructor(omitTextEndChunk: boolean = false) {\n super({\n transform: (\n evt: ServerSentEvent,\n controller: TransformStreamDefaultController<StreamChatData>\n ) => {\n if (!evt) return;\n\n // 解析evt为part对象(原逻辑中的part构建)\n const part = {\n event: evt.type,\n data: JSON.parse(evt.data) || {},\n } as StreamChatData;\n\n // 过滤逻辑:仅传递满足条件的part\n if (this.isVisibleMsgPart(part.data, part, omitTextEndChunk)) {\n controller.enqueue(part);\n }\n },\n });\n }\n}\n","import { LanguageModelV2StreamPart, SharedV2ProviderMetadata } from '@ai-sdk/provider';\nimport { ChatEventType } from '@coze/api';\n\nexport const mcp2llmChunk = (part: any): LanguageModelV2StreamPart | null => {\n const fullData = JSON.stringify(part);\n\n switch (part.event) {\n case ChatEventType.CONVERSATION_CHAT_CREATED:\n return {\n type: 'raw',\n rawValue: part.data,\n };\n break;\n\n case ChatEventType.CONVERSATION_CHAT_IN_PROGRESS:\n return {\n // type: \"text-delta\",\n // id: part.data.conversation_id,\n // delta: part.data.content || \"\",\n // providerMetadata: {\n // raw: { data: fullData },\n // },\n type: 'raw',\n rawValue: part.data,\n };\n break;\n\n case ChatEventType.CONVERSATION_MESSAGE_DELTA:\n const isReasoning = Boolean(part.data.reasoning_content);\n return {\n type: isReasoning ? 'reasoning-delta' : 'text-delta',\n delta: isReasoning ? part.data.reasoning_content : part.data.content,\n id: part.data.conversation_id,\n providerMetadata: {},\n };\n break;\n\n case ChatEventType.CONVERSATION_MESSAGE_COMPLETED:\n if (part.data && part.data.type === 'follow_up') {\n return {\n type: 'raw',\n rawValue: part.data,\n };\n }\n\n if (part.status === 'completed') {\n return {\n type: 'text-end',\n id: part.data.conversation_id,\n // delta: part.data.content || part.data.reasoning_content || \"\",\n providerMetadata: {},\n };\n }\n\n return {\n type: 'raw',\n rawValue: part.data,\n };\n\n break;\n\n case ChatEventType.CONVERSATION_CHAT_COMPLETED:\n // Yield finish event with usage information\n return {\n type: 'finish',\n finishReason: 'stop',\n usage: {\n inputTokens: part.data.usage?.input_count || 0,\n outputTokens: part.data.usage?.output_count || 0,\n totalTokens: part.data.usage?.total_count || 0,\n },\n };\n break;\n\n case ChatEventType.DONE:\n // Stream completed successfully\n return {\n type: 'finish',\n finishReason: 'stop',\n usage: {\n inputTokens: part.data.usage?.input_count || 0,\n outputTokens: part.data.usage?.output_count || 0,\n totalTokens: part.data.usage?.total_count || 0,\n },\n };\n break;\n\n case ChatEventType.ERROR:\n // Handle errors\n console.error('[ERROR]', part.data);\n return {\n type: 'error',\n error: part.data,\n };\n\n default:\n // Handle unknown event types\n console.warn('Unknown event type:', part.event);\n return {\n type: 'error',\n error: 'Unknown event type' + part.event,\n };\n }\n\n return {\n type: 'error',\n error: 'unknown',\n };\n};\n","import { ChatEventType, StreamChatData } from '@coze/api';\nimport { mcp2llmChunk } from '../utils/mcp-to-llm-chunk';\nimport { LanguageModelV2StreamPart } from '@ai-sdk/provider';\n\nexport default class LLMPartTrasnformStream extends TransformStream {\n constructor() {\n super({\n transform: (\n part: StreamChatData | (LanguageModelV2StreamPart & { disableTransform: boolean }),\n controller: TransformStreamDefaultController<LanguageModelV2StreamPart | undefined>\n ) => {\n // Bypass transform if disableTransform flag is set\n const { disableTransform } = part as any;\n if (disableTransform) {\n controller.enqueue(part as any);\n return;\n }\n\n try {\n const chunk = mcp2llmChunk(part as any);\n if (chunk) {\n controller.enqueue(chunk as any);\n }\n } catch (error) {\n console.error('transform coze evt error');\n }\n },\n });\n }\n}\n","import { CreateChatRes } from '@coze/api';\nimport { CozeChatConfig, IGenerateResult } from '../types';\nimport { getCozeChatMsgDetail } from './get-coze-chat-msg-detail';\n\nexport const BuildWarningGenerateResult = (message: string): IGenerateResult => {\n return {\n content: [],\n finishReason: 'error',\n request: {\n body: null,\n },\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n },\n response: {\n body: null,\n },\n warnings: [\n {\n type: 'other',\n message,\n },\n ],\n };\n};\n\nexport const BuildGenerateResultByChatRes = async (\n response: Response,\n chatConfig: CozeChatConfig,\n reqBody?: unknown\n): Promise<IGenerateResult> => {\n if (!response.ok) {\n return Promise.reject(\n BuildWarningGenerateResult(`Coze API error: ${response.status} ${response.statusText}`)\n );\n }\n\n const res = (await response.json()) as CreateChatRes;\n if (res.code !== 0) {\n return Promise.reject(BuildWarningGenerateResult(`Coze API error: ${res.code} ${res.msg}`));\n }\n\n const msgRes = await getCozeChatMsgDetail(res.data.conversation_id, res.data.id, chatConfig);\n if (!msgRes.ok) {\n return Promise.reject(\n BuildWarningGenerateResult(\n `Failed to get message detail: ${msgRes.status} ${msgRes.statusText}`\n )\n );\n }\n const msgDetail = await msgRes.json();\n\n return {\n content: msgDetail.data.message.content,\n finishReason: msgDetail.data.message.status === 'finished' ? 'stop' : 'error',\n request: {\n body: reqBody,\n },\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n },\n response: {\n body: msgDetail,\n },\n warnings: [],\n };\n};\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { JSONParser } from '@streamparser/json';\nimport { createTextInfoEnqueuer, TextInfoEnqueuer } from '../utils/enqueue-text-info';\nimport { rebuildFieldsJsonStructure } from '@baishuyun/ai-feat-utils';\n\nexport const createFieldsJsonTransformStream = (enableJsonParser: boolean) => {\n let parser: JSONParser;\n let enqueueTextDelta: TextInfoEnqueuer;\n let id: string;\n let isFirstChunk = true;\n // 当 LLM 返回的不是 JSON 而是普通文本时,切换到直通模式\n let passthroughMode = false;\n\n const chunkGuard = (chunk: LanguageModelV2StreamPart): boolean => {\n if (!enableJsonParser || passthroughMode) {\n return false;\n }\n\n if (chunk.type !== 'text-delta' || !('delta' in chunk)) {\n return false;\n }\n\n return true;\n };\n\n const transformer = {\n flush: (controller: TransformStreamDefaultController<any>) => {\n try {\n // parser?.end();\n controller.terminate(); // 信号通知下游可读流已关闭\n } catch (e) {\n controller.error('stop error' + e);\n }\n },\n transform: (\n chunk: LanguageModelV2StreamPart,\n controller: TransformStreamDefaultController<LanguageModelV2StreamPart>\n ) => {\n if (!parser && !passthroughMode) {\n return;\n }\n\n try {\n if (chunkGuard(chunk)) {\n if ('id' in chunk && 'delta' in chunk) {\n id = chunk.id;\n let delta = chunk.delta;\n if (isFirstChunk) {\n delta = delta.replace(/^\\uFEFF/, '');\n isFirstChunk = false;\n }\n parser.write(delta);\n } else {\n console.warn('Unexpected chunk format for JSON parsing:', chunk);\n controller.enqueue(chunk);\n }\n } else {\n controller.enqueue(chunk);\n }\n } catch (e) {\n console.log('write or enqueue error', e);\n controller.error(e);\n }\n },\n start: (controller: TransformStreamDefaultController<any>) => {\n parser = new JSONParser({\n paths: ['$.*'],\n });\n\n enqueueTextDelta = enableJsonParser\n ? createTextInfoEnqueuer(controller)\n : (content: string) => {};\n\n parser.onValue = (parsedInfo: any) => {\n const value = parsedInfo.value;\n\n if (value.widget) {\n value.widget.widgetName = `_widget_${Date.now()}`;\n }\n\n enqueueTextDelta(\n JSON.stringify(value),\n JSON.stringify({\n type: 'mcp-fields-json',\n field: rebuildFieldsJsonStructure(value),\n }),\n id\n );\n };\n\n parser.onError = (err: any) => {\n console.error('JsonWidgetStream: JSON Parsing Error:', err);\n\n // LLM 返回的不是 JSON,切换到直通模式,后续 text-delta 直接透传\n passthroughMode = true;\n };\n\n parser.onEnd = () => {\n enqueueTextDelta(\n ' ',\n JSON.stringify({\n appendConfirm: 'save-fields',\n })\n );\n };\n },\n };\n\n return new TransformStream<LanguageModelV2StreamPart, any>(transformer);\n};\n","import { JSONValue, LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { generateId } from '@ai-sdk/provider-utils';\n\nexport type TextInfoEnqueuer = (textInfo: string, metaPayload?: JSONValue, id?: string) => void;\n\nexport const createTextInfoEnqueuer =\n (controller: TransformStreamDefaultController<LanguageModelV2StreamPart>) =>\n (\n textInfo: string,\n metaPayload?: JSONValue,\n id: string = generateId(),\n deltaOnly: boolean = false\n ) => {\n const i = id ?? generateId();\n\n const startPart: LanguageModelV2StreamPart = {\n type: 'text-start',\n id: i,\n };\n\n const deltaPart: LanguageModelV2StreamPart = {\n type: 'text-delta',\n id: i,\n delta: textInfo,\n providerMetadata: metaPayload\n ? {\n raw: { data: metaPayload },\n }\n : undefined,\n };\n\n const endPart: LanguageModelV2StreamPart = {\n type: 'text-end',\n id: i,\n };\n\n if (deltaOnly) {\n controller.enqueue(deltaPart);\n return;\n }\n\n controller.enqueue(startPart);\n controller.enqueue(deltaPart);\n controller.enqueue(endPart);\n };\n","import {\n createTextInfoEnqueuer,\n TextInfoEnqueuer,\n} from \"../utils/enqueue-text-info\";\n\nexport default class SuggestionTransformStream extends TransformStream<\n any,\n any\n> {\n constructor(enable: boolean) {\n let enqueuer: TextInfoEnqueuer;\n super({\n start(controller) {\n enqueuer = createTextInfoEnqueuer(controller);\n },\n transform(chunk, controller) {\n if (\n enable &&\n chunk.type === \"raw\" &&\n chunk.rawValue.type === \"follow_up\" &&\n enqueuer\n ) {\n enqueuer(\n chunk.rawValue.content,\n JSON.stringify({\n type: \"suggestion\",\n }),\n );\n } else {\n controller.enqueue(chunk);\n }\n },\n });\n }\n}\n"],"mappings":"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","names":["ServerSentEventTransformStream","TextDecoderStream","ChatEventType","TextDecoderStream","ServerSentEventTransformStream","generateId"]}
|
|
1
|
+
{"version":3,"sources":["../src/coze-provider.ts","../src/const.ts","../src/coze-language-model.ts","../src/utils/prompt-to-model-msg.ts","../src/utils/accumulate-sse-response.ts","../src/utils/mcp-to-llm-chunk.ts","../src/utils/create-error-stream.ts","../src/evt-sample.ts","../src/stream-trasnformer/llm-chunk-injector-transform-stream.ts","../src/stream-trasnformer/mcp-chunk-filter-transform-stream.ts","../src/stream-trasnformer/llm-part-transform-stream.ts","../src/utils/build-generate-result-by-chat-res.ts","../src/stream-trasnformer/fields-json-transform-stream.ts","../src/utils/enqueue-text-info.ts","../src/stream-trasnformer/suggestion-transform-stream.ts"],"sourcesContent":["import {\n LanguageModelV2,\n LanguageModelV2StreamPart,\n NoSuchModelError,\n ProviderV2,\n} from '@ai-sdk/provider';\n\nimport {\n FetchFunction,\n loadApiKey,\n withoutTrailingSlash,\n withUserAgentSuffix,\n} from '@ai-sdk/provider-utils';\nimport { CozeChatModelId } from './types';\nimport { VERSION } from './const';\nimport { CozeLanguageModel } from './coze-language-model';\n\nexport interface CozeProviderSettings {\n apiKey?: string;\n /**\nBase URL for the API calls.\n*/\n baseURL?: string;\n\n botId: string;\n\n /**\nCustom headers to include in the requests.\n*/\n headers?: Record<string, string>;\n /**\nCustom fetch implementation. You can use it as a middleware to intercept requests,\nor to provide a custom fetch implementation for e.g. testing.\n*/\n fetch?: FetchFunction;\n\n extraStreamTransformers?: (() => TransformStream<LanguageModelV2StreamPart, any>)[];\n}\n\nexport interface CozeProvider extends ProviderV2 {\n (modelId: CozeChatModelId): LanguageModelV2;\n\n languageModel(modelId: CozeChatModelId): LanguageModelV2;\n\n /**\nCreates a DeepSeek chat model for text generation.\n*/\n chat(modelId: CozeChatModelId): LanguageModelV2;\n}\n\nexport function createCoze(\n options: CozeProviderSettings = {\n botId: '',\n }\n): CozeProvider {\n const baseURL = withoutTrailingSlash(options.baseURL);\n\n const agentPartHeader = withUserAgentSuffix(options.headers || {}, `ai-sdk/coze/${VERSION}`);\n const authorizationHeader = `Bearer ${loadApiKey({\n apiKey: options.apiKey,\n environmentVariableName: 'COZE_API_KEY',\n description: '',\n })}`;\n\n const getHeaders = () => ({\n ...agentPartHeader,\n Authorization: authorizationHeader,\n 'content-type': 'application/json',\n });\n\n const createLanguageModel = (modelId: CozeChatModelId) => {\n return new CozeLanguageModel(modelId, {\n botId: options.botId,\n provider: `coze.chat`,\n url: ({ path }) => `${baseURL}${path}`,\n headers: getHeaders,\n fetch: options.fetch,\n extraStreamTransformers: options.extraStreamTransformers || [],\n });\n };\n\n const provider = (modelId: CozeChatModelId) => createLanguageModel(modelId);\n\n provider.specificationVersion = 'v3' as const;\n provider.languageModel = createLanguageModel;\n provider.chat = createLanguageModel;\n\n provider.embeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });\n };\n provider.imageModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'imageModel' });\n };\n provider.textEmbeddingModel = (modelId: string) => {\n throw new NoSuchModelError({ modelId, modelType: 'textEmbeddingModel' });\n };\n\n return provider;\n}\n","export const VERSION = \"0.0.1\";\n","import {\n LanguageModelV2,\n LanguageModelV2CallOptions,\n LanguageModelV2CallWarning,\n LanguageModelV2Prompt,\n LanguageModelV2StreamPart,\n SharedV2Headers,\n} from '@ai-sdk/provider';\nimport { CozeChatConfig, IGenerateResult } from './types';\nimport { ServerSentEventTransformStream } from 'parse-sse';\nimport { TextDecoderStream } from 'stream/web';\nimport { convertPromptToMessages } from './utils/prompt-to-model-msg';\nimport { accumulateSSEResponse } from './utils/accumulate-sse-response';\nimport { createErrorStream } from './utils/create-error-stream';\nimport { LLMChunkInjectorTransformStream } from './stream-trasnformer/llm-chunk-injector-transform-stream';\nimport MCPChunkFilterTransformStream from './stream-trasnformer/mcp-chunk-filter-transform-stream';\nimport LLMPartTrasnformStream from './stream-trasnformer/llm-part-transform-stream';\nimport { BuildWarningGenerateResult } from './utils/build-generate-result-by-chat-res';\nimport { getChatCtxForHuman, getChatCtxForMcp, safeParseJson } from '@baishuyun/ai-feat-utils';\nimport { IChatCtx } from '@baishuyun/types';\n\nexport class CozeLanguageModel implements LanguageModelV2 {\n specificationVersion: 'v2' = 'v2';\n provider: string;\n modelId: string;\n supportedUrls: Record<string, RegExp[]> | PromiseLike<Record<string, RegExp[]>>;\n\n private readonly config: CozeChatConfig;\n\n constructor(modelId: string, config: CozeChatConfig) {\n this.modelId = modelId;\n this.provider = config.provider || 'coze';\n this.supportedUrls = config.supportedUrls?.() || {};\n this.config = config;\n }\n\n async doGenerate(options: LanguageModelV2CallOptions): Promise<IGenerateResult> {\n const messages = convertPromptToMessages(options.prompt);\n const warnings: LanguageModelV2CallWarning[] = [];\n\n const url = this.config.url({ path: '/chat' });\n\n const user_id = options.headers ? options.headers['x-user-id'] : '';\n const user_var = options.headers ? options.headers['x-user-var'] : '';\n\n let customVar;\n if (user_var) {\n try {\n customVar = JSON.parse(user_var);\n } catch (e) {\n console.warn('x-user-var parse error', e);\n }\n }\n\n const body = {\n bot_id: this.config.botId,\n auto_save_history: false,\n user_id: user_id || '7543191937730215936',\n stream: true,\n additional_messages: messages,\n };\n\n if (customVar) {\n (body as any).custom_variables = customVar;\n }\n\n const headers = this.config.headers();\n const abortSignal = options.abortSignal;\n\n const response = await fetch(url, {\n method: 'POST',\n headers: headers,\n credentials: 'include',\n body: JSON.stringify(body),\n signal: abortSignal,\n });\n\n if (!response.ok || !response.body) {\n const rawError = await response.text();\n let errorDetail;\n try {\n errorDetail = JSON.parse(rawError);\n } catch {\n errorDetail = rawError;\n }\n\n const errorMessage =\n typeof errorDetail === 'object' && errorDetail?.msg\n ? errorDetail.msg\n : `Coze API error: ${response.status} ${response.statusText}`;\n\n return BuildWarningGenerateResult(errorMessage);\n }\n\n const { content, finishReason, usage } = await accumulateSSEResponse(response.body);\n\n return {\n content,\n finishReason,\n usage,\n request: { body },\n response: { body: null },\n warnings,\n };\n }\n\n isVisibleMsgPart(evtData: any) {\n if (evtData.type === 'knowledge' && evtData.role === 'assistant') {\n return false;\n }\n\n return true;\n }\n\n async doStream(options: LanguageModelV2CallOptions): Promise<{\n stream: ReadableStream<LanguageModelV2StreamPart>;\n request?: { body?: unknown };\n response?: { headers?: SharedV2Headers };\n }> {\n const conversation_id = options.headers ? options.headers['x-conversation-id'] : '';\n\n // 有 conversation_id 时,服务端会话中已持有完整历史(含中断记录)。\n const prompt = conversation_id ? keepOnlyLastUserMessage(options.prompt) : options.prompt;\n\n const messages = convertPromptToMessages(prompt);\n const queryStr = conversation_id ? `?conversation_id=${conversation_id}` : '';\n\n const url = this.config.url({\n path: `/chat${queryStr}`,\n });\n\n // 团队级别\n const user_id = options.headers ? options.headers['x-user-id'] : '';\n\n // 个人用户\n const operator_id = (options.headers ? options.headers['x-operator-id'] : '') ?? '';\n\n const user_var = options.headers ? options.headers['x-user-var'] : '';\n const user_param = (options.headers ? options.headers['x-user-param'] : '') ?? '';\n\n const params = user_param ? safeParseJson(user_param) : {};\n\n console.log('params 2 workflow', params);\n console.log('conversation id 2 workflow', conversation_id);\n const chatCtx = options?.providerOptions?.chatCtx as unknown as IChatCtx;\n\n console.log('chatCtx', chatCtx);\n\n const userId = operator_id || chatCtx?.user?._id || user_id || Date.now().toString();\n\n const body = {\n bot_id: this.config.botId,\n auto_save_history: Boolean(conversation_id),\n user_id: userId,\n stream: true,\n additional_messages: messages,\n parameters: params,\n custom_variables: user_var ? safeParseJson(user_var) : {},\n extra_params: {\n remark: getChatCtxForHuman(chatCtx),\n mcp_ctx: getChatCtxForMcp(chatCtx),\n },\n };\n\n const headers = this.config.headers();\n\n const abortSignal = options.abortSignal;\n\n console.log('url', url);\n console.log('body', JSON.stringify(body, null, 2));\n console.log('operator_id', operator_id);\n\n const response = await fetch(url, {\n method: 'POST',\n headers: headers,\n credentials: 'include',\n body: JSON.stringify(body),\n signal: abortSignal,\n });\n\n console.log('chat res status', response.status);\n\n if (!response.ok || !response.body) {\n // if (true) {\n const rawError = await response.text();\n let errorDetail;\n try {\n errorDetail = JSON.parse(rawError); // 尝试解析为 JSON\n } catch {\n errorDetail = rawError; // 非 JSON 直接使用\n }\n\n // 创建一个包含错误信息的流,让 UI 层处理\n const errorMessage =\n typeof errorDetail === 'object' && errorDetail?.msg\n ? errorDetail.msg\n : `Coze API error: ${response.status} ${response.statusText}`;\n\n console.error(errorMessage);\n\n return {\n stream: createErrorStream('会话异常,请重试'),\n };\n }\n\n let externalTransformers = (this.config.extraStreamTransformers || []).map((factory) =>\n factory()\n );\n\n /// 不同阶段,可能需要不同的流处理逻辑\n const stage = options.headers ? options.headers['x-user-stage'] : '';\n const isBuildStage = stage === 'build';\n const isFillStage = stage === 'fill';\n\n const result = response.body\n // 将字节流解码为文本流\n .pipeThrough(\n new TextDecoderStream() as ReadableWritablePair<\n string | undefined,\n Uint8Array<ArrayBufferLike>\n >\n )\n // 解析为 SSE 事件流\n .pipeThrough(new ServerSentEventTransformStream())\n .pipeThrough(new MCPChunkFilterTransformStream(isBuildStage || isFillStage))\n // 补充特殊 llm chunk\n .pipeThrough(new LLMChunkInjectorTransformStream())\n // 转换为 LanguageModelV2StreamPart 格式\n .pipeThrough(new LLMPartTrasnformStream());\n\n let finalResult = result;\n\n if (externalTransformers.length > 0) {\n finalResult = externalTransformers.reduce(\n (stream, transformer) => stream.pipeThrough(transformer),\n result // 初始累积值(原始流)\n );\n }\n\n return {\n stream: finalResult as ReadableStream<LanguageModelV2StreamPart>,\n };\n }\n}\n\n/**\n * 只保留最后一条 user 消息(含其内容),用于有 conversation_id 的场景:\n * 服务端会话中已持有完整历史,只需发送当前用户输入。\n */\nfunction keepOnlyLastUserMessage(prompt: LanguageModelV2Prompt): LanguageModelV2Prompt {\n for (let i = prompt.length - 1; i >= 0; i--) {\n if (prompt[i].role === 'user') {\n return [prompt[i]];\n }\n }\n return prompt;\n}\n","import {\n LanguageModelV2FilePart,\n LanguageModelV2Message,\n LanguageModelV2Prompt,\n LanguageModelV2TextPart,\n} from '@ai-sdk/provider';\nimport { RoleType } from '@coze/api';\nimport { Attachment } from '@baishuyun/types/src/chat';\nimport { excel2json } from './excel2json';\n\nconst decoder = new TextDecoder('utf-8');\n\nconst data2csvText = (data: Uint8Array) => {\n return decoder.decode(data);\n};\n\ntype userMsg = {\n role: 'user';\n content: Array<LanguageModelV2TextPart | LanguageModelV2FilePart>;\n};\n\nconst getPartType = (part: LanguageModelV2TextPart | LanguageModelV2FilePart) => {\n if (part.type === 'text') {\n return 'text';\n }\n\n const isImg = part.mediaType?.startsWith('image/');\n if (isImg) {\n return 'image';\n }\n\n const isAudio = part.mediaType?.startsWith('audio/');\n if (isAudio) {\n return 'audio';\n }\n\n return 'file';\n};\n\nconst parseMessageContent = (message: LanguageModelV2Message, isTextOnly?: boolean) => {\n if (isTextOnly) {\n return (message.content as Array<LanguageModelV2TextPart>)\n .map((part: LanguageModelV2TextPart) => part.text)\n .join('\\n');\n }\n\n const result = (message.content as Array<LanguageModelV2TextPart | LanguageModelV2FilePart>).map(\n (part) => {\n const meta = part.providerOptions?.uploadMetadata as Attachment;\n const url = meta?.url;\n\n return {\n type: getPartType(part),\n text: part.type === 'text' ? (part as LanguageModelV2TextPart).text : '',\n file_id: meta?.file_id,\n name: meta?.name,\n // 附件地址:模型需要在「附件上传」标准动作中引用(IAttachment.attachmentUrl)\n url,\n };\n }\n );\n\n return JSON.stringify(result);\n};\n\nconst isTextOnlyMsg = (message: userMsg) => message.content.every((part) => part.type === 'text');\n\nexport const convertPromptToMessages = (messages: LanguageModelV2Prompt) => {\n return messages.map((message) => {\n const isTextOnly = isTextOnlyMsg(message as userMsg);\n switch (message.role) {\n case 'user':\n return {\n role: RoleType.User,\n content: parseMessageContent(message, isTextOnly),\n content_type: isTextOnly ? 'text' : 'object_string',\n };\n break;\n\n case 'assistant':\n return {\n role: RoleType.Assistant,\n content: (message.content as Array<LanguageModelV2TextPart>)\n .map((part: LanguageModelV2TextPart) => (part.type === 'text' ? part.text : ''))\n .join(''),\n content_type: 'text',\n };\n break;\n }\n });\n};\n","import {\n LanguageModelV2Content,\n LanguageModelV2FinishReason,\n LanguageModelV2Usage,\n} from '@ai-sdk/provider';\nimport { ServerSentEventTransformStream } from 'parse-sse';\nimport { TextDecoderStream } from 'stream/web';\nimport { mapCozeUsage } from './mcp-to-llm-chunk';\n\nexport interface AccumulatedSSEResponse {\n content: LanguageModelV2Content[];\n finishReason: LanguageModelV2FinishReason;\n usage: LanguageModelV2Usage;\n}\n\n/**\n * 从字节流中解码 SSE 事件并累积完整响应内容\n */\nexport async function accumulateSSEResponse(\n body: ReadableStream<Uint8Array>\n): Promise<AccumulatedSSEResponse> {\n const sseStream = body\n .pipeThrough(\n new TextDecoderStream() as ReadableWritablePair<\n string | undefined,\n Uint8Array<ArrayBufferLike>\n >\n )\n .pipeThrough(new ServerSentEventTransformStream());\n\n let textContent = '';\n let reasoningContent = '';\n let finishReason: LanguageModelV2FinishReason = 'stop';\n let usage: LanguageModelV2Usage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n\n const reader = sseStream.getReader();\n try {\n while (true) {\n const { done, value: evt } = await reader.read();\n if (done) break;\n if (!evt) continue;\n\n let evtData;\n try {\n evtData = JSON.parse(evt.data);\n } catch {\n continue;\n }\n\n const event = evt.type;\n\n if (event === 'conversation.message.delta') {\n if (evtData.reasoning_content) {\n reasoningContent += evtData.reasoning_content;\n } else if (evtData.content) {\n textContent += evtData.content;\n }\n } else if (event === 'conversation.chat.completed' || event === 'done') {\n finishReason = 'stop';\n if (evtData.usage) {\n usage = mapCozeUsage(evtData.usage);\n }\n } else if (event === 'error') {\n finishReason = 'error';\n }\n }\n } finally {\n reader.releaseLock();\n }\n\n const content: LanguageModelV2Content[] = [];\n if (reasoningContent) {\n content.push({ type: 'reasoning', text: reasoningContent });\n }\n if (textContent) {\n content.push({ type: 'text', text: textContent });\n }\n\n return { content, finishReason, usage };\n}\n","import { LanguageModelV2StreamPart, SharedV2ProviderMetadata } from '@ai-sdk/provider';\nimport { ChatEventType } from '@coze/api';\n\n/**\n * 上游 usage 字段兼容:官方 Coze v3 的 completed 事件为\n * token_count/input_count/output_count(无 total_count),\n * 总额按 total_count → token_count → input+output 的顺序取\n */\nexport const mapCozeUsage = (usage: any) => {\n const inputTokens = usage?.input_count || 0;\n const outputTokens = usage?.output_count || 0;\n const totalTokens = usage?.total_count ?? usage?.token_count ?? inputTokens + outputTokens;\n return { inputTokens, outputTokens, totalTokens };\n};\n\n/**\n * 从消息 meta_data 提取 token 用量。上游会把本轮模型用量写入 answer 消息\n * (含 workflow 用量消息)的 meta_data:token / input_tokens / output_tokens,\n * 是 chat.completed 事件不带 usage 时(旧版上游)的兜底来源\n */\nexport const extractUsageFromMsgMeta = (meta: any) => {\n if (!meta) return null;\n const totalTokens = Number(meta.token);\n if (!totalTokens) return null;\n return {\n inputTokens: Number(meta.input_tokens) || 0,\n outputTokens: Number(meta.output_tokens) || 0,\n totalTokens,\n };\n};\n\nexport const mcp2llmChunk = (part: any): LanguageModelV2StreamPart | null => {\n const fullData = JSON.stringify(part);\n\n switch (part.event) {\n case ChatEventType.CONVERSATION_CHAT_CREATED:\n return {\n type: 'raw',\n rawValue: part.data,\n };\n break;\n\n case ChatEventType.CONVERSATION_CHAT_IN_PROGRESS:\n return {\n // type: \"text-delta\",\n // id: part.data.conversation_id,\n // delta: part.data.content || \"\",\n // providerMetadata: {\n // raw: { data: fullData },\n // },\n type: 'raw',\n rawValue: part.data,\n };\n break;\n\n case ChatEventType.CONVERSATION_MESSAGE_DELTA:\n const isReasoning = Boolean(part.data.reasoning_content);\n return {\n type: isReasoning ? 'reasoning-delta' : 'text-delta',\n delta: isReasoning ? part.data.reasoning_content : part.data.content,\n id: part.data.conversation_id,\n providerMetadata: {},\n };\n break;\n\n case ChatEventType.CONVERSATION_MESSAGE_COMPLETED:\n if (part.data && part.data.type === 'follow_up') {\n return {\n type: 'raw',\n rawValue: part.data,\n };\n }\n\n if (part.status === 'completed') {\n return {\n type: 'text-end',\n id: part.data.conversation_id,\n // delta: part.data.content || part.data.reasoning_content || \"\",\n providerMetadata: {},\n };\n }\n\n return {\n type: 'raw',\n rawValue: part.data,\n };\n\n break;\n\n case ChatEventType.CONVERSATION_CHAT_COMPLETED:\n // Yield finish event with usage information\n return {\n type: 'finish',\n finishReason: 'stop',\n usage: mapCozeUsage(part.data.usage),\n };\n break;\n\n case ChatEventType.DONE:\n // Stream completed successfully\n return {\n type: 'finish',\n finishReason: 'stop',\n usage: mapCozeUsage(part.data.usage),\n };\n break;\n\n case ChatEventType.ERROR:\n // Handle errors\n console.error('[ERROR]', part.data);\n return {\n type: 'error',\n error: part.data,\n };\n\n default:\n // Handle unknown event types\n console.warn('Unknown event type:', part.event);\n return {\n type: 'error',\n error: 'Unknown event type' + part.event,\n };\n }\n\n return {\n type: 'error',\n error: 'unknown',\n };\n};\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { generateId } from '@ai-sdk/provider-utils';\n\n/**\n * 创建一个包含错误信息的流\n * @param error 错误信息\n * @returns ReadableStream<LanguageModelV2StreamPart>\n */\nexport const createErrorStream = (error: string): ReadableStream<LanguageModelV2StreamPart> => {\n return new ReadableStream<LanguageModelV2StreamPart>({\n start(controller) {\n const id = generateId();\n controller.enqueue({\n id,\n type: 'text-start',\n });\n controller.enqueue({\n id,\n type: 'text-delta',\n providerMetadata: {\n raw: { data: { type: 'agent-error', error } },\n },\n delta: error,\n });\n controller.enqueue({\n type: 'text-end',\n id,\n });\n controller.close();\n },\n });\n};\n","/**\n * 事件数据取样,某些流 chunk 处理,需要用到前后的 chunk 信息,因此设计一个类缓存相邻 chunk,用于处理依据\n */\nexport class EvtSample {\n private _evtSampleMap: Map<string, any> = new Map();\n private _key1: string = \"1\";\n private _key2: string = \"2\";\n private _maxSample = 2;\n\n public addEventSample(evt: any) {\n if (this._evtSampleMap.size >= this._maxSample) {\n const evt2 = this._evtSampleMap.get(this._key2);\n this._evtSampleMap.set(this._key1, evt2);\n this._evtSampleMap.set(this._key2, evt);\n return;\n }\n\n this._evtSampleMap.set((this._evtSampleMap.size + 1).toString(), evt);\n }\n\n public getFirstSample() {\n return this._evtSampleMap.get(this._key1);\n }\n\n public getSecondSample() {\n return this._evtSampleMap.get(this._key2);\n }\n}\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { StreamChatData } from '@coze/api';\nimport { EvtSample } from '../evt-sample';\n\n/**\n * 补充特殊的 llm chunk, reasoning-end, text-start\n */\nexport class LLMChunkInjectorTransformStream extends TransformStream<\n StreamChatData,\n | StreamChatData\n | (LanguageModelV2StreamPart & {\n disableTransform: boolean;\n })\n> {\n private eventSampleMap = new EvtSample();\n\n constructor() {\n super({\n transform: (\n part: StreamChatData,\n controller: TransformStreamDefaultController<\n StreamChatData | (LanguageModelV2StreamPart & { disableTransform: boolean })\n >\n ) => {\n // 添加事件样本(原逻辑中的addEventSample)\n this.eventSampleMap.addEventSample(part);\n\n // 处理sample1/sample2特殊判断逻辑\n const sample1 = this.eventSampleMap.getFirstSample();\n const sample2 = this.eventSampleMap.getSecondSample();\n\n // handle reasoning end\n if (\n sample1 &&\n sample2 &&\n sample1.data.reasoning_content &&\n !sample2.data.reasoning_content\n ) {\n controller.enqueue({\n disableTransform: true,\n type: 'reasoning-end',\n id: sample1.data.conversation_id,\n });\n }\n\n // handle text-start\n if (sample1 && sample2 && !sample1.data.content && sample2.data.content) {\n controller.enqueue({\n disableTransform: true,\n type: 'text-start',\n id: sample2.data.conversation_id,\n });\n }\n\n // 传递part到下一个转换流\n controller.enqueue(part);\n },\n });\n }\n}\n","import { ChatEventType, StreamChatData } from '@coze/api';\nimport { ServerSentEvent } from 'parse-sse';\n\nexport default class MCPChunkFilterTransformStream extends TransformStream {\n isVisibleMsgPart(evtData: any, part: any, omitTextEndChunk?: boolean) {\n if (evtData.type === 'knowledge' && evtData.role === 'assistant') {\n return false;\n }\n\n // Omit text-end chunk if the flag is set\n if (\n omitTextEndChunk &&\n part.event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED &&\n part.data.type !== 'follow_up'\n ) {\n return false;\n }\n\n if (part.event === 'conversation.message.completed' && evtData.type == 'verbose') {\n return false;\n }\n\n return true;\n }\n\n constructor(omitTextEndChunk: boolean = false) {\n super({\n transform: (\n evt: ServerSentEvent,\n controller: TransformStreamDefaultController<StreamChatData>\n ) => {\n if (!evt) return;\n\n // 解析evt为part对象(原逻辑中的part构建)\n const part = {\n event: evt.type,\n data: JSON.parse(evt.data) || {},\n } as StreamChatData;\n\n // 过滤逻辑:仅传递满足条件的part\n if (this.isVisibleMsgPart(part.data, part, omitTextEndChunk)) {\n controller.enqueue(part);\n }\n },\n });\n }\n}\n","import { ChatEventType, StreamChatData } from '@coze/api';\nimport { extractUsageFromMsgMeta, mcp2llmChunk } from '../utils/mcp-to-llm-chunk';\nimport { LanguageModelV2StreamPart, LanguageModelV2Usage } from '@ai-sdk/provider';\n\nexport default class LLMPartTrasnformStream extends TransformStream {\n /**\n * 本轮最近一条消息 meta_data 中携带的 token 用量。\n * 旧版上游不在 conversation.chat.completed 事件中携带 usage,\n * 发 finish chunk 时若事件 usage 缺失则用此兜底(事件已带则不覆盖)\n */\n private lastMsgUsage: LanguageModelV2Usage | null = null;\n\n constructor() {\n super({\n transform: (\n part: StreamChatData | (LanguageModelV2StreamPart & { disableTransform: boolean }),\n controller: TransformStreamDefaultController<LanguageModelV2StreamPart | undefined>\n ) => {\n // Bypass transform if disableTransform flag is set\n const { disableTransform } = part as any;\n if (disableTransform) {\n controller.enqueue(part as any);\n return;\n }\n\n try {\n if ((part as any).event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {\n const usage = extractUsageFromMsgMeta((part as any).data?.meta_data);\n if (usage) {\n this.lastMsgUsage = usage;\n }\n }\n\n const chunk = mcp2llmChunk(part as any);\n if (chunk) {\n if (chunk.type === 'finish' && !chunk.usage?.totalTokens && this.lastMsgUsage) {\n chunk.usage = this.lastMsgUsage;\n }\n controller.enqueue(chunk as any);\n }\n } catch (error) {\n console.error('transform coze evt error');\n }\n },\n });\n }\n}\n","import { CreateChatRes } from '@coze/api';\nimport { CozeChatConfig, IGenerateResult } from '../types';\nimport { getCozeChatMsgDetail } from './get-coze-chat-msg-detail';\n\nexport const BuildWarningGenerateResult = (message: string): IGenerateResult => {\n return {\n content: [],\n finishReason: 'error',\n request: {\n body: null,\n },\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n },\n response: {\n body: null,\n },\n warnings: [\n {\n type: 'other',\n message,\n },\n ],\n };\n};\n\nexport const BuildGenerateResultByChatRes = async (\n response: Response,\n chatConfig: CozeChatConfig,\n reqBody?: unknown\n): Promise<IGenerateResult> => {\n if (!response.ok) {\n return Promise.reject(\n BuildWarningGenerateResult(`Coze API error: ${response.status} ${response.statusText}`)\n );\n }\n\n const res = (await response.json()) as CreateChatRes;\n if (res.code !== 0) {\n return Promise.reject(BuildWarningGenerateResult(`Coze API error: ${res.code} ${res.msg}`));\n }\n\n const msgRes = await getCozeChatMsgDetail(res.data.conversation_id, res.data.id, chatConfig);\n if (!msgRes.ok) {\n return Promise.reject(\n BuildWarningGenerateResult(\n `Failed to get message detail: ${msgRes.status} ${msgRes.statusText}`\n )\n );\n }\n const msgDetail = await msgRes.json();\n\n return {\n content: msgDetail.data.message.content,\n finishReason: msgDetail.data.message.status === 'finished' ? 'stop' : 'error',\n request: {\n body: reqBody,\n },\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n totalTokens: 0,\n },\n response: {\n body: msgDetail,\n },\n warnings: [],\n };\n};\n","import { LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { JSONParser } from '@streamparser/json';\nimport { createTextInfoEnqueuer, TextInfoEnqueuer } from '../utils/enqueue-text-info';\nimport { rebuildFieldsJsonStructure } from '@baishuyun/ai-feat-utils';\n\nexport const createFieldsJsonTransformStream = (enableJsonParser: boolean) => {\n let parser: JSONParser;\n let enqueueTextDelta: TextInfoEnqueuer;\n let id: string;\n let isFirstChunk = true;\n // 当 LLM 返回的不是 JSON 而是普通文本时,切换到直通模式\n let passthroughMode = false;\n\n const chunkGuard = (chunk: LanguageModelV2StreamPart): boolean => {\n if (!enableJsonParser || passthroughMode) {\n return false;\n }\n\n if (chunk.type !== 'text-delta' || !('delta' in chunk)) {\n return false;\n }\n\n return true;\n };\n\n const transformer = {\n flush: (controller: TransformStreamDefaultController<any>) => {\n try {\n // parser?.end();\n controller.terminate(); // 信号通知下游可读流已关闭\n } catch (e) {\n controller.error('stop error' + e);\n }\n },\n transform: (\n chunk: LanguageModelV2StreamPart,\n controller: TransformStreamDefaultController<LanguageModelV2StreamPart>\n ) => {\n if (!parser && !passthroughMode) {\n return;\n }\n\n try {\n if (chunkGuard(chunk)) {\n if ('id' in chunk && 'delta' in chunk) {\n id = chunk.id;\n let delta = chunk.delta;\n if (isFirstChunk) {\n delta = delta.replace(/^\\uFEFF/, '');\n isFirstChunk = false;\n }\n parser.write(delta);\n } else {\n console.warn('Unexpected chunk format for JSON parsing:', chunk);\n controller.enqueue(chunk);\n }\n } else {\n controller.enqueue(chunk);\n }\n } catch (e) {\n console.log('write or enqueue error', e);\n controller.error(e);\n }\n },\n start: (controller: TransformStreamDefaultController<any>) => {\n parser = new JSONParser({\n paths: ['$.*'],\n });\n\n enqueueTextDelta = enableJsonParser\n ? createTextInfoEnqueuer(controller)\n : (content: string) => {};\n\n parser.onValue = (parsedInfo: any) => {\n const value = parsedInfo.value;\n\n if (value.widget) {\n value.widget.widgetName = `_widget_${Date.now()}`;\n }\n\n enqueueTextDelta(\n JSON.stringify(value),\n JSON.stringify({\n type: 'mcp-fields-json',\n field: rebuildFieldsJsonStructure(value),\n }),\n id\n );\n };\n\n parser.onError = (err: any) => {\n console.error('JsonWidgetStream: JSON Parsing Error:', err);\n\n // LLM 返回的不是 JSON,切换到直通模式,后续 text-delta 直接透传\n passthroughMode = true;\n };\n\n parser.onEnd = () => {\n enqueueTextDelta(\n ' ',\n JSON.stringify({\n appendConfirm: 'save-fields',\n })\n );\n };\n },\n };\n\n return new TransformStream<LanguageModelV2StreamPart, any>(transformer);\n};\n","import { JSONValue, LanguageModelV2StreamPart } from '@ai-sdk/provider';\nimport { generateId } from '@ai-sdk/provider-utils';\n\nexport type TextInfoEnqueuer = (textInfo: string, metaPayload?: JSONValue, id?: string) => void;\n\nexport const createTextInfoEnqueuer =\n (controller: TransformStreamDefaultController<LanguageModelV2StreamPart>) =>\n (\n textInfo: string,\n metaPayload?: JSONValue,\n id: string = generateId(),\n deltaOnly: boolean = false\n ) => {\n const i = id ?? generateId();\n\n const startPart: LanguageModelV2StreamPart = {\n type: 'text-start',\n id: i,\n };\n\n const deltaPart: LanguageModelV2StreamPart = {\n type: 'text-delta',\n id: i,\n delta: textInfo,\n providerMetadata: metaPayload\n ? {\n raw: { data: metaPayload },\n }\n : undefined,\n };\n\n const endPart: LanguageModelV2StreamPart = {\n type: 'text-end',\n id: i,\n };\n\n if (deltaOnly) {\n controller.enqueue(deltaPart);\n return;\n }\n\n controller.enqueue(startPart);\n controller.enqueue(deltaPart);\n controller.enqueue(endPart);\n };\n","import {\n createTextInfoEnqueuer,\n TextInfoEnqueuer,\n} from \"../utils/enqueue-text-info\";\n\nexport default class SuggestionTransformStream extends TransformStream<\n any,\n any\n> {\n constructor(enable: boolean) {\n let enqueuer: TextInfoEnqueuer;\n super({\n start(controller) {\n enqueuer = createTextInfoEnqueuer(controller);\n },\n transform(chunk, controller) {\n if (\n enable &&\n chunk.type === \"raw\" &&\n chunk.rawValue.type === \"follow_up\" &&\n enqueuer\n ) {\n enqueuer(\n chunk.rawValue.content,\n JSON.stringify({\n type: \"suggestion\",\n }),\n );\n } else {\n controller.enqueue(chunk);\n }\n },\n });\n }\n}\n"],"mappings":"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","names":["ServerSentEventTransformStream","TextDecoderStream","ChatEventType","ChatEventType","ChatEventType","TextDecoderStream","ServerSentEventTransformStream","generateId"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baishuyun/coze-provider",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.47",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"registry": "https://registry.npmjs.org/"
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"parse-sse": "^0.1.0",
|
|
24
24
|
"stream-json": "^1.9.1",
|
|
25
25
|
"xlsx": "^0.18.5",
|
|
26
|
-
"@baishuyun/ai-feat-utils": "2.0.
|
|
26
|
+
"@baishuyun/ai-feat-utils": "2.0.47"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@changesets/cli": "^2.29.8",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"typescript": "5.8.3",
|
|
34
34
|
"vite": "^5.1.4",
|
|
35
35
|
"vite-plugin-dts": "^4.5.4",
|
|
36
|
-
"@baishuyun/
|
|
37
|
-
"@baishuyun/
|
|
36
|
+
"@baishuyun/types": "3.0.43",
|
|
37
|
+
"@baishuyun/typescript-config": "2.0.9"
|
|
38
38
|
},
|
|
39
39
|
"peerDependencies": {
|
|
40
40
|
"zod": "^3.25.76 || ^4.1.8"
|
|
@@ -129,8 +129,12 @@ export class CozeLanguageModel implements LanguageModelV2 {
|
|
|
129
129
|
path: `/chat${queryStr}`,
|
|
130
130
|
});
|
|
131
131
|
|
|
132
|
+
// 团队级别
|
|
132
133
|
const user_id = options.headers ? options.headers['x-user-id'] : '';
|
|
133
134
|
|
|
135
|
+
// 个人用户
|
|
136
|
+
const operator_id = (options.headers ? options.headers['x-operator-id'] : '') ?? '';
|
|
137
|
+
|
|
134
138
|
const user_var = options.headers ? options.headers['x-user-var'] : '';
|
|
135
139
|
const user_param = (options.headers ? options.headers['x-user-param'] : '') ?? '';
|
|
136
140
|
|
|
@@ -140,7 +144,9 @@ export class CozeLanguageModel implements LanguageModelV2 {
|
|
|
140
144
|
console.log('conversation id 2 workflow', conversation_id);
|
|
141
145
|
const chatCtx = options?.providerOptions?.chatCtx as unknown as IChatCtx;
|
|
142
146
|
|
|
143
|
-
|
|
147
|
+
console.log('chatCtx', chatCtx);
|
|
148
|
+
|
|
149
|
+
const userId = operator_id || chatCtx?.user?._id || user_id || Date.now().toString();
|
|
144
150
|
|
|
145
151
|
const body = {
|
|
146
152
|
bot_id: this.config.botId,
|
|
@@ -162,6 +168,7 @@ export class CozeLanguageModel implements LanguageModelV2 {
|
|
|
162
168
|
|
|
163
169
|
console.log('url', url);
|
|
164
170
|
console.log('body', JSON.stringify(body, null, 2));
|
|
171
|
+
console.log('operator_id', operator_id);
|
|
165
172
|
|
|
166
173
|
const response = await fetch(url, {
|
|
167
174
|
method: 'POST',
|
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
import { ChatEventType, StreamChatData } from '@coze/api';
|
|
2
|
-
import { mcp2llmChunk } from '../utils/mcp-to-llm-chunk';
|
|
3
|
-
import { LanguageModelV2StreamPart } from '@ai-sdk/provider';
|
|
2
|
+
import { extractUsageFromMsgMeta, mcp2llmChunk } from '../utils/mcp-to-llm-chunk';
|
|
3
|
+
import { LanguageModelV2StreamPart, LanguageModelV2Usage } from '@ai-sdk/provider';
|
|
4
4
|
|
|
5
5
|
export default class LLMPartTrasnformStream extends TransformStream {
|
|
6
|
+
/**
|
|
7
|
+
* 本轮最近一条消息 meta_data 中携带的 token 用量。
|
|
8
|
+
* 旧版上游不在 conversation.chat.completed 事件中携带 usage,
|
|
9
|
+
* 发 finish chunk 时若事件 usage 缺失则用此兜底(事件已带则不覆盖)
|
|
10
|
+
*/
|
|
11
|
+
private lastMsgUsage: LanguageModelV2Usage | null = null;
|
|
12
|
+
|
|
6
13
|
constructor() {
|
|
7
14
|
super({
|
|
8
15
|
transform: (
|
|
@@ -17,8 +24,18 @@ export default class LLMPartTrasnformStream extends TransformStream {
|
|
|
17
24
|
}
|
|
18
25
|
|
|
19
26
|
try {
|
|
27
|
+
if ((part as any).event === ChatEventType.CONVERSATION_MESSAGE_COMPLETED) {
|
|
28
|
+
const usage = extractUsageFromMsgMeta((part as any).data?.meta_data);
|
|
29
|
+
if (usage) {
|
|
30
|
+
this.lastMsgUsage = usage;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
20
34
|
const chunk = mcp2llmChunk(part as any);
|
|
21
35
|
if (chunk) {
|
|
36
|
+
if (chunk.type === 'finish' && !chunk.usage?.totalTokens && this.lastMsgUsage) {
|
|
37
|
+
chunk.usage = this.lastMsgUsage;
|
|
38
|
+
}
|
|
22
39
|
controller.enqueue(chunk as any);
|
|
23
40
|
}
|
|
24
41
|
} catch (error) {
|
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import { ServerSentEventTransformStream } from 'parse-sse';
|
|
7
7
|
import { TextDecoderStream } from 'stream/web';
|
|
8
|
+
import { mapCozeUsage } from './mcp-to-llm-chunk';
|
|
8
9
|
|
|
9
10
|
export interface AccumulatedSSEResponse {
|
|
10
11
|
content: LanguageModelV2Content[];
|
|
@@ -57,11 +58,7 @@ export async function accumulateSSEResponse(
|
|
|
57
58
|
} else if (event === 'conversation.chat.completed' || event === 'done') {
|
|
58
59
|
finishReason = 'stop';
|
|
59
60
|
if (evtData.usage) {
|
|
60
|
-
usage =
|
|
61
|
-
inputTokens: evtData.usage.input_count || 0,
|
|
62
|
-
outputTokens: evtData.usage.output_count || 0,
|
|
63
|
-
totalTokens: evtData.usage.total_count || 0,
|
|
64
|
-
};
|
|
61
|
+
usage = mapCozeUsage(evtData.usage);
|
|
65
62
|
}
|
|
66
63
|
} else if (event === 'error') {
|
|
67
64
|
finishReason = 'error';
|
|
@@ -1,6 +1,34 @@
|
|
|
1
1
|
import { LanguageModelV2StreamPart, SharedV2ProviderMetadata } from '@ai-sdk/provider';
|
|
2
2
|
import { ChatEventType } from '@coze/api';
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* 上游 usage 字段兼容:官方 Coze v3 的 completed 事件为
|
|
6
|
+
* token_count/input_count/output_count(无 total_count),
|
|
7
|
+
* 总额按 total_count → token_count → input+output 的顺序取
|
|
8
|
+
*/
|
|
9
|
+
export const mapCozeUsage = (usage: any) => {
|
|
10
|
+
const inputTokens = usage?.input_count || 0;
|
|
11
|
+
const outputTokens = usage?.output_count || 0;
|
|
12
|
+
const totalTokens = usage?.total_count ?? usage?.token_count ?? inputTokens + outputTokens;
|
|
13
|
+
return { inputTokens, outputTokens, totalTokens };
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* 从消息 meta_data 提取 token 用量。上游会把本轮模型用量写入 answer 消息
|
|
18
|
+
* (含 workflow 用量消息)的 meta_data:token / input_tokens / output_tokens,
|
|
19
|
+
* 是 chat.completed 事件不带 usage 时(旧版上游)的兜底来源
|
|
20
|
+
*/
|
|
21
|
+
export const extractUsageFromMsgMeta = (meta: any) => {
|
|
22
|
+
if (!meta) return null;
|
|
23
|
+
const totalTokens = Number(meta.token);
|
|
24
|
+
if (!totalTokens) return null;
|
|
25
|
+
return {
|
|
26
|
+
inputTokens: Number(meta.input_tokens) || 0,
|
|
27
|
+
outputTokens: Number(meta.output_tokens) || 0,
|
|
28
|
+
totalTokens,
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
4
32
|
export const mcp2llmChunk = (part: any): LanguageModelV2StreamPart | null => {
|
|
5
33
|
const fullData = JSON.stringify(part);
|
|
6
34
|
|
|
@@ -64,11 +92,7 @@ export const mcp2llmChunk = (part: any): LanguageModelV2StreamPart | null => {
|
|
|
64
92
|
return {
|
|
65
93
|
type: 'finish',
|
|
66
94
|
finishReason: 'stop',
|
|
67
|
-
usage:
|
|
68
|
-
inputTokens: part.data.usage?.input_count || 0,
|
|
69
|
-
outputTokens: part.data.usage?.output_count || 0,
|
|
70
|
-
totalTokens: part.data.usage?.total_count || 0,
|
|
71
|
-
},
|
|
95
|
+
usage: mapCozeUsage(part.data.usage),
|
|
72
96
|
};
|
|
73
97
|
break;
|
|
74
98
|
|
|
@@ -77,11 +101,7 @@ export const mcp2llmChunk = (part: any): LanguageModelV2StreamPart | null => {
|
|
|
77
101
|
return {
|
|
78
102
|
type: 'finish',
|
|
79
103
|
finishReason: 'stop',
|
|
80
|
-
usage:
|
|
81
|
-
inputTokens: part.data.usage?.input_count || 0,
|
|
82
|
-
outputTokens: part.data.usage?.output_count || 0,
|
|
83
|
-
totalTokens: part.data.usage?.total_count || 0,
|
|
84
|
-
},
|
|
104
|
+
usage: mapCozeUsage(part.data.usage),
|
|
85
105
|
};
|
|
86
106
|
break;
|
|
87
107
|
|