@jeffusion/bungee-llms 5.20.0 → 5.22.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.
Files changed (32) hide show
  1. package/README.md +8 -31
  2. package/dist/index.d.ts +1 -1
  3. package/dist/index.js +2158 -5530
  4. package/dist/plugin-api.d.ts +1 -4
  5. package/dist/plugin-api.js +4069 -8408
  6. package/dist/protocol-session/index.d.ts +14 -0
  7. package/dist/protocol-session/request.d.ts +5 -0
  8. package/dist/protocol-session/response.d.ts +23 -0
  9. package/dist/protocol-session/schema.d.ts +5 -0
  10. package/dist/protocol-session/stream.d.ts +35 -0
  11. package/dist/protocol-session/types.d.ts +48 -0
  12. package/dist/protocol-session/validation.d.ts +5 -0
  13. package/dist/providers/openai/index.d.ts +0 -1
  14. package/dist/responses-codec/common.d.ts +17 -2
  15. package/dist/responses-codec/events.d.ts +7 -1
  16. package/dist/responses-codec/index.d.ts +1 -1
  17. package/dist/responses-codec/request-preferences.d.ts +3 -0
  18. package/dist/responses-codec/request.d.ts +3 -1
  19. package/dist/responses-codec/web-search.d.ts +3 -0
  20. package/package.json +3 -3
  21. package/dist/protocol-converters/anthropic-to-gemini.converter.d.ts +0 -62
  22. package/dist/protocol-converters/anthropic-to-openai.converter.d.ts +0 -110
  23. package/dist/protocol-converters/base.d.ts +0 -38
  24. package/dist/protocol-converters/default-registry.d.ts +0 -1
  25. package/dist/protocol-converters/gemini-to-anthropic.converter.d.ts +0 -57
  26. package/dist/protocol-converters/gemini-to-openai.converter.d.ts +0 -31
  27. package/dist/protocol-converters/index.d.ts +0 -10
  28. package/dist/protocol-converters/openai-to-anthropic.converter.d.ts +0 -27
  29. package/dist/protocol-converters/openai-to-gemini.converter.d.ts +0 -32
  30. package/dist/protocol-converters/registry.d.ts +0 -9
  31. package/dist/protocol-converters/utils.d.ts +0 -71
  32. package/dist/providers/openai/messages-compat-normalization.d.ts +0 -42
@@ -0,0 +1,14 @@
1
+ import { type ProtocolSession, type ProtocolSessionContext } from './types';
2
+ export * from './types';
3
+ export declare const PROTOCOL_CONVERSION_RULES_VERSION = "1.0.1";
4
+ export declare function describeProtocolConversion(): {
5
+ rulesVersion: string;
6
+ protocols: ("chat_completions" | "anthropic_messages" | "responses" | "gemini_generate_content")[];
7
+ matrix: {
8
+ readonly sourceProtocol: "chat_completions" | "anthropic_messages" | "responses" | "gemini_generate_content";
9
+ readonly targetProtocol: "chat_completions" | "anthropic_messages" | "responses" | "gemini_generate_content";
10
+ readonly mode: "passthrough" | "unsupported" | "convert";
11
+ }[];
12
+ };
13
+ /** One request/attempt, bounded retained state, plain own-property functions for local service facades. */
14
+ export declare function createProtocolSession(context: ProtocolSessionContext): ProtocolSession;
@@ -0,0 +1,5 @@
1
+ import { type JsonRecord } from '../responses-codec/common';
2
+ import type { LLMProtocol, ProtocolSessionContext, ProtocolRequestConversion } from './types';
3
+ /** The normative history is Responses items, not a provider plugin conversion chain. */
4
+ export declare function canonicalRequest(raw: unknown, protocol: LLMProtocol, model: string): JsonRecord;
5
+ export declare function convertProtocolRequest(raw: unknown, context: ProtocolSessionContext): ProtocolRequestConversion;
@@ -0,0 +1,23 @@
1
+ import { type JsonRecord, type ResponsesToolNames } from '../responses-codec/common';
2
+ import type { LLMProtocol, ProtocolSessionContext } from './types';
3
+ export declare function safeProtocolError(): JsonRecord;
4
+ export declare function validateUsage(raw: unknown, protocol: LLMProtocol): void;
5
+ export declare function validateProviderResponse(raw: unknown, protocol: LLMProtocol): JsonRecord;
6
+ export declare function validateAnthropicBlock(b: JsonRecord, path: string): void;
7
+ export declare function validateCanonicalResponse(raw: unknown, context: ProtocolSessionContext, itemOnly?: boolean): JsonRecord;
8
+ export declare function canonicalUsage(raw: unknown): JsonRecord;
9
+ export declare function wireUsage(raw: unknown, protocol: LLMProtocol): JsonRecord;
10
+ export declare function responseFromCanonical(raw: unknown, protocol: LLMProtocol, context: ProtocolSessionContext): JsonRecord;
11
+ /** Gemini chunks carry complete function-call objects, never JSON argument deltas. */
12
+ export declare class GeminiCanonicalDecoder {
13
+ private context;
14
+ private encoder;
15
+ private serial;
16
+ private ended;
17
+ private tools;
18
+ private ids;
19
+ constructor(context: ProtocolSessionContext, names: ResponsesToolNames);
20
+ push(raw: unknown): JsonRecord[];
21
+ finish(): JsonRecord[];
22
+ }
23
+ export declare function canonicalResponse(raw: unknown, context: ProtocolSessionContext, names: ResponsesToolNames): JsonRecord;
@@ -0,0 +1,5 @@
1
+ import { type JsonRecord } from '../responses-codec/common';
2
+ /** Gemini's Schema is an OpenAPI dialect, not JSON Schema. Preserve supported
3
+ * constraints exactly and reject provider-specific ordering or unknown extensions.
4
+ */
5
+ export declare function geminiSchemaToJson(raw: unknown, path: string, code?: string, depth?: number): JsonRecord;
@@ -0,0 +1,35 @@
1
+ import { type JsonRecord } from '../responses-codec/common';
2
+ import type { LLMProtocol, ProtocolSessionContext } from './types';
3
+ /** Validate Responses event ordering and final snapshots before rendering another wire protocol. */
4
+ export declare class CanonicalStreamValidator {
5
+ private context;
6
+ private items;
7
+ private started;
8
+ private ended;
9
+ private sequence;
10
+ private retained;
11
+ private partCount;
12
+ private responseId?;
13
+ constructor(context: ProtocolSessionContext);
14
+ push(raw: unknown): JsonRecord[];
15
+ private retain;
16
+ finish(): JsonRecord[];
17
+ }
18
+ export declare class CanonicalStreamRenderer {
19
+ private protocol;
20
+ private context;
21
+ private id;
22
+ private created;
23
+ private toolCount;
24
+ private started;
25
+ private items;
26
+ private blocks;
27
+ private nextBlock;
28
+ private toolIndexes;
29
+ constructor(protocol: LLMProtocol, context: ProtocolSessionContext);
30
+ push(events: JsonRecord[]): JsonRecord[];
31
+ private chat;
32
+ private gemini;
33
+ private blockKey;
34
+ private render;
35
+ }
@@ -0,0 +1,48 @@
1
+ import type { ResponsesCodecCapabilities, ResponsesConversionDiagnostic, ResponsesToolNames } from '../responses-codec';
2
+ export declare const LLM_PROTOCOLS: readonly ["responses", "chat_completions", "anthropic_messages", "gemini_generate_content"];
3
+ export type LLMProtocol = typeof LLM_PROTOCOLS[number];
4
+ export type ProtocolJsonObject = Record<string, unknown>;
5
+ /** Every mapping is supplied by the capability owner, never inferred from a reasoning flag. */
6
+ export interface ProtocolReasoningPolicy {
7
+ effortMap?: Readonly<Record<string, string>>;
8
+ /** Verified target effort for source budget/mode policies that have no effort label. */
9
+ targetEffort?: string;
10
+ anthropicThinkingBudget?: number;
11
+ anthropicThinkingMode?: 'adaptive' | 'enabled' | 'disabled';
12
+ geminiThinkingBudget?: number;
13
+ geminiThinkingLevel?: string;
14
+ }
15
+ export interface ProtocolSessionCapabilities extends ResponsesCodecCapabilities {
16
+ anthropicStructuredOutput?: boolean;
17
+ anthropicStrictTools?: boolean;
18
+ anthropicEffort?: boolean;
19
+ geminiJsonSchema?: boolean;
20
+ }
21
+ export interface ProtocolSessionContext {
22
+ sourceProtocol: LLMProtocol;
23
+ targetProtocol: LLMProtocol;
24
+ /** Target model; caller owns routing and source URL validation. */
25
+ model: string;
26
+ /** Transport-derived mode for protocols such as Gemini whose stream flag is in the URL. */
27
+ streaming?: boolean;
28
+ responseModel?: string;
29
+ capabilities?: ProtocolSessionCapabilities;
30
+ reasoningPolicy?: ProtocolReasoningPolicy;
31
+ }
32
+ export interface ProtocolRequestConversion {
33
+ body: ProtocolJsonObject;
34
+ canonicalHistory: ProtocolJsonObject[];
35
+ diagnostics: ResponsesConversionDiagnostic[];
36
+ toolNames: ResponsesToolNames;
37
+ streaming: boolean;
38
+ }
39
+ /** Requests flow source→target; responses and JSON stream events flow target→source.
40
+ * Transport framing, [DONE], HTTP errors, readers and cancellation are caller-owned.
41
+ */
42
+ export interface ProtocolSession {
43
+ convertRequest(raw: unknown): ProtocolRequestConversion;
44
+ convertResponse(raw: unknown): ProtocolJsonObject;
45
+ push(event: unknown): ProtocolJsonObject[];
46
+ finish(): ProtocolJsonObject[];
47
+ dispose(): void;
48
+ }
@@ -0,0 +1,5 @@
1
+ import { type JsonRecord } from '../responses-codec/common';
2
+ export declare function fields(value: JsonRecord, allowed: readonly string[], path: string, code?: string): void;
3
+ export declare function bool(value: unknown, path: string): boolean;
4
+ export declare function integer(value: unknown, path: string, min?: number): number;
5
+ export declare function textParts(raw: unknown, path: string, style: 'chat' | 'anthropic' | 'gemini', role: string): JsonRecord[];
@@ -1,3 +1,2 @@
1
1
  export * from './protocol-conversion';
2
- export * from './messages-compat-normalization';
3
2
  export * from './openai-adapter';
@@ -16,16 +16,31 @@ export interface ResponsesCodecLimits {
16
16
  export declare const DEFAULT_RESPONSES_CODEC_LIMITS: Readonly<ResponsesCodecLimits>;
17
17
  export interface ResponsesCodecCapabilities {
18
18
  reasoningEffort?: boolean;
19
+ /** Plain reasoning history support is independent of effort parameter mapping. */
20
+ reasoningHistory?: boolean;
21
+ anthropicStrictTools?: boolean;
22
+ /** Include original names in alias descriptions so model-facing identity is retained. */
23
+ preserveToolIdentityDescription?: boolean;
24
+ preserveRefusalContent?: boolean;
25
+ /** Codex declares optional hosted search even when the selected model has no search backend. */
26
+ omitOptionalWebSearch?: boolean;
19
27
  /** Explicit provider-approved thinking budget; do not guess budgets from effort labels. */
20
28
  anthropicThinkingBudget?: number;
21
29
  maxOutputTokens?: number;
22
30
  limits?: Partial<ResponsesCodecLimits>;
23
31
  }
32
+ export interface ResponsesConversionDiagnostic {
33
+ param: string;
34
+ action: 'mapped' | 'omitted';
35
+ reason: string;
36
+ }
24
37
  export declare class ResponsesCodecError extends Error {
25
38
  readonly code: string;
26
- constructor(code: string, message: string);
39
+ readonly param?: string | undefined;
40
+ constructor(code: string, message: string, param?: string | undefined);
27
41
  }
28
- export declare function fail(code: string, message: string): never;
42
+ export declare function fail(code: string, message: string, param?: string): never;
43
+ export declare function atParam<T>(param: string, run: () => T): T;
29
44
  export declare function record(value: unknown, where: string): JsonRecord;
30
45
  export declare function string(value: unknown, where: string, nonempty?: boolean): string;
31
46
  export declare function list(value: unknown, where: string): unknown[];
@@ -7,6 +7,7 @@ export declare class ResponsesEventEncoder {
7
7
  readonly protocol: ResponsesProtocol;
8
8
  readonly model: string;
9
9
  readonly toolNames: ResponsesToolNames;
10
+ private readonly options;
10
11
  private readonly budget;
11
12
  private readonly id;
12
13
  private readonly createdAt;
@@ -23,7 +24,12 @@ export declare class ResponsesEventEncoder {
23
24
  private poisoned;
24
25
  private sequence;
25
26
  private retained;
26
- constructor(protocol: ResponsesProtocol, model: string, toolNames?: ResponsesToolNames, configuredLimits?: Partial<ResponsesCodecLimits>);
27
+ private lastKind?;
28
+ private contentSerial;
29
+ constructor(protocol: ResponsesProtocol, model: string, toolNames?: ResponsesToolNames, configuredLimits?: Partial<ResponsesCodecLimits>, options?: {
30
+ preserveContentOrder?: boolean;
31
+ });
32
+ private contentState;
27
33
  private event;
28
34
  private start;
29
35
  private retain;
@@ -1,4 +1,4 @@
1
1
  export { decodeResponsesRequest, type DecodedResponsesRequest } from './request';
2
2
  export { encodeResponsesResult } from './result';
3
3
  export { ResponsesEventEncoder } from './events';
4
- export { ResponsesCodecError, DEFAULT_RESPONSES_CODEC_LIMITS, type ResponsesProtocol, type ResponsesToolName, type ResponsesToolNames, type ResponsesCodecCapabilities, type ResponsesCodecLimits } from './common';
4
+ export { ResponsesCodecError, DEFAULT_RESPONSES_CODEC_LIMITS, type ResponsesProtocol, type ResponsesToolName, type ResponsesToolNames, type ResponsesCodecCapabilities, type ResponsesCodecLimits, type ResponsesConversionDiagnostic } from './common';
@@ -0,0 +1,3 @@
1
+ import { type JsonRecord, type ResponsesCodecCapabilities, type ResponsesConversionDiagnostic, type ResponsesProtocol } from './common';
2
+ /** Known preferences may be omitted; output constraints are handled by the request renderer. */
3
+ export declare function applyResponsesPreferences(body: JsonRecord, result: JsonRecord, protocol: ResponsesProtocol, capabilities: ResponsesCodecCapabilities, maxTokens: unknown, diagnostics: ResponsesConversionDiagnostic[]): void;
@@ -1,7 +1,9 @@
1
- import { type JsonRecord, type ResponsesCodecCapabilities, type ResponsesProtocol, type ResponsesToolNames } from './common';
1
+ import { type JsonRecord, type ResponsesCodecCapabilities, type ResponsesConversionDiagnostic, type ResponsesProtocol, type ResponsesToolNames } from './common';
2
2
  export interface DecodedResponsesRequest {
3
3
  body: JsonRecord;
4
4
  toolNames: ResponsesToolNames;
5
+ canonicalInput: JsonRecord[];
6
+ diagnostics: ResponsesConversionDiagnostic[];
5
7
  }
6
8
  /** Converts only self-contained history. Reference resolution belongs to the caller. */
7
9
  export declare function decodeResponsesRequest(raw: unknown, protocol: ResponsesProtocol, capabilities?: ResponsesCodecCapabilities): DecodedResponsesRequest;
@@ -0,0 +1,3 @@
1
+ import { type JsonRecord } from './common';
2
+ /** Validate a known hosted declaration before an explicitly permitted omission. */
3
+ export declare function validateWebSearch(tool: JsonRecord, path: string): void;
package/package.json CHANGED
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@jeffusion/bungee-llms",
3
- "version": "5.20.0",
3
+ "version": "5.22.0",
4
4
  "description": "Extensible LLM adapters and protocol conversion package for Bungee",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "scripts": {
8
8
  "dev": "bun --watch src/index.ts",
9
9
  "build": "bun build src/index.ts src/plugin-api.ts --outdir dist --target bun && tsc -p tsconfig.build.json",
10
- "test": "echo 'No tests for llms package yet'",
10
+ "test": "bun test tests/",
11
11
  "prepublishOnly": "bun run build"
12
12
  },
13
13
  "dependencies": {
14
- "@jeffusion/bungee-types": "^5.20.0"
14
+ "@jeffusion/bungee-types": "^5.22.0"
15
15
  },
16
16
  "devDependencies": {
17
17
  "bun-types": "^1.3.2",
@@ -1,62 +0,0 @@
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
- }
@@ -1,110 +0,0 @@
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 readonly protocolConversion;
19
- private configuredApiMode?;
20
- setApiMode(mode: unknown): void;
21
- setRuntimeOptions(options: unknown): void;
22
- private resolveTargetApiMode;
23
- /**
24
- * 修改请求:转换为 OpenAI Chat Completions 格式
25
- */
26
- onBeforeRequest(ctx: MutableRequestContext): Promise<void>;
27
- private isAnthropicCountTokensPath;
28
- private buildOpenAICountTokensRequest;
29
- /**
30
- * 构建 OpenAI 请求
31
- */
32
- private buildOpenAIRequest;
33
- private isOpenAINumericOSeriesModel;
34
- private buildOpenAIResponsesRequest;
35
- private convertAnthropicSystemToInstructions;
36
- private convertAnthropicMessagesToResponsesInput;
37
- private convertAnthropicImageSourceToUrl;
38
- private mapAnthropicToolChoiceToResponses;
39
- private resolveAnthropicReasoningEffort;
40
- private supportsReasoningEffort;
41
- private convertSystemMessages;
42
- private sanitizeSystemText;
43
- private extractTextFromOpenAIContent;
44
- private normalizeOpenAISystemMessages;
45
- /**
46
- * 转换 User 消息
47
- */
48
- private normalizeToolResultContent;
49
- private convertUserMessage;
50
- private convertUserContentBlock;
51
- /**
52
- * 转换 Assistant 消息
53
- */
54
- private convertAssistantMessage;
55
- private normalizeOpenAIMessageContent;
56
- private normalizeToolParametersSchema;
57
- private cleanOpenAIToolSchema;
58
- private resolvePromptCacheKey;
59
- private normalizeJsonSchema;
60
- /**
61
- * 处理非流式响应:OpenAI → Anthropic
62
- */
63
- onResponse(ctx: ResponseContext): Promise<Response | void>;
64
- private extractCountTokensInput;
65
- private convertOpenAIErrorToAnthropic;
66
- private isJsonLikeContentType;
67
- private isLikelyOpenAIErrorBody;
68
- private isLikelyOpenAICountTokensBody;
69
- private isLikelyOpenAISuccessBody;
70
- private isResponsesApiBody;
71
- private extractReasoningSummaryTexts;
72
- private extractStrictResponsesReasoningText;
73
- private extractReasoningTextFromDeltaContentPart;
74
- private extractChatThinkingDelta;
75
- private getChatUsedIndices;
76
- private allocateChatContentBlockIndex;
77
- private ensureChatTextBlockStarted;
78
- private ensureChatThinkingBlockStarted;
79
- private closeChatNonToolBlock;
80
- private resolveChatToolIndex;
81
- private resolveResponsesReasoningIndex;
82
- private nextResponsesContentIndex;
83
- private resolveResponsesContentIndex;
84
- private ensureResponsesTextBlockStarted;
85
- private resolveResponsesToolIndex;
86
- private ensureResponsesThinkingBlockStarted;
87
- private emitResponsesThinkingDelta;
88
- private extractResponsesReasoningDeltaText;
89
- private convertOpenAIResponsesToAnthropic;
90
- private mapResponsesStopReason;
91
- private buildAnthropicUsageFromResponses;
92
- /**
93
- * 转换 OpenAI 响应为 Anthropic 格式
94
- */
95
- private convertOpenAIResponseToAnthropic;
96
- private parseToolArguments;
97
- /**
98
- * 处理流式响应:OpenAI chunk → Anthropic SSE
99
- */
100
- processStreamChunk(chunk: any, ctx: StreamChunkContext): Promise<any[] | null>;
101
- /**
102
- * 刷新流 - 确保流结束
103
- */
104
- flushStream(ctx: StreamChunkContext): Promise<any[]>;
105
- private isResponsesStreamChunk;
106
- private processResponsesStreamChunk;
107
- private finalizeResponsesStreamEvents;
108
- private extractOpenAIStreamUsage;
109
- private extractDeltaText;
110
- }
@@ -1,38 +0,0 @@
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
- /** Shared immutable JSON view owned by the gateway. */
10
- bodyHandle: {
11
- json(): Promise<unknown>;
12
- };
13
- [key: string]: any;
14
- }
15
- export interface StreamChunkContext {
16
- /** SSE metadata belongs to the transport envelope, not the JSON object. */
17
- sseEvent?: {
18
- event?: string;
19
- id?: string;
20
- retry?: string;
21
- comments?: string[];
22
- };
23
- streamState: Map<string, any>;
24
- chunkIndex?: number;
25
- isFirstChunk?: boolean;
26
- isLastChunk?: boolean;
27
- [key: string]: any;
28
- }
29
- export interface AIConverter {
30
- readonly from: string;
31
- readonly to: string;
32
- setRuntimeOptions?(options: unknown): void;
33
- onBeforeRequest?(ctx: MutableRequestContext): Promise<void>;
34
- onResponse?(ctx: ResponseContext): Promise<Response | void>;
35
- processStreamChunk?(chunk: any, ctx: StreamChunkContext): Promise<any[] | null>;
36
- flushStream?(ctx: StreamChunkContext): Promise<any[]>;
37
- }
38
- export type TransformDirection = `${string}-${string}`;
@@ -1 +0,0 @@
1
- export declare function registerDefaultProtocolConverters(): void;
@@ -1,57 +0,0 @@
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
- }
@@ -1,31 +0,0 @@
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
- }
@@ -1,10 +0,0 @@
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';
@@ -1,27 +0,0 @@
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
- }
@@ -1,32 +0,0 @@
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
- }
@@ -1,9 +0,0 @@
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
- }