ai-protocol-adapters 1.0.0-alpha.4 → 1.0.0-alpha.7

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.d.mts CHANGED
@@ -38,6 +38,7 @@ interface ConversionResult$2 {
38
38
  declare class StreamingProtocolAdapter {
39
39
  private config;
40
40
  constructor(options?: StreamingProtocolAdapterOptions);
41
+ private logDebug;
41
42
  /**
42
43
  * 转换Anthropic请求为OpenAI格式
43
44
  */
@@ -61,9 +62,17 @@ declare class StreamingProtocolAdapter {
61
62
  */
62
63
  private processStreamChunk;
63
64
  /**
64
- * 处理工具调用
65
+ * 处理工具调用 - 支持OpenAI流式分块累积
66
+ * OpenAI流式API会将tool_calls分多个chunk发送:
67
+ * - Chunk 1: {index:0, id:"call_xxx", type:"function", function:{name:"web_search"}}
68
+ * - Chunk 2: {index:0, function:{arguments:"{\"query\":\"xxx\"}"}}
69
+ * - Chunk N: 继续累积arguments
65
70
  */
66
71
  private processToolCalls;
72
+ /**
73
+ * 在流结束时关闭所有未关闭的工具调用块
74
+ */
75
+ private closeAllToolCallBlocks;
67
76
  /**
68
77
  * 添加最终事件 - 支持thinking+content双模式
69
78
  */
@@ -5757,6 +5766,7 @@ declare class StandardProtocolAdapter {
5757
5766
  private debugMode;
5758
5767
  private sseAdapter;
5759
5768
  constructor(options?: StandardProtocolAdapterOptions);
5769
+ private logDebug;
5760
5770
  /**
5761
5771
  * 转换Anthropic请求为OpenAI请求格式
5762
5772
  * @param anthropicRequest - Anthropic格式的请求
package/dist/index.d.ts CHANGED
@@ -38,6 +38,7 @@ interface ConversionResult$2 {
38
38
  declare class StreamingProtocolAdapter {
39
39
  private config;
40
40
  constructor(options?: StreamingProtocolAdapterOptions);
41
+ private logDebug;
41
42
  /**
42
43
  * 转换Anthropic请求为OpenAI格式
43
44
  */
@@ -61,9 +62,17 @@ declare class StreamingProtocolAdapter {
61
62
  */
62
63
  private processStreamChunk;
63
64
  /**
64
- * 处理工具调用
65
+ * 处理工具调用 - 支持OpenAI流式分块累积
66
+ * OpenAI流式API会将tool_calls分多个chunk发送:
67
+ * - Chunk 1: {index:0, id:"call_xxx", type:"function", function:{name:"web_search"}}
68
+ * - Chunk 2: {index:0, function:{arguments:"{\"query\":\"xxx\"}"}}
69
+ * - Chunk N: 继续累积arguments
65
70
  */
66
71
  private processToolCalls;
72
+ /**
73
+ * 在流结束时关闭所有未关闭的工具调用块
74
+ */
75
+ private closeAllToolCallBlocks;
67
76
  /**
68
77
  * 添加最终事件 - 支持thinking+content双模式
69
78
  */
@@ -5757,6 +5766,7 @@ declare class StandardProtocolAdapter {
5757
5766
  private debugMode;
5758
5767
  private sseAdapter;
5759
5768
  constructor(options?: StandardProtocolAdapterOptions);
5769
+ private logDebug;
5760
5770
  /**
5761
5771
  * 转换Anthropic请求为OpenAI请求格式
5762
5772
  * @param anthropicRequest - Anthropic格式的请求
package/dist/index.js CHANGED
@@ -518,6 +518,11 @@ var StreamingProtocolAdapter = class {
518
518
  logger: options.logger ?? getGlobalLogger()
519
519
  };
520
520
  }
521
+ logDebug(message, meta) {
522
+ if (this.config.debugMode) {
523
+ this.config.logger.debug(message, meta);
524
+ }
525
+ }
521
526
  /**
522
527
  * 转换Anthropic请求为OpenAI格式
523
528
  */
@@ -626,6 +631,14 @@ var StreamingProtocolAdapter = class {
626
631
  */
627
632
  processStreamChunk(chunk, state, sseLines) {
628
633
  const choice = chunk.choices?.[0];
634
+ if (choice) {
635
+ const hasToolCalls = choice.delta?.tool_calls;
636
+ const hasFinishReason = choice.finish_reason;
637
+ const isNonText = !choice.delta?.content;
638
+ if (this.config.debugMode && (hasToolCalls || hasFinishReason || isNonText && choice.delta)) {
639
+ this.logDebug("Streaming chunk processed", { chunk });
640
+ }
641
+ }
629
642
  if (!choice) return;
630
643
  const delta = choice.delta;
631
644
  if (delta.reasoning_content) {
@@ -683,37 +696,81 @@ var StreamingProtocolAdapter = class {
683
696
  }
684
697
  }
685
698
  /**
686
- * 处理工具调用
699
+ * 处理工具调用 - 支持OpenAI流式分块累积
700
+ * OpenAI流式API会将tool_calls分多个chunk发送:
701
+ * - Chunk 1: {index:0, id:"call_xxx", type:"function", function:{name:"web_search"}}
702
+ * - Chunk 2: {index:0, function:{arguments:"{\"query\":\"xxx\"}"}}
703
+ * - Chunk N: 继续累积arguments
687
704
  */
688
705
  processToolCalls(toolCalls, state, sseLines) {
706
+ this.logDebug("processToolCalls called", { toolCalls });
689
707
  for (const toolCall of toolCalls) {
690
- if (toolCall.id && toolCall.function?.name) {
691
- const toolArgs = toolCall.function.arguments || "";
692
- const toolData = {
693
- id: toolCall.id,
694
- name: toolCall.function.name,
695
- input: toolArgs
708
+ const index = toolCall.index ?? 0;
709
+ const toolId = toolCall.id;
710
+ const toolName = toolCall.function?.name;
711
+ const toolArgs = toolCall.function?.arguments;
712
+ this.logDebug(`Processing tool chunk for index ${index}`, {
713
+ hasId: !!toolId,
714
+ hasName: !!toolName,
715
+ hasArgs: !!toolArgs,
716
+ argsLength: toolArgs?.length
717
+ });
718
+ const stateKey = `tool_${index}`;
719
+ let toolData = state.toolCallsMap.get(stateKey);
720
+ if (!toolData) {
721
+ toolData = {
722
+ id: toolId || "",
723
+ name: toolName || "",
724
+ input: "",
725
+ blockStartSent: false,
726
+ blockStopSent: false
696
727
  };
697
- state.toolCallsMap.set(toolCall.id, toolData);
728
+ state.toolCallsMap.set(stateKey, toolData);
729
+ } else {
730
+ if (toolId) toolData.id = toolId;
731
+ if (toolName) toolData.name = toolName;
732
+ }
733
+ if (toolArgs) {
734
+ toolData.input += toolArgs;
735
+ this.logDebug(`Accumulated tool arguments for index ${index}`, {
736
+ currentLength: toolData.input.length
737
+ });
738
+ }
739
+ if (toolData.id && toolData.name && !toolData.blockStartSent) {
698
740
  const blockIndex = state.completedToolCalls.length + 1;
741
+ toolData.blockIndex = blockIndex;
699
742
  sseLines.push(
700
743
  "event: content_block_start",
701
- `data: {"type":"content_block_start","index":${blockIndex},"content_block":{"type":"tool_use","id":"${toolCall.id}","name":"${toolCall.function.name}","input":{}}}`,
744
+ `data: {"type":"content_block_start","index":${blockIndex},"content_block":{"type":"tool_use","id":"${toolData.id}","name":"${toolData.name}","input":{}}}`,
702
745
  ""
703
746
  );
704
- if (toolArgs) {
705
- sseLines.push(
706
- "event: content_block_delta",
707
- `data: {"type":"content_block_delta","index":${blockIndex},"delta":{"type":"input_json_delta","partial_json":${JSON.stringify(toolArgs)}}}`,
708
- ""
709
- );
710
- }
747
+ toolData.blockStartSent = true;
748
+ this.logDebug("Sent content_block_start", { toolName: toolData.name, blockIndex });
749
+ }
750
+ if (toolArgs && toolData.blockStartSent && toolData.blockIndex !== void 0) {
751
+ sseLines.push(
752
+ "event: content_block_delta",
753
+ `data: {"type":"content_block_delta","index":${toolData.blockIndex},"delta":{"type":"input_json_delta","partial_json":${JSON.stringify(toolArgs)}}}`,
754
+ ""
755
+ );
756
+ this.logDebug("Sent input_json_delta", { blockIndex: toolData.blockIndex });
757
+ }
758
+ }
759
+ }
760
+ /**
761
+ * 在流结束时关闭所有未关闭的工具调用块
762
+ */
763
+ closeAllToolCallBlocks(state, sseLines) {
764
+ for (const [key, toolData] of state.toolCallsMap.entries()) {
765
+ if (toolData.blockStartSent && !toolData.blockStopSent && toolData.blockIndex !== void 0) {
711
766
  sseLines.push(
712
767
  "event: content_block_stop",
713
- `data: {"type":"content_block_stop","index":${blockIndex}}`,
768
+ `data: {"type":"content_block_stop","index":${toolData.blockIndex}}`,
714
769
  ""
715
770
  );
716
- state.completedToolCalls.push(toolCall.id);
771
+ toolData.blockStopSent = true;
772
+ state.completedToolCalls.push(toolData.id);
773
+ this.logDebug("Sent content_block_stop", { toolName: toolData.name, blockIndex: toolData.blockIndex });
717
774
  }
718
775
  }
719
776
  }
@@ -721,6 +778,7 @@ var StreamingProtocolAdapter = class {
721
778
  * 添加最终事件 - 支持thinking+content双模式
722
779
  */
723
780
  addFinalEvents(state, sseLines) {
781
+ this.closeAllToolCallBlocks(state, sseLines);
724
782
  if (state.contentBlockStarted) {
725
783
  const blockIndex = state.thinkingBlockStarted ? 1 : 0;
726
784
  sseLines.push(
@@ -958,6 +1016,14 @@ var MessageConverter = class {
958
1016
  * 使用tool_use_id溯回工具名称解决unknown_tool问题
959
1017
  */
960
1018
  static convertMessages(messages, system) {
1019
+ const debugEnabled = process.env.AI_PROTOCOL_DEBUG === "true";
1020
+ if (debugEnabled) {
1021
+ if (system !== void 0) {
1022
+ console.debug("[MessageConverter] convertMessages called with system:", JSON.stringify(system, null, 2));
1023
+ } else {
1024
+ console.debug("[MessageConverter] convertMessages called WITHOUT system parameter");
1025
+ }
1026
+ }
961
1027
  const context = this.createConversionContext(messages);
962
1028
  const convertedMessages = [];
963
1029
  for (const msg of messages) {
@@ -976,8 +1042,15 @@ var MessageConverter = class {
976
1042
  const systemMessage = this.processSystemMessage(system);
977
1043
  if (systemMessage) {
978
1044
  convertedMessages.unshift(systemMessage);
1045
+ if (debugEnabled) {
1046
+ console.debug("[MessageConverter] System message added to messages array at index 0");
1047
+ }
979
1048
  }
980
1049
  }
1050
+ if (debugEnabled) {
1051
+ console.debug("[MessageConverter] Final converted messages count:", convertedMessages.length);
1052
+ console.debug("[MessageConverter] First message:", JSON.stringify(convertedMessages[0], null, 2));
1053
+ }
981
1054
  return convertedMessages;
982
1055
  }
983
1056
  /**
@@ -4274,25 +4347,31 @@ var ToolCallProcessor = class _ToolCallProcessor {
4274
4347
  * 处理增量工具调用
4275
4348
  */
4276
4349
  static processIncrementalToolCalls(toolCalls, state, sseLines) {
4277
- console.log("\u{1F50D}\u{1F50D}\u{1F50D} [ToolProcessor] processIncrementalToolCalls called with:", JSON.stringify(toolCalls, null, 2));
4350
+ const debugEnabled = process.env.AI_PROTOCOL_DEBUG === "true";
4351
+ if (debugEnabled) {
4352
+ console.debug("[ToolProcessor] processIncrementalToolCalls called with:", JSON.stringify(toolCalls, null, 2));
4353
+ }
4278
4354
  for (const toolCall of toolCalls) {
4279
4355
  const toolId = toolCall.id;
4280
4356
  const toolName = toolCall.function?.name;
4281
4357
  const toolArgs = toolCall.function?.arguments;
4282
- console.log("\u{1F50D} [ToolProcessor] Processing tool call:", {
4283
- toolId,
4284
- toolName,
4285
- toolArgs: toolArgs || "UNDEFINED",
4286
- toolArgsType: typeof toolArgs,
4287
- toolArgsLength: toolArgs?.length || 0,
4288
- hasArgs: !!toolArgs
4289
- });
4358
+ if (debugEnabled) {
4359
+ console.debug("[ToolProcessor] Processing tool call:", {
4360
+ toolId,
4361
+ toolName,
4362
+ hasArgs: !!toolArgs
4363
+ });
4364
+ }
4290
4365
  if (toolName && toolId && !state.toolCallsMap.has(toolId)) {
4291
- console.log("\u2705 [ToolProcessor] Starting new tool call:", toolName);
4366
+ if (debugEnabled) {
4367
+ console.debug("[ToolProcessor] Starting new tool call:", toolName);
4368
+ }
4292
4369
  _ToolCallProcessor.processToolCallStart(toolId, toolName, state, sseLines);
4293
4370
  }
4294
4371
  if (toolArgs) {
4295
- console.log("\u2705 [ToolProcessor] Processing tool args, calling processToolArgs");
4372
+ if (debugEnabled) {
4373
+ console.debug("[ToolProcessor] Processing tool args, calling processToolArgs");
4374
+ }
4296
4375
  _ToolCallProcessor.processToolArgs(toolId, toolArgs, state, sseLines);
4297
4376
  } else {
4298
4377
  console.warn("\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F [ToolProcessor] No tool args to process! This will result in empty input!");
@@ -4303,25 +4382,31 @@ var ToolCallProcessor = class _ToolCallProcessor {
4303
4382
  * 处理工具调用
4304
4383
  */
4305
4384
  static processBatchToolCalls(toolCalls, state, sseLines) {
4306
- console.log("\u{1F50D}\u{1F50D}\u{1F50D} [ToolProcessor] processBatchToolCalls called with:", JSON.stringify(toolCalls, null, 2));
4385
+ const debugEnabled = process.env.AI_PROTOCOL_DEBUG === "true";
4386
+ if (debugEnabled) {
4387
+ console.debug("[ToolProcessor] processBatchToolCalls called with:", JSON.stringify(toolCalls, null, 2));
4388
+ }
4307
4389
  for (const toolCall of toolCalls) {
4308
4390
  const toolId = toolCall.id;
4309
4391
  const toolName = toolCall.function?.name;
4310
4392
  const toolArgs = toolCall.function?.arguments;
4311
- console.log("\u{1F50D} [ToolProcessor] Processing batch tool call:", {
4312
- toolId,
4313
- toolName,
4314
- toolArgs: toolArgs || "UNDEFINED",
4315
- toolArgsType: typeof toolArgs,
4316
- toolArgsLength: toolArgs?.length || 0,
4317
- hasArgs: !!toolArgs
4318
- });
4393
+ if (debugEnabled) {
4394
+ console.debug("[ToolProcessor] Processing batch tool call:", {
4395
+ toolId,
4396
+ toolName,
4397
+ hasArgs: !!toolArgs
4398
+ });
4399
+ }
4319
4400
  if (toolName && toolId && !state.toolCallsMap.has(toolId)) {
4320
- console.log("\u2705 [ToolProcessor] Starting new batch tool call:", toolName);
4401
+ if (debugEnabled) {
4402
+ console.debug("[ToolProcessor] Starting new batch tool call:", toolName);
4403
+ }
4321
4404
  _ToolCallProcessor.processToolCallStart(toolId, toolName, state, sseLines);
4322
4405
  }
4323
4406
  if (toolArgs) {
4324
- console.log("\u2705 [ToolProcessor] Processing batch tool args, calling processToolArgs");
4407
+ if (debugEnabled) {
4408
+ console.debug("[ToolProcessor] Processing batch tool args, calling processToolArgs");
4409
+ }
4325
4410
  _ToolCallProcessor.processToolArgs(toolId, toolArgs, state, sseLines);
4326
4411
  } else {
4327
4412
  console.warn("\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F [ToolProcessor] No batch tool args to process! This will result in empty input!");
@@ -5225,9 +5310,14 @@ var O2ASSEAdapterStatic = {
5225
5310
  // src/core/standard/standard-protocol-adapter.ts
5226
5311
  var StandardProtocolAdapter = class {
5227
5312
  constructor(options = {}) {
5228
- this.debugMode = options.debugMode !== void 0 ? options.debugMode : true;
5313
+ this.debugMode = options.debugMode ?? process.env.AI_PROTOCOL_DEBUG === "true";
5229
5314
  this.sseAdapter = new O2ASSEAdapter(this.debugMode);
5230
5315
  }
5316
+ logDebug(message, meta) {
5317
+ if (this.debugMode) {
5318
+ console.debug(message, meta ?? "");
5319
+ }
5320
+ }
5231
5321
  /**
5232
5322
  * 转换Anthropic请求为OpenAI请求格式
5233
5323
  * @param anthropicRequest - Anthropic格式的请求
@@ -5251,7 +5341,7 @@ var StandardProtocolAdapter = class {
5251
5341
  */
5252
5342
  convertFromStreamToStandard(openaiRawStream, modelName, messageId) {
5253
5343
  if (this.debugMode) {
5254
- console.log("\u{1F504} [StandardProtocolAdapter] convertFromStreamToStandard \u5F00\u59CB\u5904\u7406:", {
5344
+ this.logDebug("\u{1F504} [StandardProtocolAdapter] convertFromStreamToStandard \u5F00\u59CB\u5904\u7406:", {
5255
5345
  rawStreamLength: openaiRawStream.length,
5256
5346
  modelName,
5257
5347
  messageId,
@@ -5260,14 +5350,14 @@ var StandardProtocolAdapter = class {
5260
5350
  }
5261
5351
  const sseResult = this.sseAdapter.convertToClaudeSSE(openaiRawStream, modelName, messageId);
5262
5352
  if (this.debugMode) {
5263
- console.log("\u{1F504} [StandardProtocolAdapter] SSE\u8F6C\u6362\u5B8C\u6210:", {
5353
+ this.logDebug("\u{1F504} [StandardProtocolAdapter] SSE\u8F6C\u6362\u5B8C\u6210:", {
5264
5354
  sseResultLength: sseResult.length,
5265
5355
  ssePreview: sseResult.substring(0, 500)
5266
5356
  });
5267
5357
  }
5268
5358
  const standardResponse = this.extractStandardResponseFromSSE(sseResult, modelName, messageId);
5269
5359
  if (this.debugMode) {
5270
- console.log("\u{1F504} [StandardProtocolAdapter] \u6807\u51C6\u54CD\u5E94\u63D0\u53D6\u5B8C\u6210:", {
5360
+ this.logDebug("\u{1F504} [StandardProtocolAdapter] \u6807\u51C6\u54CD\u5E94\u63D0\u53D6\u5B8C\u6210:", {
5271
5361
  contentLength: standardResponse.content.length,
5272
5362
  usage: standardResponse.usage,
5273
5363
  stopReason: standardResponse.stop_reason
@@ -5282,7 +5372,7 @@ var StandardProtocolAdapter = class {
5282
5372
  const lines = sseContent.split("\n");
5283
5373
  const finalMessageId = messageId || generateMessageId();
5284
5374
  if (this.debugMode) {
5285
- console.log("\u{1F50D} [StandardProtocolAdapter] extractStandardResponseFromSSE \u5F00\u59CB\u89E3\u6790:", {
5375
+ this.logDebug("\u{1F50D} [StandardProtocolAdapter] extractStandardResponseFromSSE \u5F00\u59CB\u89E3\u6790:", {
5286
5376
  totalLines: lines.length,
5287
5377
  messageId: finalMessageId
5288
5378
  });
@@ -5337,25 +5427,28 @@ var StandardProtocolAdapter = class {
5337
5427
  if (data.type === "content_block_delta" && data.delta?.type === "text_delta") {
5338
5428
  currentTextContent += data.delta.text;
5339
5429
  if (this.debugMode && currentTextContent.length % 50 === 0) {
5340
- console.log(`\u{1F4DD} [StandardProtocolAdapter] \u7D2F\u79EF\u6587\u672C\u5185\u5BB9 (${currentTextContent.length}\u5B57\u7B26):`, currentTextContent.substring(currentTextContent.length - 20));
5430
+ this.logDebug(`\u{1F4DD} [StandardProtocolAdapter] \u7D2F\u79EF\u6587\u672C\u5185\u5BB9 (${currentTextContent.length}\u5B57\u7B26)`, currentTextContent.substring(currentTextContent.length - 20));
5341
5431
  }
5342
5432
  }
5343
5433
  if (data.type === "content_block_delta" && data.delta?.type === "input_json_delta") {
5344
5434
  const toolIndex = data.index;
5345
5435
  const toolId = indexToToolId.get(toolIndex);
5346
- console.log(`\u{1F527}\u{1F527}\u{1F527} [StandardProtocolAdapter] \u68C0\u6D4B\u5230input_json_delta\u4E8B\u4EF6\uFF01`, {
5347
- toolIndex,
5348
- toolId: toolId || "NOT_FOUND",
5349
- delta: data.delta.partial_json
5350
- });
5436
+ if (this.debugMode) {
5437
+ this.logDebug(`\u{1F527}\u{1F527}\u{1F527} [StandardProtocolAdapter] \u68C0\u6D4B\u5230input_json_delta\u4E8B\u4EF6\uFF01`, {
5438
+ toolIndex,
5439
+ toolId: toolId || "NOT_FOUND",
5440
+ delta: data.delta.partial_json
5441
+ });
5442
+ }
5351
5443
  if (toolId) {
5352
5444
  const currentBuffer = toolInputBuffers.get(toolIndex) || "";
5353
5445
  const newBuffer = currentBuffer + data.delta.partial_json;
5354
5446
  toolInputBuffers.set(toolIndex, newBuffer);
5355
- console.log(`\u{1F527} [StandardProtocolAdapter] \u7D2F\u79EF\u5DE5\u5177\u53C2\u6570 (index=${toolIndex}, id=${toolId}):`, {
5356
- delta: data.delta.partial_json,
5357
- bufferLength: newBuffer.length
5358
- });
5447
+ if (this.debugMode) {
5448
+ this.logDebug(`\u{1F527} [StandardProtocolAdapter] \u7D2F\u79EF\u5DE5\u5177\u53C2\u6570 (index=${toolIndex}, id=${toolId})`, {
5449
+ bufferLength: newBuffer.length
5450
+ });
5451
+ }
5359
5452
  } else {
5360
5453
  console.warn(`\u26A0\uFE0F [StandardProtocolAdapter] \u627E\u4E0D\u5230toolId for index=${toolIndex}`);
5361
5454
  }
@@ -5371,7 +5464,7 @@ var StandardProtocolAdapter = class {
5371
5464
  const parsedInput = JSON.parse(jsonBuffer);
5372
5465
  tool.input = parsedInput;
5373
5466
  if (this.debugMode) {
5374
- console.log(`\u2705 [StandardProtocolAdapter] \u5DE5\u5177\u53C2\u6570\u89E3\u6790\u5B8C\u6210 (index=${toolIndex}, id=${toolId}):`, parsedInput);
5467
+ this.logDebug(`\u2705 [StandardProtocolAdapter] \u5DE5\u5177\u53C2\u6570\u89E3\u6790\u5B8C\u6210 (index=${toolIndex}, id=${toolId})`, parsedInput);
5375
5468
  }
5376
5469
  } catch (parseError) {
5377
5470
  console.warn(`\u26A0\uFE0F [StandardProtocolAdapter] \u5DE5\u5177\u53C2\u6570JSON\u89E3\u6790\u5931\u8D25 (index=${toolIndex}, id=${toolId}):`, {
@@ -5389,7 +5482,7 @@ var StandardProtocolAdapter = class {
5389
5482
  if (data.usage) {
5390
5483
  response.usage = data.usage;
5391
5484
  if (this.debugMode) {
5392
- console.log("\u{1F4CA} [StandardProtocolAdapter] \u66F4\u65B0usage\u4FE1\u606F:", data.usage);
5485
+ this.logDebug("\u{1F4CA} [StandardProtocolAdapter] \u66F4\u65B0usage\u4FE1\u606F:", data.usage);
5393
5486
  }
5394
5487
  }
5395
5488
  }
@@ -5409,7 +5502,7 @@ var StandardProtocolAdapter = class {
5409
5502
  }
5410
5503
  response.content.push(...Array.from(toolCalls.values()));
5411
5504
  if (this.debugMode) {
5412
- console.log("\u2705 [StandardProtocolAdapter] \u6807\u51C6\u54CD\u5E94\u6784\u5EFA\u5B8C\u6210:", {
5505
+ this.logDebug("\u2705 [StandardProtocolAdapter] \u6807\u51C6\u54CD\u5E94\u6784\u5EFA\u5B8C\u6210:", {
5413
5506
  contentCount: response.content.length,
5414
5507
  textLength: currentTextContent.length,
5415
5508
  toolCallsCount: toolCalls.size,
package/dist/index.mjs CHANGED
@@ -411,6 +411,11 @@ var StreamingProtocolAdapter = class {
411
411
  logger: options.logger ?? getGlobalLogger()
412
412
  };
413
413
  }
414
+ logDebug(message, meta) {
415
+ if (this.config.debugMode) {
416
+ this.config.logger.debug(message, meta);
417
+ }
418
+ }
414
419
  /**
415
420
  * 转换Anthropic请求为OpenAI格式
416
421
  */
@@ -519,6 +524,14 @@ var StreamingProtocolAdapter = class {
519
524
  */
520
525
  processStreamChunk(chunk, state, sseLines) {
521
526
  const choice = chunk.choices?.[0];
527
+ if (choice) {
528
+ const hasToolCalls = choice.delta?.tool_calls;
529
+ const hasFinishReason = choice.finish_reason;
530
+ const isNonText = !choice.delta?.content;
531
+ if (this.config.debugMode && (hasToolCalls || hasFinishReason || isNonText && choice.delta)) {
532
+ this.logDebug("Streaming chunk processed", { chunk });
533
+ }
534
+ }
522
535
  if (!choice) return;
523
536
  const delta = choice.delta;
524
537
  if (delta.reasoning_content) {
@@ -576,37 +589,81 @@ var StreamingProtocolAdapter = class {
576
589
  }
577
590
  }
578
591
  /**
579
- * 处理工具调用
592
+ * 处理工具调用 - 支持OpenAI流式分块累积
593
+ * OpenAI流式API会将tool_calls分多个chunk发送:
594
+ * - Chunk 1: {index:0, id:"call_xxx", type:"function", function:{name:"web_search"}}
595
+ * - Chunk 2: {index:0, function:{arguments:"{\"query\":\"xxx\"}"}}
596
+ * - Chunk N: 继续累积arguments
580
597
  */
581
598
  processToolCalls(toolCalls, state, sseLines) {
599
+ this.logDebug("processToolCalls called", { toolCalls });
582
600
  for (const toolCall of toolCalls) {
583
- if (toolCall.id && toolCall.function?.name) {
584
- const toolArgs = toolCall.function.arguments || "";
585
- const toolData = {
586
- id: toolCall.id,
587
- name: toolCall.function.name,
588
- input: toolArgs
601
+ const index = toolCall.index ?? 0;
602
+ const toolId = toolCall.id;
603
+ const toolName = toolCall.function?.name;
604
+ const toolArgs = toolCall.function?.arguments;
605
+ this.logDebug(`Processing tool chunk for index ${index}`, {
606
+ hasId: !!toolId,
607
+ hasName: !!toolName,
608
+ hasArgs: !!toolArgs,
609
+ argsLength: toolArgs?.length
610
+ });
611
+ const stateKey = `tool_${index}`;
612
+ let toolData = state.toolCallsMap.get(stateKey);
613
+ if (!toolData) {
614
+ toolData = {
615
+ id: toolId || "",
616
+ name: toolName || "",
617
+ input: "",
618
+ blockStartSent: false,
619
+ blockStopSent: false
589
620
  };
590
- state.toolCallsMap.set(toolCall.id, toolData);
621
+ state.toolCallsMap.set(stateKey, toolData);
622
+ } else {
623
+ if (toolId) toolData.id = toolId;
624
+ if (toolName) toolData.name = toolName;
625
+ }
626
+ if (toolArgs) {
627
+ toolData.input += toolArgs;
628
+ this.logDebug(`Accumulated tool arguments for index ${index}`, {
629
+ currentLength: toolData.input.length
630
+ });
631
+ }
632
+ if (toolData.id && toolData.name && !toolData.blockStartSent) {
591
633
  const blockIndex = state.completedToolCalls.length + 1;
634
+ toolData.blockIndex = blockIndex;
592
635
  sseLines.push(
593
636
  "event: content_block_start",
594
- `data: {"type":"content_block_start","index":${blockIndex},"content_block":{"type":"tool_use","id":"${toolCall.id}","name":"${toolCall.function.name}","input":{}}}`,
637
+ `data: {"type":"content_block_start","index":${blockIndex},"content_block":{"type":"tool_use","id":"${toolData.id}","name":"${toolData.name}","input":{}}}`,
595
638
  ""
596
639
  );
597
- if (toolArgs) {
598
- sseLines.push(
599
- "event: content_block_delta",
600
- `data: {"type":"content_block_delta","index":${blockIndex},"delta":{"type":"input_json_delta","partial_json":${JSON.stringify(toolArgs)}}}`,
601
- ""
602
- );
603
- }
640
+ toolData.blockStartSent = true;
641
+ this.logDebug("Sent content_block_start", { toolName: toolData.name, blockIndex });
642
+ }
643
+ if (toolArgs && toolData.blockStartSent && toolData.blockIndex !== void 0) {
644
+ sseLines.push(
645
+ "event: content_block_delta",
646
+ `data: {"type":"content_block_delta","index":${toolData.blockIndex},"delta":{"type":"input_json_delta","partial_json":${JSON.stringify(toolArgs)}}}`,
647
+ ""
648
+ );
649
+ this.logDebug("Sent input_json_delta", { blockIndex: toolData.blockIndex });
650
+ }
651
+ }
652
+ }
653
+ /**
654
+ * 在流结束时关闭所有未关闭的工具调用块
655
+ */
656
+ closeAllToolCallBlocks(state, sseLines) {
657
+ for (const [key, toolData] of state.toolCallsMap.entries()) {
658
+ if (toolData.blockStartSent && !toolData.blockStopSent && toolData.blockIndex !== void 0) {
604
659
  sseLines.push(
605
660
  "event: content_block_stop",
606
- `data: {"type":"content_block_stop","index":${blockIndex}}`,
661
+ `data: {"type":"content_block_stop","index":${toolData.blockIndex}}`,
607
662
  ""
608
663
  );
609
- state.completedToolCalls.push(toolCall.id);
664
+ toolData.blockStopSent = true;
665
+ state.completedToolCalls.push(toolData.id);
666
+ this.logDebug("Sent content_block_stop", { toolName: toolData.name, blockIndex: toolData.blockIndex });
610
667
  }
611
668
  }
612
669
  }
@@ -614,6 +671,7 @@ var StreamingProtocolAdapter = class {
614
671
  * 添加最终事件 - 支持thinking+content双模式
615
672
  */
616
673
  addFinalEvents(state, sseLines) {
674
+ this.closeAllToolCallBlocks(state, sseLines);
617
675
  if (state.contentBlockStarted) {
618
676
  const blockIndex = state.thinkingBlockStarted ? 1 : 0;
619
677
  sseLines.push(
@@ -851,6 +909,14 @@ var MessageConverter = class {
851
909
  * 使用tool_use_id溯回工具名称解决unknown_tool问题
852
910
  */
853
911
  static convertMessages(messages, system) {
912
+ const debugEnabled = process.env.AI_PROTOCOL_DEBUG === "true";
913
+ if (debugEnabled) {
914
+ if (system !== void 0) {
915
+ console.debug("[MessageConverter] convertMessages called with system:", JSON.stringify(system, null, 2));
916
+ } else {
917
+ console.debug("[MessageConverter] convertMessages called WITHOUT system parameter");
918
+ }
919
+ }
854
920
  const context = this.createConversionContext(messages);
855
921
  const convertedMessages = [];
856
922
  for (const msg of messages) {
@@ -869,8 +935,15 @@ var MessageConverter = class {
869
935
  const systemMessage = this.processSystemMessage(system);
870
936
  if (systemMessage) {
871
937
  convertedMessages.unshift(systemMessage);
938
+ if (debugEnabled) {
939
+ console.debug("[MessageConverter] System message added to messages array at index 0");
940
+ }
872
941
  }
873
942
  }
943
+ if (debugEnabled) {
944
+ console.debug("[MessageConverter] Final converted messages count:", convertedMessages.length);
945
+ console.debug("[MessageConverter] First message:", JSON.stringify(convertedMessages[0], null, 2));
946
+ }
874
947
  return convertedMessages;
875
948
  }
876
949
  /**
@@ -4167,25 +4240,31 @@ var ToolCallProcessor = class _ToolCallProcessor {
4167
4240
  * 处理增量工具调用
4168
4241
  */
4169
4242
  static processIncrementalToolCalls(toolCalls, state, sseLines) {
4170
- console.log("\u{1F50D}\u{1F50D}\u{1F50D} [ToolProcessor] processIncrementalToolCalls called with:", JSON.stringify(toolCalls, null, 2));
4243
+ const debugEnabled = process.env.AI_PROTOCOL_DEBUG === "true";
4244
+ if (debugEnabled) {
4245
+ console.debug("[ToolProcessor] processIncrementalToolCalls called with:", JSON.stringify(toolCalls, null, 2));
4246
+ }
4171
4247
  for (const toolCall of toolCalls) {
4172
4248
  const toolId = toolCall.id;
4173
4249
  const toolName = toolCall.function?.name;
4174
4250
  const toolArgs = toolCall.function?.arguments;
4175
- console.log("\u{1F50D} [ToolProcessor] Processing tool call:", {
4176
- toolId,
4177
- toolName,
4178
- toolArgs: toolArgs || "UNDEFINED",
4179
- toolArgsType: typeof toolArgs,
4180
- toolArgsLength: toolArgs?.length || 0,
4181
- hasArgs: !!toolArgs
4182
- });
4251
+ if (debugEnabled) {
4252
+ console.debug("[ToolProcessor] Processing tool call:", {
4253
+ toolId,
4254
+ toolName,
4255
+ hasArgs: !!toolArgs
4256
+ });
4257
+ }
4183
4258
  if (toolName && toolId && !state.toolCallsMap.has(toolId)) {
4184
- console.log("\u2705 [ToolProcessor] Starting new tool call:", toolName);
4259
+ if (debugEnabled) {
4260
+ console.debug("[ToolProcessor] Starting new tool call:", toolName);
4261
+ }
4185
4262
  _ToolCallProcessor.processToolCallStart(toolId, toolName, state, sseLines);
4186
4263
  }
4187
4264
  if (toolArgs) {
4188
- console.log("\u2705 [ToolProcessor] Processing tool args, calling processToolArgs");
4265
+ if (debugEnabled) {
4266
+ console.debug("[ToolProcessor] Processing tool args, calling processToolArgs");
4267
+ }
4189
4268
  _ToolCallProcessor.processToolArgs(toolId, toolArgs, state, sseLines);
4190
4269
  } else {
4191
4270
  console.warn("\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F [ToolProcessor] No tool args to process! This will result in empty input!");
@@ -4196,25 +4275,31 @@ var ToolCallProcessor = class _ToolCallProcessor {
4196
4275
  * 处理工具调用
4197
4276
  */
4198
4277
  static processBatchToolCalls(toolCalls, state, sseLines) {
4199
- console.log("\u{1F50D}\u{1F50D}\u{1F50D} [ToolProcessor] processBatchToolCalls called with:", JSON.stringify(toolCalls, null, 2));
4278
+ const debugEnabled = process.env.AI_PROTOCOL_DEBUG === "true";
4279
+ if (debugEnabled) {
4280
+ console.debug("[ToolProcessor] processBatchToolCalls called with:", JSON.stringify(toolCalls, null, 2));
4281
+ }
4200
4282
  for (const toolCall of toolCalls) {
4201
4283
  const toolId = toolCall.id;
4202
4284
  const toolName = toolCall.function?.name;
4203
4285
  const toolArgs = toolCall.function?.arguments;
4204
- console.log("\u{1F50D} [ToolProcessor] Processing batch tool call:", {
4205
- toolId,
4206
- toolName,
4207
- toolArgs: toolArgs || "UNDEFINED",
4208
- toolArgsType: typeof toolArgs,
4209
- toolArgsLength: toolArgs?.length || 0,
4210
- hasArgs: !!toolArgs
4211
- });
4286
+ if (debugEnabled) {
4287
+ console.debug("[ToolProcessor] Processing batch tool call:", {
4288
+ toolId,
4289
+ toolName,
4290
+ hasArgs: !!toolArgs
4291
+ });
4292
+ }
4212
4293
  if (toolName && toolId && !state.toolCallsMap.has(toolId)) {
4213
- console.log("\u2705 [ToolProcessor] Starting new batch tool call:", toolName);
4294
+ if (debugEnabled) {
4295
+ console.debug("[ToolProcessor] Starting new batch tool call:", toolName);
4296
+ }
4214
4297
  _ToolCallProcessor.processToolCallStart(toolId, toolName, state, sseLines);
4215
4298
  }
4216
4299
  if (toolArgs) {
4217
- console.log("\u2705 [ToolProcessor] Processing batch tool args, calling processToolArgs");
4300
+ if (debugEnabled) {
4301
+ console.debug("[ToolProcessor] Processing batch tool args, calling processToolArgs");
4302
+ }
4218
4303
  _ToolCallProcessor.processToolArgs(toolId, toolArgs, state, sseLines);
4219
4304
  } else {
4220
4305
  console.warn("\u26A0\uFE0F\u26A0\uFE0F\u26A0\uFE0F [ToolProcessor] No batch tool args to process! This will result in empty input!");
@@ -5118,9 +5203,14 @@ var O2ASSEAdapterStatic = {
5118
5203
  // src/core/standard/standard-protocol-adapter.ts
5119
5204
  var StandardProtocolAdapter = class {
5120
5205
  constructor(options = {}) {
5121
- this.debugMode = options.debugMode !== void 0 ? options.debugMode : true;
5206
+ this.debugMode = options.debugMode ?? process.env.AI_PROTOCOL_DEBUG === "true";
5122
5207
  this.sseAdapter = new O2ASSEAdapter(this.debugMode);
5123
5208
  }
5209
+ logDebug(message, meta) {
5210
+ if (this.debugMode) {
5211
+ console.debug(message, meta ?? "");
5212
+ }
5213
+ }
5124
5214
  /**
5125
5215
  * 转换Anthropic请求为OpenAI请求格式
5126
5216
  * @param anthropicRequest - Anthropic格式的请求
@@ -5144,7 +5234,7 @@ var StandardProtocolAdapter = class {
5144
5234
  */
5145
5235
  convertFromStreamToStandard(openaiRawStream, modelName, messageId) {
5146
5236
  if (this.debugMode) {
5147
- console.log("\u{1F504} [StandardProtocolAdapter] convertFromStreamToStandard \u5F00\u59CB\u5904\u7406:", {
5237
+ this.logDebug("\u{1F504} [StandardProtocolAdapter] convertFromStreamToStandard \u5F00\u59CB\u5904\u7406:", {
5148
5238
  rawStreamLength: openaiRawStream.length,
5149
5239
  modelName,
5150
5240
  messageId,
@@ -5153,14 +5243,14 @@ var StandardProtocolAdapter = class {
5153
5243
  }
5154
5244
  const sseResult = this.sseAdapter.convertToClaudeSSE(openaiRawStream, modelName, messageId);
5155
5245
  if (this.debugMode) {
5156
- console.log("\u{1F504} [StandardProtocolAdapter] SSE\u8F6C\u6362\u5B8C\u6210:", {
5246
+ this.logDebug("\u{1F504} [StandardProtocolAdapter] SSE\u8F6C\u6362\u5B8C\u6210:", {
5157
5247
  sseResultLength: sseResult.length,
5158
5248
  ssePreview: sseResult.substring(0, 500)
5159
5249
  });
5160
5250
  }
5161
5251
  const standardResponse = this.extractStandardResponseFromSSE(sseResult, modelName, messageId);
5162
5252
  if (this.debugMode) {
5163
- console.log("\u{1F504} [StandardProtocolAdapter] \u6807\u51C6\u54CD\u5E94\u63D0\u53D6\u5B8C\u6210:", {
5253
+ this.logDebug("\u{1F504} [StandardProtocolAdapter] \u6807\u51C6\u54CD\u5E94\u63D0\u53D6\u5B8C\u6210:", {
5164
5254
  contentLength: standardResponse.content.length,
5165
5255
  usage: standardResponse.usage,
5166
5256
  stopReason: standardResponse.stop_reason
@@ -5175,7 +5265,7 @@ var StandardProtocolAdapter = class {
5175
5265
  const lines = sseContent.split("\n");
5176
5266
  const finalMessageId = messageId || generateMessageId();
5177
5267
  if (this.debugMode) {
5178
- console.log("\u{1F50D} [StandardProtocolAdapter] extractStandardResponseFromSSE \u5F00\u59CB\u89E3\u6790:", {
5268
+ this.logDebug("\u{1F50D} [StandardProtocolAdapter] extractStandardResponseFromSSE \u5F00\u59CB\u89E3\u6790:", {
5179
5269
  totalLines: lines.length,
5180
5270
  messageId: finalMessageId
5181
5271
  });
@@ -5230,25 +5320,28 @@ var StandardProtocolAdapter = class {
5230
5320
  if (data.type === "content_block_delta" && data.delta?.type === "text_delta") {
5231
5321
  currentTextContent += data.delta.text;
5232
5322
  if (this.debugMode && currentTextContent.length % 50 === 0) {
5233
- console.log(`\u{1F4DD} [StandardProtocolAdapter] \u7D2F\u79EF\u6587\u672C\u5185\u5BB9 (${currentTextContent.length}\u5B57\u7B26):`, currentTextContent.substring(currentTextContent.length - 20));
5323
+ this.logDebug(`\u{1F4DD} [StandardProtocolAdapter] \u7D2F\u79EF\u6587\u672C\u5185\u5BB9 (${currentTextContent.length}\u5B57\u7B26)`, currentTextContent.substring(currentTextContent.length - 20));
5234
5324
  }
5235
5325
  }
5236
5326
  if (data.type === "content_block_delta" && data.delta?.type === "input_json_delta") {
5237
5327
  const toolIndex = data.index;
5238
5328
  const toolId = indexToToolId.get(toolIndex);
5239
- console.log(`\u{1F527}\u{1F527}\u{1F527} [StandardProtocolAdapter] \u68C0\u6D4B\u5230input_json_delta\u4E8B\u4EF6\uFF01`, {
5240
- toolIndex,
5241
- toolId: toolId || "NOT_FOUND",
5242
- delta: data.delta.partial_json
5243
- });
5329
+ if (this.debugMode) {
5330
+ this.logDebug(`\u{1F527}\u{1F527}\u{1F527} [StandardProtocolAdapter] \u68C0\u6D4B\u5230input_json_delta\u4E8B\u4EF6\uFF01`, {
5331
+ toolIndex,
5332
+ toolId: toolId || "NOT_FOUND",
5333
+ delta: data.delta.partial_json
5334
+ });
5335
+ }
5244
5336
  if (toolId) {
5245
5337
  const currentBuffer = toolInputBuffers.get(toolIndex) || "";
5246
5338
  const newBuffer = currentBuffer + data.delta.partial_json;
5247
5339
  toolInputBuffers.set(toolIndex, newBuffer);
5248
- console.log(`\u{1F527} [StandardProtocolAdapter] \u7D2F\u79EF\u5DE5\u5177\u53C2\u6570 (index=${toolIndex}, id=${toolId}):`, {
5249
- delta: data.delta.partial_json,
5250
- bufferLength: newBuffer.length
5251
- });
5340
+ if (this.debugMode) {
5341
+ this.logDebug(`\u{1F527} [StandardProtocolAdapter] \u7D2F\u79EF\u5DE5\u5177\u53C2\u6570 (index=${toolIndex}, id=${toolId})`, {
5342
+ bufferLength: newBuffer.length
5343
+ });
5344
+ }
5252
5345
  } else {
5253
5346
  console.warn(`\u26A0\uFE0F [StandardProtocolAdapter] \u627E\u4E0D\u5230toolId for index=${toolIndex}`);
5254
5347
  }
@@ -5264,7 +5357,7 @@ var StandardProtocolAdapter = class {
5264
5357
  const parsedInput = JSON.parse(jsonBuffer);
5265
5358
  tool.input = parsedInput;
5266
5359
  if (this.debugMode) {
5267
- console.log(`\u2705 [StandardProtocolAdapter] \u5DE5\u5177\u53C2\u6570\u89E3\u6790\u5B8C\u6210 (index=${toolIndex}, id=${toolId}):`, parsedInput);
5360
+ this.logDebug(`\u2705 [StandardProtocolAdapter] \u5DE5\u5177\u53C2\u6570\u89E3\u6790\u5B8C\u6210 (index=${toolIndex}, id=${toolId})`, parsedInput);
5268
5361
  }
5269
5362
  } catch (parseError) {
5270
5363
  console.warn(`\u26A0\uFE0F [StandardProtocolAdapter] \u5DE5\u5177\u53C2\u6570JSON\u89E3\u6790\u5931\u8D25 (index=${toolIndex}, id=${toolId}):`, {
@@ -5282,7 +5375,7 @@ var StandardProtocolAdapter = class {
5282
5375
  if (data.usage) {
5283
5376
  response.usage = data.usage;
5284
5377
  if (this.debugMode) {
5285
- console.log("\u{1F4CA} [StandardProtocolAdapter] \u66F4\u65B0usage\u4FE1\u606F:", data.usage);
5378
+ this.logDebug("\u{1F4CA} [StandardProtocolAdapter] \u66F4\u65B0usage\u4FE1\u606F:", data.usage);
5286
5379
  }
5287
5380
  }
5288
5381
  }
@@ -5302,7 +5395,7 @@ var StandardProtocolAdapter = class {
5302
5395
  }
5303
5396
  response.content.push(...Array.from(toolCalls.values()));
5304
5397
  if (this.debugMode) {
5305
- console.log("\u2705 [StandardProtocolAdapter] \u6807\u51C6\u54CD\u5E94\u6784\u5EFA\u5B8C\u6210:", {
5398
+ this.logDebug("\u2705 [StandardProtocolAdapter] \u6807\u51C6\u54CD\u5E94\u6784\u5EFA\u5B8C\u6210:", {
5306
5399
  contentCount: response.content.length,
5307
5400
  textLength: currentTextContent.length,
5308
5401
  toolCallsCount: toolCalls.size,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-protocol-adapters",
3
- "version": "1.0.0-alpha.4",
3
+ "version": "1.0.0-alpha.7",
4
4
  "description": "Universal AI Protocol Converter - OpenAI ⇄ Anthropic with full TypeScript support",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",