@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.
- package/dist/context/index.d.ts +12 -0
- package/dist/context/index.js +11 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/process.d.ts +43 -0
- package/dist/context/process.js +381 -0
- package/dist/context/process.js.map +1 -0
- package/dist/context/types.d.ts +164 -0
- package/dist/context/types.js +61 -0
- package/dist/context/types.js.map +1 -0
- package/dist/formatters/anthropic-xml.d.ts +63 -0
- package/dist/formatters/anthropic-xml.js +417 -0
- package/dist/formatters/anthropic-xml.js.map +1 -0
- package/dist/formatters/completions.d.ts +68 -0
- package/dist/formatters/completions.js +261 -0
- package/dist/formatters/completions.js.map +1 -0
- package/dist/formatters/index.d.ts +10 -0
- package/dist/formatters/index.d.ts.map +1 -1
- package/dist/formatters/index.js +8 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/formatters/native.d.ts +35 -0
- package/dist/formatters/native.d.ts.map +1 -1
- package/dist/formatters/native.js +346 -0
- package/dist/formatters/native.js.map +1 -0
- package/dist/formatters/normalize-tool-pairs.d.ts +75 -0
- package/dist/formatters/normalize-tool-pairs.d.ts.map +1 -0
- package/dist/formatters/normalize-tool-pairs.js +498 -0
- package/dist/formatters/normalize-tool-pairs.js.map +1 -0
- package/dist/formatters/types.d.ts +222 -0
- package/dist/formatters/types.d.ts.map +1 -1
- package/dist/formatters/types.js +7 -0
- package/dist/formatters/types.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/membrane.d.ts +155 -0
- package/dist/providers/anthropic.d.ts +36 -0
- package/dist/providers/bedrock.d.ts +43 -0
- package/dist/providers/gemini.d.ts +68 -0
- package/dist/providers/gemini.js +538 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +13 -0
- package/dist/providers/index.js +13 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/mock.d.ts +90 -0
- package/dist/providers/mock.d.ts.map +1 -0
- package/dist/providers/mock.js +210 -0
- package/dist/providers/mock.js.map +1 -0
- package/dist/providers/openai-compatible.d.ts +82 -0
- package/dist/providers/openai-compatible.js +480 -0
- package/dist/providers/openai-compatible.js.map +1 -0
- package/dist/providers/openai-completions.d.ts +89 -0
- package/dist/providers/openai-completions.js +347 -0
- package/dist/providers/openai-completions.js.map +1 -0
- package/dist/providers/openai-responses.d.ts +77 -0
- package/dist/providers/openai-responses.js +333 -0
- package/dist/providers/openai-responses.js.map +1 -0
- package/dist/providers/openai.d.ts +77 -0
- package/dist/providers/openai.js +533 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openrouter.d.ts +82 -0
- package/dist/providers/openrouter.js +556 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/providers/utils.d.ts +44 -0
- package/dist/providers/utils.d.ts.map +1 -0
- package/dist/providers/utils.js +100 -0
- package/dist/providers/utils.js.map +1 -0
- package/dist/registry/default-pricing.d.ts +3 -0
- package/dist/registry/default-pricing.d.ts.map +1 -0
- package/dist/registry/default-pricing.js +75 -0
- package/dist/registry/default-pricing.js.map +1 -0
- package/dist/transforms/chat.d.ts +52 -0
- package/dist/transforms/chat.js +136 -0
- package/dist/transforms/chat.js.map +1 -0
- package/dist/transforms/index.d.ts +5 -0
- package/dist/transforms/index.js +7 -0
- package/dist/transforms/index.js.map +1 -0
- package/dist/types/config.d.ts +110 -0
- package/dist/types/config.js +21 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/content.d.ts +87 -0
- package/dist/types/content.d.ts.map +1 -0
- package/dist/types/content.js +40 -0
- package/dist/types/content.js.map +1 -0
- package/dist/types/errors.d.ts +50 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +253 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/index.d.ts +20 -0
- package/dist/types/index.js +10 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/message.d.ts +52 -0
- package/dist/types/message.d.ts.map +1 -0
- package/dist/types/message.js +38 -0
- package/dist/types/message.js.map +1 -0
- package/dist/types/provider.d.ts +169 -0
- package/dist/types/provider.d.ts.map +1 -0
- package/dist/types/provider.js +5 -0
- package/dist/types/provider.js.map +1 -0
- package/dist/types/request.d.ts +116 -0
- package/dist/types/request.d.ts.map +1 -0
- package/dist/types/request.js +5 -0
- package/dist/types/request.js.map +1 -0
- package/dist/types/response.d.ts +131 -0
- package/dist/types/response.d.ts.map +1 -0
- package/dist/types/response.js +7 -0
- package/dist/types/response.js.map +1 -0
- package/dist/types/streaming.d.ts +194 -0
- package/dist/types/streaming.js +5 -0
- package/dist/types/streaming.js.map +1 -0
- package/dist/types/tools.d.ts +71 -0
- package/dist/types/tools.d.ts.map +1 -0
- package/dist/types/tools.js +5 -0
- package/dist/types/tools.js.map +1 -0
- package/dist/utils/cost.d.ts +10 -0
- package/dist/utils/cost.d.ts.map +1 -0
- package/dist/utils/cost.js +19 -0
- package/dist/utils/cost.js.map +1 -0
- package/dist/utils/index.d.ts +7 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/stream-parser.d.ts +84 -0
- package/dist/utils/stream-parser.js +418 -0
- package/dist/utils/stream-parser.js.map +1 -0
- package/dist/utils/tool-parser.d.ts +134 -0
- package/dist/utils/tool-parser.js +600 -0
- package/dist/utils/tool-parser.js.map +1 -0
- package/dist/yielding-stream.d.ts +60 -0
- package/dist/yielding-stream.js +206 -0
- package/dist/yielding-stream.js.map +1 -0
- package/package.json +1 -1
- package/src/formatters/index.ts +9 -0
- package/src/formatters/native.ts +12 -1
- package/src/formatters/normalize-tool-pairs.ts +622 -0
- package/src/formatters/types.ts +39 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YieldingStream implementation
|
|
3
|
+
*
|
|
4
|
+
* Provides an async iterator interface for streaming inference that yields
|
|
5
|
+
* control back to the caller for tool execution.
|
|
6
|
+
*/
|
|
7
|
+
import type { StreamEvent, YieldingStream, YieldingStreamOptions, ToolCallsEvent } from './types/yielding-stream.js';
|
|
8
|
+
import type { ToolResult } from './types/tools.js';
|
|
9
|
+
/**
|
|
10
|
+
* Implementation of the YieldingStream interface.
|
|
11
|
+
*
|
|
12
|
+
* This class manages:
|
|
13
|
+
* - An event queue for yielding events to the consumer
|
|
14
|
+
* - A promise-based handshake for tool results
|
|
15
|
+
* - Cancellation via AbortController
|
|
16
|
+
* - State tracking for debugging and validation
|
|
17
|
+
*/
|
|
18
|
+
export declare class YieldingStreamImpl implements YieldingStream {
|
|
19
|
+
private readonly options;
|
|
20
|
+
private readonly runInference;
|
|
21
|
+
private state;
|
|
22
|
+
private eventQueue;
|
|
23
|
+
private pendingToolResults;
|
|
24
|
+
private abortController;
|
|
25
|
+
private _toolDepth;
|
|
26
|
+
private eventWaiter;
|
|
27
|
+
private producerDone;
|
|
28
|
+
constructor(options: YieldingStreamOptions, runInference: (stream: YieldingStreamImpl) => Promise<void>);
|
|
29
|
+
get isWaitingForTools(): boolean;
|
|
30
|
+
get pendingToolCallIds(): string[];
|
|
31
|
+
get toolDepth(): number;
|
|
32
|
+
/**
|
|
33
|
+
* Get the abort signal for use in internal operations.
|
|
34
|
+
*/
|
|
35
|
+
get signal(): AbortSignal;
|
|
36
|
+
provideToolResults(results: ToolResult[]): void;
|
|
37
|
+
cancel(): void;
|
|
38
|
+
[Symbol.asyncIterator](): AsyncIterator<StreamEvent>;
|
|
39
|
+
/**
|
|
40
|
+
* Push an event to be yielded to the consumer.
|
|
41
|
+
*/
|
|
42
|
+
emit(event: StreamEvent): void;
|
|
43
|
+
/**
|
|
44
|
+
* Request tool execution and wait for results.
|
|
45
|
+
* Called by the inference loop when tool calls are detected.
|
|
46
|
+
*/
|
|
47
|
+
requestToolExecution(event: ToolCallsEvent): Promise<ToolResult[]>;
|
|
48
|
+
/**
|
|
49
|
+
* Mark the producer as done (inference loop finished).
|
|
50
|
+
*/
|
|
51
|
+
markDone(): void;
|
|
52
|
+
/**
|
|
53
|
+
* Check if the stream has been cancelled.
|
|
54
|
+
*/
|
|
55
|
+
get isCancelled(): boolean;
|
|
56
|
+
private startInference;
|
|
57
|
+
private waitForEvent;
|
|
58
|
+
private notifyEventWaiter;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=yielding-stream.d.ts.map
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* YieldingStream implementation
|
|
3
|
+
*
|
|
4
|
+
* Provides an async iterator interface for streaming inference that yields
|
|
5
|
+
* control back to the caller for tool execution.
|
|
6
|
+
*/
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// YieldingStreamImpl
|
|
9
|
+
// ============================================================================
|
|
10
|
+
/**
|
|
11
|
+
* Implementation of the YieldingStream interface.
|
|
12
|
+
*
|
|
13
|
+
* This class manages:
|
|
14
|
+
* - An event queue for yielding events to the consumer
|
|
15
|
+
* - A promise-based handshake for tool results
|
|
16
|
+
* - Cancellation via AbortController
|
|
17
|
+
* - State tracking for debugging and validation
|
|
18
|
+
*/
|
|
19
|
+
export class YieldingStreamImpl {
|
|
20
|
+
options;
|
|
21
|
+
runInference;
|
|
22
|
+
state = { status: 'idle' };
|
|
23
|
+
eventQueue = [];
|
|
24
|
+
pendingToolResults = null;
|
|
25
|
+
abortController;
|
|
26
|
+
_toolDepth = 0;
|
|
27
|
+
// Promise/resolver for the async iterator to wait on new events
|
|
28
|
+
eventWaiter = null;
|
|
29
|
+
// Flag indicating the stream producer is done
|
|
30
|
+
producerDone = false;
|
|
31
|
+
constructor(options, runInference) {
|
|
32
|
+
this.options = options;
|
|
33
|
+
this.runInference = runInference;
|
|
34
|
+
this.abortController = new AbortController();
|
|
35
|
+
// Link external signal if provided
|
|
36
|
+
if (options.signal) {
|
|
37
|
+
options.signal.addEventListener('abort', () => {
|
|
38
|
+
this.cancel();
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// ============================================================================
|
|
43
|
+
// Public Interface
|
|
44
|
+
// ============================================================================
|
|
45
|
+
get isWaitingForTools() {
|
|
46
|
+
return this.state.status === 'waiting_for_tools';
|
|
47
|
+
}
|
|
48
|
+
get pendingToolCallIds() {
|
|
49
|
+
if (this.state.status === 'waiting_for_tools') {
|
|
50
|
+
return this.state.pendingCallIds;
|
|
51
|
+
}
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
get toolDepth() {
|
|
55
|
+
return this._toolDepth;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Get the abort signal for use in internal operations.
|
|
59
|
+
*/
|
|
60
|
+
get signal() {
|
|
61
|
+
return this.abortController.signal;
|
|
62
|
+
}
|
|
63
|
+
provideToolResults(results) {
|
|
64
|
+
if (this.state.status !== 'waiting_for_tools') {
|
|
65
|
+
throw new Error(`Cannot provide tool results: stream is not waiting for tools (status: ${this.state.status})`);
|
|
66
|
+
}
|
|
67
|
+
if (!this.pendingToolResults) {
|
|
68
|
+
throw new Error('Internal error: no pending tool results promise');
|
|
69
|
+
}
|
|
70
|
+
// Validate that results match pending call IDs
|
|
71
|
+
const pendingIds = new Set(this.state.pendingCallIds);
|
|
72
|
+
const providedIds = new Set(results.map((r) => r.toolUseId));
|
|
73
|
+
for (const id of pendingIds) {
|
|
74
|
+
if (!providedIds.has(id)) {
|
|
75
|
+
throw new Error(`Missing tool result for call ID: ${id}`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Resolve the promise and transition state
|
|
79
|
+
this.pendingToolResults.resolve(results);
|
|
80
|
+
this.pendingToolResults = null;
|
|
81
|
+
this.state = { status: 'streaming' };
|
|
82
|
+
this._toolDepth++;
|
|
83
|
+
}
|
|
84
|
+
cancel() {
|
|
85
|
+
if (this.state.status === 'done' || this.state.status === 'error') {
|
|
86
|
+
return; // Already terminated
|
|
87
|
+
}
|
|
88
|
+
this.abortController.abort();
|
|
89
|
+
// If waiting for tools, reject the pending promise
|
|
90
|
+
if (this.pendingToolResults) {
|
|
91
|
+
this.pendingToolResults.reject(new Error('Stream cancelled'));
|
|
92
|
+
this.pendingToolResults = null;
|
|
93
|
+
}
|
|
94
|
+
// Emit aborted event and wake the iterator so it can deliver it
|
|
95
|
+
this.emit({ type: 'aborted', reason: 'user' });
|
|
96
|
+
this.producerDone = true;
|
|
97
|
+
this.state = { status: 'done' };
|
|
98
|
+
}
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// Async Iterator Implementation
|
|
101
|
+
// ============================================================================
|
|
102
|
+
[Symbol.asyncIterator]() {
|
|
103
|
+
// Start the inference loop when iteration begins
|
|
104
|
+
this.startInference();
|
|
105
|
+
return {
|
|
106
|
+
next: async () => {
|
|
107
|
+
while (true) {
|
|
108
|
+
// Check for queued events
|
|
109
|
+
const event = this.eventQueue.shift();
|
|
110
|
+
if (event) {
|
|
111
|
+
// Check if this is a terminal event
|
|
112
|
+
if (event.type === 'complete' ||
|
|
113
|
+
event.type === 'error' ||
|
|
114
|
+
event.type === 'aborted') {
|
|
115
|
+
this.state = { status: 'done' };
|
|
116
|
+
}
|
|
117
|
+
return { value: event, done: false };
|
|
118
|
+
}
|
|
119
|
+
// If producer is done and queue is empty, we're done
|
|
120
|
+
if (this.producerDone) {
|
|
121
|
+
return { value: undefined, done: true };
|
|
122
|
+
}
|
|
123
|
+
// Wait for more events
|
|
124
|
+
await this.waitForEvent();
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
// ============================================================================
|
|
130
|
+
// Internal Methods (called by the inference loop)
|
|
131
|
+
// ============================================================================
|
|
132
|
+
/**
|
|
133
|
+
* Push an event to be yielded to the consumer.
|
|
134
|
+
*/
|
|
135
|
+
emit(event) {
|
|
136
|
+
this.eventQueue.push(event);
|
|
137
|
+
this.notifyEventWaiter();
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Request tool execution and wait for results.
|
|
141
|
+
* Called by the inference loop when tool calls are detected.
|
|
142
|
+
*/
|
|
143
|
+
async requestToolExecution(event) {
|
|
144
|
+
// Emit the tool calls event
|
|
145
|
+
this.emit(event);
|
|
146
|
+
// Transition to waiting state
|
|
147
|
+
this.state = {
|
|
148
|
+
status: 'waiting_for_tools',
|
|
149
|
+
pendingCallIds: event.calls.map((c) => c.id),
|
|
150
|
+
};
|
|
151
|
+
// Create a promise that will be resolved by provideToolResults()
|
|
152
|
+
return new Promise((resolve, reject) => {
|
|
153
|
+
this.pendingToolResults = { resolve, reject };
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Mark the producer as done (inference loop finished).
|
|
158
|
+
*/
|
|
159
|
+
markDone() {
|
|
160
|
+
this.producerDone = true;
|
|
161
|
+
this.notifyEventWaiter();
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Check if the stream has been cancelled.
|
|
165
|
+
*/
|
|
166
|
+
get isCancelled() {
|
|
167
|
+
return this.abortController.signal.aborted;
|
|
168
|
+
}
|
|
169
|
+
// ============================================================================
|
|
170
|
+
// Private Helpers
|
|
171
|
+
// ============================================================================
|
|
172
|
+
startInference() {
|
|
173
|
+
if (this.state.status !== 'idle') {
|
|
174
|
+
return; // Already started
|
|
175
|
+
}
|
|
176
|
+
this.state = { status: 'streaming' };
|
|
177
|
+
// Run the inference loop in the background
|
|
178
|
+
this.runInference(this)
|
|
179
|
+
.then(() => {
|
|
180
|
+
this.markDone();
|
|
181
|
+
})
|
|
182
|
+
.catch((error) => {
|
|
183
|
+
if (!this.isCancelled) {
|
|
184
|
+
this.emit({ type: 'error', error });
|
|
185
|
+
}
|
|
186
|
+
this.markDone();
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
waitForEvent() {
|
|
190
|
+
if (!this.eventWaiter) {
|
|
191
|
+
let resolve;
|
|
192
|
+
const promise = new Promise((r) => {
|
|
193
|
+
resolve = r;
|
|
194
|
+
});
|
|
195
|
+
this.eventWaiter = { resolve: resolve, promise };
|
|
196
|
+
}
|
|
197
|
+
return this.eventWaiter.promise;
|
|
198
|
+
}
|
|
199
|
+
notifyEventWaiter() {
|
|
200
|
+
if (this.eventWaiter) {
|
|
201
|
+
this.eventWaiter.resolve();
|
|
202
|
+
this.eventWaiter = null;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
//# sourceMappingURL=yielding-stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yielding-stream.js","sourceRoot":"","sources":["../src/yielding-stream.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/formatters/index.ts
CHANGED
|
@@ -17,3 +17,12 @@ export type {
|
|
|
17
17
|
export { AnthropicXmlFormatter, type AnthropicXmlFormatterConfig } from './anthropic-xml.js';
|
|
18
18
|
export { NativeFormatter, type NativeFormatterConfig } from './native.js';
|
|
19
19
|
export { CompletionsFormatter, type CompletionsFormatterConfig } from './completions.js';
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
normalizeToolPairs,
|
|
23
|
+
MembraneNormalizerError,
|
|
24
|
+
type NormalizeOptions,
|
|
25
|
+
type NormalizeResult,
|
|
26
|
+
type ProviderBlock,
|
|
27
|
+
} from './normalize-tool-pairs.js';
|
|
28
|
+
export type { NormalizeEvent } from './types.js';
|
package/src/formatters/native.ts
CHANGED
|
@@ -28,6 +28,7 @@ import type {
|
|
|
28
28
|
BlockEvent,
|
|
29
29
|
StreamEmission,
|
|
30
30
|
} from './types.js';
|
|
31
|
+
import { normalizeToolPairs } from './normalize-tool-pairs.js';
|
|
31
32
|
|
|
32
33
|
// ============================================================================
|
|
33
34
|
// Configuration
|
|
@@ -245,8 +246,17 @@ export class NativeFormatter implements PrefillFormatter {
|
|
|
245
246
|
}
|
|
246
247
|
}
|
|
247
248
|
|
|
249
|
+
// Tool-pair normalizer: wire-boundary safety net for Anthropic's
|
|
250
|
+
// structural rules on tool cycles. See `normalize-tool-pairs.ts`
|
|
251
|
+
// for the full rationale. Runs BEFORE mergeConsecutiveRoles so the
|
|
252
|
+
// merge sees role-correct envelopes.
|
|
253
|
+
const normalized = normalizeToolPairs(providerMessages, {
|
|
254
|
+
pendingToolCallIds: options.pendingToolCallIds,
|
|
255
|
+
onEvent: options.onNormalize,
|
|
256
|
+
});
|
|
257
|
+
|
|
248
258
|
// Merge consecutive same-role messages (API requires alternating)
|
|
249
|
-
const mergedMessages = this.mergeConsecutiveRoles(
|
|
259
|
+
const mergedMessages = this.mergeConsecutiveRoles(normalized.messages);
|
|
250
260
|
|
|
251
261
|
// Build system content with optional cache control
|
|
252
262
|
let systemContent: unknown;
|
|
@@ -279,6 +289,7 @@ export class NativeFormatter implements PrefillFormatter {
|
|
|
279
289
|
systemContent,
|
|
280
290
|
stopSequences: additionalStopSequences ?? [],
|
|
281
291
|
nativeTools,
|
|
292
|
+
ready: normalized.ready,
|
|
282
293
|
};
|
|
283
294
|
}
|
|
284
295
|
|