@amux.ai/adapter-qwen 0.1.1

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/dist/index.cjs ADDED
@@ -0,0 +1,602 @@
1
+ 'use strict';
2
+
3
+ var llmBridge = require('@amux.ai/llm-bridge');
4
+
5
+ // src/inbound/request-parser.ts
6
+ function parseRequest(request) {
7
+ const req = request;
8
+ let system;
9
+ const messages = [];
10
+ for (const msg of req.messages) {
11
+ if (msg.role === "system") {
12
+ if (typeof msg.content === "string") {
13
+ system = system ? `${system}
14
+ ${msg.content}` : msg.content;
15
+ }
16
+ } else {
17
+ messages.push(parseMessage(msg));
18
+ }
19
+ }
20
+ const tools = req.tools?.map((tool) => parseTool(tool));
21
+ const toolChoice = req.tool_choice ? parseToolChoice(req.tool_choice) : void 0;
22
+ return {
23
+ messages,
24
+ model: req.model,
25
+ tools,
26
+ toolChoice,
27
+ stream: req.stream,
28
+ system,
29
+ generation: {
30
+ temperature: req.temperature,
31
+ topP: req.top_p,
32
+ maxTokens: req.max_tokens,
33
+ stopSequences: req.stop ? Array.isArray(req.stop) ? req.stop : [req.stop] : void 0,
34
+ presencePenalty: req.presence_penalty,
35
+ frequencyPenalty: req.frequency_penalty,
36
+ seed: req.seed,
37
+ responseFormat: req.response_format ? { type: req.response_format.type } : void 0,
38
+ // Qwen-specific: thinking mode
39
+ thinking: req.enable_thinking !== void 0 ? { enabled: req.enable_thinking } : void 0,
40
+ // Qwen-specific: web search
41
+ enableSearch: req.enable_search
42
+ },
43
+ // Store Qwen-specific extensions
44
+ extensions: req.fps !== void 0 ? { qwen: { fps: req.fps } } : void 0,
45
+ raw: request
46
+ };
47
+ }
48
+ function parseMessage(msg) {
49
+ return {
50
+ role: msg.role,
51
+ content: parseContent(msg.content),
52
+ name: msg.name,
53
+ toolCalls: msg.tool_calls,
54
+ toolCallId: msg.tool_call_id,
55
+ // Qwen-specific: reasoning content
56
+ reasoningContent: msg.reasoning_content
57
+ };
58
+ }
59
+ function parseContent(content) {
60
+ if (content === null || content === void 0) {
61
+ return "";
62
+ }
63
+ if (typeof content === "string") {
64
+ return content;
65
+ }
66
+ return content.map((part) => {
67
+ if (part.type === "text") {
68
+ return {
69
+ type: "text",
70
+ text: part.text
71
+ };
72
+ }
73
+ if (part.type === "image_url") {
74
+ const url = part.image_url.url;
75
+ if (url.startsWith("data:")) {
76
+ const match = url.match(/^data:([^;]+);base64,(.+)$/);
77
+ if (match) {
78
+ return {
79
+ type: "image",
80
+ source: {
81
+ type: "base64",
82
+ mediaType: match[1],
83
+ data: match[2]
84
+ }
85
+ };
86
+ }
87
+ }
88
+ return {
89
+ type: "image",
90
+ source: {
91
+ type: "url",
92
+ url
93
+ }
94
+ };
95
+ }
96
+ return {
97
+ type: "text",
98
+ text: JSON.stringify(part)
99
+ };
100
+ });
101
+ }
102
+ function parseTool(tool) {
103
+ return {
104
+ type: "function",
105
+ function: {
106
+ name: tool.function.name,
107
+ description: tool.function.description,
108
+ parameters: tool.function.parameters,
109
+ strict: tool.function.strict
110
+ }
111
+ };
112
+ }
113
+ function parseToolChoice(choice) {
114
+ if (typeof choice === "string") {
115
+ return choice;
116
+ }
117
+ return {
118
+ type: "function",
119
+ function: {
120
+ name: choice.function.name
121
+ }
122
+ };
123
+ }
124
+ function parseResponse(response) {
125
+ const res = response;
126
+ const choices = res.choices.map((choice) => ({
127
+ index: choice.index,
128
+ message: {
129
+ role: choice.message.role,
130
+ content: choice.message.content ?? "",
131
+ toolCalls: choice.message.tool_calls,
132
+ // Qwen-specific: reasoning content
133
+ reasoningContent: choice.message.reasoning_content
134
+ },
135
+ finishReason: llmBridge.mapFinishReason(choice.finish_reason)
136
+ }));
137
+ return {
138
+ id: res.id,
139
+ model: res.model,
140
+ choices,
141
+ created: res.created,
142
+ systemFingerprint: res.system_fingerprint,
143
+ usage: llmBridge.parseOpenAIUsage(res.usage),
144
+ raw: response
145
+ };
146
+ }
147
+
148
+ // src/inbound/stream-parser.ts
149
+ function mapFinishReason2(reason) {
150
+ const reasonMap = {
151
+ stop: "stop",
152
+ length: "length",
153
+ tool_calls: "tool_calls",
154
+ content_filter: "content_filter"
155
+ };
156
+ return reasonMap[reason] ?? "stop";
157
+ }
158
+ function parseStream(chunk) {
159
+ const data = chunk;
160
+ if (!data.choices || data.choices.length === 0) {
161
+ if (data.usage) {
162
+ return {
163
+ type: "end",
164
+ id: data.id,
165
+ model: data.model,
166
+ usage: {
167
+ promptTokens: data.usage.prompt_tokens,
168
+ completionTokens: data.usage.completion_tokens,
169
+ totalTokens: data.usage.total_tokens
170
+ },
171
+ raw: chunk
172
+ };
173
+ }
174
+ return null;
175
+ }
176
+ const choice = data.choices[0];
177
+ if (!choice) return null;
178
+ const delta = choice.delta;
179
+ const events = [];
180
+ if (choice.index === 0 && !delta.content && !delta.tool_calls && !delta.reasoning_content && !choice.finish_reason) {
181
+ return {
182
+ type: "start",
183
+ id: data.id,
184
+ model: data.model,
185
+ raw: chunk
186
+ };
187
+ }
188
+ if (delta.reasoning_content) {
189
+ events.push({
190
+ type: "reasoning",
191
+ id: data.id,
192
+ model: data.model,
193
+ reasoning: {
194
+ type: "reasoning",
195
+ delta: delta.reasoning_content,
196
+ index: choice.index
197
+ },
198
+ raw: chunk
199
+ });
200
+ }
201
+ if (delta.content) {
202
+ events.push({
203
+ type: "content",
204
+ id: data.id,
205
+ model: data.model,
206
+ content: {
207
+ type: "content",
208
+ delta: delta.content,
209
+ index: choice.index
210
+ },
211
+ raw: chunk
212
+ });
213
+ }
214
+ if (delta.tool_calls && delta.tool_calls.length > 0) {
215
+ const toolCall = delta.tool_calls[0];
216
+ if (toolCall) {
217
+ events.push({
218
+ type: "tool_call",
219
+ id: data.id,
220
+ model: data.model,
221
+ toolCall: {
222
+ type: "tool_call",
223
+ id: toolCall.id,
224
+ name: toolCall.function?.name,
225
+ arguments: toolCall.function?.arguments,
226
+ index: toolCall.index
227
+ },
228
+ raw: chunk
229
+ });
230
+ }
231
+ }
232
+ if (choice.finish_reason) {
233
+ events.push({
234
+ type: "end",
235
+ id: data.id,
236
+ model: data.model,
237
+ finishReason: mapFinishReason2(choice.finish_reason),
238
+ usage: data.usage ? {
239
+ promptTokens: data.usage.prompt_tokens,
240
+ completionTokens: data.usage.completion_tokens,
241
+ totalTokens: data.usage.total_tokens
242
+ } : void 0,
243
+ raw: chunk
244
+ });
245
+ }
246
+ if (events.length === 0) {
247
+ return null;
248
+ }
249
+ const firstEvent = events[0];
250
+ return events.length === 1 && firstEvent ? firstEvent : events;
251
+ }
252
+ function parseError(error) {
253
+ return llmBridge.parseOpenAICompatibleError(error);
254
+ }
255
+
256
+ // src/outbound/request-builder.ts
257
+ function buildRequest(ir) {
258
+ const messages = [];
259
+ if (ir.system) {
260
+ messages.push({
261
+ role: "system",
262
+ content: ir.system
263
+ });
264
+ }
265
+ for (const msg of ir.messages) {
266
+ messages.push({
267
+ role: msg.role,
268
+ content: buildContent(msg.content),
269
+ name: msg.name,
270
+ tool_calls: msg.toolCalls,
271
+ tool_call_id: msg.toolCallId,
272
+ // Qwen-specific: reasoning content
273
+ reasoning_content: msg.reasoningContent
274
+ });
275
+ }
276
+ const request = {
277
+ model: ir.model ?? "qwen-plus",
278
+ messages,
279
+ stream: ir.stream
280
+ };
281
+ if (ir.tools && ir.tools.length > 0) {
282
+ request.tools = ir.tools.map((tool) => ({
283
+ type: "function",
284
+ function: {
285
+ name: tool.function.name,
286
+ description: tool.function.description,
287
+ parameters: tool.function.parameters,
288
+ strict: tool.function.strict
289
+ }
290
+ }));
291
+ }
292
+ if (ir.toolChoice) {
293
+ request.tool_choice = ir.toolChoice;
294
+ }
295
+ if (ir.generation) {
296
+ if (ir.generation.temperature !== void 0) {
297
+ request.temperature = ir.generation.temperature;
298
+ }
299
+ if (ir.generation.topP !== void 0) {
300
+ request.top_p = ir.generation.topP;
301
+ }
302
+ if (ir.generation.maxTokens !== void 0) {
303
+ request.max_tokens = ir.generation.maxTokens;
304
+ }
305
+ if (ir.generation.stopSequences && ir.generation.stopSequences.length > 0) {
306
+ request.stop = ir.generation.stopSequences;
307
+ }
308
+ if (ir.generation.presencePenalty !== void 0) {
309
+ request.presence_penalty = ir.generation.presencePenalty;
310
+ }
311
+ if (ir.generation.frequencyPenalty !== void 0) {
312
+ request.frequency_penalty = ir.generation.frequencyPenalty;
313
+ }
314
+ if (ir.generation.seed !== void 0) {
315
+ request.seed = ir.generation.seed;
316
+ }
317
+ if (ir.generation.responseFormat) {
318
+ if (ir.generation.responseFormat.type === "json_object") {
319
+ request.response_format = { type: "json_object" };
320
+ }
321
+ }
322
+ if (ir.generation.thinking) {
323
+ request.enable_thinking = ir.generation.thinking.enabled;
324
+ }
325
+ if (ir.generation.enableSearch !== void 0) {
326
+ request.enable_search = ir.generation.enableSearch;
327
+ }
328
+ }
329
+ const qwenExt = ir.extensions?.qwen;
330
+ if (qwenExt?.fps !== void 0) {
331
+ request.fps = qwenExt.fps;
332
+ }
333
+ if (ir.stream) {
334
+ request.stream_options = { include_usage: true };
335
+ }
336
+ return request;
337
+ }
338
+ function buildContent(content) {
339
+ if (typeof content === "string") {
340
+ return content || null;
341
+ }
342
+ if (!content || content.length === 0) {
343
+ return null;
344
+ }
345
+ const allText = content.every((part) => part.type === "text");
346
+ if (allText) {
347
+ return content.map((part) => part.type === "text" ? part.text : "").join("");
348
+ }
349
+ return content.map((part) => {
350
+ if (part.type === "text") {
351
+ return { type: "text", text: part.text };
352
+ }
353
+ if (part.type === "image") {
354
+ const imgPart = part;
355
+ if (imgPart.source.type === "url") {
356
+ return {
357
+ type: "image_url",
358
+ image_url: { url: imgPart.source.url }
359
+ };
360
+ }
361
+ return {
362
+ type: "image_url",
363
+ image_url: {
364
+ url: `data:${imgPart.source.mediaType};base64,${imgPart.source.data}`
365
+ }
366
+ };
367
+ }
368
+ return { type: "text", text: JSON.stringify(part) };
369
+ });
370
+ }
371
+ function buildResponse(ir) {
372
+ return {
373
+ id: ir.id,
374
+ object: "chat.completion",
375
+ created: ir.created ?? Math.floor(Date.now() / 1e3),
376
+ model: ir.model,
377
+ system_fingerprint: ir.systemFingerprint,
378
+ choices: ir.choices.map((choice) => ({
379
+ index: choice.index,
380
+ message: {
381
+ role: choice.message.role,
382
+ content: llmBridge.contentToString(choice.message.content),
383
+ tool_calls: choice.message.toolCalls,
384
+ // Qwen-specific: reasoning content
385
+ reasoning_content: choice.message.reasoningContent
386
+ },
387
+ finish_reason: choice.finishReason ?? "stop"
388
+ })),
389
+ usage: ir.usage ? {
390
+ prompt_tokens: ir.usage.promptTokens,
391
+ completion_tokens: ir.usage.completionTokens,
392
+ total_tokens: ir.usage.totalTokens
393
+ } : void 0
394
+ };
395
+ }
396
+
397
+ // src/outbound/stream-builder.ts
398
+ function createStreamBuilder() {
399
+ let chunkId = `chatcmpl-${Date.now()}`;
400
+ let model = "";
401
+ let created = Math.floor(Date.now() / 1e3);
402
+ const toolCallsState = /* @__PURE__ */ new Map();
403
+ return {
404
+ process(event) {
405
+ const events = [];
406
+ if (event.id) chunkId = event.id;
407
+ if (event.model) model = event.model;
408
+ if (event.type === "start") {
409
+ events.push({
410
+ event: "data",
411
+ data: {
412
+ id: chunkId,
413
+ object: "chat.completion.chunk",
414
+ created,
415
+ model,
416
+ choices: [{
417
+ index: 0,
418
+ delta: { role: "assistant", content: "" },
419
+ finish_reason: null
420
+ }]
421
+ }
422
+ });
423
+ }
424
+ if (event.type === "content" && event.content?.delta) {
425
+ events.push({
426
+ event: "data",
427
+ data: {
428
+ id: chunkId,
429
+ object: "chat.completion.chunk",
430
+ created,
431
+ model,
432
+ choices: [{
433
+ index: 0,
434
+ delta: { content: event.content.delta },
435
+ finish_reason: null
436
+ }]
437
+ }
438
+ });
439
+ }
440
+ if (event.type === "reasoning" && event.reasoning?.delta) {
441
+ events.push({
442
+ event: "data",
443
+ data: {
444
+ id: chunkId,
445
+ object: "chat.completion.chunk",
446
+ created,
447
+ model,
448
+ choices: [{
449
+ index: 0,
450
+ delta: { reasoning_content: event.reasoning.delta },
451
+ finish_reason: null
452
+ }]
453
+ }
454
+ });
455
+ }
456
+ if (event.type === "tool_call" && event.toolCall) {
457
+ const toolIndex = event.toolCall.index ?? 0;
458
+ const toolCallDelta = { index: toolIndex };
459
+ if (event.toolCall.name) {
460
+ toolCallDelta.id = event.toolCall.id || `call_${Date.now()}_${toolIndex}`;
461
+ toolCallDelta.type = "function";
462
+ toolCallDelta.function = { name: event.toolCall.name };
463
+ toolCallsState.set(toolIndex, {
464
+ id: toolCallDelta.id,
465
+ name: event.toolCall.name
466
+ });
467
+ }
468
+ if (event.toolCall.arguments) {
469
+ toolCallDelta.function = {
470
+ ...toolCallDelta.function,
471
+ arguments: event.toolCall.arguments
472
+ };
473
+ }
474
+ events.push({
475
+ event: "data",
476
+ data: {
477
+ id: chunkId,
478
+ object: "chat.completion.chunk",
479
+ created,
480
+ model,
481
+ choices: [{
482
+ index: 0,
483
+ delta: { tool_calls: [toolCallDelta] },
484
+ finish_reason: null
485
+ }]
486
+ }
487
+ });
488
+ }
489
+ if (event.type === "end") {
490
+ const finishReason = mapFinishReason3(event.finishReason);
491
+ const finalChunk = {
492
+ id: chunkId,
493
+ object: "chat.completion.chunk",
494
+ created,
495
+ model,
496
+ choices: [{
497
+ index: 0,
498
+ delta: {},
499
+ finish_reason: finishReason
500
+ }]
501
+ };
502
+ if (event.usage) {
503
+ finalChunk.usage = {
504
+ prompt_tokens: event.usage.promptTokens ?? 0,
505
+ completion_tokens: event.usage.completionTokens ?? 0,
506
+ total_tokens: event.usage.totalTokens ?? 0
507
+ };
508
+ }
509
+ events.push({ event: "data", data: finalChunk });
510
+ }
511
+ if (event.type === "error" && event.error) {
512
+ events.push({
513
+ event: "data",
514
+ data: {
515
+ error: {
516
+ message: event.error.message,
517
+ type: "server_error",
518
+ code: event.error.code
519
+ }
520
+ }
521
+ });
522
+ }
523
+ return events;
524
+ },
525
+ finalize() {
526
+ return [{ event: "data", data: "[DONE]" }];
527
+ }
528
+ };
529
+ }
530
+ function mapFinishReason3(reason) {
531
+ if (!reason) return "stop";
532
+ const reasonMap = {
533
+ stop: "stop",
534
+ length: "length",
535
+ tool_calls: "tool_calls",
536
+ content_filter: "content_filter",
537
+ end_turn: "stop",
538
+ max_tokens: "length"
539
+ };
540
+ return reasonMap[reason] ?? "stop";
541
+ }
542
+
543
+ // src/adapter.ts
544
+ var qwenAdapter = {
545
+ name: "qwen",
546
+ version: "1.0.0",
547
+ capabilities: {
548
+ streaming: true,
549
+ tools: true,
550
+ vision: true,
551
+ multimodal: true,
552
+ // Supports images, audio, video
553
+ systemPrompt: true,
554
+ toolChoice: true,
555
+ reasoning: true,
556
+ // QwQ model supports reasoning
557
+ webSearch: true,
558
+ // Qwen supports web search
559
+ jsonMode: true,
560
+ logprobs: false,
561
+ seed: true
562
+ },
563
+ inbound: {
564
+ parseRequest: (request) => {
565
+ return parseRequest(request);
566
+ },
567
+ parseResponse: (response) => {
568
+ return parseResponse(response);
569
+ },
570
+ parseStream: (chunk) => {
571
+ return parseStream(chunk);
572
+ },
573
+ parseError: (error) => {
574
+ return parseError(error);
575
+ }
576
+ },
577
+ outbound: {
578
+ buildRequest: (ir) => {
579
+ return buildRequest(ir);
580
+ },
581
+ buildResponse: (ir) => {
582
+ return buildResponse(ir);
583
+ },
584
+ createStreamBuilder
585
+ },
586
+ getInfo() {
587
+ return {
588
+ name: this.name,
589
+ version: this.version,
590
+ capabilities: this.capabilities,
591
+ endpoint: {
592
+ baseUrl: "https://dashscope.aliyuncs.com/compatible-mode",
593
+ chatPath: "/v1/chat/completions",
594
+ modelsPath: "/v1/models"
595
+ }
596
+ };
597
+ }
598
+ };
599
+
600
+ exports.qwenAdapter = qwenAdapter;
601
+ //# sourceMappingURL=index.cjs.map
602
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/inbound/request-parser.ts","../src/inbound/response-parser.ts","../src/inbound/stream-parser.ts","../src/inbound/error-parser.ts","../src/outbound/request-builder.ts","../src/outbound/response-builder.ts","../src/outbound/stream-builder.ts","../src/adapter.ts"],"names":["mapFinishReason","parseOpenAIUsage","parseOpenAICompatibleError","contentToString"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n LLMRequestIR,\n Message,\n Tool,\n ToolChoice,\n ContentPart,\n TextContent,\n ImageContent,\n} from '@amux.ai/llm-bridge'\n\nimport type { QwenRequest, QwenMessage, QwenTool, QwenContentPart } from '../types'\n\n/**\n * Parse Qwen request to IR\n */\nexport function parseRequest(request: unknown): LLMRequestIR {\n const req = request as QwenRequest\n\n // Extract system message if present\n let system: string | undefined\n const messages: Message[] = []\n\n for (const msg of req.messages) {\n if (msg.role === 'system') {\n if (typeof msg.content === 'string') {\n system = system ? `${system}\\n${msg.content}` : msg.content\n }\n } else {\n messages.push(parseMessage(msg))\n }\n }\n\n // Parse tools\n const tools: Tool[] | undefined = req.tools?.map((tool) => parseTool(tool))\n\n // Parse tool choice\n const toolChoice: ToolChoice | undefined = req.tool_choice\n ? parseToolChoice(req.tool_choice)\n : undefined\n\n return {\n messages,\n model: req.model,\n tools,\n toolChoice,\n stream: req.stream,\n system,\n generation: {\n temperature: req.temperature,\n topP: req.top_p,\n maxTokens: req.max_tokens,\n stopSequences: req.stop\n ? Array.isArray(req.stop)\n ? req.stop\n : [req.stop]\n : undefined,\n presencePenalty: req.presence_penalty,\n frequencyPenalty: req.frequency_penalty,\n seed: req.seed,\n responseFormat: req.response_format\n ? { type: req.response_format.type }\n : undefined,\n // Qwen-specific: thinking mode\n thinking: req.enable_thinking !== undefined\n ? { enabled: req.enable_thinking }\n : undefined,\n // Qwen-specific: web search\n enableSearch: req.enable_search,\n },\n // Store Qwen-specific extensions\n extensions: req.fps !== undefined\n ? { qwen: { fps: req.fps } }\n : undefined,\n raw: request,\n }\n}\n\nfunction parseMessage(msg: QwenMessage): Message {\n return {\n role: msg.role,\n content: parseContent(msg.content),\n name: msg.name,\n toolCalls: msg.tool_calls,\n toolCallId: msg.tool_call_id,\n // Qwen-specific: reasoning content\n reasoningContent: msg.reasoning_content,\n }\n}\n\nfunction parseContent(\n content: string | QwenContentPart[] | null | undefined\n): string | ContentPart[] {\n if (content === null || content === undefined) {\n return ''\n }\n\n if (typeof content === 'string') {\n return content\n }\n\n return content.map((part): ContentPart => {\n if (part.type === 'text') {\n return {\n type: 'text',\n text: part.text,\n } as TextContent\n }\n\n if (part.type === 'image_url') {\n const url = part.image_url.url\n\n if (url.startsWith('data:')) {\n const match = url.match(/^data:([^;]+);base64,(.+)$/)\n if (match) {\n return {\n type: 'image',\n source: {\n type: 'base64',\n mediaType: match[1],\n data: match[2],\n },\n } as ImageContent\n }\n }\n\n return {\n type: 'image',\n source: {\n type: 'url',\n url: url,\n },\n } as ImageContent\n }\n\n // For audio, video, etc., store as text for now\n return {\n type: 'text',\n text: JSON.stringify(part),\n } as TextContent\n })\n}\n\nfunction parseTool(tool: QwenTool): Tool {\n return {\n type: 'function',\n function: {\n name: tool.function.name,\n description: tool.function.description,\n parameters: tool.function.parameters,\n strict: tool.function.strict,\n },\n }\n}\n\nfunction parseToolChoice(\n choice: 'auto' | 'none' | 'required' | { type: 'function'; function: { name: string } }\n): ToolChoice {\n if (typeof choice === 'string') {\n return choice as ToolChoice\n }\n return {\n type: 'function',\n function: {\n name: choice.function.name,\n },\n }\n}\n","import type { LLMResponseIR, Choice, Role } from '@amux.ai/llm-bridge'\nimport { mapFinishReason, parseOpenAIUsage } from '@amux.ai/llm-bridge'\n\nimport type { QwenResponse } from '../types'\n\n/**\n * Parse Qwen response to IR\n */\nexport function parseResponse(response: unknown): LLMResponseIR {\n const res = response as QwenResponse\n\n const choices: Choice[] = res.choices.map((choice) => ({\n index: choice.index,\n message: {\n role: choice.message.role as Role,\n content: choice.message.content ?? '',\n toolCalls: choice.message.tool_calls,\n // Qwen-specific: reasoning content\n reasoningContent: choice.message.reasoning_content,\n },\n finishReason: mapFinishReason(choice.finish_reason),\n }))\n\n return {\n id: res.id,\n model: res.model,\n choices,\n created: res.created,\n systemFingerprint: res.system_fingerprint,\n usage: parseOpenAIUsage(res.usage),\n raw: response,\n }\n}\n","import type { LLMStreamEvent, FinishReason } from '@amux.ai/llm-bridge'\n\nimport type { QwenStreamChunk } from '../types'\n\n/**\n * Map Qwen finish reason to IR finish reason\n */\nfunction mapFinishReason(reason: string): FinishReason {\n const reasonMap: Record<string, FinishReason> = {\n stop: 'stop',\n length: 'length',\n tool_calls: 'tool_calls',\n content_filter: 'content_filter',\n }\n return reasonMap[reason] ?? 'stop'\n}\n\n/**\n * Parse Qwen stream chunk to IR stream event\n */\nexport function parseStream(\n chunk: unknown\n): LLMStreamEvent | LLMStreamEvent[] | null {\n const data = chunk as QwenStreamChunk\n\n if (!data.choices || data.choices.length === 0) {\n // Check for usage-only chunk\n if (data.usage) {\n return {\n type: 'end',\n id: data.id,\n model: data.model,\n usage: {\n promptTokens: data.usage.prompt_tokens,\n completionTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n },\n raw: chunk,\n }\n }\n return null\n }\n\n const choice = data.choices[0]\n if (!choice) return null\n\n const delta = choice.delta\n const events: LLMStreamEvent[] = []\n\n // Start event (first chunk with role or empty delta at index 0)\n if (choice.index === 0 && !delta.content && !delta.tool_calls && !delta.reasoning_content && !choice.finish_reason) {\n return {\n type: 'start',\n id: data.id,\n model: data.model,\n raw: chunk,\n }\n }\n\n // Qwen-specific: Reasoning content delta\n if (delta.reasoning_content) {\n events.push({\n type: 'reasoning',\n id: data.id,\n model: data.model,\n reasoning: {\n type: 'reasoning',\n delta: delta.reasoning_content,\n index: choice.index,\n },\n raw: chunk,\n })\n }\n\n // Content delta\n if (delta.content) {\n events.push({\n type: 'content',\n id: data.id,\n model: data.model,\n content: {\n type: 'content',\n delta: delta.content,\n index: choice.index,\n },\n raw: chunk,\n })\n }\n\n // Tool call delta\n if (delta.tool_calls && delta.tool_calls.length > 0) {\n const toolCall = delta.tool_calls[0]\n if (toolCall) {\n events.push({\n type: 'tool_call',\n id: data.id,\n model: data.model,\n toolCall: {\n type: 'tool_call',\n id: toolCall.id,\n name: toolCall.function?.name,\n arguments: toolCall.function?.arguments,\n index: toolCall.index,\n },\n raw: chunk,\n })\n }\n }\n\n // End event\n if (choice.finish_reason) {\n events.push({\n type: 'end',\n id: data.id,\n model: data.model,\n finishReason: mapFinishReason(choice.finish_reason),\n usage: data.usage\n ? {\n promptTokens: data.usage.prompt_tokens,\n completionTokens: data.usage.completion_tokens,\n totalTokens: data.usage.total_tokens,\n }\n : undefined,\n raw: chunk,\n })\n }\n\n if (events.length === 0) {\n return null\n }\n\n const firstEvent = events[0]\n return events.length === 1 && firstEvent ? firstEvent : events\n}\n","import { parseOpenAICompatibleError } from '@amux.ai/llm-bridge'\nimport type { LLMErrorIR } from '@amux.ai/llm-bridge'\n\n/**\n * Parse Qwen error to IR\n */\nexport function parseError(error: unknown): LLMErrorIR {\n return parseOpenAICompatibleError(error)\n}\n","import type { LLMRequestIR, ContentPart, ImageContent } from '@amux.ai/llm-bridge'\n\nimport type { QwenRequest, QwenMessage, QwenContentPart } from '../types'\n\n/**\n * Build Qwen request from IR\n */\nexport function buildRequest(ir: LLMRequestIR): QwenRequest {\n const messages: QwenMessage[] = []\n\n // Add system message if present\n if (ir.system) {\n messages.push({\n role: 'system',\n content: ir.system,\n })\n }\n\n // Add conversation messages\n for (const msg of ir.messages) {\n messages.push({\n role: msg.role,\n content: buildContent(msg.content),\n name: msg.name,\n tool_calls: msg.toolCalls,\n tool_call_id: msg.toolCallId,\n // Qwen-specific: reasoning content\n reasoning_content: msg.reasoningContent,\n })\n }\n\n const request: QwenRequest = {\n model: ir.model ?? 'qwen-plus',\n messages,\n stream: ir.stream,\n }\n\n // Add tools if present\n if (ir.tools && ir.tools.length > 0) {\n request.tools = ir.tools.map((tool) => ({\n type: 'function',\n function: {\n name: tool.function.name,\n description: tool.function.description,\n parameters: tool.function.parameters,\n strict: tool.function.strict,\n },\n }))\n }\n\n // Add tool choice if present\n if (ir.toolChoice) {\n request.tool_choice = ir.toolChoice\n }\n\n // Add generation parameters\n if (ir.generation) {\n if (ir.generation.temperature !== undefined) {\n request.temperature = ir.generation.temperature\n }\n if (ir.generation.topP !== undefined) {\n request.top_p = ir.generation.topP\n }\n if (ir.generation.maxTokens !== undefined) {\n request.max_tokens = ir.generation.maxTokens\n }\n if (ir.generation.stopSequences && ir.generation.stopSequences.length > 0) {\n request.stop = ir.generation.stopSequences\n }\n if (ir.generation.presencePenalty !== undefined) {\n request.presence_penalty = ir.generation.presencePenalty\n }\n if (ir.generation.frequencyPenalty !== undefined) {\n request.frequency_penalty = ir.generation.frequencyPenalty\n }\n if (ir.generation.seed !== undefined) {\n request.seed = ir.generation.seed\n }\n if (ir.generation.responseFormat) {\n if (ir.generation.responseFormat.type === 'json_object') {\n request.response_format = { type: 'json_object' }\n }\n }\n // Qwen-specific: thinking mode\n if (ir.generation.thinking) {\n request.enable_thinking = ir.generation.thinking.enabled\n }\n // Qwen-specific: web search\n if (ir.generation.enableSearch !== undefined) {\n request.enable_search = ir.generation.enableSearch\n }\n }\n\n // Qwen-specific: fps for video\n const qwenExt = ir.extensions?.qwen as { fps?: number } | undefined\n if (qwenExt?.fps !== undefined) {\n request.fps = qwenExt.fps\n }\n\n // Add stream options for usage in streaming\n if (ir.stream) {\n request.stream_options = { include_usage: true }\n }\n\n return request\n}\n\nfunction buildContent(\n content: string | ContentPart[]\n): string | QwenContentPart[] | null {\n if (typeof content === 'string') {\n return content || null\n }\n\n if (!content || content.length === 0) {\n return null\n }\n\n // Check if all parts are text - if so, concatenate them\n const allText = content.every((part) => part.type === 'text')\n if (allText) {\n return content\n .map((part) => (part.type === 'text' ? part.text : ''))\n .join('')\n }\n\n // Build multimodal content\n return content.map((part): QwenContentPart => {\n if (part.type === 'text') {\n return { type: 'text', text: part.text }\n }\n\n if (part.type === 'image') {\n const imgPart = part as ImageContent\n if (imgPart.source.type === 'url') {\n return {\n type: 'image_url',\n image_url: { url: imgPart.source.url },\n }\n }\n return {\n type: 'image_url',\n image_url: {\n url: `data:${imgPart.source.mediaType};base64,${imgPart.source.data}`,\n },\n }\n }\n\n return { type: 'text', text: JSON.stringify(part) }\n })\n}\n","import type { LLMResponseIR } from '@amux.ai/llm-bridge'\nimport { contentToString } from '@amux.ai/llm-bridge'\n\nimport type { QwenResponse } from '../types'\n\n/**\n * Build Qwen response from IR\n */\nexport function buildResponse(ir: LLMResponseIR): QwenResponse {\n return {\n id: ir.id,\n object: 'chat.completion',\n created: ir.created ?? Math.floor(Date.now() / 1000),\n model: ir.model,\n system_fingerprint: ir.systemFingerprint,\n choices: ir.choices.map((choice) => ({\n index: choice.index,\n message: {\n role: choice.message.role,\n content: contentToString(choice.message.content),\n tool_calls: choice.message.toolCalls,\n // Qwen-specific: reasoning content\n reasoning_content: choice.message.reasoningContent,\n },\n finish_reason: choice.finishReason ?? 'stop',\n })),\n usage: ir.usage\n ? {\n prompt_tokens: ir.usage.promptTokens,\n completion_tokens: ir.usage.completionTokens,\n total_tokens: ir.usage.totalTokens,\n }\n : undefined,\n }\n}\n","import type { LLMStreamEvent, SSEEvent, StreamEventBuilder } from '@amux.ai/llm-bridge'\n\n/**\n * OpenAI stream event builder\n * Converts IR stream events to OpenAI SSE format\n *\n * OpenAI uses a simpler SSE format compared to Anthropic:\n * - All events use \"data:\" prefix (no event type)\n * - Each chunk contains the full delta structure\n * - Stream ends with \"data: [DONE]\"\n */\nexport function createStreamBuilder(): StreamEventBuilder {\n let chunkId = `chatcmpl-${Date.now()}`\n let model = ''\n let created = Math.floor(Date.now() / 1000)\n const toolCallsState: Map<number, { id: string; name: string }> = new Map()\n\n return {\n process(event: LLMStreamEvent): SSEEvent[] {\n const events: SSEEvent[] = []\n\n // Update metadata from event\n if (event.id) chunkId = event.id\n if (event.model) model = event.model\n\n // Handle start event\n if (event.type === 'start') {\n // OpenAI doesn't have a separate start event\n // The first content chunk serves as the start\n events.push({\n event: 'data',\n data: {\n id: chunkId,\n object: 'chat.completion.chunk',\n created,\n model,\n choices: [{\n index: 0,\n delta: { role: 'assistant', content: '' },\n finish_reason: null,\n }],\n },\n })\n }\n\n // Handle content delta\n if (event.type === 'content' && event.content?.delta) {\n events.push({\n event: 'data',\n data: {\n id: chunkId,\n object: 'chat.completion.chunk',\n created,\n model,\n choices: [{\n index: 0,\n delta: { content: event.content.delta },\n finish_reason: null,\n }],\n },\n })\n }\n\n // Handle reasoning delta (for Qwen QwQ model)\n if (event.type === 'reasoning' && event.reasoning?.delta) {\n // Qwen uses reasoning_content field for thinking process\n events.push({\n event: 'data',\n data: {\n id: chunkId,\n object: 'chat.completion.chunk',\n created,\n model,\n choices: [{\n index: 0,\n delta: { reasoning_content: event.reasoning.delta },\n finish_reason: null,\n }],\n },\n })\n }\n\n // Handle tool call\n if (event.type === 'tool_call' && event.toolCall) {\n const toolIndex = event.toolCall.index ?? 0\n const toolCallDelta: {\n index: number\n id?: string\n type?: string\n function?: { name?: string; arguments?: string }\n } = { index: toolIndex }\n\n // If this is a new tool call (has name)\n if (event.toolCall.name) {\n toolCallDelta.id = event.toolCall.id || `call_${Date.now()}_${toolIndex}`\n toolCallDelta.type = 'function'\n toolCallDelta.function = { name: event.toolCall.name }\n toolCallsState.set(toolIndex, {\n id: toolCallDelta.id,\n name: event.toolCall.name,\n })\n }\n\n // If this has arguments\n if (event.toolCall.arguments) {\n toolCallDelta.function = {\n ...toolCallDelta.function,\n arguments: event.toolCall.arguments,\n }\n }\n\n events.push({\n event: 'data',\n data: {\n id: chunkId,\n object: 'chat.completion.chunk',\n created,\n model,\n choices: [{\n index: 0,\n delta: { tool_calls: [toolCallDelta] },\n finish_reason: null,\n }],\n },\n })\n }\n\n // Handle end event\n if (event.type === 'end') {\n const finishReason = mapFinishReason(event.finishReason)\n\n // Emit final chunk with finish_reason\n const finalChunk: {\n id: string\n object: string\n created: number\n model: string\n choices: Array<{\n index: number\n delta: Record<string, never>\n finish_reason: string\n }>\n usage?: {\n prompt_tokens: number\n completion_tokens: number\n total_tokens: number\n }\n } = {\n id: chunkId,\n object: 'chat.completion.chunk',\n created,\n model,\n choices: [{\n index: 0,\n delta: {},\n finish_reason: finishReason,\n }],\n }\n\n // Include usage if available\n if (event.usage) {\n finalChunk.usage = {\n prompt_tokens: event.usage.promptTokens ?? 0,\n completion_tokens: event.usage.completionTokens ?? 0,\n total_tokens: event.usage.totalTokens ?? 0,\n }\n }\n\n events.push({ event: 'data', data: finalChunk })\n }\n\n // Handle error event\n if (event.type === 'error' && event.error) {\n events.push({\n event: 'data',\n data: {\n error: {\n message: event.error.message,\n type: 'server_error',\n code: event.error.code,\n },\n },\n })\n }\n\n return events\n },\n\n finalize(): SSEEvent[] {\n // OpenAI streams end with [DONE]\n return [{ event: 'data', data: '[DONE]' }]\n },\n }\n}\n\n/**\n * Map IR finish reason to OpenAI finish reason\n */\nfunction mapFinishReason(reason?: string): string {\n if (!reason) return 'stop'\n\n const reasonMap: Record<string, string> = {\n stop: 'stop',\n length: 'length',\n tool_calls: 'tool_calls',\n content_filter: 'content_filter',\n end_turn: 'stop',\n max_tokens: 'length',\n }\n\n return reasonMap[reason] ?? 'stop'\n}\n","import type {\n LLMAdapter,\n LLMRequestIR,\n LLMResponseIR,\n LLMStreamEvent,\n LLMErrorIR,\n AdapterInfo,\n} from '@amux.ai/llm-bridge'\n\nimport { parseRequest } from './inbound/request-parser'\nimport { parseResponse } from './inbound/response-parser'\nimport { parseStream } from './inbound/stream-parser'\nimport { parseError } from './inbound/error-parser'\nimport { buildRequest } from './outbound/request-builder'\nimport { buildResponse } from './outbound/response-builder'\nimport { createStreamBuilder } from './outbound/stream-builder'\n\n/**\n * Qwen (通义千问) adapter implementation\n * Handles Qwen-specific features like enable_thinking, enable_search, and multimodal\n */\nexport const qwenAdapter: LLMAdapter = {\n name: 'qwen',\n version: '1.0.0',\n capabilities: {\n streaming: true,\n tools: true,\n vision: true,\n multimodal: true, // Supports images, audio, video\n systemPrompt: true,\n toolChoice: true,\n reasoning: true, // QwQ model supports reasoning\n webSearch: true, // Qwen supports web search\n jsonMode: true,\n logprobs: false,\n seed: true,\n },\n\n inbound: {\n parseRequest: (request: unknown): LLMRequestIR => {\n return parseRequest(request)\n },\n\n parseResponse: (response: unknown): LLMResponseIR => {\n return parseResponse(response)\n },\n\n parseStream: (chunk: unknown): LLMStreamEvent | LLMStreamEvent[] | null => {\n return parseStream(chunk)\n },\n\n parseError: (error: unknown): LLMErrorIR => {\n return parseError(error)\n },\n },\n\n outbound: {\n buildRequest: (ir: LLMRequestIR): unknown => {\n return buildRequest(ir)\n },\n\n buildResponse: (ir: LLMResponseIR): unknown => {\n return buildResponse(ir)\n },\n\n createStreamBuilder,\n },\n\n getInfo(): AdapterInfo {\n return {\n name: this.name,\n version: this.version,\n capabilities: this.capabilities,\n endpoint: {\n baseUrl: 'https://dashscope.aliyuncs.com/compatible-mode',\n chatPath: '/v1/chat/completions',\n modelsPath: '/v1/models',\n },\n }\n },\n}\n"]}