rosetta-ai 1.6.1 → 1.6.2
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/index.cjs +78 -42
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +90 -90
- package/dist/index.d.ts +90 -90
- package/dist/index.js +78 -42
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -509,12 +509,11 @@ const AnthropicSpecification = {
|
|
|
509
509
|
messageSchema: AnthropicMessageSchema,
|
|
510
510
|
systemSchema: AnthropicSystemSchema,
|
|
511
511
|
toGenAI({ messages, system, direction }) {
|
|
512
|
-
// Handle string input
|
|
512
|
+
// Handle string input - wrap in Anthropic format then fall through
|
|
513
|
+
// (avoids skipping system instruction handling below)
|
|
513
514
|
if (typeof messages === "string") {
|
|
514
515
|
const role = direction === "input" ? "user" : "assistant";
|
|
515
|
-
|
|
516
|
-
messages: [{ role, parts: [{ type: "text", content: messages }] }],
|
|
517
|
-
};
|
|
516
|
+
messages = [{ role, content: messages }];
|
|
518
517
|
}
|
|
519
518
|
// Validate with schema
|
|
520
519
|
const parsedMessages = AnthropicMessageSchema.array().parse(messages);
|
|
@@ -947,12 +946,11 @@ const CompatSpecification = {
|
|
|
947
946
|
messageSchema: CompatMessageSchema,
|
|
948
947
|
systemSchema: CompatSystemSchema,
|
|
949
948
|
toGenAI({ messages, system, direction }) {
|
|
950
|
-
// Handle string input
|
|
949
|
+
// Handle string input - wrap in compat format then fall through
|
|
950
|
+
// (avoids skipping system instruction handling below)
|
|
951
951
|
if (typeof messages === "string") {
|
|
952
952
|
const role = direction === "input" ? "user" : "assistant";
|
|
953
|
-
|
|
954
|
-
messages: [{ role, parts: [{ type: "text", content: messages }] }],
|
|
955
|
-
};
|
|
953
|
+
messages = [{ role, content: messages }];
|
|
956
954
|
}
|
|
957
955
|
// Validate with permissive schema
|
|
958
956
|
const parsedMessages = CompatMessageSchema.array().parse(messages);
|
|
@@ -1090,7 +1088,7 @@ function convertMessage(message, direction) {
|
|
|
1090
1088
|
}
|
|
1091
1089
|
// Handle tool response message (role: tool with tool_call_id)
|
|
1092
1090
|
if ((role === "tool" || role === "function") && parts.length > 0) {
|
|
1093
|
-
const toolCallId = getProperty(normalized, "toolCallId") ?? getProperty(normalized, "toolUseId") ?? null;
|
|
1091
|
+
const toolCallId = getProperty(normalized, "toolCallId") ?? getProperty(normalized, "toolUseId") ?? getProperty(normalized, "toolId") ?? null;
|
|
1094
1092
|
const toolName = getProperty(normalized, "name") ?? getProperty(normalized, "toolName");
|
|
1095
1093
|
// Check if we already have tool_call_response parts from content
|
|
1096
1094
|
const hasToolResponse = parts.some((p) => p.type === "tool_call_response");
|
|
@@ -1202,6 +1200,11 @@ function convertTypedPart(part, type) {
|
|
|
1202
1200
|
if (url) {
|
|
1203
1201
|
return [convertImageUrl(url)];
|
|
1204
1202
|
}
|
|
1203
|
+
// Handle image_url as a direct string (data URI or URL)
|
|
1204
|
+
const imageUrlStr = getStringProperty(part, "imageUrl");
|
|
1205
|
+
if (imageUrlStr) {
|
|
1206
|
+
return [convertImageUrl(imageUrlStr)];
|
|
1207
|
+
}
|
|
1205
1208
|
return [];
|
|
1206
1209
|
}
|
|
1207
1210
|
case "image": {
|
|
@@ -1215,6 +1218,21 @@ function convertTypedPart(part, type) {
|
|
|
1215
1218
|
if (image) {
|
|
1216
1219
|
return [convertImageUrl(image)];
|
|
1217
1220
|
}
|
|
1221
|
+
// Fallback: check url or data fields
|
|
1222
|
+
const imageUri = getStringProperty(part, "url") ?? getStringProperty(part, "uri");
|
|
1223
|
+
if (imageUri) {
|
|
1224
|
+
return [convertImageUrl(imageUri)];
|
|
1225
|
+
}
|
|
1226
|
+
const imageData = getStringProperty(part, "data");
|
|
1227
|
+
const imageMime = getStringProperty(part, "mediaType") ?? getStringProperty(part, "mimeType");
|
|
1228
|
+
if (imageData) {
|
|
1229
|
+
if (imageData.startsWith("data:")) {
|
|
1230
|
+
return [convertImageUrl(imageData)];
|
|
1231
|
+
}
|
|
1232
|
+
return [
|
|
1233
|
+
{ type: "blob", modality: "image", content: imageData, ...(imageMime ? { mime_type: imageMime } : {}) },
|
|
1234
|
+
];
|
|
1235
|
+
}
|
|
1218
1236
|
return [];
|
|
1219
1237
|
}
|
|
1220
1238
|
case "input_audio":
|
|
@@ -1248,6 +1266,25 @@ function convertTypedPart(part, type) {
|
|
|
1248
1266
|
return [{ type: "blob", modality, content: fileData, ...(mimeType ? { mime_type: mimeType } : {}) }];
|
|
1249
1267
|
}
|
|
1250
1268
|
}
|
|
1269
|
+
// Handle file field as string (data URI, URL, or filename)
|
|
1270
|
+
const fileStr = getStringProperty(part, "file");
|
|
1271
|
+
if (fileStr) {
|
|
1272
|
+
const mimeType = getStringProperty(part, "mediaType") ?? getStringProperty(part, "mimeType");
|
|
1273
|
+
const modality = inferModality(mimeType);
|
|
1274
|
+
if (fileStr.startsWith("data:")) {
|
|
1275
|
+
const match = fileStr.match(/^data:([^;,]+)?(?:;base64)?,(.*)$/);
|
|
1276
|
+
if (match) {
|
|
1277
|
+
const parsedMime = match[1] || mimeType || "application/octet-stream";
|
|
1278
|
+
const data = match[2] || "";
|
|
1279
|
+
return [{ type: "blob", modality: inferModality(parsedMime), mime_type: parsedMime, content: data }];
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
if (isUrlString(fileStr)) {
|
|
1283
|
+
return [{ type: "uri", modality, uri: fileStr, ...(mimeType ? { mime_type: mimeType } : {}) }];
|
|
1284
|
+
}
|
|
1285
|
+
// Treat as file ID
|
|
1286
|
+
return [{ type: "file", modality, file_id: fileStr, ...(mimeType ? { mime_type: mimeType } : {}) }];
|
|
1287
|
+
}
|
|
1251
1288
|
if (source) {
|
|
1252
1289
|
return [convertAnthropicDocumentSource(source)];
|
|
1253
1290
|
}
|
|
@@ -1888,14 +1925,14 @@ function groupPartsByMessageIndex(parts) {
|
|
|
1888
1925
|
/** Inline blob data (images, audio, etc.) */
|
|
1889
1926
|
const GoogleBlobSchema = zod.z
|
|
1890
1927
|
.object({
|
|
1891
|
-
data: zod.z.string()
|
|
1892
|
-
mimeType: zod.z.string()
|
|
1928
|
+
data: zod.z.string(),
|
|
1929
|
+
mimeType: zod.z.string(),
|
|
1893
1930
|
})
|
|
1894
1931
|
.passthrough();
|
|
1895
1932
|
/** File reference by URI */
|
|
1896
1933
|
const GoogleFileDataSchema = zod.z
|
|
1897
1934
|
.object({
|
|
1898
|
-
fileUri: zod.z.string()
|
|
1935
|
+
fileUri: zod.z.string(),
|
|
1899
1936
|
mimeType: zod.z.string().optional(),
|
|
1900
1937
|
})
|
|
1901
1938
|
.passthrough();
|
|
@@ -1903,29 +1940,29 @@ const GoogleFileDataSchema = zod.z
|
|
|
1903
1940
|
const GoogleFunctionCallSchema = zod.z
|
|
1904
1941
|
.object({
|
|
1905
1942
|
id: zod.z.string().optional(),
|
|
1906
|
-
name: zod.z.string()
|
|
1907
|
-
args: zod.z.
|
|
1943
|
+
name: zod.z.string(),
|
|
1944
|
+
args: zod.z.object({}).passthrough().optional(),
|
|
1908
1945
|
})
|
|
1909
1946
|
.passthrough();
|
|
1910
1947
|
/** Function response provided to the model */
|
|
1911
1948
|
const GoogleFunctionResponseSchema = zod.z
|
|
1912
1949
|
.object({
|
|
1913
1950
|
id: zod.z.string().optional(),
|
|
1914
|
-
name: zod.z.string()
|
|
1915
|
-
response: zod.z.
|
|
1951
|
+
name: zod.z.string(),
|
|
1952
|
+
response: zod.z.object({}).passthrough(),
|
|
1916
1953
|
})
|
|
1917
1954
|
.passthrough();
|
|
1918
1955
|
/** Executable code generated by the model */
|
|
1919
1956
|
const GoogleExecutableCodeSchema = zod.z
|
|
1920
1957
|
.object({
|
|
1921
|
-
code: zod.z.string()
|
|
1922
|
-
language: zod.z.string()
|
|
1958
|
+
code: zod.z.string(),
|
|
1959
|
+
language: zod.z.string(),
|
|
1923
1960
|
})
|
|
1924
1961
|
.passthrough();
|
|
1925
1962
|
/** Code execution result */
|
|
1926
1963
|
const GoogleCodeExecutionResultSchema = zod.z
|
|
1927
1964
|
.object({
|
|
1928
|
-
outcome: zod.z.string()
|
|
1965
|
+
outcome: zod.z.string(),
|
|
1929
1966
|
output: zod.z.string().optional(),
|
|
1930
1967
|
})
|
|
1931
1968
|
.passthrough();
|
|
@@ -1969,13 +2006,13 @@ const GooglePartSchema = zod.z
|
|
|
1969
2006
|
/**
|
|
1970
2007
|
* Content (message) schema.
|
|
1971
2008
|
*
|
|
1972
|
-
*
|
|
1973
|
-
*
|
|
2009
|
+
* Parts is a required array of Part objects.
|
|
2010
|
+
* Role is optional and can be 'user' or 'model'.
|
|
1974
2011
|
*/
|
|
1975
2012
|
const GoogleContentSchema = zod.z
|
|
1976
2013
|
.object({
|
|
1977
2014
|
role: zod.z.string().optional(),
|
|
1978
|
-
parts: zod.z.array(GooglePartSchema)
|
|
2015
|
+
parts: zod.z.array(GooglePartSchema),
|
|
1979
2016
|
})
|
|
1980
2017
|
.passthrough();
|
|
1981
2018
|
/** System instruction - uses the same Content/Part structure */
|
|
@@ -2007,12 +2044,11 @@ const GoogleSpecification = {
|
|
|
2007
2044
|
messageSchema: GoogleContentSchema,
|
|
2008
2045
|
systemSchema: GoogleSystemSchema,
|
|
2009
2046
|
toGenAI({ messages, system, direction }) {
|
|
2010
|
-
// Handle string input
|
|
2047
|
+
// Handle string input - wrap in Google format (role: "user"/"model", parts with text)
|
|
2048
|
+
// then fall through to the normal conversion pipeline
|
|
2011
2049
|
if (typeof messages === "string") {
|
|
2012
2050
|
const role = direction === "input" ? "user" : "model";
|
|
2013
|
-
|
|
2014
|
-
messages: [{ role, parts: [{ type: "text", content: messages }] }],
|
|
2015
|
-
};
|
|
2051
|
+
messages = [{ role, parts: [{ text: messages }] }];
|
|
2016
2052
|
}
|
|
2017
2053
|
// Validate with schema
|
|
2018
2054
|
const parsedMessages = GoogleContentSchema.array().parse(messages);
|
|
@@ -2067,7 +2103,7 @@ function googleContentToGenAI(content, direction) {
|
|
|
2067
2103
|
const existingMetadata = readMetadata(content);
|
|
2068
2104
|
const parts = [];
|
|
2069
2105
|
// Convert each part
|
|
2070
|
-
for (const part of content.parts
|
|
2106
|
+
for (const part of content.parts) {
|
|
2071
2107
|
parts.push(...convertPart(part));
|
|
2072
2108
|
}
|
|
2073
2109
|
// Map role: 'model' -> 'assistant', otherwise keep as-is
|
|
@@ -2138,8 +2174,8 @@ function convertPart(part) {
|
|
|
2138
2174
|
{
|
|
2139
2175
|
type: "blob",
|
|
2140
2176
|
modality,
|
|
2141
|
-
mime_type: blob.mimeType
|
|
2142
|
-
content: blob.data
|
|
2177
|
+
mime_type: blob.mimeType,
|
|
2178
|
+
content: blob.data,
|
|
2143
2179
|
...(metadata ? { _provider_metadata: metadata } : {}),
|
|
2144
2180
|
},
|
|
2145
2181
|
];
|
|
@@ -2155,7 +2191,7 @@ function convertPart(part) {
|
|
|
2155
2191
|
type: "uri",
|
|
2156
2192
|
modality,
|
|
2157
2193
|
mime_type: file.mimeType ?? null,
|
|
2158
|
-
uri: file.fileUri
|
|
2194
|
+
uri: file.fileUri,
|
|
2159
2195
|
...(metadata ? { _provider_metadata: metadata } : {}),
|
|
2160
2196
|
},
|
|
2161
2197
|
];
|
|
@@ -2169,7 +2205,7 @@ function convertPart(part) {
|
|
|
2169
2205
|
{
|
|
2170
2206
|
type: "tool_call",
|
|
2171
2207
|
id: fc.id ?? null,
|
|
2172
|
-
name: fc.name
|
|
2208
|
+
name: fc.name,
|
|
2173
2209
|
arguments: fc.args,
|
|
2174
2210
|
...(metadata ? { _provider_metadata: metadata } : {}),
|
|
2175
2211
|
},
|
|
@@ -2179,8 +2215,12 @@ function convertPart(part) {
|
|
|
2179
2215
|
if (part.functionResponse !== undefined) {
|
|
2180
2216
|
const fr = part.functionResponse;
|
|
2181
2217
|
const frExtra = extractExtraFields(fr, ["id", "name", "response"]);
|
|
2182
|
-
//
|
|
2183
|
-
const
|
|
2218
|
+
// Detect error: per Gemini docs, a failed function call has an "error" key in the response
|
|
2219
|
+
const isError = "error" in fr.response;
|
|
2220
|
+
const metadata = storeMetadata(existingMetadata, { ...extraFields, ...frExtra }, {
|
|
2221
|
+
toolName: fr.name,
|
|
2222
|
+
...(isError ? { isError: true } : {}),
|
|
2223
|
+
});
|
|
2184
2224
|
return [
|
|
2185
2225
|
{
|
|
2186
2226
|
type: "tool_call_response",
|
|
@@ -2198,7 +2238,7 @@ function convertPart(part) {
|
|
|
2198
2238
|
return [
|
|
2199
2239
|
{
|
|
2200
2240
|
type: "executable_code",
|
|
2201
|
-
code: code.code
|
|
2241
|
+
code: code.code,
|
|
2202
2242
|
language: code.language,
|
|
2203
2243
|
...(metadata ? { _provider_metadata: metadata } : {}),
|
|
2204
2244
|
},
|
|
@@ -2410,12 +2450,10 @@ const OpenAICompletionsSpecification = {
|
|
|
2410
2450
|
name: "OpenAI Completions",
|
|
2411
2451
|
messageSchema: OpenAICompletionsMessageSchema,
|
|
2412
2452
|
toGenAI({ messages, direction }) {
|
|
2413
|
-
// Handle string input
|
|
2453
|
+
// Handle string input - wrap in OpenAI Completions format then fall through
|
|
2414
2454
|
if (typeof messages === "string") {
|
|
2415
2455
|
const role = direction === "input" ? "user" : "assistant";
|
|
2416
|
-
|
|
2417
|
-
messages: [{ role, parts: [{ type: "text", content: messages }] }],
|
|
2418
|
-
};
|
|
2456
|
+
messages = [{ role, content: messages }];
|
|
2419
2457
|
}
|
|
2420
2458
|
// Validate with schema
|
|
2421
2459
|
const parsedMessages = OpenAICompletionsMessageSchema.array().parse(messages);
|
|
@@ -2853,12 +2891,10 @@ const OpenAIResponsesSpecification = {
|
|
|
2853
2891
|
name: "OpenAI Responses",
|
|
2854
2892
|
messageSchema: OpenAIResponsesItemSchema,
|
|
2855
2893
|
toGenAI({ messages, direction }) {
|
|
2856
|
-
// Handle string input
|
|
2894
|
+
// Handle string input - wrap in OpenAI Responses format then fall through
|
|
2857
2895
|
if (typeof messages === "string") {
|
|
2858
2896
|
const role = direction === "input" ? "user" : "assistant";
|
|
2859
|
-
|
|
2860
|
-
messages: [{ role, parts: [{ type: "text", content: messages }] }],
|
|
2861
|
-
};
|
|
2897
|
+
messages = [{ role, content: messages }];
|
|
2862
2898
|
}
|
|
2863
2899
|
// Validate with schema
|
|
2864
2900
|
const parsedItems = OpenAIResponsesItemSchema.array().parse(messages);
|