@providerprotocol/ai 0.0.27 → 0.0.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/anthropic/index.d.ts +1 -1
- package/dist/anthropic/index.js +38 -1
- package/dist/anthropic/index.js.map +1 -1
- package/dist/{chunk-6AZVUI6H.js → chunk-ILR2D5PN.js} +7 -1
- package/dist/chunk-ILR2D5PN.js.map +1 -0
- package/dist/{chunk-MKDLXV4O.js → chunk-NSE7QN3P.js} +1 -1
- package/dist/chunk-NSE7QN3P.js.map +1 -0
- package/dist/embedding-DtyOFIsS.d.ts +158 -0
- package/dist/google/index.d.ts +1 -1
- package/dist/google/index.js +41 -4
- package/dist/google/index.js.map +1 -1
- package/dist/http/index.d.ts +2 -2
- package/dist/index.d.ts +430 -514
- package/dist/index.js +627 -3
- package/dist/index.js.map +1 -1
- package/dist/llm-DgDEy9il.d.ts +3118 -0
- package/dist/ollama/index.d.ts +1 -1
- package/dist/ollama/index.js +2 -1
- package/dist/ollama/index.js.map +1 -1
- package/dist/openai/index.d.ts +1 -1
- package/dist/openai/index.js +70 -3
- package/dist/openai/index.js.map +1 -1
- package/dist/openrouter/index.d.ts +20 -2
- package/dist/openrouter/index.js +134 -13
- package/dist/openrouter/index.js.map +1 -1
- package/dist/proxy/index.d.ts +2 -2
- package/dist/proxy/index.js +3 -2
- package/dist/proxy/index.js.map +1 -1
- package/dist/{retry-BhX8mIrL.d.ts → retry-DXLQnTuU.d.ts} +1 -1
- package/dist/xai/index.d.ts +1 -1
- package/dist/xai/index.js +7 -3
- package/dist/xai/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-6AZVUI6H.js.map +0 -1
- package/dist/chunk-MKDLXV4O.js.map +0 -1
- package/dist/embedding-CK5oa38O.d.ts +0 -1235
- package/dist/provider-6-mJYOOl.d.ts +0 -1474
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
aggregateUsage,
|
|
3
3
|
createTurn,
|
|
4
4
|
emptyUsage
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NSE7QN3P.js";
|
|
6
6
|
import {
|
|
7
7
|
Image
|
|
8
8
|
} from "./chunk-WAKD3OO5.js";
|
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
resolveEmbeddingHandler,
|
|
33
33
|
resolveImageHandler,
|
|
34
34
|
resolveLLMHandler
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-ILR2D5PN.js";
|
|
36
36
|
import {
|
|
37
37
|
ExponentialBackoff,
|
|
38
38
|
LinearBackoff,
|
|
@@ -61,6 +61,8 @@ var ContentBlockType = {
|
|
|
61
61
|
Reasoning: "reasoning",
|
|
62
62
|
/** Image content */
|
|
63
63
|
Image: "image",
|
|
64
|
+
/** Document content (PDFs, text files) */
|
|
65
|
+
Document: "document",
|
|
64
66
|
/** Audio content */
|
|
65
67
|
Audio: "audio",
|
|
66
68
|
/** Video content */
|
|
@@ -76,6 +78,14 @@ var ImageSourceType = {
|
|
|
76
78
|
/** Raw bytes image data */
|
|
77
79
|
Bytes: "bytes"
|
|
78
80
|
};
|
|
81
|
+
var DocumentSourceType = {
|
|
82
|
+
/** Base64-encoded document data (for PDFs) */
|
|
83
|
+
Base64: "base64",
|
|
84
|
+
/** URL reference to document (for PDFs) */
|
|
85
|
+
Url: "url",
|
|
86
|
+
/** Plain text document content */
|
|
87
|
+
Text: "text"
|
|
88
|
+
};
|
|
79
89
|
function text(content) {
|
|
80
90
|
return { type: ContentBlockType.Text, text: content };
|
|
81
91
|
}
|
|
@@ -91,6 +101,9 @@ function isReasoningBlock(block) {
|
|
|
91
101
|
function isImageBlock(block) {
|
|
92
102
|
return block.type === ContentBlockType.Image;
|
|
93
103
|
}
|
|
104
|
+
function isDocumentBlock(block) {
|
|
105
|
+
return block.type === ContentBlockType.Document;
|
|
106
|
+
}
|
|
94
107
|
function isAudioBlock(block) {
|
|
95
108
|
return block.type === ContentBlockType.Audio;
|
|
96
109
|
}
|
|
@@ -243,7 +256,7 @@ function inputToMessage(input) {
|
|
|
243
256
|
if (isTextBlock(block)) {
|
|
244
257
|
return new UserMessage(block.text);
|
|
245
258
|
}
|
|
246
|
-
if (isImageBlock(block) || isAudioBlock(block) || isVideoBlock(block) || isBinaryBlock(block)) {
|
|
259
|
+
if (isImageBlock(block) || isDocumentBlock(block) || isAudioBlock(block) || isVideoBlock(block) || isBinaryBlock(block)) {
|
|
247
260
|
return new UserMessage([block]);
|
|
248
261
|
}
|
|
249
262
|
throw new Error("Invalid inference input");
|
|
@@ -597,6 +610,14 @@ function validateMediaCapabilities(messages, capabilities, providerName) {
|
|
|
597
610
|
ModalityType.LLM
|
|
598
611
|
);
|
|
599
612
|
}
|
|
613
|
+
if (block.type === "document" && !capabilities.documentInput) {
|
|
614
|
+
throw new UPPError(
|
|
615
|
+
`Provider '${providerName}' does not support document input`,
|
|
616
|
+
ErrorCode.InvalidRequest,
|
|
617
|
+
providerName,
|
|
618
|
+
ModalityType.LLM
|
|
619
|
+
);
|
|
620
|
+
}
|
|
600
621
|
if (block.type === "video" && !capabilities.videoInput) {
|
|
601
622
|
throw new UPPError(
|
|
602
623
|
`Provider '${providerName}' does not support video input`,
|
|
@@ -938,6 +959,604 @@ function normalizeInput(input) {
|
|
|
938
959
|
return input.prompt;
|
|
939
960
|
}
|
|
940
961
|
|
|
962
|
+
// src/core/media/document.ts
|
|
963
|
+
var Document = class _Document {
|
|
964
|
+
/** The underlying document source (base64, url, or text) */
|
|
965
|
+
source;
|
|
966
|
+
/** MIME type of the document ('application/pdf' or 'text/plain') */
|
|
967
|
+
mimeType;
|
|
968
|
+
/** Optional document title (used for citations) */
|
|
969
|
+
title;
|
|
970
|
+
constructor(source, mimeType, title) {
|
|
971
|
+
this.source = source;
|
|
972
|
+
this.mimeType = mimeType;
|
|
973
|
+
this.title = title;
|
|
974
|
+
}
|
|
975
|
+
/**
|
|
976
|
+
* Whether this document has data loaded in memory.
|
|
977
|
+
*
|
|
978
|
+
* Returns `false` for URL-sourced documents that reference external resources.
|
|
979
|
+
*/
|
|
980
|
+
get hasData() {
|
|
981
|
+
return this.source.type !== "url";
|
|
982
|
+
}
|
|
983
|
+
/**
|
|
984
|
+
* Whether this document is a PDF.
|
|
985
|
+
*/
|
|
986
|
+
get isPdf() {
|
|
987
|
+
return this.mimeType === "application/pdf";
|
|
988
|
+
}
|
|
989
|
+
/**
|
|
990
|
+
* Whether this document is plain text.
|
|
991
|
+
*/
|
|
992
|
+
get isText() {
|
|
993
|
+
return this.mimeType === "text/plain";
|
|
994
|
+
}
|
|
995
|
+
/**
|
|
996
|
+
* Converts the document to a base64-encoded string.
|
|
997
|
+
*
|
|
998
|
+
* @returns The document data as a base64 string
|
|
999
|
+
* @throws {Error} When the source is a URL or plain text
|
|
1000
|
+
*/
|
|
1001
|
+
toBase64() {
|
|
1002
|
+
if (this.source.type === "base64") {
|
|
1003
|
+
return this.source.data;
|
|
1004
|
+
}
|
|
1005
|
+
throw new Error("Cannot convert to base64. Only base64-sourced documents support this.");
|
|
1006
|
+
}
|
|
1007
|
+
/**
|
|
1008
|
+
* Gets the plain text content for text documents.
|
|
1009
|
+
*
|
|
1010
|
+
* @returns The document text content
|
|
1011
|
+
* @throws {Error} When the source is not plain text
|
|
1012
|
+
*/
|
|
1013
|
+
toText() {
|
|
1014
|
+
if (this.source.type === "text") {
|
|
1015
|
+
return this.source.data;
|
|
1016
|
+
}
|
|
1017
|
+
throw new Error("Cannot get text content. Only text-sourced documents support this.");
|
|
1018
|
+
}
|
|
1019
|
+
/**
|
|
1020
|
+
* Gets the URL for URL-sourced documents.
|
|
1021
|
+
*
|
|
1022
|
+
* @returns The document URL
|
|
1023
|
+
* @throws {Error} When the source is not a URL
|
|
1024
|
+
*/
|
|
1025
|
+
toUrl() {
|
|
1026
|
+
if (this.source.type === "url") {
|
|
1027
|
+
return this.source.url;
|
|
1028
|
+
}
|
|
1029
|
+
throw new Error("This document does not have a URL source.");
|
|
1030
|
+
}
|
|
1031
|
+
/**
|
|
1032
|
+
* Converts this Document to a DocumentBlock for use in UPP messages.
|
|
1033
|
+
*
|
|
1034
|
+
* @returns A DocumentBlock that can be included in message content arrays
|
|
1035
|
+
*/
|
|
1036
|
+
toBlock() {
|
|
1037
|
+
return {
|
|
1038
|
+
type: "document",
|
|
1039
|
+
source: this.source,
|
|
1040
|
+
mimeType: this.mimeType,
|
|
1041
|
+
title: this.title
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
/**
|
|
1045
|
+
* Creates a Document by reading a file from disk.
|
|
1046
|
+
*
|
|
1047
|
+
* The file is read into memory and base64-encoded. MIME type is automatically
|
|
1048
|
+
* detected from the file extension.
|
|
1049
|
+
*
|
|
1050
|
+
* @param path - Path to the document file
|
|
1051
|
+
* @param title - Optional document title
|
|
1052
|
+
* @returns Promise resolving to a Document with the file contents
|
|
1053
|
+
*
|
|
1054
|
+
* @example
|
|
1055
|
+
* ```typescript
|
|
1056
|
+
* const doc = await Document.fromPath('./reports/annual.pdf');
|
|
1057
|
+
* const docWithTitle = await Document.fromPath('./report.pdf', 'Annual Report 2024');
|
|
1058
|
+
* ```
|
|
1059
|
+
*/
|
|
1060
|
+
static async fromPath(path, title) {
|
|
1061
|
+
const file = Bun.file(path);
|
|
1062
|
+
const exists = await file.exists();
|
|
1063
|
+
if (!exists) {
|
|
1064
|
+
throw new Error(`Document file not found at path: ${path}`);
|
|
1065
|
+
}
|
|
1066
|
+
let data;
|
|
1067
|
+
try {
|
|
1068
|
+
data = await file.arrayBuffer();
|
|
1069
|
+
} catch (error) {
|
|
1070
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1071
|
+
throw new Error(`Failed to read document file at path: ${path}. ${message}`);
|
|
1072
|
+
}
|
|
1073
|
+
if (data.byteLength === 0) {
|
|
1074
|
+
throw new Error(`Document file is empty at path: ${path}`);
|
|
1075
|
+
}
|
|
1076
|
+
const base64 = Buffer.from(data).toString("base64");
|
|
1077
|
+
const mimeType = detectMimeType(path);
|
|
1078
|
+
return new _Document(
|
|
1079
|
+
{ type: "base64", data: base64 },
|
|
1080
|
+
mimeType,
|
|
1081
|
+
title
|
|
1082
|
+
);
|
|
1083
|
+
}
|
|
1084
|
+
/**
|
|
1085
|
+
* Creates a Document from a URL reference.
|
|
1086
|
+
*
|
|
1087
|
+
* The URL is stored as a reference and not fetched. Providers will handle
|
|
1088
|
+
* URL fetching if needed. Only PDF URLs are supported.
|
|
1089
|
+
* URLs must use the http or https protocol.
|
|
1090
|
+
*
|
|
1091
|
+
* @param url - URL pointing to the PDF document
|
|
1092
|
+
* @param title - Optional document title
|
|
1093
|
+
* @returns A Document referencing the URL
|
|
1094
|
+
*
|
|
1095
|
+
* @example
|
|
1096
|
+
* ```typescript
|
|
1097
|
+
* const doc = Document.fromUrl('https://example.com/report.pdf');
|
|
1098
|
+
* ```
|
|
1099
|
+
*/
|
|
1100
|
+
static fromUrl(url, title) {
|
|
1101
|
+
let parsedUrl;
|
|
1102
|
+
try {
|
|
1103
|
+
parsedUrl = new URL(url);
|
|
1104
|
+
} catch (error) {
|
|
1105
|
+
const message = error instanceof Error ? error.message : "Invalid URL";
|
|
1106
|
+
throw new Error(`Invalid document URL: ${message}`);
|
|
1107
|
+
}
|
|
1108
|
+
if (parsedUrl.protocol !== "http:" && parsedUrl.protocol !== "https:") {
|
|
1109
|
+
throw new Error(`Document URL must use http or https: ${url}`);
|
|
1110
|
+
}
|
|
1111
|
+
return new _Document(
|
|
1112
|
+
{ type: "url", url },
|
|
1113
|
+
"application/pdf",
|
|
1114
|
+
title
|
|
1115
|
+
);
|
|
1116
|
+
}
|
|
1117
|
+
/**
|
|
1118
|
+
* Creates a Document from base64-encoded data.
|
|
1119
|
+
*
|
|
1120
|
+
* @param base64 - The base64-encoded document data
|
|
1121
|
+
* @param mimeType - The MIME type ('application/pdf' or 'text/plain')
|
|
1122
|
+
* @param title - Optional document title
|
|
1123
|
+
* @returns A Document containing the base64 data
|
|
1124
|
+
*
|
|
1125
|
+
* @example
|
|
1126
|
+
* ```typescript
|
|
1127
|
+
* const doc = Document.fromBase64(pdfBase64, 'application/pdf', 'Contract');
|
|
1128
|
+
* ```
|
|
1129
|
+
*/
|
|
1130
|
+
static fromBase64(base64, mimeType, title) {
|
|
1131
|
+
return new _Document(
|
|
1132
|
+
{ type: "base64", data: base64 },
|
|
1133
|
+
mimeType,
|
|
1134
|
+
title
|
|
1135
|
+
);
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Creates a Document from plain text content.
|
|
1139
|
+
*
|
|
1140
|
+
* @param text - The document text content
|
|
1141
|
+
* @param title - Optional document title
|
|
1142
|
+
* @returns A Document containing the text
|
|
1143
|
+
*
|
|
1144
|
+
* @example
|
|
1145
|
+
* ```typescript
|
|
1146
|
+
* const doc = Document.fromText('This is the document content.', 'Notes');
|
|
1147
|
+
* ```
|
|
1148
|
+
*/
|
|
1149
|
+
static fromText(text2, title) {
|
|
1150
|
+
return new _Document(
|
|
1151
|
+
{ type: "text", data: text2 },
|
|
1152
|
+
"text/plain",
|
|
1153
|
+
title
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1156
|
+
/**
|
|
1157
|
+
* Creates a Document from an existing DocumentBlock.
|
|
1158
|
+
*
|
|
1159
|
+
* Useful for converting content blocks received from providers back
|
|
1160
|
+
* into Document instances for further processing.
|
|
1161
|
+
*
|
|
1162
|
+
* @param block - A DocumentBlock from message content
|
|
1163
|
+
* @returns A Document with the block's source and metadata
|
|
1164
|
+
*/
|
|
1165
|
+
static fromBlock(block) {
|
|
1166
|
+
return new _Document(
|
|
1167
|
+
block.source,
|
|
1168
|
+
block.mimeType,
|
|
1169
|
+
block.title
|
|
1170
|
+
);
|
|
1171
|
+
}
|
|
1172
|
+
};
|
|
1173
|
+
function detectMimeType(path) {
|
|
1174
|
+
const ext = path.split(".").pop()?.toLowerCase();
|
|
1175
|
+
switch (ext) {
|
|
1176
|
+
case "pdf":
|
|
1177
|
+
return "application/pdf";
|
|
1178
|
+
case "txt":
|
|
1179
|
+
case "text":
|
|
1180
|
+
case "md":
|
|
1181
|
+
case "markdown":
|
|
1182
|
+
return "text/plain";
|
|
1183
|
+
default:
|
|
1184
|
+
return "application/octet-stream";
|
|
1185
|
+
}
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
// src/core/media/Audio.ts
|
|
1189
|
+
var Audio = class _Audio {
|
|
1190
|
+
/** The audio data as raw bytes */
|
|
1191
|
+
data;
|
|
1192
|
+
/** MIME type of the audio (e.g., 'audio/mp3', 'audio/wav') */
|
|
1193
|
+
mimeType;
|
|
1194
|
+
/** Duration in seconds, if known */
|
|
1195
|
+
duration;
|
|
1196
|
+
constructor(data, mimeType, duration) {
|
|
1197
|
+
this.data = data;
|
|
1198
|
+
this.mimeType = mimeType;
|
|
1199
|
+
this.duration = duration;
|
|
1200
|
+
}
|
|
1201
|
+
/**
|
|
1202
|
+
* Gets the size of the audio data in bytes.
|
|
1203
|
+
*/
|
|
1204
|
+
get size() {
|
|
1205
|
+
return this.data.length;
|
|
1206
|
+
}
|
|
1207
|
+
/**
|
|
1208
|
+
* Converts the audio to a base64-encoded string.
|
|
1209
|
+
*
|
|
1210
|
+
* @returns The audio data as a base64 string
|
|
1211
|
+
*/
|
|
1212
|
+
toBase64() {
|
|
1213
|
+
return btoa(
|
|
1214
|
+
Array.from(this.data).map((b) => String.fromCharCode(b)).join("")
|
|
1215
|
+
);
|
|
1216
|
+
}
|
|
1217
|
+
/**
|
|
1218
|
+
* Converts the audio to a data URL suitable for embedding.
|
|
1219
|
+
*
|
|
1220
|
+
* @returns A data URL in the format `data:{mimeType};base64,{data}`
|
|
1221
|
+
*/
|
|
1222
|
+
toDataUrl() {
|
|
1223
|
+
const base64 = this.toBase64();
|
|
1224
|
+
return `data:${this.mimeType};base64,${base64}`;
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Gets the audio data as raw bytes.
|
|
1228
|
+
*
|
|
1229
|
+
* @returns The audio data as a Uint8Array
|
|
1230
|
+
*/
|
|
1231
|
+
toBytes() {
|
|
1232
|
+
return this.data;
|
|
1233
|
+
}
|
|
1234
|
+
/**
|
|
1235
|
+
* Converts this Audio to an AudioBlock for use in UPP messages.
|
|
1236
|
+
*
|
|
1237
|
+
* @returns An AudioBlock that can be included in message content arrays
|
|
1238
|
+
*/
|
|
1239
|
+
toBlock() {
|
|
1240
|
+
return {
|
|
1241
|
+
type: "audio",
|
|
1242
|
+
data: this.data,
|
|
1243
|
+
mimeType: this.mimeType,
|
|
1244
|
+
duration: this.duration
|
|
1245
|
+
};
|
|
1246
|
+
}
|
|
1247
|
+
/**
|
|
1248
|
+
* Creates an Audio by reading a file from disk.
|
|
1249
|
+
*
|
|
1250
|
+
* The file is read into memory as bytes. MIME type is automatically
|
|
1251
|
+
* detected from the file extension.
|
|
1252
|
+
*
|
|
1253
|
+
* @param path - Path to the audio file
|
|
1254
|
+
* @param duration - Optional duration in seconds
|
|
1255
|
+
* @returns Promise resolving to an Audio with the file contents
|
|
1256
|
+
*
|
|
1257
|
+
* @example
|
|
1258
|
+
* ```typescript
|
|
1259
|
+
* const audio = await Audio.fromPath('./recordings/interview.mp3');
|
|
1260
|
+
* ```
|
|
1261
|
+
*/
|
|
1262
|
+
static async fromPath(path, duration) {
|
|
1263
|
+
const file = Bun.file(path);
|
|
1264
|
+
const exists = await file.exists();
|
|
1265
|
+
if (!exists) {
|
|
1266
|
+
throw new Error(`Audio file not found at path: ${path}`);
|
|
1267
|
+
}
|
|
1268
|
+
let arrayBuffer;
|
|
1269
|
+
try {
|
|
1270
|
+
arrayBuffer = await file.arrayBuffer();
|
|
1271
|
+
} catch (error) {
|
|
1272
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1273
|
+
throw new Error(`Failed to read audio file at path: ${path}. ${message}`);
|
|
1274
|
+
}
|
|
1275
|
+
if (arrayBuffer.byteLength === 0) {
|
|
1276
|
+
throw new Error(`Audio file is empty at path: ${path}`);
|
|
1277
|
+
}
|
|
1278
|
+
const mimeType = detectMimeType2(path);
|
|
1279
|
+
return new _Audio(
|
|
1280
|
+
new Uint8Array(arrayBuffer),
|
|
1281
|
+
mimeType,
|
|
1282
|
+
duration
|
|
1283
|
+
);
|
|
1284
|
+
}
|
|
1285
|
+
/**
|
|
1286
|
+
* Creates an Audio from raw byte data.
|
|
1287
|
+
*
|
|
1288
|
+
* @param data - The audio data as a Uint8Array
|
|
1289
|
+
* @param mimeType - The MIME type of the audio
|
|
1290
|
+
* @param duration - Optional duration in seconds
|
|
1291
|
+
* @returns An Audio containing the byte data
|
|
1292
|
+
*
|
|
1293
|
+
* @example
|
|
1294
|
+
* ```typescript
|
|
1295
|
+
* const audio = Audio.fromBytes(wavData, 'audio/wav');
|
|
1296
|
+
* ```
|
|
1297
|
+
*/
|
|
1298
|
+
static fromBytes(data, mimeType, duration) {
|
|
1299
|
+
return new _Audio(data, mimeType, duration);
|
|
1300
|
+
}
|
|
1301
|
+
/**
|
|
1302
|
+
* Creates an Audio from a base64-encoded string.
|
|
1303
|
+
*
|
|
1304
|
+
* @param base64 - The base64-encoded audio data (without data URL prefix)
|
|
1305
|
+
* @param mimeType - The MIME type of the audio
|
|
1306
|
+
* @param duration - Optional duration in seconds
|
|
1307
|
+
* @returns An Audio containing the decoded data
|
|
1308
|
+
*
|
|
1309
|
+
* @example
|
|
1310
|
+
* ```typescript
|
|
1311
|
+
* const audio = Audio.fromBase64(base64String, 'audio/mp3');
|
|
1312
|
+
* ```
|
|
1313
|
+
*/
|
|
1314
|
+
static fromBase64(base64, mimeType, duration) {
|
|
1315
|
+
const binaryString = atob(base64);
|
|
1316
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
1317
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
1318
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
1319
|
+
}
|
|
1320
|
+
return new _Audio(bytes, mimeType, duration);
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
* Creates an Audio from an existing AudioBlock.
|
|
1324
|
+
*
|
|
1325
|
+
* Useful for converting content blocks received from providers back
|
|
1326
|
+
* into Audio instances for further processing.
|
|
1327
|
+
*
|
|
1328
|
+
* @param block - An AudioBlock from message content
|
|
1329
|
+
* @returns An Audio with the block's data and metadata
|
|
1330
|
+
*/
|
|
1331
|
+
static fromBlock(block) {
|
|
1332
|
+
return new _Audio(
|
|
1333
|
+
block.data,
|
|
1334
|
+
block.mimeType,
|
|
1335
|
+
block.duration
|
|
1336
|
+
);
|
|
1337
|
+
}
|
|
1338
|
+
};
|
|
1339
|
+
function detectMimeType2(path) {
|
|
1340
|
+
const ext = path.split(".").pop()?.toLowerCase();
|
|
1341
|
+
switch (ext) {
|
|
1342
|
+
case "mp3":
|
|
1343
|
+
return "audio/mp3";
|
|
1344
|
+
case "wav":
|
|
1345
|
+
return "audio/wav";
|
|
1346
|
+
case "ogg":
|
|
1347
|
+
case "oga":
|
|
1348
|
+
return "audio/ogg";
|
|
1349
|
+
case "flac":
|
|
1350
|
+
return "audio/flac";
|
|
1351
|
+
case "aac":
|
|
1352
|
+
return "audio/aac";
|
|
1353
|
+
case "m4a":
|
|
1354
|
+
return "audio/mp4";
|
|
1355
|
+
case "webm":
|
|
1356
|
+
return "audio/webm";
|
|
1357
|
+
case "aiff":
|
|
1358
|
+
case "aif":
|
|
1359
|
+
return "audio/aiff";
|
|
1360
|
+
default:
|
|
1361
|
+
return "application/octet-stream";
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
|
|
1365
|
+
// src/core/media/Video.ts
|
|
1366
|
+
var Video = class _Video {
|
|
1367
|
+
/** The video data as raw bytes */
|
|
1368
|
+
data;
|
|
1369
|
+
/** MIME type of the video (e.g., 'video/mp4', 'video/webm') */
|
|
1370
|
+
mimeType;
|
|
1371
|
+
/** Duration in seconds, if known */
|
|
1372
|
+
duration;
|
|
1373
|
+
/** Video width in pixels, if known */
|
|
1374
|
+
width;
|
|
1375
|
+
/** Video height in pixels, if known */
|
|
1376
|
+
height;
|
|
1377
|
+
constructor(data, mimeType, options) {
|
|
1378
|
+
this.data = data;
|
|
1379
|
+
this.mimeType = mimeType;
|
|
1380
|
+
this.duration = options?.duration;
|
|
1381
|
+
this.width = options?.width;
|
|
1382
|
+
this.height = options?.height;
|
|
1383
|
+
}
|
|
1384
|
+
/**
|
|
1385
|
+
* Gets the size of the video data in bytes.
|
|
1386
|
+
*/
|
|
1387
|
+
get size() {
|
|
1388
|
+
return this.data.length;
|
|
1389
|
+
}
|
|
1390
|
+
/**
|
|
1391
|
+
* Converts the video to a base64-encoded string.
|
|
1392
|
+
*
|
|
1393
|
+
* @returns The video data as a base64 string
|
|
1394
|
+
*/
|
|
1395
|
+
toBase64() {
|
|
1396
|
+
return btoa(
|
|
1397
|
+
Array.from(this.data).map((b) => String.fromCharCode(b)).join("")
|
|
1398
|
+
);
|
|
1399
|
+
}
|
|
1400
|
+
/**
|
|
1401
|
+
* Converts the video to a data URL suitable for embedding.
|
|
1402
|
+
*
|
|
1403
|
+
* @returns A data URL in the format `data:{mimeType};base64,{data}`
|
|
1404
|
+
*/
|
|
1405
|
+
toDataUrl() {
|
|
1406
|
+
const base64 = this.toBase64();
|
|
1407
|
+
return `data:${this.mimeType};base64,${base64}`;
|
|
1408
|
+
}
|
|
1409
|
+
/**
|
|
1410
|
+
* Gets the video data as raw bytes.
|
|
1411
|
+
*
|
|
1412
|
+
* @returns The video data as a Uint8Array
|
|
1413
|
+
*/
|
|
1414
|
+
toBytes() {
|
|
1415
|
+
return this.data;
|
|
1416
|
+
}
|
|
1417
|
+
/**
|
|
1418
|
+
* Converts this Video to a VideoBlock for use in UPP messages.
|
|
1419
|
+
*
|
|
1420
|
+
* @returns A VideoBlock that can be included in message content arrays
|
|
1421
|
+
*/
|
|
1422
|
+
toBlock() {
|
|
1423
|
+
return {
|
|
1424
|
+
type: "video",
|
|
1425
|
+
data: this.data,
|
|
1426
|
+
mimeType: this.mimeType,
|
|
1427
|
+
duration: this.duration,
|
|
1428
|
+
width: this.width,
|
|
1429
|
+
height: this.height
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1432
|
+
/**
|
|
1433
|
+
* Creates a Video by reading a file from disk.
|
|
1434
|
+
*
|
|
1435
|
+
* The file is read into memory as bytes. MIME type is automatically
|
|
1436
|
+
* detected from the file extension.
|
|
1437
|
+
*
|
|
1438
|
+
* @param path - Path to the video file
|
|
1439
|
+
* @param options - Optional metadata (duration, width, height)
|
|
1440
|
+
* @returns Promise resolving to a Video with the file contents
|
|
1441
|
+
*
|
|
1442
|
+
* @example
|
|
1443
|
+
* ```typescript
|
|
1444
|
+
* const video = await Video.fromPath('./clips/demo.mp4');
|
|
1445
|
+
* const videoWithMeta = await Video.fromPath('./clip.mp4', { duration: 30, width: 1920, height: 1080 });
|
|
1446
|
+
* ```
|
|
1447
|
+
*/
|
|
1448
|
+
static async fromPath(path, options) {
|
|
1449
|
+
const file = Bun.file(path);
|
|
1450
|
+
const exists = await file.exists();
|
|
1451
|
+
if (!exists) {
|
|
1452
|
+
throw new Error(`Video file not found at path: ${path}`);
|
|
1453
|
+
}
|
|
1454
|
+
let arrayBuffer;
|
|
1455
|
+
try {
|
|
1456
|
+
arrayBuffer = await file.arrayBuffer();
|
|
1457
|
+
} catch (error) {
|
|
1458
|
+
const message = error instanceof Error ? error.message : "Unknown error";
|
|
1459
|
+
throw new Error(`Failed to read video file at path: ${path}. ${message}`);
|
|
1460
|
+
}
|
|
1461
|
+
if (arrayBuffer.byteLength === 0) {
|
|
1462
|
+
throw new Error(`Video file is empty at path: ${path}`);
|
|
1463
|
+
}
|
|
1464
|
+
const mimeType = detectMimeType3(path);
|
|
1465
|
+
return new _Video(
|
|
1466
|
+
new Uint8Array(arrayBuffer),
|
|
1467
|
+
mimeType,
|
|
1468
|
+
options
|
|
1469
|
+
);
|
|
1470
|
+
}
|
|
1471
|
+
/**
|
|
1472
|
+
* Creates a Video from raw byte data.
|
|
1473
|
+
*
|
|
1474
|
+
* @param data - The video data as a Uint8Array
|
|
1475
|
+
* @param mimeType - The MIME type of the video
|
|
1476
|
+
* @param options - Optional metadata (duration, width, height)
|
|
1477
|
+
* @returns A Video containing the byte data
|
|
1478
|
+
*
|
|
1479
|
+
* @example
|
|
1480
|
+
* ```typescript
|
|
1481
|
+
* const video = Video.fromBytes(mp4Data, 'video/mp4');
|
|
1482
|
+
* const videoWithMeta = Video.fromBytes(data, 'video/mp4', { duration: 60 });
|
|
1483
|
+
* ```
|
|
1484
|
+
*/
|
|
1485
|
+
static fromBytes(data, mimeType, options) {
|
|
1486
|
+
return new _Video(data, mimeType, options);
|
|
1487
|
+
}
|
|
1488
|
+
/**
|
|
1489
|
+
* Creates a Video from a base64-encoded string.
|
|
1490
|
+
*
|
|
1491
|
+
* @param base64 - The base64-encoded video data (without data URL prefix)
|
|
1492
|
+
* @param mimeType - The MIME type of the video
|
|
1493
|
+
* @param options - Optional metadata (duration, width, height)
|
|
1494
|
+
* @returns A Video containing the decoded data
|
|
1495
|
+
*
|
|
1496
|
+
* @example
|
|
1497
|
+
* ```typescript
|
|
1498
|
+
* const video = Video.fromBase64(base64String, 'video/mp4');
|
|
1499
|
+
* ```
|
|
1500
|
+
*/
|
|
1501
|
+
static fromBase64(base64, mimeType, options) {
|
|
1502
|
+
const binaryString = atob(base64);
|
|
1503
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
1504
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
1505
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
1506
|
+
}
|
|
1507
|
+
return new _Video(bytes, mimeType, options);
|
|
1508
|
+
}
|
|
1509
|
+
/**
|
|
1510
|
+
* Creates a Video from an existing VideoBlock.
|
|
1511
|
+
*
|
|
1512
|
+
* Useful for converting content blocks received from providers back
|
|
1513
|
+
* into Video instances for further processing.
|
|
1514
|
+
*
|
|
1515
|
+
* @param block - A VideoBlock from message content
|
|
1516
|
+
* @returns A Video with the block's data and metadata
|
|
1517
|
+
*/
|
|
1518
|
+
static fromBlock(block) {
|
|
1519
|
+
return new _Video(
|
|
1520
|
+
block.data,
|
|
1521
|
+
block.mimeType,
|
|
1522
|
+
{
|
|
1523
|
+
duration: block.duration,
|
|
1524
|
+
width: block.width,
|
|
1525
|
+
height: block.height
|
|
1526
|
+
}
|
|
1527
|
+
);
|
|
1528
|
+
}
|
|
1529
|
+
};
|
|
1530
|
+
function detectMimeType3(path) {
|
|
1531
|
+
const ext = path.split(".").pop()?.toLowerCase();
|
|
1532
|
+
switch (ext) {
|
|
1533
|
+
case "mp4":
|
|
1534
|
+
case "m4v":
|
|
1535
|
+
return "video/mp4";
|
|
1536
|
+
case "webm":
|
|
1537
|
+
return "video/webm";
|
|
1538
|
+
case "ogv":
|
|
1539
|
+
case "ogg":
|
|
1540
|
+
return "video/ogg";
|
|
1541
|
+
case "mov":
|
|
1542
|
+
return "video/quicktime";
|
|
1543
|
+
case "avi":
|
|
1544
|
+
return "video/x-msvideo";
|
|
1545
|
+
case "mpeg":
|
|
1546
|
+
case "mpg":
|
|
1547
|
+
return "video/mpeg";
|
|
1548
|
+
case "wmv":
|
|
1549
|
+
return "video/x-ms-wmv";
|
|
1550
|
+
case "3gp":
|
|
1551
|
+
case "3gpp":
|
|
1552
|
+
return "video/3gpp";
|
|
1553
|
+
case "flv":
|
|
1554
|
+
return "video/x-flv";
|
|
1555
|
+
default:
|
|
1556
|
+
return "application/octet-stream";
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
|
|
941
1560
|
// src/types/thread.ts
|
|
942
1561
|
var Thread = class _Thread {
|
|
943
1562
|
/** Unique thread identifier */
|
|
@@ -1202,7 +1821,10 @@ var ai = {
|
|
|
1202
1821
|
};
|
|
1203
1822
|
export {
|
|
1204
1823
|
AssistantMessage,
|
|
1824
|
+
Audio,
|
|
1205
1825
|
ContentBlockType,
|
|
1826
|
+
Document,
|
|
1827
|
+
DocumentSourceType,
|
|
1206
1828
|
DynamicKey,
|
|
1207
1829
|
ErrorCode,
|
|
1208
1830
|
ExponentialBackoff,
|
|
@@ -1221,6 +1843,7 @@ export {
|
|
|
1221
1843
|
ToolResultMessage,
|
|
1222
1844
|
UPPError,
|
|
1223
1845
|
UserMessage,
|
|
1846
|
+
Video,
|
|
1224
1847
|
WeightedKeys,
|
|
1225
1848
|
aggregateUsage,
|
|
1226
1849
|
ai,
|
|
@@ -1235,6 +1858,7 @@ export {
|
|
|
1235
1858
|
isAssistantMessage,
|
|
1236
1859
|
isAudioBlock,
|
|
1237
1860
|
isBinaryBlock,
|
|
1861
|
+
isDocumentBlock,
|
|
1238
1862
|
isImageBlock,
|
|
1239
1863
|
isReasoningBlock,
|
|
1240
1864
|
isTextBlock,
|