@heyputer/puter.js 2.1.4 → 2.1.7
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.cjs +2 -2
- package/index.d.ts +41 -15
- package/package.json +1 -1
- package/src/index.js +116 -79
- package/src/lib/APICallLogger.js +20 -21
- package/src/lib/EventListener.js +10 -10
- package/src/lib/filesystem/APIFS.js +11 -19
- package/src/lib/filesystem/CacheFS.js +25 -25
- package/src/lib/filesystem/PostMessageFS.js +11 -11
- package/src/lib/filesystem/definitions.js +11 -10
- package/src/lib/path.js +505 -446
- package/src/lib/polyfills/fileReaderPoly.js +40 -0
- package/src/lib/polyfills/localStorage.js +30 -33
- package/src/lib/polyfills/xhrshim.js +206 -207
- package/src/lib/utils.js +160 -151
- package/src/lib/xdrpc.js +9 -9
- package/src/modules/AI.js +473 -292
- package/src/modules/Apps.js +56 -56
- package/src/modules/Auth.js +17 -17
- package/src/modules/Debug.js +1 -1
- package/src/modules/Drivers.js +41 -41
- package/src/modules/FSItem.js +64 -62
- package/src/modules/FileSystem/index.js +22 -23
- package/src/modules/FileSystem/operations/copy.js +7 -7
- package/src/modules/FileSystem/operations/deleteFSEntry.js +14 -12
- package/src/modules/FileSystem/operations/getReadUrl.js +16 -14
- package/src/modules/FileSystem/operations/mkdir.js +11 -11
- package/src/modules/FileSystem/operations/move.js +12 -12
- package/src/modules/FileSystem/operations/read.js +10 -10
- package/src/modules/FileSystem/operations/readdir.js +28 -28
- package/src/modules/FileSystem/operations/rename.js +11 -11
- package/src/modules/FileSystem/operations/sign.js +33 -30
- package/src/modules/FileSystem/operations/space.js +7 -7
- package/src/modules/FileSystem/operations/stat.js +25 -25
- package/src/modules/FileSystem/operations/symlink.js +15 -17
- package/src/modules/FileSystem/operations/upload.js +151 -122
- package/src/modules/FileSystem/operations/write.js +16 -12
- package/src/modules/FileSystem/utils/getAbsolutePathForApp.js +10 -6
- package/src/modules/Hosting.js +29 -29
- package/src/modules/KV.js +23 -23
- package/src/modules/OS.js +15 -15
- package/src/modules/Perms.js +19 -21
- package/src/modules/PuterDialog.js +46 -48
- package/src/modules/Threads.js +17 -20
- package/src/modules/UI.js +156 -156
- package/src/modules/Util.js +3 -3
- package/src/modules/Workers.js +52 -49
- package/src/modules/networking/PSocket.js +38 -38
- package/src/modules/networking/PTLS.js +54 -47
- package/src/modules/networking/PWispHandler.js +49 -47
- package/src/modules/networking/parsers.js +110 -108
- package/src/modules/networking/requests.js +67 -78
- package/src/services/APIAccess.js +9 -9
- package/src/services/FSRelay.js +6 -6
- package/src/services/Filesystem.js +8 -8
- package/src/services/NoPuterYet.js +2 -2
- package/src/services/XDIncoming.js +1 -1
package/src/index.js
CHANGED
|
@@ -35,10 +35,10 @@ import { XDIncomingService } from './services/XDIncoming.js';
|
|
|
35
35
|
// (using defaultGUIOrigin breaks locally-hosted apps)
|
|
36
36
|
const PROD_ORIGIN = 'https://puter.com';
|
|
37
37
|
|
|
38
|
-
const puterInit = (function() {
|
|
38
|
+
const puterInit = (function () {
|
|
39
39
|
'use strict';
|
|
40
40
|
|
|
41
|
-
class Puter{
|
|
41
|
+
class Puter {
|
|
42
42
|
// The environment that the SDK is running in. Can be 'gui', 'app' or 'web'.
|
|
43
43
|
// 'gui' means the SDK is running in the Puter GUI, i.e. Puter.com.
|
|
44
44
|
// 'app' means the SDK is running as a Puter app, i.e. within an iframe in the Puter GUI.
|
|
@@ -48,17 +48,17 @@ const puterInit = (function() {
|
|
|
48
48
|
#defaultAPIOrigin = 'https://api.puter.com';
|
|
49
49
|
#defaultGUIOrigin = 'https://puter.com';
|
|
50
50
|
|
|
51
|
-
get defaultAPIOrigin() {
|
|
51
|
+
get defaultAPIOrigin () {
|
|
52
52
|
return globalThis.PUTER_API_ORIGIN || globalThis.PUTER_API_ORIGIN_ENV || this.#defaultAPIOrigin;
|
|
53
53
|
}
|
|
54
|
-
set defaultAPIOrigin(v) {
|
|
54
|
+
set defaultAPIOrigin (v) {
|
|
55
55
|
this.#defaultAPIOrigin = v;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
get defaultGUIOrigin() {
|
|
58
|
+
get defaultGUIOrigin () {
|
|
59
59
|
return globalThis.PUTER_ORIGIN || globalThis.PUTER_ORIGIN_ENV || this.#defaultGUIOrigin;
|
|
60
60
|
}
|
|
61
|
-
set defaultGUIOrigin(v) {
|
|
61
|
+
set defaultGUIOrigin (v) {
|
|
62
62
|
this.#defaultGUIOrigin = v;
|
|
63
63
|
}
|
|
64
64
|
|
|
@@ -100,7 +100,7 @@ const puterInit = (function() {
|
|
|
100
100
|
*
|
|
101
101
|
* initSubmodules is called from the constructor of this class.
|
|
102
102
|
*/
|
|
103
|
-
initSubmodules = function(){
|
|
103
|
+
initSubmodules = function () {
|
|
104
104
|
// Util
|
|
105
105
|
this.util = new Util();
|
|
106
106
|
|
|
@@ -127,10 +127,10 @@ const puterInit = (function() {
|
|
|
127
127
|
// --------------------------------------------
|
|
128
128
|
// Constructor
|
|
129
129
|
// --------------------------------------------
|
|
130
|
-
constructor() {
|
|
130
|
+
constructor () {
|
|
131
131
|
|
|
132
132
|
// Initialize the cache using kv.js
|
|
133
|
-
this._cache = new kvjs({dbName: 'puter_cache'});
|
|
133
|
+
this._cache = new kvjs({ dbName: 'puter_cache' });
|
|
134
134
|
this._opscache = new kvjs();
|
|
135
135
|
|
|
136
136
|
// "modules" in puter.js are external interfaces for the developer
|
|
@@ -158,31 +158,31 @@ const puterInit = (function() {
|
|
|
158
158
|
else if ( globalThis.WorkerGlobalScope ) {
|
|
159
159
|
if ( globalThis.ServiceWorkerGlobalScope ) {
|
|
160
160
|
this.env = 'service-worker';
|
|
161
|
-
if ( !globalThis.XMLHttpRequest ) {
|
|
161
|
+
if ( ! globalThis.XMLHttpRequest ) {
|
|
162
162
|
globalThis.XMLHttpRequest = xhrshim;
|
|
163
163
|
}
|
|
164
|
-
if ( !globalThis.location ) {
|
|
164
|
+
if ( ! globalThis.location ) {
|
|
165
165
|
globalThis.location = new URL('https://puter.site/');
|
|
166
166
|
}
|
|
167
167
|
// XHRShimGlobalize here
|
|
168
168
|
} else {
|
|
169
169
|
this.env = 'web-worker';
|
|
170
170
|
}
|
|
171
|
-
if ( !globalThis.localStorage ) {
|
|
171
|
+
if ( ! globalThis.localStorage ) {
|
|
172
172
|
globalThis.localStorage = localStorageMemory;
|
|
173
173
|
}
|
|
174
174
|
} else if ( globalThis.process ) {
|
|
175
175
|
this.env = 'nodejs';
|
|
176
|
-
if ( !globalThis.localStorage ) {
|
|
176
|
+
if ( ! globalThis.localStorage ) {
|
|
177
177
|
globalThis.localStorage = localStorageMemory;
|
|
178
178
|
}
|
|
179
|
-
if ( !globalThis.XMLHttpRequest ) {
|
|
179
|
+
if ( ! globalThis.XMLHttpRequest ) {
|
|
180
180
|
globalThis.XMLHttpRequest = xhrshim;
|
|
181
181
|
}
|
|
182
|
-
if ( !globalThis.location ) {
|
|
182
|
+
if ( ! globalThis.location ) {
|
|
183
183
|
globalThis.location = new URL('https://nodejs.puter.site/');
|
|
184
184
|
}
|
|
185
|
-
if ( !globalThis.addEventListener ) {
|
|
185
|
+
if ( ! globalThis.addEventListener ) {
|
|
186
186
|
globalThis.addEventListener = () => {
|
|
187
187
|
}; // API Stub
|
|
188
188
|
}
|
|
@@ -193,7 +193,7 @@ const puterInit = (function() {
|
|
|
193
193
|
// There are some specific situations where puter is definitely loaded in GUI mode
|
|
194
194
|
// we're going to check for those situations here so that we don't break anything unintentionally
|
|
195
195
|
// if navigator URL's hostname is 'puter.com'
|
|
196
|
-
if ( this.env !== 'gui' ){
|
|
196
|
+
if ( this.env !== 'gui' ) {
|
|
197
197
|
// Retrieve the hostname from the URL: Remove the trailing dot if it exists. This is to handle the case where the URL is, for example, `https://puter.com.` (note the trailing dot).
|
|
198
198
|
// This is necessary because the trailing dot can cause the hostname to not match the expected value.
|
|
199
199
|
let hostname = location.hostname.replace(/\.$/, '');
|
|
@@ -205,13 +205,13 @@ const puterInit = (function() {
|
|
|
205
205
|
const gui_hostname = url.hostname;
|
|
206
206
|
|
|
207
207
|
// If the hostname matches the GUI hostname, then the SDK is running in the GUI environment
|
|
208
|
-
if ( hostname === gui_hostname ){
|
|
208
|
+
if ( hostname === gui_hostname ) {
|
|
209
209
|
this.env = 'gui';
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
|
|
213
213
|
// Get the 'args' from the URL. This is used to pass arguments to the app.
|
|
214
|
-
if ( URLParams.has('puter.args') ){
|
|
214
|
+
if ( URLParams.has('puter.args') ) {
|
|
215
215
|
this.args = JSON.parse(decodeURIComponent(URLParams.get('puter.args')));
|
|
216
216
|
} else {
|
|
217
217
|
this.args = {};
|
|
@@ -220,30 +220,30 @@ const puterInit = (function() {
|
|
|
220
220
|
// Try to extract appInstanceID from the URL. appInstanceID is included in every messaage
|
|
221
221
|
// sent to the host environment. This is used to help host environment identify the app
|
|
222
222
|
// instance that sent the message and communicate back to it.
|
|
223
|
-
if ( URLParams.has('puter.app_instance_id') ){
|
|
223
|
+
if ( URLParams.has('puter.app_instance_id') ) {
|
|
224
224
|
this.appInstanceID = decodeURIComponent(URLParams.get('puter.app_instance_id'));
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
// Try to extract parentInstanceID from the URL. If another app launched this app instance, parentInstanceID
|
|
228
228
|
// holds its instance ID, and is used to communicate with that parent app.
|
|
229
|
-
if ( URLParams.has('puter.parent_instance_id') ){
|
|
229
|
+
if ( URLParams.has('puter.parent_instance_id') ) {
|
|
230
230
|
this.parentInstanceID = decodeURIComponent(URLParams.get('puter.parent_instance_id'));
|
|
231
231
|
}
|
|
232
232
|
|
|
233
233
|
// Try to extract `puter.app.id` from the URL. `puter.app.id` is the unique ID of the app.
|
|
234
234
|
// App ID is useful for identifying the app when communicating with the Puter API, among other things.
|
|
235
|
-
if ( URLParams.has('puter.app.id') ){
|
|
235
|
+
if ( URLParams.has('puter.app.id') ) {
|
|
236
236
|
this.appID = decodeURIComponent(URLParams.get('puter.app.id'));
|
|
237
237
|
}
|
|
238
238
|
|
|
239
239
|
// Extract app name (added later)
|
|
240
|
-
if ( URLParams.has('puter.app.name') ){
|
|
240
|
+
if ( URLParams.has('puter.app.name') ) {
|
|
241
241
|
this.appName = decodeURIComponent(URLParams.get('puter.app.name'));
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
// Construct this App's AppData path based on the appID. AppData path is used to store files that are specific to this app.
|
|
245
245
|
// The default AppData path is `~/AppData/<appID>`.
|
|
246
|
-
if ( this.appID ){
|
|
246
|
+
if ( this.appID ) {
|
|
247
247
|
this.appDataPath = `~/AppData/${this.appID}`;
|
|
248
248
|
}
|
|
249
249
|
|
|
@@ -253,10 +253,10 @@ const puterInit = (function() {
|
|
|
253
253
|
// is constructed as `https://api.<puter.domain>`.
|
|
254
254
|
// This should only be done when the SDK is running in 'app' mode.
|
|
255
255
|
this.APIOrigin = this.defaultAPIOrigin;
|
|
256
|
-
if ( URLParams.has('puter.api_origin') && this.env === 'app' ){
|
|
256
|
+
if ( URLParams.has('puter.api_origin') && this.env === 'app' ) {
|
|
257
257
|
this.APIOrigin = decodeURIComponent(URLParams.get('puter.api_origin'));
|
|
258
|
-
} else if ( URLParams.has('puter.domain') && this.env === 'app' ){
|
|
259
|
-
this.APIOrigin =
|
|
258
|
+
} else if ( URLParams.has('puter.domain') && this.env === 'app' ) {
|
|
259
|
+
this.APIOrigin = `https://api.${ URLParams.get('puter.domain')}`;
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
// === START :: Logger ===
|
|
@@ -302,10 +302,10 @@ const puterInit = (function() {
|
|
|
302
302
|
['APIOrigin', 'api_origin'],
|
|
303
303
|
].forEach(([k1, k2]) => {
|
|
304
304
|
Object.defineProperty(this, k1, {
|
|
305
|
-
get() {
|
|
305
|
+
get () {
|
|
306
306
|
return svc_apiAccess[k2];
|
|
307
307
|
},
|
|
308
|
-
set(v) {
|
|
308
|
+
set (v) {
|
|
309
309
|
svc_apiAccess[k2] = v;
|
|
310
310
|
},
|
|
311
311
|
});
|
|
@@ -315,7 +315,7 @@ const puterInit = (function() {
|
|
|
315
315
|
// === Start :: Modules === //
|
|
316
316
|
|
|
317
317
|
// The SDK is running in the Puter GUI (i.e. 'gui')
|
|
318
|
-
if ( this.env === 'gui' ){
|
|
318
|
+
if ( this.env === 'gui' ) {
|
|
319
319
|
this.authToken = window.auth_token;
|
|
320
320
|
// initialize submodules
|
|
321
321
|
this.initSubmodules();
|
|
@@ -328,14 +328,14 @@ const puterInit = (function() {
|
|
|
328
328
|
this.initSubmodules();
|
|
329
329
|
// If the authToken is already set in localStorage, then we don't need to show the dialog
|
|
330
330
|
try {
|
|
331
|
-
if ( localStorage.getItem('puter.auth.token') ){
|
|
331
|
+
if ( localStorage.getItem('puter.auth.token') ) {
|
|
332
332
|
this.setAuthToken(localStorage.getItem('puter.auth.token'));
|
|
333
333
|
}
|
|
334
334
|
// if appID is already set in localStorage, then we don't need to show the dialog
|
|
335
|
-
if ( localStorage.getItem('puter.app.id') ){
|
|
335
|
+
if ( localStorage.getItem('puter.app.id') ) {
|
|
336
336
|
this.setAppID(localStorage.getItem('puter.app.id'));
|
|
337
337
|
}
|
|
338
|
-
} catch( error ) {
|
|
338
|
+
} catch ( error ) {
|
|
339
339
|
// Handle the error here
|
|
340
340
|
console.error('Error accessing localStorage:', error);
|
|
341
341
|
}
|
|
@@ -348,14 +348,14 @@ const puterInit = (function() {
|
|
|
348
348
|
this.initSubmodules();
|
|
349
349
|
try {
|
|
350
350
|
// If the authToken is already set in localStorage, then we don't need to show the dialog
|
|
351
|
-
if ( localStorage.getItem('puter.auth.token') ){
|
|
351
|
+
if ( localStorage.getItem('puter.auth.token') ) {
|
|
352
352
|
this.setAuthToken(localStorage.getItem('puter.auth.token'));
|
|
353
353
|
}
|
|
354
354
|
// if appID is already set in localStorage, then we don't need to show the dialog
|
|
355
|
-
if ( localStorage.getItem('puter.app.id') ){
|
|
355
|
+
if ( localStorage.getItem('puter.app.id') ) {
|
|
356
356
|
this.setAppID(localStorage.getItem('puter.app.id'));
|
|
357
357
|
}
|
|
358
|
-
} catch( error ) {
|
|
358
|
+
} catch ( error ) {
|
|
359
359
|
// Handle the error here
|
|
360
360
|
console.error('Error accessing localStorage:', error);
|
|
361
361
|
}
|
|
@@ -369,9 +369,9 @@ const puterInit = (function() {
|
|
|
369
369
|
const whoami = await this.auth.whoami();
|
|
370
370
|
logger = new putility.libs.log.PrefixLogger({
|
|
371
371
|
delegate: logger,
|
|
372
|
-
prefix:
|
|
373
|
-
|
|
374
|
-
|
|
372
|
+
prefix: `[${
|
|
373
|
+
whoami?.app_name ?? this.appInstanceID ?? 'HOST'
|
|
374
|
+
}] `,
|
|
375
375
|
});
|
|
376
376
|
|
|
377
377
|
this.logger.impl = logger;
|
|
@@ -392,7 +392,7 @@ const puterInit = (function() {
|
|
|
392
392
|
|
|
393
393
|
this.net = {
|
|
394
394
|
generateWispV1URL: async () => {
|
|
395
|
-
const { token: wispToken, server: wispServer } = (await (await fetch(this.APIOrigin
|
|
395
|
+
const { token: wispToken, server: wispServer } = (await (await fetch(`${this.APIOrigin }/wisp/relay-token/create`, {
|
|
396
396
|
method: 'POST',
|
|
397
397
|
headers: {
|
|
398
398
|
Authorization: `Bearer ${this.authToken}`,
|
|
@@ -420,7 +420,7 @@ const puterInit = (function() {
|
|
|
420
420
|
* Makes a request to `/rao`. This method aquires a lock to prevent
|
|
421
421
|
* multiple requests, and is effectively idempotent.
|
|
422
422
|
*/
|
|
423
|
-
async request_rao_() {
|
|
423
|
+
async request_rao_ () {
|
|
424
424
|
await this.p_can_request_rao_;
|
|
425
425
|
|
|
426
426
|
if ( this.env === 'gui' ) {
|
|
@@ -437,7 +437,7 @@ const puterInit = (function() {
|
|
|
437
437
|
|
|
438
438
|
let had_error = false;
|
|
439
439
|
try {
|
|
440
|
-
const resp = await fetch(this.APIOrigin
|
|
440
|
+
const resp = await fetch(`${this.APIOrigin }/rao`, {
|
|
441
441
|
method: 'POST',
|
|
442
442
|
headers: {
|
|
443
443
|
Authorization: `Bearer ${this.authToken}`,
|
|
@@ -445,7 +445,7 @@ const puterInit = (function() {
|
|
|
445
445
|
},
|
|
446
446
|
});
|
|
447
447
|
return await resp.json();
|
|
448
|
-
} catch( e ) {
|
|
448
|
+
} catch ( e ) {
|
|
449
449
|
had_error = true;
|
|
450
450
|
console.error(e);
|
|
451
451
|
} finally {
|
|
@@ -456,14 +456,14 @@ const puterInit = (function() {
|
|
|
456
456
|
}
|
|
457
457
|
}
|
|
458
458
|
|
|
459
|
-
registerModule(name, cls, parameters = {}) {
|
|
459
|
+
registerModule (name, cls, parameters = {}) {
|
|
460
460
|
const instance = new cls(this.context, parameters);
|
|
461
461
|
this.modules_.push(name);
|
|
462
462
|
this[name] = instance;
|
|
463
463
|
if ( instance._init ) instance._init({ puter: this });
|
|
464
464
|
}
|
|
465
465
|
|
|
466
|
-
updateSubmodules() {
|
|
466
|
+
updateSubmodules () {
|
|
467
467
|
// Update submodules with new auth token and API origin
|
|
468
468
|
for ( const name of this.modules_ ) {
|
|
469
469
|
if ( ! this[name] ) continue;
|
|
@@ -472,30 +472,30 @@ const puterInit = (function() {
|
|
|
472
472
|
}
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
-
setAppID = function(appID) {
|
|
475
|
+
setAppID = function (appID) {
|
|
476
476
|
// save to localStorage
|
|
477
477
|
try {
|
|
478
478
|
localStorage.setItem('puter.app.id', appID);
|
|
479
|
-
} catch( error ) {
|
|
479
|
+
} catch ( error ) {
|
|
480
480
|
// Handle the error here
|
|
481
481
|
console.error('Error accessing localStorage:', error);
|
|
482
482
|
}
|
|
483
483
|
this.appID = appID;
|
|
484
484
|
};
|
|
485
485
|
|
|
486
|
-
setAuthToken = function(authToken) {
|
|
486
|
+
setAuthToken = function (authToken) {
|
|
487
487
|
this.authToken = authToken;
|
|
488
488
|
// If the SDK is running on a 3rd-party site or an app, then save the authToken in localStorage
|
|
489
|
-
if ( this.env === 'web' || this.env === 'app' ){
|
|
489
|
+
if ( this.env === 'web' || this.env === 'app' ) {
|
|
490
490
|
try {
|
|
491
491
|
localStorage.setItem('puter.auth.token', authToken);
|
|
492
|
-
} catch( error ) {
|
|
492
|
+
} catch ( error ) {
|
|
493
493
|
// Handle the error here
|
|
494
494
|
console.error('Error accessing localStorage:', error);
|
|
495
495
|
}
|
|
496
496
|
}
|
|
497
497
|
// initialize loop for updating caches for major directories
|
|
498
|
-
if(this.env === 'gui'){
|
|
498
|
+
if ( this.env === 'gui' ) {
|
|
499
499
|
// check and update gui fs cache regularly
|
|
500
500
|
setInterval(puter.checkAndUpdateGUIFScache, 10000);
|
|
501
501
|
}
|
|
@@ -511,19 +511,19 @@ const puterInit = (function() {
|
|
|
511
511
|
});
|
|
512
512
|
};
|
|
513
513
|
|
|
514
|
-
setAPIOrigin = function(APIOrigin) {
|
|
514
|
+
setAPIOrigin = function (APIOrigin) {
|
|
515
515
|
this.APIOrigin = APIOrigin;
|
|
516
516
|
// reinitialize submodules
|
|
517
517
|
this.updateSubmodules();
|
|
518
518
|
};
|
|
519
519
|
|
|
520
|
-
resetAuthToken = function() {
|
|
520
|
+
resetAuthToken = function () {
|
|
521
521
|
this.authToken = null;
|
|
522
522
|
// If the SDK is running on a 3rd-party site or an app, then save the authToken in localStorage
|
|
523
|
-
if ( this.env === 'web' || this.env === 'app' ){
|
|
523
|
+
if ( this.env === 'web' || this.env === 'app' ) {
|
|
524
524
|
try {
|
|
525
525
|
localStorage.removeItem('puter.auth.token');
|
|
526
|
-
} catch( error ) {
|
|
526
|
+
} catch ( error ) {
|
|
527
527
|
// Handle the error here
|
|
528
528
|
console.error('Error accessing localStorage:', error);
|
|
529
529
|
}
|
|
@@ -532,7 +532,7 @@ const puterInit = (function() {
|
|
|
532
532
|
this.updateSubmodules();
|
|
533
533
|
};
|
|
534
534
|
|
|
535
|
-
exit = function(statusCode = 0) {
|
|
535
|
+
exit = function (statusCode = 0) {
|
|
536
536
|
if ( statusCode && (typeof statusCode !== 'number') ) {
|
|
537
537
|
console.warn('puter.exit() requires status code to be a number. Treating it as 1');
|
|
538
538
|
statusCode = 1;
|
|
@@ -554,7 +554,7 @@ const puterInit = (function() {
|
|
|
554
554
|
* @returns {string} A unique, hyphen-separated string comprising of an adjective, a noun, and a number.
|
|
555
555
|
*
|
|
556
556
|
*/
|
|
557
|
-
randName = function(separateWith = '-'){
|
|
557
|
+
randName = function (separateWith = '-') {
|
|
558
558
|
const first_adj = ['helpful', 'sensible', 'loyal', 'honest', 'clever', 'capable', 'calm', 'smart', 'genius', 'bright', 'charming', 'creative', 'diligent', 'elegant', 'fancy',
|
|
559
559
|
'colorful', 'avid', 'active', 'gentle', 'happy', 'intelligent', 'jolly', 'kind', 'lively', 'merry', 'nice', 'optimistic', 'polite',
|
|
560
560
|
'quiet', 'relaxed', 'silly', 'victorious', 'witty', 'young', 'zealous', 'strong', 'brave', 'agile', 'bold'];
|
|
@@ -573,7 +573,7 @@ const puterInit = (function() {
|
|
|
573
573
|
return first_adj[Math.floor(Math.random() * first_adj.length)] + separateWith + nouns[Math.floor(Math.random() * nouns.length)] + separateWith + Math.floor(Math.random() * 10000);
|
|
574
574
|
};
|
|
575
575
|
|
|
576
|
-
getUser = function(...args){
|
|
576
|
+
getUser = function (...args) {
|
|
577
577
|
let options;
|
|
578
578
|
|
|
579
579
|
// If first argument is an object, it's the options
|
|
@@ -596,7 +596,7 @@ const puterInit = (function() {
|
|
|
596
596
|
});
|
|
597
597
|
};
|
|
598
598
|
|
|
599
|
-
print = function(...args){
|
|
599
|
+
print = function (...args) {
|
|
600
600
|
// Check if the last argument is an options object with escapeHTML or code property
|
|
601
601
|
let options = {};
|
|
602
602
|
if ( args.length > 0 && typeof args[args.length - 1] === 'object' && args[args.length - 1] !== null &&
|
|
@@ -604,7 +604,7 @@ const puterInit = (function() {
|
|
|
604
604
|
options = args.pop();
|
|
605
605
|
}
|
|
606
606
|
|
|
607
|
-
for ( let arg of args ){
|
|
607
|
+
for ( let arg of args ) {
|
|
608
608
|
// Escape HTML if the option is set to true or if code option is true
|
|
609
609
|
if ( (options.escapeHTML === true || options.code === true) && typeof arg === 'string' ) {
|
|
610
610
|
arg = arg.replace(/&/g, '&')
|
|
@@ -629,7 +629,7 @@ const puterInit = (function() {
|
|
|
629
629
|
* @param {boolean} config.enabled - Enable/disable API call logging
|
|
630
630
|
* @param {boolean} config.enabled - Enable/disable API call logging
|
|
631
631
|
*/
|
|
632
|
-
configureAPILogging = function(config = {}){
|
|
632
|
+
configureAPILogging = function (config = {}) {
|
|
633
633
|
if ( this.apiCallLogger ) {
|
|
634
634
|
this.apiCallLogger.updateConfig(config);
|
|
635
635
|
}
|
|
@@ -640,7 +640,7 @@ const puterInit = (function() {
|
|
|
640
640
|
* Enables API call logging with optional configuration
|
|
641
641
|
* @param {Object} config - Optional configuration to apply when enabling
|
|
642
642
|
*/
|
|
643
|
-
enableAPILogging = function(config = {}) {
|
|
643
|
+
enableAPILogging = function (config = {}) {
|
|
644
644
|
if ( this.apiCallLogger ) {
|
|
645
645
|
this.apiCallLogger.updateConfig({ ...config, enabled: true });
|
|
646
646
|
}
|
|
@@ -650,7 +650,7 @@ const puterInit = (function() {
|
|
|
650
650
|
/**
|
|
651
651
|
* Disables API call logging
|
|
652
652
|
*/
|
|
653
|
-
disableAPILogging = function() {
|
|
653
|
+
disableAPILogging = function () {
|
|
654
654
|
if ( this.apiCallLogger ) {
|
|
655
655
|
this.apiCallLogger.disable();
|
|
656
656
|
}
|
|
@@ -661,7 +661,7 @@ const puterInit = (function() {
|
|
|
661
661
|
* Initializes network connectivity monitoring to purge cache when connection is lost
|
|
662
662
|
* @private
|
|
663
663
|
*/
|
|
664
|
-
initNetworkMonitoring = function() {
|
|
664
|
+
initNetworkMonitoring = function () {
|
|
665
665
|
// Only initialize in environments that support navigator.onLine and window events
|
|
666
666
|
if ( typeof globalThis.navigator === 'undefined' ||
|
|
667
667
|
typeof globalThis.addEventListener !== 'function' ) {
|
|
@@ -681,7 +681,7 @@ const puterInit = (function() {
|
|
|
681
681
|
try {
|
|
682
682
|
this._cache.flushall();
|
|
683
683
|
console.log('Cache purged successfully');
|
|
684
|
-
} catch( error ) {
|
|
684
|
+
} catch ( error ) {
|
|
685
685
|
console.error('Error purging cache:', error);
|
|
686
686
|
}
|
|
687
687
|
}
|
|
@@ -708,11 +708,11 @@ const puterInit = (function() {
|
|
|
708
708
|
* Checks and updates the GUI FS cache for most-commonly used paths
|
|
709
709
|
* @private
|
|
710
710
|
*/
|
|
711
|
-
checkAndUpdateGUIFScache = function(){
|
|
711
|
+
checkAndUpdateGUIFScache = function () {
|
|
712
712
|
// only run in gui environment
|
|
713
|
-
if(puter.env !== 'gui') return;
|
|
713
|
+
if ( puter.env !== 'gui' ) return;
|
|
714
714
|
// only run if user is authenticated
|
|
715
|
-
if(!puter.whoami) return;
|
|
715
|
+
if ( ! puter.whoami ) return;
|
|
716
716
|
|
|
717
717
|
let username = puter.whoami.username;
|
|
718
718
|
|
|
@@ -723,55 +723,55 @@ const puterInit = (function() {
|
|
|
723
723
|
let public_path = `/${username}/Public`;
|
|
724
724
|
|
|
725
725
|
// item:Home
|
|
726
|
-
if(!puter._cache.get(
|
|
726
|
+
if ( ! puter._cache.get(`item:${ home_path}`) ) {
|
|
727
727
|
console.log(`/${username} item is not cached, refetching cache`);
|
|
728
728
|
// fetch home
|
|
729
729
|
puter.fs.stat(home_path);
|
|
730
730
|
}
|
|
731
731
|
// item:Desktop
|
|
732
|
-
if(!puter._cache.get(
|
|
732
|
+
if ( ! puter._cache.get(`item:${ desktop_path}`) ) {
|
|
733
733
|
console.log(`/${username}/Desktop item is not cached, refetching cache`);
|
|
734
734
|
// fetch desktop
|
|
735
735
|
puter.fs.stat(desktop_path);
|
|
736
736
|
}
|
|
737
737
|
// item:Documents
|
|
738
|
-
if(!puter._cache.get(
|
|
738
|
+
if ( ! puter._cache.get(`item:${ documents_path}`) ) {
|
|
739
739
|
console.log(`/${username}/Documents item is not cached, refetching cache`);
|
|
740
740
|
// fetch documents
|
|
741
741
|
puter.fs.stat(documents_path);
|
|
742
742
|
}
|
|
743
743
|
// item:Public
|
|
744
|
-
if(!puter._cache.get(
|
|
744
|
+
if ( ! puter._cache.get(`item:${ public_path}`) ) {
|
|
745
745
|
console.log(`/${username}/Public item is not cached, refetching cache`);
|
|
746
746
|
// fetch public
|
|
747
747
|
puter.fs.stat(public_path);
|
|
748
748
|
}
|
|
749
749
|
|
|
750
750
|
// readdir:Home
|
|
751
|
-
if(!puter._cache.get(
|
|
751
|
+
if ( ! puter._cache.get(`readdir:${ home_path}`) ) {
|
|
752
752
|
console.log(`/${username} is not cached, refetching cache`);
|
|
753
753
|
// fetch home
|
|
754
754
|
puter.fs.readdir(home_path);
|
|
755
755
|
}
|
|
756
756
|
// readdir:Desktop
|
|
757
|
-
if(!puter._cache.get(
|
|
757
|
+
if ( ! puter._cache.get(`readdir:${ desktop_path}`) ) {
|
|
758
758
|
console.log(`/${username}/Desktop is not cached, refetching cache`);
|
|
759
759
|
// fetch desktop
|
|
760
760
|
puter.fs.readdir(desktop_path);
|
|
761
761
|
}
|
|
762
762
|
// readdir:Documents
|
|
763
|
-
if(!puter._cache.get(
|
|
763
|
+
if ( ! puter._cache.get(`readdir:${ documents_path}`) ) {
|
|
764
764
|
console.log(`/${username}/Documents is not cached, refetching cache`);
|
|
765
765
|
// fetch documents
|
|
766
766
|
puter.fs.readdir(documents_path);
|
|
767
767
|
}
|
|
768
768
|
// readdir:Public
|
|
769
|
-
if(!puter._cache.get(
|
|
769
|
+
if ( ! puter._cache.get(`readdir:${ public_path}`) ) {
|
|
770
770
|
console.log(`/${username}/Public is not cached, refetching cache`);
|
|
771
771
|
// fetch public
|
|
772
772
|
puter.fs.readdir(public_path);
|
|
773
773
|
}
|
|
774
|
-
}
|
|
774
|
+
};
|
|
775
775
|
}
|
|
776
776
|
|
|
777
777
|
// Create a new Puter object and return it
|
|
@@ -785,11 +785,48 @@ export const puter = puterInit();
|
|
|
785
785
|
export default puter;
|
|
786
786
|
globalThis.puter = puter;
|
|
787
787
|
|
|
788
|
+
puter.tools = [];
|
|
789
|
+
/**
|
|
790
|
+
* @type {{messageTarget: Window}}
|
|
791
|
+
*/
|
|
792
|
+
const puterParent = puter.ui.parentApp();
|
|
793
|
+
globalThis.puterParent = puterParent;
|
|
794
|
+
if ( puterParent ) {
|
|
795
|
+
console.log('I have a parent, registering tools');
|
|
796
|
+
puterParent.on('message', async (event) => {
|
|
797
|
+
console.log('Got tool req ', event);
|
|
798
|
+
if ( event.$ === 'requestTools' ) {
|
|
799
|
+
console.log('Responding with tools');
|
|
800
|
+
puterParent.postMessage({
|
|
801
|
+
$: 'providedTools',
|
|
802
|
+
tools: JSON.parse(JSON.stringify(puter.tools)),
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
|
|
806
|
+
if ( event.$ === 'executeTool' ) {
|
|
807
|
+
console.log('xecuting tools');
|
|
808
|
+
/**
|
|
809
|
+
* Puter tools format
|
|
810
|
+
* @type {[{exec: Function, function: {description: string, name: string, parameters: {properties: any, required: Array<string>}, type: string}}]}
|
|
811
|
+
*/
|
|
812
|
+
const [tool] = puter.tools.filter(e => e.function.name === event.toolName);
|
|
813
|
+
|
|
814
|
+
const response = await tool.exec(event.parameters);
|
|
815
|
+
puterParent.postMessage({
|
|
816
|
+
$: 'toolResponse',
|
|
817
|
+
response,
|
|
818
|
+
tag: event.tag,
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
});
|
|
822
|
+
puterParent.postMessage({ $: 'ready' });
|
|
823
|
+
}
|
|
824
|
+
|
|
788
825
|
globalThis.addEventListener && globalThis.addEventListener('message', async (event) => {
|
|
789
826
|
// if the message is not from Puter, then ignore it
|
|
790
827
|
if ( event.origin !== puter.defaultGUIOrigin ) return;
|
|
791
828
|
|
|
792
|
-
if ( event.data.msg && event.data.msg === 'requestOrigin' ){
|
|
829
|
+
if ( event.data.msg && event.data.msg === 'requestOrigin' ) {
|
|
793
830
|
event.source.postMessage({
|
|
794
831
|
msg: 'originResponse',
|
|
795
832
|
}, '*');
|
|
@@ -808,7 +845,7 @@ globalThis.addEventListener && globalThis.addEventListener('message', async (eve
|
|
|
808
845
|
// resolve();
|
|
809
846
|
|
|
810
847
|
// Call onAuth callback
|
|
811
|
-
if ( puter.onAuth && typeof puter.onAuth === 'function' ){
|
|
848
|
+
if ( puter.onAuth && typeof puter.onAuth === 'function' ) {
|
|
812
849
|
puter.getUser().then((user) => {
|
|
813
850
|
puter.onAuth(user);
|
|
814
851
|
});
|