@animalabs/membrane 0.1.0

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 (131) hide show
  1. package/dist/context/index.d.ts +10 -0
  2. package/dist/context/index.d.ts.map +1 -0
  3. package/dist/context/index.js +9 -0
  4. package/dist/context/index.js.map +1 -0
  5. package/dist/context/process.d.ts +22 -0
  6. package/dist/context/process.d.ts.map +1 -0
  7. package/dist/context/process.js +369 -0
  8. package/dist/context/process.js.map +1 -0
  9. package/dist/context/types.d.ts +118 -0
  10. package/dist/context/types.d.ts.map +1 -0
  11. package/dist/context/types.js +60 -0
  12. package/dist/context/types.js.map +1 -0
  13. package/dist/index.d.ts +12 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +18 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/membrane.d.ts +96 -0
  18. package/dist/membrane.d.ts.map +1 -0
  19. package/dist/membrane.js +893 -0
  20. package/dist/membrane.js.map +1 -0
  21. package/dist/providers/anthropic.d.ts +36 -0
  22. package/dist/providers/anthropic.d.ts.map +1 -0
  23. package/dist/providers/anthropic.js +265 -0
  24. package/dist/providers/anthropic.js.map +1 -0
  25. package/dist/providers/index.d.ts +8 -0
  26. package/dist/providers/index.d.ts.map +1 -0
  27. package/dist/providers/index.js +8 -0
  28. package/dist/providers/index.js.map +1 -0
  29. package/dist/providers/openai-compatible.d.ts +74 -0
  30. package/dist/providers/openai-compatible.d.ts.map +1 -0
  31. package/dist/providers/openai-compatible.js +412 -0
  32. package/dist/providers/openai-compatible.js.map +1 -0
  33. package/dist/providers/openai.d.ts +69 -0
  34. package/dist/providers/openai.d.ts.map +1 -0
  35. package/dist/providers/openai.js +455 -0
  36. package/dist/providers/openai.js.map +1 -0
  37. package/dist/providers/openrouter.d.ts +76 -0
  38. package/dist/providers/openrouter.d.ts.map +1 -0
  39. package/dist/providers/openrouter.js +492 -0
  40. package/dist/providers/openrouter.js.map +1 -0
  41. package/dist/transforms/chat.d.ts +52 -0
  42. package/dist/transforms/chat.d.ts.map +1 -0
  43. package/dist/transforms/chat.js +136 -0
  44. package/dist/transforms/chat.js.map +1 -0
  45. package/dist/transforms/index.d.ts +6 -0
  46. package/dist/transforms/index.d.ts.map +1 -0
  47. package/dist/transforms/index.js +6 -0
  48. package/dist/transforms/index.js.map +1 -0
  49. package/dist/transforms/prefill.d.ts +89 -0
  50. package/dist/transforms/prefill.d.ts.map +1 -0
  51. package/dist/transforms/prefill.js +401 -0
  52. package/dist/transforms/prefill.js.map +1 -0
  53. package/dist/types/config.d.ts +103 -0
  54. package/dist/types/config.d.ts.map +1 -0
  55. package/dist/types/config.js +21 -0
  56. package/dist/types/config.js.map +1 -0
  57. package/dist/types/content.d.ts +81 -0
  58. package/dist/types/content.d.ts.map +1 -0
  59. package/dist/types/content.js +40 -0
  60. package/dist/types/content.js.map +1 -0
  61. package/dist/types/errors.d.ts +42 -0
  62. package/dist/types/errors.d.ts.map +1 -0
  63. package/dist/types/errors.js +208 -0
  64. package/dist/types/errors.js.map +1 -0
  65. package/dist/types/index.d.ts +18 -0
  66. package/dist/types/index.d.ts.map +1 -0
  67. package/dist/types/index.js +9 -0
  68. package/dist/types/index.js.map +1 -0
  69. package/dist/types/message.d.ts +46 -0
  70. package/dist/types/message.d.ts.map +1 -0
  71. package/dist/types/message.js +38 -0
  72. package/dist/types/message.js.map +1 -0
  73. package/dist/types/provider.d.ts +155 -0
  74. package/dist/types/provider.d.ts.map +1 -0
  75. package/dist/types/provider.js +5 -0
  76. package/dist/types/provider.js.map +1 -0
  77. package/dist/types/request.d.ts +78 -0
  78. package/dist/types/request.d.ts.map +1 -0
  79. package/dist/types/request.js +5 -0
  80. package/dist/types/request.js.map +1 -0
  81. package/dist/types/response.d.ts +131 -0
  82. package/dist/types/response.d.ts.map +1 -0
  83. package/dist/types/response.js +7 -0
  84. package/dist/types/response.js.map +1 -0
  85. package/dist/types/streaming.d.ts +164 -0
  86. package/dist/types/streaming.d.ts.map +1 -0
  87. package/dist/types/streaming.js +5 -0
  88. package/dist/types/streaming.js.map +1 -0
  89. package/dist/types/tools.d.ts +71 -0
  90. package/dist/types/tools.d.ts.map +1 -0
  91. package/dist/types/tools.js +5 -0
  92. package/dist/types/tools.js.map +1 -0
  93. package/dist/utils/index.d.ts +5 -0
  94. package/dist/utils/index.d.ts.map +1 -0
  95. package/dist/utils/index.js +5 -0
  96. package/dist/utils/index.js.map +1 -0
  97. package/dist/utils/stream-parser.d.ts +53 -0
  98. package/dist/utils/stream-parser.d.ts.map +1 -0
  99. package/dist/utils/stream-parser.js +359 -0
  100. package/dist/utils/stream-parser.js.map +1 -0
  101. package/dist/utils/tool-parser.d.ts +130 -0
  102. package/dist/utils/tool-parser.d.ts.map +1 -0
  103. package/dist/utils/tool-parser.js +571 -0
  104. package/dist/utils/tool-parser.js.map +1 -0
  105. package/package.json +37 -0
  106. package/src/context/index.ts +24 -0
  107. package/src/context/process.ts +520 -0
  108. package/src/context/types.ts +231 -0
  109. package/src/index.ts +23 -0
  110. package/src/membrane.ts +1174 -0
  111. package/src/providers/anthropic.ts +340 -0
  112. package/src/providers/index.ts +31 -0
  113. package/src/providers/openai-compatible.ts +570 -0
  114. package/src/providers/openai.ts +625 -0
  115. package/src/providers/openrouter.ts +662 -0
  116. package/src/transforms/chat.ts +212 -0
  117. package/src/transforms/index.ts +22 -0
  118. package/src/transforms/prefill.ts +585 -0
  119. package/src/types/config.ts +172 -0
  120. package/src/types/content.ts +181 -0
  121. package/src/types/errors.ts +277 -0
  122. package/src/types/index.ts +154 -0
  123. package/src/types/message.ts +89 -0
  124. package/src/types/provider.ts +249 -0
  125. package/src/types/request.ts +131 -0
  126. package/src/types/response.ts +223 -0
  127. package/src/types/streaming.ts +231 -0
  128. package/src/types/tools.ts +92 -0
  129. package/src/utils/index.ts +15 -0
  130. package/src/utils/stream-parser.ts +440 -0
  131. package/src/utils/tool-parser.ts +715 -0
@@ -0,0 +1,223 @@
1
+ /**
2
+ * Response types for membrane
3
+ */
4
+
5
+ import type { ContentBlock } from './content.js';
6
+ import type { ToolCall, ToolResult } from './tools.js';
7
+
8
+ // ============================================================================
9
+ // Stop Reason
10
+ // ============================================================================
11
+
12
+ export type StopReason =
13
+ | 'end_turn' // Natural completion
14
+ | 'max_tokens' // Hit token limit
15
+ | 'stop_sequence' // Hit stop sequence
16
+ | 'tool_use' // Stopped for tool use
17
+ | 'refusal' // Content refused by safety
18
+ | 'abort'; // Request was aborted
19
+
20
+ // ============================================================================
21
+ // Usage Information
22
+ // ============================================================================
23
+
24
+ export interface BasicUsage {
25
+ inputTokens: number;
26
+ outputTokens: number;
27
+ }
28
+
29
+ export interface DetailedUsage extends BasicUsage {
30
+ /** Tokens used for cache creation */
31
+ cacheCreationTokens?: number;
32
+
33
+ /** Tokens read from cache */
34
+ cacheReadTokens?: number;
35
+
36
+ /** Tokens used for thinking/reasoning */
37
+ thinkingTokens?: number;
38
+
39
+ /** Estimated cost breakdown */
40
+ estimatedCost?: CostBreakdown;
41
+ }
42
+
43
+ export interface CostBreakdown {
44
+ input: number;
45
+ output: number;
46
+ cacheWrite?: number;
47
+ cacheRead?: number;
48
+ total: number;
49
+ currency: string;
50
+ }
51
+
52
+ // ============================================================================
53
+ // Stop Information
54
+ // ============================================================================
55
+
56
+ export interface StopInfo {
57
+ reason: StopReason;
58
+
59
+ /** Which stop sequence triggered (if stop_sequence) */
60
+ triggeredSequence?: string;
61
+
62
+ /** Whether output was truncated */
63
+ wasTruncated: boolean;
64
+ }
65
+
66
+ // ============================================================================
67
+ // Model Information
68
+ // ============================================================================
69
+
70
+ export interface ModelInfo {
71
+ /** Model ID that was requested */
72
+ requested: string;
73
+
74
+ /** Model ID that actually ran (may differ due to routing/fallback) */
75
+ actual: string;
76
+
77
+ /** Provider that served the request */
78
+ provider: string;
79
+ }
80
+
81
+ // ============================================================================
82
+ // Timing Information
83
+ // ============================================================================
84
+
85
+ export interface TimingInfo {
86
+ /** Total request duration */
87
+ totalDurationMs: number;
88
+
89
+ /** Time to first token (streaming only) */
90
+ timeToFirstTokenMs?: number;
91
+
92
+ /** Tokens per second (streaming only) */
93
+ tokensPerSecond?: number;
94
+
95
+ /** Number of retry attempts */
96
+ attempts: number;
97
+
98
+ /** Delay between retries */
99
+ retryDelaysMs?: number[];
100
+ }
101
+
102
+ // ============================================================================
103
+ // Cache Information
104
+ // ============================================================================
105
+
106
+ export interface CacheInfo {
107
+ /** Number of cache markers in request */
108
+ markersInRequest: number;
109
+
110
+ /** Tokens created in cache */
111
+ tokensCreated: number;
112
+
113
+ /** Tokens read from cache */
114
+ tokensRead: number;
115
+
116
+ /** Cache hit ratio (0-1) */
117
+ hitRatio: number;
118
+ }
119
+
120
+ // ============================================================================
121
+ // Response Details
122
+ // ============================================================================
123
+
124
+ export interface ResponseDetails {
125
+ stop: StopInfo;
126
+ usage: DetailedUsage;
127
+ timing: TimingInfo;
128
+ model: ModelInfo;
129
+ cache: CacheInfo;
130
+ }
131
+
132
+ // ============================================================================
133
+ // Raw Access
134
+ // ============================================================================
135
+
136
+ export interface RawAccess {
137
+ /** Exact request body sent to provider */
138
+ request: unknown;
139
+
140
+ /** Exact response received from provider */
141
+ response: unknown;
142
+
143
+ /** Response headers */
144
+ headers?: Record<string, string>;
145
+ }
146
+
147
+ // ============================================================================
148
+ // Normalized Response
149
+ // ============================================================================
150
+
151
+ export interface NormalizedResponse {
152
+ /** Response content blocks (parsed/structured) */
153
+ content: ContentBlock[];
154
+
155
+ /**
156
+ * Raw assistant output text including all XML.
157
+ * Use this for building subsequent turn context (verbatim prefill).
158
+ */
159
+ rawAssistantText: string;
160
+
161
+ /**
162
+ * Tool calls extracted from the response.
163
+ * Convenience accessor - these are also in content as tool_use blocks.
164
+ */
165
+ toolCalls: ToolCall[];
166
+
167
+ /**
168
+ * Tool results that were executed during this response.
169
+ * Empty if no tools were called or tool execution was disabled.
170
+ */
171
+ toolResults: ToolResult[];
172
+
173
+ /** Why generation stopped */
174
+ stopReason: StopReason;
175
+
176
+ /** Basic usage (always available) */
177
+ usage: BasicUsage;
178
+
179
+ /** Detailed response information */
180
+ details: ResponseDetails;
181
+
182
+ /** Raw request/response for debugging */
183
+ raw: RawAccess;
184
+ }
185
+
186
+ // ============================================================================
187
+ // Aborted Response
188
+ // ============================================================================
189
+
190
+ export interface AbortedResponse {
191
+ aborted: true;
192
+
193
+ /** Content received before abort */
194
+ partialContent?: ContentBlock[];
195
+
196
+ /** Tokens consumed before abort */
197
+ partialUsage?: BasicUsage;
198
+
199
+ /** Why it was aborted */
200
+ reason: 'user' | 'timeout' | 'error';
201
+
202
+ /**
203
+ * Raw assistant text accumulated before abort.
204
+ * Use for displaying partial output or as prefill to continue.
205
+ */
206
+ rawAssistantText?: string;
207
+
208
+ /**
209
+ * Tool calls that were executed before abort.
210
+ */
211
+ toolCalls?: ToolCall[];
212
+
213
+ /**
214
+ * Tool results received before abort.
215
+ */
216
+ toolResults?: ToolResult[];
217
+ }
218
+
219
+ export function isAbortedResponse(
220
+ response: NormalizedResponse | AbortedResponse
221
+ ): response is AbortedResponse {
222
+ return 'aborted' in response && response.aborted === true;
223
+ }
@@ -0,0 +1,231 @@
1
+ /**
2
+ * Streaming types for membrane
3
+ */
4
+
5
+ import type { ContentBlock } from './content.js';
6
+ import type { ToolCall, ToolResult, ToolContext } from './tools.js';
7
+ import type { BasicUsage } from './response.js';
8
+
9
+ // ============================================================================
10
+ // Membrane Block Types (logical content regions, not API types)
11
+ // ============================================================================
12
+
13
+ /**
14
+ * Membrane block types - logical content regions at the context level.
15
+ * These are abstract structures, not tied to any wire format.
16
+ */
17
+ export type MembraneBlockType = 'text' | 'thinking' | 'tool_call' | 'tool_result';
18
+
19
+ /**
20
+ * Membrane block - a logical content region with full content.
21
+ * Used in block_complete events.
22
+ */
23
+ export interface MembraneBlock {
24
+ type: MembraneBlockType;
25
+ content?: string; // Full content (for text, thinking, tool_result)
26
+ toolId?: string; // For tool_call / tool_result
27
+ toolName?: string; // For tool_call
28
+ input?: Record<string, unknown>; // For tool_call (parsed parameters)
29
+ isError?: boolean; // For tool_result
30
+ }
31
+
32
+ // ============================================================================
33
+ // Chunk Metadata
34
+ // ============================================================================
35
+
36
+ /**
37
+ * Chunk type - alias for MembraneBlockType for clarity in chunk contexts
38
+ */
39
+ export type ChunkType = MembraneBlockType;
40
+
41
+ /**
42
+ * Metadata about a streaming chunk.
43
+ * Provides context about which block the chunk belongs to and its visibility.
44
+ */
45
+ export interface ChunkMeta {
46
+ /** Which membrane block type this chunk belongs to */
47
+ type: ChunkType;
48
+
49
+ /** Convenience flag for TTS/display filtering - false for thinking/tool content */
50
+ visible: boolean;
51
+
52
+ /** Which content block this belongs to (0-indexed) */
53
+ blockIndex: number;
54
+
55
+ /** Tool nesting depth (for nested tool calls) */
56
+ depth?: number;
57
+
58
+ /** For tool_call chunks - which part of the tool call is streaming */
59
+ toolCallPart?: 'name' | 'id' | 'input';
60
+
61
+ /** Tool use ID (for tool_call / tool_result chunks) */
62
+ toolId?: string;
63
+
64
+ /** Tool name (for tool_call chunks, once known) */
65
+ toolName?: string;
66
+ }
67
+
68
+ // ============================================================================
69
+ // Block Events
70
+ // ============================================================================
71
+
72
+ /**
73
+ * Block start event - signals a new block is starting.
74
+ * Fired before any onChunk calls for that block.
75
+ */
76
+ export interface BlockStartEvent {
77
+ event: 'block_start';
78
+ index: number;
79
+ block: { type: MembraneBlockType };
80
+ }
81
+
82
+ /**
83
+ * Block complete event - signals a block is done.
84
+ * Includes full accumulated content. Fired after all onChunk calls for that block.
85
+ */
86
+ export interface BlockCompleteEvent {
87
+ event: 'block_complete';
88
+ index: number;
89
+ block: MembraneBlock;
90
+ }
91
+
92
+ /**
93
+ * Block event - either start or complete.
94
+ * Note: No block_delta - streaming content is provided via onChunk with metadata.
95
+ */
96
+ export type BlockEvent = BlockStartEvent | BlockCompleteEvent;
97
+
98
+ /**
99
+ * @deprecated Use BlockEvent instead. BlockDelta is no longer used;
100
+ * streaming content is provided via onChunk with ChunkMeta.
101
+ */
102
+ export type BlockDelta =
103
+ | { type: 'text'; text: string }
104
+ | { type: 'thinking'; thinking: string }
105
+ | { type: 'tool_input'; partialJson: string };
106
+
107
+ // ============================================================================
108
+ // Stream State
109
+ // ============================================================================
110
+
111
+ export interface StreamState {
112
+ /** Accumulated text output */
113
+ accumulated: string;
114
+
115
+ /** Current content blocks (updated during stream) */
116
+ contentBlocks: ContentBlock[];
117
+
118
+ /** Current tool execution depth */
119
+ toolDepth: number;
120
+
121
+ /** Tool calls executed so far */
122
+ toolCallsExecuted: ToolCall[];
123
+
124
+ /** Tokens generated so far (estimate) */
125
+ tokensGenerated: number;
126
+
127
+ /** Abort function */
128
+ abort: () => void;
129
+ }
130
+
131
+ // ============================================================================
132
+ // Stream Callbacks
133
+ // ============================================================================
134
+
135
+ /**
136
+ * Callback for text chunks - called immediately as tokens arrive.
137
+ * Includes metadata about block type, visibility, and position.
138
+ */
139
+ export type OnChunkCallback = (chunk: string, meta: ChunkMeta) => void;
140
+
141
+ /**
142
+ * @deprecated Use onBlock + onChunk with ChunkMeta instead.
143
+ * This callback is superseded by:
144
+ * - onBlock for structured block_start/block_complete events
145
+ * - onChunk with ChunkMeta for streaming content with block context
146
+ */
147
+ export type OnContentBlockCallback = (index: number, block: ContentBlock) => void;
148
+
149
+ /**
150
+ * Callback for tool execution
151
+ * Return tool results to continue; throw to abort
152
+ */
153
+ export type OnToolCallsCallback = (
154
+ calls: ToolCall[],
155
+ context: ToolContext
156
+ ) => Promise<ToolResult[]>;
157
+
158
+ /**
159
+ * Callback for pre-tool content notification
160
+ * Called with content that appeared before tool calls
161
+ */
162
+ export type OnPreToolContentCallback = (content: string) => Promise<void> | void;
163
+
164
+ /**
165
+ * Callback for usage updates during streaming
166
+ */
167
+ export type OnUsageCallback = (usage: BasicUsage) => void;
168
+
169
+ /**
170
+ * Callback for structured block events during streaming.
171
+ * Provides parsed block information as it's detected.
172
+ */
173
+ export type OnBlockCallback = (event: BlockEvent) => void;
174
+
175
+ // ============================================================================
176
+ // Stream Options
177
+ // ============================================================================
178
+
179
+ export interface StreamOptions {
180
+ /** Abort signal for cancellation */
181
+ signal?: AbortSignal;
182
+
183
+ /** Request timeout */
184
+ timeoutMs?: number;
185
+
186
+ /** Request ID for correlation */
187
+ requestId?: string;
188
+
189
+ // ---- Callbacks ----
190
+
191
+ /** Called immediately for each text chunk */
192
+ onChunk?: OnChunkCallback;
193
+
194
+ /** Called when content blocks update (thinking, images) */
195
+ onContentBlockUpdate?: OnContentBlockCallback;
196
+
197
+ /** Called when tool calls are detected; return results to continue */
198
+ onToolCalls?: OnToolCallsCallback;
199
+
200
+ /** Called with content before tool calls (for UI preview) */
201
+ onPreToolContent?: OnPreToolContentCallback;
202
+
203
+ /** Called with usage updates */
204
+ onUsage?: OnUsageCallback;
205
+
206
+ /** Called for structured block events (thinking, tool_use, tool_result) */
207
+ onBlock?: OnBlockCallback;
208
+
209
+ // ---- Tool Loop Config ----
210
+
211
+ /** Maximum tool execution depth (default: 10) */
212
+ maxToolDepth?: number;
213
+
214
+ /** Timeout for each tool execution */
215
+ toolTimeoutMs?: number;
216
+ }
217
+
218
+ // ============================================================================
219
+ // Non-Streaming Options
220
+ // ============================================================================
221
+
222
+ export interface CompleteOptions {
223
+ /** Abort signal for cancellation */
224
+ signal?: AbortSignal;
225
+
226
+ /** Request timeout */
227
+ timeoutMs?: number;
228
+
229
+ /** Request ID for correlation */
230
+ requestId?: string;
231
+ }
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Tool definition and execution types
3
+ */
4
+
5
+ // ============================================================================
6
+ // Tool Definition
7
+ // ============================================================================
8
+
9
+ export interface ToolParameter {
10
+ type: string;
11
+ description?: string;
12
+ enum?: string[];
13
+ items?: ToolParameter;
14
+ properties?: Record<string, ToolParameter>;
15
+ required?: string[];
16
+ }
17
+
18
+ export interface ToolDefinition {
19
+ name: string;
20
+ description: string;
21
+ inputSchema: {
22
+ type: 'object';
23
+ properties: Record<string, ToolParameter>;
24
+ required?: string[];
25
+ };
26
+ }
27
+
28
+ // ============================================================================
29
+ // Tool Execution
30
+ // ============================================================================
31
+
32
+ export interface ToolCall {
33
+ id: string;
34
+ name: string;
35
+ input: Record<string, unknown>;
36
+ }
37
+
38
+ export interface ToolResult {
39
+ toolUseId: string;
40
+ /**
41
+ * Result content - can be string or structured content blocks (for images).
42
+ * For XML mode, images are noted in text. For native mode, passed as content blocks.
43
+ */
44
+ content: string | ToolResultContentBlock[];
45
+ isError?: boolean;
46
+ }
47
+
48
+ /**
49
+ * Content block types allowed in tool results
50
+ */
51
+ export type ToolResultContentBlock =
52
+ | { type: 'text'; text: string }
53
+ | { type: 'image'; source: { type: 'base64'; data: string; mediaType: string } };
54
+
55
+ // ============================================================================
56
+ // Tool Context (passed to execution callback)
57
+ // ============================================================================
58
+
59
+ export interface ToolContext {
60
+ /** The raw text that contained the tool calls */
61
+ rawText: string;
62
+
63
+ /** Text before the tool calls (already streamed to user) */
64
+ preamble: string;
65
+
66
+ /** Current depth in tool execution loop */
67
+ depth: number;
68
+
69
+ /** Previous tool results in this execution chain */
70
+ previousResults: ToolResult[];
71
+
72
+ /** Accumulated output so far */
73
+ accumulated: string;
74
+ }
75
+
76
+ // ============================================================================
77
+ // Tool Parsing
78
+ // ============================================================================
79
+
80
+ export interface ParsedToolCalls {
81
+ /** Parsed tool calls */
82
+ calls: ToolCall[];
83
+
84
+ /** Text before the tool calls block */
85
+ beforeText: string;
86
+
87
+ /** Text after the tool calls block */
88
+ afterText: string;
89
+
90
+ /** The full matched tool calls XML block */
91
+ fullMatch: string;
92
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Utility exports
3
+ */
4
+
5
+ export {
6
+ parseToolCalls,
7
+ formatToolResults,
8
+ formatToolResult,
9
+ formatToolDefinitions,
10
+ getToolInstructions,
11
+ hasUnclosedToolBlock,
12
+ endsWithPartialToolBlock,
13
+ unescapeXml,
14
+ type ToolDefinitionForPrompt,
15
+ } from './tool-parser.js';