ai-protocol-adapters 1.0.0-alpha.16 → 1.0.0-alpha.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -5606,6 +5606,11 @@ interface A2ORequestAdapterConfig {
5606
5606
  logLevel: 'none' | 'error' | 'warn' | 'info' | 'debug';
5607
5607
  enableMetrics: boolean;
5608
5608
  };
5609
+ imageProxy: {
5610
+ enabled: boolean;
5611
+ timeout: number;
5612
+ maxSize: number;
5613
+ };
5609
5614
  }
5610
5615
 
5611
5616
  /**
@@ -5626,9 +5631,9 @@ declare class A2ORequestAdapter {
5626
5631
  */
5627
5632
  convertAnthropicRequestToOpenAIEnhanced(anthropicRequest: unknown): Promise<ConversionResult$2<OpenAIRequest>>;
5628
5633
  /**
5629
- * 执行核心转换逻辑(原有逻辑保持不变)
5634
+ * 执行核心转换逻辑(支持图片代理)
5630
5635
  */
5631
- private performCoreConversion;
5636
+ performCoreConversion(anthropicRequest: ClaudeRequest): Promise<any>;
5632
5637
  /**
5633
5638
  * 转换Anthropic请求格式为OpenAI兼容格式 - 原有方法保持兼容
5634
5639
  */
@@ -5723,8 +5728,35 @@ declare const A2ORequestAdapterStatic: {
5723
5728
  * 获取工具映射(静态方法,已弃用)
5724
5729
  */
5725
5730
  getToolMapping: (claudeToolName: string) => string | undefined;
5731
+ /**
5732
+ * 转换Anthropic请求格式为OpenAI兼容格式(异步版本,支持图片URL自动下载)
5733
+ * 解决GitHub Copilot等API不支持外部图片URL的问题
5734
+ * @param anthropicRequest Claude格式的请求
5735
+ * @param downloadImageUrls 是否下载图片URL并转换为base64(默认true)
5736
+ */
5737
+ convertAnthropicRequestToOpenAIAsync: (anthropicRequest: ClaudeRequest, downloadImageUrls?: boolean) => Promise<OpenAIRequest>;
5726
5738
  };
5727
5739
 
5740
+ /**
5741
+ * 从URL下载图片并转换为base64 data URI
5742
+ * @param url 图片URL
5743
+ * @param options 下载选项
5744
+ * @returns base64 data URI (例如: "data:image/jpeg;base64,/9j/4AAQ...")
5745
+ */
5746
+ declare function downloadImageAsBase64(url: string, options?: {
5747
+ timeout?: number;
5748
+ maxSize?: number;
5749
+ userAgent?: string;
5750
+ }): Promise<string>;
5751
+ /**
5752
+ * 判断URL是否是外部URL(http/https开头)
5753
+ */
5754
+ declare function isExternalUrl(url: string): boolean;
5755
+ /**
5756
+ * 判断URL是否已经是base64 data URI
5757
+ */
5758
+ declare function isBase64DataUri(url: string): boolean;
5759
+
5728
5760
  /**
5729
5761
  * A2O格式验证器
5730
5762
  * 专门处理Claude和OpenAI请求格式的验证
@@ -7333,4 +7365,4 @@ declare const FEATURES: {
7333
7365
  readonly externalPackageVerified: true;
7334
7366
  };
7335
7367
 
7336
- export { A2ORequestAdapter, A2ORequestAdapterStatic, ADAPTERS_VERSION, type AnthropicContentBlock, AnthropicContentBlockBaseSchema, AnthropicContentBlockDeltaEventSchema, AnthropicContentBlockSchema, AnthropicContentBlockStartEventSchema, AnthropicContentBlockStopEventSchema, AnthropicErrorEventSchema, type AnthropicImageContentBlock, AnthropicImageContentBlockSchema, AnthropicImageSourceSchema, type AnthropicMessage, AnthropicMessageDeltaEventSchema, AnthropicMessageSchema, AnthropicMessageStartEventSchema, AnthropicMessageStopEventSchema, AnthropicMetadataSchema, AnthropicPingEventSchema, type AnthropicRequest, AnthropicRequestSchema, type AnthropicResponse, AnthropicResponseSchema, type AnthropicSDKConfig, AnthropicSDKWrapper, type AnthropicStreamEvent, AnthropicStreamEventBaseSchema, AnthropicStreamEventSchema, AnthropicSystemMessageSchema, type AnthropicTextContentBlock, AnthropicTextContentBlockSchema, type AnthropicTool, AnthropicToolInputSchemaSchema, type AnthropicToolResultContentBlock, AnthropicToolResultContentBlockSchema, AnthropicToolSchema, type AnthropicToolUseContentBlock, AnthropicToolUseContentBlockSchema, type AnthropicUsage, AnthropicUsageSchema, type BaseSDKClient, A2ORequestAdapter as ClaudeToOpenAIConverter, type ConversionFixResult, ConversionFixer, type ConversionResult$1 as ConversionResult, type ConversionState, ConversionValidator, type ConvertedRequest, type ConvertedResponse, EMERGENCY_HEALING_STRATEGIES, type EnhancedAdapterOptions, type EnhancedConversionResult, ErrorDetector, type ErrorInfo, ErrorRecovery, type ErrorSeverity, type ErrorType, FEATURES, FormatValidator, type HealingContext, type HealingResult, type HealingRule, StandardProtocolAdapter as NonStreamingIOConverter, O2ASSEAdapter, O2ASSEAdapterStatic, type OpenAIChoice, OpenAIChoiceSchema, OpenAIFunctionParametersSchema, OpenAIFunctionSchema, type OpenAIMessage, OpenAIMessageContentSchema, OpenAIMessageSchema, type OpenAIRequest$1 as OpenAIRequest, OpenAIRequestSchema, type OpenAIResponse$1 as OpenAIResponse, OpenAIResponseSchema, type OpenAISDKConfig, OpenAISDKWrapper, type OpenAIStreamChunk, OpenAIStreamChunkSchema, O2ASSEAdapter as OpenAIToClaudeSSEConverter, type OpenAITool, type OpenAIToolCall, OpenAIToolCallSchema, OpenAIToolSchema, type OpenAIUsage, OpenAIUsageSchema, ProtocolHealer, RECOVERY_STRATEGIES, REQUEST_HEALING_STRATEGIES, RESPONSE_HEALING_STRATEGIES, type RecoveryResult, type RecoveryStrategy, type RequestOptions, type SDKConfig, SDKFactory, type SDKProvider, type SDKResponse, type SDKStreamEvent, SSEEventGenerator, STREAM_HEALING_STRATEGIES, type ConversionResult as SchemaConversionResult, StandardProtocolAdapter as StandardGateway, StandardProtocolAdapter, type StandardProtocolAdapterOptions, StreamingProtocolAdapter as StreamingGateway, StreamingProtocolAdapter as StreamingIOConverter, StreamingProtocolAdapter, type StreamingProtocolAdapterOptions, type UnifiedSDKConfig, type ValidationResult, attemptRecovery, conversionValidator, createAnthropicSDK, createOpenAISDK, createValidator, errorRecovery, getAllHealingStrategies, getGlobalLogger, getRecoveryRecommendations, getStrategiesForContext, healA2ORequest, healO2ARequest, healO2AResponse, healingValidate, isRecoverable, protocolHealer, safeValidate, sdkFactory, selectSDKByModel, strictValidate, validateA2OConversion, validateAnthropicRequest, validateAnthropicResponse, validateAnthropicStreamEvent, validateBatch, validateO2AConversion, validateOpenAIRequest, validateOpenAIResponse, validateOpenAIStreamChunk, validateSDKConfig, validateStreamConversion };
7368
+ export { A2ORequestAdapter, A2ORequestAdapterStatic, ADAPTERS_VERSION, type AnthropicContentBlock, AnthropicContentBlockBaseSchema, AnthropicContentBlockDeltaEventSchema, AnthropicContentBlockSchema, AnthropicContentBlockStartEventSchema, AnthropicContentBlockStopEventSchema, AnthropicErrorEventSchema, type AnthropicImageContentBlock, AnthropicImageContentBlockSchema, AnthropicImageSourceSchema, type AnthropicMessage, AnthropicMessageDeltaEventSchema, AnthropicMessageSchema, AnthropicMessageStartEventSchema, AnthropicMessageStopEventSchema, AnthropicMetadataSchema, AnthropicPingEventSchema, type AnthropicRequest, AnthropicRequestSchema, type AnthropicResponse, AnthropicResponseSchema, type AnthropicSDKConfig, AnthropicSDKWrapper, type AnthropicStreamEvent, AnthropicStreamEventBaseSchema, AnthropicStreamEventSchema, AnthropicSystemMessageSchema, type AnthropicTextContentBlock, AnthropicTextContentBlockSchema, type AnthropicTool, AnthropicToolInputSchemaSchema, type AnthropicToolResultContentBlock, AnthropicToolResultContentBlockSchema, AnthropicToolSchema, type AnthropicToolUseContentBlock, AnthropicToolUseContentBlockSchema, type AnthropicUsage, AnthropicUsageSchema, type BaseSDKClient, A2ORequestAdapter as ClaudeToOpenAIConverter, type ConversionFixResult, ConversionFixer, type ConversionResult$1 as ConversionResult, type ConversionState, ConversionValidator, type ConvertedRequest, type ConvertedResponse, EMERGENCY_HEALING_STRATEGIES, type EnhancedAdapterOptions, type EnhancedConversionResult, ErrorDetector, type ErrorInfo, ErrorRecovery, type ErrorSeverity, type ErrorType, FEATURES, FormatValidator, type HealingContext, type HealingResult, type HealingRule, StandardProtocolAdapter as NonStreamingIOConverter, O2ASSEAdapter, O2ASSEAdapterStatic, type OpenAIChoice, OpenAIChoiceSchema, OpenAIFunctionParametersSchema, OpenAIFunctionSchema, type OpenAIMessage, OpenAIMessageContentSchema, OpenAIMessageSchema, type OpenAIRequest$1 as OpenAIRequest, OpenAIRequestSchema, type OpenAIResponse$1 as OpenAIResponse, OpenAIResponseSchema, type OpenAISDKConfig, OpenAISDKWrapper, type OpenAIStreamChunk, OpenAIStreamChunkSchema, O2ASSEAdapter as OpenAIToClaudeSSEConverter, type OpenAITool, type OpenAIToolCall, OpenAIToolCallSchema, OpenAIToolSchema, type OpenAIUsage, OpenAIUsageSchema, ProtocolHealer, RECOVERY_STRATEGIES, REQUEST_HEALING_STRATEGIES, RESPONSE_HEALING_STRATEGIES, type RecoveryResult, type RecoveryStrategy, type RequestOptions, type SDKConfig, SDKFactory, type SDKProvider, type SDKResponse, type SDKStreamEvent, SSEEventGenerator, STREAM_HEALING_STRATEGIES, type ConversionResult as SchemaConversionResult, StandardProtocolAdapter as StandardGateway, StandardProtocolAdapter, type StandardProtocolAdapterOptions, StreamingProtocolAdapter as StreamingGateway, StreamingProtocolAdapter as StreamingIOConverter, StreamingProtocolAdapter, type StreamingProtocolAdapterOptions, type UnifiedSDKConfig, type ValidationResult, attemptRecovery, conversionValidator, createAnthropicSDK, createOpenAISDK, createValidator, downloadImageAsBase64, errorRecovery, getAllHealingStrategies, getGlobalLogger, getRecoveryRecommendations, getStrategiesForContext, healA2ORequest, healO2ARequest, healO2AResponse, healingValidate, isBase64DataUri, isExternalUrl, isRecoverable, protocolHealer, safeValidate, sdkFactory, selectSDKByModel, strictValidate, validateA2OConversion, validateAnthropicRequest, validateAnthropicResponse, validateAnthropicStreamEvent, validateBatch, validateO2AConversion, validateOpenAIRequest, validateOpenAIResponse, validateOpenAIStreamChunk, validateSDKConfig, validateStreamConversion };
package/dist/index.d.ts CHANGED
@@ -5606,6 +5606,11 @@ interface A2ORequestAdapterConfig {
5606
5606
  logLevel: 'none' | 'error' | 'warn' | 'info' | 'debug';
5607
5607
  enableMetrics: boolean;
5608
5608
  };
5609
+ imageProxy: {
5610
+ enabled: boolean;
5611
+ timeout: number;
5612
+ maxSize: number;
5613
+ };
5609
5614
  }
5610
5615
 
5611
5616
  /**
@@ -5626,9 +5631,9 @@ declare class A2ORequestAdapter {
5626
5631
  */
5627
5632
  convertAnthropicRequestToOpenAIEnhanced(anthropicRequest: unknown): Promise<ConversionResult$2<OpenAIRequest>>;
5628
5633
  /**
5629
- * 执行核心转换逻辑(原有逻辑保持不变)
5634
+ * 执行核心转换逻辑(支持图片代理)
5630
5635
  */
5631
- private performCoreConversion;
5636
+ performCoreConversion(anthropicRequest: ClaudeRequest): Promise<any>;
5632
5637
  /**
5633
5638
  * 转换Anthropic请求格式为OpenAI兼容格式 - 原有方法保持兼容
5634
5639
  */
@@ -5723,8 +5728,35 @@ declare const A2ORequestAdapterStatic: {
5723
5728
  * 获取工具映射(静态方法,已弃用)
5724
5729
  */
5725
5730
  getToolMapping: (claudeToolName: string) => string | undefined;
5731
+ /**
5732
+ * 转换Anthropic请求格式为OpenAI兼容格式(异步版本,支持图片URL自动下载)
5733
+ * 解决GitHub Copilot等API不支持外部图片URL的问题
5734
+ * @param anthropicRequest Claude格式的请求
5735
+ * @param downloadImageUrls 是否下载图片URL并转换为base64(默认true)
5736
+ */
5737
+ convertAnthropicRequestToOpenAIAsync: (anthropicRequest: ClaudeRequest, downloadImageUrls?: boolean) => Promise<OpenAIRequest>;
5726
5738
  };
5727
5739
 
5740
+ /**
5741
+ * 从URL下载图片并转换为base64 data URI
5742
+ * @param url 图片URL
5743
+ * @param options 下载选项
5744
+ * @returns base64 data URI (例如: "data:image/jpeg;base64,/9j/4AAQ...")
5745
+ */
5746
+ declare function downloadImageAsBase64(url: string, options?: {
5747
+ timeout?: number;
5748
+ maxSize?: number;
5749
+ userAgent?: string;
5750
+ }): Promise<string>;
5751
+ /**
5752
+ * 判断URL是否是外部URL(http/https开头)
5753
+ */
5754
+ declare function isExternalUrl(url: string): boolean;
5755
+ /**
5756
+ * 判断URL是否已经是base64 data URI
5757
+ */
5758
+ declare function isBase64DataUri(url: string): boolean;
5759
+
5728
5760
  /**
5729
5761
  * A2O格式验证器
5730
5762
  * 专门处理Claude和OpenAI请求格式的验证
@@ -7333,4 +7365,4 @@ declare const FEATURES: {
7333
7365
  readonly externalPackageVerified: true;
7334
7366
  };
7335
7367
 
7336
- export { A2ORequestAdapter, A2ORequestAdapterStatic, ADAPTERS_VERSION, type AnthropicContentBlock, AnthropicContentBlockBaseSchema, AnthropicContentBlockDeltaEventSchema, AnthropicContentBlockSchema, AnthropicContentBlockStartEventSchema, AnthropicContentBlockStopEventSchema, AnthropicErrorEventSchema, type AnthropicImageContentBlock, AnthropicImageContentBlockSchema, AnthropicImageSourceSchema, type AnthropicMessage, AnthropicMessageDeltaEventSchema, AnthropicMessageSchema, AnthropicMessageStartEventSchema, AnthropicMessageStopEventSchema, AnthropicMetadataSchema, AnthropicPingEventSchema, type AnthropicRequest, AnthropicRequestSchema, type AnthropicResponse, AnthropicResponseSchema, type AnthropicSDKConfig, AnthropicSDKWrapper, type AnthropicStreamEvent, AnthropicStreamEventBaseSchema, AnthropicStreamEventSchema, AnthropicSystemMessageSchema, type AnthropicTextContentBlock, AnthropicTextContentBlockSchema, type AnthropicTool, AnthropicToolInputSchemaSchema, type AnthropicToolResultContentBlock, AnthropicToolResultContentBlockSchema, AnthropicToolSchema, type AnthropicToolUseContentBlock, AnthropicToolUseContentBlockSchema, type AnthropicUsage, AnthropicUsageSchema, type BaseSDKClient, A2ORequestAdapter as ClaudeToOpenAIConverter, type ConversionFixResult, ConversionFixer, type ConversionResult$1 as ConversionResult, type ConversionState, ConversionValidator, type ConvertedRequest, type ConvertedResponse, EMERGENCY_HEALING_STRATEGIES, type EnhancedAdapterOptions, type EnhancedConversionResult, ErrorDetector, type ErrorInfo, ErrorRecovery, type ErrorSeverity, type ErrorType, FEATURES, FormatValidator, type HealingContext, type HealingResult, type HealingRule, StandardProtocolAdapter as NonStreamingIOConverter, O2ASSEAdapter, O2ASSEAdapterStatic, type OpenAIChoice, OpenAIChoiceSchema, OpenAIFunctionParametersSchema, OpenAIFunctionSchema, type OpenAIMessage, OpenAIMessageContentSchema, OpenAIMessageSchema, type OpenAIRequest$1 as OpenAIRequest, OpenAIRequestSchema, type OpenAIResponse$1 as OpenAIResponse, OpenAIResponseSchema, type OpenAISDKConfig, OpenAISDKWrapper, type OpenAIStreamChunk, OpenAIStreamChunkSchema, O2ASSEAdapter as OpenAIToClaudeSSEConverter, type OpenAITool, type OpenAIToolCall, OpenAIToolCallSchema, OpenAIToolSchema, type OpenAIUsage, OpenAIUsageSchema, ProtocolHealer, RECOVERY_STRATEGIES, REQUEST_HEALING_STRATEGIES, RESPONSE_HEALING_STRATEGIES, type RecoveryResult, type RecoveryStrategy, type RequestOptions, type SDKConfig, SDKFactory, type SDKProvider, type SDKResponse, type SDKStreamEvent, SSEEventGenerator, STREAM_HEALING_STRATEGIES, type ConversionResult as SchemaConversionResult, StandardProtocolAdapter as StandardGateway, StandardProtocolAdapter, type StandardProtocolAdapterOptions, StreamingProtocolAdapter as StreamingGateway, StreamingProtocolAdapter as StreamingIOConverter, StreamingProtocolAdapter, type StreamingProtocolAdapterOptions, type UnifiedSDKConfig, type ValidationResult, attemptRecovery, conversionValidator, createAnthropicSDK, createOpenAISDK, createValidator, errorRecovery, getAllHealingStrategies, getGlobalLogger, getRecoveryRecommendations, getStrategiesForContext, healA2ORequest, healO2ARequest, healO2AResponse, healingValidate, isRecoverable, protocolHealer, safeValidate, sdkFactory, selectSDKByModel, strictValidate, validateA2OConversion, validateAnthropicRequest, validateAnthropicResponse, validateAnthropicStreamEvent, validateBatch, validateO2AConversion, validateOpenAIRequest, validateOpenAIResponse, validateOpenAIStreamChunk, validateSDKConfig, validateStreamConversion };
7368
+ export { A2ORequestAdapter, A2ORequestAdapterStatic, ADAPTERS_VERSION, type AnthropicContentBlock, AnthropicContentBlockBaseSchema, AnthropicContentBlockDeltaEventSchema, AnthropicContentBlockSchema, AnthropicContentBlockStartEventSchema, AnthropicContentBlockStopEventSchema, AnthropicErrorEventSchema, type AnthropicImageContentBlock, AnthropicImageContentBlockSchema, AnthropicImageSourceSchema, type AnthropicMessage, AnthropicMessageDeltaEventSchema, AnthropicMessageSchema, AnthropicMessageStartEventSchema, AnthropicMessageStopEventSchema, AnthropicMetadataSchema, AnthropicPingEventSchema, type AnthropicRequest, AnthropicRequestSchema, type AnthropicResponse, AnthropicResponseSchema, type AnthropicSDKConfig, AnthropicSDKWrapper, type AnthropicStreamEvent, AnthropicStreamEventBaseSchema, AnthropicStreamEventSchema, AnthropicSystemMessageSchema, type AnthropicTextContentBlock, AnthropicTextContentBlockSchema, type AnthropicTool, AnthropicToolInputSchemaSchema, type AnthropicToolResultContentBlock, AnthropicToolResultContentBlockSchema, AnthropicToolSchema, type AnthropicToolUseContentBlock, AnthropicToolUseContentBlockSchema, type AnthropicUsage, AnthropicUsageSchema, type BaseSDKClient, A2ORequestAdapter as ClaudeToOpenAIConverter, type ConversionFixResult, ConversionFixer, type ConversionResult$1 as ConversionResult, type ConversionState, ConversionValidator, type ConvertedRequest, type ConvertedResponse, EMERGENCY_HEALING_STRATEGIES, type EnhancedAdapterOptions, type EnhancedConversionResult, ErrorDetector, type ErrorInfo, ErrorRecovery, type ErrorSeverity, type ErrorType, FEATURES, FormatValidator, type HealingContext, type HealingResult, type HealingRule, StandardProtocolAdapter as NonStreamingIOConverter, O2ASSEAdapter, O2ASSEAdapterStatic, type OpenAIChoice, OpenAIChoiceSchema, OpenAIFunctionParametersSchema, OpenAIFunctionSchema, type OpenAIMessage, OpenAIMessageContentSchema, OpenAIMessageSchema, type OpenAIRequest$1 as OpenAIRequest, OpenAIRequestSchema, type OpenAIResponse$1 as OpenAIResponse, OpenAIResponseSchema, type OpenAISDKConfig, OpenAISDKWrapper, type OpenAIStreamChunk, OpenAIStreamChunkSchema, O2ASSEAdapter as OpenAIToClaudeSSEConverter, type OpenAITool, type OpenAIToolCall, OpenAIToolCallSchema, OpenAIToolSchema, type OpenAIUsage, OpenAIUsageSchema, ProtocolHealer, RECOVERY_STRATEGIES, REQUEST_HEALING_STRATEGIES, RESPONSE_HEALING_STRATEGIES, type RecoveryResult, type RecoveryStrategy, type RequestOptions, type SDKConfig, SDKFactory, type SDKProvider, type SDKResponse, type SDKStreamEvent, SSEEventGenerator, STREAM_HEALING_STRATEGIES, type ConversionResult as SchemaConversionResult, StandardProtocolAdapter as StandardGateway, StandardProtocolAdapter, type StandardProtocolAdapterOptions, StreamingProtocolAdapter as StreamingGateway, StreamingProtocolAdapter as StreamingIOConverter, StreamingProtocolAdapter, type StreamingProtocolAdapterOptions, type UnifiedSDKConfig, type ValidationResult, attemptRecovery, conversionValidator, createAnthropicSDK, createOpenAISDK, createValidator, downloadImageAsBase64, errorRecovery, getAllHealingStrategies, getGlobalLogger, getRecoveryRecommendations, getStrategiesForContext, healA2ORequest, healO2ARequest, healO2AResponse, healingValidate, isBase64DataUri, isExternalUrl, isRecoverable, protocolHealer, safeValidate, sdkFactory, selectSDKByModel, strictValidate, validateA2OConversion, validateAnthropicRequest, validateAnthropicResponse, validateAnthropicStreamEvent, validateBatch, validateO2AConversion, validateOpenAIRequest, validateOpenAIResponse, validateOpenAIStreamChunk, validateSDKConfig, validateStreamConversion };
package/dist/index.js CHANGED
@@ -453,6 +453,7 @@ __export(index_exports, {
453
453
  createAnthropicSDK: () => createAnthropicSDK,
454
454
  createOpenAISDK: () => createOpenAISDK,
455
455
  createValidator: () => createValidator,
456
+ downloadImageAsBase64: () => downloadImageAsBase64,
456
457
  errorRecovery: () => errorRecovery,
457
458
  getAllHealingStrategies: () => getAllHealingStrategies,
458
459
  getGlobalLogger: () => getGlobalLogger,
@@ -462,6 +463,8 @@ __export(index_exports, {
462
463
  healO2ARequest: () => healO2ARequest,
463
464
  healO2AResponse: () => healO2AResponse,
464
465
  healingValidate: () => healingValidate,
466
+ isBase64DataUri: () => isBase64DataUri,
467
+ isExternalUrl: () => isExternalUrl,
465
468
  isRecoverable: () => isRecoverable,
466
469
  protocolHealer: () => protocolHealer,
467
470
  safeValidate: () => safeValidate,
@@ -532,6 +535,14 @@ var DEFAULT_CONFIG = {
532
535
  enabled: false,
533
536
  logLevel: "warn",
534
537
  enableMetrics: false
538
+ },
539
+ imageProxy: {
540
+ enabled: true,
541
+ // 默认启用图片代理(解决GitHub Copilot等不支持外部URL的问题)
542
+ timeout: 1e4,
543
+ // 10秒超时
544
+ maxSize: 10 * 1024 * 1024
545
+ // 10MB最大文件大小
535
546
  }
536
547
  };
537
548
  var SUPPORTED_IMAGE_TYPES = [
@@ -556,6 +567,61 @@ var TOOL_CONVERSION = {
556
567
  UNKNOWN_TOOL_FALLBACK: "unknown_tool"
557
568
  };
558
569
 
570
+ // src/core/a2o-request-adapter/image-proxy.ts
571
+ var SUPPORTED_IMAGE_MIME_TYPES = [
572
+ "image/jpeg",
573
+ "image/png",
574
+ "image/gif",
575
+ "image/webp"
576
+ ];
577
+ async function downloadImageAsBase64(url, options = {}) {
578
+ const {
579
+ timeout = 1e4,
580
+ maxSize = 10 * 1024 * 1024,
581
+ // 10MB
582
+ userAgent = "ai-protocol-adapters/1.0"
583
+ } = options;
584
+ try {
585
+ const controller = new AbortController();
586
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
587
+ const response = await fetch(url, {
588
+ signal: controller.signal,
589
+ headers: {
590
+ "User-Agent": userAgent
591
+ }
592
+ });
593
+ clearTimeout(timeoutId);
594
+ if (!response.ok) {
595
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
596
+ }
597
+ const contentType = response.headers.get("content-type");
598
+ if (!contentType || !SUPPORTED_IMAGE_MIME_TYPES.some((type) => contentType.includes(type))) {
599
+ throw new Error(`Unsupported content type: ${contentType}`);
600
+ }
601
+ const contentLength = response.headers.get("content-length");
602
+ if (contentLength && parseInt(contentLength) > maxSize) {
603
+ throw new Error(`Image too large: ${contentLength} bytes (max: ${maxSize} bytes)`);
604
+ }
605
+ const arrayBuffer = await response.arrayBuffer();
606
+ if (arrayBuffer.byteLength > maxSize) {
607
+ throw new Error(`Image too large: ${arrayBuffer.byteLength} bytes (max: ${maxSize} bytes)`);
608
+ }
609
+ const base64 = Buffer.from(arrayBuffer).toString("base64");
610
+ return `data:${contentType};base64,${base64}`;
611
+ } catch (error) {
612
+ if (error.name === "AbortError") {
613
+ throw new Error(`Image download timeout after ${timeout}ms`);
614
+ }
615
+ throw new Error(`Failed to download image from ${url}: ${error.message}`);
616
+ }
617
+ }
618
+ function isExternalUrl(url) {
619
+ return url.startsWith("http://") || url.startsWith("https://");
620
+ }
621
+ function isBase64DataUri(url) {
622
+ return url.startsWith("data:");
623
+ }
624
+
559
625
  // src/core/a2o-request-adapter/message-converter.ts
560
626
  var MessageConverter = class {
561
627
  /**
@@ -695,9 +761,23 @@ var MessageConverter = class {
695
761
  }
696
762
  /**
697
763
  * 转换图片内容格式
764
+ * 支持两种格式:URL 和 base64
698
765
  */
699
766
  static convertImageContent(item) {
700
- if (item.source && item.source.type === "base64" && item.source.data && item.source.media_type) {
767
+ if (!item.source) {
768
+ return null;
769
+ }
770
+ if (item.source.type === "url" && item.source.url) {
771
+ return {
772
+ type: "image_url",
773
+ image_url: {
774
+ url: item.source.url,
775
+ detail: "auto"
776
+ // OpenAI 支持的可选参数
777
+ }
778
+ };
779
+ }
780
+ if (item.source.type === "base64" && item.source.data && item.source.media_type) {
701
781
  if (!SUPPORTED_IMAGE_TYPES.includes(item.source.media_type)) {
702
782
  console.warn(`\u4E0D\u652F\u6301\u7684\u56FE\u7247\u683C\u5F0F: ${item.source.media_type}`);
703
783
  return null;
@@ -706,7 +786,8 @@ var MessageConverter = class {
706
786
  return {
707
787
  type: "image_url",
708
788
  image_url: {
709
- url: dataUri
789
+ url: dataUri,
790
+ detail: "auto"
710
791
  }
711
792
  };
712
793
  }
@@ -802,6 +883,170 @@ var MessageConverter = class {
802
883
  }
803
884
  return null;
804
885
  }
886
+ /**
887
+ * 异步转换图片内容格式(支持URL自动下载转base64)
888
+ * @param item 图片内容项
889
+ * @param downloadUrls 是否下载URL并转换为base64(默认true)
890
+ */
891
+ static async convertImageContentAsync(item, downloadUrls = true) {
892
+ if (!item.source) {
893
+ return null;
894
+ }
895
+ if (item.source.type === "url" && item.source.url) {
896
+ const url = item.source.url;
897
+ if (isBase64DataUri(url)) {
898
+ return {
899
+ type: "image_url",
900
+ image_url: {
901
+ url,
902
+ detail: "auto"
903
+ }
904
+ };
905
+ }
906
+ if (downloadUrls && isExternalUrl(url)) {
907
+ try {
908
+ console.log(`[MessageConverter] Downloading image from URL: ${url}`);
909
+ const base64DataUri = await downloadImageAsBase64(url);
910
+ console.log(`[MessageConverter] Successfully converted image to base64`);
911
+ return {
912
+ type: "image_url",
913
+ image_url: {
914
+ url: base64DataUri,
915
+ detail: "auto"
916
+ }
917
+ };
918
+ } catch (error) {
919
+ console.error(`[MessageConverter] Failed to download image: ${error.message}`);
920
+ return {
921
+ type: "image_url",
922
+ image_url: {
923
+ url,
924
+ detail: "auto"
925
+ }
926
+ };
927
+ }
928
+ }
929
+ return {
930
+ type: "image_url",
931
+ image_url: {
932
+ url,
933
+ detail: "auto"
934
+ }
935
+ };
936
+ }
937
+ if (item.source.type === "base64" && item.source.data && item.source.media_type) {
938
+ if (!SUPPORTED_IMAGE_TYPES.includes(item.source.media_type)) {
939
+ console.warn(`\u4E0D\u652F\u6301\u7684\u56FE\u7247\u683C\u5F0F: ${item.source.media_type}`);
940
+ return null;
941
+ }
942
+ const dataUri = `data:${item.source.media_type};base64,${item.source.data}`;
943
+ return {
944
+ type: "image_url",
945
+ image_url: {
946
+ url: dataUri,
947
+ detail: "auto"
948
+ }
949
+ };
950
+ }
951
+ return null;
952
+ }
953
+ /**
954
+ * 异步处理消息内容(支持图片URL下载)
955
+ */
956
+ static async processMessageContentAsync(content, downloadUrls = true) {
957
+ const textContent = [];
958
+ const toolUses = [];
959
+ const toolResults = [];
960
+ for (const item of content) {
961
+ if (item.type) {
962
+ switch (item.type) {
963
+ case "text":
964
+ if (item.text) {
965
+ textContent.push({ type: "text", text: item.text });
966
+ }
967
+ break;
968
+ case "tool_use":
969
+ toolUses.push(item);
970
+ break;
971
+ case "tool_result":
972
+ toolResults.push(item);
973
+ break;
974
+ case "image":
975
+ const imageContent = await this.convertImageContentAsync(item, downloadUrls);
976
+ if (imageContent) {
977
+ textContent.push(imageContent);
978
+ }
979
+ break;
980
+ }
981
+ }
982
+ }
983
+ return { textContent, toolUses, toolResults };
984
+ }
985
+ /**
986
+ * 异步转换消息格式(支持图片URL自动下载)
987
+ * @param messages Claude格式的消息数组
988
+ * @param system 系统消息
989
+ * @param downloadImageUrls 是否下载图片URL并转换为base64(默认true,解决GitHub Copilot等API不支持外部URL的问题)
990
+ */
991
+ static async convertMessagesAsync(messages, system, downloadImageUrls = true) {
992
+ const debugEnabled = process.env.AI_PROTOCOL_DEBUG === "true";
993
+ if (debugEnabled) {
994
+ console.debug(
995
+ `[MessageConverter] convertMessagesAsync called (downloadImageUrls: ${downloadImageUrls})`
996
+ );
997
+ }
998
+ const context = this.createConversionContext(messages);
999
+ const convertedMessages = [];
1000
+ for (const msg of messages) {
1001
+ if (Array.isArray(msg.content)) {
1002
+ const processedMessages = await this.processComplexMessageAsync(msg, context, downloadImageUrls);
1003
+ convertedMessages.push(...processedMessages);
1004
+ } else {
1005
+ const safeMsg = { ...msg };
1006
+ if (safeMsg.content === null || safeMsg.content === void 0) {
1007
+ safeMsg.content = "";
1008
+ }
1009
+ convertedMessages.push(safeMsg);
1010
+ }
1011
+ }
1012
+ const systemMessage = this.processSystemMessage(system);
1013
+ if (systemMessage) {
1014
+ return [systemMessage, ...convertedMessages];
1015
+ }
1016
+ return convertedMessages;
1017
+ }
1018
+ /**
1019
+ * 异步处理复杂消息(支持图片URL下载)
1020
+ */
1021
+ static async processComplexMessageAsync(msg, context, downloadUrls) {
1022
+ const { textContent, toolUses, toolResults } = await this.processMessageContentAsync(
1023
+ msg.content,
1024
+ downloadUrls
1025
+ );
1026
+ const result = [];
1027
+ if (msg.role === "user") {
1028
+ const toolMessages = this.createToolResultMessages(toolResults, context.toolIdToNameMap);
1029
+ result.push(...toolMessages);
1030
+ const textMessage = this.createTextMessage("user", textContent);
1031
+ if (textMessage) {
1032
+ result.push(textMessage);
1033
+ }
1034
+ } else if (msg.role === "assistant") {
1035
+ if (toolUses.length > 0) {
1036
+ const assistantMessage = this.createAssistantMessageWithToolCalls(textContent, toolUses);
1037
+ result.push(assistantMessage);
1038
+ toolUses.forEach((toolUse) => {
1039
+ context.toolIdToNameMap.set(toolUse.id, toolUse.name);
1040
+ });
1041
+ } else {
1042
+ const textMessage = this.createTextMessage("assistant", textContent);
1043
+ if (textMessage) {
1044
+ result.push(textMessage);
1045
+ }
1046
+ }
1047
+ }
1048
+ return result;
1049
+ }
805
1050
  };
806
1051
 
807
1052
  // src/core/a2o-request-adapter/tool-converter.ts
@@ -3454,15 +3699,21 @@ var A2ORequestAdapter = class {
3454
3699
  }
3455
3700
  }
3456
3701
  /**
3457
- * 执行核心转换逻辑(原有逻辑保持不变)
3702
+ * 执行核心转换逻辑(支持图片代理)
3458
3703
  */
3459
3704
  async performCoreConversion(anthropicRequest) {
3460
3705
  if (this.config.enableFormatValidation) {
3461
3706
  FormatValidator.validateClaudeRequest(anthropicRequest);
3462
3707
  }
3708
+ const messages = this.config.imageProxy.enabled ? await MessageConverter.convertMessagesAsync(
3709
+ anthropicRequest.messages,
3710
+ anthropicRequest.system,
3711
+ true
3712
+ // 启用图片下载
3713
+ ) : MessageConverter.convertMessages(anthropicRequest.messages, anthropicRequest.system);
3463
3714
  const openaiRequest = {
3464
3715
  model: anthropicRequest.model,
3465
- messages: MessageConverter.convertMessages(anthropicRequest.messages, anthropicRequest.system),
3716
+ messages,
3466
3717
  max_tokens: anthropicRequest.max_tokens,
3467
3718
  temperature: anthropicRequest.temperature,
3468
3719
  stream: anthropicRequest.stream
@@ -3772,6 +4023,36 @@ var A2ORequestAdapterStatic = {
3772
4023
  */
3773
4024
  getToolMapping: (claudeToolName) => {
3774
4025
  return claudeToolName;
4026
+ },
4027
+ /**
4028
+ * 转换Anthropic请求格式为OpenAI兼容格式(异步版本,支持图片URL自动下载)
4029
+ * 解决GitHub Copilot等API不支持外部图片URL的问题
4030
+ * @param anthropicRequest Claude格式的请求
4031
+ * @param downloadImageUrls 是否下载图片URL并转换为base64(默认true)
4032
+ */
4033
+ convertAnthropicRequestToOpenAIAsync: async (anthropicRequest, downloadImageUrls = true) => {
4034
+ const adapter = new A2ORequestAdapter({
4035
+ debugMode: false,
4036
+ maxDescriptionLength: 100,
4037
+ enableToolNameValidation: true,
4038
+ enableFormatValidation: true,
4039
+ validation: { enabled: true, strict: false },
4040
+ healing: { enabled: true, maxAttempts: 2, enableCustomRules: true },
4041
+ recovery: { enabled: false, maxRetries: 0, backoffMs: 1e3 },
4042
+ monitoring: { enabled: false, logLevel: "none", enableMetrics: false },
4043
+ imageProxy: {
4044
+ enabled: downloadImageUrls,
4045
+ timeout: 1e4,
4046
+ maxSize: 10 * 1024 * 1024
4047
+ }
4048
+ });
4049
+ try {
4050
+ const result = await adapter.performCoreConversion(anthropicRequest);
4051
+ return result;
4052
+ } catch (error) {
4053
+ console.warn(`[A2ORequestAdapterStatic] Async conversion failed: ${error?.message || error}`);
4054
+ return adapter.performBasicConversion(anthropicRequest, true);
4055
+ }
3775
4056
  }
3776
4057
  };
3777
4058
 
@@ -6658,6 +6939,7 @@ var FEATURES = {
6658
6939
  createAnthropicSDK,
6659
6940
  createOpenAISDK,
6660
6941
  createValidator,
6942
+ downloadImageAsBase64,
6661
6943
  errorRecovery,
6662
6944
  getAllHealingStrategies,
6663
6945
  getGlobalLogger,
@@ -6667,6 +6949,8 @@ var FEATURES = {
6667
6949
  healO2ARequest,
6668
6950
  healO2AResponse,
6669
6951
  healingValidate,
6952
+ isBase64DataUri,
6953
+ isExternalUrl,
6670
6954
  isRecoverable,
6671
6955
  protocolHealer,
6672
6956
  safeValidate,
package/dist/index.mjs CHANGED
@@ -425,6 +425,14 @@ var DEFAULT_CONFIG = {
425
425
  enabled: false,
426
426
  logLevel: "warn",
427
427
  enableMetrics: false
428
+ },
429
+ imageProxy: {
430
+ enabled: true,
431
+ // 默认启用图片代理(解决GitHub Copilot等不支持外部URL的问题)
432
+ timeout: 1e4,
433
+ // 10秒超时
434
+ maxSize: 10 * 1024 * 1024
435
+ // 10MB最大文件大小
428
436
  }
429
437
  };
430
438
  var SUPPORTED_IMAGE_TYPES = [
@@ -449,6 +457,61 @@ var TOOL_CONVERSION = {
449
457
  UNKNOWN_TOOL_FALLBACK: "unknown_tool"
450
458
  };
451
459
 
460
+ // src/core/a2o-request-adapter/image-proxy.ts
461
+ var SUPPORTED_IMAGE_MIME_TYPES = [
462
+ "image/jpeg",
463
+ "image/png",
464
+ "image/gif",
465
+ "image/webp"
466
+ ];
467
+ async function downloadImageAsBase64(url, options = {}) {
468
+ const {
469
+ timeout = 1e4,
470
+ maxSize = 10 * 1024 * 1024,
471
+ // 10MB
472
+ userAgent = "ai-protocol-adapters/1.0"
473
+ } = options;
474
+ try {
475
+ const controller = new AbortController();
476
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
477
+ const response = await fetch(url, {
478
+ signal: controller.signal,
479
+ headers: {
480
+ "User-Agent": userAgent
481
+ }
482
+ });
483
+ clearTimeout(timeoutId);
484
+ if (!response.ok) {
485
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
486
+ }
487
+ const contentType = response.headers.get("content-type");
488
+ if (!contentType || !SUPPORTED_IMAGE_MIME_TYPES.some((type) => contentType.includes(type))) {
489
+ throw new Error(`Unsupported content type: ${contentType}`);
490
+ }
491
+ const contentLength = response.headers.get("content-length");
492
+ if (contentLength && parseInt(contentLength) > maxSize) {
493
+ throw new Error(`Image too large: ${contentLength} bytes (max: ${maxSize} bytes)`);
494
+ }
495
+ const arrayBuffer = await response.arrayBuffer();
496
+ if (arrayBuffer.byteLength > maxSize) {
497
+ throw new Error(`Image too large: ${arrayBuffer.byteLength} bytes (max: ${maxSize} bytes)`);
498
+ }
499
+ const base64 = Buffer.from(arrayBuffer).toString("base64");
500
+ return `data:${contentType};base64,${base64}`;
501
+ } catch (error) {
502
+ if (error.name === "AbortError") {
503
+ throw new Error(`Image download timeout after ${timeout}ms`);
504
+ }
505
+ throw new Error(`Failed to download image from ${url}: ${error.message}`);
506
+ }
507
+ }
508
+ function isExternalUrl(url) {
509
+ return url.startsWith("http://") || url.startsWith("https://");
510
+ }
511
+ function isBase64DataUri(url) {
512
+ return url.startsWith("data:");
513
+ }
514
+
452
515
  // src/core/a2o-request-adapter/message-converter.ts
453
516
  var MessageConverter = class {
454
517
  /**
@@ -588,9 +651,23 @@ var MessageConverter = class {
588
651
  }
589
652
  /**
590
653
  * 转换图片内容格式
654
+ * 支持两种格式:URL 和 base64
591
655
  */
592
656
  static convertImageContent(item) {
593
- if (item.source && item.source.type === "base64" && item.source.data && item.source.media_type) {
657
+ if (!item.source) {
658
+ return null;
659
+ }
660
+ if (item.source.type === "url" && item.source.url) {
661
+ return {
662
+ type: "image_url",
663
+ image_url: {
664
+ url: item.source.url,
665
+ detail: "auto"
666
+ // OpenAI 支持的可选参数
667
+ }
668
+ };
669
+ }
670
+ if (item.source.type === "base64" && item.source.data && item.source.media_type) {
594
671
  if (!SUPPORTED_IMAGE_TYPES.includes(item.source.media_type)) {
595
672
  console.warn(`\u4E0D\u652F\u6301\u7684\u56FE\u7247\u683C\u5F0F: ${item.source.media_type}`);
596
673
  return null;
@@ -599,7 +676,8 @@ var MessageConverter = class {
599
676
  return {
600
677
  type: "image_url",
601
678
  image_url: {
602
- url: dataUri
679
+ url: dataUri,
680
+ detail: "auto"
603
681
  }
604
682
  };
605
683
  }
@@ -695,6 +773,170 @@ var MessageConverter = class {
695
773
  }
696
774
  return null;
697
775
  }
776
+ /**
777
+ * 异步转换图片内容格式(支持URL自动下载转base64)
778
+ * @param item 图片内容项
779
+ * @param downloadUrls 是否下载URL并转换为base64(默认true)
780
+ */
781
+ static async convertImageContentAsync(item, downloadUrls = true) {
782
+ if (!item.source) {
783
+ return null;
784
+ }
785
+ if (item.source.type === "url" && item.source.url) {
786
+ const url = item.source.url;
787
+ if (isBase64DataUri(url)) {
788
+ return {
789
+ type: "image_url",
790
+ image_url: {
791
+ url,
792
+ detail: "auto"
793
+ }
794
+ };
795
+ }
796
+ if (downloadUrls && isExternalUrl(url)) {
797
+ try {
798
+ console.log(`[MessageConverter] Downloading image from URL: ${url}`);
799
+ const base64DataUri = await downloadImageAsBase64(url);
800
+ console.log(`[MessageConverter] Successfully converted image to base64`);
801
+ return {
802
+ type: "image_url",
803
+ image_url: {
804
+ url: base64DataUri,
805
+ detail: "auto"
806
+ }
807
+ };
808
+ } catch (error) {
809
+ console.error(`[MessageConverter] Failed to download image: ${error.message}`);
810
+ return {
811
+ type: "image_url",
812
+ image_url: {
813
+ url,
814
+ detail: "auto"
815
+ }
816
+ };
817
+ }
818
+ }
819
+ return {
820
+ type: "image_url",
821
+ image_url: {
822
+ url,
823
+ detail: "auto"
824
+ }
825
+ };
826
+ }
827
+ if (item.source.type === "base64" && item.source.data && item.source.media_type) {
828
+ if (!SUPPORTED_IMAGE_TYPES.includes(item.source.media_type)) {
829
+ console.warn(`\u4E0D\u652F\u6301\u7684\u56FE\u7247\u683C\u5F0F: ${item.source.media_type}`);
830
+ return null;
831
+ }
832
+ const dataUri = `data:${item.source.media_type};base64,${item.source.data}`;
833
+ return {
834
+ type: "image_url",
835
+ image_url: {
836
+ url: dataUri,
837
+ detail: "auto"
838
+ }
839
+ };
840
+ }
841
+ return null;
842
+ }
843
+ /**
844
+ * 异步处理消息内容(支持图片URL下载)
845
+ */
846
+ static async processMessageContentAsync(content, downloadUrls = true) {
847
+ const textContent = [];
848
+ const toolUses = [];
849
+ const toolResults = [];
850
+ for (const item of content) {
851
+ if (item.type) {
852
+ switch (item.type) {
853
+ case "text":
854
+ if (item.text) {
855
+ textContent.push({ type: "text", text: item.text });
856
+ }
857
+ break;
858
+ case "tool_use":
859
+ toolUses.push(item);
860
+ break;
861
+ case "tool_result":
862
+ toolResults.push(item);
863
+ break;
864
+ case "image":
865
+ const imageContent = await this.convertImageContentAsync(item, downloadUrls);
866
+ if (imageContent) {
867
+ textContent.push(imageContent);
868
+ }
869
+ break;
870
+ }
871
+ }
872
+ }
873
+ return { textContent, toolUses, toolResults };
874
+ }
875
+ /**
876
+ * 异步转换消息格式(支持图片URL自动下载)
877
+ * @param messages Claude格式的消息数组
878
+ * @param system 系统消息
879
+ * @param downloadImageUrls 是否下载图片URL并转换为base64(默认true,解决GitHub Copilot等API不支持外部URL的问题)
880
+ */
881
+ static async convertMessagesAsync(messages, system, downloadImageUrls = true) {
882
+ const debugEnabled = process.env.AI_PROTOCOL_DEBUG === "true";
883
+ if (debugEnabled) {
884
+ console.debug(
885
+ `[MessageConverter] convertMessagesAsync called (downloadImageUrls: ${downloadImageUrls})`
886
+ );
887
+ }
888
+ const context = this.createConversionContext(messages);
889
+ const convertedMessages = [];
890
+ for (const msg of messages) {
891
+ if (Array.isArray(msg.content)) {
892
+ const processedMessages = await this.processComplexMessageAsync(msg, context, downloadImageUrls);
893
+ convertedMessages.push(...processedMessages);
894
+ } else {
895
+ const safeMsg = { ...msg };
896
+ if (safeMsg.content === null || safeMsg.content === void 0) {
897
+ safeMsg.content = "";
898
+ }
899
+ convertedMessages.push(safeMsg);
900
+ }
901
+ }
902
+ const systemMessage = this.processSystemMessage(system);
903
+ if (systemMessage) {
904
+ return [systemMessage, ...convertedMessages];
905
+ }
906
+ return convertedMessages;
907
+ }
908
+ /**
909
+ * 异步处理复杂消息(支持图片URL下载)
910
+ */
911
+ static async processComplexMessageAsync(msg, context, downloadUrls) {
912
+ const { textContent, toolUses, toolResults } = await this.processMessageContentAsync(
913
+ msg.content,
914
+ downloadUrls
915
+ );
916
+ const result = [];
917
+ if (msg.role === "user") {
918
+ const toolMessages = this.createToolResultMessages(toolResults, context.toolIdToNameMap);
919
+ result.push(...toolMessages);
920
+ const textMessage = this.createTextMessage("user", textContent);
921
+ if (textMessage) {
922
+ result.push(textMessage);
923
+ }
924
+ } else if (msg.role === "assistant") {
925
+ if (toolUses.length > 0) {
926
+ const assistantMessage = this.createAssistantMessageWithToolCalls(textContent, toolUses);
927
+ result.push(assistantMessage);
928
+ toolUses.forEach((toolUse) => {
929
+ context.toolIdToNameMap.set(toolUse.id, toolUse.name);
930
+ });
931
+ } else {
932
+ const textMessage = this.createTextMessage("assistant", textContent);
933
+ if (textMessage) {
934
+ result.push(textMessage);
935
+ }
936
+ }
937
+ }
938
+ return result;
939
+ }
698
940
  };
699
941
 
700
942
  // src/core/a2o-request-adapter/tool-converter.ts
@@ -3347,15 +3589,21 @@ var A2ORequestAdapter = class {
3347
3589
  }
3348
3590
  }
3349
3591
  /**
3350
- * 执行核心转换逻辑(原有逻辑保持不变)
3592
+ * 执行核心转换逻辑(支持图片代理)
3351
3593
  */
3352
3594
  async performCoreConversion(anthropicRequest) {
3353
3595
  if (this.config.enableFormatValidation) {
3354
3596
  FormatValidator.validateClaudeRequest(anthropicRequest);
3355
3597
  }
3598
+ const messages = this.config.imageProxy.enabled ? await MessageConverter.convertMessagesAsync(
3599
+ anthropicRequest.messages,
3600
+ anthropicRequest.system,
3601
+ true
3602
+ // 启用图片下载
3603
+ ) : MessageConverter.convertMessages(anthropicRequest.messages, anthropicRequest.system);
3356
3604
  const openaiRequest = {
3357
3605
  model: anthropicRequest.model,
3358
- messages: MessageConverter.convertMessages(anthropicRequest.messages, anthropicRequest.system),
3606
+ messages,
3359
3607
  max_tokens: anthropicRequest.max_tokens,
3360
3608
  temperature: anthropicRequest.temperature,
3361
3609
  stream: anthropicRequest.stream
@@ -3665,6 +3913,36 @@ var A2ORequestAdapterStatic = {
3665
3913
  */
3666
3914
  getToolMapping: (claudeToolName) => {
3667
3915
  return claudeToolName;
3916
+ },
3917
+ /**
3918
+ * 转换Anthropic请求格式为OpenAI兼容格式(异步版本,支持图片URL自动下载)
3919
+ * 解决GitHub Copilot等API不支持外部图片URL的问题
3920
+ * @param anthropicRequest Claude格式的请求
3921
+ * @param downloadImageUrls 是否下载图片URL并转换为base64(默认true)
3922
+ */
3923
+ convertAnthropicRequestToOpenAIAsync: async (anthropicRequest, downloadImageUrls = true) => {
3924
+ const adapter = new A2ORequestAdapter({
3925
+ debugMode: false,
3926
+ maxDescriptionLength: 100,
3927
+ enableToolNameValidation: true,
3928
+ enableFormatValidation: true,
3929
+ validation: { enabled: true, strict: false },
3930
+ healing: { enabled: true, maxAttempts: 2, enableCustomRules: true },
3931
+ recovery: { enabled: false, maxRetries: 0, backoffMs: 1e3 },
3932
+ monitoring: { enabled: false, logLevel: "none", enableMetrics: false },
3933
+ imageProxy: {
3934
+ enabled: downloadImageUrls,
3935
+ timeout: 1e4,
3936
+ maxSize: 10 * 1024 * 1024
3937
+ }
3938
+ });
3939
+ try {
3940
+ const result = await adapter.performCoreConversion(anthropicRequest);
3941
+ return result;
3942
+ } catch (error) {
3943
+ console.warn(`[A2ORequestAdapterStatic] Async conversion failed: ${error?.message || error}`);
3944
+ return adapter.performBasicConversion(anthropicRequest, true);
3945
+ }
3668
3946
  }
3669
3947
  };
3670
3948
 
@@ -6550,6 +6828,7 @@ export {
6550
6828
  createAnthropicSDK,
6551
6829
  createOpenAISDK,
6552
6830
  createValidator,
6831
+ downloadImageAsBase64,
6553
6832
  errorRecovery,
6554
6833
  getAllHealingStrategies,
6555
6834
  getGlobalLogger,
@@ -6559,6 +6838,8 @@ export {
6559
6838
  healO2ARequest,
6560
6839
  healO2AResponse,
6561
6840
  healingValidate,
6841
+ isBase64DataUri,
6842
+ isExternalUrl,
6562
6843
  isRecoverable,
6563
6844
  protocolHealer,
6564
6845
  safeValidate,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-protocol-adapters",
3
- "version": "1.0.0-alpha.16",
3
+ "version": "1.0.0-alpha.18",
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",