@animalabs/membrane 0.5.51 → 0.5.53

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 (134) 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 +10 -0
  17. package/dist/formatters/index.d.ts.map +1 -1
  18. package/dist/formatters/index.js +8 -0
  19. package/dist/formatters/index.js.map +1 -0
  20. package/dist/formatters/native.d.ts +35 -0
  21. package/dist/formatters/native.d.ts.map +1 -1
  22. package/dist/formatters/native.js +346 -0
  23. package/dist/formatters/native.js.map +1 -0
  24. package/dist/formatters/normalize-tool-pairs.d.ts +75 -0
  25. package/dist/formatters/normalize-tool-pairs.d.ts.map +1 -0
  26. package/dist/formatters/normalize-tool-pairs.js +498 -0
  27. package/dist/formatters/normalize-tool-pairs.js.map +1 -0
  28. package/dist/formatters/types.d.ts +222 -0
  29. package/dist/formatters/types.d.ts.map +1 -1
  30. package/dist/formatters/types.js +7 -0
  31. package/dist/formatters/types.js.map +1 -0
  32. package/dist/index.d.ts +13 -0
  33. package/dist/index.js +20 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/membrane.d.ts +155 -0
  36. package/dist/providers/anthropic.d.ts +36 -0
  37. package/dist/providers/bedrock.d.ts +43 -0
  38. package/dist/providers/gemini.d.ts +68 -0
  39. package/dist/providers/gemini.js +538 -0
  40. package/dist/providers/gemini.js.map +1 -0
  41. package/dist/providers/index.d.ts +13 -0
  42. package/dist/providers/index.js +13 -0
  43. package/dist/providers/index.js.map +1 -0
  44. package/dist/providers/mock.d.ts +90 -0
  45. package/dist/providers/mock.d.ts.map +1 -0
  46. package/dist/providers/mock.js +210 -0
  47. package/dist/providers/mock.js.map +1 -0
  48. package/dist/providers/openai-compatible.d.ts +82 -0
  49. package/dist/providers/openai-compatible.js +480 -0
  50. package/dist/providers/openai-compatible.js.map +1 -0
  51. package/dist/providers/openai-completions.d.ts +89 -0
  52. package/dist/providers/openai-completions.js +347 -0
  53. package/dist/providers/openai-completions.js.map +1 -0
  54. package/dist/providers/openai-responses.d.ts +77 -0
  55. package/dist/providers/openai-responses.js +333 -0
  56. package/dist/providers/openai-responses.js.map +1 -0
  57. package/dist/providers/openai.d.ts +77 -0
  58. package/dist/providers/openai.js +533 -0
  59. package/dist/providers/openai.js.map +1 -0
  60. package/dist/providers/openrouter.d.ts +82 -0
  61. package/dist/providers/openrouter.js +556 -0
  62. package/dist/providers/openrouter.js.map +1 -0
  63. package/dist/providers/utils.d.ts +44 -0
  64. package/dist/providers/utils.d.ts.map +1 -0
  65. package/dist/providers/utils.js +100 -0
  66. package/dist/providers/utils.js.map +1 -0
  67. package/dist/registry/default-pricing.d.ts +3 -0
  68. package/dist/registry/default-pricing.d.ts.map +1 -0
  69. package/dist/registry/default-pricing.js +75 -0
  70. package/dist/registry/default-pricing.js.map +1 -0
  71. package/dist/transforms/chat.d.ts +52 -0
  72. package/dist/transforms/chat.js +136 -0
  73. package/dist/transforms/chat.js.map +1 -0
  74. package/dist/transforms/index.d.ts +5 -0
  75. package/dist/transforms/index.js +7 -0
  76. package/dist/transforms/index.js.map +1 -0
  77. package/dist/types/config.d.ts +110 -0
  78. package/dist/types/config.js +21 -0
  79. package/dist/types/config.js.map +1 -0
  80. package/dist/types/content.d.ts +87 -0
  81. package/dist/types/content.d.ts.map +1 -0
  82. package/dist/types/content.js +40 -0
  83. package/dist/types/content.js.map +1 -0
  84. package/dist/types/errors.d.ts +50 -0
  85. package/dist/types/errors.d.ts.map +1 -0
  86. package/dist/types/errors.js +253 -0
  87. package/dist/types/errors.js.map +1 -0
  88. package/dist/types/index.d.ts +20 -0
  89. package/dist/types/index.js +10 -0
  90. package/dist/types/index.js.map +1 -0
  91. package/dist/types/message.d.ts +52 -0
  92. package/dist/types/message.d.ts.map +1 -0
  93. package/dist/types/message.js +38 -0
  94. package/dist/types/message.js.map +1 -0
  95. package/dist/types/provider.d.ts +169 -0
  96. package/dist/types/provider.d.ts.map +1 -0
  97. package/dist/types/provider.js +5 -0
  98. package/dist/types/provider.js.map +1 -0
  99. package/dist/types/request.d.ts +116 -0
  100. package/dist/types/request.d.ts.map +1 -0
  101. package/dist/types/request.js +5 -0
  102. package/dist/types/request.js.map +1 -0
  103. package/dist/types/response.d.ts +131 -0
  104. package/dist/types/response.d.ts.map +1 -0
  105. package/dist/types/response.js +7 -0
  106. package/dist/types/response.js.map +1 -0
  107. package/dist/types/streaming.d.ts +194 -0
  108. package/dist/types/streaming.js +5 -0
  109. package/dist/types/streaming.js.map +1 -0
  110. package/dist/types/tools.d.ts +71 -0
  111. package/dist/types/tools.d.ts.map +1 -0
  112. package/dist/types/tools.js +5 -0
  113. package/dist/types/tools.js.map +1 -0
  114. package/dist/utils/cost.d.ts +10 -0
  115. package/dist/utils/cost.d.ts.map +1 -0
  116. package/dist/utils/cost.js +19 -0
  117. package/dist/utils/cost.js.map +1 -0
  118. package/dist/utils/index.d.ts +7 -0
  119. package/dist/utils/index.js +6 -0
  120. package/dist/utils/index.js.map +1 -0
  121. package/dist/utils/stream-parser.d.ts +84 -0
  122. package/dist/utils/stream-parser.js +418 -0
  123. package/dist/utils/stream-parser.js.map +1 -0
  124. package/dist/utils/tool-parser.d.ts +134 -0
  125. package/dist/utils/tool-parser.js +600 -0
  126. package/dist/utils/tool-parser.js.map +1 -0
  127. package/dist/yielding-stream.d.ts +60 -0
  128. package/dist/yielding-stream.js +206 -0
  129. package/dist/yielding-stream.js.map +1 -0
  130. package/package.json +1 -1
  131. package/src/formatters/index.ts +9 -0
  132. package/src/formatters/native.ts +12 -1
  133. package/src/formatters/normalize-tool-pairs.ts +622 -0
  134. package/src/formatters/types.ts +39 -0
@@ -0,0 +1,346 @@
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 { normalizeToolPairs } from './normalize-tool-pairs.js';
12
+ // ============================================================================
13
+ // Pass-through Stream Parser
14
+ // ============================================================================
15
+ /**
16
+ * Simple pass-through parser that doesn't do XML tracking.
17
+ * Just accumulates content and emits text chunks.
18
+ */
19
+ class PassthroughParser {
20
+ accumulated = '';
21
+ blockIndex = 0;
22
+ blockStarted = false;
23
+ processChunk(chunk) {
24
+ this.accumulated += chunk;
25
+ const meta = {
26
+ type: 'text',
27
+ visible: true,
28
+ blockIndex: this.blockIndex,
29
+ };
30
+ const emissions = [];
31
+ const blockEvents = [];
32
+ // Emit block_start on first chunk
33
+ if (!this.blockStarted) {
34
+ const startEvent = {
35
+ event: 'block_start',
36
+ index: this.blockIndex,
37
+ block: { type: 'text' },
38
+ };
39
+ emissions.push({ kind: 'blockEvent', event: startEvent });
40
+ blockEvents.push(startEvent);
41
+ this.blockStarted = true;
42
+ }
43
+ emissions.push({ kind: 'content', text: chunk, meta });
44
+ return { emissions, content: [{ text: chunk, meta }], blockEvents };
45
+ }
46
+ flush() {
47
+ const emissions = [];
48
+ const blockEvents = [];
49
+ if (this.blockStarted) {
50
+ const completeEvent = {
51
+ event: 'block_complete',
52
+ index: this.blockIndex,
53
+ block: { type: 'text', content: this.accumulated },
54
+ };
55
+ emissions.push({ kind: 'blockEvent', event: completeEvent });
56
+ blockEvents.push(completeEvent);
57
+ this.blockStarted = false;
58
+ }
59
+ return { emissions, content: [], blockEvents };
60
+ }
61
+ getAccumulated() {
62
+ return this.accumulated;
63
+ }
64
+ reset() {
65
+ this.accumulated = '';
66
+ this.blockIndex = 0;
67
+ this.blockStarted = false;
68
+ }
69
+ push(content) {
70
+ this.accumulated += content;
71
+ }
72
+ getCurrentBlockType() {
73
+ return 'text';
74
+ }
75
+ getBlockIndex() {
76
+ return this.blockIndex;
77
+ }
78
+ incrementBlockIndex() {
79
+ this.blockIndex++;
80
+ }
81
+ isInsideBlock() {
82
+ // Pass-through mode never has nested blocks
83
+ return false;
84
+ }
85
+ getDepths() {
86
+ return { functionCalls: 0, functionResults: 0, thinking: 0 };
87
+ }
88
+ resetForNewIteration() {
89
+ // No special reset needed for pass-through mode
90
+ }
91
+ }
92
+ // ============================================================================
93
+ // Native Formatter
94
+ // ============================================================================
95
+ export class NativeFormatter {
96
+ name = 'native';
97
+ usesPrefill = false;
98
+ config;
99
+ constructor(config = {}) {
100
+ this.config = {
101
+ nameFormat: config.nameFormat ?? '{name}: ',
102
+ unsupportedMedia: config.unsupportedMedia ?? 'error',
103
+ warnOnStrip: config.warnOnStrip ?? true,
104
+ };
105
+ }
106
+ // ==========================================================================
107
+ // REQUEST BUILDING
108
+ // ==========================================================================
109
+ buildMessages(messages, options) {
110
+ const { participantMode, assistantParticipant, humanParticipant, tools, systemPrompt, promptCaching = false, cacheTtl, hasCacheMarker, contextPrefix, additionalStopSequences, } = options;
111
+ // Build cache_control object if prompt caching is enabled
112
+ const cacheControl = promptCaching
113
+ ? { type: 'ephemeral', ...(cacheTtl ? { ttl: cacheTtl } : {}) }
114
+ : undefined;
115
+ const providerMessages = [];
116
+ // Add context prefix as first assistant message (for simulacrum seeding)
117
+ if (contextPrefix) {
118
+ const prefixBlock = { type: 'text', text: contextPrefix };
119
+ if (promptCaching && cacheControl) {
120
+ prefixBlock.cache_control = cacheControl;
121
+ }
122
+ providerMessages.push({
123
+ role: 'assistant',
124
+ content: [prefixBlock],
125
+ });
126
+ }
127
+ // Validate simple mode participants
128
+ if (participantMode === 'simple' && !humanParticipant) {
129
+ throw new Error('NativeFormatter in simple mode requires humanParticipant option');
130
+ }
131
+ for (let i = 0; i < messages.length; i++) {
132
+ const message = messages[i];
133
+ if (!message)
134
+ continue;
135
+ // Determine role
136
+ const isAssistant = message.participant === assistantParticipant;
137
+ // Validate participant in simple mode
138
+ if (participantMode === 'simple') {
139
+ if (!isAssistant && message.participant !== humanParticipant) {
140
+ throw new Error(`NativeFormatter in simple mode only supports "${humanParticipant}" and "${assistantParticipant}". ` +
141
+ `Got: "${message.participant}". Use participantMode: 'multiuser' for multiple participants.`);
142
+ }
143
+ }
144
+ const role = isAssistant ? 'assistant' : 'user';
145
+ // Convert content
146
+ const content = this.convertContent(message.content, message.participant, {
147
+ includeNames: participantMode === 'multiuser' && !isAssistant,
148
+ });
149
+ if (content.length === 0) {
150
+ continue; // Skip empty messages
151
+ }
152
+ // hasCacheMarker: cache boundary is BEFORE this message — tag previous message's last block
153
+ if (hasCacheMarker && hasCacheMarker(message, i) && cacheControl && providerMessages.length > 0) {
154
+ const prevMsg = providerMessages[providerMessages.length - 1];
155
+ const prevContent = Array.isArray(prevMsg.content) ? prevMsg.content : [];
156
+ if (prevContent.length > 0) {
157
+ prevContent[prevContent.length - 1].cache_control = cacheControl;
158
+ }
159
+ }
160
+ providerMessages.push({ role, content });
161
+ // cacheBreakpoint: cache up to and INCLUDING this message — tag last block
162
+ if (message.cacheBreakpoint && cacheControl && content.length > 0) {
163
+ content[content.length - 1].cache_control = cacheControl;
164
+ }
165
+ }
166
+ // Tool-pair normalizer: wire-boundary safety net for Anthropic's
167
+ // structural rules on tool cycles. See `normalize-tool-pairs.ts`
168
+ // for the full rationale. Runs BEFORE mergeConsecutiveRoles so the
169
+ // merge sees role-correct envelopes.
170
+ const normalized = normalizeToolPairs(providerMessages, {
171
+ pendingToolCallIds: options.pendingToolCallIds,
172
+ onEvent: options.onNormalize,
173
+ });
174
+ // Merge consecutive same-role messages (API requires alternating)
175
+ const mergedMessages = this.mergeConsecutiveRoles(normalized.messages);
176
+ // Build system content with optional cache control
177
+ let systemContent;
178
+ if (typeof systemPrompt === 'string') {
179
+ if (cacheControl) {
180
+ // Must use array format for cache_control support
181
+ systemContent = [{ type: 'text', text: systemPrompt, cache_control: cacheControl }];
182
+ }
183
+ else {
184
+ systemContent = systemPrompt;
185
+ }
186
+ }
187
+ else if (Array.isArray(systemPrompt)) {
188
+ if (cacheControl && systemPrompt.length > 0) {
189
+ // Add cache_control to the last system block
190
+ systemContent = systemPrompt.map((block, idx) => {
191
+ if (idx === systemPrompt.length - 1) {
192
+ return { ...block, cache_control: cacheControl };
193
+ }
194
+ return block;
195
+ });
196
+ }
197
+ else {
198
+ systemContent = systemPrompt;
199
+ }
200
+ }
201
+ // Native tools
202
+ const nativeTools = tools?.length ? this.convertToNativeTools(tools) : undefined;
203
+ return {
204
+ messages: mergedMessages,
205
+ systemContent,
206
+ stopSequences: additionalStopSequences ?? [],
207
+ nativeTools,
208
+ ready: normalized.ready,
209
+ };
210
+ }
211
+ formatToolResults(results) {
212
+ // Native mode uses API tool_result blocks, not string formatting
213
+ // This method is mainly for prefill modes
214
+ return JSON.stringify(results.map(r => ({
215
+ tool_use_id: r.toolUseId,
216
+ content: r.content,
217
+ is_error: r.isError,
218
+ })));
219
+ }
220
+ // ==========================================================================
221
+ // RESPONSE PARSING
222
+ // ==========================================================================
223
+ createStreamParser() {
224
+ return new PassthroughParser();
225
+ }
226
+ parseToolCalls(content) {
227
+ // Native mode gets tool calls from API response, not from content parsing
228
+ // Return empty - tool calls come through the native API response
229
+ return [];
230
+ }
231
+ hasToolUse(content) {
232
+ // Native mode determines tool use from API stop_reason, not content
233
+ return false;
234
+ }
235
+ parseContentBlocks(content) {
236
+ // Native mode - content is plain text
237
+ if (!content.trim()) {
238
+ return [];
239
+ }
240
+ return [{ type: 'text', text: content }];
241
+ }
242
+ // ==========================================================================
243
+ // PRIVATE HELPERS
244
+ // ==========================================================================
245
+ convertContent(content, participant, options) {
246
+ const result = [];
247
+ let hasUnsupportedMedia = false;
248
+ for (const block of content) {
249
+ if (block.type === 'text') {
250
+ let text = block.text;
251
+ if (options.includeNames) {
252
+ const prefix = this.config.nameFormat.replace('{name}', participant);
253
+ text = prefix + text;
254
+ }
255
+ const textBlock = { type: 'text', text };
256
+ if (block.cache_control) {
257
+ textBlock.cache_control = block.cache_control;
258
+ }
259
+ result.push(textBlock);
260
+ }
261
+ else if (block.type === 'image') {
262
+ if (block.source.type === 'base64') {
263
+ const imageBlock = {
264
+ type: 'image',
265
+ source: {
266
+ type: 'base64',
267
+ media_type: block.source.mediaType,
268
+ data: block.source.data,
269
+ },
270
+ };
271
+ // Preserve sourceUrl for providers that use URL-as-text (Gemini 3.x)
272
+ if (block.sourceUrl) {
273
+ imageBlock.sourceUrl = block.sourceUrl;
274
+ }
275
+ result.push(imageBlock);
276
+ }
277
+ }
278
+ else if (block.type === 'tool_use') {
279
+ result.push({
280
+ type: 'tool_use',
281
+ id: block.id,
282
+ name: block.name,
283
+ input: block.input,
284
+ });
285
+ }
286
+ else if (block.type === 'tool_result') {
287
+ result.push({
288
+ type: 'tool_result',
289
+ tool_use_id: block.toolUseId,
290
+ content: block.content,
291
+ is_error: block.isError,
292
+ });
293
+ }
294
+ else if (block.type === 'thinking') {
295
+ result.push({
296
+ type: 'thinking',
297
+ thinking: block.thinking,
298
+ });
299
+ }
300
+ else if (block.type === 'document' || block.type === 'audio') {
301
+ hasUnsupportedMedia = true;
302
+ }
303
+ }
304
+ if (hasUnsupportedMedia) {
305
+ if (this.config.unsupportedMedia === 'error') {
306
+ throw new Error(`NativeFormatter: unsupported media type in content. Configure unsupportedMedia: 'strip' to ignore.`);
307
+ }
308
+ else if (this.config.warnOnStrip) {
309
+ console.warn(`[NativeFormatter] Stripped unsupported media from message`);
310
+ }
311
+ }
312
+ return result;
313
+ }
314
+ mergeConsecutiveRoles(messages) {
315
+ if (messages.length === 0)
316
+ return [];
317
+ const merged = [];
318
+ let current = messages[0];
319
+ for (let i = 1; i < messages.length; i++) {
320
+ const next = messages[i];
321
+ if (next.role === current.role) {
322
+ // Merge content arrays
323
+ const currentContent = Array.isArray(current.content) ? current.content : [current.content];
324
+ const nextContent = Array.isArray(next.content) ? next.content : [next.content];
325
+ current = {
326
+ role: current.role,
327
+ content: [...currentContent, ...nextContent],
328
+ };
329
+ }
330
+ else {
331
+ merged.push(current);
332
+ current = next;
333
+ }
334
+ }
335
+ merged.push(current);
336
+ return merged;
337
+ }
338
+ convertToNativeTools(tools) {
339
+ return tools.map(tool => ({
340
+ name: tool.name,
341
+ description: tool.description,
342
+ input_schema: tool.inputSchema,
343
+ }));
344
+ }
345
+ }
346
+ //# sourceMappingURL=native.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"native.js","sourceRoot":"","sources":["../../src/formatters/native.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Tool-Pair Normalizer
3
+ *
4
+ * Anthropic's API enforces structural rules on tool cycles that any of
5
+ * Membrane's upstreams can accidentally violate:
6
+ *
7
+ * - `tool_use` blocks must live in assistant-role messages.
8
+ * - `tool_result` blocks must live in user-role messages.
9
+ * - Every `tool_use` must be matched by its `tool_result` in the very
10
+ * next user-role message.
11
+ * - `thinking` blocks must live in assistant turns.
12
+ *
13
+ * When these are violated, the API returns 400 (e.g. `tool_use blocks can
14
+ * only be in assistant messages`). This module is the wire-boundary safety
15
+ * net: every formatter funnels through `normalizeToolPairs` before its
16
+ * output is shipped, so producer-side bugs cannot leak the same 400 family
17
+ * (compression-bug 5/6/7/8/9, agent-framework #37, 2026-05-22 miner stall).
18
+ *
19
+ * Algorithm overview (six phases): reclassify blocks by required role,
20
+ * reflow into role-correct envelopes, hoist matching tool_results across
21
+ * the assistant→user boundary, evict interlopers wedged between use and
22
+ * result, synthesize `[pending]` results for trailing orphans (or signal
23
+ * not-ready when the id is in the caller-supplied pending set), validate.
24
+ */
25
+ import type { ProviderMessage as LooseProviderMessage } from './types.js';
26
+ import type { NormalizeEvent } from './types.js';
27
+ /**
28
+ * Block shape used internally and exposed for callers that want to
29
+ * build inputs without the full Anthropic SDK types. The required
30
+ * `type` discriminator names the kind of block; any block whose `type`
31
+ * matches a strict-role entry in `requiredRoleOf` is re-roled to its
32
+ * required role during normalization. Unrecognized `tool_*` or
33
+ * `thinking*` types fall through as `inherit` — see the one-shot
34
+ * warning below.
35
+ */
36
+ export type ProviderBlock = Record<string, unknown> & {
37
+ type: string;
38
+ };
39
+ export interface NormalizeOptions {
40
+ /** See `BuildOptions.pendingToolCallIds`. */
41
+ pendingToolCallIds?: ReadonlySet<string>;
42
+ /** See `BuildOptions.onNormalize`. */
43
+ onEvent?: (event: NormalizeEvent) => void;
44
+ }
45
+ export interface NormalizeResult {
46
+ /**
47
+ * Normalized messages, structurally compatible with the loose
48
+ * `ProviderMessage` from `./types.js`. Block contents are
49
+ * `ProviderBlock[]` at runtime; the loose type is preserved at the
50
+ * public boundary so callers wired against `./types.js` don't need
51
+ * to cast.
52
+ */
53
+ messages: LooseProviderMessage[];
54
+ /**
55
+ * `false` iff a trailing unmatched tool_use's id was in
56
+ * `pendingToolCallIds`. Caller should wait for the in-flight result
57
+ * to land and retry instead of shipping the request.
58
+ */
59
+ ready: boolean;
60
+ }
61
+ export declare class MembraneNormalizerError extends Error {
62
+ readonly input: ReadonlyArray<LooseProviderMessage>;
63
+ readonly output: ReadonlyArray<LooseProviderMessage>;
64
+ constructor(message: string, input: ReadonlyArray<LooseProviderMessage>, output: ReadonlyArray<LooseProviderMessage>);
65
+ }
66
+ /**
67
+ * Normalize a sequence of provider messages so the output is API-valid
68
+ * with respect to Anthropic's tool-cycle structural rules.
69
+ *
70
+ * This function does NOT merge consecutive same-role envelopes — that
71
+ * remains the caller's responsibility (NativeFormatter.mergeConsecutiveRoles)
72
+ * so existing cache-control / breakpoint logic continues to work.
73
+ */
74
+ export declare function normalizeToolPairs(input: ReadonlyArray<LooseProviderMessage>, options?: NormalizeOptions): NormalizeResult;
75
+ //# sourceMappingURL=normalize-tool-pairs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"normalize-tool-pairs.d.ts","sourceRoot":"","sources":["../../src/formatters/normalize-tool-pairs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,eAAe,IAAI,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAC1E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAMjD;;;;;;;;GAQG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvE,MAAM,WAAW,gBAAgB;IAC/B,6CAA6C;IAC7C,kBAAkB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,sCAAsC;IACtC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B;;;;;;OAMG;IACH,QAAQ,EAAE,oBAAoB,EAAE,CAAC;IACjC;;;;OAIG;IACH,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,qBAAa,uBAAwB,SAAQ,KAAK;aAG9B,KAAK,EAAE,aAAa,CAAC,oBAAoB,CAAC;aAC1C,MAAM,EAAE,aAAa,CAAC,oBAAoB,CAAC;gBAF3D,OAAO,EAAE,MAAM,EACC,KAAK,EAAE,aAAa,CAAC,oBAAoB,CAAC,EAC1C,MAAM,EAAE,aAAa,CAAC,oBAAoB,CAAC;CAK9D;AAMD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,aAAa,CAAC,oBAAoB,CAAC,EAC1C,OAAO,GAAE,gBAAqB,GAC7B,eAAe,CA+DjB"}