@animalabs/membrane 0.5.27 → 0.5.29
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/formatters/native.d.ts.map +1 -1
- package/dist/formatters/native.js +7 -2
- package/dist/formatters/native.js.map +1 -1
- package/dist/membrane.d.ts.map +1 -1
- package/dist/membrane.js +7 -2
- package/dist/membrane.js.map +1 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +17 -1
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/gemini.d.ts.map +1 -1
- package/dist/providers/gemini.js +12 -7
- package/dist/providers/gemini.js.map +1 -1
- package/dist/providers/index.d.ts +1 -0
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +1 -0
- package/dist/providers/index.js.map +1 -1
- package/dist/providers/openai-responses.d.ts +45 -0
- package/dist/providers/openai-responses.d.ts.map +1 -0
- package/dist/providers/openai-responses.js +394 -0
- package/dist/providers/openai-responses.js.map +1 -0
- package/dist/types/content.d.ts +4 -0
- package/dist/types/content.d.ts.map +1 -1
- package/dist/types/content.js.map +1 -1
- package/package.json +1 -1
- package/src/formatters/native.ts +7 -2
- package/src/membrane.ts +7 -2
- package/src/providers/anthropic.ts +17 -1
- package/src/providers/gemini.ts +13 -7
- package/src/providers/index.ts +5 -0
- package/src/providers/openai-responses.ts +581 -0
- package/src/types/content.ts +4 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Responses API provider adapter
|
|
3
|
+
*
|
|
4
|
+
* Adapter for OpenAI's `/v1/responses` endpoint, required for image generation
|
|
5
|
+
* models like `gpt-image-1`. The Responses API differs from Chat Completions:
|
|
6
|
+
*
|
|
7
|
+
* - Uses `input` array instead of `messages`
|
|
8
|
+
* - Content types: `input_text` / `input_image` (not `text` / `image_url`)
|
|
9
|
+
* - Image generation is a tool: `{"type": "image_generation"}`
|
|
10
|
+
* - Generated images come back as `image_generation_call` output items
|
|
11
|
+
* - Streaming uses different event types
|
|
12
|
+
*
|
|
13
|
+
* This adapter converts membrane's ProviderRequest into the Responses API format,
|
|
14
|
+
* sends the request, and converts the response back into membrane ContentBlocks.
|
|
15
|
+
*/
|
|
16
|
+
import type { ProviderAdapter, ProviderRequest, ProviderRequestOptions, ProviderResponse, StreamCallbacks } from '../types/index.js';
|
|
17
|
+
export interface OpenAIResponsesAdapterConfig {
|
|
18
|
+
/** API key (defaults to OPENAI_API_KEY env var) */
|
|
19
|
+
apiKey?: string;
|
|
20
|
+
/** Base URL (default: https://api.openai.com/v1) */
|
|
21
|
+
baseURL?: string;
|
|
22
|
+
/** Organization ID (optional) */
|
|
23
|
+
organization?: string;
|
|
24
|
+
/** Default max output tokens */
|
|
25
|
+
defaultMaxTokens?: number;
|
|
26
|
+
}
|
|
27
|
+
export declare class OpenAIResponsesAdapter implements ProviderAdapter {
|
|
28
|
+
readonly name = "openai-responses";
|
|
29
|
+
private apiKey;
|
|
30
|
+
private baseURL;
|
|
31
|
+
private organization?;
|
|
32
|
+
private defaultMaxTokens;
|
|
33
|
+
constructor(config?: OpenAIResponsesAdapterConfig);
|
|
34
|
+
supportsModel(modelId: string): boolean;
|
|
35
|
+
complete(request: ProviderRequest, options?: ProviderRequestOptions): Promise<ProviderResponse>;
|
|
36
|
+
stream(request: ProviderRequest, callbacks: StreamCallbacks, options?: ProviderRequestOptions): Promise<ProviderResponse>;
|
|
37
|
+
private getHeaders;
|
|
38
|
+
private buildRequest;
|
|
39
|
+
private convertMessages;
|
|
40
|
+
private mapRole;
|
|
41
|
+
private parseResponse;
|
|
42
|
+
private buildContentBlocks;
|
|
43
|
+
private handleError;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=openai-responses.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-responses.d.ts","sourceRoot":"","sources":["../../src/providers/openai-responses.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EACV,eAAe,EACf,eAAe,EACf,sBAAsB,EACtB,gBAAgB,EAChB,eAAe,EAEhB,MAAM,mBAAmB,CAAC;AAyF3B,MAAM,WAAW,4BAA4B;IAC3C,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,iCAAiC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB,gCAAgC;IAChC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAMD,qBAAa,sBAAuB,YAAW,eAAe;IAC5D,QAAQ,CAAC,IAAI,sBAAsB;IACnC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,gBAAgB,CAAS;gBAErB,MAAM,GAAE,4BAAiC;IAWrD,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO;IAIjC,QAAQ,CACZ,OAAO,EAAE,eAAe,EACxB,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,gBAAgB,CAAC;IA6BtB,MAAM,CACV,OAAO,EAAE,eAAe,EACxB,SAAS,EAAE,eAAe,EAC1B,OAAO,CAAC,EAAE,sBAAsB,GAC/B,OAAO,CAAC,gBAAgB,CAAC;IAwI5B,OAAO,CAAC,UAAU;IAalB,OAAO,CAAC,YAAY;IA+CpB,OAAO,CAAC,eAAe;IAmDvB,OAAO,CAAC,OAAO;IAiBf,OAAO,CAAC,aAAa;IA6CrB,OAAO,CAAC,kBAAkB;IAyB1B,OAAO,CAAC,WAAW;CA0DpB"}
|
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI Responses API provider adapter
|
|
3
|
+
*
|
|
4
|
+
* Adapter for OpenAI's `/v1/responses` endpoint, required for image generation
|
|
5
|
+
* models like `gpt-image-1`. The Responses API differs from Chat Completions:
|
|
6
|
+
*
|
|
7
|
+
* - Uses `input` array instead of `messages`
|
|
8
|
+
* - Content types: `input_text` / `input_image` (not `text` / `image_url`)
|
|
9
|
+
* - Image generation is a tool: `{"type": "image_generation"}`
|
|
10
|
+
* - Generated images come back as `image_generation_call` output items
|
|
11
|
+
* - Streaming uses different event types
|
|
12
|
+
*
|
|
13
|
+
* This adapter converts membrane's ProviderRequest into the Responses API format,
|
|
14
|
+
* sends the request, and converts the response back into membrane ContentBlocks.
|
|
15
|
+
*/
|
|
16
|
+
import { MembraneError, rateLimitError, contextLengthError, authError, serverError, abortError, networkError, } from '../types/index.js';
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// OpenAI Responses Adapter
|
|
19
|
+
// ============================================================================
|
|
20
|
+
export class OpenAIResponsesAdapter {
|
|
21
|
+
name = 'openai-responses';
|
|
22
|
+
apiKey;
|
|
23
|
+
baseURL;
|
|
24
|
+
organization;
|
|
25
|
+
defaultMaxTokens;
|
|
26
|
+
constructor(config = {}) {
|
|
27
|
+
this.apiKey = config.apiKey ?? process.env.OPENAI_API_KEY ?? '';
|
|
28
|
+
this.baseURL = (config.baseURL ?? 'https://api.openai.com/v1').replace(/\/$/, '');
|
|
29
|
+
this.organization = config.organization;
|
|
30
|
+
this.defaultMaxTokens = config.defaultMaxTokens ?? 4096;
|
|
31
|
+
if (!this.apiKey) {
|
|
32
|
+
throw new Error('OpenAI API key not provided');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
supportsModel(modelId) {
|
|
36
|
+
return modelId.startsWith('gpt-image');
|
|
37
|
+
}
|
|
38
|
+
async complete(request, options) {
|
|
39
|
+
const responsesRequest = this.buildRequest(request);
|
|
40
|
+
options?.onRequest?.(responsesRequest);
|
|
41
|
+
try {
|
|
42
|
+
const response = await fetch(`${this.baseURL}/responses`, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
headers: this.getHeaders(),
|
|
45
|
+
body: JSON.stringify(responsesRequest),
|
|
46
|
+
signal: options?.signal,
|
|
47
|
+
});
|
|
48
|
+
if (!response.ok) {
|
|
49
|
+
const errorText = await response.text();
|
|
50
|
+
throw new Error(`OpenAI Responses API error: ${response.status} ${errorText}`);
|
|
51
|
+
}
|
|
52
|
+
const data = (await response.json());
|
|
53
|
+
if (data.error) {
|
|
54
|
+
throw new Error(`OpenAI Responses API error: ${data.error.code} ${data.error.message}`);
|
|
55
|
+
}
|
|
56
|
+
return this.parseResponse(data, request.model, responsesRequest);
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
throw this.handleError(error, responsesRequest);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async stream(request, callbacks, options) {
|
|
63
|
+
const responsesRequest = this.buildRequest(request);
|
|
64
|
+
responsesRequest.stream = true;
|
|
65
|
+
options?.onRequest?.(responsesRequest);
|
|
66
|
+
try {
|
|
67
|
+
const response = await fetch(`${this.baseURL}/responses`, {
|
|
68
|
+
method: 'POST',
|
|
69
|
+
headers: this.getHeaders(),
|
|
70
|
+
body: JSON.stringify(responsesRequest),
|
|
71
|
+
signal: options?.signal,
|
|
72
|
+
});
|
|
73
|
+
if (!response.ok) {
|
|
74
|
+
const errorText = await response.text();
|
|
75
|
+
throw new Error(`OpenAI Responses API error: ${response.status} ${errorText}`);
|
|
76
|
+
}
|
|
77
|
+
const reader = response.body?.getReader();
|
|
78
|
+
if (!reader) {
|
|
79
|
+
throw new Error('No response body');
|
|
80
|
+
}
|
|
81
|
+
const decoder = new TextDecoder();
|
|
82
|
+
let accumulated = '';
|
|
83
|
+
let images = [];
|
|
84
|
+
let lastUsage;
|
|
85
|
+
let buffer = '';
|
|
86
|
+
while (true) {
|
|
87
|
+
const { done, value } = await reader.read();
|
|
88
|
+
if (done)
|
|
89
|
+
break;
|
|
90
|
+
buffer += decoder.decode(value, { stream: true });
|
|
91
|
+
const lines = buffer.split('\n');
|
|
92
|
+
buffer = lines.pop() ?? '';
|
|
93
|
+
for (const line of lines) {
|
|
94
|
+
if (!line.startsWith('data: '))
|
|
95
|
+
continue;
|
|
96
|
+
const data = line.slice(6).trim();
|
|
97
|
+
if (!data || data === '[DONE]')
|
|
98
|
+
continue;
|
|
99
|
+
try {
|
|
100
|
+
const parsed = JSON.parse(data);
|
|
101
|
+
// Handle text deltas
|
|
102
|
+
if (parsed.type === 'response.output_text.delta') {
|
|
103
|
+
const delta = parsed.delta ?? '';
|
|
104
|
+
accumulated += delta;
|
|
105
|
+
callbacks.onChunk(delta);
|
|
106
|
+
}
|
|
107
|
+
// Handle completed text
|
|
108
|
+
if (parsed.type === 'response.output_text.done') {
|
|
109
|
+
// Text already accumulated via deltas
|
|
110
|
+
}
|
|
111
|
+
// Handle image generation results
|
|
112
|
+
if (parsed.type === 'response.image_generation_call.done') {
|
|
113
|
+
if (parsed.result) {
|
|
114
|
+
images.push({
|
|
115
|
+
data: parsed.result,
|
|
116
|
+
mimeType: 'image/png',
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Handle completed response (has usage)
|
|
121
|
+
if (parsed.type === 'response.completed' || parsed.type === 'response.done') {
|
|
122
|
+
const resp = parsed.response ?? parsed;
|
|
123
|
+
if (resp.usage) {
|
|
124
|
+
lastUsage = resp.usage;
|
|
125
|
+
}
|
|
126
|
+
// Extract any images from the completed response output
|
|
127
|
+
if (resp.output) {
|
|
128
|
+
for (const item of resp.output) {
|
|
129
|
+
if (item.type === 'image_generation_call' && item.result) {
|
|
130
|
+
// Only add if not already captured via streaming events
|
|
131
|
+
const alreadyCaptured = images.some(img => img.data === item.result);
|
|
132
|
+
if (!alreadyCaptured) {
|
|
133
|
+
images.push({
|
|
134
|
+
data: item.result,
|
|
135
|
+
mimeType: 'image/png',
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
// Ignore parse errors in stream chunks
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
// Process remaining buffer
|
|
149
|
+
if (buffer.trim()) {
|
|
150
|
+
const remaining = buffer.trim();
|
|
151
|
+
const dataLine = remaining.startsWith('data: ') ? remaining.slice(6).trim() : remaining;
|
|
152
|
+
if (dataLine && dataLine !== '[DONE]') {
|
|
153
|
+
try {
|
|
154
|
+
const parsed = JSON.parse(dataLine);
|
|
155
|
+
if (parsed.type === 'response.completed' || parsed.type === 'response.done') {
|
|
156
|
+
const resp = parsed.response ?? parsed;
|
|
157
|
+
if (resp.usage)
|
|
158
|
+
lastUsage = resp.usage;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
// Final buffer wasn't valid JSON
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
const cachedTokens = lastUsage?.input_tokens_details?.cached_tokens ?? 0;
|
|
167
|
+
return {
|
|
168
|
+
content: this.buildContentBlocks(accumulated, images),
|
|
169
|
+
stopReason: 'end_turn',
|
|
170
|
+
stopSequence: undefined,
|
|
171
|
+
usage: {
|
|
172
|
+
inputTokens: lastUsage?.input_tokens ?? 0,
|
|
173
|
+
outputTokens: lastUsage?.output_tokens ?? 0,
|
|
174
|
+
cacheReadTokens: cachedTokens > 0 ? cachedTokens : undefined,
|
|
175
|
+
},
|
|
176
|
+
model: request.model,
|
|
177
|
+
rawRequest: responsesRequest,
|
|
178
|
+
raw: { usage: lastUsage },
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
throw this.handleError(error, responsesRequest);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// --------------------------------------------------------------------------
|
|
186
|
+
// Request Building
|
|
187
|
+
// --------------------------------------------------------------------------
|
|
188
|
+
getHeaders() {
|
|
189
|
+
const headers = {
|
|
190
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
191
|
+
'Content-Type': 'application/json',
|
|
192
|
+
};
|
|
193
|
+
if (this.organization) {
|
|
194
|
+
headers['OpenAI-Organization'] = this.organization;
|
|
195
|
+
}
|
|
196
|
+
return headers;
|
|
197
|
+
}
|
|
198
|
+
buildRequest(request) {
|
|
199
|
+
const input = this.convertMessages(request.messages);
|
|
200
|
+
const maxTokens = request.maxTokens || this.defaultMaxTokens;
|
|
201
|
+
const responsesRequest = {
|
|
202
|
+
model: request.model,
|
|
203
|
+
input,
|
|
204
|
+
max_output_tokens: maxTokens,
|
|
205
|
+
};
|
|
206
|
+
// System prompt → instructions
|
|
207
|
+
if (request.system) {
|
|
208
|
+
const systemText = typeof request.system === 'string'
|
|
209
|
+
? request.system
|
|
210
|
+
: request.system
|
|
211
|
+
.filter((b) => b.type === 'text')
|
|
212
|
+
.map((b) => b.text)
|
|
213
|
+
.join('\n');
|
|
214
|
+
if (systemText) {
|
|
215
|
+
responsesRequest.instructions = systemText;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
if (request.temperature !== undefined) {
|
|
219
|
+
responsesRequest.temperature = request.temperature;
|
|
220
|
+
}
|
|
221
|
+
if (request.topP !== undefined) {
|
|
222
|
+
responsesRequest.top_p = request.topP;
|
|
223
|
+
}
|
|
224
|
+
// Auto-include image_generation tool for image models
|
|
225
|
+
if (request.model?.includes('image')) {
|
|
226
|
+
responsesRequest.tools = [{ type: 'image_generation' }];
|
|
227
|
+
}
|
|
228
|
+
// Apply extra params (filter out internal membrane fields)
|
|
229
|
+
if (request.extra) {
|
|
230
|
+
const { normalizedMessages, prompt, ...rest } = request.extra;
|
|
231
|
+
Object.assign(responsesRequest, rest);
|
|
232
|
+
}
|
|
233
|
+
return responsesRequest;
|
|
234
|
+
}
|
|
235
|
+
convertMessages(messages) {
|
|
236
|
+
const result = [];
|
|
237
|
+
for (const msg of messages) {
|
|
238
|
+
const role = this.mapRole(msg.role);
|
|
239
|
+
// Simple string content
|
|
240
|
+
if (typeof msg.content === 'string') {
|
|
241
|
+
result.push({ role, content: msg.content });
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
// Array content blocks (Anthropic-style)
|
|
245
|
+
if (Array.isArray(msg.content)) {
|
|
246
|
+
const parts = [];
|
|
247
|
+
for (const block of msg.content) {
|
|
248
|
+
if (block.type === 'text') {
|
|
249
|
+
if (block.text) {
|
|
250
|
+
parts.push({ type: 'input_text', text: block.text });
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
else if (block.type === 'image') {
|
|
254
|
+
const source = block.source;
|
|
255
|
+
if (source?.type === 'base64' && source.data) {
|
|
256
|
+
const mimeType = source.media_type ?? source.mediaType ?? 'image/jpeg';
|
|
257
|
+
parts.push({
|
|
258
|
+
type: 'input_image',
|
|
259
|
+
image_url: `data:${mimeType};base64,${source.data}`,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// tool_use and tool_result are not supported in the Responses API input
|
|
264
|
+
// for image models — skip them silently
|
|
265
|
+
}
|
|
266
|
+
if (parts.length > 0) {
|
|
267
|
+
result.push({ role, content: parts });
|
|
268
|
+
}
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
// Null/empty content — skip
|
|
272
|
+
if (msg.content === null || msg.content === undefined)
|
|
273
|
+
continue;
|
|
274
|
+
// Fallback
|
|
275
|
+
result.push({ role, content: String(msg.content) });
|
|
276
|
+
}
|
|
277
|
+
return result;
|
|
278
|
+
}
|
|
279
|
+
mapRole(role) {
|
|
280
|
+
switch (role) {
|
|
281
|
+
case 'user':
|
|
282
|
+
return 'user';
|
|
283
|
+
case 'assistant':
|
|
284
|
+
return 'assistant';
|
|
285
|
+
case 'system':
|
|
286
|
+
return 'developer';
|
|
287
|
+
default:
|
|
288
|
+
return 'user';
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
// --------------------------------------------------------------------------
|
|
292
|
+
// Response Parsing
|
|
293
|
+
// --------------------------------------------------------------------------
|
|
294
|
+
parseResponse(response, requestedModel, rawRequest) {
|
|
295
|
+
let text = '';
|
|
296
|
+
const images = [];
|
|
297
|
+
for (const item of response.output) {
|
|
298
|
+
if (item.type === 'message') {
|
|
299
|
+
for (const content of item.content) {
|
|
300
|
+
if (content.type === 'output_text') {
|
|
301
|
+
text += content.text;
|
|
302
|
+
}
|
|
303
|
+
else if (content.type === 'image_generation_call') {
|
|
304
|
+
images.push({
|
|
305
|
+
data: content.result,
|
|
306
|
+
mimeType: 'image/png',
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
else if (item.type === 'image_generation_call') {
|
|
312
|
+
images.push({
|
|
313
|
+
data: item.result,
|
|
314
|
+
mimeType: 'image/png',
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const cachedTokens = response.usage?.input_tokens_details?.cached_tokens ?? 0;
|
|
319
|
+
return {
|
|
320
|
+
content: this.buildContentBlocks(text, images),
|
|
321
|
+
stopReason: 'end_turn',
|
|
322
|
+
stopSequence: undefined,
|
|
323
|
+
usage: {
|
|
324
|
+
inputTokens: response.usage?.input_tokens ?? 0,
|
|
325
|
+
outputTokens: response.usage?.output_tokens ?? 0,
|
|
326
|
+
cacheReadTokens: cachedTokens > 0 ? cachedTokens : undefined,
|
|
327
|
+
},
|
|
328
|
+
model: response.model ?? requestedModel,
|
|
329
|
+
rawRequest,
|
|
330
|
+
raw: response,
|
|
331
|
+
};
|
|
332
|
+
}
|
|
333
|
+
buildContentBlocks(text, images = []) {
|
|
334
|
+
const content = [];
|
|
335
|
+
if (text) {
|
|
336
|
+
content.push({ type: 'text', text });
|
|
337
|
+
}
|
|
338
|
+
for (const img of images) {
|
|
339
|
+
content.push({
|
|
340
|
+
type: 'generated_image',
|
|
341
|
+
data: img.data,
|
|
342
|
+
mimeType: img.mimeType,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
return content;
|
|
346
|
+
}
|
|
347
|
+
// --------------------------------------------------------------------------
|
|
348
|
+
// Error Handling
|
|
349
|
+
// --------------------------------------------------------------------------
|
|
350
|
+
handleError(error, rawRequest) {
|
|
351
|
+
if (error instanceof MembraneError)
|
|
352
|
+
return error;
|
|
353
|
+
if (error instanceof Error) {
|
|
354
|
+
const message = error.message;
|
|
355
|
+
if (message.includes('429') || message.includes('rate_limit')) {
|
|
356
|
+
const retryMatch = message.match(/retry after (\d+)/i);
|
|
357
|
+
const retryAfter = retryMatch?.[1] ? parseInt(retryMatch[1], 10) * 1000 : undefined;
|
|
358
|
+
return rateLimitError(message, retryAfter, error, rawRequest);
|
|
359
|
+
}
|
|
360
|
+
if (message.includes('401') ||
|
|
361
|
+
message.includes('invalid_api_key') ||
|
|
362
|
+
message.includes('Incorrect API key')) {
|
|
363
|
+
return authError(message, error, rawRequest);
|
|
364
|
+
}
|
|
365
|
+
if (message.includes('context_length') ||
|
|
366
|
+
message.includes('maximum context') ||
|
|
367
|
+
message.includes('too long')) {
|
|
368
|
+
return contextLengthError(message, error, rawRequest);
|
|
369
|
+
}
|
|
370
|
+
if (message.includes('500') ||
|
|
371
|
+
message.includes('502') ||
|
|
372
|
+
message.includes('503') ||
|
|
373
|
+
message.includes('server_error')) {
|
|
374
|
+
return serverError(message, undefined, error, rawRequest);
|
|
375
|
+
}
|
|
376
|
+
if (error.name === 'AbortError') {
|
|
377
|
+
return abortError(undefined, rawRequest);
|
|
378
|
+
}
|
|
379
|
+
if (message.includes('network') ||
|
|
380
|
+
message.includes('fetch') ||
|
|
381
|
+
message.includes('ECONNREFUSED')) {
|
|
382
|
+
return networkError(message, error, rawRequest);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
return new MembraneError({
|
|
386
|
+
type: 'unknown',
|
|
387
|
+
message: error instanceof Error ? error.message : String(error),
|
|
388
|
+
retryable: false,
|
|
389
|
+
rawError: error,
|
|
390
|
+
rawRequest,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
//# sourceMappingURL=openai-responses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-responses.js","sourceRoot":"","sources":["../../src/providers/openai-responses.ts"],"names":[],"mappings":"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"}
|
package/dist/types/content.d.ts
CHANGED
|
@@ -26,6 +26,10 @@ export interface ImageContent {
|
|
|
26
26
|
type: 'image';
|
|
27
27
|
source: MediaSource;
|
|
28
28
|
tokenEstimate?: number;
|
|
29
|
+
/** Original URL of the image (e.g., Discord CDN). Used by providers that
|
|
30
|
+
* can auto-fetch URLs from text (like Gemini 3.x) when inlineData is
|
|
31
|
+
* not viable (e.g., missing thought_signature on model-role images). */
|
|
32
|
+
sourceUrl?: string;
|
|
29
33
|
}
|
|
30
34
|
export interface DocumentContent {
|
|
31
35
|
type: 'document';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/types/content.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,kEAAkE;IAClE,GAAG,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACnB;AAMD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,KAAK,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,MAAM,WAAW,GAAG,YAAY,GAAG,SAAS,CAAC;AAMnD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,iDAAiD;IACjD,aAAa,CAAC,EAAE,YAAY,CAAC;CAC9B;AAMD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,WAAW,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../../src/types/content.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/types/content.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../../src/types/content.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwIH,+EAA+E;AAC/E,cAAc;AACd,+EAA+E;AAE/E,MAAM,UAAU,aAAa,CAAC,KAAmB;IAC/C,OAAO,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAmB;IAChD,OAAO,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAmB;IACnD,OAAO,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAmB;IAChD,OAAO,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAmB;IAChD,OAAO,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,KAAmB;IACzD,OAAO,KAAK,CAAC,IAAI,KAAK,iBAAiB,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,KAAmB;IAClD,OAAO,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAmB;IACrD,OAAO,KAAK,CAAC,IAAI,KAAK,aAAa,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAmB;IACnD,OAAO,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,yBAAyB,CAAC,KAAmB;IAC3D,OAAO,KAAK,CAAC,IAAI,KAAK,mBAAmB,CAAC;AAC5C,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,KAAmB;IAEnB,OAAO,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACtE,CAAC"}
|
package/package.json
CHANGED
package/src/formatters/native.ts
CHANGED
|
@@ -313,14 +313,19 @@ export class NativeFormatter implements PrefillFormatter {
|
|
|
313
313
|
result.push(textBlock);
|
|
314
314
|
} else if (block.type === 'image') {
|
|
315
315
|
if (block.source.type === 'base64') {
|
|
316
|
-
|
|
316
|
+
const imageBlock: Record<string, unknown> = {
|
|
317
317
|
type: 'image',
|
|
318
318
|
source: {
|
|
319
319
|
type: 'base64',
|
|
320
320
|
media_type: block.source.mediaType,
|
|
321
321
|
data: block.source.data,
|
|
322
322
|
},
|
|
323
|
-
}
|
|
323
|
+
};
|
|
324
|
+
// Preserve sourceUrl for providers that use URL-as-text (Gemini 3.x)
|
|
325
|
+
if (block.sourceUrl) {
|
|
326
|
+
imageBlock.sourceUrl = block.sourceUrl;
|
|
327
|
+
}
|
|
328
|
+
result.push(imageBlock);
|
|
324
329
|
}
|
|
325
330
|
} else if (block.type === 'tool_use') {
|
|
326
331
|
result.push({
|
package/src/membrane.ts
CHANGED
|
@@ -931,14 +931,19 @@ export class Membrane {
|
|
|
931
931
|
});
|
|
932
932
|
} else if (block.type === 'image') {
|
|
933
933
|
if (block.source.type === 'base64') {
|
|
934
|
-
|
|
934
|
+
const imageBlock: Record<string, unknown> = {
|
|
935
935
|
type: 'image',
|
|
936
936
|
source: {
|
|
937
937
|
type: 'base64',
|
|
938
938
|
media_type: block.source.mediaType,
|
|
939
939
|
data: block.source.data,
|
|
940
940
|
},
|
|
941
|
-
}
|
|
941
|
+
};
|
|
942
|
+
// Preserve sourceUrl for providers that use URL-as-text (Gemini 3.x)
|
|
943
|
+
if (block.sourceUrl) {
|
|
944
|
+
imageBlock.sourceUrl = block.sourceUrl;
|
|
945
|
+
}
|
|
946
|
+
content.push(imageBlock);
|
|
942
947
|
}
|
|
943
948
|
}
|
|
944
949
|
}
|
|
@@ -122,10 +122,26 @@ export class AnthropicAdapter implements ProviderAdapter {
|
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
private buildRequest(request: ProviderRequest): Anthropic.MessageCreateParams {
|
|
125
|
+
// Strip provider-specific fields (e.g., sourceUrl for Gemini) from image blocks
|
|
126
|
+
// before sending to Anthropic, which rejects extra inputs
|
|
127
|
+
const sanitizedMessages = (request.messages as any[]).map((msg: any) => {
|
|
128
|
+
if (!Array.isArray(msg.content)) return msg;
|
|
129
|
+
return {
|
|
130
|
+
...msg,
|
|
131
|
+
content: msg.content.map((block: any) => {
|
|
132
|
+
if (block.type === 'image' && block.sourceUrl !== undefined) {
|
|
133
|
+
const { sourceUrl, ...rest } = block;
|
|
134
|
+
return rest;
|
|
135
|
+
}
|
|
136
|
+
return block;
|
|
137
|
+
}),
|
|
138
|
+
};
|
|
139
|
+
});
|
|
140
|
+
|
|
125
141
|
const params: Anthropic.MessageCreateParams = {
|
|
126
142
|
model: request.model,
|
|
127
143
|
max_tokens: request.maxTokens || this.defaultMaxTokens,
|
|
128
|
-
messages:
|
|
144
|
+
messages: sanitizedMessages as Anthropic.MessageParam[],
|
|
129
145
|
};
|
|
130
146
|
|
|
131
147
|
// Handle system prompt - can be string or content blocks with cache_control
|
package/src/providers/gemini.ts
CHANGED
|
@@ -378,11 +378,13 @@ export class GeminiAdapter implements ProviderAdapter {
|
|
|
378
378
|
private convertMessages(messages: any[], model?: string): GeminiContent[] {
|
|
379
379
|
const contents: GeminiContent[] = [];
|
|
380
380
|
|
|
381
|
-
// Gemini 3.x
|
|
382
|
-
//
|
|
383
|
-
//
|
|
384
|
-
//
|
|
385
|
-
|
|
381
|
+
// Gemini 3.x requires thought_signature on image parts from model outputs.
|
|
382
|
+
// Images that round-trip through Discord lose their thought_signature metadata,
|
|
383
|
+
// causing 400 INVALID_ARGUMENT when sent back as inlineData. For gemini-3.x
|
|
384
|
+
// model-role images, we fall back to embedding the source URL as text — Gemini
|
|
385
|
+
// auto-fetches URLs from text content, enabling iterative editing without
|
|
386
|
+
// thought_signature. User images pass through as normal inlineData.
|
|
387
|
+
const useUrlForModelImages = model?.startsWith('gemini-3');
|
|
386
388
|
|
|
387
389
|
for (const msg of messages) {
|
|
388
390
|
const role: 'user' | 'model' = msg.role === 'assistant' ? 'model' : 'user';
|
|
@@ -402,8 +404,12 @@ export class GeminiAdapter implements ProviderAdapter {
|
|
|
402
404
|
if (block.type === 'text') {
|
|
403
405
|
if (block.text) parts.push({ text: block.text });
|
|
404
406
|
} else if (block.type === 'image') {
|
|
405
|
-
//
|
|
406
|
-
|
|
407
|
+
// Gemini 3.x model-role images: use URL-as-text so Gemini auto-fetches
|
|
408
|
+
// the image without needing thought_signature metadata
|
|
409
|
+
if (useUrlForModelImages && role === 'model' && block.sourceUrl) {
|
|
410
|
+
parts.push({ text: block.sourceUrl });
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
407
413
|
|
|
408
414
|
// Anthropic image format → Gemini inlineData
|
|
409
415
|
const source = block.source;
|