@heyputer/puter.js 2.0.1 → 2.0.3
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/puter.js +4 -0
- package/package.json +4 -4
- package/src/bg.png +0 -0
- package/src/bg.webp +0 -0
- package/src/index.js +165 -165
- package/src/lib/APICallLogger.js +110 -0
- package/src/lib/EventListener.js +51 -0
- package/src/lib/RequestError.js +6 -0
- package/src/lib/filesystem/APIFS.js +73 -0
- package/src/lib/filesystem/CacheFS.js +243 -0
- package/src/lib/filesystem/PostMessageFS.js +40 -0
- package/src/lib/filesystem/definitions.js +39 -0
- package/src/lib/path.js +509 -0
- package/src/lib/polyfills/localStorage.js +92 -0
- package/src/lib/polyfills/xhrshim.js +233 -0
- package/src/lib/socket.io/socket.io.esm.min.js +7 -0
- package/src/lib/socket.io/socket.io.esm.min.js.map +1 -0
- package/src/lib/socket.io/socket.io.js +4385 -0
- package/src/lib/socket.io/socket.io.js.map +1 -0
- package/src/lib/socket.io/socket.io.min.js +7 -0
- package/src/lib/socket.io/socket.io.min.js.map +1 -0
- package/src/lib/socket.io/socket.io.msgpack.min.js +7 -0
- package/src/lib/socket.io/socket.io.msgpack.min.js.map +1 -0
- package/src/lib/utils.js +620 -0
- package/src/lib/xdrpc.js +104 -0
- package/src/modules/AI.js +680 -0
- package/src/modules/Apps.js +215 -0
- package/src/modules/Auth.js +171 -0
- package/src/modules/Debug.js +39 -0
- package/src/modules/Drivers.js +278 -0
- package/src/modules/FSItem.js +139 -0
- package/src/modules/FileSystem/index.js +187 -0
- package/src/modules/FileSystem/operations/copy.js +64 -0
- package/src/modules/FileSystem/operations/deleteFSEntry.js +59 -0
- package/src/modules/FileSystem/operations/getReadUrl.js +42 -0
- package/src/modules/FileSystem/operations/mkdir.js +62 -0
- package/src/modules/FileSystem/operations/move.js +75 -0
- package/src/modules/FileSystem/operations/read.js +46 -0
- package/src/modules/FileSystem/operations/readdir.js +102 -0
- package/src/modules/FileSystem/operations/rename.js +58 -0
- package/src/modules/FileSystem/operations/sign.js +103 -0
- package/src/modules/FileSystem/operations/space.js +40 -0
- package/src/modules/FileSystem/operations/stat.js +95 -0
- package/src/modules/FileSystem/operations/symlink.js +55 -0
- package/src/modules/FileSystem/operations/upload.js +440 -0
- package/src/modules/FileSystem/operations/write.js +65 -0
- package/src/modules/FileSystem/utils/getAbsolutePathForApp.js +21 -0
- package/src/modules/Hosting.js +138 -0
- package/src/modules/KV.js +301 -0
- package/src/modules/OS.js +95 -0
- package/src/modules/Perms.js +109 -0
- package/src/modules/PuterDialog.js +481 -0
- package/src/modules/Threads.js +75 -0
- package/src/modules/UI.js +1555 -0
- package/src/modules/Util.js +38 -0
- package/src/modules/Workers.js +120 -0
- package/src/modules/networking/PSocket.js +87 -0
- package/src/modules/networking/PTLS.js +100 -0
- package/src/modules/networking/PWispHandler.js +89 -0
- package/src/modules/networking/parsers.js +157 -0
- package/src/modules/networking/requests.js +282 -0
- package/src/safeLoadPuter.cjs +29 -0
- package/src/services/APIAccess.js +46 -0
- package/src/services/FSRelay.js +20 -0
- package/src/services/Filesystem.js +122 -0
- package/src/services/NoPuterYet.js +20 -0
- package/src/services/XDIncoming.js +44 -0
- package/index.d.ts +0 -479
|
@@ -0,0 +1,680 @@
|
|
|
1
|
+
import * as utils from '../lib/utils.js';
|
|
2
|
+
|
|
3
|
+
class AI{
|
|
4
|
+
/**
|
|
5
|
+
* Creates a new instance with the given authentication token, API origin, and app ID,
|
|
6
|
+
*
|
|
7
|
+
* @class
|
|
8
|
+
* @param {string} authToken - Token used to authenticate the user.
|
|
9
|
+
* @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
|
|
10
|
+
* @param {string} appID - ID of the app to use.
|
|
11
|
+
*/
|
|
12
|
+
constructor (context) {
|
|
13
|
+
this.authToken = context.authToken;
|
|
14
|
+
this.APIOrigin = context.APIOrigin;
|
|
15
|
+
this.appID = context.appID;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Sets a new authentication token and resets the socket connection with the updated token, if applicable.
|
|
20
|
+
*
|
|
21
|
+
* @param {string} authToken - The new authentication token.
|
|
22
|
+
* @memberof [AI]
|
|
23
|
+
* @returns {void}
|
|
24
|
+
*/
|
|
25
|
+
setAuthToken (authToken) {
|
|
26
|
+
this.authToken = authToken;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Sets the API origin.
|
|
31
|
+
*
|
|
32
|
+
* @param {string} APIOrigin - The new API origin.
|
|
33
|
+
* @memberof [AI]
|
|
34
|
+
* @returns {void}
|
|
35
|
+
*/
|
|
36
|
+
setAPIOrigin (APIOrigin) {
|
|
37
|
+
this.APIOrigin = APIOrigin;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Returns a list of available AI models.
|
|
42
|
+
* @param {string} provider - The provider to filter the models returned.
|
|
43
|
+
* @returns {Object} Object containing lists of available models by provider
|
|
44
|
+
*/
|
|
45
|
+
async listModels(provider) {
|
|
46
|
+
const modelsByProvider = {};
|
|
47
|
+
|
|
48
|
+
const models = await puter.drivers.call('puter-chat-completion','ai-chat','models');
|
|
49
|
+
|
|
50
|
+
if (!models || !models.result || !Array.isArray(models.result)) {
|
|
51
|
+
return modelsByProvider;
|
|
52
|
+
}
|
|
53
|
+
models.result.forEach(item => {
|
|
54
|
+
if (!item.provider || !item.id) return;
|
|
55
|
+
if (provider && item.provider !== provider) return;
|
|
56
|
+
if (!modelsByProvider[item.provider]) modelsByProvider[item.provider] = [];
|
|
57
|
+
modelsByProvider[item.provider].push(item.id);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return modelsByProvider;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Returns a list of all available AI providers
|
|
65
|
+
* @returns {Array} Array containing providers
|
|
66
|
+
*/
|
|
67
|
+
async listModelProviders() {
|
|
68
|
+
let providers = [];
|
|
69
|
+
const models = await puter.drivers.call('puter-chat-completion','ai-chat','models');
|
|
70
|
+
|
|
71
|
+
if (!models || !models.result || !Array.isArray(models.result)) return providers; // if models is invalid then return empty array
|
|
72
|
+
providers = new Set(); // Use a Set to store unique providers
|
|
73
|
+
models.result.forEach(item => {
|
|
74
|
+
if (item.provider) providers.add(item.provider);
|
|
75
|
+
});
|
|
76
|
+
providers = Array.from(providers); // Convert Set to an array
|
|
77
|
+
return providers;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
img2txt = async (...args) => {
|
|
81
|
+
let MAX_INPUT_SIZE = 10 * 1024 * 1024;
|
|
82
|
+
let options = {};
|
|
83
|
+
let testMode = false;
|
|
84
|
+
|
|
85
|
+
// Check that the argument is not undefined or null
|
|
86
|
+
if(!args){
|
|
87
|
+
throw({message: 'Arguments are required', code: 'arguments_required'});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// if argument is string transform it to the object that the API expects
|
|
91
|
+
if (typeof args[0] === 'string' || args[0] instanceof Blob) {
|
|
92
|
+
options.source = args[0];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// if input is a blob, transform it to a data URI
|
|
96
|
+
if (args[0].source instanceof Blob) {
|
|
97
|
+
options.source = await utils.blobToDataUri(args[0].source);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// check input size
|
|
101
|
+
if (options.source.length > this.MAX_INPUT_SIZE) {
|
|
102
|
+
throw { message: 'Input size cannot be larger than ' + MAX_INPUT_SIZE, code: 'input_too_large' };
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// determine if test mode is enabled
|
|
106
|
+
if (typeof args[1] === 'boolean' && args[1] === true ||
|
|
107
|
+
typeof args[2] === 'boolean' && args[2] === true ||
|
|
108
|
+
typeof args[3] === 'boolean' && args[3] === true) {
|
|
109
|
+
testMode = true;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return await utils.make_driver_method(['source'], 'puter-ocr', 'aws-textract', 'recognize', {
|
|
113
|
+
test_mode: testMode ?? false,
|
|
114
|
+
transform: async (result) => {
|
|
115
|
+
let str = '';
|
|
116
|
+
for (let i = 0; i < result?.blocks?.length; i++) {
|
|
117
|
+
if("text/textract:LINE" === result.blocks[i].type)
|
|
118
|
+
str += result.blocks[i].text + "\n";
|
|
119
|
+
}
|
|
120
|
+
return str;
|
|
121
|
+
}
|
|
122
|
+
}).call(this, options);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
txt2speech = async (...args) => {
|
|
126
|
+
let MAX_INPUT_SIZE = 3000;
|
|
127
|
+
let options = {};
|
|
128
|
+
let testMode = false;
|
|
129
|
+
|
|
130
|
+
if(!args){
|
|
131
|
+
throw({message: 'Arguments are required', code: 'arguments_required'});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Accept arguments in the following formats:
|
|
135
|
+
// 1. Shorthand API
|
|
136
|
+
// puter.ai.txt2speech("Hello world")
|
|
137
|
+
// 2. Verbose API
|
|
138
|
+
// puter.ai.txt2speech("Hello world", {
|
|
139
|
+
// voice: "Joanna",
|
|
140
|
+
// engine: "neural",
|
|
141
|
+
// language: "en-US"
|
|
142
|
+
// })
|
|
143
|
+
// 3. Positional arguments (Legacy)
|
|
144
|
+
// puter.ai.txt2speech(<text>, <language>, <voice>, <engine>)
|
|
145
|
+
// e.g:
|
|
146
|
+
// puter.ai.txt2speech("Hello world", "en-US")
|
|
147
|
+
// puter.ai.txt2speech("Hello world", "en-US", "Joanna")
|
|
148
|
+
// puter.ai.txt2speech("Hello world", "en-US", "Joanna", "neural")
|
|
149
|
+
//
|
|
150
|
+
// Undefined parameters will be set to default values:
|
|
151
|
+
// - voice: "Joanna"
|
|
152
|
+
// - engine: "standard"
|
|
153
|
+
// - language: "en-US"
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
if (typeof args[0] === 'string') {
|
|
157
|
+
options = { text: args[0] };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (args[1] && typeof args[1] === 'object' && !Array.isArray(args[1])) {
|
|
161
|
+
// for verbose object API
|
|
162
|
+
Object.assign(options, args[1]);
|
|
163
|
+
} else if (args[1] && typeof args[1] === 'string') {
|
|
164
|
+
// for legacy positional-arguments API
|
|
165
|
+
//
|
|
166
|
+
// puter.ai.txt2speech(<text>, <language>, <voice>, <engine>)
|
|
167
|
+
options.language = args[1];
|
|
168
|
+
|
|
169
|
+
if (args[2] && typeof args[2] === 'string') {
|
|
170
|
+
options.voice = args[2];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (args[3] && typeof args[3] === 'string') {
|
|
174
|
+
options.engine = args[3];
|
|
175
|
+
}
|
|
176
|
+
} else if (args[1] && typeof args[1] !== 'boolean') {
|
|
177
|
+
// If second argument is not an object, string, or boolean, throw an error
|
|
178
|
+
throw { message: 'Second argument must be an options object or language string. Use: txt2speech("text", { voice: "name", engine: "type", language: "code" }) or txt2speech("text", "language", "voice", "engine")', code: 'invalid_arguments' };
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Validate required text parameter
|
|
182
|
+
if (!options.text) {
|
|
183
|
+
throw { message: 'Text parameter is required', code: 'text_required' };
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Validate engine if provided
|
|
187
|
+
if (options.engine) {
|
|
188
|
+
const validEngines = ['standard', 'neural', 'long-form', 'generative'];
|
|
189
|
+
if (!validEngines.includes(options.engine)) {
|
|
190
|
+
throw { message: 'Invalid engine. Must be one of: ' + validEngines.join(', '), code: 'invalid_engine' };
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Set default values if not provided
|
|
195
|
+
if (!options.voice) {
|
|
196
|
+
options.voice = 'Joanna';
|
|
197
|
+
}
|
|
198
|
+
if (!options.engine) {
|
|
199
|
+
options.engine = 'standard';
|
|
200
|
+
}
|
|
201
|
+
if (!options.language) {
|
|
202
|
+
options.language = 'en-US';
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// check input size
|
|
206
|
+
if (options.text.length > MAX_INPUT_SIZE) {
|
|
207
|
+
throw { message: 'Input size cannot be larger than ' + MAX_INPUT_SIZE, code: 'input_too_large' };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// determine if test mode is enabled (check all arguments for boolean true)
|
|
211
|
+
for (let i = 0; i < args.length; i++) {
|
|
212
|
+
if (typeof args[i] === 'boolean' && args[i] === true) {
|
|
213
|
+
testMode = true;
|
|
214
|
+
break;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return await utils.make_driver_method(['source'], 'puter-tts', 'aws-polly', 'synthesize', {
|
|
219
|
+
responseType: 'blob',
|
|
220
|
+
test_mode: testMode ?? false,
|
|
221
|
+
transform: async (result) => {
|
|
222
|
+
const url = await utils.blob_to_url(result);
|
|
223
|
+
const audio = new Audio(url);
|
|
224
|
+
audio.toString = () => url;
|
|
225
|
+
audio.valueOf = () => url;
|
|
226
|
+
return audio;
|
|
227
|
+
}
|
|
228
|
+
}).call(this, options);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// Add new methods for TTS engine management
|
|
232
|
+
txt2speech = Object.assign(this.txt2speech, {
|
|
233
|
+
/**
|
|
234
|
+
* List available TTS engines with pricing information
|
|
235
|
+
* @returns {Promise<Array>} Array of available engines
|
|
236
|
+
*/
|
|
237
|
+
listEngines: async () => {
|
|
238
|
+
return await utils.make_driver_method(['source'], 'puter-tts', 'aws-polly', 'list_engines', {
|
|
239
|
+
responseType: 'text',
|
|
240
|
+
}).call(this, {});
|
|
241
|
+
},
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* List all available voices, optionally filtered by engine
|
|
245
|
+
* @param {string} [engine] - Optional engine filter
|
|
246
|
+
* @returns {Promise<Array>} Array of available voices
|
|
247
|
+
*/
|
|
248
|
+
listVoices: async (engine) => {
|
|
249
|
+
const params = {};
|
|
250
|
+
if (engine) {
|
|
251
|
+
params.engine = engine;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return utils.make_driver_method(['source'], 'puter-tts', 'aws-polly', 'list_voices', {
|
|
255
|
+
responseType: 'text',
|
|
256
|
+
}).call(this, params);
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
// accepts either a string or an array of message objects
|
|
262
|
+
// if string, it's treated as the prompt which is a shorthand for { messages: [{ content: prompt }] }
|
|
263
|
+
// if object, it's treated as the full argument object that the API expects
|
|
264
|
+
chat = async (...args) => {
|
|
265
|
+
// requestParams: parameters that will be sent to the backend driver
|
|
266
|
+
let requestParams = {};
|
|
267
|
+
// userParams: parameters provided by the user in the function call
|
|
268
|
+
let userParams = {};
|
|
269
|
+
let testMode = false;
|
|
270
|
+
|
|
271
|
+
// default driver is openai-completion
|
|
272
|
+
let driver = 'openai-completion';
|
|
273
|
+
|
|
274
|
+
// Check that the argument is not undefined or null
|
|
275
|
+
if(!args){
|
|
276
|
+
throw({message: 'Arguments are required', code: 'arguments_required'});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// ai.chat(prompt)
|
|
280
|
+
if(typeof args[0] === 'string'){
|
|
281
|
+
requestParams = { messages: [{ content: args[0] }] };
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// ai.chat(prompt, testMode)
|
|
285
|
+
if (typeof args[0] === 'string' && (!args[1] || typeof args[1] === 'boolean')) {
|
|
286
|
+
requestParams = { messages: [{ content: args[0] }] };
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ai.chat(prompt, imageURL/File)
|
|
290
|
+
// ai.chat(prompt, imageURL/File, testMode)
|
|
291
|
+
else if (typeof args[0] === 'string' && (typeof args[1] === 'string' || args[1] instanceof File)) {
|
|
292
|
+
// if imageURL is a File, transform it to a data URI
|
|
293
|
+
if(args[1] instanceof File){
|
|
294
|
+
args[1] = await utils.blobToDataUri(args[1]);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// parse args[1] as an image_url object
|
|
298
|
+
requestParams = {
|
|
299
|
+
vision: true,
|
|
300
|
+
messages: [
|
|
301
|
+
{
|
|
302
|
+
content: [
|
|
303
|
+
args[0],
|
|
304
|
+
{
|
|
305
|
+
image_url: {
|
|
306
|
+
url: args[1]
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
],
|
|
310
|
+
}
|
|
311
|
+
]
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
// chat(prompt, [imageURLs])
|
|
315
|
+
else if (typeof args[0] === 'string' && Array.isArray(args[1])) {
|
|
316
|
+
// parse args[1] as an array of image_url objects
|
|
317
|
+
for (let i = 0; i < args[1].length; i++) {
|
|
318
|
+
args[1][i] = { image_url: { url: args[1][i] } };
|
|
319
|
+
}
|
|
320
|
+
requestParams = {
|
|
321
|
+
vision: true,
|
|
322
|
+
messages: [
|
|
323
|
+
{
|
|
324
|
+
content: [
|
|
325
|
+
args[0],
|
|
326
|
+
...args[1]
|
|
327
|
+
],
|
|
328
|
+
}
|
|
329
|
+
]
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
// chat([messages])
|
|
333
|
+
else if (Array.isArray(args[0])) {
|
|
334
|
+
requestParams = { messages: args[0] };
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// determine if testMode is enabled
|
|
338
|
+
if (typeof args[1] === 'boolean' && args[1] === true ||
|
|
339
|
+
typeof args[2] === 'boolean' && args[2] === true ||
|
|
340
|
+
typeof args[3] === 'boolean' && args[3] === true) {
|
|
341
|
+
testMode = true;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// if any of the args is an object, assume it's the user parameters object
|
|
345
|
+
const is_object = v => {
|
|
346
|
+
return typeof v === 'object' &&
|
|
347
|
+
!Array.isArray(v) &&
|
|
348
|
+
v !== null;
|
|
349
|
+
};
|
|
350
|
+
for (let i = 0; i < args.length; i++) {
|
|
351
|
+
if (is_object(args[i])) {
|
|
352
|
+
userParams = args[i];
|
|
353
|
+
break;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
|
|
358
|
+
// Copy relevant parameters from userParams to requestParams
|
|
359
|
+
if (userParams.model) {
|
|
360
|
+
requestParams.model = userParams.model;
|
|
361
|
+
}
|
|
362
|
+
if (userParams.temperature) {
|
|
363
|
+
requestParams.temperature = userParams.temperature;
|
|
364
|
+
}
|
|
365
|
+
if (userParams.max_tokens) {
|
|
366
|
+
requestParams.max_tokens = userParams.max_tokens;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// convert undefined to empty string so that .startsWith works
|
|
370
|
+
requestParams.model = requestParams.model ?? '';
|
|
371
|
+
|
|
372
|
+
// If model starts with "anthropic/", remove it
|
|
373
|
+
// later on we should standardize the model names to [vendor]/[model]
|
|
374
|
+
// for example: "claude-3-5-sonnet" should become "anthropic/claude-3-5-sonnet"
|
|
375
|
+
// but for now, we want to keep the old behavior
|
|
376
|
+
// so we remove the "anthropic/" prefix if it exists
|
|
377
|
+
if (requestParams.model && requestParams.model.startsWith('anthropic/')) {
|
|
378
|
+
requestParams.model = requestParams.model.replace('anthropic/', '');
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// convert to the correct model name if necessary
|
|
382
|
+
if( requestParams.model === 'claude-3-5-sonnet'){
|
|
383
|
+
requestParams.model = 'claude-3-5-sonnet-latest';
|
|
384
|
+
}
|
|
385
|
+
if( requestParams.model === 'claude-3-7-sonnet' || requestParams.model === 'claude'){
|
|
386
|
+
requestParams.model = 'claude-3-7-sonnet-latest';
|
|
387
|
+
}
|
|
388
|
+
if( requestParams.model === 'claude-sonnet-4' || requestParams.model === 'claude-sonnet-4-latest'){
|
|
389
|
+
requestParams.model = 'claude-sonnet-4-20250514';
|
|
390
|
+
}
|
|
391
|
+
if( requestParams.model === 'claude-opus-4' || requestParams.model === 'claude-opus-4-latest') {
|
|
392
|
+
requestParams.model = 'claude-opus-4-20250514';
|
|
393
|
+
}
|
|
394
|
+
if ( requestParams.model === 'mistral' ) {
|
|
395
|
+
requestParams.model = 'mistral-large-latest';
|
|
396
|
+
}
|
|
397
|
+
if ( requestParams.model === 'groq' ) {
|
|
398
|
+
requestParams.model = 'llama3-8b-8192';
|
|
399
|
+
}
|
|
400
|
+
if ( requestParams.model === 'deepseek' ) {
|
|
401
|
+
requestParams.model = 'deepseek-chat';
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
// o1-mini to openrouter:openai/o1-mini
|
|
405
|
+
if ( requestParams.model === 'o1-mini') {
|
|
406
|
+
requestParams.model = 'openrouter:openai/o1-mini';
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// if a model is prepended with "openai/", remove it
|
|
410
|
+
if (requestParams.model && requestParams.model.startsWith('openai/')) {
|
|
411
|
+
requestParams.model = requestParams.model.replace('openai/', '');
|
|
412
|
+
driver = 'openai-completion';
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// if model starts with:
|
|
416
|
+
// agentica-org/
|
|
417
|
+
// ai21/
|
|
418
|
+
// aion-labs/
|
|
419
|
+
// alfredpros/
|
|
420
|
+
// alpindale/
|
|
421
|
+
// amazon/
|
|
422
|
+
// anthracite-org/
|
|
423
|
+
// arcee-ai/
|
|
424
|
+
// arliai/
|
|
425
|
+
// baidu/
|
|
426
|
+
// bytedance/
|
|
427
|
+
// cognitivecomputations/
|
|
428
|
+
// cohere/
|
|
429
|
+
// deepseek/
|
|
430
|
+
// eleutherai/
|
|
431
|
+
// google/
|
|
432
|
+
// gryphe/
|
|
433
|
+
// inception/
|
|
434
|
+
// infermatic/
|
|
435
|
+
// liquid/
|
|
436
|
+
// mancer/
|
|
437
|
+
// meta-llama/
|
|
438
|
+
// microsoft/
|
|
439
|
+
// minimax/
|
|
440
|
+
// mistralai/
|
|
441
|
+
// moonshotai/
|
|
442
|
+
// morph/
|
|
443
|
+
// neversleep/
|
|
444
|
+
// nousresearch/
|
|
445
|
+
// nvidia/
|
|
446
|
+
// openrouter/
|
|
447
|
+
// perplexity/
|
|
448
|
+
// pygmalionai/
|
|
449
|
+
// qwen/
|
|
450
|
+
// raifle/
|
|
451
|
+
// rekaai/
|
|
452
|
+
// sao10k/
|
|
453
|
+
// sarvamai/
|
|
454
|
+
// scb10x/
|
|
455
|
+
// shisa-ai/
|
|
456
|
+
// sophosympatheia/
|
|
457
|
+
// switchpoint/
|
|
458
|
+
// tencent/
|
|
459
|
+
// thedrummer/
|
|
460
|
+
// thudm/
|
|
461
|
+
// tngtech/
|
|
462
|
+
// undi95/
|
|
463
|
+
// x-ai/
|
|
464
|
+
// z-ai/
|
|
465
|
+
|
|
466
|
+
// prepend it with openrouter:
|
|
467
|
+
if (
|
|
468
|
+
requestParams.model.startsWith('agentica-org/') ||
|
|
469
|
+
requestParams.model.startsWith('ai21/') ||
|
|
470
|
+
requestParams.model.startsWith('aion-labs/') ||
|
|
471
|
+
requestParams.model.startsWith('alfredpros/') ||
|
|
472
|
+
requestParams.model.startsWith('alpindale/') ||
|
|
473
|
+
requestParams.model.startsWith('amazon/') ||
|
|
474
|
+
requestParams.model.startsWith('anthracite-org/') ||
|
|
475
|
+
requestParams.model.startsWith('arcee-ai/') ||
|
|
476
|
+
requestParams.model.startsWith('arliai/') ||
|
|
477
|
+
requestParams.model.startsWith('baidu/') ||
|
|
478
|
+
requestParams.model.startsWith('bytedance/') ||
|
|
479
|
+
requestParams.model.startsWith('cognitivecomputations/') ||
|
|
480
|
+
requestParams.model.startsWith('cohere/') ||
|
|
481
|
+
requestParams.model.startsWith('deepseek/') ||
|
|
482
|
+
requestParams.model.startsWith('eleutherai/') ||
|
|
483
|
+
requestParams.model.startsWith('google/') ||
|
|
484
|
+
requestParams.model.startsWith('gryphe/') ||
|
|
485
|
+
requestParams.model.startsWith('inception/') ||
|
|
486
|
+
requestParams.model.startsWith('infermatic/') ||
|
|
487
|
+
requestParams.model.startsWith('liquid/') ||
|
|
488
|
+
requestParams.model.startsWith('mancer/') ||
|
|
489
|
+
requestParams.model.startsWith('meta-llama/') ||
|
|
490
|
+
requestParams.model.startsWith('microsoft/') ||
|
|
491
|
+
requestParams.model.startsWith('minimax/') ||
|
|
492
|
+
requestParams.model.startsWith('mistralai/') ||
|
|
493
|
+
requestParams.model.startsWith('moonshotai/') ||
|
|
494
|
+
requestParams.model.startsWith('morph/') ||
|
|
495
|
+
requestParams.model.startsWith('neversleep/') ||
|
|
496
|
+
requestParams.model.startsWith('nousresearch/') ||
|
|
497
|
+
requestParams.model.startsWith('nvidia/') ||
|
|
498
|
+
requestParams.model.startsWith('openrouter/') ||
|
|
499
|
+
requestParams.model.startsWith('perplexity/') ||
|
|
500
|
+
requestParams.model.startsWith('pygmalionai/') ||
|
|
501
|
+
requestParams.model.startsWith('qwen/') ||
|
|
502
|
+
requestParams.model.startsWith('raifle/') ||
|
|
503
|
+
requestParams.model.startsWith('rekaai/') ||
|
|
504
|
+
requestParams.model.startsWith('sao10k/') ||
|
|
505
|
+
requestParams.model.startsWith('sarvamai/') ||
|
|
506
|
+
requestParams.model.startsWith('scb10x/') ||
|
|
507
|
+
requestParams.model.startsWith('shisa-ai/') ||
|
|
508
|
+
requestParams.model.startsWith('sophosympatheia/') ||
|
|
509
|
+
requestParams.model.startsWith('switchpoint/') ||
|
|
510
|
+
requestParams.model.startsWith('tencent/') ||
|
|
511
|
+
requestParams.model.startsWith('thedrummer/') ||
|
|
512
|
+
requestParams.model.startsWith('thudm/') ||
|
|
513
|
+
requestParams.model.startsWith('tngtech/') ||
|
|
514
|
+
requestParams.model.startsWith('undi95/') ||
|
|
515
|
+
requestParams.model.startsWith('x-ai/') ||
|
|
516
|
+
requestParams.model.startsWith('z-ai/')
|
|
517
|
+
) {
|
|
518
|
+
requestParams.model = 'openrouter:' + requestParams.model;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// map model to the appropriate driver
|
|
522
|
+
if (!requestParams.model || requestParams.model.startsWith('gpt-')) {
|
|
523
|
+
driver = 'openai-completion';
|
|
524
|
+
}else if(
|
|
525
|
+
requestParams.model.startsWith('claude-')
|
|
526
|
+
){
|
|
527
|
+
driver = 'claude';
|
|
528
|
+
}else if(requestParams.model === 'meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo' || requestParams.model === 'meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo' || requestParams.model === 'meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo' || requestParams.model === `google/gemma-2-27b-it`){
|
|
529
|
+
driver = 'together-ai';
|
|
530
|
+
}else if(requestParams.model.startsWith('mistral-') || requestParams.model.startsWith('codestral-') || requestParams.model.startsWith('pixtral-') || requestParams.model.startsWith('magistral-') || requestParams.model.startsWith('devstral-') || requestParams.model.startsWith('mistral-ocr-') || requestParams.model.startsWith('open-mistral-')){
|
|
531
|
+
driver = 'mistral';
|
|
532
|
+
}else if([
|
|
533
|
+
"distil-whisper-large-v3-en",
|
|
534
|
+
"gemma2-9b-it",
|
|
535
|
+
"gemma-7b-it",
|
|
536
|
+
"llama-3.1-70b-versatile",
|
|
537
|
+
"llama-3.1-8b-instant",
|
|
538
|
+
"llama3-70b-8192",
|
|
539
|
+
"llama3-8b-8192",
|
|
540
|
+
"llama3-groq-70b-8192-tool-use-preview",
|
|
541
|
+
"llama3-groq-8b-8192-tool-use-preview",
|
|
542
|
+
"llama-guard-3-8b",
|
|
543
|
+
"mixtral-8x7b-32768",
|
|
544
|
+
"whisper-large-v3"
|
|
545
|
+
].includes(requestParams.model)) {
|
|
546
|
+
driver = 'groq';
|
|
547
|
+
}else if(requestParams.model === 'grok-beta') {
|
|
548
|
+
driver = 'xai';
|
|
549
|
+
}
|
|
550
|
+
else if(requestParams.model.startsWith('grok-')){
|
|
551
|
+
driver = 'openrouter';
|
|
552
|
+
}
|
|
553
|
+
else if(
|
|
554
|
+
requestParams.model === 'deepseek-chat' ||
|
|
555
|
+
requestParams.model === 'deepseek-reasoner'
|
|
556
|
+
){
|
|
557
|
+
driver = 'deepseek';
|
|
558
|
+
}
|
|
559
|
+
else if(
|
|
560
|
+
requestParams.model === 'gemini-1.5-flash' ||
|
|
561
|
+
requestParams.model === 'gemini-2.0-flash'
|
|
562
|
+
){
|
|
563
|
+
driver = 'gemini';
|
|
564
|
+
}
|
|
565
|
+
else if ( requestParams.model.startsWith('openrouter:') ) {
|
|
566
|
+
driver = 'openrouter';
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
// stream flag from userParams
|
|
570
|
+
if(userParams.stream !== undefined && typeof userParams.stream === 'boolean'){
|
|
571
|
+
requestParams.stream = userParams.stream;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
if ( userParams.driver ) {
|
|
575
|
+
driver = userParams.driver;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
// Additional parameters to pass from userParams to requestParams
|
|
579
|
+
const PARAMS_TO_PASS = ['tools', 'response'];
|
|
580
|
+
for ( const name of PARAMS_TO_PASS ) {
|
|
581
|
+
if ( userParams[name] ) {
|
|
582
|
+
requestParams[name] = userParams[name];
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
if ( requestParams.model === '' ) {
|
|
587
|
+
delete requestParams.model;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
// Call the original chat.complete method
|
|
591
|
+
return await utils.make_driver_method(['messages'], 'puter-chat-completion', driver, 'complete', {
|
|
592
|
+
test_mode: testMode ?? false,
|
|
593
|
+
transform: async (result) => {
|
|
594
|
+
result.toString = () => {
|
|
595
|
+
return result.message?.content;
|
|
596
|
+
};
|
|
597
|
+
|
|
598
|
+
result.valueOf = () => {
|
|
599
|
+
return result.message?.content;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
return result;
|
|
603
|
+
}
|
|
604
|
+
}).call(this, requestParams);
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Generate images from text prompts or perform image-to-image generation
|
|
609
|
+
*
|
|
610
|
+
* @param {string|object} prompt - Text prompt or options object
|
|
611
|
+
* @param {object|boolean} [options] - Generation options or test mode flag
|
|
612
|
+
* @param {string} [options.prompt] - Text description of the image to generate
|
|
613
|
+
* @param {string} [options.model] - Model to use (e.g., "gemini-2.5-flash-image-preview")
|
|
614
|
+
* @param {object} [options.ratio] - Image dimensions (e.g., {w: 1024, h: 1024})
|
|
615
|
+
* @param {string} [options.input_image] - Base64 encoded input image for image-to-image generation
|
|
616
|
+
* @param {string} [options.input_image_mime_type] - MIME type of input image (e.g., "image/png")
|
|
617
|
+
* @returns {Promise<Image>} Generated image object with src property
|
|
618
|
+
*
|
|
619
|
+
* @example
|
|
620
|
+
* // Text-to-image
|
|
621
|
+
* const img = await puter.ai.txt2img("A beautiful sunset");
|
|
622
|
+
*
|
|
623
|
+
* @example
|
|
624
|
+
* // Image-to-image
|
|
625
|
+
* const img = await puter.ai.txt2img({
|
|
626
|
+
* prompt: "Transform this into a watercolor painting",
|
|
627
|
+
* input_image: base64ImageData,
|
|
628
|
+
* input_image_mime_type: "image/png",
|
|
629
|
+
* model: "gemini-2.5-flash-image-preview"
|
|
630
|
+
* });
|
|
631
|
+
*/
|
|
632
|
+
txt2img = async (...args) => {
|
|
633
|
+
let options = {};
|
|
634
|
+
let testMode = false;
|
|
635
|
+
|
|
636
|
+
if(!args){
|
|
637
|
+
throw({message: 'Arguments are required', code: 'arguments_required'});
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// if argument is string transform it to the object that the API expects
|
|
641
|
+
if (typeof args[0] === 'string') {
|
|
642
|
+
options = { prompt: args[0] };
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
// if second argument is string, it's the `testMode`
|
|
646
|
+
if (typeof args[1] === 'boolean' && args[1] === true) {
|
|
647
|
+
testMode = true;
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
if (typeof args[0] === 'string' && typeof args[1] === "object") {
|
|
651
|
+
options = args[1];
|
|
652
|
+
options.prompt = args[0];
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
if (typeof args[0] === 'object') {
|
|
656
|
+
options = args[0]
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
let AIService = "openai-image-generation"
|
|
660
|
+
if (options.model === "nano-banana")
|
|
661
|
+
options.model = "gemini-2.5-flash-image-preview";
|
|
662
|
+
|
|
663
|
+
if (options.model === "gemini-2.5-flash-image-preview")
|
|
664
|
+
AIService = "gemini-image-generation";
|
|
665
|
+
// Call the original chat.complete method
|
|
666
|
+
return await utils.make_driver_method(['prompt'], 'puter-image-generation', AIService, 'generate', {
|
|
667
|
+
responseType: 'blob',
|
|
668
|
+
test_mode: testMode ?? false,
|
|
669
|
+
transform: async blob => {
|
|
670
|
+
let img = new Image();
|
|
671
|
+
img.src = await utils.blob_to_url(blob);
|
|
672
|
+
img.toString = () => img.src;
|
|
673
|
+
img.valueOf = () => img.src;
|
|
674
|
+
return img;
|
|
675
|
+
}
|
|
676
|
+
}).call(this, options);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
export default AI;
|