@animalabs/membrane 0.5.50 → 0.5.52

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 (123) hide show
  1. package/dist/context/index.d.ts +12 -0
  2. package/dist/context/index.js +11 -0
  3. package/dist/context/index.js.map +1 -0
  4. package/dist/context/process.d.ts +43 -0
  5. package/dist/context/process.js +381 -0
  6. package/dist/context/process.js.map +1 -0
  7. package/dist/context/types.d.ts +164 -0
  8. package/dist/context/types.js +61 -0
  9. package/dist/context/types.js.map +1 -0
  10. package/dist/formatters/anthropic-xml.d.ts +63 -0
  11. package/dist/formatters/anthropic-xml.js +417 -0
  12. package/dist/formatters/anthropic-xml.js.map +1 -0
  13. package/dist/formatters/completions.d.ts +68 -0
  14. package/dist/formatters/completions.js +261 -0
  15. package/dist/formatters/completions.js.map +1 -0
  16. package/dist/formatters/index.d.ts +8 -0
  17. package/dist/formatters/index.js +7 -0
  18. package/dist/formatters/index.js.map +1 -0
  19. package/dist/formatters/native.d.ts +35 -0
  20. package/dist/formatters/native.js +336 -0
  21. package/dist/formatters/native.js.map +1 -0
  22. package/dist/formatters/types.d.ts +167 -0
  23. package/dist/formatters/types.js +7 -0
  24. package/dist/formatters/types.js.map +1 -0
  25. package/dist/index.d.ts +13 -0
  26. package/dist/index.js +20 -0
  27. package/dist/index.js.map +1 -0
  28. package/dist/membrane.d.ts +155 -0
  29. package/dist/providers/anthropic.d.ts +36 -0
  30. package/dist/providers/bedrock.d.ts +43 -0
  31. package/dist/providers/gemini.d.ts +68 -0
  32. package/dist/providers/gemini.js +538 -0
  33. package/dist/providers/gemini.js.map +1 -0
  34. package/dist/providers/index.d.ts +13 -0
  35. package/dist/providers/index.js +13 -0
  36. package/dist/providers/index.js.map +1 -0
  37. package/dist/providers/mock.d.ts +90 -0
  38. package/dist/providers/mock.d.ts.map +1 -0
  39. package/dist/providers/mock.js +210 -0
  40. package/dist/providers/mock.js.map +1 -0
  41. package/dist/providers/openai-compatible.d.ts +82 -0
  42. package/dist/providers/openai-compatible.js +480 -0
  43. package/dist/providers/openai-compatible.js.map +1 -0
  44. package/dist/providers/openai-completions.d.ts +89 -0
  45. package/dist/providers/openai-completions.js +347 -0
  46. package/dist/providers/openai-completions.js.map +1 -0
  47. package/dist/providers/openai-responses.d.ts +77 -0
  48. package/dist/providers/openai-responses.js +333 -0
  49. package/dist/providers/openai-responses.js.map +1 -0
  50. package/dist/providers/openai.d.ts +77 -0
  51. package/dist/providers/openai.js +533 -0
  52. package/dist/providers/openai.js.map +1 -0
  53. package/dist/providers/openrouter.d.ts +82 -0
  54. package/dist/providers/openrouter.js +556 -0
  55. package/dist/providers/openrouter.js.map +1 -0
  56. package/dist/providers/utils.d.ts +44 -0
  57. package/dist/providers/utils.d.ts.map +1 -0
  58. package/dist/providers/utils.js +100 -0
  59. package/dist/providers/utils.js.map +1 -0
  60. package/dist/registry/default-pricing.d.ts +3 -0
  61. package/dist/registry/default-pricing.d.ts.map +1 -0
  62. package/dist/registry/default-pricing.js +75 -0
  63. package/dist/registry/default-pricing.js.map +1 -0
  64. package/dist/transforms/chat.d.ts +52 -0
  65. package/dist/transforms/chat.js +136 -0
  66. package/dist/transforms/chat.js.map +1 -0
  67. package/dist/transforms/index.d.ts +5 -0
  68. package/dist/transforms/index.js +7 -0
  69. package/dist/transforms/index.js.map +1 -0
  70. package/dist/types/config.d.ts +110 -0
  71. package/dist/types/config.js +21 -0
  72. package/dist/types/config.js.map +1 -0
  73. package/dist/types/content.d.ts +87 -0
  74. package/dist/types/content.d.ts.map +1 -0
  75. package/dist/types/content.js +40 -0
  76. package/dist/types/content.js.map +1 -0
  77. package/dist/types/errors.d.ts +50 -0
  78. package/dist/types/errors.d.ts.map +1 -0
  79. package/dist/types/errors.js +253 -0
  80. package/dist/types/errors.js.map +1 -0
  81. package/dist/types/index.d.ts +20 -0
  82. package/dist/types/index.js +10 -0
  83. package/dist/types/index.js.map +1 -0
  84. package/dist/types/message.d.ts +52 -0
  85. package/dist/types/message.d.ts.map +1 -0
  86. package/dist/types/message.js +38 -0
  87. package/dist/types/message.js.map +1 -0
  88. package/dist/types/provider.d.ts +169 -0
  89. package/dist/types/provider.d.ts.map +1 -0
  90. package/dist/types/provider.js +5 -0
  91. package/dist/types/provider.js.map +1 -0
  92. package/dist/types/request.d.ts +116 -0
  93. package/dist/types/request.d.ts.map +1 -0
  94. package/dist/types/request.js +5 -0
  95. package/dist/types/request.js.map +1 -0
  96. package/dist/types/response.d.ts +131 -0
  97. package/dist/types/response.d.ts.map +1 -0
  98. package/dist/types/response.js +7 -0
  99. package/dist/types/response.js.map +1 -0
  100. package/dist/types/streaming.d.ts +194 -0
  101. package/dist/types/streaming.js +5 -0
  102. package/dist/types/streaming.js.map +1 -0
  103. package/dist/types/tools.d.ts +71 -0
  104. package/dist/types/tools.d.ts.map +1 -0
  105. package/dist/types/tools.js +5 -0
  106. package/dist/types/tools.js.map +1 -0
  107. package/dist/utils/cost.d.ts +10 -0
  108. package/dist/utils/cost.d.ts.map +1 -0
  109. package/dist/utils/cost.js +19 -0
  110. package/dist/utils/cost.js.map +1 -0
  111. package/dist/utils/index.d.ts +7 -0
  112. package/dist/utils/index.js +6 -0
  113. package/dist/utils/index.js.map +1 -0
  114. package/dist/utils/stream-parser.d.ts +84 -0
  115. package/dist/utils/stream-parser.js +418 -0
  116. package/dist/utils/stream-parser.js.map +1 -0
  117. package/dist/utils/tool-parser.d.ts +134 -0
  118. package/dist/utils/tool-parser.js +600 -0
  119. package/dist/utils/tool-parser.js.map +1 -0
  120. package/dist/yielding-stream.d.ts +60 -0
  121. package/dist/yielding-stream.js +206 -0
  122. package/dist/yielding-stream.js.map +1 -0
  123. package/package.json +1 -1
@@ -0,0 +1,261 @@
1
+ /**
2
+ * Completions Formatter
3
+ *
4
+ * Formatter for base/completion models that use single-prompt input.
5
+ * Serializes conversations to "Participant: content<eot>" format.
6
+ *
7
+ * Key features:
8
+ * - Converts multi-turn conversations to single prompt string
9
+ * - Adds configurable end-of-turn tokens
10
+ * - Generates stop sequences from participant names
11
+ * - Strips images (not supported in completion models)
12
+ * - No XML block parsing (passthrough mode)
13
+ */
14
+ // ============================================================================
15
+ // Passthrough Stream Parser (same as NativeFormatter)
16
+ // ============================================================================
17
+ /**
18
+ * Simple pass-through parser for base models.
19
+ * No XML tracking - just accumulates content.
20
+ */
21
+ class CompletionsStreamParser {
22
+ accumulated = '';
23
+ blockIndex = 0;
24
+ blockStarted = false;
25
+ processChunk(chunk) {
26
+ this.accumulated += chunk;
27
+ const meta = {
28
+ type: 'text',
29
+ visible: true,
30
+ blockIndex: this.blockIndex,
31
+ };
32
+ const emissions = [];
33
+ const blockEvents = [];
34
+ // Emit block_start on first chunk
35
+ if (!this.blockStarted) {
36
+ const startEvent = {
37
+ event: 'block_start',
38
+ index: this.blockIndex,
39
+ block: { type: 'text' },
40
+ };
41
+ emissions.push({ kind: 'blockEvent', event: startEvent });
42
+ blockEvents.push(startEvent);
43
+ this.blockStarted = true;
44
+ }
45
+ emissions.push({ kind: 'content', text: chunk, meta });
46
+ return { emissions, content: [{ text: chunk, meta }], blockEvents };
47
+ }
48
+ flush() {
49
+ const emissions = [];
50
+ const blockEvents = [];
51
+ if (this.blockStarted) {
52
+ const completeEvent = {
53
+ event: 'block_complete',
54
+ index: this.blockIndex,
55
+ block: { type: 'text', content: this.accumulated },
56
+ };
57
+ emissions.push({ kind: 'blockEvent', event: completeEvent });
58
+ blockEvents.push(completeEvent);
59
+ this.blockStarted = false;
60
+ }
61
+ return { emissions, content: [], blockEvents };
62
+ }
63
+ getAccumulated() {
64
+ return this.accumulated;
65
+ }
66
+ reset() {
67
+ this.accumulated = '';
68
+ this.blockIndex = 0;
69
+ this.blockStarted = false;
70
+ }
71
+ push(content) {
72
+ this.accumulated += content;
73
+ }
74
+ getCurrentBlockType() {
75
+ return 'text';
76
+ }
77
+ getBlockIndex() {
78
+ return this.blockIndex;
79
+ }
80
+ incrementBlockIndex() {
81
+ this.blockIndex++;
82
+ }
83
+ isInsideBlock() {
84
+ return false;
85
+ }
86
+ getDepths() {
87
+ return { functionCalls: 0, functionResults: 0, thinking: 0 };
88
+ }
89
+ resetForNewIteration() {
90
+ // No special reset needed
91
+ }
92
+ }
93
+ // ============================================================================
94
+ // Completions Formatter
95
+ // ============================================================================
96
+ export class CompletionsFormatter {
97
+ name = 'completions';
98
+ usesPrefill = true;
99
+ config;
100
+ constructor(config = {}) {
101
+ this.config = {
102
+ eotToken: config.eotToken ?? '<|eot|>',
103
+ nameFormat: config.nameFormat ?? '{name}: ',
104
+ messageSeparator: config.messageSeparator ?? '\n\n',
105
+ maxParticipantsForStop: config.maxParticipantsForStop ?? 10,
106
+ caseInsensitiveStops: config.caseInsensitiveStops ?? false,
107
+ warnOnImageStrip: config.warnOnImageStrip ?? true,
108
+ // Completions models don't support images - always strip
109
+ unsupportedMedia: 'strip',
110
+ warnOnStrip: config.warnOnStrip ?? true,
111
+ };
112
+ }
113
+ // ==========================================================================
114
+ // REQUEST BUILDING
115
+ // ==========================================================================
116
+ buildMessages(messages, options) {
117
+ const { assistantParticipant, systemPrompt, additionalStopSequences, maxParticipantsForStop = this.config.maxParticipantsForStop, contextPrefix, } = options;
118
+ const parts = [];
119
+ const participants = new Set();
120
+ let hasStrippedImages = false;
121
+ // Add system prompt as first part if present
122
+ if (systemPrompt) {
123
+ const systemText = typeof systemPrompt === 'string'
124
+ ? systemPrompt
125
+ : systemPrompt
126
+ .filter((b) => b.type === 'text')
127
+ .map(b => b.text)
128
+ .join('\n');
129
+ if (systemText) {
130
+ parts.push(systemText);
131
+ }
132
+ }
133
+ // Add context prefix after system prompt (for simulacrum seeding)
134
+ if (contextPrefix) {
135
+ const assistantPrefix = this.config.nameFormat.replace('{name}', assistantParticipant);
136
+ parts.push(`${assistantPrefix}${contextPrefix}${this.config.eotToken}`);
137
+ }
138
+ // Serialize each message
139
+ for (const message of messages) {
140
+ participants.add(message.participant);
141
+ const { text, hadImages } = this.extractTextContent(message.content);
142
+ if (hadImages) {
143
+ hasStrippedImages = true;
144
+ }
145
+ // Skip empty messages (except if it's the final completion target)
146
+ if (!text.trim()) {
147
+ continue;
148
+ }
149
+ // Format: "Participant: content<eot>"
150
+ const prefix = this.config.nameFormat.replace('{name}', message.participant);
151
+ const eot = this.config.eotToken;
152
+ parts.push(`${prefix}${text}${eot}`);
153
+ }
154
+ // Warn about stripped images
155
+ if (hasStrippedImages && this.config.warnOnImageStrip) {
156
+ console.warn('[CompletionsFormatter] Images were stripped from context (not supported in completions mode)');
157
+ }
158
+ // Add final assistant prefix (no EOT - model generates this)
159
+ const assistantPrefix = this.config.nameFormat.replace('{name}', assistantParticipant);
160
+ parts.push(assistantPrefix.trimEnd()); // Remove trailing space for cleaner completion
161
+ // Join all parts into single prompt
162
+ const prompt = parts.join(this.config.messageSeparator);
163
+ // Build stop sequences from participants
164
+ const stopSequences = this.buildStopSequences(participants, assistantParticipant, maxParticipantsForStop, additionalStopSequences);
165
+ // Return as single assistant message with prompt as content
166
+ // The provider adapter will extract this as the prompt
167
+ const providerMessages = [
168
+ { role: 'assistant', content: prompt },
169
+ ];
170
+ return {
171
+ messages: providerMessages,
172
+ assistantPrefill: prompt,
173
+ stopSequences,
174
+ };
175
+ }
176
+ formatToolResults(results, options) {
177
+ // Completions mode typically doesn't support tools
178
+ // But format them as simple text if needed
179
+ const parts = results.map(r => {
180
+ const content = typeof r.content === 'string' ? r.content : JSON.stringify(r.content);
181
+ return `[Tool Result: ${content}]`;
182
+ });
183
+ return parts.join('\n');
184
+ }
185
+ // ==========================================================================
186
+ // RESPONSE PARSING
187
+ // ==========================================================================
188
+ createStreamParser() {
189
+ return new CompletionsStreamParser();
190
+ }
191
+ parseToolCalls(content) {
192
+ // Base models don't have structured tool output
193
+ return [];
194
+ }
195
+ hasToolUse(content) {
196
+ // Base models determine completion via stop sequences
197
+ return false;
198
+ }
199
+ parseContentBlocks(content) {
200
+ // Trim leading whitespace (model often starts with space after prefix)
201
+ const trimmed = content.replace(/^\s+/, '');
202
+ if (!trimmed) {
203
+ return [];
204
+ }
205
+ return [{ type: 'text', text: trimmed }];
206
+ }
207
+ // ==========================================================================
208
+ // PRIVATE HELPERS
209
+ // ==========================================================================
210
+ extractTextContent(content) {
211
+ const textParts = [];
212
+ let hadImages = false;
213
+ for (const block of content) {
214
+ if (block.type === 'text') {
215
+ textParts.push(block.text);
216
+ }
217
+ else if (block.type === 'image') {
218
+ hadImages = true;
219
+ }
220
+ // Skip tool_use, tool_result, thinking blocks for base models
221
+ }
222
+ return {
223
+ text: textParts.join('\n'),
224
+ hadImages,
225
+ };
226
+ }
227
+ buildStopSequences(participants, assistantParticipant, maxParticipants, additionalStopSequences) {
228
+ const stops = [];
229
+ // Get recent participants (excluding assistant)
230
+ let count = 0;
231
+ for (const participant of participants) {
232
+ if (participant === assistantParticipant)
233
+ continue;
234
+ if (count >= maxParticipants)
235
+ break;
236
+ // Add both "\n\nName:" and "\nName:" variants
237
+ const prefix = this.config.nameFormat.replace('{name}', participant).trimEnd();
238
+ stops.push(`\n\n${prefix}`);
239
+ stops.push(`\n${prefix}`);
240
+ // Add lowercased variants if casing differs (for models that generate mixed-case names)
241
+ if (this.config.caseInsensitiveStops) {
242
+ const lower = this.config.nameFormat.replace('{name}', participant.toLowerCase()).trimEnd();
243
+ if (lower !== prefix) {
244
+ stops.push(`\n\n${lower}`);
245
+ stops.push(`\n${lower}`);
246
+ }
247
+ }
248
+ count++;
249
+ }
250
+ // Add EOT token as stop sequence if configured
251
+ if (this.config.eotToken) {
252
+ stops.push(this.config.eotToken);
253
+ }
254
+ // Add any additional stop sequences
255
+ if (additionalStopSequences?.length) {
256
+ stops.push(...additionalStopSequences);
257
+ }
258
+ return stops;
259
+ }
260
+ }
261
+ //# sourceMappingURL=completions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"completions.js","sourceRoot":"","sources":["../../src/formatters/completions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Formatter exports
3
+ */
4
+ export type { PrefillFormatter, StreamParser, FormatterConfig, BuildOptions, BuildResult, ParseResult, BlockType, ProviderMessage, } from './types.js';
5
+ export { AnthropicXmlFormatter, type AnthropicXmlFormatterConfig } from './anthropic-xml.js';
6
+ export { NativeFormatter, type NativeFormatterConfig } from './native.js';
7
+ export { CompletionsFormatter, type CompletionsFormatterConfig } from './completions.js';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Formatter exports
3
+ */
4
+ export { AnthropicXmlFormatter } from './anthropic-xml.js';
5
+ export { NativeFormatter } from './native.js';
6
+ export { CompletionsFormatter } from './completions.js';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/formatters/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH,OAAO,EAAE,qBAAqB,EAAoC,MAAM,oBAAoB,CAAC;AAC7F,OAAO,EAAE,eAAe,EAA8B,MAAM,aAAa,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAmC,MAAM,kBAAkB,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Native Formatter
3
+ *
4
+ * Pass-through formatter that converts messages to standard user/assistant
5
+ * format without prefill. Uses native API tool calling.
6
+ *
7
+ * Supports two participant modes:
8
+ * - 'simple': Strict two-party (Human/Assistant), no names in content
9
+ * - 'multiuser': Multiple participants, names prefixed to content
10
+ */
11
+ import type { NormalizedMessage, ContentBlock, ToolCall, ToolResult } from '../types/index.js';
12
+ import type { PrefillFormatter, StreamParser, BuildOptions, BuildResult, FormatterConfig } from './types.js';
13
+ export interface NativeFormatterConfig extends FormatterConfig {
14
+ /**
15
+ * Format for participant name prefix in multiuser mode.
16
+ * Use {name} as placeholder. Default: '{name}: '
17
+ */
18
+ nameFormat?: string;
19
+ }
20
+ export declare class NativeFormatter implements PrefillFormatter {
21
+ readonly name = "native";
22
+ readonly usesPrefill = false;
23
+ private config;
24
+ constructor(config?: NativeFormatterConfig);
25
+ buildMessages(messages: NormalizedMessage[], options: BuildOptions): BuildResult;
26
+ formatToolResults(results: ToolResult[]): string;
27
+ createStreamParser(): StreamParser;
28
+ parseToolCalls(content: string): ToolCall[];
29
+ hasToolUse(content: string): boolean;
30
+ parseContentBlocks(content: string): ContentBlock[];
31
+ private convertContent;
32
+ private mergeConsecutiveRoles;
33
+ private convertToNativeTools;
34
+ }
35
+ //# sourceMappingURL=native.d.ts.map
@@ -0,0 +1,336 @@
1
+ /**
2
+ * Native Formatter
3
+ *
4
+ * Pass-through formatter that converts messages to standard user/assistant
5
+ * format without prefill. Uses native API tool calling.
6
+ *
7
+ * Supports two participant modes:
8
+ * - 'simple': Strict two-party (Human/Assistant), no names in content
9
+ * - 'multiuser': Multiple participants, names prefixed to content
10
+ */
11
+ // ============================================================================
12
+ // Pass-through Stream Parser
13
+ // ============================================================================
14
+ /**
15
+ * Simple pass-through parser that doesn't do XML tracking.
16
+ * Just accumulates content and emits text chunks.
17
+ */
18
+ class PassthroughParser {
19
+ accumulated = '';
20
+ blockIndex = 0;
21
+ blockStarted = false;
22
+ processChunk(chunk) {
23
+ this.accumulated += chunk;
24
+ const meta = {
25
+ type: 'text',
26
+ visible: true,
27
+ blockIndex: this.blockIndex,
28
+ };
29
+ const emissions = [];
30
+ const blockEvents = [];
31
+ // Emit block_start on first chunk
32
+ if (!this.blockStarted) {
33
+ const startEvent = {
34
+ event: 'block_start',
35
+ index: this.blockIndex,
36
+ block: { type: 'text' },
37
+ };
38
+ emissions.push({ kind: 'blockEvent', event: startEvent });
39
+ blockEvents.push(startEvent);
40
+ this.blockStarted = true;
41
+ }
42
+ emissions.push({ kind: 'content', text: chunk, meta });
43
+ return { emissions, content: [{ text: chunk, meta }], blockEvents };
44
+ }
45
+ flush() {
46
+ const emissions = [];
47
+ const blockEvents = [];
48
+ if (this.blockStarted) {
49
+ const completeEvent = {
50
+ event: 'block_complete',
51
+ index: this.blockIndex,
52
+ block: { type: 'text', content: this.accumulated },
53
+ };
54
+ emissions.push({ kind: 'blockEvent', event: completeEvent });
55
+ blockEvents.push(completeEvent);
56
+ this.blockStarted = false;
57
+ }
58
+ return { emissions, content: [], blockEvents };
59
+ }
60
+ getAccumulated() {
61
+ return this.accumulated;
62
+ }
63
+ reset() {
64
+ this.accumulated = '';
65
+ this.blockIndex = 0;
66
+ this.blockStarted = false;
67
+ }
68
+ push(content) {
69
+ this.accumulated += content;
70
+ }
71
+ getCurrentBlockType() {
72
+ return 'text';
73
+ }
74
+ getBlockIndex() {
75
+ return this.blockIndex;
76
+ }
77
+ incrementBlockIndex() {
78
+ this.blockIndex++;
79
+ }
80
+ isInsideBlock() {
81
+ // Pass-through mode never has nested blocks
82
+ return false;
83
+ }
84
+ getDepths() {
85
+ return { functionCalls: 0, functionResults: 0, thinking: 0 };
86
+ }
87
+ resetForNewIteration() {
88
+ // No special reset needed for pass-through mode
89
+ }
90
+ }
91
+ // ============================================================================
92
+ // Native Formatter
93
+ // ============================================================================
94
+ export class NativeFormatter {
95
+ name = 'native';
96
+ usesPrefill = false;
97
+ config;
98
+ constructor(config = {}) {
99
+ this.config = {
100
+ nameFormat: config.nameFormat ?? '{name}: ',
101
+ unsupportedMedia: config.unsupportedMedia ?? 'error',
102
+ warnOnStrip: config.warnOnStrip ?? true,
103
+ };
104
+ }
105
+ // ==========================================================================
106
+ // REQUEST BUILDING
107
+ // ==========================================================================
108
+ buildMessages(messages, options) {
109
+ const { participantMode, assistantParticipant, humanParticipant, tools, systemPrompt, promptCaching = false, cacheTtl, hasCacheMarker, contextPrefix, additionalStopSequences, } = options;
110
+ // Build cache_control object if prompt caching is enabled
111
+ const cacheControl = promptCaching
112
+ ? { type: 'ephemeral', ...(cacheTtl ? { ttl: cacheTtl } : {}) }
113
+ : undefined;
114
+ const providerMessages = [];
115
+ // Add context prefix as first assistant message (for simulacrum seeding)
116
+ if (contextPrefix) {
117
+ const prefixBlock = { type: 'text', text: contextPrefix };
118
+ if (promptCaching && cacheControl) {
119
+ prefixBlock.cache_control = cacheControl;
120
+ }
121
+ providerMessages.push({
122
+ role: 'assistant',
123
+ content: [prefixBlock],
124
+ });
125
+ }
126
+ // Validate simple mode participants
127
+ if (participantMode === 'simple' && !humanParticipant) {
128
+ throw new Error('NativeFormatter in simple mode requires humanParticipant option');
129
+ }
130
+ for (let i = 0; i < messages.length; i++) {
131
+ const message = messages[i];
132
+ if (!message)
133
+ continue;
134
+ // Determine role
135
+ const isAssistant = message.participant === assistantParticipant;
136
+ // Validate participant in simple mode
137
+ if (participantMode === 'simple') {
138
+ if (!isAssistant && message.participant !== humanParticipant) {
139
+ throw new Error(`NativeFormatter in simple mode only supports "${humanParticipant}" and "${assistantParticipant}". ` +
140
+ `Got: "${message.participant}". Use participantMode: 'multiuser' for multiple participants.`);
141
+ }
142
+ }
143
+ const role = isAssistant ? 'assistant' : 'user';
144
+ // Convert content
145
+ const content = this.convertContent(message.content, message.participant, {
146
+ includeNames: participantMode === 'multiuser' && !isAssistant,
147
+ });
148
+ if (content.length === 0) {
149
+ continue; // Skip empty messages
150
+ }
151
+ // hasCacheMarker: cache boundary is BEFORE this message — tag previous message's last block
152
+ if (hasCacheMarker && hasCacheMarker(message, i) && cacheControl && providerMessages.length > 0) {
153
+ const prevMsg = providerMessages[providerMessages.length - 1];
154
+ const prevContent = Array.isArray(prevMsg.content) ? prevMsg.content : [];
155
+ if (prevContent.length > 0) {
156
+ prevContent[prevContent.length - 1].cache_control = cacheControl;
157
+ }
158
+ }
159
+ providerMessages.push({ role, content });
160
+ // cacheBreakpoint: cache up to and INCLUDING this message — tag last block
161
+ if (message.cacheBreakpoint && cacheControl && content.length > 0) {
162
+ content[content.length - 1].cache_control = cacheControl;
163
+ }
164
+ }
165
+ // Merge consecutive same-role messages (API requires alternating)
166
+ const mergedMessages = this.mergeConsecutiveRoles(providerMessages);
167
+ // Build system content with optional cache control
168
+ let systemContent;
169
+ if (typeof systemPrompt === 'string') {
170
+ if (cacheControl) {
171
+ // Must use array format for cache_control support
172
+ systemContent = [{ type: 'text', text: systemPrompt, cache_control: cacheControl }];
173
+ }
174
+ else {
175
+ systemContent = systemPrompt;
176
+ }
177
+ }
178
+ else if (Array.isArray(systemPrompt)) {
179
+ if (cacheControl && systemPrompt.length > 0) {
180
+ // Add cache_control to the last system block
181
+ systemContent = systemPrompt.map((block, idx) => {
182
+ if (idx === systemPrompt.length - 1) {
183
+ return { ...block, cache_control: cacheControl };
184
+ }
185
+ return block;
186
+ });
187
+ }
188
+ else {
189
+ systemContent = systemPrompt;
190
+ }
191
+ }
192
+ // Native tools
193
+ const nativeTools = tools?.length ? this.convertToNativeTools(tools) : undefined;
194
+ return {
195
+ messages: mergedMessages,
196
+ systemContent,
197
+ stopSequences: additionalStopSequences ?? [],
198
+ nativeTools,
199
+ };
200
+ }
201
+ formatToolResults(results) {
202
+ // Native mode uses API tool_result blocks, not string formatting
203
+ // This method is mainly for prefill modes
204
+ return JSON.stringify(results.map(r => ({
205
+ tool_use_id: r.toolUseId,
206
+ content: r.content,
207
+ is_error: r.isError,
208
+ })));
209
+ }
210
+ // ==========================================================================
211
+ // RESPONSE PARSING
212
+ // ==========================================================================
213
+ createStreamParser() {
214
+ return new PassthroughParser();
215
+ }
216
+ parseToolCalls(content) {
217
+ // Native mode gets tool calls from API response, not from content parsing
218
+ // Return empty - tool calls come through the native API response
219
+ return [];
220
+ }
221
+ hasToolUse(content) {
222
+ // Native mode determines tool use from API stop_reason, not content
223
+ return false;
224
+ }
225
+ parseContentBlocks(content) {
226
+ // Native mode - content is plain text
227
+ if (!content.trim()) {
228
+ return [];
229
+ }
230
+ return [{ type: 'text', text: content }];
231
+ }
232
+ // ==========================================================================
233
+ // PRIVATE HELPERS
234
+ // ==========================================================================
235
+ convertContent(content, participant, options) {
236
+ const result = [];
237
+ let hasUnsupportedMedia = false;
238
+ for (const block of content) {
239
+ if (block.type === 'text') {
240
+ let text = block.text;
241
+ if (options.includeNames) {
242
+ const prefix = this.config.nameFormat.replace('{name}', participant);
243
+ text = prefix + text;
244
+ }
245
+ const textBlock = { type: 'text', text };
246
+ if (block.cache_control) {
247
+ textBlock.cache_control = block.cache_control;
248
+ }
249
+ result.push(textBlock);
250
+ }
251
+ else if (block.type === 'image') {
252
+ if (block.source.type === 'base64') {
253
+ const imageBlock = {
254
+ type: 'image',
255
+ source: {
256
+ type: 'base64',
257
+ media_type: block.source.mediaType,
258
+ data: block.source.data,
259
+ },
260
+ };
261
+ // Preserve sourceUrl for providers that use URL-as-text (Gemini 3.x)
262
+ if (block.sourceUrl) {
263
+ imageBlock.sourceUrl = block.sourceUrl;
264
+ }
265
+ result.push(imageBlock);
266
+ }
267
+ }
268
+ else if (block.type === 'tool_use') {
269
+ result.push({
270
+ type: 'tool_use',
271
+ id: block.id,
272
+ name: block.name,
273
+ input: block.input,
274
+ });
275
+ }
276
+ else if (block.type === 'tool_result') {
277
+ result.push({
278
+ type: 'tool_result',
279
+ tool_use_id: block.toolUseId,
280
+ content: block.content,
281
+ is_error: block.isError,
282
+ });
283
+ }
284
+ else if (block.type === 'thinking') {
285
+ result.push({
286
+ type: 'thinking',
287
+ thinking: block.thinking,
288
+ });
289
+ }
290
+ else if (block.type === 'document' || block.type === 'audio') {
291
+ hasUnsupportedMedia = true;
292
+ }
293
+ }
294
+ if (hasUnsupportedMedia) {
295
+ if (this.config.unsupportedMedia === 'error') {
296
+ throw new Error(`NativeFormatter: unsupported media type in content. Configure unsupportedMedia: 'strip' to ignore.`);
297
+ }
298
+ else if (this.config.warnOnStrip) {
299
+ console.warn(`[NativeFormatter] Stripped unsupported media from message`);
300
+ }
301
+ }
302
+ return result;
303
+ }
304
+ mergeConsecutiveRoles(messages) {
305
+ if (messages.length === 0)
306
+ return [];
307
+ const merged = [];
308
+ let current = messages[0];
309
+ for (let i = 1; i < messages.length; i++) {
310
+ const next = messages[i];
311
+ if (next.role === current.role) {
312
+ // Merge content arrays
313
+ const currentContent = Array.isArray(current.content) ? current.content : [current.content];
314
+ const nextContent = Array.isArray(next.content) ? next.content : [next.content];
315
+ current = {
316
+ role: current.role,
317
+ content: [...currentContent, ...nextContent],
318
+ };
319
+ }
320
+ else {
321
+ merged.push(current);
322
+ current = next;
323
+ }
324
+ }
325
+ merged.push(current);
326
+ return merged;
327
+ }
328
+ convertToNativeTools(tools) {
329
+ return tools.map(tool => ({
330
+ name: tool.name,
331
+ description: tool.description,
332
+ input_schema: tool.inputSchema,
333
+ }));
334
+ }
335
+ }
336
+ //# sourceMappingURL=native.js.map