@jsonstudio/llms 0.4.4 → 0.4.5

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 (159) hide show
  1. package/dist/conversion/codec-registry.js +11 -1
  2. package/dist/conversion/codecs/anthropic-openai-codec.d.ts +13 -0
  3. package/dist/conversion/codecs/anthropic-openai-codec.js +18 -473
  4. package/dist/conversion/codecs/gemini-openai-codec.js +91 -48
  5. package/dist/conversion/codecs/responses-openai-codec.js +9 -2
  6. package/dist/conversion/hub/format-adapters/anthropic-format-adapter.js +3 -0
  7. package/dist/conversion/hub/format-adapters/chat-format-adapter.js +3 -0
  8. package/dist/conversion/hub/format-adapters/gemini-format-adapter.js +3 -0
  9. package/dist/conversion/hub/format-adapters/responses-format-adapter.d.ts +19 -0
  10. package/dist/conversion/hub/format-adapters/responses-format-adapter.js +9 -0
  11. package/dist/conversion/hub/node-support.js +3 -1
  12. package/dist/conversion/hub/pipeline/hub-pipeline.js +37 -32
  13. package/dist/conversion/hub/response/provider-response.js +1 -1
  14. package/dist/conversion/hub/response/response-mappers.js +1 -1
  15. package/dist/conversion/hub/response/response-runtime.js +109 -10
  16. package/dist/conversion/hub/semantic-mappers/anthropic-mapper.js +70 -156
  17. package/dist/conversion/hub/semantic-mappers/chat-mapper.js +63 -52
  18. package/dist/conversion/hub/semantic-mappers/gemini-mapper.js +76 -143
  19. package/dist/conversion/hub/semantic-mappers/responses-mapper.js +40 -160
  20. package/dist/conversion/hub/standardized-bridge.js +3 -0
  21. package/dist/conversion/hub/tool-governance/rules.js +2 -2
  22. package/dist/conversion/index.d.ts +5 -0
  23. package/dist/conversion/index.js +5 -0
  24. package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.d.ts +12 -0
  25. package/dist/conversion/pipeline/codecs/v2/anthropic-openai-pipeline.js +100 -0
  26. package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.d.ts +15 -0
  27. package/dist/conversion/pipeline/codecs/v2/openai-openai-pipeline.js +174 -0
  28. package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.d.ts +14 -0
  29. package/dist/conversion/pipeline/codecs/v2/responses-openai-pipeline.js +166 -0
  30. package/dist/conversion/pipeline/codecs/v2/shared/openai-chat-helpers.d.ts +13 -0
  31. package/dist/conversion/pipeline/codecs/v2/shared/openai-chat-helpers.js +66 -0
  32. package/dist/conversion/pipeline/hooks/adapter-context.d.ts +7 -0
  33. package/dist/conversion/pipeline/hooks/adapter-context.js +18 -0
  34. package/dist/conversion/pipeline/hooks/protocol-hooks.d.ts +67 -0
  35. package/dist/conversion/pipeline/hooks/protocol-hooks.js +1 -0
  36. package/dist/conversion/pipeline/index.d.ts +35 -0
  37. package/dist/conversion/pipeline/index.js +103 -0
  38. package/dist/conversion/pipeline/meta/meta-bag.d.ts +20 -0
  39. package/dist/conversion/pipeline/meta/meta-bag.js +81 -0
  40. package/dist/conversion/pipeline/schema/canonical-chat.d.ts +18 -0
  41. package/dist/conversion/pipeline/schema/canonical-chat.js +1 -0
  42. package/dist/conversion/pipeline/schema/index.d.ts +1 -0
  43. package/dist/conversion/pipeline/schema/index.js +1 -0
  44. package/dist/conversion/responses/responses-openai-bridge.d.ts +48 -0
  45. package/dist/conversion/responses/responses-openai-bridge.js +157 -1146
  46. package/dist/conversion/shared/anthropic-message-utils.d.ts +12 -0
  47. package/dist/conversion/shared/anthropic-message-utils.js +587 -0
  48. package/dist/conversion/shared/bridge-actions.d.ts +39 -0
  49. package/dist/conversion/shared/bridge-actions.js +709 -0
  50. package/dist/conversion/shared/bridge-conversation-store.d.ts +41 -0
  51. package/dist/conversion/shared/bridge-conversation-store.js +279 -0
  52. package/dist/conversion/shared/bridge-id-utils.d.ts +7 -0
  53. package/dist/conversion/shared/bridge-id-utils.js +42 -0
  54. package/dist/conversion/shared/bridge-instructions.d.ts +1 -0
  55. package/dist/conversion/shared/bridge-instructions.js +113 -0
  56. package/dist/conversion/shared/bridge-message-types.d.ts +39 -0
  57. package/dist/conversion/shared/bridge-message-types.js +1 -0
  58. package/dist/conversion/shared/bridge-message-utils.d.ts +22 -0
  59. package/dist/conversion/shared/bridge-message-utils.js +473 -0
  60. package/dist/conversion/shared/bridge-metadata.d.ts +1 -0
  61. package/dist/conversion/shared/bridge-metadata.js +1 -0
  62. package/dist/conversion/shared/bridge-policies.d.ts +18 -0
  63. package/dist/conversion/shared/bridge-policies.js +276 -0
  64. package/dist/conversion/shared/bridge-request-adapter.d.ts +28 -0
  65. package/dist/conversion/shared/bridge-request-adapter.js +430 -0
  66. package/dist/conversion/shared/chat-output-normalizer.d.ts +4 -0
  67. package/dist/conversion/shared/chat-output-normalizer.js +56 -0
  68. package/dist/conversion/shared/chat-request-filters.js +24 -1
  69. package/dist/conversion/shared/gemini-tool-utils.d.ts +5 -0
  70. package/dist/conversion/shared/gemini-tool-utils.js +130 -0
  71. package/dist/conversion/shared/metadata-passthrough.d.ts +11 -0
  72. package/dist/conversion/shared/metadata-passthrough.js +57 -0
  73. package/dist/conversion/shared/output-content-normalizer.d.ts +12 -0
  74. package/dist/conversion/shared/output-content-normalizer.js +119 -0
  75. package/dist/conversion/shared/reasoning-normalizer.d.ts +21 -0
  76. package/dist/conversion/shared/reasoning-normalizer.js +368 -0
  77. package/dist/conversion/shared/reasoning-tool-normalizer.d.ts +12 -0
  78. package/dist/conversion/shared/reasoning-tool-normalizer.js +132 -0
  79. package/dist/conversion/shared/reasoning-tool-parser.d.ts +10 -0
  80. package/dist/conversion/shared/reasoning-tool-parser.js +95 -0
  81. package/dist/conversion/shared/reasoning-utils.d.ts +2 -0
  82. package/dist/conversion/shared/reasoning-utils.js +42 -0
  83. package/dist/conversion/shared/responses-conversation-store.js +5 -11
  84. package/dist/conversion/shared/responses-message-utils.d.ts +15 -0
  85. package/dist/conversion/shared/responses-message-utils.js +206 -0
  86. package/dist/conversion/shared/responses-output-builder.d.ts +15 -0
  87. package/dist/conversion/shared/responses-output-builder.js +179 -0
  88. package/dist/conversion/shared/responses-output-utils.d.ts +7 -0
  89. package/dist/conversion/shared/responses-output-utils.js +108 -0
  90. package/dist/conversion/shared/responses-request-adapter.d.ts +28 -0
  91. package/dist/conversion/shared/responses-request-adapter.js +9 -40
  92. package/dist/conversion/shared/responses-response-utils.d.ts +3 -0
  93. package/dist/conversion/shared/responses-response-utils.js +209 -0
  94. package/dist/conversion/shared/responses-tool-utils.d.ts +12 -0
  95. package/dist/conversion/shared/responses-tool-utils.js +90 -0
  96. package/dist/conversion/shared/responses-types.d.ts +33 -0
  97. package/dist/conversion/shared/responses-types.js +1 -0
  98. package/dist/conversion/shared/tool-call-utils.d.ts +11 -0
  99. package/dist/conversion/shared/tool-call-utils.js +56 -0
  100. package/dist/conversion/shared/tool-mapping.d.ts +19 -0
  101. package/dist/conversion/shared/tool-mapping.js +124 -0
  102. package/dist/conversion/shared/tool-normalizers.d.ts +4 -0
  103. package/dist/conversion/shared/tool-normalizers.js +84 -0
  104. package/dist/router/virtual-router/bootstrap.js +18 -3
  105. package/dist/router/virtual-router/provider-registry.js +4 -2
  106. package/dist/router/virtual-router/types.d.ts +212 -0
  107. package/dist/sse/index.d.ts +38 -2
  108. package/dist/sse/index.js +27 -0
  109. package/dist/sse/json-to-sse/anthropic-json-to-sse-converter.d.ts +14 -0
  110. package/dist/sse/json-to-sse/anthropic-json-to-sse-converter.js +106 -73
  111. package/dist/sse/json-to-sse/chat-json-to-sse-converter.js +6 -2
  112. package/dist/sse/json-to-sse/gemini-json-to-sse-converter.d.ts +14 -0
  113. package/dist/sse/json-to-sse/gemini-json-to-sse-converter.js +99 -0
  114. package/dist/sse/json-to-sse/index.d.ts +7 -0
  115. package/dist/sse/json-to-sse/index.js +2 -0
  116. package/dist/sse/json-to-sse/sequencers/anthropic-sequencer.d.ts +13 -0
  117. package/dist/sse/json-to-sse/sequencers/anthropic-sequencer.js +150 -0
  118. package/dist/sse/json-to-sse/sequencers/chat-sequencer.d.ts +39 -0
  119. package/dist/sse/json-to-sse/sequencers/chat-sequencer.js +49 -3
  120. package/dist/sse/json-to-sse/sequencers/gemini-sequencer.d.ts +10 -0
  121. package/dist/sse/json-to-sse/sequencers/gemini-sequencer.js +95 -0
  122. package/dist/sse/json-to-sse/sequencers/responses-sequencer.js +31 -5
  123. package/dist/sse/registry/sse-codec-registry.d.ts +32 -0
  124. package/dist/sse/registry/sse-codec-registry.js +30 -1
  125. package/dist/sse/shared/reasoning-dispatcher.d.ts +10 -0
  126. package/dist/sse/shared/reasoning-dispatcher.js +25 -0
  127. package/dist/sse/shared/responses-output-normalizer.d.ts +12 -0
  128. package/dist/sse/shared/responses-output-normalizer.js +45 -0
  129. package/dist/sse/shared/serializers/anthropic-event-serializer.d.ts +2 -0
  130. package/dist/sse/shared/serializers/anthropic-event-serializer.js +9 -0
  131. package/dist/sse/shared/serializers/gemini-event-serializer.d.ts +2 -0
  132. package/dist/sse/shared/serializers/gemini-event-serializer.js +5 -0
  133. package/dist/sse/shared/serializers/index.d.ts +41 -0
  134. package/dist/sse/shared/serializers/index.js +2 -0
  135. package/dist/sse/shared/writer.d.ts +127 -0
  136. package/dist/sse/shared/writer.js +37 -1
  137. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.d.ts +11 -0
  138. package/dist/sse/sse-to-json/anthropic-sse-to-json-converter.js +92 -127
  139. package/dist/sse/sse-to-json/builders/anthropic-response-builder.d.ts +16 -0
  140. package/dist/sse/sse-to-json/builders/anthropic-response-builder.js +151 -0
  141. package/dist/sse/sse-to-json/builders/response-builder.d.ts +165 -0
  142. package/dist/sse/sse-to-json/builders/response-builder.js +27 -6
  143. package/dist/sse/sse-to-json/chat-sse-to-json-converter.d.ts +114 -0
  144. package/dist/sse/sse-to-json/chat-sse-to-json-converter.js +79 -3
  145. package/dist/sse/sse-to-json/gemini-sse-to-json-converter.d.ts +13 -0
  146. package/dist/sse/sse-to-json/gemini-sse-to-json-converter.js +160 -0
  147. package/dist/sse/sse-to-json/index.d.ts +7 -0
  148. package/dist/sse/sse-to-json/index.js +2 -0
  149. package/dist/sse/sse-to-json/parsers/sse-parser.js +53 -1
  150. package/dist/sse/types/anthropic-types.d.ts +170 -0
  151. package/dist/sse/types/anthropic-types.js +8 -5
  152. package/dist/sse/types/chat-types.d.ts +10 -0
  153. package/dist/sse/types/chat-types.js +2 -1
  154. package/dist/sse/types/core-interfaces.d.ts +1 -1
  155. package/dist/sse/types/gemini-types.d.ts +116 -0
  156. package/dist/sse/types/gemini-types.js +5 -0
  157. package/dist/sse/types/index.d.ts +5 -2
  158. package/dist/sse/types/index.js +2 -0
  159. package/package.json +1 -1
@@ -0,0 +1,160 @@
1
+ import { DEFAULT_GEMINI_CONVERSION_CONFIG } from '../types/index.js';
2
+ import { ErrorUtils } from '../shared/utils.js';
3
+ import { dispatchReasoning } from '../shared/reasoning-dispatcher.js';
4
+ import { createSseParser } from './parsers/sse-parser.js';
5
+ export class GeminiSseToJsonConverter {
6
+ config = DEFAULT_GEMINI_CONVERSION_CONFIG;
7
+ contexts = new Map();
8
+ constructor(config) {
9
+ if (config) {
10
+ this.config = { ...this.config, ...config };
11
+ }
12
+ }
13
+ async convertSseToJson(sseStream, options) {
14
+ const context = this.createContext(options);
15
+ this.contexts.set(options.requestId, context);
16
+ const parser = createSseParser({
17
+ enableStrictValidation: true,
18
+ enableEventRecovery: true,
19
+ allowedEventTypes: new Set([
20
+ 'gemini.data',
21
+ 'gemini.done'
22
+ ])
23
+ });
24
+ const accumulator = new Map();
25
+ let donePayload = null;
26
+ try {
27
+ for await (const result of parser.parseStreamAsync(this.normalizeStream(sseStream))) {
28
+ if (!result.success || !result.event) {
29
+ if (result.error) {
30
+ throw new Error(result.error);
31
+ }
32
+ continue;
33
+ }
34
+ const event = result.event;
35
+ if (event.protocol !== 'gemini-chat')
36
+ continue;
37
+ if (event.type === 'gemini.data') {
38
+ this.processChunkEvent(event, accumulator, context);
39
+ context.eventStats.chunkEvents += 1;
40
+ }
41
+ else if (event.type === 'gemini.done') {
42
+ donePayload = event.data;
43
+ context.eventStats.doneEvents += 1;
44
+ }
45
+ context.eventStats.totalEvents += 1;
46
+ }
47
+ if (!donePayload) {
48
+ throw new Error('Gemini SSE stream missing done event');
49
+ }
50
+ const response = this.buildResponse(accumulator, donePayload);
51
+ context.isCompleted = true;
52
+ context.eventStats.endTime = Date.now();
53
+ return response;
54
+ }
55
+ catch (error) {
56
+ context.eventStats.errors += 1;
57
+ throw this.wrapError('GEMINI_SSE_TO_JSON_FAILED', error, options.requestId);
58
+ }
59
+ finally {
60
+ this.contexts.delete(options.requestId);
61
+ }
62
+ }
63
+ processChunkEvent(event, accumulator, context) {
64
+ const payload = event.data;
65
+ const candidateIndex = typeof payload?.candidateIndex === 'number' ? payload.candidateIndex : 0;
66
+ const part = payload?.part;
67
+ if (!part)
68
+ return;
69
+ const role = typeof payload?.role === 'string' ? payload.role : 'model';
70
+ if (!accumulator.has(candidateIndex)) {
71
+ accumulator.set(candidateIndex, { role, parts: [] });
72
+ }
73
+ const normalizedParts = this.normalizeReasoningPart(part, context);
74
+ for (const normalizedPart of normalizedParts) {
75
+ accumulator.get(candidateIndex).parts.push(normalizedPart);
76
+ }
77
+ }
78
+ buildResponse(accumulator, donePayload) {
79
+ const candidates = [];
80
+ const candidateMeta = {};
81
+ if (Array.isArray(donePayload?.candidates)) {
82
+ for (const entry of donePayload.candidates) {
83
+ if (!entry || typeof entry.index !== 'number')
84
+ continue;
85
+ candidateMeta[entry.index] = {
86
+ finishReason: entry.finishReason,
87
+ safetyRatings: entry.safetyRatings
88
+ };
89
+ }
90
+ }
91
+ const indices = Array.from(accumulator.keys()).sort((a, b) => a - b);
92
+ for (const index of indices) {
93
+ const acc = accumulator.get(index);
94
+ if (!acc)
95
+ continue;
96
+ candidates.push({
97
+ content: {
98
+ role: acc.role,
99
+ parts: acc.parts
100
+ },
101
+ finishReason: candidateMeta[index]?.finishReason,
102
+ safetyRatings: candidateMeta[index]?.safetyRatings
103
+ });
104
+ }
105
+ return {
106
+ candidates,
107
+ promptFeedback: donePayload?.promptFeedback,
108
+ usageMetadata: donePayload?.usageMetadata,
109
+ modelVersion: donePayload?.modelVersion
110
+ };
111
+ }
112
+ async *normalizeStream(stream) {
113
+ for await (const chunk of stream) {
114
+ yield typeof chunk === 'string' ? chunk : chunk.toString();
115
+ }
116
+ }
117
+ createContext(options) {
118
+ return {
119
+ requestId: options.requestId,
120
+ model: options.model,
121
+ options: {
122
+ reasoningMode: options.reasoningMode ?? this.config.reasoningMode,
123
+ reasoningTextPrefix: options.reasoningTextPrefix ?? this.config.reasoningTextPrefix
124
+ },
125
+ startTime: Date.now(),
126
+ eventStats: {
127
+ totalEvents: 0,
128
+ chunkEvents: 0,
129
+ doneEvents: 0,
130
+ errors: 0,
131
+ startTime: Date.now()
132
+ },
133
+ isCompleted: false
134
+ };
135
+ }
136
+ wrapError(code, error, requestId) {
137
+ return ErrorUtils.createError(error.message, code, { requestId });
138
+ }
139
+ normalizeReasoningPart(part, context) {
140
+ if (!part || typeof part !== 'object') {
141
+ return [part];
142
+ }
143
+ const reasoning = typeof part.reasoning === 'string' ? part.reasoning : undefined;
144
+ if (!reasoning) {
145
+ return [part];
146
+ }
147
+ const decision = dispatchReasoning(reasoning, {
148
+ mode: context.options.reasoningMode ?? this.config.reasoningMode,
149
+ prefix: context.options.reasoningTextPrefix ?? this.config.reasoningTextPrefix
150
+ });
151
+ const normalized = [];
152
+ if (decision.appendToContent) {
153
+ normalized.push({ text: decision.appendToContent });
154
+ }
155
+ if (decision.channel) {
156
+ normalized.push({ reasoning: decision.channel });
157
+ }
158
+ return normalized;
159
+ }
160
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * SSE→JSON转换模块导出
3
+ */
4
+ export { ChatSseToJsonConverter, defaultChatSseToJsonConverter } from './chat-sse-to-json-converter.js';
5
+ export { ResponsesSseToJsonConverterRefactored as ResponsesSseToJsonConverter } from './responses-sse-to-json-converter.js';
6
+ export { GeminiSseToJsonConverter } from './gemini-sse-to-json-converter.js';
7
+ export type { SseToChatJsonOptions, SseToChatJsonContext, ChatEventStats, SseToResponsesJsonOptions, SseToResponsesJsonContext, ResponsesEventStats, SseToGeminiJsonOptions, SseToGeminiJsonContext, GeminiEventStats } from '../types/index.js';
@@ -5,3 +5,5 @@
5
5
  export { ChatSseToJsonConverter, defaultChatSseToJsonConverter } from './chat-sse-to-json-converter.js';
6
6
  // Responses协议转换器(重构版本)
7
7
  export { ResponsesSseToJsonConverterRefactored as ResponsesSseToJsonConverter } from './responses-sse-to-json-converter.js';
8
+ // Gemini协议转换器
9
+ export { GeminiSseToJsonConverter } from './gemini-sse-to-json-converter.js';
@@ -50,7 +50,17 @@ export const DEFAULT_SSE_PARSER_CONFIG = {
50
50
  'reasoning.start',
51
51
  'reasoning.delta',
52
52
  'reasoning.done',
53
- 'required_action'
53
+ 'required_action',
54
+ // Anthropic event types
55
+ 'message_start',
56
+ 'content_block_start',
57
+ 'content_block_delta',
58
+ 'content_block_stop',
59
+ 'message_delta',
60
+ 'message_stop',
61
+ // Gemini event types
62
+ 'gemini.data',
63
+ 'gemini.done'
54
64
  ])
55
65
  };
56
66
  /**
@@ -195,15 +205,51 @@ function createResponsesEvent(baseEvent) {
195
205
  direction: 'sse_to_json'
196
206
  };
197
207
  }
208
+ function createAnthropicEvent(baseEvent) {
209
+ return {
210
+ type: baseEvent.type,
211
+ timestamp: baseEvent.timestamp,
212
+ data: baseEvent.data,
213
+ sequenceNumber: baseEvent.sequenceNumber,
214
+ protocol: 'anthropic-messages',
215
+ direction: 'sse_to_json'
216
+ };
217
+ }
218
+ function createGeminiEvent(baseEvent) {
219
+ return {
220
+ type: baseEvent.type,
221
+ event: baseEvent.type,
222
+ timestamp: baseEvent.timestamp,
223
+ data: baseEvent.data,
224
+ sequenceNumber: baseEvent.sequenceNumber,
225
+ protocol: 'gemini-chat',
226
+ direction: 'sse_to_json'
227
+ };
228
+ }
198
229
  /**
199
230
  * 检测事件协议类型
200
231
  */
201
232
  function detectEventType(eventType) {
202
233
  // Chat协议事件类型
203
234
  const chatEventTypes = new Set(['chunk', 'done', 'error', 'heartbeat']);
235
+ const anthropicEventTypes = new Set([
236
+ 'message_start',
237
+ 'content_block_start',
238
+ 'content_block_delta',
239
+ 'content_block_stop',
240
+ 'message_delta',
241
+ 'message_stop'
242
+ ]);
243
+ const geminiEventTypes = new Set(['gemini.data', 'gemini.done']);
204
244
  if (chatEventTypes.has(eventType)) {
205
245
  return 'chat';
206
246
  }
247
+ if (anthropicEventTypes.has(eventType)) {
248
+ return 'anthropic';
249
+ }
250
+ if (geminiEventTypes.has(eventType)) {
251
+ return 'gemini';
252
+ }
207
253
  // Responses协议事件类型(以点分隔或特定关键词)
208
254
  if (eventType.includes('.') ||
209
255
  eventType.startsWith('response') ||
@@ -250,6 +296,12 @@ export function parseSseEvent(sseText, config = DEFAULT_SSE_PARSER_CONFIG) {
250
296
  if (protocol === 'chat') {
251
297
  result.event = createChatEvent(baseEvent);
252
298
  }
299
+ else if (protocol === 'anthropic') {
300
+ result.event = createAnthropicEvent(baseEvent);
301
+ }
302
+ else if (protocol === 'gemini') {
303
+ result.event = createGeminiEvent(baseEvent);
304
+ }
253
305
  else {
254
306
  result.event = createResponsesEvent(baseEvent);
255
307
  }
@@ -0,0 +1,170 @@
1
+ import type { BaseSseEvent, StreamDirection } from './core-interfaces.js';
2
+ import type { ChatReasoningMode } from './chat-types.js';
3
+ /**
4
+ * Anthropic JSON/SSE 类型定义与转换上下文
5
+ */
6
+ export interface AnthropicContentTextBlock {
7
+ type: 'text';
8
+ text: string;
9
+ }
10
+ export interface AnthropicContentThinkingBlock {
11
+ type: 'thinking';
12
+ text: string;
13
+ }
14
+ export interface AnthropicContentToolUseBlock {
15
+ type: 'tool_use';
16
+ id: string;
17
+ name: string;
18
+ input: Record<string, unknown>;
19
+ }
20
+ export interface AnthropicContentToolResultBlock {
21
+ type: 'tool_result';
22
+ tool_use_id: string;
23
+ content: unknown;
24
+ is_error?: boolean;
25
+ }
26
+ export type AnthropicContentBlock = AnthropicContentTextBlock | AnthropicContentThinkingBlock | AnthropicContentToolUseBlock | AnthropicContentToolResultBlock;
27
+ export interface AnthropicMessageResponse {
28
+ id: string;
29
+ type: 'message';
30
+ role: 'assistant' | 'user';
31
+ model: string;
32
+ content: AnthropicContentBlock[];
33
+ usage?: {
34
+ input_tokens?: number;
35
+ output_tokens?: number;
36
+ };
37
+ stop_reason?: 'end_turn' | 'max_tokens' | 'stop_sequence' | 'tool_use';
38
+ }
39
+ export interface AnthropicEventStats {
40
+ totalEvents: number;
41
+ contentBlocks: number;
42
+ toolUseBlocks: number;
43
+ thinkingBlocks: number;
44
+ textBlocks: number;
45
+ errors: number;
46
+ startTime: number;
47
+ endTime?: number;
48
+ }
49
+ export interface AnthropicJsonToSseContext {
50
+ requestId: string;
51
+ model: string;
52
+ response: AnthropicMessageResponse;
53
+ options: AnthropicJsonToSseOptions;
54
+ startTime: number;
55
+ eventStats: AnthropicEventStats;
56
+ }
57
+ export interface SseToAnthropicJsonContext {
58
+ requestId: string;
59
+ model?: string;
60
+ startTime: number;
61
+ eventStats: AnthropicEventStats;
62
+ isCompleted: boolean;
63
+ startTimestamp?: number;
64
+ endTimestamp?: number;
65
+ }
66
+ export interface AnthropicJsonToSseOptions {
67
+ requestId: string;
68
+ model: string;
69
+ chunkSize?: number;
70
+ chunkDelayMs?: number;
71
+ reasoningMode?: ChatReasoningMode;
72
+ reasoningTextPrefix?: string;
73
+ }
74
+ export interface SseToAnthropicJsonOptions {
75
+ requestId: string;
76
+ model?: string;
77
+ reasoningMode?: ChatReasoningMode;
78
+ reasoningTextPrefix?: string;
79
+ }
80
+ export declare const DEFAULT_ANTHROPIC_CONVERSION_CONFIG: {
81
+ defaultChunkSize: number;
82
+ defaultDelayMs: number;
83
+ enableEventValidation: boolean;
84
+ strictMode: boolean;
85
+ reasoningMode: ChatReasoningMode;
86
+ reasoningTextPrefix: string | undefined;
87
+ };
88
+ export type AnthropicSseEventType = 'message_start' | 'content_block_start' | 'content_block_delta' | 'content_block_stop' | 'message_delta' | 'message_stop';
89
+ export interface AnthropicSseEventBase<T extends AnthropicSseEventType = AnthropicSseEventType> extends BaseSseEvent {
90
+ type: T;
91
+ event?: T;
92
+ protocol: 'anthropic-messages';
93
+ direction: StreamDirection;
94
+ data: unknown;
95
+ }
96
+ export interface AnthropicSseEventMessageStart extends AnthropicSseEventBase<'message_start'> {
97
+ data: {
98
+ type: 'message_start';
99
+ message: {
100
+ id: string;
101
+ type: 'message';
102
+ role: 'assistant';
103
+ model: string;
104
+ };
105
+ };
106
+ }
107
+ export interface AnthropicSseEventContentBlockStart extends AnthropicSseEventBase<'content_block_start'> {
108
+ data: {
109
+ type: 'content_block_start';
110
+ index: number;
111
+ content_block: {
112
+ type: 'text';
113
+ text?: string;
114
+ } | {
115
+ type: 'thinking';
116
+ text?: string;
117
+ } | {
118
+ type: 'tool_use';
119
+ id: string;
120
+ name: string;
121
+ input?: Record<string, unknown>;
122
+ } | {
123
+ type: 'tool_result';
124
+ tool_use_id: string;
125
+ content?: unknown;
126
+ is_error?: boolean;
127
+ };
128
+ };
129
+ }
130
+ export interface AnthropicSseEventContentBlockDelta extends AnthropicSseEventBase<'content_block_delta'> {
131
+ data: {
132
+ type: 'content_block_delta';
133
+ index: number;
134
+ delta: {
135
+ type: 'text_delta';
136
+ text: string;
137
+ } | {
138
+ type: 'thinking_delta';
139
+ text: string;
140
+ } | {
141
+ type: 'input_json_delta';
142
+ partial_json: string;
143
+ } | {
144
+ type: 'output_json_delta';
145
+ partial_json: string;
146
+ };
147
+ };
148
+ }
149
+ export interface AnthropicSseEventContentBlockStop extends AnthropicSseEventBase<'content_block_stop'> {
150
+ data: {
151
+ type: 'content_block_stop';
152
+ index: number;
153
+ };
154
+ }
155
+ export interface AnthropicSseEventMessageDelta extends AnthropicSseEventBase<'message_delta'> {
156
+ data: {
157
+ type: 'message_delta';
158
+ delta?: {
159
+ stop_reason?: AnthropicMessageResponse['stop_reason'];
160
+ usage?: AnthropicMessageResponse['usage'];
161
+ };
162
+ };
163
+ }
164
+ export interface AnthropicSseEventMessageStop extends AnthropicSseEventBase<'message_stop'> {
165
+ data: {
166
+ type: 'message_stop';
167
+ };
168
+ }
169
+ export type AnthropicSseEvent = AnthropicSseEventMessageStart | AnthropicSseEventContentBlockStart | AnthropicSseEventContentBlockDelta | AnthropicSseEventContentBlockStop | AnthropicSseEventMessageDelta | AnthropicSseEventMessageStop;
170
+ export type AnthropicSseEventStream = AsyncIterable<string> | AsyncIterable<Buffer>;
@@ -1,5 +1,8 @@
1
- /**
2
- * Minimal Anthropic SSE/JSON types for v3 SSE converters
3
- * Only covers text and basic tool_use blocks needed for roundtrip.
4
- */
5
- export {};
1
+ export const DEFAULT_ANTHROPIC_CONVERSION_CONFIG = {
2
+ defaultChunkSize: 1024,
3
+ defaultDelayMs: 0,
4
+ enableEventValidation: true,
5
+ strictMode: false,
6
+ reasoningMode: 'channel',
7
+ reasoningTextPrefix: undefined
8
+ };
@@ -116,6 +116,8 @@ export interface ChatMessage {
116
116
  role: 'system' | 'user' | 'assistant' | 'tool';
117
117
  content?: string | null;
118
118
  name?: string;
119
+ reasoning_content?: string;
120
+ reasoning?: string;
119
121
  function_call?: ChatFunctionCall;
120
122
  tool_calls?: ChatToolCall[];
121
123
  tool_call_id?: string;
@@ -191,6 +193,7 @@ export interface ChatChoiceBuilder {
191
193
  export interface ChatMessageBuilder {
192
194
  role?: 'system' | 'user' | 'assistant' | 'tool';
193
195
  content?: string;
196
+ reasoningContent?: string;
194
197
  name?: string;
195
198
  functionCall?: ChatFunctionCall;
196
199
  toolCalls?: ChatToolCall[];
@@ -208,6 +211,7 @@ export interface ChatToolCallBuilder {
208
211
  isCompleted: boolean;
209
212
  accumulatedArguments: string;
210
213
  }
214
+ export type ChatReasoningMode = 'channel' | 'text' | 'drop';
211
215
  export interface ChatJsonToSseOptions {
212
216
  requestId: string;
213
217
  model: string;
@@ -219,6 +223,8 @@ export interface ChatJsonToSseOptions {
219
223
  includeLogprobs?: boolean;
220
224
  maxTokensPerChunk?: number;
221
225
  validationMode?: 'none' | 'basic' | 'strict';
226
+ reasoningMode?: ChatReasoningMode;
227
+ reasoningTextPrefix?: string;
222
228
  onChunk?: (chunk: ChatCompletionChunk) => void;
223
229
  onError?: (error: Error) => void;
224
230
  onComplete?: () => void;
@@ -230,6 +236,8 @@ export interface SseToChatJsonOptions {
230
236
  validateChunks?: boolean;
231
237
  enableSequenceValidation?: boolean;
232
238
  accumulateToolCalls?: boolean;
239
+ reasoningMode?: ChatReasoningMode;
240
+ reasoningTextPrefix?: string;
233
241
  onPartialResponse?: (partial: Partial<ChatCompletionResponse>) => void;
234
242
  onEvent?: (event: ChatSseEvent) => void;
235
243
  onChunk?: (chunk: ChatCompletionChunk) => void;
@@ -295,6 +303,8 @@ export interface ChatConversionConfig {
295
303
  debugMode: boolean;
296
304
  logLevel: 'debug' | 'info' | 'warn' | 'error';
297
305
  enableMetrics: boolean;
306
+ reasoningMode: ChatReasoningMode;
307
+ reasoningTextPrefix?: string;
298
308
  }
299
309
  export declare const DEFAULT_CHAT_CONVERSION_CONFIG: ChatConversionConfig;
300
310
  export interface ChatSseEventStream extends AsyncIterable<ChatSseEvent> {
@@ -28,5 +28,6 @@ export const DEFAULT_CHAT_CONVERSION_CONFIG = {
28
28
  eventBufferSize: 1000,
29
29
  debugMode: false,
30
30
  logLevel: 'info',
31
- enableMetrics: true
31
+ enableMetrics: true,
32
+ reasoningMode: 'channel'
32
33
  };
@@ -20,7 +20,7 @@ export interface BaseSseEvent {
20
20
  /** 方向标识 */
21
21
  direction?: StreamDirection;
22
22
  }
23
- export type StreamProtocol = 'chat' | 'responses';
23
+ export type StreamProtocol = 'chat' | 'responses' | 'anthropic-messages' | 'gemini-chat';
24
24
  export type StreamDirection = 'json_to_sse' | 'sse_to_json';
25
25
  export type SseProtocol = StreamProtocol;
26
26
  export type SseDirection = StreamDirection;
@@ -0,0 +1,116 @@
1
+ import type { BaseSseEvent, StreamDirection } from './core-interfaces.js';
2
+ import type { ChatReasoningMode } from './chat-types.js';
3
+ export interface GeminiContentTextPart {
4
+ text: string;
5
+ }
6
+ export interface GeminiContentFunctionCallPart {
7
+ functionCall: {
8
+ name: string;
9
+ args?: Record<string, unknown>;
10
+ [key: string]: unknown;
11
+ };
12
+ }
13
+ export interface GeminiContentFunctionResponsePart {
14
+ functionResponse: {
15
+ name?: string;
16
+ response?: unknown;
17
+ [key: string]: unknown;
18
+ };
19
+ }
20
+ export interface GeminiContentInlineDataPart {
21
+ inlineData: {
22
+ mimeType: string;
23
+ data: string;
24
+ };
25
+ }
26
+ export type GeminiContentPart = GeminiContentTextPart | GeminiContentFunctionCallPart | GeminiContentFunctionResponsePart | GeminiContentInlineDataPart | Record<string, unknown>;
27
+ export interface GeminiCandidate {
28
+ content?: {
29
+ role?: string;
30
+ parts?: GeminiContentPart[];
31
+ };
32
+ finishReason?: string;
33
+ safetyRatings?: unknown[];
34
+ }
35
+ export interface GeminiUsageMetadata {
36
+ promptTokenCount?: number;
37
+ candidatesTokenCount?: number;
38
+ totalTokenCount?: number;
39
+ }
40
+ export interface GeminiResponse {
41
+ candidates?: GeminiCandidate[];
42
+ promptFeedback?: Record<string, unknown>;
43
+ usageMetadata?: GeminiUsageMetadata;
44
+ modelVersion?: string;
45
+ }
46
+ export interface GeminiEventStats {
47
+ totalEvents: number;
48
+ chunkEvents: number;
49
+ doneEvents: number;
50
+ errors: number;
51
+ startTime: number;
52
+ endTime?: number;
53
+ }
54
+ export interface GeminiJsonToSseOptions {
55
+ requestId: string;
56
+ model?: string;
57
+ chunkDelayMs?: number;
58
+ reasoningMode?: ChatReasoningMode;
59
+ reasoningTextPrefix?: string;
60
+ }
61
+ export interface GeminiJsonToSseContext {
62
+ requestId: string;
63
+ model?: string;
64
+ response: GeminiResponse;
65
+ options: GeminiJsonToSseOptions;
66
+ startTime: number;
67
+ eventStats: GeminiEventStats;
68
+ }
69
+ export interface SseToGeminiJsonOptions {
70
+ requestId: string;
71
+ model?: string;
72
+ reasoningMode?: ChatReasoningMode;
73
+ reasoningTextPrefix?: string;
74
+ }
75
+ export interface SseToGeminiJsonContext {
76
+ requestId: string;
77
+ model?: string;
78
+ options: {
79
+ reasoningMode?: ChatReasoningMode;
80
+ reasoningTextPrefix?: string;
81
+ };
82
+ startTime: number;
83
+ eventStats: GeminiEventStats;
84
+ isCompleted: boolean;
85
+ }
86
+ export type GeminiSseEventType = 'gemini.data' | 'gemini.done' | 'gemini.error';
87
+ export interface GeminiSseEvent extends BaseSseEvent {
88
+ type: GeminiSseEventType;
89
+ event?: GeminiSseEventType;
90
+ protocol: 'gemini-chat';
91
+ direction: StreamDirection;
92
+ data: unknown;
93
+ }
94
+ export interface GeminiChunkEventData {
95
+ kind: 'part';
96
+ candidateIndex: number;
97
+ partIndex: number;
98
+ role: string;
99
+ part: GeminiContentPart;
100
+ }
101
+ export interface GeminiDoneEventData {
102
+ kind: 'done';
103
+ usageMetadata?: GeminiUsageMetadata;
104
+ promptFeedback?: Record<string, unknown>;
105
+ modelVersion?: string;
106
+ candidates?: Array<{
107
+ index: number;
108
+ finishReason?: string;
109
+ safetyRatings?: unknown[];
110
+ }>;
111
+ }
112
+ export declare const DEFAULT_GEMINI_CONVERSION_CONFIG: {
113
+ chunkDelayMs: number;
114
+ reasoningMode: ChatReasoningMode;
115
+ reasoningTextPrefix: string | undefined;
116
+ };
@@ -0,0 +1,5 @@
1
+ export const DEFAULT_GEMINI_CONVERSION_CONFIG = {
2
+ chunkDelayMs: 0,
3
+ reasoningMode: 'channel',
4
+ reasoningTextPrefix: undefined
5
+ };
@@ -3,11 +3,14 @@
3
3
  * 支持Responses和Chat协议的JSON↔SSE双向转换
4
4
  */
5
5
  export type { BaseSseEvent, BaseSseEventStream, StreamProtocol, StreamDirection, SseProtocol, SseDirection } from './core-interfaces.js';
6
- export type { ChatSseEvent, ChatSseEventType, ChatSseEventStream, ChatEventStats, ChatJsonToSseContext, SseToChatJsonContext, ChatCompletionRequest, ChatCompletionResponse, ChatCompletionChunk, ChatMessage, ChatJsonToSseOptions, SseToChatJsonOptions, ChatConversionError, ChatToolCall, ChatToolCallChunk, ChatChoiceBuilder, ChatMessageBuilder, ChatToolCallBuilder } from './chat-types.js';
6
+ export type { ChatSseEvent, ChatSseEventType, ChatSseEventStream, ChatEventStats, ChatJsonToSseContext, SseToChatJsonContext, ChatCompletionRequest, ChatCompletionResponse, ChatCompletionChunk, ChatMessage, ChatJsonToSseOptions, SseToChatJsonOptions, ChatConversionError, ChatToolCall, ChatToolCallChunk, ChatChoiceBuilder, ChatMessageBuilder, ChatToolCallBuilder, ChatReasoningMode } from './chat-types.js';
7
7
  export type { ChatJsonToSseConverter } from '../json-to-sse/chat-json-to-sse-converter.js';
8
8
  export type { ResponsesJsonToSseConverter } from '../json-to-sse/responses-json-to-sse-converter.js';
9
9
  export type { ResponsesSseEvent, ResponsesSseEventType, ResponsesSseEventStream, ResponsesEventStats, ResponsesJsonToSseContext, SseToResponsesJsonContext, ResponsesJsonToSseOptions, SseToResponsesJsonOptions, ResponsesResponse, ResponsesRequest, ResponsesOutputItem, ResponsesMessageItem, ResponsesFunctionCallItem, ResponsesFunctionCallOutputItem, ResponsesReasoningItem, ResponsesContent, ResponsesTool, ResponsesToolCall, ResponsesUsage, OutputItemBuilder, OutputItemProcessingState } from './responses-types.js';
10
- export type { AnthropicMessageResponse } from './anthropic-types.js';
10
+ export type { AnthropicMessageResponse, AnthropicContentBlock, AnthropicJsonToSseContext, AnthropicJsonToSseOptions, AnthropicEventStats, SseToAnthropicJsonContext, SseToAnthropicJsonOptions, AnthropicSseEvent, AnthropicSseEventStream } from './anthropic-types.js';
11
+ export { DEFAULT_ANTHROPIC_CONVERSION_CONFIG } from './anthropic-types.js';
12
+ export type { GeminiResponse, GeminiCandidate, GeminiContentPart, GeminiUsageMetadata, GeminiJsonToSseOptions, GeminiJsonToSseContext, SseToGeminiJsonOptions, SseToGeminiJsonContext, GeminiEventStats, GeminiSseEvent, GeminiChunkEventData, GeminiDoneEventData } from './gemini-types.js';
13
+ export { DEFAULT_GEMINI_CONVERSION_CONFIG } from './gemini-types.js';
11
14
  export type { ChatSseToJsonConverter } from '../sse-to-json/chat-sse-to-json-converter.js';
12
15
  export type { ResponsesSseToJsonConverterRefactored as ResponsesSseToJsonConverter } from '../sse-to-json/responses-sse-to-json-converter.js';
13
16
  export { DEFAULT_CHAT_CONVERSION_CONFIG, CHAT_CONVERSION_ERROR_CODES } from './chat-types.js';
@@ -2,6 +2,8 @@
2
2
  * SSE双向转换模块类型定义统一导出
3
3
  * 支持Responses和Chat协议的JSON↔SSE双向转换
4
4
  */
5
+ export { DEFAULT_ANTHROPIC_CONVERSION_CONFIG } from './anthropic-types.js';
6
+ export { DEFAULT_GEMINI_CONVERSION_CONFIG } from './gemini-types.js';
5
7
  // 常量
6
8
  export { DEFAULT_CHAT_CONVERSION_CONFIG, CHAT_CONVERSION_ERROR_CODES } from './chat-types.js';
7
9
  export { DEFAULT_RESPONSES_CONVERSION_CONFIG, RESPONSES_CONVERSION_ERROR_CODES } from './responses-types.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jsonstudio/llms",
3
- "version": "0.4.4",
3
+ "version": "0.4.5",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",