ai-protocol-adapters 1.0.0-alpha.17 → 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 +35 -3
- package/dist/index.d.ts +35 -3
- package/dist/index.js +271 -2
- package/dist/index.mjs +268 -2
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
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
|
/**
|
|
@@ -817,6 +883,170 @@ var MessageConverter = class {
|
|
|
817
883
|
}
|
|
818
884
|
return null;
|
|
819
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
|
+
}
|
|
820
1050
|
};
|
|
821
1051
|
|
|
822
1052
|
// src/core/a2o-request-adapter/tool-converter.ts
|
|
@@ -3469,15 +3699,21 @@ var A2ORequestAdapter = class {
|
|
|
3469
3699
|
}
|
|
3470
3700
|
}
|
|
3471
3701
|
/**
|
|
3472
|
-
*
|
|
3702
|
+
* 执行核心转换逻辑(支持图片代理)
|
|
3473
3703
|
*/
|
|
3474
3704
|
async performCoreConversion(anthropicRequest) {
|
|
3475
3705
|
if (this.config.enableFormatValidation) {
|
|
3476
3706
|
FormatValidator.validateClaudeRequest(anthropicRequest);
|
|
3477
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);
|
|
3478
3714
|
const openaiRequest = {
|
|
3479
3715
|
model: anthropicRequest.model,
|
|
3480
|
-
messages
|
|
3716
|
+
messages,
|
|
3481
3717
|
max_tokens: anthropicRequest.max_tokens,
|
|
3482
3718
|
temperature: anthropicRequest.temperature,
|
|
3483
3719
|
stream: anthropicRequest.stream
|
|
@@ -3787,6 +4023,36 @@ var A2ORequestAdapterStatic = {
|
|
|
3787
4023
|
*/
|
|
3788
4024
|
getToolMapping: (claudeToolName) => {
|
|
3789
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
|
+
}
|
|
3790
4056
|
}
|
|
3791
4057
|
};
|
|
3792
4058
|
|
|
@@ -6673,6 +6939,7 @@ var FEATURES = {
|
|
|
6673
6939
|
createAnthropicSDK,
|
|
6674
6940
|
createOpenAISDK,
|
|
6675
6941
|
createValidator,
|
|
6942
|
+
downloadImageAsBase64,
|
|
6676
6943
|
errorRecovery,
|
|
6677
6944
|
getAllHealingStrategies,
|
|
6678
6945
|
getGlobalLogger,
|
|
@@ -6682,6 +6949,8 @@ var FEATURES = {
|
|
|
6682
6949
|
healO2ARequest,
|
|
6683
6950
|
healO2AResponse,
|
|
6684
6951
|
healingValidate,
|
|
6952
|
+
isBase64DataUri,
|
|
6953
|
+
isExternalUrl,
|
|
6685
6954
|
isRecoverable,
|
|
6686
6955
|
protocolHealer,
|
|
6687
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
|
/**
|
|
@@ -710,6 +773,170 @@ var MessageConverter = class {
|
|
|
710
773
|
}
|
|
711
774
|
return null;
|
|
712
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
|
+
}
|
|
713
940
|
};
|
|
714
941
|
|
|
715
942
|
// src/core/a2o-request-adapter/tool-converter.ts
|
|
@@ -3362,15 +3589,21 @@ var A2ORequestAdapter = class {
|
|
|
3362
3589
|
}
|
|
3363
3590
|
}
|
|
3364
3591
|
/**
|
|
3365
|
-
*
|
|
3592
|
+
* 执行核心转换逻辑(支持图片代理)
|
|
3366
3593
|
*/
|
|
3367
3594
|
async performCoreConversion(anthropicRequest) {
|
|
3368
3595
|
if (this.config.enableFormatValidation) {
|
|
3369
3596
|
FormatValidator.validateClaudeRequest(anthropicRequest);
|
|
3370
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);
|
|
3371
3604
|
const openaiRequest = {
|
|
3372
3605
|
model: anthropicRequest.model,
|
|
3373
|
-
messages
|
|
3606
|
+
messages,
|
|
3374
3607
|
max_tokens: anthropicRequest.max_tokens,
|
|
3375
3608
|
temperature: anthropicRequest.temperature,
|
|
3376
3609
|
stream: anthropicRequest.stream
|
|
@@ -3680,6 +3913,36 @@ var A2ORequestAdapterStatic = {
|
|
|
3680
3913
|
*/
|
|
3681
3914
|
getToolMapping: (claudeToolName) => {
|
|
3682
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
|
+
}
|
|
3683
3946
|
}
|
|
3684
3947
|
};
|
|
3685
3948
|
|
|
@@ -6565,6 +6828,7 @@ export {
|
|
|
6565
6828
|
createAnthropicSDK,
|
|
6566
6829
|
createOpenAISDK,
|
|
6567
6830
|
createValidator,
|
|
6831
|
+
downloadImageAsBase64,
|
|
6568
6832
|
errorRecovery,
|
|
6569
6833
|
getAllHealingStrategies,
|
|
6570
6834
|
getGlobalLogger,
|
|
@@ -6574,6 +6838,8 @@ export {
|
|
|
6574
6838
|
healO2ARequest,
|
|
6575
6839
|
healO2AResponse,
|
|
6576
6840
|
healingValidate,
|
|
6841
|
+
isBase64DataUri,
|
|
6842
|
+
isExternalUrl,
|
|
6577
6843
|
isRecoverable,
|
|
6578
6844
|
protocolHealer,
|
|
6579
6845
|
safeValidate,
|
package/package.json
CHANGED