@jeffusion/bungee-llms 3.2.0
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/README.md +38 -0
- package/dist/adapter.d.ts +1 -0
- package/dist/core/adapter.d.ts +10 -0
- package/dist/core/conversion-service.d.ts +14 -0
- package/dist/core/index.d.ts +4 -0
- package/dist/core/registry.d.ts +10 -0
- package/dist/core/types.d.ts +40 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +6597 -0
- package/dist/openai/index.d.ts +1 -0
- package/dist/openai/openai-protocol-conversion.d.ts +1 -0
- package/dist/openai-anthropic/index.d.ts +1 -0
- package/dist/openai-anthropic/openai-to-anthropic-request-conversion.d.ts +1 -0
- package/dist/plugin-api.d.ts +4 -0
- package/dist/plugin-api.js +6596 -0
- package/dist/protocol-converters/anthropic-to-gemini.converter.d.ts +62 -0
- package/dist/protocol-converters/anthropic-to-openai.converter.d.ts +105 -0
- package/dist/protocol-converters/base.d.ts +27 -0
- package/dist/protocol-converters/default-registry.d.ts +1 -0
- package/dist/protocol-converters/gemini-to-anthropic.converter.d.ts +57 -0
- package/dist/protocol-converters/gemini-to-openai.converter.d.ts +31 -0
- package/dist/protocol-converters/index.d.ts +10 -0
- package/dist/protocol-converters/openai-to-anthropic.converter.d.ts +27 -0
- package/dist/protocol-converters/openai-to-gemini.converter.d.ts +32 -0
- package/dist/protocol-converters/registry.d.ts +9 -0
- package/dist/protocol-converters/utils.d.ts +71 -0
- package/dist/providers/anthropic/anthropic-adapter.d.ts +16 -0
- package/dist/providers/anthropic/index.d.ts +1 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/openai/index.d.ts +3 -0
- package/dist/providers/openai/messages-compat-normalization.d.ts +42 -0
- package/dist/providers/openai/openai-adapter.d.ts +16 -0
- package/dist/providers/openai/protocol-conversion.d.ts +27 -0
- package/dist/providers/openai-anthropic/index.d.ts +1 -0
- package/dist/providers/openai-anthropic/request-conversion.d.ts +20 -0
- package/dist/providers/provider-catalog.d.ts +26 -0
- package/dist/registry.d.ts +1 -0
- package/dist/runtime/index.d.ts +1 -0
- package/dist/runtime/llms-runtime.d.ts +30 -0
- package/dist/service.d.ts +1 -0
- package/dist/types.d.ts +1 -0
- package/package.json +76 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic to Gemini Converter
|
|
3
|
+
*
|
|
4
|
+
* 将 Anthropic Messages API 格式转换为 Google Gemini API 格式
|
|
5
|
+
*
|
|
6
|
+
* 主要转换:
|
|
7
|
+
* - 请求:/v1/messages → /v1beta/models/{model}:generateContent
|
|
8
|
+
* - 请求:messages → contents (role: assistant → model)
|
|
9
|
+
* - 请求:system → systemInstruction
|
|
10
|
+
* - 请求:tools → functionDeclarations
|
|
11
|
+
* - 响应:Gemini 累积文本 → Anthropic 增量文本(SSE)
|
|
12
|
+
*/
|
|
13
|
+
import type { AIConverter, MutableRequestContext, ResponseContext, StreamChunkContext } from './base';
|
|
14
|
+
export declare class AnthropicToGeminiConverter implements AIConverter {
|
|
15
|
+
readonly from = "anthropic";
|
|
16
|
+
readonly to = "gemini";
|
|
17
|
+
private toolIdToNameMap;
|
|
18
|
+
private readonly ALLOWED_QUERY_PARAMS;
|
|
19
|
+
/**
|
|
20
|
+
* 过滤 query 参数,只保留白名单中的参数
|
|
21
|
+
*/
|
|
22
|
+
private filterSearchParams;
|
|
23
|
+
/**
|
|
24
|
+
* 修改请求 URL 和 body,转换为 Gemini 格式
|
|
25
|
+
*/
|
|
26
|
+
onBeforeRequest(ctx: MutableRequestContext): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* 构建 Gemini generateContent 请求
|
|
29
|
+
*/
|
|
30
|
+
private buildGenerateContentRequest;
|
|
31
|
+
/**
|
|
32
|
+
* 转换 Anthropic messages 为 Gemini contents
|
|
33
|
+
*/
|
|
34
|
+
private convertMessages;
|
|
35
|
+
/**
|
|
36
|
+
* 清理 JSON Schema(移除 Gemini 不支持的字段)
|
|
37
|
+
* 按文档 3.4 Line 144: 深度清洗,去除不被 Gemini 接受的关键词
|
|
38
|
+
* 参考 llms 项目的 cleanupParameters 和 processJsonSchema 实现
|
|
39
|
+
*/
|
|
40
|
+
private cleanSchema;
|
|
41
|
+
/**
|
|
42
|
+
* 处理非流式响应
|
|
43
|
+
* 将 Gemini 响应转换为 Anthropic 格式
|
|
44
|
+
*/
|
|
45
|
+
onResponse(ctx: ResponseContext): Promise<Response | void>;
|
|
46
|
+
private isJsonLikeContentType;
|
|
47
|
+
private isLikelyGeminiErrorBody;
|
|
48
|
+
private isLikelyGeminiSuccessBody;
|
|
49
|
+
/**
|
|
50
|
+
* 转换 Gemini 响应为 Anthropic 格式
|
|
51
|
+
*/
|
|
52
|
+
private convertGeminiResponseToAnthropic;
|
|
53
|
+
/**
|
|
54
|
+
* 处理流式响应 chunk
|
|
55
|
+
* Gemini 返回累积文本,需要转换为 Anthropic 的增量文本
|
|
56
|
+
*/
|
|
57
|
+
processStreamChunk(chunk: any, ctx: StreamChunkContext): Promise<any[] | null>;
|
|
58
|
+
/**
|
|
59
|
+
* 流结束时发送最终事件
|
|
60
|
+
*/
|
|
61
|
+
flushStream(_ctx: StreamChunkContext): Promise<any[]>;
|
|
62
|
+
}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Anthropic to OpenAI Converter
|
|
3
|
+
*
|
|
4
|
+
* 将 Anthropic Messages API 格式转换为 OpenAI Chat Completions API 格式
|
|
5
|
+
*
|
|
6
|
+
* 转换规则:
|
|
7
|
+
* - 请求:/v1/messages → /v1/chat/completions
|
|
8
|
+
* - 请求:system → messages[0] (role=system)
|
|
9
|
+
* - 请求:tool_result → tool role, tool_use → tool_calls
|
|
10
|
+
* - 请求:thinking.effort / output_config.effort → reasoning_effort 映射
|
|
11
|
+
* - 响应:OpenAI → Anthropic (tool_calls, thinking 标签)
|
|
12
|
+
* - 响应:OpenAI SSE → Anthropic SSE 事件序列
|
|
13
|
+
*/
|
|
14
|
+
import type { AIConverter, MutableRequestContext, ResponseContext, StreamChunkContext } from './base';
|
|
15
|
+
export declare class AnthropicToOpenAIConverter implements AIConverter {
|
|
16
|
+
readonly from = "anthropic";
|
|
17
|
+
readonly to = "openai";
|
|
18
|
+
private configuredApiMode?;
|
|
19
|
+
private readonly protocolConversion;
|
|
20
|
+
private readonly runtime;
|
|
21
|
+
constructor();
|
|
22
|
+
setApiMode(mode: unknown): void;
|
|
23
|
+
setRuntimeOptions(options: unknown): void;
|
|
24
|
+
private parseIntegerOption;
|
|
25
|
+
private resolveReasoningMaxCompletionTokens;
|
|
26
|
+
private resolveTargetApiMode;
|
|
27
|
+
/**
|
|
28
|
+
* 修改请求:转换为 OpenAI Chat Completions 格式
|
|
29
|
+
*/
|
|
30
|
+
onBeforeRequest(ctx: MutableRequestContext): Promise<void>;
|
|
31
|
+
private canUseRuntimeRequestConversion;
|
|
32
|
+
private isAnthropicCountTokensPath;
|
|
33
|
+
private buildOpenAICountTokensRequest;
|
|
34
|
+
/**
|
|
35
|
+
* 构建 OpenAI 请求
|
|
36
|
+
*/
|
|
37
|
+
private buildOpenAIRequest;
|
|
38
|
+
private isAnthropicThinkingEnabled;
|
|
39
|
+
private resolveAnthropicThinkingEffort;
|
|
40
|
+
private resolveOutputConfigEffort;
|
|
41
|
+
private normalizeOpenAIReasoningEffort;
|
|
42
|
+
private supportsXHighReasoningEffort;
|
|
43
|
+
private buildOpenAIResponsesRequest;
|
|
44
|
+
private convertSystemMessages;
|
|
45
|
+
private validateAndCleanToolCalls;
|
|
46
|
+
/**
|
|
47
|
+
* 转换 User 消息
|
|
48
|
+
*/
|
|
49
|
+
private normalizeToolResultContent;
|
|
50
|
+
private convertUserMessage;
|
|
51
|
+
private convertUserContentBlock;
|
|
52
|
+
/**
|
|
53
|
+
* 转换 Assistant 消息
|
|
54
|
+
*/
|
|
55
|
+
private convertAssistantMessage;
|
|
56
|
+
private normalizeToolCallId;
|
|
57
|
+
private mapAnthropicToolChoiceToOpenAI;
|
|
58
|
+
private parseOpenAIImageUrlSource;
|
|
59
|
+
private normalizeToolParametersSchema;
|
|
60
|
+
private normalizeJsonSchema;
|
|
61
|
+
/**
|
|
62
|
+
* 处理非流式响应:OpenAI → Anthropic
|
|
63
|
+
*/
|
|
64
|
+
onResponse(ctx: ResponseContext): Promise<Response | void>;
|
|
65
|
+
private extractCountTokensInput;
|
|
66
|
+
private convertOpenAIErrorToAnthropic;
|
|
67
|
+
private isJsonLikeContentType;
|
|
68
|
+
private isLikelyOpenAIErrorBody;
|
|
69
|
+
private isLikelyOpenAICountTokensBody;
|
|
70
|
+
private isLikelyOpenAISuccessBody;
|
|
71
|
+
private isResponsesApiBody;
|
|
72
|
+
private extractReasoningSummaryTexts;
|
|
73
|
+
private appendUniqueThinkingBlocks;
|
|
74
|
+
private appendParsedContent;
|
|
75
|
+
private extractChatCompletionReasoningTexts;
|
|
76
|
+
private extractReasoningTextFromDeltaContentPart;
|
|
77
|
+
private extractChatThinkingDelta;
|
|
78
|
+
private getChatUsedIndices;
|
|
79
|
+
private allocateChatContentBlockIndex;
|
|
80
|
+
private ensureChatTextBlockStarted;
|
|
81
|
+
private ensureChatThinkingBlockStarted;
|
|
82
|
+
private resolveChatToolIndex;
|
|
83
|
+
private resolveResponsesReasoningIndex;
|
|
84
|
+
private ensureResponsesThinkingBlockStarted;
|
|
85
|
+
private emitResponsesThinkingDelta;
|
|
86
|
+
private extractResponsesReasoningDeltaText;
|
|
87
|
+
private convertOpenAIResponsesToAnthropic;
|
|
88
|
+
/**
|
|
89
|
+
* 转换 OpenAI 响应为 Anthropic 格式
|
|
90
|
+
*/
|
|
91
|
+
private convertOpenAIResponseToAnthropic;
|
|
92
|
+
/**
|
|
93
|
+
* 处理流式响应:OpenAI chunk → Anthropic SSE
|
|
94
|
+
*/
|
|
95
|
+
processStreamChunk(chunk: any, ctx: StreamChunkContext): Promise<any[] | null>;
|
|
96
|
+
/**
|
|
97
|
+
* 刷新流 - 确保流结束
|
|
98
|
+
*/
|
|
99
|
+
flushStream(ctx: StreamChunkContext): Promise<any[]>;
|
|
100
|
+
private isResponsesStreamChunk;
|
|
101
|
+
private processResponsesStreamChunk;
|
|
102
|
+
private finalizeResponsesStreamEvents;
|
|
103
|
+
private extractOpenAIStreamUsage;
|
|
104
|
+
private extractDeltaText;
|
|
105
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export interface MutableRequestContext {
|
|
2
|
+
url: URL;
|
|
3
|
+
headers: Record<string, string>;
|
|
4
|
+
body: any;
|
|
5
|
+
[key: string]: any;
|
|
6
|
+
}
|
|
7
|
+
export interface ResponseContext {
|
|
8
|
+
response: Response;
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
}
|
|
11
|
+
export interface StreamChunkContext {
|
|
12
|
+
streamState: Map<string, any>;
|
|
13
|
+
chunkIndex?: number;
|
|
14
|
+
isFirstChunk?: boolean;
|
|
15
|
+
isLastChunk?: boolean;
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
}
|
|
18
|
+
export interface AIConverter {
|
|
19
|
+
readonly from: string;
|
|
20
|
+
readonly to: string;
|
|
21
|
+
setRuntimeOptions?(options: unknown): void;
|
|
22
|
+
onBeforeRequest?(ctx: MutableRequestContext): Promise<void>;
|
|
23
|
+
onResponse?(ctx: ResponseContext): Promise<Response | void>;
|
|
24
|
+
processStreamChunk?(chunk: any, ctx: StreamChunkContext): Promise<any[] | null>;
|
|
25
|
+
flushStream?(ctx: StreamChunkContext): Promise<any[]>;
|
|
26
|
+
}
|
|
27
|
+
export type TransformDirection = `${string}-${string}`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function registerDefaultProtocolConverters(): void;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini to Anthropic Plugin
|
|
3
|
+
*
|
|
4
|
+
* 将 Google Gemini API 格式转换为 Anthropic Messages API 格式
|
|
5
|
+
*
|
|
6
|
+
* 主要转换:
|
|
7
|
+
* - 请求:/v1beta/models/{model}:generateContent → /v1/messages
|
|
8
|
+
* - 请求:contents → messages (role: model → assistant, tool → user)
|
|
9
|
+
* - 请求:systemInstruction → system
|
|
10
|
+
* - 请求:functionDeclarations → tools
|
|
11
|
+
* - 响应:Anthropic 格式 → Gemini candidates 格式
|
|
12
|
+
* - 响应:Anthropic 增量 SSE → Gemini 累积 SSE
|
|
13
|
+
*/
|
|
14
|
+
import type { AIConverter, MutableRequestContext, ResponseContext, StreamChunkContext } from './base';
|
|
15
|
+
export declare class GeminiToAnthropicConverter implements AIConverter {
|
|
16
|
+
readonly from = "gemini";
|
|
17
|
+
readonly to = "anthropic";
|
|
18
|
+
private parseGeminiEndpoint;
|
|
19
|
+
/**
|
|
20
|
+
* 修改请求 URL 和 body,转换为 Anthropic 格式
|
|
21
|
+
*/
|
|
22
|
+
onBeforeRequest(ctx: MutableRequestContext): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* 转换 Gemini contents 为 Anthropic messages
|
|
25
|
+
*/
|
|
26
|
+
private convertContentsToMessages;
|
|
27
|
+
/**
|
|
28
|
+
* 转换 Gemini tools 为 Anthropic tools
|
|
29
|
+
*/
|
|
30
|
+
private convertTools;
|
|
31
|
+
/**
|
|
32
|
+
* 转换 Gemini schema 类型为 JSON Schema
|
|
33
|
+
*/
|
|
34
|
+
private convertSchema;
|
|
35
|
+
/**
|
|
36
|
+
* 处理非流式响应
|
|
37
|
+
* 将 Anthropic 响应转换为 Gemini 格式
|
|
38
|
+
*/
|
|
39
|
+
onResponse(ctx: ResponseContext): Promise<Response | void>;
|
|
40
|
+
/**
|
|
41
|
+
* 转换 Anthropic 错误响应为 Gemini 格式
|
|
42
|
+
*/
|
|
43
|
+
private mapAnthropicErrorToGeminiStatus;
|
|
44
|
+
private transformErrorResponse;
|
|
45
|
+
private isJsonLikeContentType;
|
|
46
|
+
private isLikelyAnthropicErrorBody;
|
|
47
|
+
private isLikelyAnthropicSuccessBody;
|
|
48
|
+
/**
|
|
49
|
+
* 转换 Anthropic 响应为 Gemini candidates 格式
|
|
50
|
+
*/
|
|
51
|
+
private convertAnthropicResponseToGemini;
|
|
52
|
+
/**
|
|
53
|
+
* 处理流式响应 chunk
|
|
54
|
+
* Anthropic 返回增量文本,需要累积为 Gemini 的累积格式
|
|
55
|
+
*/
|
|
56
|
+
processStreamChunk(chunk: any, ctx: StreamChunkContext): Promise<any[] | null>;
|
|
57
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini to OpenAI Plugin
|
|
3
|
+
*
|
|
4
|
+
* 将 Google Gemini API 格式转换为 OpenAI Chat Completions API 格式
|
|
5
|
+
*
|
|
6
|
+
* 主要转换:
|
|
7
|
+
* - 请求:/v1beta/models/{model}:generateContent → /v1/chat/completions
|
|
8
|
+
* - 请求:contents → messages
|
|
9
|
+
* - 响应:OpenAI chat.completion → Gemini candidates 格式
|
|
10
|
+
*/
|
|
11
|
+
import type { AIConverter, MutableRequestContext, ResponseContext, StreamChunkContext } from './base';
|
|
12
|
+
export declare class GeminiToOpenAIConverter implements AIConverter {
|
|
13
|
+
readonly from = "gemini";
|
|
14
|
+
readonly to = "openai";
|
|
15
|
+
private parseGeminiEndpoint;
|
|
16
|
+
onBeforeRequest(ctx: MutableRequestContext): Promise<void>;
|
|
17
|
+
private parseToolArgumentsToObject;
|
|
18
|
+
private buildOpenAIRequest;
|
|
19
|
+
onResponse(ctx: ResponseContext): Promise<Response | void>;
|
|
20
|
+
private mapOpenAIErrorToGeminiStatus;
|
|
21
|
+
private transformErrorResponse;
|
|
22
|
+
private isJsonLikeContentType;
|
|
23
|
+
private isLikelyOpenAIErrorBody;
|
|
24
|
+
private isLikelyOpenAISuccessBody;
|
|
25
|
+
private convertOpenAIResponseToGemini;
|
|
26
|
+
processStreamChunk(chunk: any, ctx: StreamChunkContext): Promise<any[] | null>;
|
|
27
|
+
/**
|
|
28
|
+
* flushStream - 此 transformer 不需要缓冲,返回空数组
|
|
29
|
+
*/
|
|
30
|
+
flushStream(ctx: StreamChunkContext): Promise<any[]>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './base';
|
|
2
|
+
export * from './utils';
|
|
3
|
+
export * from './registry';
|
|
4
|
+
export * from './default-registry';
|
|
5
|
+
export * from './openai-to-anthropic.converter';
|
|
6
|
+
export * from './anthropic-to-openai.converter';
|
|
7
|
+
export * from './openai-to-gemini.converter';
|
|
8
|
+
export * from './gemini-to-openai.converter';
|
|
9
|
+
export * from './anthropic-to-gemini.converter';
|
|
10
|
+
export * from './gemini-to-anthropic.converter';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI to Anthropic Converter
|
|
3
|
+
*
|
|
4
|
+
* 将 OpenAI Chat Completions API 格式转换为 Anthropic Messages API 格式
|
|
5
|
+
*
|
|
6
|
+
* 转换规则:
|
|
7
|
+
* - 请求:/v1/chat/completions → /v1/messages
|
|
8
|
+
* - 请求:messages、tools、reasoning_effort
|
|
9
|
+
* - 响应:Anthropic message → OpenAI chat.completion
|
|
10
|
+
* - 响应:Anthropic SSE → OpenAI SSE
|
|
11
|
+
*/
|
|
12
|
+
import type { AIConverter, MutableRequestContext, ResponseContext, StreamChunkContext } from './base';
|
|
13
|
+
export declare class OpenAIToAnthropicConverter implements AIConverter {
|
|
14
|
+
readonly from = "openai";
|
|
15
|
+
readonly to = "anthropic";
|
|
16
|
+
private readonly runtime;
|
|
17
|
+
constructor();
|
|
18
|
+
onBeforeRequest(ctx: MutableRequestContext): Promise<void>;
|
|
19
|
+
onResponse(ctx: ResponseContext): Promise<Response | void>;
|
|
20
|
+
private mapAnthropicErrorToOpenAIType;
|
|
21
|
+
private transformErrorResponse;
|
|
22
|
+
private isJsonLikeContentType;
|
|
23
|
+
private isLikelyAnthropicErrorBody;
|
|
24
|
+
private convertAnthropicResponseToOpenAI;
|
|
25
|
+
processStreamChunk(chunk: any, ctx: StreamChunkContext): Promise<any[] | null>;
|
|
26
|
+
flushStream(ctx: StreamChunkContext): Promise<any[]>;
|
|
27
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI to Gemini Plugin
|
|
3
|
+
*
|
|
4
|
+
* 将 OpenAI Chat Completions API 格式转换为 Google Gemini API 格式
|
|
5
|
+
*
|
|
6
|
+
* 主要转换:
|
|
7
|
+
* - 请求:/v1/chat/completions → /v1beta/models/{model}:generateContent
|
|
8
|
+
* - 请求:messages → contents
|
|
9
|
+
* - 响应:Gemini → OpenAI chat.completion
|
|
10
|
+
*/
|
|
11
|
+
import type { AIConverter, MutableRequestContext, ResponseContext, StreamChunkContext } from './base';
|
|
12
|
+
export declare class OpenAIToGeminiConverter implements AIConverter {
|
|
13
|
+
readonly from = "openai";
|
|
14
|
+
readonly to = "gemini";
|
|
15
|
+
private extractInstructionText;
|
|
16
|
+
private parseToolArgumentsToObject;
|
|
17
|
+
private buildToolCallIdToNameMap;
|
|
18
|
+
onBeforeRequest(ctx: MutableRequestContext): Promise<void>;
|
|
19
|
+
private buildGeminiRequest;
|
|
20
|
+
private cleanSchema;
|
|
21
|
+
onResponse(ctx: ResponseContext): Promise<Response | void>;
|
|
22
|
+
private mapGeminiErrorToOpenAIType;
|
|
23
|
+
private transformErrorResponse;
|
|
24
|
+
private isJsonLikeContentType;
|
|
25
|
+
private isLikelyGeminiErrorBody;
|
|
26
|
+
private convertGeminiResponseToOpenAI;
|
|
27
|
+
processStreamChunk(chunk: any, ctx: StreamChunkContext): Promise<any[] | null>;
|
|
28
|
+
/**
|
|
29
|
+
* flushStream - 此 transformer 不需要缓冲,返回空数组
|
|
30
|
+
*/
|
|
31
|
+
flushStream(ctx: StreamChunkContext): Promise<any[]>;
|
|
32
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AIConverter, TransformDirection } from './base';
|
|
2
|
+
export declare class ProtocolTransformerRegistry {
|
|
3
|
+
private static converters;
|
|
4
|
+
static register(from: string, to: string, ConverterClass: new () => AIConverter): void;
|
|
5
|
+
static get(from: string, to: string): AIConverter;
|
|
6
|
+
static has(from: string, to: string): boolean;
|
|
7
|
+
static getAllDirections(): TransformDirection[];
|
|
8
|
+
static clear(): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converter Utility Functions
|
|
3
|
+
*
|
|
4
|
+
* 提供转换器使用的通用工具函数
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* 生成 Anthropic 风格的消息 ID
|
|
8
|
+
*
|
|
9
|
+
* @returns 格式为 msg_xxxxxxxxxxxxxxxxxxxxxxxx 的 ID(24位十六进制)
|
|
10
|
+
*/
|
|
11
|
+
export declare function generateAnthropicMessageId(): string;
|
|
12
|
+
/**
|
|
13
|
+
* 生成 OpenAI 风格的聊天完成 ID
|
|
14
|
+
*
|
|
15
|
+
* @returns 格式为 chatcmpl-xxxxxxxxxxxxxxxxxxxxxxxx 的 ID
|
|
16
|
+
*/
|
|
17
|
+
export declare function generateOpenAIChatCompletionId(): string;
|
|
18
|
+
/**
|
|
19
|
+
* 生成 Gemini 风格的候选 ID
|
|
20
|
+
*
|
|
21
|
+
* @returns 格式为 candidate-xxxxxxxx 的 ID
|
|
22
|
+
*/
|
|
23
|
+
export declare function generateGeminiCandidateId(): string;
|
|
24
|
+
/**
|
|
25
|
+
* 解析文本中的 <thinking> 标签
|
|
26
|
+
*
|
|
27
|
+
* @param text - 包含 <thinking> 标签的文本
|
|
28
|
+
* @returns 解析后的内容块数组
|
|
29
|
+
*/
|
|
30
|
+
export declare function parseThinkingTags(text: string): Array<{
|
|
31
|
+
type: string;
|
|
32
|
+
text?: string;
|
|
33
|
+
thinking?: string;
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* 将 thinking 块转换为 <thinking> 标签文本
|
|
37
|
+
*
|
|
38
|
+
* @param blocks - 内容块数组
|
|
39
|
+
* @returns 包含 <thinking> 标签的文本
|
|
40
|
+
*/
|
|
41
|
+
export declare function convertThinkingBlocksToTags(blocks: any[]): string;
|
|
42
|
+
/**
|
|
43
|
+
* 映射 Anthropic stop_reason 到 OpenAI finish_reason
|
|
44
|
+
*
|
|
45
|
+
* @param stopReason - Anthropic stop_reason
|
|
46
|
+
* @returns OpenAI finish_reason
|
|
47
|
+
*/
|
|
48
|
+
export declare function mapAnthropicStopReasonToOpenAI(stopReason: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* 映射 OpenAI finish_reason 到 Anthropic stop_reason
|
|
51
|
+
*
|
|
52
|
+
* @param finishReason - OpenAI finish_reason
|
|
53
|
+
* @returns Anthropic stop_reason
|
|
54
|
+
*/
|
|
55
|
+
export declare function mapOpenAIFinishReasonToAnthropic(finishReason: string): string;
|
|
56
|
+
/**
|
|
57
|
+
* 安全解析 JSON 字符串
|
|
58
|
+
*
|
|
59
|
+
* @param jsonString - JSON 字符串
|
|
60
|
+
* @param defaultValue - 解析失败时的默认值
|
|
61
|
+
* @returns 解析结果或默认值
|
|
62
|
+
*/
|
|
63
|
+
export declare function safeJsonParse<T = any>(jsonString: string, defaultValue?: T): T;
|
|
64
|
+
/**
|
|
65
|
+
* 安全 JSON 字符串化
|
|
66
|
+
*
|
|
67
|
+
* @param obj - 要字符串化的对象
|
|
68
|
+
* @param defaultValue - 字符串化失败时的默认值
|
|
69
|
+
* @returns JSON 字符串或默认值
|
|
70
|
+
*/
|
|
71
|
+
export declare function safeJsonStringify(obj: any, defaultValue?: string): string;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LLMProtocolAdapter } from '../../core/adapter';
|
|
2
|
+
import type { CanonicalRequest, CanonicalResponse, CanonicalStreamEvent, ConversionContext } from '../../core/types';
|
|
3
|
+
import { OpenAIToAnthropicRequestConversion } from '../openai-anthropic/request-conversion';
|
|
4
|
+
type JsonRecord = Record<string, unknown>;
|
|
5
|
+
export declare class AnthropicAdapter implements LLMProtocolAdapter<JsonRecord, JsonRecord, unknown> {
|
|
6
|
+
private readonly openAIToAnthropic;
|
|
7
|
+
readonly provider: "anthropic";
|
|
8
|
+
constructor(openAIToAnthropic?: OpenAIToAnthropicRequestConversion);
|
|
9
|
+
toCanonicalRequest(request: JsonRecord, context: ConversionContext): CanonicalRequest;
|
|
10
|
+
fromCanonicalRequest(request: CanonicalRequest, context: ConversionContext): JsonRecord;
|
|
11
|
+
toCanonicalResponse(response: JsonRecord, context: ConversionContext): CanonicalResponse;
|
|
12
|
+
fromCanonicalResponse(response: CanonicalResponse): JsonRecord;
|
|
13
|
+
toCanonicalStreamEvent(event: unknown): CanonicalStreamEvent;
|
|
14
|
+
fromCanonicalStreamEvent(event: CanonicalStreamEvent): unknown;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './anthropic-adapter';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface OpenAIMessagesCompatibilityNormalizerOptions {
|
|
2
|
+
strictValidation?: boolean;
|
|
3
|
+
allowShortPathAlias?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export interface OpenAIMessagesCompatibilityRequestLike {
|
|
6
|
+
method: string;
|
|
7
|
+
url: {
|
|
8
|
+
pathname: string;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
export type OpenAIMessagesCompatibilityJsonObject = Record<string, unknown>;
|
|
12
|
+
export type OpenAIMessagesCompatibilityBodyValidationResult = {
|
|
13
|
+
ok: true;
|
|
14
|
+
body: OpenAIMessagesCompatibilityJsonObject;
|
|
15
|
+
} | {
|
|
16
|
+
ok: false;
|
|
17
|
+
message: string;
|
|
18
|
+
};
|
|
19
|
+
export declare class OpenAIMessagesCompatibilityNormalizer {
|
|
20
|
+
private readonly strictValidation;
|
|
21
|
+
private readonly allowShortPathAlias;
|
|
22
|
+
constructor(options?: OpenAIMessagesCompatibilityNormalizerOptions);
|
|
23
|
+
shouldHandleRequest(ctx: OpenAIMessagesCompatibilityRequestLike): boolean;
|
|
24
|
+
validateAndNormalizeBody(rawBody: unknown): OpenAIMessagesCompatibilityBodyValidationResult;
|
|
25
|
+
isOpenAIResponsePayload(payload: unknown): boolean;
|
|
26
|
+
isOpenAIStreamChunk(chunk: unknown): boolean;
|
|
27
|
+
buildBadRequest(message: string): Response;
|
|
28
|
+
private normalizePathname;
|
|
29
|
+
private collectConflictingFields;
|
|
30
|
+
private parseToolsInput;
|
|
31
|
+
private normalizeSingleTool;
|
|
32
|
+
private normalizeTools;
|
|
33
|
+
private normalizeToolChoice;
|
|
34
|
+
private ensureAssistantToolCallReasoningContent;
|
|
35
|
+
private normalizeMessage;
|
|
36
|
+
private normalizeToolCallId;
|
|
37
|
+
private normalizeToolResultContent;
|
|
38
|
+
private extractThinkingText;
|
|
39
|
+
private normalizeUserMessageWithToolResults;
|
|
40
|
+
private normalizeAssistantMessageWithToolUse;
|
|
41
|
+
private normalizeContentPart;
|
|
42
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LLMProtocolAdapter } from '../../core/adapter';
|
|
2
|
+
import type { CanonicalRequest, CanonicalResponse, CanonicalStreamEvent, ConversionContext } from '../../core/types';
|
|
3
|
+
import { OpenAIProtocolConversion } from './protocol-conversion';
|
|
4
|
+
type JsonRecord = Record<string, unknown>;
|
|
5
|
+
export declare class OpenAIAdapter implements LLMProtocolAdapter<JsonRecord, JsonRecord, unknown> {
|
|
6
|
+
private readonly protocolConversion;
|
|
7
|
+
readonly provider: "openai";
|
|
8
|
+
constructor(protocolConversion?: OpenAIProtocolConversion);
|
|
9
|
+
toCanonicalRequest(request: JsonRecord, context: ConversionContext): CanonicalRequest;
|
|
10
|
+
fromCanonicalRequest(request: CanonicalRequest): JsonRecord;
|
|
11
|
+
toCanonicalResponse(response: JsonRecord, context: ConversionContext): CanonicalResponse;
|
|
12
|
+
fromCanonicalResponse(response: CanonicalResponse): JsonRecord;
|
|
13
|
+
toCanonicalStreamEvent(event: unknown): CanonicalStreamEvent;
|
|
14
|
+
fromCanonicalStreamEvent(event: CanonicalStreamEvent): unknown;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type JsonRecord = Record<string, unknown>;
|
|
2
|
+
export interface OpenAIProtocolConversionOptions {
|
|
3
|
+
trimWhitespace?: boolean;
|
|
4
|
+
}
|
|
5
|
+
export declare class OpenAIProtocolConversion {
|
|
6
|
+
private readonly trimWhitespace;
|
|
7
|
+
constructor(options?: OpenAIProtocolConversionOptions);
|
|
8
|
+
isResponsesPath(pathname: string): boolean;
|
|
9
|
+
isReasoningContext(body: JsonRecord): boolean;
|
|
10
|
+
normalizeResponsesReasoningBody(body: JsonRecord): JsonRecord;
|
|
11
|
+
ensureAssistantToolUseReasoningContent(response: Response): Promise<Response>;
|
|
12
|
+
ensureMessagesStreamCompatibility(events: unknown[], ctx: {
|
|
13
|
+
streamState: Map<string, unknown>;
|
|
14
|
+
}): unknown[];
|
|
15
|
+
convertChatMessagesToResponsesInput(messages: unknown): {
|
|
16
|
+
input: JsonRecord[];
|
|
17
|
+
instructions?: string;
|
|
18
|
+
};
|
|
19
|
+
mapChatToolsToResponsesTools(chatTools: unknown): JsonRecord[];
|
|
20
|
+
convertResponsesInputToMessages(input: unknown): JsonRecord[];
|
|
21
|
+
normalizeResponsesMessageContent(content: unknown): unknown;
|
|
22
|
+
private normalizeMessageCollection;
|
|
23
|
+
private normalizeAssistantToolCallCandidate;
|
|
24
|
+
private extractThinkingTextFromAnthropicContent;
|
|
25
|
+
private ensureMessageStartReasoningContent;
|
|
26
|
+
private ensureMessageDeltaUsage;
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './request-conversion';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { OpenAIProtocolConversion } from '../openai/protocol-conversion';
|
|
2
|
+
export interface OpenAIToAnthropicRequestConversionResult {
|
|
3
|
+
pathname: '/v1/messages';
|
|
4
|
+
body: Record<string, unknown>;
|
|
5
|
+
}
|
|
6
|
+
export declare class OpenAIToAnthropicRequestConversion {
|
|
7
|
+
private readonly protocolConversion;
|
|
8
|
+
constructor(protocolConversion?: OpenAIProtocolConversion);
|
|
9
|
+
convert(pathname: string, body: unknown): OpenAIToAnthropicRequestConversionResult | null;
|
|
10
|
+
private normalizeOpenAIRequestBody;
|
|
11
|
+
private convertTools;
|
|
12
|
+
private mapOpenAIToolChoiceToAnthropic;
|
|
13
|
+
private extractInstructionText;
|
|
14
|
+
private validateAndCleanToolCalls;
|
|
15
|
+
private parseImageSource;
|
|
16
|
+
private normalizeToolResultContent;
|
|
17
|
+
private convertToolResultPart;
|
|
18
|
+
private convertToolMessageToResultBlock;
|
|
19
|
+
private convertMessages;
|
|
20
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { LLMProvider } from '../core/types';
|
|
2
|
+
export interface ProviderCapabilities {
|
|
3
|
+
supportsChatCompletions?: boolean;
|
|
4
|
+
supportsResponsesApi?: boolean;
|
|
5
|
+
supportsToolCalls?: boolean;
|
|
6
|
+
supportsReasoning?: boolean;
|
|
7
|
+
supportsStreaming?: boolean;
|
|
8
|
+
supportsVision?: boolean;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}
|
|
11
|
+
export interface ProviderDescriptor {
|
|
12
|
+
provider: LLMProvider;
|
|
13
|
+
displayName?: string;
|
|
14
|
+
aliases?: string[];
|
|
15
|
+
capabilities?: ProviderCapabilities;
|
|
16
|
+
metadata?: Record<string, unknown>;
|
|
17
|
+
}
|
|
18
|
+
export declare class LLMProviderCatalog {
|
|
19
|
+
private readonly descriptors;
|
|
20
|
+
private readonly aliasToProvider;
|
|
21
|
+
register(descriptor: ProviderDescriptor): void;
|
|
22
|
+
unregister(provider: LLMProvider): void;
|
|
23
|
+
get(provider: LLMProvider | string): ProviderDescriptor | undefined;
|
|
24
|
+
has(provider: LLMProvider | string): boolean;
|
|
25
|
+
list(): ProviderDescriptor[];
|
|
26
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './core/registry';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './llms-runtime';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { LLMProtocolAdapter } from '../core/adapter';
|
|
2
|
+
import { LLMProtocolAdapterRegistry } from '../core/registry';
|
|
3
|
+
import { LLMProtocolConversionService } from '../core/conversion-service';
|
|
4
|
+
import type { LLMProvider } from '../core/types';
|
|
5
|
+
import { LLMProviderCatalog, type ProviderDescriptor } from '../providers/provider-catalog';
|
|
6
|
+
export interface LLMSRuntimeOptions {
|
|
7
|
+
adapterRegistry?: LLMProtocolAdapterRegistry;
|
|
8
|
+
conversionService?: LLMProtocolConversionService;
|
|
9
|
+
providerCatalog?: LLMProviderCatalog;
|
|
10
|
+
}
|
|
11
|
+
export interface RuntimeAdapterRegistration {
|
|
12
|
+
adapter: LLMProtocolAdapter;
|
|
13
|
+
descriptor?: ProviderDescriptor;
|
|
14
|
+
}
|
|
15
|
+
export declare class LLMSRuntime {
|
|
16
|
+
private readonly adapterRegistry;
|
|
17
|
+
private readonly conversionService;
|
|
18
|
+
private readonly providerCatalog;
|
|
19
|
+
constructor(options?: LLMSRuntimeOptions);
|
|
20
|
+
registerAdapter(adapter: LLMProtocolAdapter, descriptor?: ProviderDescriptor): void;
|
|
21
|
+
registerAdapters(registrations: RuntimeAdapterRegistration[]): void;
|
|
22
|
+
unregisterProvider(provider: LLMProvider): void;
|
|
23
|
+
convertRequest<T = unknown>(from: LLMProvider, to: LLMProvider, request: unknown, metadata?: Record<string, unknown>): T;
|
|
24
|
+
convertResponse<T = unknown>(from: LLMProvider, to: LLMProvider, response: unknown, metadata?: Record<string, unknown>): T;
|
|
25
|
+
convertStreamEvent<T = unknown>(from: LLMProvider, to: LLMProvider, event: unknown, metadata?: Record<string, unknown>): T | null;
|
|
26
|
+
getProviderCatalog(): LLMProviderCatalog;
|
|
27
|
+
getAdapterRegistry(): LLMProtocolAdapterRegistry;
|
|
28
|
+
getConversionService(): LLMProtocolConversionService;
|
|
29
|
+
listProviders(): ProviderDescriptor[];
|
|
30
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './core/conversion-service';
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './core/types';
|