@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.
- package/dist/context/index.d.ts +10 -0
- package/dist/context/index.d.ts.map +1 -0
- package/dist/context/index.js +9 -0
- package/dist/context/index.js.map +1 -0
- package/dist/context/process.d.ts +22 -0
- package/dist/context/process.d.ts.map +1 -0
- package/dist/context/process.js +369 -0
- package/dist/context/process.js.map +1 -0
- package/dist/context/types.d.ts +118 -0
- package/dist/context/types.d.ts.map +1 -0
- package/dist/context/types.js +60 -0
- package/dist/context/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/membrane.d.ts +96 -0
- package/dist/membrane.d.ts.map +1 -0
- package/dist/membrane.js +893 -0
- package/dist/membrane.js.map +1 -0
- package/dist/providers/anthropic.d.ts +36 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +265 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/index.d.ts +8 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +8 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai-compatible.d.ts +74 -0
- package/dist/providers/openai-compatible.d.ts.map +1 -0
- package/dist/providers/openai-compatible.js +412 -0
- package/dist/providers/openai-compatible.js.map +1 -0
- package/dist/providers/openai.d.ts +69 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +455 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/openrouter.d.ts +76 -0
- package/dist/providers/openrouter.d.ts.map +1 -0
- package/dist/providers/openrouter.js +492 -0
- package/dist/providers/openrouter.js.map +1 -0
- package/dist/transforms/chat.d.ts +52 -0
- package/dist/transforms/chat.d.ts.map +1 -0
- package/dist/transforms/chat.js +136 -0
- package/dist/transforms/chat.js.map +1 -0
- package/dist/transforms/index.d.ts +6 -0
- package/dist/transforms/index.d.ts.map +1 -0
- package/dist/transforms/index.js +6 -0
- package/dist/transforms/index.js.map +1 -0
- package/dist/transforms/prefill.d.ts +89 -0
- package/dist/transforms/prefill.d.ts.map +1 -0
- package/dist/transforms/prefill.js +401 -0
- package/dist/transforms/prefill.js.map +1 -0
- package/dist/types/config.d.ts +103 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +21 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/content.d.ts +81 -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 +42 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/errors.js +208 -0
- package/dist/types/errors.js.map +1 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +9 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/message.d.ts +46 -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 +155 -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 +78 -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 +164 -0
- package/dist/types/streaming.d.ts.map +1 -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/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +5 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/stream-parser.d.ts +53 -0
- package/dist/utils/stream-parser.d.ts.map +1 -0
- package/dist/utils/stream-parser.js +359 -0
- package/dist/utils/stream-parser.js.map +1 -0
- package/dist/utils/tool-parser.d.ts +130 -0
- package/dist/utils/tool-parser.d.ts.map +1 -0
- package/dist/utils/tool-parser.js +571 -0
- package/dist/utils/tool-parser.js.map +1 -0
- package/package.json +37 -0
- package/src/context/index.ts +24 -0
- package/src/context/process.ts +520 -0
- package/src/context/types.ts +231 -0
- package/src/index.ts +23 -0
- package/src/membrane.ts +1174 -0
- package/src/providers/anthropic.ts +340 -0
- package/src/providers/index.ts +31 -0
- package/src/providers/openai-compatible.ts +570 -0
- package/src/providers/openai.ts +625 -0
- package/src/providers/openrouter.ts +662 -0
- package/src/transforms/chat.ts +212 -0
- package/src/transforms/index.ts +22 -0
- package/src/transforms/prefill.ts +585 -0
- package/src/types/config.ts +172 -0
- package/src/types/content.ts +181 -0
- package/src/types/errors.ts +277 -0
- package/src/types/index.ts +154 -0
- package/src/types/message.ts +89 -0
- package/src/types/provider.ts +249 -0
- package/src/types/request.ts +131 -0
- package/src/types/response.ts +223 -0
- package/src/types/streaming.ts +231 -0
- package/src/types/tools.ts +92 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/stream-parser.ts +440 -0
- 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';
|