@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,212 @@
1
+ /**
2
+ * Chat mode transforms
3
+ *
4
+ * Converts normalized messages to role-based alternating format
5
+ * for providers that don't support prefill mode.
6
+ */
7
+
8
+ import type {
9
+ NormalizedMessage,
10
+ NormalizedRequest,
11
+ ContentBlock,
12
+ } from '../types/index.js';
13
+ import { isTextContent, isToolUseContent, isToolResultContent } from '../types/index.js';
14
+
15
+ // ============================================================================
16
+ // Chat Transform Result
17
+ // ============================================================================
18
+
19
+ export interface ChatMessage {
20
+ role: 'user' | 'assistant';
21
+ content: ChatContent[];
22
+ }
23
+
24
+ export type ChatContent =
25
+ | { type: 'text'; text: string }
26
+ | { type: 'image'; source: { type: 'base64'; data: string; mediaType: string } }
27
+ | { type: 'tool_use'; id: string; name: string; input: Record<string, unknown> }
28
+ | { type: 'tool_result'; tool_use_id: string; content: string };
29
+
30
+ export interface ChatTransformResult {
31
+ /** System prompt */
32
+ system: string;
33
+
34
+ /** Messages in role-based format */
35
+ messages: ChatMessage[];
36
+
37
+ /** Stop sequences to use */
38
+ stopSequences: string[];
39
+ }
40
+
41
+ // ============================================================================
42
+ // Transform Options
43
+ // ============================================================================
44
+
45
+ export interface ChatTransformOptions {
46
+ /** Name of the assistant participant (default: 'Claude') */
47
+ assistantName?: string;
48
+
49
+ /** Names to treat as 'user' role */
50
+ userParticipants?: string[];
51
+
52
+ /** How to handle multiple consecutive same-role messages */
53
+ mergeStrategy?: 'concatenate' | 'separate';
54
+ }
55
+
56
+ // ============================================================================
57
+ // Main Transform Function
58
+ // ============================================================================
59
+
60
+ /**
61
+ * Transform normalized request to chat format
62
+ */
63
+ export function transformToChat(
64
+ request: NormalizedRequest,
65
+ options: ChatTransformOptions = {}
66
+ ): ChatTransformResult {
67
+ const {
68
+ assistantName = 'Claude',
69
+ userParticipants = [],
70
+ mergeStrategy = 'concatenate',
71
+ } = options;
72
+
73
+ const userSet = new Set(userParticipants);
74
+ const messages: ChatMessage[] = [];
75
+
76
+ for (const message of request.messages) {
77
+ const role = determineRole(message.participant, assistantName, userSet);
78
+ const content = transformContent(message.content);
79
+
80
+ if (mergeStrategy === 'concatenate' && messages.length > 0) {
81
+ const lastMessage = messages[messages.length - 1];
82
+ if (lastMessage && lastMessage.role === role) {
83
+ // Merge with previous message
84
+ lastMessage.content.push(...content);
85
+ continue;
86
+ }
87
+ }
88
+
89
+ messages.push({ role, content });
90
+ }
91
+
92
+ // Ensure alternating roles (required by most providers)
93
+ const normalizedMessages = ensureAlternatingRoles(messages);
94
+
95
+ // Build stop sequences
96
+ const stopSequences = buildChatStopSequences(request);
97
+
98
+ return {
99
+ system: request.system ?? '',
100
+ messages: normalizedMessages,
101
+ stopSequences,
102
+ };
103
+ }
104
+
105
+ // ============================================================================
106
+ // Helper Functions
107
+ // ============================================================================
108
+
109
+ function determineRole(
110
+ participant: string,
111
+ assistantName: string,
112
+ userSet: Set<string>
113
+ ): 'user' | 'assistant' {
114
+ if (participant === assistantName) {
115
+ return 'assistant';
116
+ }
117
+ if (userSet.has(participant)) {
118
+ return 'user';
119
+ }
120
+ // Default: non-assistant is user
121
+ return 'user';
122
+ }
123
+
124
+ function transformContent(blocks: ContentBlock[]): ChatContent[] {
125
+ const result: ChatContent[] = [];
126
+
127
+ for (const block of blocks) {
128
+ if (isTextContent(block)) {
129
+ result.push({ type: 'text', text: block.text });
130
+ } else if (block.type === 'image' && block.source.type === 'base64') {
131
+ result.push({
132
+ type: 'image',
133
+ source: {
134
+ type: 'base64',
135
+ data: block.source.data,
136
+ mediaType: block.source.mediaType,
137
+ },
138
+ });
139
+ } else if (isToolUseContent(block)) {
140
+ result.push({
141
+ type: 'tool_use',
142
+ id: block.id,
143
+ name: block.name,
144
+ input: block.input as Record<string, unknown>,
145
+ });
146
+ } else if (isToolResultContent(block)) {
147
+ const content = typeof block.content === 'string'
148
+ ? block.content
149
+ : JSON.stringify(block.content);
150
+ result.push({
151
+ type: 'tool_result',
152
+ tool_use_id: block.toolUseId,
153
+ content,
154
+ });
155
+ }
156
+ // Other block types are skipped or could be handled here
157
+ }
158
+
159
+ return result;
160
+ }
161
+
162
+ function ensureAlternatingRoles(messages: ChatMessage[]): ChatMessage[] {
163
+ if (messages.length === 0) return messages;
164
+
165
+ const result: ChatMessage[] = [];
166
+ let lastRole: 'user' | 'assistant' | null = null;
167
+
168
+ for (const message of messages) {
169
+ if (lastRole === message.role) {
170
+ // Insert empty message of opposite role
171
+ const fillerRole = message.role === 'user' ? 'assistant' : 'user';
172
+ result.push({
173
+ role: fillerRole,
174
+ content: [{ type: 'text', text: '...' }],
175
+ });
176
+ }
177
+
178
+ result.push(message);
179
+ lastRole = message.role;
180
+ }
181
+
182
+ // Ensure starts with user
183
+ const first = result[0];
184
+ if (result.length > 0 && first && first.role === 'assistant') {
185
+ result.unshift({
186
+ role: 'user',
187
+ content: [{ type: 'text', text: '...' }],
188
+ });
189
+ }
190
+
191
+ return result;
192
+ }
193
+
194
+ function buildChatStopSequences(request: NormalizedRequest): string[] {
195
+ const sequences: string[] = [];
196
+
197
+ // Add tool-related stop if tools are defined
198
+ if (request.tools && request.tools.length > 0) {
199
+ sequences.push('</function_calls>');
200
+ }
201
+
202
+ // Add any explicit stop sequences from request
203
+ if (request.stopSequences) {
204
+ if (Array.isArray(request.stopSequences)) {
205
+ sequences.push(...request.stopSequences);
206
+ } else {
207
+ sequences.push(...request.stopSequences.sequences);
208
+ }
209
+ }
210
+
211
+ return sequences;
212
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Transform exports
3
+ */
4
+
5
+ export {
6
+ transformToPrefill,
7
+ buildContinuationPrefill,
8
+ type PrefillTransformResult,
9
+ type PrefillTransformOptions,
10
+ type ProviderTextBlock,
11
+ type ProviderImageBlock,
12
+ type ProviderContentBlock,
13
+ type ProviderMessage,
14
+ } from './prefill.js';
15
+
16
+ export {
17
+ transformToChat,
18
+ type ChatTransformResult,
19
+ type ChatTransformOptions,
20
+ type ChatMessage,
21
+ type ChatContent,
22
+ } from './chat.js';