@jsonstudio/llms 0.4.4 → 0.4.6
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/conversion/codec-registry.js +11 -1
- package/dist/conversion/codecs/anthropic-openai-codec.d.ts +13 -0
- package/dist/conversion/codecs/anthropic-openai-codec.js +18 -473
- package/dist/conversion/codecs/gemini-openai-codec.js +91 -48
- package/dist/conversion/codecs/responses-openai-codec.js +9 -2
- package/dist/conversion/hub/format-adapters/anthropic-format-adapter.js +3 -0
- package/dist/conversion/hub/format-adapters/chat-format-adapter.js +3 -0
- package/dist/conversion/hub/format-adapters/gemini-format-adapter.js +3 -0
- package/dist/conversion/hub/format-adapters/responses-format-adapter.d.ts +19 -0
- package/dist/conversion/hub/format-adapters/responses-format-adapter.js +9 -0
- package/dist/conversion/hub/node-support.js +3 -1
- package/dist/conversion/hub/pipeline/hub-pipeline.js +37 -32
- package/dist/conversion/hub/response/provider-response.js +1 -1
- package/dist/conversion/hub/response/response-mappers.js +1 -1
- package/dist/conversion/hub/response/response-runtime.js +109 -10
- package/dist/conversion/hub/semantic-mappers/anthropic-mapper.js +70 -156
- package/dist/conversion/hub/semantic-mappers/chat-mapper.js +63 -52
- package/dist/conversion/hub/semantic-mappers/gemini-mapper.js +76 -143
- package/dist/conversion/hub/semantic-mappers/responses-mapper.js +40 -160
- package/dist/conversion/hub/standardized-bridge.js +3 -0
- package/dist/conversion/hub/tool-governance/rules.js +2 -2
- package/dist/conversion/index.d.ts +5 -0
- package/dist/conversion/index.js +5 -0
- package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.d.ts +12 -0
- package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.js +100 -0
- package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.d.ts +15 -0
- package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.js +174 -0
- package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.d.ts +14 -0
- package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.js +166 -0
- package/dist/conversion/pipeline/codecs/v2/shared/openai-chat-helpers.d.ts +13 -0
- package/dist/conversion/pipeline/codecs/v2/shared/openai-chat-helpers.js +66 -0
- package/dist/conversion/pipeline/hooks/adapter-context.d.ts +7 -0
- package/dist/conversion/pipeline/hooks/adapter-context.js +18 -0
- package/dist/conversion/pipeline/hooks/protocol-hooks.d.ts +67 -0
- package/dist/conversion/pipeline/hooks/protocol-hooks.js +1 -0
- package/dist/conversion/pipeline/index.d.ts +35 -0
- package/dist/conversion/pipeline/index.js +103 -0
- package/dist/conversion/pipeline/meta/meta-bag.d.ts +20 -0
- package/dist/conversion/pipeline/meta/meta-bag.js +81 -0
- package/dist/conversion/pipeline/schema/canonical-chat.d.ts +18 -0
- package/dist/conversion/pipeline/schema/canonical-chat.js +1 -0
- package/dist/conversion/pipeline/schema/index.d.ts +1 -0
- package/dist/conversion/pipeline/schema/index.js +1 -0
- package/dist/conversion/responses/responses-openai-bridge.d.ts +48 -0
- package/dist/conversion/responses/responses-openai-bridge.js +157 -1146
- package/dist/conversion/shared/anthropic-message-utils.d.ts +12 -0
- package/dist/conversion/shared/anthropic-message-utils.js +587 -0
- package/dist/conversion/shared/bridge-actions.d.ts +39 -0
- package/dist/conversion/shared/bridge-actions.js +709 -0
- package/dist/conversion/shared/bridge-conversation-store.d.ts +41 -0
- package/dist/conversion/shared/bridge-conversation-store.js +279 -0
- package/dist/conversion/shared/bridge-id-utils.d.ts +7 -0
- package/dist/conversion/shared/bridge-id-utils.js +42 -0
- package/dist/conversion/shared/bridge-instructions.d.ts +1 -0
- package/dist/conversion/shared/bridge-instructions.js +113 -0
- package/dist/conversion/shared/bridge-message-types.d.ts +39 -0
- package/dist/conversion/shared/bridge-message-types.js +1 -0
- package/dist/conversion/shared/bridge-message-utils.d.ts +22 -0
- package/dist/conversion/shared/bridge-message-utils.js +473 -0
- package/dist/conversion/shared/bridge-metadata.d.ts +1 -0
- package/dist/conversion/shared/bridge-metadata.js +1 -0
- package/dist/conversion/shared/bridge-policies.d.ts +18 -0
- package/dist/conversion/shared/bridge-policies.js +276 -0
- package/dist/conversion/shared/bridge-request-adapter.d.ts +28 -0
- package/dist/conversion/shared/bridge-request-adapter.js +430 -0
- package/dist/conversion/shared/chat-output-normalizer.d.ts +4 -0
- package/dist/conversion/shared/chat-output-normalizer.js +56 -0
- package/dist/conversion/shared/chat-request-filters.js +24 -1
- package/dist/conversion/shared/gemini-tool-utils.d.ts +5 -0
- package/dist/conversion/shared/gemini-tool-utils.js +130 -0
- package/dist/conversion/shared/metadata-passthrough.d.ts +11 -0
- package/dist/conversion/shared/metadata-passthrough.js +57 -0
- package/dist/conversion/shared/output-content-normalizer.d.ts +12 -0
- package/dist/conversion/shared/output-content-normalizer.js +119 -0
- package/dist/conversion/shared/reasoning-normalizer.d.ts +21 -0
- package/dist/conversion/shared/reasoning-normalizer.js +368 -0
- package/dist/conversion/shared/reasoning-tool-normalizer.d.ts +12 -0
- package/dist/conversion/shared/reasoning-tool-normalizer.js +132 -0
- package/dist/conversion/shared/reasoning-tool-parser.d.ts +10 -0
- package/dist/conversion/shared/reasoning-tool-parser.js +95 -0
- package/dist/conversion/shared/reasoning-utils.d.ts +2 -0
- package/dist/conversion/shared/reasoning-utils.js +42 -0
- package/dist/conversion/shared/responses-conversation-store.js +5 -11
- package/dist/conversion/shared/responses-message-utils.d.ts +15 -0
- package/dist/conversion/shared/responses-message-utils.js +206 -0
- package/dist/conversion/shared/responses-output-builder.d.ts +15 -0
- package/dist/conversion/shared/responses-output-builder.js +179 -0
- package/dist/conversion/shared/responses-output-utils.d.ts +7 -0
- package/dist/conversion/shared/responses-output-utils.js +108 -0
- package/dist/conversion/shared/responses-request-adapter.d.ts +28 -0
- package/dist/conversion/shared/responses-request-adapter.js +9 -40
- package/dist/conversion/shared/responses-response-utils.d.ts +3 -0
- package/dist/conversion/shared/responses-response-utils.js +209 -0
- package/dist/conversion/shared/responses-tool-utils.d.ts +12 -0
- package/dist/conversion/shared/responses-tool-utils.js +90 -0
- package/dist/conversion/shared/responses-types.d.ts +33 -0
- package/dist/conversion/shared/responses-types.js +1 -0
- package/dist/conversion/shared/tool-call-utils.d.ts +11 -0
- package/dist/conversion/shared/tool-call-utils.js +56 -0
- package/dist/conversion/shared/tool-governor.js +5 -0
- package/dist/conversion/shared/tool-mapping.d.ts +19 -0
- package/dist/conversion/shared/tool-mapping.js +124 -0
- package/dist/conversion/shared/tool-normalizers.d.ts +4 -0
- package/dist/conversion/shared/tool-normalizers.js +84 -0
- package/dist/router/virtual-router/bootstrap.js +18 -3
- package/dist/router/virtual-router/provider-registry.js +4 -2
- package/dist/router/virtual-router/types.d.ts +212 -0
- package/dist/sse/index.d.ts +38 -2
- package/dist/sse/index.js +27 -0
- package/dist/sse/json-to-sse/anthropic-json-to-sse-converter.d.ts +14 -0
- package/dist/sse/json-to-sse/anthropic-json-to-sse-converter.js +106 -73
- package/dist/sse/json-to-sse/chat-json-to-sse-converter.js +6 -2
- package/dist/sse/json-to-sse/gemini-json-to-sse-converter.d.ts +14 -0
- package/dist/sse/json-to-sse/gemini-json-to-sse-converter.js +99 -0
- package/dist/sse/json-to-sse/index.d.ts +7 -0
- package/dist/sse/json-to-sse/index.js +2 -0
- package/dist/sse/json-to-sse/sequencers/anthropic-sequencer.d.ts +13 -0
- package/dist/sse/json-to-sse/sequencers/anthropic-sequencer.js +150 -0
- package/dist/sse/json-to-sse/sequencers/chat-sequencer.d.ts +39 -0
- package/dist/sse/json-to-sse/sequencers/chat-sequencer.js +49 -3
- package/dist/sse/json-to-sse/sequencers/gemini-sequencer.d.ts +10 -0
- package/dist/sse/json-to-sse/sequencers/gemini-sequencer.js +95 -0
- package/dist/sse/json-to-sse/sequencers/responses-sequencer.js +31 -5
- package/dist/sse/registry/sse-codec-registry.d.ts +32 -0
- package/dist/sse/registry/sse-codec-registry.js +30 -1
- package/dist/sse/shared/reasoning-dispatcher.d.ts +10 -0
- package/dist/sse/shared/reasoning-dispatcher.js +25 -0
- package/dist/sse/shared/responses-output-normalizer.d.ts +12 -0
- package/dist/sse/shared/responses-output-normalizer.js +45 -0
- package/dist/sse/shared/serializers/anthropic-event-serializer.d.ts +2 -0
- package/dist/sse/shared/serializers/anthropic-event-serializer.js +9 -0
- package/dist/sse/shared/serializers/gemini-event-serializer.d.ts +2 -0
- package/dist/sse/shared/serializers/gemini-event-serializer.js +5 -0
- package/dist/sse/shared/serializers/index.d.ts +41 -0
- package/dist/sse/shared/serializers/index.js +2 -0
- package/dist/sse/shared/writer.d.ts +127 -0
- package/dist/sse/shared/writer.js +37 -1
- package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +11 -0
- package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.js +92 -127
- package/dist/sse/sse-to-json/builders/anthropic-response-builder.d.ts +16 -0
- package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +151 -0
- package/dist/sse/sse-to-json/builders/response-builder.d.ts +165 -0
- package/dist/sse/sse-to-json/builders/response-builder.js +27 -6
- package/dist/sse/sse-to-json/chat-sse-to-json-converter.d.ts +114 -0
- package/dist/sse/sse-to-json/chat-sse-to-json-converter.js +79 -3
- package/dist/sse/sse-to-json/gemini-sse-to-json-converter.d.ts +13 -0
- package/dist/sse/sse-to-json/gemini-sse-to-json-converter.js +160 -0
- package/dist/sse/sse-to-json/index.d.ts +7 -0
- package/dist/sse/sse-to-json/index.js +2 -0
- package/dist/sse/sse-to-json/parsers/sse-parser.js +53 -1
- package/dist/sse/types/anthropic-types.d.ts +170 -0
- package/dist/sse/types/anthropic-types.js +8 -5
- package/dist/sse/types/chat-types.d.ts +10 -0
- package/dist/sse/types/chat-types.js +2 -1
- package/dist/sse/types/core-interfaces.d.ts +1 -1
- package/dist/sse/types/gemini-types.d.ts +116 -0
- package/dist/sse/types/gemini-types.js +5 -0
- package/dist/sse/types/index.d.ts +5 -2
- package/dist/sse/types/index.js +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Virtual Router 类型定义
|
|
3
|
+
*/
|
|
4
|
+
import type { StandardizedRequest } from '../../conversion/hub/types/standardized.js';
|
|
5
|
+
export declare const DEFAULT_ROUTE = "default";
|
|
6
|
+
export declare const ROUTE_PRIORITY: string[];
|
|
7
|
+
export type RoutingPools = Record<string, string[]>;
|
|
8
|
+
export interface ProviderAuthConfig {
|
|
9
|
+
type: 'apiKey' | 'oauth';
|
|
10
|
+
secretRef?: string;
|
|
11
|
+
value?: string;
|
|
12
|
+
tokenFile?: string;
|
|
13
|
+
tokenUrl?: string;
|
|
14
|
+
deviceCodeUrl?: string;
|
|
15
|
+
clientId?: string;
|
|
16
|
+
clientSecret?: string;
|
|
17
|
+
scopes?: string[];
|
|
18
|
+
authorizationUrl?: string;
|
|
19
|
+
userInfoUrl?: string;
|
|
20
|
+
refreshUrl?: string;
|
|
21
|
+
oauthProviderId?: string;
|
|
22
|
+
rawType?: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ProviderProfile {
|
|
25
|
+
providerKey: string;
|
|
26
|
+
providerType: string;
|
|
27
|
+
endpoint: string;
|
|
28
|
+
auth: ProviderAuthConfig;
|
|
29
|
+
outboundProfile: string;
|
|
30
|
+
compatibilityProfile?: string;
|
|
31
|
+
runtimeKey?: string;
|
|
32
|
+
modelId?: string;
|
|
33
|
+
processMode?: 'chat' | 'passthrough';
|
|
34
|
+
responsesConfig?: ResponsesProviderConfig;
|
|
35
|
+
}
|
|
36
|
+
export interface ProviderRuntimeProfile {
|
|
37
|
+
runtimeKey: string;
|
|
38
|
+
providerId: string;
|
|
39
|
+
keyAlias: string;
|
|
40
|
+
providerType: string;
|
|
41
|
+
endpoint: string;
|
|
42
|
+
headers?: Record<string, string>;
|
|
43
|
+
auth: ProviderAuthConfig;
|
|
44
|
+
outboundProfile: string;
|
|
45
|
+
compatibilityProfile?: string;
|
|
46
|
+
modelId?: string;
|
|
47
|
+
processMode?: 'chat' | 'passthrough';
|
|
48
|
+
responsesConfig?: ResponsesProviderConfig;
|
|
49
|
+
}
|
|
50
|
+
export interface VirtualRouterClassifierConfig {
|
|
51
|
+
longContextThresholdTokens?: number;
|
|
52
|
+
thinkingKeywords?: string[];
|
|
53
|
+
codingKeywords?: string[];
|
|
54
|
+
backgroundKeywords?: string[];
|
|
55
|
+
visionKeywords?: string[];
|
|
56
|
+
}
|
|
57
|
+
export interface LoadBalancingPolicy {
|
|
58
|
+
strategy: 'round-robin' | 'weighted' | 'sticky';
|
|
59
|
+
weights?: Record<string, number>;
|
|
60
|
+
}
|
|
61
|
+
export interface ProviderHealthConfig {
|
|
62
|
+
failureThreshold: number;
|
|
63
|
+
cooldownMs: number;
|
|
64
|
+
fatalCooldownMs?: number;
|
|
65
|
+
}
|
|
66
|
+
export interface VirtualRouterConfig {
|
|
67
|
+
routing: RoutingPools;
|
|
68
|
+
providers: Record<string, ProviderProfile>;
|
|
69
|
+
classifier: VirtualRouterClassifierConfig;
|
|
70
|
+
loadBalancing?: LoadBalancingPolicy;
|
|
71
|
+
health?: ProviderHealthConfig;
|
|
72
|
+
}
|
|
73
|
+
export type VirtualRouterProviderDefinition = Record<string, unknown>;
|
|
74
|
+
export interface VirtualRouterBootstrapInput extends Record<string, unknown> {
|
|
75
|
+
virtualrouter?: Record<string, unknown>;
|
|
76
|
+
providers?: Record<string, VirtualRouterProviderDefinition>;
|
|
77
|
+
routing?: Record<string, unknown>;
|
|
78
|
+
classifier?: VirtualRouterClassifierConfig;
|
|
79
|
+
loadBalancing?: LoadBalancingPolicy;
|
|
80
|
+
health?: ProviderHealthConfig;
|
|
81
|
+
}
|
|
82
|
+
export type ProviderRuntimeMap = Record<string, ProviderRuntimeProfile>;
|
|
83
|
+
export interface VirtualRouterBootstrapResult {
|
|
84
|
+
config: VirtualRouterConfig;
|
|
85
|
+
runtime: ProviderRuntimeMap;
|
|
86
|
+
targetRuntime: Record<string, ProviderRuntimeProfile>;
|
|
87
|
+
providers: Record<string, ProviderProfile>;
|
|
88
|
+
routing: RoutingPools;
|
|
89
|
+
}
|
|
90
|
+
export interface RouterMetadataInput {
|
|
91
|
+
requestId: string;
|
|
92
|
+
entryEndpoint: string;
|
|
93
|
+
processMode: 'chat' | 'passthrough';
|
|
94
|
+
stream: boolean;
|
|
95
|
+
direction: 'request' | 'response';
|
|
96
|
+
providerProtocol?: string;
|
|
97
|
+
stage?: 'inbound' | 'outbound' | 'response';
|
|
98
|
+
routeHint?: string;
|
|
99
|
+
}
|
|
100
|
+
export interface RoutingFeatures {
|
|
101
|
+
requestId: string;
|
|
102
|
+
model: string;
|
|
103
|
+
totalMessages: number;
|
|
104
|
+
userTextSample: string;
|
|
105
|
+
toolCount: number;
|
|
106
|
+
hasTools: boolean;
|
|
107
|
+
hasToolCallResponses: boolean;
|
|
108
|
+
hasVisionTool: boolean;
|
|
109
|
+
hasImageAttachment: boolean;
|
|
110
|
+
hasWebTool: boolean;
|
|
111
|
+
hasCodingTool: boolean;
|
|
112
|
+
hasThinkingKeyword: boolean;
|
|
113
|
+
estimatedTokens: number;
|
|
114
|
+
metadata: RouterMetadataInput;
|
|
115
|
+
}
|
|
116
|
+
export interface ClassificationResult {
|
|
117
|
+
routeName: string;
|
|
118
|
+
confidence: number;
|
|
119
|
+
reasoning: string;
|
|
120
|
+
fallback: boolean;
|
|
121
|
+
candidates?: string[];
|
|
122
|
+
}
|
|
123
|
+
export interface RoutingDecision {
|
|
124
|
+
routeName: string;
|
|
125
|
+
providerKey: string;
|
|
126
|
+
confidence: number;
|
|
127
|
+
reasoning: string;
|
|
128
|
+
fallback: boolean;
|
|
129
|
+
pool: string[];
|
|
130
|
+
}
|
|
131
|
+
export interface TargetMetadata {
|
|
132
|
+
providerKey: string;
|
|
133
|
+
providerType: string;
|
|
134
|
+
outboundProfile: string;
|
|
135
|
+
compatibilityProfile?: string;
|
|
136
|
+
runtimeKey?: string;
|
|
137
|
+
modelId: string;
|
|
138
|
+
processMode?: 'chat' | 'passthrough';
|
|
139
|
+
responsesConfig?: ResponsesProviderConfig;
|
|
140
|
+
}
|
|
141
|
+
export interface ResponsesProviderConfig {
|
|
142
|
+
toolCallIdStyle?: 'fc' | 'preserve';
|
|
143
|
+
}
|
|
144
|
+
export declare enum VirtualRouterErrorCode {
|
|
145
|
+
NO_STANDARDIZED_REQUEST = "NO_STANDARDIZED_REQUEST",
|
|
146
|
+
ROUTE_NOT_FOUND = "ROUTE_NOT_FOUND",
|
|
147
|
+
PROVIDER_NOT_AVAILABLE = "PROVIDER_NOT_AVAILABLE",
|
|
148
|
+
CONFIG_ERROR = "CONFIG_ERROR"
|
|
149
|
+
}
|
|
150
|
+
export declare class VirtualRouterError extends Error {
|
|
151
|
+
readonly code: VirtualRouterErrorCode;
|
|
152
|
+
readonly details?: Record<string, unknown>;
|
|
153
|
+
constructor(message: string, code: VirtualRouterErrorCode, details?: Record<string, unknown>);
|
|
154
|
+
}
|
|
155
|
+
export interface RoutingDiagnostics {
|
|
156
|
+
routeName: string;
|
|
157
|
+
providerKey: string;
|
|
158
|
+
reasoning: string;
|
|
159
|
+
fallback: boolean;
|
|
160
|
+
pool: string[];
|
|
161
|
+
confidence: number;
|
|
162
|
+
}
|
|
163
|
+
export interface RoutingStatusSnapshot {
|
|
164
|
+
routes: Record<string, {
|
|
165
|
+
providers: string[];
|
|
166
|
+
hits: number;
|
|
167
|
+
lastUsedProvider?: string;
|
|
168
|
+
}>;
|
|
169
|
+
health: ProviderHealthState[];
|
|
170
|
+
}
|
|
171
|
+
export interface ProviderHealthState {
|
|
172
|
+
providerKey: string;
|
|
173
|
+
state: 'healthy' | 'tripped';
|
|
174
|
+
failureCount: number;
|
|
175
|
+
cooldownExpiresAt?: number;
|
|
176
|
+
reason?: string;
|
|
177
|
+
}
|
|
178
|
+
export interface ProviderFailureEvent {
|
|
179
|
+
providerKey: string;
|
|
180
|
+
routeName?: string;
|
|
181
|
+
reason?: string;
|
|
182
|
+
fatal?: boolean;
|
|
183
|
+
statusCode?: number;
|
|
184
|
+
errorCode?: string;
|
|
185
|
+
retryable?: boolean;
|
|
186
|
+
affectsHealth?: boolean;
|
|
187
|
+
cooldownOverrideMs?: number;
|
|
188
|
+
metadata?: Record<string, unknown>;
|
|
189
|
+
}
|
|
190
|
+
export interface ProviderErrorRuntimeMetadata {
|
|
191
|
+
requestId: string;
|
|
192
|
+
routeName?: string;
|
|
193
|
+
providerKey?: string;
|
|
194
|
+
providerId?: string;
|
|
195
|
+
providerType?: string;
|
|
196
|
+
providerProtocol?: string;
|
|
197
|
+
pipelineId?: string;
|
|
198
|
+
target?: TargetMetadata | Record<string, unknown>;
|
|
199
|
+
}
|
|
200
|
+
export interface ProviderErrorEvent {
|
|
201
|
+
code: string;
|
|
202
|
+
message: string;
|
|
203
|
+
stage: string;
|
|
204
|
+
status?: number;
|
|
205
|
+
recoverable?: boolean;
|
|
206
|
+
runtime: ProviderErrorRuntimeMetadata;
|
|
207
|
+
timestamp: number;
|
|
208
|
+
details?: Record<string, unknown>;
|
|
209
|
+
}
|
|
210
|
+
export interface FeatureBuilder {
|
|
211
|
+
build(request: StandardizedRequest, metadata: RouterMetadataInput): RoutingFeatures;
|
|
212
|
+
}
|
package/dist/sse/index.d.ts
CHANGED
|
@@ -4,14 +4,19 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import type { ChatCompletionResponse, ChatJsonToSseOptions, ResponsesJsonToSseOptions, ResponsesResponse, SseToChatJsonOptions, SseToResponsesJsonOptions } from './types/index.js';
|
|
6
6
|
import type { AnthropicMessageResponse } from './types/anthropic-types.js';
|
|
7
|
+
import type { GeminiResponse, GeminiJsonToSseOptions, SseToGeminiJsonOptions } from './types/gemini-types.js';
|
|
7
8
|
import { ChatSseToJsonConverter as ChatSseToJsonConverterCtor } from './sse-to-json/index.js';
|
|
8
9
|
import { ResponsesSseToJsonConverter as ResponsesSseToJsonConverterCtor } from './sse-to-json/index.js';
|
|
9
10
|
import { AnthropicJsonToSseConverter as AnthropicJsonToSseConverterCtor } from './json-to-sse/anthropic-json-to-sse-converter.js';
|
|
10
11
|
import { AnthropicSseToJsonConverter as AnthropicSseToJsonConverterCtor } from './sse-to-json/anthropic-sse-to-json-converter.js';
|
|
12
|
+
import { GeminiJsonToSseConverter as GeminiJsonToSseConverterCtor } from './json-to-sse/gemini-json-to-sse-converter.js';
|
|
13
|
+
import { GeminiSseToJsonConverter as GeminiSseToJsonConverterCtor } from './sse-to-json/gemini-sse-to-json-converter.js';
|
|
11
14
|
export { ChatJsonToSseConverter } from './json-to-sse/index.js';
|
|
12
15
|
export { ChatSseToJsonConverter } from './sse-to-json/index.js';
|
|
13
16
|
export { ResponsesJsonToSseConverter } from './json-to-sse/index.js';
|
|
14
17
|
export { ResponsesSseToJsonConverter } from './sse-to-json/index.js';
|
|
18
|
+
export { GeminiJsonToSseConverter } from './json-to-sse/index.js';
|
|
19
|
+
export { GeminiSseToJsonConverter } from './sse-to-json/index.js';
|
|
15
20
|
export * from './shared/utils.js';
|
|
16
21
|
export * from './types/index.js';
|
|
17
22
|
/**
|
|
@@ -45,8 +50,18 @@ export declare function createAnthropicConverters(): {
|
|
|
45
50
|
roundTrip(input: AnthropicMessageResponse, options: {
|
|
46
51
|
requestId: string;
|
|
47
52
|
model: string;
|
|
53
|
+
reasoningMode?: import("./types/chat-types.js").ChatReasoningMode;
|
|
54
|
+
reasoningTextPrefix?: string;
|
|
48
55
|
}): Promise<AnthropicMessageResponse>;
|
|
49
56
|
};
|
|
57
|
+
/**
|
|
58
|
+
* 工厂函数:创建Gemini协议转换器
|
|
59
|
+
*/
|
|
60
|
+
export declare function createGeminiConverters(): {
|
|
61
|
+
jsonToSse: GeminiJsonToSseConverterCtor;
|
|
62
|
+
sseToJson: GeminiSseToJsonConverterCtor;
|
|
63
|
+
roundTrip(input: GeminiResponse, options: GeminiJsonToSseOptions & SseToGeminiJsonOptions): Promise<GeminiResponse>;
|
|
64
|
+
};
|
|
50
65
|
/**
|
|
51
66
|
* 工厂函数:创建完整的双向转换器(支持Chat和Responses协议)
|
|
52
67
|
*/
|
|
@@ -73,12 +88,19 @@ export declare function createBidirectionalConverters(): {
|
|
|
73
88
|
roundTrip(input: AnthropicMessageResponse, options: {
|
|
74
89
|
requestId: string;
|
|
75
90
|
model: string;
|
|
91
|
+
reasoningMode?: import("./types/chat-types.js").ChatReasoningMode;
|
|
92
|
+
reasoningTextPrefix?: string;
|
|
76
93
|
}): Promise<AnthropicMessageResponse>;
|
|
77
94
|
};
|
|
95
|
+
gemini: {
|
|
96
|
+
jsonToSse: GeminiJsonToSseConverterCtor;
|
|
97
|
+
sseToJson: GeminiSseToJsonConverterCtor;
|
|
98
|
+
roundTrip(input: GeminiResponse, options: GeminiJsonToSseOptions & SseToGeminiJsonOptions): Promise<GeminiResponse>;
|
|
99
|
+
};
|
|
78
100
|
/**
|
|
79
101
|
* 自动检测协议类型并执行转换
|
|
80
102
|
*/
|
|
81
|
-
autoConvert(input: any, options?: any): Promise<ChatCompletionResponse | ResponsesResponse | AnthropicMessageResponse>;
|
|
103
|
+
autoConvert(input: any, options?: any): Promise<ChatCompletionResponse | ResponsesResponse | AnthropicMessageResponse | GeminiResponse>;
|
|
82
104
|
};
|
|
83
105
|
/**
|
|
84
106
|
* 默认转换器实例
|
|
@@ -122,12 +144,19 @@ export declare const bidirectionalConverters: {
|
|
|
122
144
|
roundTrip(input: AnthropicMessageResponse, options: {
|
|
123
145
|
requestId: string;
|
|
124
146
|
model: string;
|
|
147
|
+
reasoningMode?: import("./types/chat-types.js").ChatReasoningMode;
|
|
148
|
+
reasoningTextPrefix?: string;
|
|
125
149
|
}): Promise<AnthropicMessageResponse>;
|
|
126
150
|
};
|
|
151
|
+
gemini: {
|
|
152
|
+
jsonToSse: GeminiJsonToSseConverterCtor;
|
|
153
|
+
sseToJson: GeminiSseToJsonConverterCtor;
|
|
154
|
+
roundTrip(input: GeminiResponse, options: GeminiJsonToSseOptions & SseToGeminiJsonOptions): Promise<GeminiResponse>;
|
|
155
|
+
};
|
|
127
156
|
/**
|
|
128
157
|
* 自动检测协议类型并执行转换
|
|
129
158
|
*/
|
|
130
|
-
autoConvert(input: any, options?: any): Promise<ChatCompletionResponse | ResponsesResponse | AnthropicMessageResponse>;
|
|
159
|
+
autoConvert(input: any, options?: any): Promise<ChatCompletionResponse | ResponsesResponse | AnthropicMessageResponse | GeminiResponse>;
|
|
131
160
|
};
|
|
132
161
|
export declare const anthropicConverters: {
|
|
133
162
|
jsonToSse: AnthropicJsonToSseConverterCtor;
|
|
@@ -135,6 +164,13 @@ export declare const anthropicConverters: {
|
|
|
135
164
|
roundTrip(input: AnthropicMessageResponse, options: {
|
|
136
165
|
requestId: string;
|
|
137
166
|
model: string;
|
|
167
|
+
reasoningMode?: import("./types/chat-types.js").ChatReasoningMode;
|
|
168
|
+
reasoningTextPrefix?: string;
|
|
138
169
|
}): Promise<AnthropicMessageResponse>;
|
|
139
170
|
};
|
|
171
|
+
export declare const geminiConverters: {
|
|
172
|
+
jsonToSse: GeminiJsonToSseConverterCtor;
|
|
173
|
+
sseToJson: GeminiSseToJsonConverterCtor;
|
|
174
|
+
roundTrip(input: GeminiResponse, options: GeminiJsonToSseOptions & SseToGeminiJsonOptions): Promise<GeminiResponse>;
|
|
175
|
+
};
|
|
140
176
|
export { defaultSseCodecRegistry, SseCodecRegistry, type SseCodec, type SseProtocol, type JsonToSseContext, type SseToJsonContext, type NormalizeSseContext } from './registry/sse-codec-registry.js';
|
package/dist/sse/index.js
CHANGED
|
@@ -8,12 +8,17 @@ import { ResponsesJsonToSseConverter as ResponsesJsonToSseConverterCtor } from '
|
|
|
8
8
|
import { ResponsesSseToJsonConverter as ResponsesSseToJsonConverterCtor } from './sse-to-json/index.js';
|
|
9
9
|
import { AnthropicJsonToSseConverter as AnthropicJsonToSseConverterCtor } from './json-to-sse/anthropic-json-to-sse-converter.js';
|
|
10
10
|
import { AnthropicSseToJsonConverter as AnthropicSseToJsonConverterCtor } from './sse-to-json/anthropic-sse-to-json-converter.js';
|
|
11
|
+
import { GeminiJsonToSseConverter as GeminiJsonToSseConverterCtor } from './json-to-sse/gemini-json-to-sse-converter.js';
|
|
12
|
+
import { GeminiSseToJsonConverter as GeminiSseToJsonConverterCtor } from './sse-to-json/gemini-sse-to-json-converter.js';
|
|
11
13
|
// Chat协议转换器
|
|
12
14
|
export { ChatJsonToSseConverter } from './json-to-sse/index.js';
|
|
13
15
|
export { ChatSseToJsonConverter } from './sse-to-json/index.js';
|
|
14
16
|
// Responses协议转换器
|
|
15
17
|
export { ResponsesJsonToSseConverter } from './json-to-sse/index.js';
|
|
16
18
|
export { ResponsesSseToJsonConverter } from './sse-to-json/index.js';
|
|
19
|
+
// Gemini协议转换器
|
|
20
|
+
export { GeminiJsonToSseConverter } from './json-to-sse/index.js';
|
|
21
|
+
export { GeminiSseToJsonConverter } from './sse-to-json/index.js';
|
|
17
22
|
// 共享工具导出
|
|
18
23
|
export * from './shared/utils.js';
|
|
19
24
|
// 序列化器暂时禁用以专注核心SSE转换功能
|
|
@@ -74,6 +79,22 @@ export function createAnthropicConverters() {
|
|
|
74
79
|
}
|
|
75
80
|
};
|
|
76
81
|
}
|
|
82
|
+
/**
|
|
83
|
+
* 工厂函数:创建Gemini协议转换器
|
|
84
|
+
*/
|
|
85
|
+
export function createGeminiConverters() {
|
|
86
|
+
const jsonToSse = new GeminiJsonToSseConverterCtor();
|
|
87
|
+
const sseToJson = new GeminiSseToJsonConverterCtor();
|
|
88
|
+
return {
|
|
89
|
+
jsonToSse,
|
|
90
|
+
sseToJson,
|
|
91
|
+
async roundTrip(input, options) {
|
|
92
|
+
const sseStream = await jsonToSse.convertResponseToJsonToSse(input, options);
|
|
93
|
+
const result = await sseToJson.convertSseToJson(sseStream, options);
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
}
|
|
77
98
|
/**
|
|
78
99
|
* 工厂函数:创建完整的双向转换器(支持Chat和Responses协议)
|
|
79
100
|
*/
|
|
@@ -81,10 +102,12 @@ export function createBidirectionalConverters() {
|
|
|
81
102
|
const chat = createChatConverters();
|
|
82
103
|
const responses = createResponsesConverters();
|
|
83
104
|
const anthropic = createAnthropicConverters();
|
|
105
|
+
const gemini = createGeminiConverters();
|
|
84
106
|
return {
|
|
85
107
|
chat,
|
|
86
108
|
responses,
|
|
87
109
|
anthropic,
|
|
110
|
+
gemini,
|
|
88
111
|
/**
|
|
89
112
|
* 自动检测协议类型并执行转换
|
|
90
113
|
*/
|
|
@@ -99,6 +122,9 @@ export function createBidirectionalConverters() {
|
|
|
99
122
|
else if (input.type === 'message') {
|
|
100
123
|
return await anthropic.roundTrip(input, options);
|
|
101
124
|
}
|
|
125
|
+
else if (Array.isArray(input?.candidates)) {
|
|
126
|
+
return await gemini.roundTrip(input, options);
|
|
127
|
+
}
|
|
102
128
|
else {
|
|
103
129
|
throw new Error(`无法识别的协议类型: ${input.object}`);
|
|
104
130
|
}
|
|
@@ -112,4 +138,5 @@ export const chatConverters = createChatConverters();
|
|
|
112
138
|
export const responsesConverters = createResponsesConverters();
|
|
113
139
|
export const bidirectionalConverters = createBidirectionalConverters();
|
|
114
140
|
export const anthropicConverters = createAnthropicConverters();
|
|
141
|
+
export const geminiConverters = createGeminiConverters();
|
|
115
142
|
export { defaultSseCodecRegistry, SseCodecRegistry } from './registry/sse-codec-registry.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PassThrough } from 'node:stream';
|
|
2
|
+
import { AnthropicMessageResponse, AnthropicJsonToSseOptions, DEFAULT_ANTHROPIC_CONVERSION_CONFIG } from '../types/index.js';
|
|
3
|
+
export declare class AnthropicJsonToSseConverter {
|
|
4
|
+
private config;
|
|
5
|
+
private contexts;
|
|
6
|
+
constructor(config?: Partial<typeof DEFAULT_ANTHROPIC_CONVERSION_CONFIG>);
|
|
7
|
+
convertResponseToJsonToSse(response: AnthropicMessageResponse, options: AnthropicJsonToSseOptions): Promise<PassThrough>;
|
|
8
|
+
private createContext;
|
|
9
|
+
private processResponse;
|
|
10
|
+
private updateStats;
|
|
11
|
+
private validateResponse;
|
|
12
|
+
private handleStreamError;
|
|
13
|
+
private wrapError;
|
|
14
|
+
}
|
|
@@ -1,79 +1,112 @@
|
|
|
1
1
|
import { PassThrough } from 'node:stream';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
* NOTE: This converter purposely avoids any tool governance. It only maps shapes/fields.
|
|
8
|
-
*/
|
|
2
|
+
import { DEFAULT_ANTHROPIC_CONVERSION_CONFIG } from '../types/index.js';
|
|
3
|
+
import { ErrorUtils } from '../shared/utils.js';
|
|
4
|
+
import { createAnthropicSequencer } from './sequencers/anthropic-sequencer.js';
|
|
5
|
+
import { createAnthropicStreamWriter } from '../shared/writer.js';
|
|
9
6
|
export class AnthropicJsonToSseConverter {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
config = DEFAULT_ANTHROPIC_CONVERSION_CONFIG;
|
|
8
|
+
contexts = new Map();
|
|
9
|
+
constructor(config) {
|
|
10
|
+
if (config) {
|
|
11
|
+
this.config = { ...this.config, ...config };
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
async convertResponseToJsonToSse(response, options) {
|
|
15
|
+
const context = this.createContext(response, options);
|
|
16
|
+
this.contexts.set(options.requestId, context);
|
|
17
|
+
const stream = new PassThrough({ objectMode: true });
|
|
18
|
+
const writer = createAnthropicStreamWriter(stream, {
|
|
19
|
+
onEvent: (event) => this.updateStats(context, event),
|
|
20
|
+
onError: (error) => this.handleStreamError(context, error, stream)
|
|
21
|
+
});
|
|
22
|
+
this.processResponse(response, context, writer, stream).catch((error) => {
|
|
23
|
+
this.handleStreamError(context, error, stream);
|
|
24
|
+
});
|
|
25
|
+
return Object.assign(stream, {
|
|
26
|
+
protocol: 'anthropic-messages',
|
|
27
|
+
direction: 'json_to_sse',
|
|
28
|
+
requestId: options.requestId,
|
|
29
|
+
getStats: () => context.eventStats,
|
|
30
|
+
complete: () => writer.complete(),
|
|
31
|
+
abort: (error) => writer.abort(error)
|
|
22
32
|
});
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
delta: { type: 'input_json_delta', partial_json }
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
// best-effort: skip delta on stringify error
|
|
65
|
-
}
|
|
66
|
-
write('content_block_stop', { type: 'content_block_stop', index });
|
|
67
|
-
index += 1;
|
|
68
|
-
}
|
|
33
|
+
}
|
|
34
|
+
createContext(response, options) {
|
|
35
|
+
const stats = {
|
|
36
|
+
totalEvents: 0,
|
|
37
|
+
contentBlocks: 0,
|
|
38
|
+
toolUseBlocks: 0,
|
|
39
|
+
thinkingBlocks: 0,
|
|
40
|
+
textBlocks: 0,
|
|
41
|
+
errors: 0,
|
|
42
|
+
startTime: Date.now()
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
requestId: options.requestId,
|
|
46
|
+
model: options.model,
|
|
47
|
+
response,
|
|
48
|
+
options,
|
|
49
|
+
startTime: Date.now(),
|
|
50
|
+
eventStats: stats
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
async processResponse(response, context, writer, stream) {
|
|
54
|
+
try {
|
|
55
|
+
this.validateResponse(response);
|
|
56
|
+
const sequencer = createAnthropicSequencer({
|
|
57
|
+
chunkSize: context.options.chunkSize ?? this.config.defaultChunkSize,
|
|
58
|
+
chunkDelayMs: context.options.chunkDelayMs ?? this.config.defaultDelayMs,
|
|
59
|
+
enableDelay: Boolean(context.options.chunkDelayMs),
|
|
60
|
+
reasoningMode: context.options.reasoningMode ?? this.config.reasoningMode,
|
|
61
|
+
reasoningTextPrefix: context.options.reasoningTextPrefix ?? this.config.reasoningTextPrefix
|
|
62
|
+
});
|
|
63
|
+
const events = sequencer.sequenceResponse(response, context.requestId);
|
|
64
|
+
await writer.writeAnthropicEvents(events);
|
|
65
|
+
writer.complete();
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
writer.abort(error);
|
|
69
|
+
throw this.wrapError('ANTHROPIC_JSON_TO_SSE_FAILED', error, context.requestId);
|
|
69
70
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
71
|
+
finally {
|
|
72
|
+
this.contexts.delete(context.requestId);
|
|
73
|
+
stream.end();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
updateStats(context, event) {
|
|
77
|
+
context.eventStats.totalEvents += 1;
|
|
78
|
+
if (!event || typeof event !== 'object')
|
|
79
|
+
return;
|
|
80
|
+
const type = event.type;
|
|
81
|
+
if (type === 'content_block_start') {
|
|
82
|
+
context.eventStats.contentBlocks += 1;
|
|
83
|
+
const blockType = event.data?.content_block?.type;
|
|
84
|
+
if (blockType === 'tool_use')
|
|
85
|
+
context.eventStats.toolUseBlocks += 1;
|
|
86
|
+
if (blockType === 'thinking')
|
|
87
|
+
context.eventStats.thinkingBlocks += 1;
|
|
88
|
+
if (blockType === 'text')
|
|
89
|
+
context.eventStats.textBlocks += 1;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
validateResponse(response) {
|
|
93
|
+
if (!response || typeof response !== 'object') {
|
|
94
|
+
throw new Error('Invalid Anthropic response payload');
|
|
95
|
+
}
|
|
96
|
+
if (!Array.isArray(response.content)) {
|
|
97
|
+
throw new Error('Anthropic response content must be an array');
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
handleStreamError(context, error, stream) {
|
|
101
|
+
context.eventStats.errors += 1;
|
|
102
|
+
try {
|
|
103
|
+
stream.destroy(error);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
/* noop */
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
wrapError(code, error, requestId) {
|
|
110
|
+
return ErrorUtils.createError(error.message, code, { requestId });
|
|
78
111
|
}
|
|
79
112
|
}
|
|
@@ -85,7 +85,9 @@ export class ChatJsonToSseConverterRefactored {
|
|
|
85
85
|
const sequencer = createChatSequencer({
|
|
86
86
|
chunkSize: context.options.maxTokensPerChunk || this.config.maxTokensPerChunk,
|
|
87
87
|
chunkDelayMs: context.options.chunkDelayMs || this.config.defaultChunkDelayMs,
|
|
88
|
-
enableDelay: !!context.options.chunkDelayMs
|
|
88
|
+
enableDelay: !!context.options.chunkDelayMs,
|
|
89
|
+
reasoningMode: context.options.reasoningMode || this.config.reasoningMode,
|
|
90
|
+
reasoningTextPrefix: context.options.reasoningTextPrefix ?? this.config.reasoningTextPrefix
|
|
89
91
|
});
|
|
90
92
|
// 4. 生成事件序列并写入流
|
|
91
93
|
const eventStream = sequencer.sequenceRequest(request, context.model, context.requestId);
|
|
@@ -113,7 +115,9 @@ export class ChatJsonToSseConverterRefactored {
|
|
|
113
115
|
const sequencer = createChatSequencer({
|
|
114
116
|
chunkSize: context.options.maxTokensPerChunk || this.config.maxTokensPerChunk,
|
|
115
117
|
chunkDelayMs: context.options.chunkDelayMs || this.config.defaultChunkDelayMs,
|
|
116
|
-
enableDelay: !!context.options.chunkDelayMs
|
|
118
|
+
enableDelay: !!context.options.chunkDelayMs,
|
|
119
|
+
reasoningMode: context.options.reasoningMode || this.config.reasoningMode,
|
|
120
|
+
reasoningTextPrefix: context.options.reasoningTextPrefix ?? this.config.reasoningTextPrefix
|
|
117
121
|
});
|
|
118
122
|
// 4. 生成事件序列并写入流
|
|
119
123
|
const eventStream = sequencer.sequenceResponse(response, context.model, context.requestId);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PassThrough } from 'node:stream';
|
|
2
|
+
import { GeminiResponse, GeminiJsonToSseOptions, DEFAULT_GEMINI_CONVERSION_CONFIG } from '../types/index.js';
|
|
3
|
+
export declare class GeminiJsonToSseConverter {
|
|
4
|
+
private config;
|
|
5
|
+
private contexts;
|
|
6
|
+
constructor(config?: Partial<typeof DEFAULT_GEMINI_CONVERSION_CONFIG>);
|
|
7
|
+
convertResponseToJsonToSse(response: GeminiResponse, options: GeminiJsonToSseOptions): Promise<PassThrough>;
|
|
8
|
+
private createContext;
|
|
9
|
+
private processResponse;
|
|
10
|
+
private validateResponse;
|
|
11
|
+
private updateStats;
|
|
12
|
+
private handleStreamError;
|
|
13
|
+
private wrapError;
|
|
14
|
+
}
|