pinokiod 3.40.0 → 3.42.0
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/kernel/api/browser/index.js +3 -1
- package/kernel/api/cloudflare/index.js +3 -3
- package/kernel/api/index.js +187 -51
- package/kernel/api/loading/index.js +15 -0
- package/kernel/api/process/index.js +7 -0
- package/kernel/api/shell/index.js +0 -2
- package/kernel/bin/browserless.js +22 -0
- package/kernel/bin/caddy.js +36 -4
- package/kernel/bin/index.js +4 -1
- package/kernel/bin/setup.js +38 -5
- package/kernel/connect/backend.js +110 -0
- package/kernel/connect/config.js +171 -0
- package/kernel/connect/index.js +18 -7
- package/kernel/connect/providers/huggingface/index.js +98 -0
- package/kernel/connect/providers/x/index.js +0 -1
- package/kernel/environment.js +91 -19
- package/kernel/git.js +46 -3
- package/kernel/index.js +119 -39
- package/kernel/peer.js +40 -5
- package/kernel/plugin.js +3 -2
- package/kernel/procs.js +27 -20
- package/kernel/prototype.js +30 -16
- package/kernel/router/common.js +1 -1
- package/kernel/router/connector.js +1 -3
- package/kernel/router/index.js +38 -4
- package/kernel/router/localhost_home_router.js +5 -1
- package/kernel/router/localhost_port_router.js +27 -1
- package/kernel/router/localhost_static_router.js +93 -0
- package/kernel/router/localhost_variable_router.js +14 -9
- package/kernel/router/peer_peer_router.js +3 -0
- package/kernel/router/peer_static_router.js +43 -0
- package/kernel/router/peer_variable_router.js +15 -14
- package/kernel/router/processor.js +26 -1
- package/kernel/router/rewriter.js +59 -0
- package/kernel/scripts/git/commit +11 -1
- package/kernel/shell.js +8 -3
- package/kernel/util.js +65 -6
- package/package.json +2 -1
- package/server/index.js +1048 -970
- package/server/public/common.js +382 -1
- package/server/public/fscreator.js +0 -1
- package/server/public/loading.js +17 -0
- package/server/public/notifyinput.js +0 -1
- package/server/public/opener.js +4 -2
- package/server/public/style.css +310 -11
- package/server/socket.js +7 -1
- package/server/views/app.ejs +1747 -351
- package/server/views/columns.ejs +338 -0
- package/server/views/connect/huggingface.ejs +353 -0
- package/server/views/connect/index.ejs +410 -0
- package/server/views/connect/x.ejs +43 -9
- package/server/views/connect.ejs +709 -49
- package/server/views/container.ejs +357 -0
- package/server/views/d.ejs +251 -62
- package/server/views/download.ejs +54 -10
- package/server/views/editor.ejs +11 -0
- package/server/views/explore.ejs +40 -15
- package/server/views/file_explorer.ejs +25 -246
- package/server/views/form.ejs +44 -1
- package/server/views/frame.ejs +39 -1
- package/server/views/github.ejs +48 -11
- package/server/views/help.ejs +48 -7
- package/server/views/index.ejs +119 -58
- package/server/views/index2.ejs +3 -4
- package/server/views/init/index.ejs +651 -197
- package/server/views/install.ejs +1 -1
- package/server/views/mini.ejs +47 -18
- package/server/views/net.ejs +199 -67
- package/server/views/network.ejs +229 -93
- package/server/views/network2.ejs +3 -4
- package/server/views/old_network.ejs +3 -3
- package/server/views/prototype/index.ejs +48 -11
- package/server/views/review.ejs +1005 -0
- package/server/views/rows.ejs +341 -0
- package/server/views/screenshots.ejs +1020 -0
- package/server/views/settings.ejs +160 -23
- package/server/views/setup.ejs +49 -7
- package/server/views/setup_home.ejs +43 -10
- package/server/views/shell.ejs +7 -1
- package/server/views/start.ejs +14 -9
- package/server/views/terminal.ejs +13 -2
- package/server/views/tools.ejs +1015 -0
package/server/index.js
CHANGED
|
@@ -23,6 +23,7 @@ const fse = require('fs-extra')
|
|
|
23
23
|
const QRCode = require('qrcode')
|
|
24
24
|
const axios = require('axios')
|
|
25
25
|
const crypto = require('crypto')
|
|
26
|
+
const serveIndex = require('serve-index')
|
|
26
27
|
|
|
27
28
|
const git = require('isomorphic-git')
|
|
28
29
|
const http = require('isomorphic-git/http/node')
|
|
@@ -60,8 +61,6 @@ function normalize(str) {
|
|
|
60
61
|
|
|
61
62
|
class Server {
|
|
62
63
|
constructor(config) {
|
|
63
|
-
this.menu_hidden = {}
|
|
64
|
-
this.selected = {}
|
|
65
64
|
this.tabs = {}
|
|
66
65
|
this.agent = config.agent
|
|
67
66
|
this.port = DEFAULT_PORT
|
|
@@ -112,38 +111,6 @@ class Server {
|
|
|
112
111
|
exists (s) {
|
|
113
112
|
return new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e)))
|
|
114
113
|
}
|
|
115
|
-
async updateMeta(formData, app_path) {
|
|
116
|
-
// write title/description to pinokio.json
|
|
117
|
-
let dirty
|
|
118
|
-
let meta_path = this.kernel.path("api", app_path, "pinokio.json")
|
|
119
|
-
let meta = (await this.kernel.loader.load(meta_path)).resolved
|
|
120
|
-
if (!meta) meta = {}
|
|
121
|
-
if (formData.title) {
|
|
122
|
-
meta.title = formData.title
|
|
123
|
-
dirty = true
|
|
124
|
-
}
|
|
125
|
-
if (formData.description) {
|
|
126
|
-
meta.description = formData.description
|
|
127
|
-
dirty = true
|
|
128
|
-
}
|
|
129
|
-
if (!meta.plugin) {
|
|
130
|
-
meta.plugin = {
|
|
131
|
-
menu: []
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (formData.icon_dirty) {
|
|
136
|
-
//
|
|
137
|
-
// write icon file
|
|
138
|
-
let icon_path = this.kernel.path("api", formData.new_path, formData.icon_path)
|
|
139
|
-
await fs.promises.writeFile(icon_path, formData.avatar)
|
|
140
|
-
meta.icon = formData.icon_path
|
|
141
|
-
dirty = true
|
|
142
|
-
}
|
|
143
|
-
if (dirty) {
|
|
144
|
-
await fs.promises.writeFile(meta_path, JSON.stringify(meta, null, 2))
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
114
|
running_dynamic (name, menu) {
|
|
148
115
|
let cwd = this.kernel.path("api", name)
|
|
149
116
|
let running_dynamic = []
|
|
@@ -204,24 +171,6 @@ class Server {
|
|
|
204
171
|
traverse(menu)
|
|
205
172
|
return running_dynamic
|
|
206
173
|
}
|
|
207
|
-
async createMeta(formData) {
|
|
208
|
-
let _path = this.kernel.path("api", formData.path)
|
|
209
|
-
await fs.promises.mkdir(_path, { recursive: true }).catch((e) => {})
|
|
210
|
-
let icon_path = this.kernel.path("api", formData.path, "icon.png")
|
|
211
|
-
await fs.promises.writeFile(icon_path, formData.avatar)
|
|
212
|
-
|
|
213
|
-
// write title/description to pinokio.json
|
|
214
|
-
let meta_path = this.kernel.path("api", formData.path, "pinokio.json")
|
|
215
|
-
let meta = {
|
|
216
|
-
title: formData.title,
|
|
217
|
-
description: formData.description,
|
|
218
|
-
icon: "icon.png",
|
|
219
|
-
plugin: {
|
|
220
|
-
menu: []
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
await fs.promises.writeFile(meta_path, JSON.stringify(meta, null, 2))
|
|
224
|
-
}
|
|
225
174
|
getMemory(filepath) {
|
|
226
175
|
let localMem = this.kernel.memory.local[filepath]
|
|
227
176
|
let globalMem = this.kernel.memory.global[filepath]
|
|
@@ -287,14 +236,22 @@ class Server {
|
|
|
287
236
|
name = x.name
|
|
288
237
|
description = ""
|
|
289
238
|
}
|
|
239
|
+
|
|
240
|
+
|
|
290
241
|
let browser_url
|
|
242
|
+
let target
|
|
243
|
+
|
|
291
244
|
if (x.run) {
|
|
292
245
|
browser_url = "/env/api/" + x.name
|
|
293
246
|
} else {
|
|
294
247
|
//browser_url = "/pinokio/browser/" + x.name
|
|
295
248
|
browser_url = "/p/" + x.name
|
|
296
249
|
}
|
|
297
|
-
let
|
|
250
|
+
let dev_url = browser_url + "/dev"
|
|
251
|
+
let review_url = browser_url + "/review"
|
|
252
|
+
|
|
253
|
+
let dns = this.kernel.pinokio_configs[x.name].dns
|
|
254
|
+
let routes = dns["@"]
|
|
298
255
|
return {
|
|
299
256
|
filepath: this.kernel.path("api", x.name),
|
|
300
257
|
icon,
|
|
@@ -313,12 +270,86 @@ class Server {
|
|
|
313
270
|
description,
|
|
314
271
|
url: p + "/" + x.name,
|
|
315
272
|
browser_url,
|
|
273
|
+
target,
|
|
316
274
|
url: browser_url,
|
|
317
275
|
path: uri,
|
|
318
|
-
|
|
276
|
+
dev_url,
|
|
277
|
+
review_url,
|
|
319
278
|
}
|
|
320
279
|
})
|
|
321
280
|
}
|
|
281
|
+
async getGit(ref, filepath) {
|
|
282
|
+
let dir = this.kernel.path("api", filepath)
|
|
283
|
+
let branches = await git.listBranches({ fs, dir });
|
|
284
|
+
let log = []
|
|
285
|
+
try {
|
|
286
|
+
log = await git.log({ fs, dir, depth: 50, ref: ref }); // fetch last 50 commits
|
|
287
|
+
log.forEach((item) => {
|
|
288
|
+
item.info = `/gitcommit/${item.oid}/${filepath}`
|
|
289
|
+
})
|
|
290
|
+
} catch (e) {
|
|
291
|
+
console.log("Log error", e)
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
let config = await this.kernel.git.config(dir)
|
|
295
|
+
|
|
296
|
+
let hosts = ""
|
|
297
|
+
let hosts_file = this.kernel.path("config/gh/hosts.yml")
|
|
298
|
+
let e = await this.exists(hosts_file)
|
|
299
|
+
if (e) {
|
|
300
|
+
hosts = await fs.promises.readFile(hosts_file, "utf8")
|
|
301
|
+
if (hosts.startsWith("{}")) {
|
|
302
|
+
hosts = ""
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
let connected = (hosts.length > 0)
|
|
306
|
+
let remote = null
|
|
307
|
+
if (config["remote \"origin\""]) {
|
|
308
|
+
remote = config["remote \"origin\""].url
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
let branch = await git.currentBranch({ fs, dir, fullname: false });
|
|
312
|
+
|
|
313
|
+
const remote2 = await git.getConfig({
|
|
314
|
+
fs,
|
|
315
|
+
dir,
|
|
316
|
+
path: `branch.${branch}.remote`
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// if current branch exitss => currengt branch is selected
|
|
320
|
+
// if current branch does not exist => get logs[0].oid
|
|
321
|
+
if (branch) {
|
|
322
|
+
branches = branches.map((b) => {
|
|
323
|
+
if (b === branch) {
|
|
324
|
+
return {
|
|
325
|
+
branch: b,
|
|
326
|
+
selected: true
|
|
327
|
+
}
|
|
328
|
+
} else {
|
|
329
|
+
return {
|
|
330
|
+
branch: b,
|
|
331
|
+
selected: false
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
})
|
|
335
|
+
} else {
|
|
336
|
+
branches.push(log[0].oid)
|
|
337
|
+
branches = branches.map((b) => {
|
|
338
|
+
if (b === log[0].oid) {
|
|
339
|
+
return {
|
|
340
|
+
branch: b,
|
|
341
|
+
selected: true
|
|
342
|
+
}
|
|
343
|
+
} else {
|
|
344
|
+
return {
|
|
345
|
+
branch: b,
|
|
346
|
+
selected: false
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
})
|
|
350
|
+
}
|
|
351
|
+
return { ref, config, remote, connected, log, branch, branches, dir }
|
|
352
|
+
}
|
|
322
353
|
async init_env(env_dir_path, options) {
|
|
323
354
|
let current = this.kernel.path(env_dir_path, "ENVIRONMENT")
|
|
324
355
|
// if environment.json doesn't exist,
|
|
@@ -338,7 +369,7 @@ class Server {
|
|
|
338
369
|
await fs.promises.writeFile(current, _environmentStr)
|
|
339
370
|
}
|
|
340
371
|
} else {
|
|
341
|
-
let content = await Environment.ENV("app", this.kernel.homedir)
|
|
372
|
+
let content = await Environment.ENV("app", this.kernel.homedir, this.kernel)
|
|
342
373
|
if (_exists) {
|
|
343
374
|
let _environmentStr = await fs.promises.readFile(_environment, "utf8")
|
|
344
375
|
await fs.promises.writeFile(current, _environmentStr + "\n\n\n" + content)
|
|
@@ -348,31 +379,45 @@ class Server {
|
|
|
348
379
|
}
|
|
349
380
|
}
|
|
350
381
|
}
|
|
351
|
-
async
|
|
352
|
-
let
|
|
353
|
-
let
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
u.pathname = current_path
|
|
360
|
-
}
|
|
361
|
-
current_urls.http = u.toString()
|
|
362
|
-
|
|
363
|
-
// https
|
|
364
|
-
if (router_running.success) {
|
|
365
|
-
let u = new URL("https://pinokio.localhost")
|
|
366
|
-
if (current_path) {
|
|
367
|
-
u.pathname = current_path
|
|
382
|
+
async get_github_hosts() {
|
|
383
|
+
let hosts = ""
|
|
384
|
+
let hosts_file = this.kernel.path("config/gh/hosts.yml")
|
|
385
|
+
let e = await this.exists(hosts_file)
|
|
386
|
+
if (e) {
|
|
387
|
+
hosts = await fs.promises.readFile(hosts_file, "utf8")
|
|
388
|
+
if (hosts.startsWith("{}")) {
|
|
389
|
+
hosts = ""
|
|
368
390
|
}
|
|
369
|
-
current_urls.https = u.toString()
|
|
370
391
|
}
|
|
371
|
-
|
|
372
|
-
|
|
392
|
+
return hosts
|
|
393
|
+
}
|
|
394
|
+
async current_urls(current_path) {
|
|
395
|
+
return {}
|
|
396
|
+
// let router_running = await this.check_router_up()
|
|
397
|
+
// let u = new URL("http://localhost:42000")
|
|
398
|
+
//
|
|
399
|
+
// let current_urls = {}
|
|
400
|
+
//
|
|
401
|
+
// // http
|
|
402
|
+
// if (current_path) {
|
|
403
|
+
// u.pathname = current_path
|
|
404
|
+
// }
|
|
405
|
+
// current_urls.http = u.toString()
|
|
406
|
+
//
|
|
407
|
+
// // https
|
|
408
|
+
// if (router_running.success) {
|
|
409
|
+
// let u = new URL("https://pinokio.localhost")
|
|
410
|
+
// if (current_path) {
|
|
411
|
+
// u.pathname = current_path
|
|
412
|
+
// }
|
|
413
|
+
// current_urls.https = u.toString()
|
|
414
|
+
// }
|
|
415
|
+
//
|
|
416
|
+
// return current_urls
|
|
373
417
|
}
|
|
374
418
|
|
|
375
419
|
async chrome(req, res, type) {
|
|
420
|
+
|
|
376
421
|
let d = Date.now()
|
|
377
422
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
378
423
|
bin: this.kernel.bin.preset("dev"),
|
|
@@ -408,32 +453,6 @@ class Server {
|
|
|
408
453
|
}
|
|
409
454
|
}
|
|
410
455
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
// let requires_instantiation = false
|
|
414
|
-
// console.log("## CONFIG", config)
|
|
415
|
-
// if (config && config.pre) {
|
|
416
|
-
// let env = await Environment.get2(app_path, this.kernel)
|
|
417
|
-
// for(let item of config.pre) {
|
|
418
|
-
// console.log("ITEM" , item)
|
|
419
|
-
// if (item.env) {
|
|
420
|
-
// if (env[item.env]) {
|
|
421
|
-
//
|
|
422
|
-
// } else {
|
|
423
|
-
// requires_instantiation = true
|
|
424
|
-
// break;
|
|
425
|
-
// }
|
|
426
|
-
// }
|
|
427
|
-
// }
|
|
428
|
-
// }
|
|
429
|
-
// console.log({ requires_instantiation })
|
|
430
|
-
// if (requires_instantiation) {
|
|
431
|
-
// // redirect to pre
|
|
432
|
-
// res.redirect("/required_env/api/" + name)
|
|
433
|
-
// return
|
|
434
|
-
// }
|
|
435
|
-
|
|
436
|
-
|
|
437
456
|
let menu = config.menu || []
|
|
438
457
|
try {
|
|
439
458
|
if (typeof config.menu === "function") {
|
|
@@ -448,80 +467,53 @@ class Server {
|
|
|
448
467
|
config.menu = []
|
|
449
468
|
}
|
|
450
469
|
|
|
470
|
+
|
|
451
471
|
let uri = this.kernel.path("api")
|
|
452
472
|
try {
|
|
473
|
+
let launcher = await this.kernel.api.launcher(name)
|
|
474
|
+
req.launcher_root = launcher.launcher_root
|
|
453
475
|
await this.renderMenu(req, uri, name, config, [])
|
|
454
476
|
} catch(e) {
|
|
455
477
|
config.menu = []
|
|
456
478
|
err = e.stack
|
|
457
479
|
}
|
|
458
480
|
|
|
459
|
-
|
|
460
481
|
let platform = os.platform()
|
|
461
482
|
|
|
462
|
-
|
|
463
|
-
// //config.iconpath = this.kernel.path("api", name, config.icon)
|
|
464
|
-
// config.iconpath = config.icon
|
|
465
|
-
// config.icon = `${rawpath}/${config.icon}?raw=true`
|
|
466
|
-
// } else {
|
|
467
|
-
// //config.iconpath = this.kernel.path("api", name, "pinokio_icon.png")
|
|
468
|
-
// config.iconpath = "pinokio.png"
|
|
469
|
-
// config.icon = "/pinokio-black.png"
|
|
470
|
-
// }
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
// // get all memory variable stied to the current repository
|
|
474
|
-
// let api_path = this.kernel.path("api", name)
|
|
475
|
-
// let mem = {}
|
|
476
|
-
// for(let type in this.kernel.memory) {
|
|
477
|
-
// // type := local|global
|
|
478
|
-
// let vars = this.kernel.memory[type]
|
|
479
|
-
// for(let k in vars) {
|
|
480
|
-
// if (k.includes(api_path)) {
|
|
481
|
-
// if (mem[k]) {
|
|
482
|
-
// mem[k][type] = vars[k]
|
|
483
|
-
// } else {
|
|
484
|
-
// mem[k] = {
|
|
485
|
-
// [type]: vars[k]
|
|
486
|
-
// }
|
|
487
|
-
// }
|
|
488
|
-
// }
|
|
489
|
-
// }
|
|
490
|
-
// }
|
|
491
|
-
|
|
492
|
-
// console.time("2 chrome " + d)
|
|
493
|
-
await this.init_env("api/" + name)
|
|
483
|
+
await Environment.init({ name }, this.kernel)
|
|
494
484
|
|
|
495
485
|
// copy gitignore from ~pinokio/prototype/system/gitignore if it doesn't exist
|
|
496
486
|
|
|
497
487
|
|
|
498
488
|
let gitignore_path = this.kernel.path("api/" + name + "/.gitignore")
|
|
489
|
+
let dot_path = this.kernel.path("api", name, "pinokio")
|
|
499
490
|
let gitignore_template_path = this.kernel.path("prototype/system/gitignore")
|
|
500
491
|
let template_exists = await this.exists(gitignore_template_path)
|
|
501
492
|
if (template_exists) {
|
|
502
|
-
await
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
493
|
+
let exists = await this.exists(dot_path)
|
|
494
|
+
if (exists) {
|
|
495
|
+
// 1. when importing existing projects (.pinokio exists), don't mess with .gitignore
|
|
496
|
+
} else {
|
|
497
|
+
// 2. otherwise, merge gitignore
|
|
498
|
+
await Util.mergeLines(
|
|
499
|
+
gitignore_path, // existing path
|
|
500
|
+
gitignore_template_path // overwrite with template
|
|
501
|
+
)
|
|
502
|
+
}
|
|
506
503
|
}
|
|
507
504
|
|
|
508
505
|
|
|
509
506
|
|
|
510
507
|
|
|
511
|
-
// console.timeEnd("2 chrome " + d)
|
|
512
|
-
|
|
513
|
-
// console.time("3 chrome " + d)
|
|
514
508
|
let mode = "run"
|
|
515
509
|
if (req.query && req.query.mode) {
|
|
516
510
|
mode = req.query.mode
|
|
517
511
|
}
|
|
518
512
|
const env = await this.kernel.env("api/" + name)
|
|
519
|
-
// console.timeEnd("3 chrome " + d)
|
|
520
513
|
|
|
521
514
|
// profile + feed
|
|
522
515
|
const repositoryPath = path.resolve(this.kernel.api.userdir, name)
|
|
523
516
|
|
|
524
|
-
// console.time("4 chrome " + d)
|
|
525
517
|
try {
|
|
526
518
|
await git.resolveRef({ fs, dir: repositoryPath, ref: 'HEAD' });
|
|
527
519
|
} catch (err) {
|
|
@@ -530,9 +522,6 @@ class Server {
|
|
|
530
522
|
await git.init({ fs, dir: repositoryPath });
|
|
531
523
|
}
|
|
532
524
|
|
|
533
|
-
// console.timeEnd("4 chrome " + d)
|
|
534
|
-
|
|
535
|
-
// console.time("5 chrome " + d)
|
|
536
525
|
let gitRemote = await git.getConfig({ fs, http, dir: repositoryPath, path: 'remote.origin.url' })
|
|
537
526
|
let profile
|
|
538
527
|
let feed
|
|
@@ -541,24 +530,18 @@ class Server {
|
|
|
541
530
|
|
|
542
531
|
let system_env = {}
|
|
543
532
|
if (this.kernel.homedir) {
|
|
544
|
-
system_env = await Environment.get(this.kernel.homedir)
|
|
533
|
+
system_env = await Environment.get(this.kernel.homedir, this.kernel)
|
|
545
534
|
}
|
|
546
535
|
profile = this.profile(gitRemote)
|
|
547
536
|
feed = this.newsfeed(gitRemote)
|
|
548
537
|
}
|
|
549
|
-
// console.timeEnd("5 chrome " + d)
|
|
550
538
|
|
|
551
539
|
// git
|
|
552
540
|
|
|
553
541
|
let c = this.kernel.path("api", name)
|
|
554
542
|
|
|
555
|
-
// console.time("6 chrome " + d)
|
|
556
543
|
// await this.kernel.plugin.init()
|
|
557
|
-
// console.timeEnd("6 chrome " + d)
|
|
558
|
-
// console.time("7 chrome " + d)
|
|
559
544
|
// let plugin = await this.getPlugin(name)
|
|
560
|
-
// console.timeEnd("7 chrome " + d)
|
|
561
|
-
// console.time("8 chrome " + d)
|
|
562
545
|
// let plugin_menu = null
|
|
563
546
|
// if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
564
547
|
// let running_dynamic = this.running_dynamic(name, plugin.menu)
|
|
@@ -569,15 +552,12 @@ class Server {
|
|
|
569
552
|
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
570
553
|
|
|
571
554
|
let plugin_menu = null
|
|
572
|
-
let
|
|
555
|
+
let plugin_config = structuredClone(this.kernel.plugin.config)
|
|
556
|
+
let plugin = await this.getPlugin(req, plugin_config, name)
|
|
573
557
|
if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
574
558
|
plugin = structuredClone(plugin)
|
|
575
559
|
plugin_menu = this.running_dynamic(name, plugin.menu)
|
|
576
560
|
}
|
|
577
|
-
let menu_hidden = false
|
|
578
|
-
if (this.menu_hidden[name] && this.menu_hidden[name][type]) {
|
|
579
|
-
menu_hidden = true
|
|
580
|
-
}
|
|
581
561
|
|
|
582
562
|
let posix_path = Util.p2u(this.kernel.path("api", name))
|
|
583
563
|
let dev_link
|
|
@@ -587,9 +567,13 @@ class Server {
|
|
|
587
567
|
dev_link = "/d/" + posix_path
|
|
588
568
|
}
|
|
589
569
|
|
|
570
|
+
let run_tab = "/p/" + name
|
|
571
|
+
let dev_tab = "/p/" + name + "/dev"
|
|
572
|
+
let review_tab = "/p/" + name + "/review"
|
|
573
|
+
|
|
574
|
+
|
|
590
575
|
const result = {
|
|
591
576
|
dev_link,
|
|
592
|
-
minimized: menu_hidden,
|
|
593
577
|
// repos,
|
|
594
578
|
current_urls,
|
|
595
579
|
path: this.kernel.path("api", name),
|
|
@@ -619,20 +603,22 @@ class Server {
|
|
|
619
603
|
config,
|
|
620
604
|
// sidebar_url: "/pinokio/sidebar/" + name,
|
|
621
605
|
home: req.originalUrl,
|
|
606
|
+
run_tab,
|
|
607
|
+
dev_tab,
|
|
608
|
+
review_tab,
|
|
622
609
|
// paths,
|
|
623
610
|
theme: this.theme,
|
|
624
611
|
agent: this.agent,
|
|
625
612
|
src: "/_api/" + name,
|
|
626
613
|
logs: "/_api/" + name + "/logs",
|
|
627
614
|
execUrl: "/api/" + name,
|
|
615
|
+
git_monitor_url: `/gitcommit/HEAD/${name}`,
|
|
616
|
+
git_history_url: `/info/git/HEAD/${name}`,
|
|
628
617
|
// rawpath,
|
|
629
618
|
}
|
|
630
|
-
// console.timeEnd("8 chrome " + d)
|
|
631
|
-
// console.time("9 chrome " + d)
|
|
632
619
|
// if (!this.kernel.proto.config) {
|
|
633
620
|
// await this.kernel.proto.init()
|
|
634
621
|
// }
|
|
635
|
-
// console.timeEnd("9 chrome " + d)
|
|
636
622
|
res.render("app", result)
|
|
637
623
|
}
|
|
638
624
|
getVariationUrls(req) {
|
|
@@ -651,12 +637,13 @@ class Server {
|
|
|
651
637
|
return { editorUrl, prevUrl }
|
|
652
638
|
}
|
|
653
639
|
get_shell_id(name, i, rendered) {
|
|
654
|
-
let hash = crypto.createHash('md5').update(JSON.stringify(rendered)).digest('hex')
|
|
655
640
|
let shell_id
|
|
656
641
|
if (rendered.id) {
|
|
657
642
|
shell_id = encodeURIComponent(`${name}_${rendered.id}`)
|
|
658
643
|
} else {
|
|
659
|
-
|
|
644
|
+
let hash = crypto.createHash('md5').update(JSON.stringify(rendered)).digest('hex')
|
|
645
|
+
//shell_id = encodeURIComponent(`${name}_${i}_session_${hash}`)
|
|
646
|
+
shell_id = encodeURIComponent(`${name}_session_${hash}`)
|
|
660
647
|
}
|
|
661
648
|
return shell_id
|
|
662
649
|
}
|
|
@@ -728,50 +715,11 @@ class Server {
|
|
|
728
715
|
|
|
729
716
|
}
|
|
730
717
|
|
|
731
|
-
// if (pathComponents.length > 1) {
|
|
732
|
-
// if (pathComponents[1] === 'web') {
|
|
733
|
-
// let filepath = this.kernel.path("api", ...pathComponents)
|
|
734
|
-
// console.log("filepath", filepath)
|
|
735
|
-
// try {
|
|
736
|
-
// console.log("testing")
|
|
737
|
-
// let stat = await fs.promises.stat(filepath)
|
|
738
|
-
// console.log("stat", stat)
|
|
739
|
-
// // if it's a folder
|
|
740
|
-
// if (stat.isDirectory()) {
|
|
741
|
-
// // if the current folder has "index.html", send that file
|
|
742
|
-
// // otherwise 404
|
|
743
|
-
// let indexFile = path.resolve(filepath, "index.html")
|
|
744
|
-
// let exists = await this.exists(indexFile)
|
|
745
|
-
// if (exists) {
|
|
746
|
-
// res.sendFile(indexFile)
|
|
747
|
-
// } else {
|
|
748
|
-
// // res.redirect("/api/" + pathComponents[0])
|
|
749
|
-
// res.status(404).render("404", {
|
|
750
|
-
// message: "index.html not found"
|
|
751
|
-
// })
|
|
752
|
-
// }
|
|
753
|
-
// } else if (stat.isFile()) {
|
|
754
|
-
// res.sendFile(filepath)
|
|
755
|
-
// }
|
|
756
|
-
// return
|
|
757
|
-
// } catch (e) {
|
|
758
|
-
// console.log("E", e)
|
|
759
|
-
// res.redirect("/api/" + pathComponents[0])
|
|
760
|
-
// return
|
|
761
|
-
// /*
|
|
762
|
-
// res.status(404).render("404", {
|
|
763
|
-
// message: e.message
|
|
764
|
-
// })
|
|
765
|
-
// */
|
|
766
|
-
// }
|
|
767
|
-
// }
|
|
768
|
-
// }
|
|
769
|
-
|
|
770
718
|
if (path.basename(filepath) === "ENVIRONMENT") {
|
|
771
719
|
// if environment.json doesn't exist,
|
|
772
720
|
let exists = await this.exists(filepath)
|
|
773
721
|
if (!exists) {
|
|
774
|
-
let content = await Environment.ENV("app", this.kernel.homedir)
|
|
722
|
+
let content = await Environment.ENV("app", this.kernel.homedir, this.kernel)
|
|
775
723
|
await fs.promises.writeFile(filepath, content)
|
|
776
724
|
}
|
|
777
725
|
}
|
|
@@ -816,7 +764,7 @@ class Server {
|
|
|
816
764
|
} else if (pathComponents.length === 0 && req.query.mode === "settings") {
|
|
817
765
|
let system_env = {}
|
|
818
766
|
if (this.kernel.homedir) {
|
|
819
|
-
system_env = await Environment.get(this.kernel.homedir)
|
|
767
|
+
system_env = await Environment.get(this.kernel.homedir, this.kernel)
|
|
820
768
|
}
|
|
821
769
|
let configArray = [{
|
|
822
770
|
key: "home",
|
|
@@ -837,7 +785,7 @@ class Server {
|
|
|
837
785
|
}, {
|
|
838
786
|
key: "mode",
|
|
839
787
|
val: this.mode,
|
|
840
|
-
options: ["
|
|
788
|
+
options: ["desktop", "background"]
|
|
841
789
|
}, {
|
|
842
790
|
key: "HTTP_PROXY",
|
|
843
791
|
val: (system_env.HTTP_PROXY || ""),
|
|
@@ -862,7 +810,10 @@ class Server {
|
|
|
862
810
|
drive: path.resolve(this.kernel.homedir, "drive"),
|
|
863
811
|
}
|
|
864
812
|
}
|
|
813
|
+
let list = this.getPeers()
|
|
865
814
|
res.render("settings", {
|
|
815
|
+
list,
|
|
816
|
+
current_host: this.kernel.peer.host,
|
|
866
817
|
platform,
|
|
867
818
|
version: this.version,
|
|
868
819
|
logo: this.logo,
|
|
@@ -1068,23 +1019,23 @@ class Server {
|
|
|
1068
1019
|
let env_requirements = await Environment.requirements(resolved, cwd, this.kernel)
|
|
1069
1020
|
if (env_requirements.requires_instantiation) {
|
|
1070
1021
|
//let p = Util.api_path(filepath, this.kernel)
|
|
1071
|
-
let
|
|
1022
|
+
let api_path = Util.api_path(cwd, this.kernel)
|
|
1023
|
+
let root = await Environment.get_root({ path: api_path }, this.kernel)
|
|
1024
|
+
let root_path = root.root
|
|
1072
1025
|
let platform = os.platform()
|
|
1073
1026
|
if (platform === "win32") {
|
|
1074
|
-
|
|
1027
|
+
root_path = root_path.replace(/\\/g, '\\\\')
|
|
1075
1028
|
}
|
|
1076
|
-
console.log({
|
|
1029
|
+
console.log({ cwd, api_path, root, root_path })
|
|
1077
1030
|
res.render("required_env_editor", {
|
|
1078
1031
|
portal: this.portal,
|
|
1079
1032
|
agent: this.agent,
|
|
1080
1033
|
theme: this.theme,
|
|
1081
1034
|
filename,
|
|
1082
|
-
filepath:
|
|
1035
|
+
filepath: root_path,
|
|
1083
1036
|
items: env_requirements.items
|
|
1084
1037
|
})
|
|
1085
1038
|
} else {
|
|
1086
|
-
console.log("req.query.callback", req.query.callback)
|
|
1087
|
-
|
|
1088
1039
|
// check if it's a prototype script
|
|
1089
1040
|
let kill_message
|
|
1090
1041
|
let callback
|
|
@@ -1162,7 +1113,6 @@ class Server {
|
|
|
1162
1113
|
})
|
|
1163
1114
|
}
|
|
1164
1115
|
} else if (stat.isDirectory()) {
|
|
1165
|
-
|
|
1166
1116
|
if (req.query && req.query.mode === "browser") {
|
|
1167
1117
|
return
|
|
1168
1118
|
}
|
|
@@ -1185,12 +1135,11 @@ class Server {
|
|
|
1185
1135
|
}
|
|
1186
1136
|
|
|
1187
1137
|
for(let file of files) {
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
}
|
|
1138
|
+
let type = await Util.file_type(filepath, file)
|
|
1139
|
+
if (type.directory) {
|
|
1140
|
+
f.folders.push(file)
|
|
1141
|
+
} else {
|
|
1142
|
+
f.files.push(file)
|
|
1194
1143
|
}
|
|
1195
1144
|
}
|
|
1196
1145
|
|
|
@@ -1210,8 +1159,6 @@ class Server {
|
|
|
1210
1159
|
let p = path.resolve(filepath, file.name)
|
|
1211
1160
|
config = (await this.kernel.loader.load(p)).resolved
|
|
1212
1161
|
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
1162
|
if (config && config.menu) {
|
|
1216
1163
|
if (typeof config.menu === "function") {
|
|
1217
1164
|
if (config.menu.constructor.name === "AsyncFunction") {
|
|
@@ -1272,8 +1219,13 @@ class Server {
|
|
|
1272
1219
|
|
|
1273
1220
|
|
|
1274
1221
|
// let folder = pathComponents[pathComponents.length - 1]
|
|
1275
|
-
|
|
1276
|
-
|
|
1222
|
+
if (meta) {
|
|
1223
|
+
// home => only show the folders
|
|
1224
|
+
items = f.folders
|
|
1225
|
+
} else {
|
|
1226
|
+
// app view file explorer => show all files and folders
|
|
1227
|
+
items = f.folders.concat(f.files)
|
|
1228
|
+
}
|
|
1277
1229
|
// }
|
|
1278
1230
|
let display = pathComponents.length === 0 ? ["form", "explore"] : []
|
|
1279
1231
|
//let display = ["form"]
|
|
@@ -1329,9 +1281,16 @@ class Server {
|
|
|
1329
1281
|
let index = 0
|
|
1330
1282
|
for(let i=0; i<items.length; i++) {
|
|
1331
1283
|
let item = items[i]
|
|
1332
|
-
let
|
|
1333
|
-
let config
|
|
1284
|
+
let launcher = await this.kernel.api.launcher(item.name)
|
|
1285
|
+
let config = launcher.script
|
|
1286
|
+
await this.kernel.dns({
|
|
1287
|
+
name: item.name,
|
|
1288
|
+
config
|
|
1289
|
+
})
|
|
1290
|
+
|
|
1291
|
+
|
|
1334
1292
|
if (config) {
|
|
1293
|
+
|
|
1335
1294
|
if (config.shortcuts) {
|
|
1336
1295
|
if (typeof config.shortcuts === "function") {
|
|
1337
1296
|
if (config.shortcuts.constructor.name === "AsyncFunction") {
|
|
@@ -1414,8 +1373,9 @@ class Server {
|
|
|
1414
1373
|
// other global scripts
|
|
1415
1374
|
let chunks = key.split("?")
|
|
1416
1375
|
let dev = chunks[0]
|
|
1417
|
-
let
|
|
1418
|
-
let
|
|
1376
|
+
let relpath = path.relative(this.kernel.homedir, dev)
|
|
1377
|
+
let name_chunks = relpath.split(path.sep)
|
|
1378
|
+
let name = "/" + relpath
|
|
1419
1379
|
items[i].running_scripts.push({ id: key, name })
|
|
1420
1380
|
}
|
|
1421
1381
|
} else {
|
|
@@ -1603,6 +1563,7 @@ class Server {
|
|
|
1603
1563
|
items
|
|
1604
1564
|
})
|
|
1605
1565
|
} else {
|
|
1566
|
+
console.log("RENDER FILE EXPLORER")
|
|
1606
1567
|
res.render("file_explorer", {
|
|
1607
1568
|
docs: this.docs,
|
|
1608
1569
|
portal: this.portal,
|
|
@@ -1819,9 +1780,10 @@ class Server {
|
|
|
1819
1780
|
//// icon: "fa-solid fa-gear"
|
|
1820
1781
|
// }].concat(config.menu)
|
|
1821
1782
|
|
|
1783
|
+
let launcher_root = req.launcher_root || ""
|
|
1784
|
+
|
|
1822
1785
|
for(let i=0; i<config.menu.length; i++) {
|
|
1823
1786
|
let menuitem = config.menu[i]
|
|
1824
|
-
|
|
1825
1787
|
if (menuitem.menu) {
|
|
1826
1788
|
let newIndexPath
|
|
1827
1789
|
if (indexPath) {
|
|
@@ -1841,10 +1803,10 @@ class Server {
|
|
|
1841
1803
|
// href resolution
|
|
1842
1804
|
if (menuitem.fs) {
|
|
1843
1805
|
// file explorer
|
|
1844
|
-
config.menu[i].href = path.resolve(this.kernel.homedir, "api", name, menuitem.href)
|
|
1806
|
+
config.menu[i].href = path.resolve(this.kernel.homedir, "api", name, launcher_root, menuitem.href)
|
|
1845
1807
|
} else if (menuitem.command) {
|
|
1846
1808
|
// file explorer
|
|
1847
|
-
config.menu[i].href = path.resolve(this.kernel.homedir, "api", name, menuitem.href)
|
|
1809
|
+
config.menu[i].href = path.resolve(this.kernel.homedir, "api", name, launcher_root, menuitem.href)
|
|
1848
1810
|
} else {
|
|
1849
1811
|
if (menuitem.href.startsWith("/")) {
|
|
1850
1812
|
config.menu[i].href = menuitem.href
|
|
@@ -1853,7 +1815,11 @@ class Server {
|
|
|
1853
1815
|
let seed = path.resolve(__dirname)
|
|
1854
1816
|
let p = absolute.replace(seed, "")
|
|
1855
1817
|
let link = p.split(/[\/\\]/).filter((x) => { return x }).join("/")
|
|
1856
|
-
|
|
1818
|
+
if (launcher_root) {
|
|
1819
|
+
config.menu[i].href = "/api/" + name + "/" + launcher_root + "/" + link
|
|
1820
|
+
} else {
|
|
1821
|
+
config.menu[i].href = "/api/" + name + "/" + link
|
|
1822
|
+
}
|
|
1857
1823
|
}
|
|
1858
1824
|
}
|
|
1859
1825
|
} else if (menuitem.run) {
|
|
@@ -1862,12 +1828,21 @@ class Server {
|
|
|
1862
1828
|
if (typeof rendered.run === "object") {
|
|
1863
1829
|
let run = rendered.run
|
|
1864
1830
|
config.menu[i].run = run.message
|
|
1865
|
-
|
|
1866
|
-
|
|
1831
|
+
if (launcher_root) {
|
|
1832
|
+
config.menu[i].cwd = run.path ? path.resolve(this.kernel.homedir, "api", name, launcher_root, run.path) : path.resolve(this.kernel.homedir, "api", name, launcher_root)
|
|
1833
|
+
config.menu[i].href = "/api/" + name + "/" + launcher_root
|
|
1834
|
+
} else {
|
|
1835
|
+
config.menu[i].cwd = run.path ? path.resolve(this.kernel.homedir, "api", name, run.path) : path.resolve(this.kernel.homedir, "api", name)
|
|
1836
|
+
config.menu[i].href = "/api/" + name
|
|
1837
|
+
}
|
|
1867
1838
|
} else {
|
|
1868
1839
|
config.menu[i].run = rendered.run
|
|
1869
|
-
config.menu[i].cwd = path.resolve(this.kernel.homedir, "api", name)
|
|
1870
|
-
|
|
1840
|
+
config.menu[i].cwd = path.resolve(this.kernel.homedir, "api", launcher_root, name)
|
|
1841
|
+
if (launcher_root) {
|
|
1842
|
+
config.menu[i].href = "/api/" + name + "/" + launcher_root
|
|
1843
|
+
} else {
|
|
1844
|
+
config.menu[i].href = "/api/" + name
|
|
1845
|
+
}
|
|
1871
1846
|
}
|
|
1872
1847
|
}
|
|
1873
1848
|
}
|
|
@@ -1878,8 +1853,13 @@ class Server {
|
|
|
1878
1853
|
|
|
1879
1854
|
|
|
1880
1855
|
if (menuitem.shell) {
|
|
1881
|
-
|
|
1882
|
-
|
|
1856
|
+
if (launcher_root) {
|
|
1857
|
+
let basePath = this.kernel.path("api", name, launcher_root)
|
|
1858
|
+
this.renderShell(basePath, indexPath, i, menuitem)
|
|
1859
|
+
} else {
|
|
1860
|
+
let basePath = this.kernel.path("api", name)
|
|
1861
|
+
this.renderShell(basePath, indexPath, i, menuitem)
|
|
1862
|
+
}
|
|
1883
1863
|
}
|
|
1884
1864
|
|
|
1885
1865
|
if (menuitem.href) {
|
|
@@ -1917,7 +1897,12 @@ class Server {
|
|
|
1917
1897
|
}
|
|
1918
1898
|
} else {
|
|
1919
1899
|
// prototype script
|
|
1920
|
-
let api_path
|
|
1900
|
+
let api_path
|
|
1901
|
+
if (launcher_root) {
|
|
1902
|
+
api_path = this.kernel.path("api", name, launcher_root)
|
|
1903
|
+
} else {
|
|
1904
|
+
api_path = this.kernel.path("api", name)
|
|
1905
|
+
}
|
|
1921
1906
|
let id = `${fullpath}?cwd=${api_path}`
|
|
1922
1907
|
if (this.kernel.api.running[id]) {
|
|
1923
1908
|
menuitem.running = true
|
|
@@ -1934,7 +1919,6 @@ class Server {
|
|
|
1934
1919
|
let p = absolute.replace(seed, "")
|
|
1935
1920
|
let link = p.split(/[\/\\]/).filter((x) => { return x }).join("/")
|
|
1936
1921
|
let uri = "~/api/" + name + "/" + link
|
|
1937
|
-
|
|
1938
1922
|
config.menu[i].action.uri = uri
|
|
1939
1923
|
}
|
|
1940
1924
|
}
|
|
@@ -1999,7 +1983,12 @@ class Server {
|
|
|
1999
1983
|
if (menuitem.image.startsWith("/")) {
|
|
2000
1984
|
imagePath = menuitem.image
|
|
2001
1985
|
} else {
|
|
2002
|
-
|
|
1986
|
+
console.log({ launcher_root, name, image: menuitem.image })
|
|
1987
|
+
if (launcher_root) {
|
|
1988
|
+
imagePath = `/api/${name}/${launcher_root}/${menuitem.image}?raw=true`
|
|
1989
|
+
} else {
|
|
1990
|
+
imagePath = `/api/${name}/${menuitem.image}?raw=true`
|
|
1991
|
+
}
|
|
2003
1992
|
}
|
|
2004
1993
|
menuitem.html = `<img class='menu-item-image' src='${imagePath}' /> ${menuitem.text}`
|
|
2005
1994
|
} else if (menuitem.hasOwnProperty("icon")) {
|
|
@@ -2077,10 +2066,7 @@ class Server {
|
|
|
2077
2066
|
// config.icon = "/pinokio-white.png"
|
|
2078
2067
|
// }
|
|
2079
2068
|
// }
|
|
2080
|
-
console.log("############## config", JSON.stringify(config, null, 2))
|
|
2081
|
-
|
|
2082
2069
|
config = Util.rewrite_localhost(this.kernel, config, req.$source)
|
|
2083
|
-
|
|
2084
2070
|
return config
|
|
2085
2071
|
} else {
|
|
2086
2072
|
return config
|
|
@@ -2260,12 +2246,12 @@ class Server {
|
|
|
2260
2246
|
|
|
2261
2247
|
// 1. THEME
|
|
2262
2248
|
this.theme = this.kernel.store.get("theme") || "light"
|
|
2263
|
-
this.mode = this.kernel.store.get("mode") || "
|
|
2249
|
+
this.mode = this.kernel.store.get("mode") || "desktop"
|
|
2264
2250
|
|
|
2265
2251
|
// when loaded in electron but in minimal mode,
|
|
2266
2252
|
// the app is loaded in the web so the agent should be "web"
|
|
2267
2253
|
if (this.agent === "electron") {
|
|
2268
|
-
if (this.mode === "minimal") {
|
|
2254
|
+
if (this.mode === "minimal" || this.mode === "background") {
|
|
2269
2255
|
this.agent = "web"
|
|
2270
2256
|
}
|
|
2271
2257
|
}
|
|
@@ -2504,17 +2490,70 @@ class Server {
|
|
|
2504
2490
|
return true
|
|
2505
2491
|
}
|
|
2506
2492
|
}
|
|
2507
|
-
async
|
|
2493
|
+
async terminals(filepath) {
|
|
2494
|
+
let venvs = await Util.find_venv(filepath)
|
|
2495
|
+
let terminal
|
|
2496
|
+
if (venvs.length > 0) {
|
|
2497
|
+
let terminals = []
|
|
2498
|
+
try {
|
|
2499
|
+
for(let i=0; i<venvs.length; i++) {
|
|
2500
|
+
let venv = venvs[i]
|
|
2501
|
+
let parsed = path.parse(venv)
|
|
2502
|
+
terminals.push(this.renderShell(filepath, i, 0, {
|
|
2503
|
+
icon: "fa-brands fa-python",
|
|
2504
|
+
title: "Python virtual environment",
|
|
2505
|
+
subtitle: this.kernel.path("api", parsed.name),
|
|
2506
|
+
text: `[venv] ${parsed.name}`,
|
|
2507
|
+
type: "Start",
|
|
2508
|
+
shell: {
|
|
2509
|
+
venv: venv,
|
|
2510
|
+
input: true,
|
|
2511
|
+
}
|
|
2512
|
+
}))
|
|
2513
|
+
}
|
|
2514
|
+
} catch (e) {
|
|
2515
|
+
console.log(e)
|
|
2516
|
+
}
|
|
2517
|
+
terminal = {
|
|
2518
|
+
icon: "fa-solid fa-terminal",
|
|
2519
|
+
title: "Web Terminal",
|
|
2520
|
+
subtitle: "Open the terminal in the browser",
|
|
2521
|
+
menu: terminals
|
|
2522
|
+
}
|
|
2523
|
+
} else {
|
|
2524
|
+
terminal = {
|
|
2525
|
+
icon: "fa-solid fa-terminal",
|
|
2526
|
+
title: "Web terminal",
|
|
2527
|
+
subtitle: "Work with the terminal directly in the browser",
|
|
2528
|
+
menu: [this.renderShell(filepath, 0, 0, {
|
|
2529
|
+
icon: "fa-solid fa-terminal",
|
|
2530
|
+
title: "Terminal",
|
|
2531
|
+
subtitle: filepath,
|
|
2532
|
+
text: `Terminal`,
|
|
2533
|
+
type: "Start",
|
|
2534
|
+
shell: {
|
|
2535
|
+
input: true
|
|
2536
|
+
}
|
|
2537
|
+
})]
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
return terminal
|
|
2541
|
+
}
|
|
2542
|
+
async getPluginGlobal(req, config, terminal, filepath) {
|
|
2508
2543
|
// if (!this.kernel.plugin.config) {
|
|
2509
2544
|
// await this.kernel.plugin.init()
|
|
2510
2545
|
// }
|
|
2511
|
-
if (
|
|
2546
|
+
if (config) {
|
|
2547
|
+
|
|
2548
|
+
let c = structuredClone(config)
|
|
2549
|
+
let menu = structuredClone(terminal.menu)
|
|
2550
|
+
c.menu = c.menu.concat(menu)
|
|
2512
2551
|
try {
|
|
2513
2552
|
let info = new Info(this.kernel)
|
|
2514
2553
|
info.cwd = () => {
|
|
2515
2554
|
return filepath
|
|
2516
2555
|
}
|
|
2517
|
-
let menu =
|
|
2556
|
+
let menu = c.menu.map((item) => {
|
|
2518
2557
|
return {
|
|
2519
2558
|
params: {
|
|
2520
2559
|
cwd: filepath
|
|
@@ -2547,34 +2586,26 @@ class Server {
|
|
|
2547
2586
|
return null
|
|
2548
2587
|
}
|
|
2549
2588
|
}
|
|
2550
|
-
async getPlugin(req, name) {
|
|
2551
|
-
if (
|
|
2589
|
+
async getPlugin(req, config, name) {
|
|
2590
|
+
if (config) {
|
|
2591
|
+
let c = structuredClone(config)
|
|
2552
2592
|
try {
|
|
2553
|
-
if (this.kernel.plugin.cache[name]) {
|
|
2554
|
-
let cached = this.kernel.plugin.cache[name]
|
|
2555
|
-
return cached
|
|
2556
|
-
} else {
|
|
2557
|
-
// let info = new Info(this.kernel)
|
|
2558
|
-
// info.caller = () => {
|
|
2559
|
-
// return this.kernel.path("api", name, "pinokio.js")
|
|
2560
|
-
// }
|
|
2561
|
-
// let menu = await this.kernel.plugin.config.menu(this.kernel, info)
|
|
2562
2593
|
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
}
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
|
|
2594
|
+
let filepath = this.kernel.path("api", name)
|
|
2595
|
+
let terminal = await this.terminals(filepath)
|
|
2596
|
+
c.menu = c.menu.concat(terminal.menu)
|
|
2597
|
+
let menu = c.menu.map((item) => {
|
|
2598
|
+
return {
|
|
2599
|
+
params: {
|
|
2600
|
+
cwd: filepath,
|
|
2601
|
+
},
|
|
2602
|
+
...item
|
|
2603
|
+
}
|
|
2604
|
+
})
|
|
2605
|
+
let plugin = { menu }
|
|
2606
|
+
let uri = this.kernel.path("api")
|
|
2607
|
+
await this.renderMenu(req, uri, name, plugin, [])
|
|
2608
|
+
return plugin
|
|
2578
2609
|
} catch (e) {
|
|
2579
2610
|
console.log("getPlugin ERROR", e)
|
|
2580
2611
|
return null
|
|
@@ -2767,7 +2798,7 @@ class Server {
|
|
|
2767
2798
|
if (this.kernel.homedir) {
|
|
2768
2799
|
let ex = await this.kernel.exists(this.kernel.homedir, "ENVIRONMENT")
|
|
2769
2800
|
if (!ex) {
|
|
2770
|
-
let str = await Environment.ENV("system", this.kernel.homedir)
|
|
2801
|
+
let str = await Environment.ENV("system", this.kernel.homedir, this.kernel)
|
|
2771
2802
|
await fs.promises.writeFile(path.resolve(this.kernel.homedir, "ENVIRONMENT"), str)
|
|
2772
2803
|
}
|
|
2773
2804
|
}
|
|
@@ -2869,11 +2900,45 @@ class Server {
|
|
|
2869
2900
|
this.app.use(express.static(path.resolve(__dirname, 'public')));
|
|
2870
2901
|
this.app.use("/web", express.static(path.resolve(__dirname, "..", "..", "web")))
|
|
2871
2902
|
this.app.set('view engine', 'ejs');
|
|
2903
|
+
this.app.use((req, res, next) => {
|
|
2904
|
+
let protocol = req.get('X-Forwarded-Proto') || "http"
|
|
2905
|
+
req.$source = {
|
|
2906
|
+
protocol,
|
|
2907
|
+
host: req.get("host")
|
|
2908
|
+
}
|
|
2909
|
+
next()
|
|
2910
|
+
})
|
|
2872
2911
|
if (this.kernel.homedir) {
|
|
2873
2912
|
this.app.set("views", [
|
|
2874
2913
|
this.kernel.path("web/views"),
|
|
2875
2914
|
path.resolve(__dirname, "views")
|
|
2876
2915
|
])
|
|
2916
|
+
let serve = express.static(this.kernel.homedir, { fallthrough: true })
|
|
2917
|
+
let http_serve = express.static(this.kernel.homedir, {
|
|
2918
|
+
redirect: true,
|
|
2919
|
+
})
|
|
2920
|
+
let https_serve = express.static(this.kernel.homedir, {
|
|
2921
|
+
redirect: false,
|
|
2922
|
+
})
|
|
2923
|
+
this.app.use('/asset', serve, serveIndex(this.kernel.homedir, {'icons': true}))
|
|
2924
|
+
this.app.use('/asset', (req, res, next) => {
|
|
2925
|
+
if (req.path.match(/\.(png|jpg|jpeg|gif|ico|svg)$/)) {
|
|
2926
|
+
res.sendFile(path.resolve(__dirname, 'public', 'pinokio-black.png'));
|
|
2927
|
+
} else {
|
|
2928
|
+
next();
|
|
2929
|
+
}
|
|
2930
|
+
});
|
|
2931
|
+
this.app.use("/asset", async (req, res, next) => {
|
|
2932
|
+
let asset_path = this.kernel.path(req.path.slice(1), "index.html")
|
|
2933
|
+
let exists = await this.exists(asset_path)
|
|
2934
|
+
if (exists) {
|
|
2935
|
+
return res.sendFile(asset_path)
|
|
2936
|
+
} else {
|
|
2937
|
+
let chunks = req.path.slice(1).split("/")
|
|
2938
|
+
let parent_path = chunks.slice(0, -1).join("/")
|
|
2939
|
+
res.redirect("/asset/" + parent_path)
|
|
2940
|
+
}
|
|
2941
|
+
})
|
|
2877
2942
|
} else {
|
|
2878
2943
|
this.app.set("views", [
|
|
2879
2944
|
path.resolve(__dirname, "views")
|
|
@@ -2891,16 +2956,106 @@ class Server {
|
|
|
2891
2956
|
};
|
|
2892
2957
|
next();
|
|
2893
2958
|
});
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2959
|
+
/*
|
|
2960
|
+
this.app.get("/asset/*", ex((req, res) => {
|
|
2961
|
+
let pathComponents = req.params[0].split("/")
|
|
2962
|
+
let filepath = this.kernel.path(...pathComponents)
|
|
2963
|
+
console.log("req.originalUrl", req.originalUrl)
|
|
2964
|
+
console.log("pathComponents", pathComponents)
|
|
2965
|
+
// if (pathComponents.length === 2 && pathComponents[0] === "api") {
|
|
2966
|
+
// // ex: /asset/api/comfy.git
|
|
2967
|
+
// filepath = path.resolve(filepath, "index.html")
|
|
2968
|
+
// }
|
|
2969
|
+
try {
|
|
2970
|
+
if (req.query.frame) {
|
|
2971
|
+
let m = mime.lookup(filepath)
|
|
2972
|
+
res.type("text/plain")
|
|
2973
|
+
}
|
|
2974
|
+
//res.setHeader('Content-Disposition', 'inline');
|
|
2975
|
+
res.sendFile(filepath)
|
|
2976
|
+
} catch (e) {
|
|
2977
|
+
res.status(404).send(e.message);
|
|
2899
2978
|
}
|
|
2900
|
-
|
|
2901
|
-
|
|
2979
|
+
}))
|
|
2980
|
+
*/
|
|
2981
|
+
this.app.get("/tools", ex(async (req, res) => {
|
|
2982
|
+
let list = this.getPeers()
|
|
2983
|
+
let installs = []
|
|
2984
|
+
for(let key in this.kernel.bin.installed) {
|
|
2985
|
+
let installed = this.kernel.bin.installed[key]
|
|
2986
|
+
let modules = Array.from(installed)
|
|
2987
|
+
if (modules.length > 0) {
|
|
2988
|
+
installs.push({
|
|
2989
|
+
package_manager: key,
|
|
2990
|
+
modules,
|
|
2991
|
+
})
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
// add minimal
|
|
2995
|
+
const bundle_names = ["dev", "advanced_dev", "ai", "network"]
|
|
2996
|
+
let bundles = []
|
|
2997
|
+
let pending
|
|
2998
|
+
for(let bundle_name of bundle_names) {
|
|
2999
|
+
let result = await this.kernel.bin.check({
|
|
3000
|
+
bin: this.kernel.bin.preset(bundle_name)
|
|
3001
|
+
})
|
|
3002
|
+
if (result.requirements_pending) {
|
|
3003
|
+
pending = true
|
|
3004
|
+
}
|
|
3005
|
+
bundles.push({
|
|
3006
|
+
name: bundle_name,
|
|
3007
|
+
setup: "/setup/" + bundle_name + "?callback=/tools",
|
|
3008
|
+
...result
|
|
3009
|
+
})
|
|
3010
|
+
}
|
|
3011
|
+
console.log(JSON.stringify(bundles, null, 2))
|
|
3012
|
+
res.render("tools", {
|
|
3013
|
+
pending,
|
|
3014
|
+
installs,
|
|
3015
|
+
bundles,
|
|
3016
|
+
version: this.version,
|
|
3017
|
+
portal: this.portal,
|
|
3018
|
+
logo: this.logo,
|
|
3019
|
+
theme: this.theme,
|
|
3020
|
+
agent: this.agent,
|
|
3021
|
+
list,
|
|
3022
|
+
})
|
|
3023
|
+
}))
|
|
3024
|
+
this.app.get("/screenshots", ex(async (req, res) => {
|
|
3025
|
+
let list = this.getPeers()
|
|
3026
|
+
res.render("screenshots", {
|
|
3027
|
+
version: this.version,
|
|
3028
|
+
portal: this.portal,
|
|
3029
|
+
logo: this.logo,
|
|
3030
|
+
theme: this.theme,
|
|
3031
|
+
agent: this.agent,
|
|
3032
|
+
list,
|
|
3033
|
+
})
|
|
3034
|
+
}))
|
|
3035
|
+
this.app.get("/columns", ex(async (req, res) => {
|
|
3036
|
+
res.render("columns", {
|
|
3037
|
+
theme: this.theme,
|
|
3038
|
+
agent: this.agent,
|
|
3039
|
+
src: req.get('Referrer')
|
|
3040
|
+
})
|
|
3041
|
+
}))
|
|
3042
|
+
this.app.get("/rows", ex(async (req, res) => {
|
|
3043
|
+
res.render("rows", {
|
|
3044
|
+
theme: this.theme,
|
|
3045
|
+
agent: this.agent,
|
|
3046
|
+
src: req.get('Referrer')
|
|
3047
|
+
})
|
|
3048
|
+
}))
|
|
2902
3049
|
|
|
2903
3050
|
|
|
3051
|
+
this.app.get("/container", ex(async (req, res) => {
|
|
3052
|
+
res.render("container", {
|
|
3053
|
+
theme: this.theme,
|
|
3054
|
+
agent: this.agent,
|
|
3055
|
+
src: req.query.url
|
|
3056
|
+
})
|
|
3057
|
+
}))
|
|
3058
|
+
|
|
2904
3059
|
//let home = this.kernel.homedir
|
|
2905
3060
|
//let home = this.kernel.store.get("home")
|
|
2906
3061
|
this.app.get("/launch", ex(async (req, res) => {
|
|
@@ -2915,7 +3070,7 @@ class Server {
|
|
|
2915
3070
|
let url = req.query.url
|
|
2916
3071
|
let u = new URL(url)
|
|
2917
3072
|
let host = u.host
|
|
2918
|
-
let env = await Environment.get(this.kernel.homedir)
|
|
3073
|
+
let env = await Environment.get(this.kernel.homedir, this.kernel)
|
|
2919
3074
|
let autolaunch = false
|
|
2920
3075
|
if (env && env.PINOKIO_ONDEMAND_AUTOLAUNCH === "1") {
|
|
2921
3076
|
autolaunch = true
|
|
@@ -2932,18 +3087,17 @@ class Server {
|
|
|
2932
3087
|
// otherwise => redirect
|
|
2933
3088
|
|
|
2934
3089
|
|
|
2935
|
-
if (chunks.length
|
|
3090
|
+
if (chunks.length >= 2) {
|
|
2936
3091
|
|
|
2937
3092
|
let apipath = this.kernel.path("api")
|
|
2938
3093
|
let files = await fs.promises.readdir(apipath, { withFileTypes: true })
|
|
2939
|
-
let folders =
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
|
|
2946
|
-
|
|
3094
|
+
let folders = []
|
|
3095
|
+
for(let file of files) {
|
|
3096
|
+
let type = await Util.file_type(apipath, file)
|
|
3097
|
+
if (type.directory) {
|
|
3098
|
+
folders.push(file.name)
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
2947
3101
|
|
|
2948
3102
|
let matched = false
|
|
2949
3103
|
for(let folder of folders) {
|
|
@@ -2988,7 +3142,15 @@ class Server {
|
|
|
2988
3142
|
let exists = await this.exists(api_path)
|
|
2989
3143
|
if (exists) {
|
|
2990
3144
|
let meta = await this.kernel.api.meta(name)
|
|
3145
|
+
let launcher = await this.kernel.api.launcher(name)
|
|
3146
|
+
let pinokio = launcher.script
|
|
3147
|
+
let launchable = false
|
|
3148
|
+
if (pinokio && pinokio.menu && pinokio.menu.length > 0) {
|
|
3149
|
+
launchable = true
|
|
3150
|
+
}
|
|
2991
3151
|
res.render("start", {
|
|
3152
|
+
url,
|
|
3153
|
+
launchable,
|
|
2992
3154
|
autolaunch,
|
|
2993
3155
|
logo: this.logo,
|
|
2994
3156
|
theme: this.theme,
|
|
@@ -3001,6 +3163,8 @@ class Server {
|
|
|
3001
3163
|
}
|
|
3002
3164
|
}
|
|
3003
3165
|
res.render("start", {
|
|
3166
|
+
url,
|
|
3167
|
+
launchable: false,
|
|
3004
3168
|
autolaunch,
|
|
3005
3169
|
logo: this.logo,
|
|
3006
3170
|
theme: this.theme,
|
|
@@ -3061,7 +3225,7 @@ class Server {
|
|
|
3061
3225
|
}
|
|
3062
3226
|
let system_env = {}
|
|
3063
3227
|
if (this.kernel.homedir) {
|
|
3064
|
-
system_env = await Environment.get(this.kernel.homedir)
|
|
3228
|
+
system_env = await Environment.get(this.kernel.homedir, this.kernel)
|
|
3065
3229
|
}
|
|
3066
3230
|
let configArray = [{
|
|
3067
3231
|
key: "home",
|
|
@@ -3083,7 +3247,7 @@ class Server {
|
|
|
3083
3247
|
}, {
|
|
3084
3248
|
key: "mode",
|
|
3085
3249
|
val: this.mode,
|
|
3086
|
-
options: ["
|
|
3250
|
+
options: ["desktop", "background"]
|
|
3087
3251
|
}, {
|
|
3088
3252
|
key: "HTTP_PROXY",
|
|
3089
3253
|
val: (system_env.HTTP_PROXY || ""),
|
|
@@ -3109,7 +3273,10 @@ class Server {
|
|
|
3109
3273
|
drive: path.resolve(this.kernel.homedir, "drive"),
|
|
3110
3274
|
}
|
|
3111
3275
|
}
|
|
3276
|
+
let list = this.getPeers()
|
|
3112
3277
|
res.render("settings", {
|
|
3278
|
+
current_host: this.kernel.peer.host,
|
|
3279
|
+
list,
|
|
3113
3280
|
platform,
|
|
3114
3281
|
version: this.version,
|
|
3115
3282
|
portal: this.portal,
|
|
@@ -3127,75 +3294,21 @@ class Server {
|
|
|
3127
3294
|
|
|
3128
3295
|
let apipath = this.kernel.path("api")
|
|
3129
3296
|
let files = await fs.promises.readdir(apipath, { withFileTypes: true })
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3297
|
+
|
|
3298
|
+
let folders = []
|
|
3299
|
+
for(let file of files) {
|
|
3300
|
+
let type = await Util.file_type(apipath, file)
|
|
3301
|
+
if (type.directory) {
|
|
3302
|
+
folders.push(file.name)
|
|
3303
|
+
}
|
|
3304
|
+
}
|
|
3135
3305
|
let meta = {}
|
|
3136
3306
|
for(let folder of folders) {
|
|
3137
3307
|
meta[folder] = await this.kernel.api.meta(folder)
|
|
3138
|
-
// let p = path.resolve(apipath, folder, "pinokio.js")
|
|
3139
|
-
// let pinokio = (await this.kernel.loader.load(p)).resolved
|
|
3140
|
-
// let p2 = path.resolve(apipath, folder, "pinokio_meta.json")
|
|
3141
|
-
// let pinokio2 = (await this.kernel.loader.load(p2)).resolved
|
|
3142
|
-
//
|
|
3143
|
-
// meta[folder] = Object.assign({}, pinokio, pinokio2)
|
|
3144
|
-
// meta[folder].iconpath = meta[folder].icon ? path.resolve(apipath, folder, meta[folder].icon) : null
|
|
3145
|
-
// meta[folder].icon = meta[folder].icon ? `/api/${folder}/${meta[folder].icon}?raw=true` : null
|
|
3146
|
-
// meta[folder].path = path.resolve(apipath, folder)
|
|
3147
|
-
|
|
3148
|
-
|
|
3149
|
-
// if (pinokio) {
|
|
3150
|
-
// meta[folder] = {
|
|
3151
|
-
// title: pinokio.title,
|
|
3152
|
-
// description: pinokio.description,
|
|
3153
|
-
// icon: pinokio.icon ? `/api/${folder}/${pinokio.icon}?raw=true` : null
|
|
3154
|
-
// }
|
|
3155
|
-
// }
|
|
3156
|
-
// if (pinokio2) {
|
|
3157
|
-
// if (pinokio2.title) meta[folder].title = pinokio2.title
|
|
3158
|
-
// if (pinokio2.description) meta[folder].description = pinokio2.description
|
|
3159
|
-
// if (pinokio2.icon) meta[folder].icon = pinokio2.icon
|
|
3160
|
-
// }
|
|
3161
3308
|
}
|
|
3162
3309
|
await this.render(req, res, [], meta)
|
|
3163
|
-
// if (this.kernel.bin.all_installed) {
|
|
3164
|
-
// this.started = true
|
|
3165
|
-
// let apipath = this.kernel.path("api")
|
|
3166
|
-
// let files = await fs.promises.readdir(apipath, { withFileTypes: true })
|
|
3167
|
-
// let folders = files.filter((f) => {
|
|
3168
|
-
// return f.isDirectory()
|
|
3169
|
-
// }).map((x) => {
|
|
3170
|
-
// return x.name
|
|
3171
|
-
// })
|
|
3172
|
-
// let meta = {}
|
|
3173
|
-
// for(let folder of folders) {
|
|
3174
|
-
// let p = path.resolve(apipath, folder, "pinokio.js")
|
|
3175
|
-
// let pinokio = (await this.kernel.loader.load(p)).resolved
|
|
3176
|
-
// if (pinokio) {
|
|
3177
|
-
// meta[folder] = {
|
|
3178
|
-
// title: pinokio.title,
|
|
3179
|
-
// description: pinokio.description,
|
|
3180
|
-
// icon: pinokio.icon ? `/api/${folder}/${pinokio.icon}?raw=true` : null
|
|
3181
|
-
// }
|
|
3182
|
-
// }
|
|
3183
|
-
// }
|
|
3184
|
-
// await this.render(req, res, [], meta)
|
|
3185
|
-
// } else {
|
|
3186
|
-
// // get all the "start" scripts from pinokio.json
|
|
3187
|
-
// // render installer page
|
|
3188
|
-
// this.started = true
|
|
3189
|
-
// let home = this.kernel.homedir ? this.kernel.homedir : path.resolve(os.homedir(), "pinokio")
|
|
3190
|
-
// res.render("bootstrap", {
|
|
3191
|
-
// home,
|
|
3192
|
-
// agent: this.agent,
|
|
3193
|
-
// })
|
|
3194
|
-
// }
|
|
3195
3310
|
}))
|
|
3196
3311
|
|
|
3197
|
-
// this.app.get("/init/:name", ex(async (req, res) => {
|
|
3198
|
-
// console.log("Rnder init", req.params.name)
|
|
3199
3312
|
this.app.get("/init", ex(async (req, res) => {
|
|
3200
3313
|
/*
|
|
3201
3314
|
option 1: new vs. clone
|
|
@@ -3222,17 +3335,15 @@ class Server {
|
|
|
3222
3335
|
return
|
|
3223
3336
|
}
|
|
3224
3337
|
|
|
3225
|
-
|
|
3226
|
-
// await this.kernel.proto.init()
|
|
3227
|
-
let list = this.getPeerInfo()
|
|
3338
|
+
let list = this.getPeers()
|
|
3228
3339
|
let ai = await this.kernel.proto.ai()
|
|
3229
|
-
ai
|
|
3340
|
+
ai = [{
|
|
3230
3341
|
title: "Use your own AI recipe",
|
|
3231
3342
|
description: "Enter your own markdown instruction for AI",
|
|
3343
|
+
placeholder: "(example: 'build a launcher for https://github.com/comfyanonymous/ComfyUI)",
|
|
3232
3344
|
meta: {},
|
|
3233
3345
|
content: ""
|
|
3234
|
-
})
|
|
3235
|
-
console.log("ai", ai)
|
|
3346
|
+
}].concat(ai)
|
|
3236
3347
|
res.render("init/index", {
|
|
3237
3348
|
list,
|
|
3238
3349
|
ai,
|
|
@@ -3281,22 +3392,71 @@ class Server {
|
|
|
3281
3392
|
- x
|
|
3282
3393
|
*/
|
|
3283
3394
|
this.app.get("/connect", ex(async (req, res) => {
|
|
3395
|
+
let list = this.getPeers()
|
|
3396
|
+
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
3397
|
+
let items = [{
|
|
3398
|
+
image: "/pinokio-black.png",
|
|
3399
|
+
name: "pinokio",
|
|
3400
|
+
title: "pinokio.co",
|
|
3401
|
+
description: "Connect with pinokio.co",
|
|
3402
|
+
url: "/connect/pinokio"
|
|
3403
|
+
}, {
|
|
3404
|
+
icon: "fa-brands fa-square-x-twitter",
|
|
3405
|
+
name: "x",
|
|
3406
|
+
title: "x.com",
|
|
3407
|
+
description: "Connect with X.com",
|
|
3408
|
+
url: "/connect/x"
|
|
3409
|
+
}, {
|
|
3410
|
+
emoji: "🤗",
|
|
3411
|
+
name: "huggingface",
|
|
3412
|
+
title: "huggingface.co",
|
|
3413
|
+
description: "Connect with huggingface.co",
|
|
3414
|
+
url: "/connect/huggingface"
|
|
3415
|
+
}, {
|
|
3416
|
+
icon: "fa-brands fa-github",
|
|
3417
|
+
name: "github",
|
|
3418
|
+
title: "github.com",
|
|
3419
|
+
description: "Connect with GitHub.com",
|
|
3420
|
+
url: "/github"
|
|
3421
|
+
}]
|
|
3422
|
+
let github_hosts = await this.get_github_hosts()
|
|
3423
|
+
for(let i=0; i<items.length; i++) {
|
|
3424
|
+
try {
|
|
3425
|
+
if (items[i].name === "github") {
|
|
3426
|
+
if (github_hosts.length > 0) {
|
|
3427
|
+
items[i].profile = {
|
|
3428
|
+
icon: "fa-brands fa-github",
|
|
3429
|
+
items: [{
|
|
3430
|
+
key: "config",
|
|
3431
|
+
val: github_hosts
|
|
3432
|
+
}]
|
|
3433
|
+
}
|
|
3434
|
+
items[i].description = `<i class="fa-solid fa-circle-check"></i> Connected with ${items[i].title}`
|
|
3435
|
+
items[i].connected = true
|
|
3436
|
+
}
|
|
3437
|
+
} else {
|
|
3438
|
+
const config = this.kernel.connect.config[items[i].name]
|
|
3439
|
+
if (config) {
|
|
3440
|
+
let profile = await this.kernel.connect.profile(items[i].name)
|
|
3441
|
+
if (profile) {
|
|
3442
|
+
items[i].profile = profile
|
|
3443
|
+
items[i].description = `<i class="fa-solid fa-circle-check"></i> Connected with ${items[i].title}`
|
|
3444
|
+
items[i].connected = true
|
|
3445
|
+
}
|
|
3446
|
+
}
|
|
3447
|
+
}
|
|
3448
|
+
} catch (e) {
|
|
3449
|
+
}
|
|
3450
|
+
}
|
|
3284
3451
|
res.render(`connect`, {
|
|
3452
|
+
current_urls,
|
|
3453
|
+
current_host: this.kernel.peer.host,
|
|
3454
|
+
list,
|
|
3285
3455
|
portal: this.portal,
|
|
3286
3456
|
logo: this.logo,
|
|
3287
3457
|
theme: this.theme,
|
|
3288
3458
|
agent: this.agent,
|
|
3289
|
-
items
|
|
3290
|
-
icon: "fa-brands fa-square-x-twitter",
|
|
3291
|
-
title: "X",
|
|
3292
|
-
description: "Connect with X.com",
|
|
3293
|
-
url: "/connect/x"
|
|
3294
|
-
}, {
|
|
3295
|
-
icon: "fa-brands fa-github",
|
|
3296
|
-
title: "GitHub",
|
|
3297
|
-
description: "Connect with GitHub.com",
|
|
3298
|
-
url: "/github"
|
|
3299
|
-
}]
|
|
3459
|
+
items,
|
|
3300
3460
|
})
|
|
3301
3461
|
}))
|
|
3302
3462
|
/*
|
|
@@ -3353,17 +3513,32 @@ class Server {
|
|
|
3353
3513
|
}
|
|
3354
3514
|
|
|
3355
3515
|
|
|
3356
|
-
let readme =
|
|
3357
|
-
|
|
3516
|
+
let readme = ""
|
|
3517
|
+
let id = ""
|
|
3518
|
+
try {
|
|
3519
|
+
readme = await this.kernel.connect[req.params.provider].readme()
|
|
3520
|
+
id = this.kernel.connect[req.params.provider].id
|
|
3521
|
+
} catch (e) {
|
|
3522
|
+
}
|
|
3523
|
+
//res.render(`connect/${req.params.provider}`, {
|
|
3524
|
+
const config = this.kernel.connect.config[req.params.provider]
|
|
3525
|
+
res.render(`connect/index`, {
|
|
3526
|
+
protocol: req.$source.protocol,
|
|
3527
|
+
name: req.params.provider,
|
|
3528
|
+
config,
|
|
3358
3529
|
portal: this.portal,
|
|
3359
3530
|
logo: this.logo,
|
|
3360
3531
|
theme: this.theme,
|
|
3361
3532
|
agent: this.agent,
|
|
3362
|
-
id
|
|
3533
|
+
id,
|
|
3363
3534
|
readme
|
|
3364
3535
|
})
|
|
3365
3536
|
}))
|
|
3366
3537
|
|
|
3538
|
+
this.app.get("/connect/:provider/profile", ex(async (req, res) => {
|
|
3539
|
+
let response = await this.kernel.connect.profile(req.params.provider, req.body)
|
|
3540
|
+
res.send(response)
|
|
3541
|
+
}))
|
|
3367
3542
|
/*
|
|
3368
3543
|
* POST /connect/x/login => login and acquire auth token
|
|
3369
3544
|
* POST /connect/x/logout => loout
|
|
@@ -3548,17 +3723,8 @@ class Server {
|
|
|
3548
3723
|
let md = await fs.promises.readFile(path.resolve(__dirname, "..", "kernel/connect/providers/github/README.md"), "utf8")
|
|
3549
3724
|
let readme = marked.parse(md)
|
|
3550
3725
|
|
|
3551
|
-
let hosts =
|
|
3552
|
-
|
|
3553
|
-
let e = await this.exists(hosts_file)
|
|
3554
|
-
console.log({ hosts_file, e })
|
|
3555
|
-
if (e) {
|
|
3556
|
-
hosts = await fs.promises.readFile(hosts_file, "utf8")
|
|
3557
|
-
console.log( { hosts: `#${hosts}#` })
|
|
3558
|
-
if (hosts.startsWith("{}")) {
|
|
3559
|
-
hosts = ""
|
|
3560
|
-
}
|
|
3561
|
-
}
|
|
3726
|
+
let hosts = await this.get_github_hosts()
|
|
3727
|
+
|
|
3562
3728
|
console.log("hosts", hosts)
|
|
3563
3729
|
|
|
3564
3730
|
let items
|
|
@@ -3865,8 +4031,22 @@ class Server {
|
|
|
3865
4031
|
agent: this.agent,
|
|
3866
4032
|
})
|
|
3867
4033
|
}))
|
|
4034
|
+
this.app.post("/plugin/update_spec", ex(async (req, res) => {
|
|
4035
|
+
try {
|
|
4036
|
+
let filepath = req.body.filepath
|
|
4037
|
+
let content = req.body.spec
|
|
4038
|
+
let spec_path = path.resolve(filepath, "SPEC.md")
|
|
4039
|
+
await fs.promises.writeFile(spec_path, content)
|
|
4040
|
+
res.json({
|
|
4041
|
+
success: true
|
|
4042
|
+
})
|
|
4043
|
+
} catch (e) {
|
|
4044
|
+
res.error({
|
|
4045
|
+
error: e.stack
|
|
4046
|
+
})
|
|
4047
|
+
}
|
|
4048
|
+
}))
|
|
3868
4049
|
this.app.post("/plugin/update", ex(async (req, res) => {
|
|
3869
|
-
console.time("/plugin/update")
|
|
3870
4050
|
try {
|
|
3871
4051
|
await this.kernel.exec({
|
|
3872
4052
|
message: "git pull",
|
|
@@ -3874,7 +4054,6 @@ class Server {
|
|
|
3874
4054
|
}, (e) => {
|
|
3875
4055
|
console.log(e)
|
|
3876
4056
|
})
|
|
3877
|
-
console.timeEnd("/plugin/update")
|
|
3878
4057
|
res.json({
|
|
3879
4058
|
success: true
|
|
3880
4059
|
})
|
|
@@ -3946,8 +4125,13 @@ class Server {
|
|
|
3946
4125
|
}
|
|
3947
4126
|
} catch (e) {
|
|
3948
4127
|
}
|
|
4128
|
+
console.log("PEER INFO", JSON.stringify(this.kernel.peer.info[host], null, 2))
|
|
3949
4129
|
|
|
3950
4130
|
let installed = this.kernel.peer.info[host].installed
|
|
4131
|
+
let serverless_mapping = this.kernel.peer.info[host].rewrite_mapping
|
|
4132
|
+
let serverless = Object.keys(serverless_mapping).map((name) => {
|
|
4133
|
+
return serverless_mapping[name]
|
|
4134
|
+
})
|
|
3951
4135
|
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
3952
4136
|
res.render("net", {
|
|
3953
4137
|
selected_name: req.params.name,
|
|
@@ -3959,6 +4143,7 @@ class Server {
|
|
|
3959
4143
|
theme: this.theme,
|
|
3960
4144
|
processes,
|
|
3961
4145
|
installed,
|
|
4146
|
+
serverless,
|
|
3962
4147
|
error: null,
|
|
3963
4148
|
list,
|
|
3964
4149
|
host,
|
|
@@ -3996,11 +4181,11 @@ class Server {
|
|
|
3996
4181
|
})
|
|
3997
4182
|
}
|
|
3998
4183
|
|
|
3999
|
-
if (peers.length === 0) {
|
|
4000
|
-
console.log("network not yet ready")
|
|
4001
|
-
res.redirect("/")
|
|
4002
|
-
return
|
|
4003
|
-
}
|
|
4184
|
+
// if (peers.length === 0) {
|
|
4185
|
+
// console.log("network not yet ready")
|
|
4186
|
+
// res.redirect("/")
|
|
4187
|
+
// return
|
|
4188
|
+
// }
|
|
4004
4189
|
|
|
4005
4190
|
|
|
4006
4191
|
let live_proxies = this.kernel.api.proxies["/proxy"]
|
|
@@ -4050,11 +4235,13 @@ class Server {
|
|
|
4050
4235
|
// App sharing
|
|
4051
4236
|
let apipath = this.kernel.path("api")
|
|
4052
4237
|
let files = await fs.promises.readdir(apipath, { withFileTypes: true })
|
|
4053
|
-
let folders =
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4238
|
+
let folders = []
|
|
4239
|
+
for(let file of files) {
|
|
4240
|
+
let type = await Util.file_type(apipath, file)
|
|
4241
|
+
if (type.directory) {
|
|
4242
|
+
folders.push(file.name)
|
|
4243
|
+
}
|
|
4244
|
+
}
|
|
4058
4245
|
let apps = []
|
|
4059
4246
|
for(let folder of folders) {
|
|
4060
4247
|
let meta = await this.kernel.api.meta(folder)
|
|
@@ -4066,20 +4253,25 @@ class Server {
|
|
|
4066
4253
|
|
|
4067
4254
|
|
|
4068
4255
|
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
4069
|
-
let current_peer = this.kernel.peer.info[this.kernel.peer.host]
|
|
4070
|
-
let host =
|
|
4256
|
+
let current_peer = this.kernel.peer.info ? this.kernel.peer.info[this.kernel.peer.host] : null
|
|
4257
|
+
let host = null
|
|
4258
|
+
if (current_peer) {
|
|
4259
|
+
host = current_peer.host
|
|
4260
|
+
}
|
|
4071
4261
|
let peer = current_peer
|
|
4072
4262
|
|
|
4073
4263
|
let processes = []
|
|
4074
4264
|
try {
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
if (
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4265
|
+
if (current_peer) {
|
|
4266
|
+
processes = current_peer.router_info
|
|
4267
|
+
for(let i=0; i<processes.length; i++) {
|
|
4268
|
+
if (!processes[i].icon) {
|
|
4269
|
+
if (protocol === "https") {
|
|
4270
|
+
processes[i].icon = processes[i].https_icon
|
|
4271
|
+
} else {
|
|
4272
|
+
// http
|
|
4273
|
+
processes[i].icon = processes[i].http_icon
|
|
4274
|
+
}
|
|
4083
4275
|
}
|
|
4084
4276
|
}
|
|
4085
4277
|
}
|
|
@@ -4095,9 +4287,13 @@ class Server {
|
|
|
4095
4287
|
|
|
4096
4288
|
|
|
4097
4289
|
let list = this.getPeers()
|
|
4098
|
-
let installed = this.kernel.peer.info[host].installed
|
|
4099
|
-
res.render("network", {
|
|
4290
|
+
let installed = this.kernel.peer.info && this.kernel.peer.info[host] ? this.kernel.peer.info[host].installed : []
|
|
4100
4291
|
|
|
4292
|
+
let static_routes = Object.keys(this.kernel.router.rewrite_mapping).map((key) => {
|
|
4293
|
+
return this.kernel.router.rewrite_mapping[key]
|
|
4294
|
+
})
|
|
4295
|
+
res.render("network", {
|
|
4296
|
+
static_routes,
|
|
4101
4297
|
host,
|
|
4102
4298
|
favicons,
|
|
4103
4299
|
titles,
|
|
@@ -4137,78 +4333,16 @@ class Server {
|
|
|
4137
4333
|
let str = await fs.promises.readFile(req.query.logpath, "utf8")
|
|
4138
4334
|
res.send(str)
|
|
4139
4335
|
}))
|
|
4140
|
-
this.app.get("/state/:type/:name", ex(async (req,res) => {
|
|
4141
|
-
let selected = null
|
|
4142
|
-
try {
|
|
4143
|
-
selected = this.selected[req.params.name][req.params.type]
|
|
4144
|
-
} catch (e) {
|
|
4145
|
-
}
|
|
4146
|
-
res.json({
|
|
4147
|
-
selected,
|
|
4148
|
-
})
|
|
4149
|
-
}))
|
|
4150
|
-
this.app.post("/state", ex(async (req, res) => {
|
|
4151
|
-
/*
|
|
4152
|
-
req.body := {
|
|
4153
|
-
name: <name>,
|
|
4154
|
-
type: "browse"|"run",
|
|
4155
|
-
method: "toggleMenu"|"select",
|
|
4156
|
-
params: {
|
|
4157
|
-
<url>,
|
|
4158
|
-
}
|
|
4159
|
-
}
|
|
4160
|
-
*/
|
|
4161
|
-
if (req.body.method === "select") {
|
|
4162
|
-
if (!this.selected[req.body.name]) {
|
|
4163
|
-
this.selected[req.body.name] = {}
|
|
4164
|
-
}
|
|
4165
|
-
this.selected[req.body.name][req.body.type] = req.body.params.url
|
|
4166
|
-
} else if (req.body.method === "toggleMenu") {
|
|
4167
|
-
if (!this.menu_hidden[req.body.name]) {
|
|
4168
|
-
this.menu_hidden[req.body.name] = {}
|
|
4169
|
-
}
|
|
4170
|
-
if (this.menu_hidden[req.body.name][req.body.type]) {
|
|
4171
|
-
this.menu_hidden[req.body.name][req.body.type] = false
|
|
4172
|
-
} else {
|
|
4173
|
-
this.menu_hidden[req.body.name][req.body.type] = true
|
|
4174
|
-
}
|
|
4175
|
-
}
|
|
4176
|
-
res.json({
|
|
4177
|
-
success: true
|
|
4178
|
-
})
|
|
4179
|
-
}))
|
|
4180
4336
|
this.app.post("/mkdir", ex(async (req, res) => {
|
|
4181
4337
|
let folder = req.body.folder
|
|
4182
4338
|
let folder_path = path.resolve(this.kernel.api.userdir, req.body.folder)
|
|
4183
4339
|
try {
|
|
4184
4340
|
// mkdir
|
|
4185
4341
|
await fs.promises.mkdir(folder_path)
|
|
4186
|
-
|
|
4187
|
-
// create basic pinokio.json
|
|
4188
|
-
|
|
4189
|
-
// add default icon
|
|
4190
|
-
|
|
4191
4342
|
let default_icon_path = path.resolve(__dirname, "public/pinokio-black.png")
|
|
4192
4343
|
let icon_path = path.resolve(folder_path, "icon.png")
|
|
4193
4344
|
await fs.promises.cp(default_icon_path, icon_path)
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
// write title/description to pinokio.json
|
|
4197
|
-
// let meta_path = path.resolve(folder_path, "pinokio.json")
|
|
4198
|
-
// let meta = {
|
|
4199
|
-
// title: "No title",
|
|
4200
|
-
// description: "",
|
|
4201
|
-
// icon: "icon.png",
|
|
4202
|
-
// plugin: {
|
|
4203
|
-
// menu: []
|
|
4204
|
-
// }
|
|
4205
|
-
// }
|
|
4206
|
-
// console.log({ folder_path, default_icon_path, icon_path, meta_path, meta })
|
|
4207
|
-
// await fs.promises.writeFile(meta_path, JSON.stringify(meta, null, 2))
|
|
4208
|
-
|
|
4209
4345
|
res.json({
|
|
4210
|
-
//success: "/pinokio/browser/"+folder
|
|
4211
|
-
//success: "/p/"+folder
|
|
4212
4346
|
success: "/init/"+folder
|
|
4213
4347
|
})
|
|
4214
4348
|
} catch (e) {
|
|
@@ -4291,7 +4425,7 @@ class Server {
|
|
|
4291
4425
|
*/
|
|
4292
4426
|
if (req.body.type) {
|
|
4293
4427
|
if (req.body.type === "local") {
|
|
4294
|
-
let env = await Environment.get(this.kernel.homedir)
|
|
4428
|
+
let env = await Environment.get(this.kernel.homedir, this.kernel)
|
|
4295
4429
|
if (env && env.PINOKIO_SHARE_LOCAL_PORT) {
|
|
4296
4430
|
let port = env.PINOKIO_SHARE_LOCAL_PORT.trim()
|
|
4297
4431
|
if (port.length > 0) {
|
|
@@ -4320,244 +4454,217 @@ class Server {
|
|
|
4320
4454
|
res.json({ error: "type must be 'local' or 'cloudflare'" })
|
|
4321
4455
|
}
|
|
4322
4456
|
}))
|
|
4323
|
-
this.app.get("/prototype/run/*", ex(async (req, res) => {
|
|
4324
|
-
let pathComponents = req.params[0].split("/").concat("pinokio.js")
|
|
4325
|
-
let config = await this.kernel.api.meta({ path: req.query.path })
|
|
4326
|
-
let pinokiojson_path = path.resolve(req.query.path, "pinokio.json")
|
|
4327
|
-
let pinokiojson = await this.kernel.require(pinokiojson_path)
|
|
4328
|
-
if (pinokiojson) {
|
|
4329
|
-
if (pinokiojson.plugin) {
|
|
4330
|
-
if (pinokiojson.plugin.menu) {
|
|
4331
|
-
} else {
|
|
4332
|
-
pinokiojson.plugin.menu = []
|
|
4333
|
-
await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
4334
|
-
}
|
|
4335
|
-
} else {
|
|
4336
|
-
pinokiojson.plugin = { menu: [] }
|
|
4337
|
-
await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
4338
|
-
}
|
|
4339
|
-
} else {
|
|
4340
|
-
pinokiojson = {
|
|
4341
|
-
plugin: {
|
|
4342
|
-
menu: []
|
|
4343
|
-
}
|
|
4344
|
-
}
|
|
4345
|
-
await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
4346
|
-
}
|
|
4347
|
-
req.base = this.kernel.path("prototype")
|
|
4348
|
-
req.query.callback = config.ui
|
|
4349
|
-
//req.query.callback = config.browse
|
|
4350
|
-
req.query.cwd = req.query.path
|
|
4351
|
-
await this.render(req, res, pathComponents, null)
|
|
4352
|
-
}))
|
|
4353
|
-
this.app.get("/prototype/show/*", ex(async (req, res) => {
|
|
4354
|
-
let name = req.params[0].split("/").filter((x) => { return x }).join("/")
|
|
4355
|
-
|
|
4356
|
-
// print readme
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4360
|
-
|
|
4361
|
-
let paths = req.params[0].split("/")
|
|
4362
|
-
let item
|
|
4363
|
-
let config = this.kernel.proto.config
|
|
4364
|
-
for(let key of paths) {
|
|
4365
|
-
config = config.menu[key]
|
|
4366
|
-
}
|
|
4367
|
-
console.log("config.shell", config.shell)
|
|
4368
|
-
if (config.shell) {
|
|
4369
|
-
|
|
4370
|
-
let rendered = this.kernel.template.render(config.shell, {})
|
|
4371
|
-
let params = new URLSearchParams()
|
|
4372
|
-
if (rendered.path) params.set("path", encodeURIComponent(rendered.path))
|
|
4373
|
-
if (rendered.message) params.set("message", encodeURIComponent(rendered.message))
|
|
4374
|
-
if (rendered.venv) params.set("venv", encodeURIComponent(rendered.venv))
|
|
4375
|
-
if (rendered.input) params.set("input", true)
|
|
4376
|
-
if (rendered.callback) params.set("callback", encodeURIComponent(rendered.callback))
|
|
4377
|
-
if (rendered.kill) params.set("kill", encodeURIComponent(rendered.kill))
|
|
4378
|
-
if (rendered.done) params.set("done", encodeURIComponent(rendered.done))
|
|
4379
|
-
if (rendered.env) {
|
|
4380
|
-
for(let key in rendered.env) {
|
|
4381
|
-
let env_key = "env." + key
|
|
4382
|
-
params.set(env_key, rendered.env[key])
|
|
4383
|
-
}
|
|
4384
|
-
}
|
|
4385
|
-
if (rendered.conda) {
|
|
4386
|
-
for(let key in rendered.conda) {
|
|
4387
|
-
let conda_key = "conda." + key
|
|
4388
|
-
params.set(conda_key, rendered.conda[key])
|
|
4389
|
-
}
|
|
4390
|
-
}
|
|
4391
|
-
let shell_id = Math.floor("SH_" + 1000000000000 * Math.random())
|
|
4392
|
-
let href = "/shell/" + shell_id + "?" + params.toString()
|
|
4393
|
-
res.redirect(href)
|
|
4394
|
-
} else {
|
|
4395
|
-
let run_path = "/run/prototype/system/" + config.href + "?cwd=" + req.query.path
|
|
4396
|
-
let readme_path = this.kernel.path("prototype/system", config.readme)
|
|
4397
|
-
let md = await fs.promises.readFile(readme_path, "utf8")
|
|
4398
|
-
let baseUrl = "/asset/prototype/system/" + (config.readme.split("/").slice(0, -1).join("/")) + "/"
|
|
4399
|
-
let readme = marked.parse(md, {
|
|
4400
|
-
baseUrl
|
|
4401
|
-
})
|
|
4402
|
-
res.render("prototype/show", {
|
|
4403
|
-
run_path,
|
|
4404
|
-
portal: this.portal,
|
|
4405
|
-
readme,
|
|
4406
|
-
logo: this.logo,
|
|
4407
|
-
theme: this.theme,
|
|
4408
|
-
agent: this.agent,
|
|
4409
|
-
kernel: this.kernel,
|
|
4410
|
-
})
|
|
4411
|
-
}
|
|
4412
|
-
|
|
4413
|
-
}))
|
|
4414
|
-
this.app.get("/prototype", ex(async (req, res) => {
|
|
4415
|
-
// load meta
|
|
4457
|
+
// this.app.get("/prototype/run/*", ex(async (req, res) => {
|
|
4458
|
+
// let pathComponents = req.params[0].split("/").concat("pinokio.js")
|
|
4416
4459
|
// let config = await this.kernel.api.meta({ path: req.query.path })
|
|
4417
|
-
// let
|
|
4418
|
-
//
|
|
4419
|
-
//
|
|
4460
|
+
// let pinokiojson_path = path.resolve(req.query.path, "pinokio.json")
|
|
4461
|
+
// let pinokiojson = await this.kernel.require(pinokiojson_path)
|
|
4462
|
+
// if (pinokiojson) {
|
|
4463
|
+
// if (pinokiojson.plugin) {
|
|
4464
|
+
// if (pinokiojson.plugin.menu) {
|
|
4465
|
+
// } else {
|
|
4466
|
+
// pinokiojson.plugin.menu = []
|
|
4467
|
+
// await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
4468
|
+
// }
|
|
4469
|
+
// } else {
|
|
4470
|
+
// pinokiojson.plugin = { menu: [] }
|
|
4471
|
+
// await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
4472
|
+
// }
|
|
4473
|
+
// } else {
|
|
4474
|
+
// pinokiojson = {
|
|
4475
|
+
// plugin: {
|
|
4476
|
+
// menu: []
|
|
4477
|
+
// }
|
|
4478
|
+
// }
|
|
4479
|
+
// await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
4420
4480
|
// }
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
}
|
|
4430
|
-
|
|
4431
|
-
let config = structuredClone(this.kernel.proto.config)
|
|
4432
|
-
config = this.renderMenu2(config, {
|
|
4433
|
-
cwd: req.query.path,
|
|
4434
|
-
href: "/prototype/show",
|
|
4435
|
-
path: this.kernel.path("prototype/system"),
|
|
4436
|
-
web_path: "/asset/prototype/system"
|
|
4437
|
-
})
|
|
4438
|
-
|
|
4439
|
-
// {
|
|
4440
|
-
// "icon": "fa-solid fa-power-off",
|
|
4441
|
-
// "text": "Run Default",
|
|
4442
|
-
// "href": "/api/facefusion-pinokio.git/run.js?run=true&fullscreen=true&mode=Default",
|
|
4443
|
-
// "params": {
|
|
4444
|
-
// "run": true,
|
|
4445
|
-
// "fullscreen": true,
|
|
4446
|
-
// "mode": "Default"
|
|
4447
|
-
// },
|
|
4448
|
-
// "src": "/api/facefusion-pinokio.git/run.js",
|
|
4449
|
-
// "html": "<i class=\"fa-solid fa-power-off\"></i> Run Default",
|
|
4450
|
-
// "btn": "<i class=\"fa-solid fa-power-off\"></i> Run Default",
|
|
4451
|
-
// "target": "@/api/facefusion-pinokio.git/run.js"
|
|
4452
|
-
// },
|
|
4481
|
+
// req.base = this.kernel.path("prototype")
|
|
4482
|
+
// req.query.callback = config.ui
|
|
4483
|
+
// //req.query.callback = config.browse
|
|
4484
|
+
// req.query.cwd = req.query.path
|
|
4485
|
+
// await this.render(req, res, pathComponents, null)
|
|
4486
|
+
// }))
|
|
4487
|
+
// this.app.get("/prototype/show/*", ex(async (req, res) => {
|
|
4488
|
+
// let name = req.params[0].split("/").filter((x) => { return x }).join("/")
|
|
4453
4489
|
//
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
//
|
|
4461
|
-
|
|
4462
|
-
|
|
4463
|
-
|
|
4464
|
-
|
|
4465
|
-
|
|
4466
|
-
|
|
4467
|
-
|
|
4468
|
-
|
|
4469
|
-
|
|
4470
|
-
|
|
4471
|
-
|
|
4472
|
-
|
|
4473
|
-
|
|
4474
|
-
|
|
4475
|
-
|
|
4476
|
-
|
|
4477
|
-
|
|
4478
|
-
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
}
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
|
|
4492
|
-
|
|
4493
|
-
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
}
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
|
|
4527
|
-
|
|
4528
|
-
|
|
4529
|
-
|
|
4530
|
-
|
|
4531
|
-
|
|
4532
|
-
|
|
4533
|
-
|
|
4534
|
-
|
|
4535
|
-
|
|
4536
|
-
|
|
4537
|
-
|
|
4538
|
-
|
|
4539
|
-
|
|
4540
|
-
|
|
4490
|
+
// // print readme
|
|
4491
|
+
//
|
|
4492
|
+
//
|
|
4493
|
+
//
|
|
4494
|
+
//
|
|
4495
|
+
// let paths = req.params[0].split("/")
|
|
4496
|
+
// let item
|
|
4497
|
+
// let config = this.kernel.proto.config
|
|
4498
|
+
// for(let key of paths) {
|
|
4499
|
+
// config = config.menu[key]
|
|
4500
|
+
// }
|
|
4501
|
+
// console.log("config.shell", config.shell)
|
|
4502
|
+
// if (config.shell) {
|
|
4503
|
+
//
|
|
4504
|
+
// let rendered = this.kernel.template.render(config.shell, {})
|
|
4505
|
+
// let params = new URLSearchParams()
|
|
4506
|
+
// if (rendered.path) params.set("path", encodeURIComponent(rendered.path))
|
|
4507
|
+
// if (rendered.message) params.set("message", encodeURIComponent(rendered.message))
|
|
4508
|
+
// if (rendered.venv) params.set("venv", encodeURIComponent(rendered.venv))
|
|
4509
|
+
// if (rendered.input) params.set("input", true)
|
|
4510
|
+
// if (rendered.callback) params.set("callback", encodeURIComponent(rendered.callback))
|
|
4511
|
+
// if (rendered.kill) params.set("kill", encodeURIComponent(rendered.kill))
|
|
4512
|
+
// if (rendered.done) params.set("done", encodeURIComponent(rendered.done))
|
|
4513
|
+
// if (rendered.env) {
|
|
4514
|
+
// for(let key in rendered.env) {
|
|
4515
|
+
// let env_key = "env." + key
|
|
4516
|
+
// params.set(env_key, rendered.env[key])
|
|
4517
|
+
// }
|
|
4518
|
+
// }
|
|
4519
|
+
// if (rendered.conda) {
|
|
4520
|
+
// for(let key in rendered.conda) {
|
|
4521
|
+
// let conda_key = "conda." + key
|
|
4522
|
+
// params.set(conda_key, rendered.conda[key])
|
|
4523
|
+
// }
|
|
4524
|
+
// }
|
|
4525
|
+
// let shell_id = Math.floor("SH_" + 1000000000000 * Math.random())
|
|
4526
|
+
// let href = "/shell/" + shell_id + "?" + params.toString()
|
|
4527
|
+
// res.redirect(href)
|
|
4528
|
+
// } else {
|
|
4529
|
+
// let run_path = "/run/prototype/system/" + config.href + "?cwd=" + req.query.path
|
|
4530
|
+
// let readme_path = this.kernel.path("prototype/system", config.readme)
|
|
4531
|
+
// let md = await fs.promises.readFile(readme_path, "utf8")
|
|
4532
|
+
// let baseUrl = "/asset/prototype/system/" + (config.readme.split("/").slice(0, -1).join("/")) + "/"
|
|
4533
|
+
// let readme = marked.parse(md, {
|
|
4534
|
+
// baseUrl
|
|
4535
|
+
// })
|
|
4536
|
+
// res.render("prototype/show", {
|
|
4537
|
+
// run_path,
|
|
4538
|
+
// portal: this.portal,
|
|
4539
|
+
// readme,
|
|
4540
|
+
// logo: this.logo,
|
|
4541
|
+
// theme: this.theme,
|
|
4542
|
+
// agent: this.agent,
|
|
4543
|
+
// kernel: this.kernel,
|
|
4544
|
+
// })
|
|
4545
|
+
// }
|
|
4546
|
+
//
|
|
4547
|
+
// }))
|
|
4548
|
+
// this.app.get("/prototype", ex(async (req, res) => {
|
|
4549
|
+
// let title
|
|
4550
|
+
// let description
|
|
4551
|
+
// if (req.query.type === "init") {
|
|
4552
|
+
// title = "Initialize"
|
|
4553
|
+
// description = "Select an option to intitialize the project with. This may overwrite the folder if you already have existing files"
|
|
4554
|
+
// } else if (req.query.type === "extension") {
|
|
4555
|
+
// title = "Extensions"
|
|
4556
|
+
// description = "Add extension modules to the current folder"
|
|
4557
|
+
// }
|
|
4558
|
+
//
|
|
4559
|
+
// let config = structuredClone(this.kernel.proto.config)
|
|
4560
|
+
// config = this.renderMenu2(config, {
|
|
4561
|
+
// cwd: req.query.path,
|
|
4562
|
+
// href: "/prototype/show",
|
|
4563
|
+
// path: this.kernel.path("prototype/system"),
|
|
4564
|
+
// web_path: "/asset/prototype/system"
|
|
4565
|
+
// })
|
|
4566
|
+
// res.render("prototype/index", {
|
|
4567
|
+
// title,
|
|
4568
|
+
// description,
|
|
4569
|
+
// config,
|
|
4570
|
+
// path: req.query.path,
|
|
4571
|
+
// portal: this.portal,
|
|
4572
|
+
// logo: this.logo,
|
|
4573
|
+
// platform: this.kernel.platform,
|
|
4574
|
+
// theme: this.theme,
|
|
4575
|
+
// agent: this.agent,
|
|
4576
|
+
// kernel: this.kernel,
|
|
4577
|
+
// })
|
|
4578
|
+
// }))
|
|
4579
|
+
// this.app.post("/prototype", this.upload.any(), ex(async (req, res) => {
|
|
4580
|
+
// try {
|
|
4581
|
+
// /*
|
|
4582
|
+
// {
|
|
4583
|
+
// title,
|
|
4584
|
+
// description,
|
|
4585
|
+
// path,
|
|
4586
|
+
// id
|
|
4587
|
+
// }
|
|
4588
|
+
// */
|
|
4589
|
+
// let formData = req.body
|
|
4590
|
+
// for(let key in req.files) {
|
|
4591
|
+
// let file = req.files[key]
|
|
4592
|
+
// formData[file.fieldname] = file.buffer
|
|
4593
|
+
// }
|
|
4594
|
+
// console.log({ formData })
|
|
4595
|
+
//
|
|
4596
|
+
//
|
|
4597
|
+
// // check if the path exists. if it does, return error
|
|
4598
|
+
// let api_path = this.kernel.path("api", formData.path)
|
|
4599
|
+
// let e = await this.exists(api_path)
|
|
4600
|
+
// if (e) {
|
|
4601
|
+
// console.log("e", e)
|
|
4602
|
+
// console.log("e.message", e.message)
|
|
4603
|
+
// res.status(500).json({ error: `The path ${api_path} already exists` })
|
|
4604
|
+
// } else {
|
|
4605
|
+
// await this.kernel.api.createMeta(formData)
|
|
4606
|
+
//
|
|
4607
|
+
// // run
|
|
4608
|
+
//
|
|
4609
|
+
// res.json({ success: true })
|
|
4610
|
+
// }
|
|
4611
|
+
// } catch (e) {
|
|
4612
|
+
// console.log("e", e)
|
|
4613
|
+
// console.log("e.message", e.message)
|
|
4614
|
+
// res.status(500).json({ error: e.message })
|
|
4615
|
+
// }
|
|
4616
|
+
// }))
|
|
4617
|
+
// this.app.post("/new", this.upload.any(), ex(async (req, res) => {
|
|
4618
|
+
// try {
|
|
4619
|
+
// /*
|
|
4620
|
+
// {
|
|
4621
|
+
// title,
|
|
4622
|
+
// description,
|
|
4623
|
+
// path,
|
|
4624
|
+
// id
|
|
4625
|
+
// }
|
|
4626
|
+
// */
|
|
4627
|
+
// let formData = req.body
|
|
4628
|
+
// for(let key in req.files) {
|
|
4629
|
+
// let file = req.files[key]
|
|
4630
|
+
// formData[file.fieldname] = file.buffer
|
|
4631
|
+
// }
|
|
4632
|
+
// console.log({ formData })
|
|
4633
|
+
//
|
|
4634
|
+
//
|
|
4635
|
+
// // check if the path exists. if it does, return error
|
|
4636
|
+
// let api_path = this.kernel.path("api", formData.path)
|
|
4637
|
+
// let e = await this.exists(api_path)
|
|
4638
|
+
// if (e) {
|
|
4639
|
+
// console.log("e", e)
|
|
4640
|
+
// console.log("e.message", e.message)
|
|
4641
|
+
// res.status(500).json({ error: `The path ${api_path} already exists` })
|
|
4642
|
+
// } else {
|
|
4643
|
+
// await this.kernel.api.createMeta(formData)
|
|
4644
|
+
// res.json({ success: true })
|
|
4645
|
+
// }
|
|
4646
|
+
// } catch (e) {
|
|
4647
|
+
// console.log("e", e)
|
|
4648
|
+
// console.log("e.message", e.message)
|
|
4649
|
+
// res.status(500).json({ error: e.message })
|
|
4650
|
+
// }
|
|
4651
|
+
// }))
|
|
4541
4652
|
this.app.post("/env", ex(async (req, res) => {
|
|
4542
4653
|
let fullpath = path.resolve(this.kernel.homedir, req.body.filepath, "ENVIRONMENT")
|
|
4543
4654
|
let updated = req.body.vals
|
|
4544
4655
|
let hosts = req.body.hosts
|
|
4545
|
-
console.log("Util.update_env", { fullpath, filepath: req.body.filepath, updated })
|
|
4546
4656
|
await Util.update_env(fullpath, updated)
|
|
4547
4657
|
// for all environment variables that have hosts, save the key as well
|
|
4548
4658
|
// hosts := { env_key: host }
|
|
4549
4659
|
for(let env in hosts) {
|
|
4550
4660
|
let host = hosts[env]
|
|
4551
4661
|
let val = updated[env]
|
|
4552
|
-
console.log({ hosts, updated, host, val })
|
|
4553
4662
|
await this.kernel.kv.set(host.value, val, host.index)
|
|
4554
4663
|
}
|
|
4555
4664
|
res.json({})
|
|
4556
4665
|
}))
|
|
4557
4666
|
this.app.get("/env", ex(async (req, res) => {
|
|
4558
|
-
|
|
4559
|
-
await this.init_env(env_path)
|
|
4560
|
-
|
|
4667
|
+
await Environment.init({}, this.kernel)
|
|
4561
4668
|
let filepath = path.resolve(this.kernel.homedir, "ENVIRONMENT")
|
|
4562
4669
|
let editorpath = "/edit/ENVIRONMENT"
|
|
4563
4670
|
|
|
@@ -4576,41 +4683,47 @@ class Server {
|
|
|
4576
4683
|
})
|
|
4577
4684
|
}))
|
|
4578
4685
|
this.app.get("/env/*", ex(async (req, res) => {
|
|
4579
|
-
|
|
4580
4686
|
let env_path = req.params[0]
|
|
4581
|
-
// let p = path.resolve(this.kernel.homedir, env_path, "pinokio.js")
|
|
4582
|
-
// let config = (await this.kernel.loader.load(p)).resolved
|
|
4583
4687
|
let api_path
|
|
4584
4688
|
if (env_path.startsWith("api/")) {
|
|
4585
4689
|
api_path = env_path.slice(4)
|
|
4586
4690
|
}
|
|
4587
4691
|
let config = await this.kernel.api.meta(api_path)
|
|
4692
|
+
let env_result
|
|
4588
4693
|
if (config.run) {
|
|
4589
|
-
await
|
|
4694
|
+
env_result = await Environment.init({
|
|
4695
|
+
name: api_path,
|
|
4696
|
+
no_inherit: true
|
|
4697
|
+
}, this.kernel)
|
|
4590
4698
|
} else {
|
|
4591
|
-
await
|
|
4699
|
+
env_result = await Environment.init({
|
|
4700
|
+
name: api_path,
|
|
4701
|
+
}, this.kernel)
|
|
4592
4702
|
}
|
|
4593
4703
|
|
|
4594
|
-
|
|
4595
|
-
let filepath =
|
|
4704
|
+
|
|
4705
|
+
let filepath = env_result.env_path
|
|
4706
|
+
|
|
4707
|
+
// let pathComponents = req.params[0].split("/")
|
|
4708
|
+
// let filepath = path.resolve(this.kernel.homedir, req.params[0], "ENVIRONMENT")
|
|
4596
4709
|
|
|
4597
4710
|
let items = []
|
|
4598
4711
|
let e = await this.exists(filepath)
|
|
4599
4712
|
if (e) {
|
|
4600
4713
|
items = await Util.parse_env_detail(filepath)
|
|
4601
4714
|
}
|
|
4602
|
-
// if (config.icon) {
|
|
4603
|
-
// config.icon = `/${env_path}/${config.icon}?raw=true`
|
|
4604
|
-
// } else {
|
|
4605
|
-
// config.icon = "/pinokio-black.png"
|
|
4606
|
-
// }
|
|
4607
4715
|
|
|
4608
4716
|
let name
|
|
4609
4717
|
if (env_path.startsWith("api")) {
|
|
4610
4718
|
name = env_path.split("/")[1]
|
|
4611
4719
|
}
|
|
4612
|
-
let editorpath = "/edit/" + req.params[0] + "/ENVIRONMENT"
|
|
4613
4720
|
|
|
4721
|
+
let editorpath
|
|
4722
|
+
if (env_result.relpath) {
|
|
4723
|
+
editorpath = "/edit/" + req.params[0] + "/" + env_result.relpath + "/ENVIRONMENT"
|
|
4724
|
+
} else {
|
|
4725
|
+
editorpath = "/edit/" + req.params[0] + "/ENVIRONMENT"
|
|
4726
|
+
}
|
|
4614
4727
|
if (config.run) {
|
|
4615
4728
|
let configStr = await fs.promises.readFile(p, "utf8")
|
|
4616
4729
|
res.render("task", {
|
|
@@ -4671,9 +4784,8 @@ class Server {
|
|
|
4671
4784
|
//})
|
|
4672
4785
|
}))
|
|
4673
4786
|
this.app.get("/pre/api/:name", ex(async (req, res) => {
|
|
4674
|
-
let
|
|
4675
|
-
let
|
|
4676
|
-
let config = (await this.kernel.loader.load(p)).resolved
|
|
4787
|
+
let launcher = await this.kernel.api.launcher(req.params.name)
|
|
4788
|
+
let config = launcher.script
|
|
4677
4789
|
if (config && config.pre) {
|
|
4678
4790
|
config.pre.forEach((item) => {
|
|
4679
4791
|
if (item.icon) {
|
|
@@ -4685,6 +4797,7 @@ class Server {
|
|
|
4685
4797
|
item.href = path.resolve(this.kernel.homedir, "api", req.params.name, item.href)
|
|
4686
4798
|
}
|
|
4687
4799
|
})
|
|
4800
|
+
let p2 = launcher.root
|
|
4688
4801
|
let env = await Environment.get2(p2, this.kernel)
|
|
4689
4802
|
res.render("pre", {
|
|
4690
4803
|
name: req.params.name,
|
|
@@ -4699,8 +4812,8 @@ class Server {
|
|
|
4699
4812
|
}
|
|
4700
4813
|
}))
|
|
4701
4814
|
this.app.get("/initialize/:name", ex(async (req, res) => {
|
|
4702
|
-
let
|
|
4703
|
-
let config
|
|
4815
|
+
let launcher = await this.kernel.api.launcher(req.params.name)
|
|
4816
|
+
let config = launcher.script
|
|
4704
4817
|
if (config) {
|
|
4705
4818
|
// if pinokio.js exists
|
|
4706
4819
|
if (config.pre && Array.isArray(config.pre)) {
|
|
@@ -4817,8 +4930,8 @@ class Server {
|
|
|
4817
4930
|
this.app.get("/gitcommit/:ref/*", ex(async (req, res) => {
|
|
4818
4931
|
// return git log
|
|
4819
4932
|
let dir = this.kernel.path("api", req.params[0])
|
|
4820
|
-
let changes = []
|
|
4821
4933
|
let d = Date.now()
|
|
4934
|
+
let changes = []
|
|
4822
4935
|
if (req.params.ref === "HEAD") {
|
|
4823
4936
|
try {
|
|
4824
4937
|
let statusMatrix = await git.statusMatrix({ dir, fs });
|
|
@@ -4841,6 +4954,7 @@ class Server {
|
|
|
4841
4954
|
webpath,
|
|
4842
4955
|
file: filepath,
|
|
4843
4956
|
path: fullPath,
|
|
4957
|
+
diffpath: `/gitdiff/${req.params.ref}/${req.params[0]}/${filepath}`,
|
|
4844
4958
|
status: Util.classifyChange(head, workdir, stage),
|
|
4845
4959
|
});
|
|
4846
4960
|
}
|
|
@@ -4900,6 +5014,7 @@ class Server {
|
|
|
4900
5014
|
webpath,
|
|
4901
5015
|
file: filepath,
|
|
4902
5016
|
path: fullPath,
|
|
5017
|
+
diffpath: `/gitdiff/${req.params.ref}/${req.params[0]}/${filepath}`,
|
|
4903
5018
|
status: type,
|
|
4904
5019
|
});
|
|
4905
5020
|
}
|
|
@@ -4907,7 +5022,8 @@ class Server {
|
|
|
4907
5022
|
console.log("git diff error", err);
|
|
4908
5023
|
}
|
|
4909
5024
|
}
|
|
4910
|
-
|
|
5025
|
+
let git_commit_url = `/run/scripts/git/commit.json?cwd=${dir}&callback_target=parent&callback=$location.href`
|
|
5026
|
+
res.json({ git_commit_url, changes })
|
|
4911
5027
|
}))
|
|
4912
5028
|
this.app.get("/gitdiff/:ref/*", ex(async (req, res) => {
|
|
4913
5029
|
let fullpath = this.kernel.path("api", req.params[0])
|
|
@@ -4987,6 +5103,10 @@ class Server {
|
|
|
4987
5103
|
}
|
|
4988
5104
|
res.json(response)
|
|
4989
5105
|
}))
|
|
5106
|
+
this.app.get("/info/git/:ref/*", ex(async (req, res) => {
|
|
5107
|
+
let response = await this.getGit(req.params.ref, req.params[0])
|
|
5108
|
+
res.json(response)
|
|
5109
|
+
}))
|
|
4990
5110
|
this.app.get("/git/:ref/*", ex(async (req, res) => {
|
|
4991
5111
|
|
|
4992
5112
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
@@ -4998,95 +5118,28 @@ class Server {
|
|
|
4998
5118
|
}
|
|
4999
5119
|
|
|
5000
5120
|
|
|
5001
|
-
|
|
5002
|
-
let dir = this.kernel.path("api", req.params[0])
|
|
5003
|
-
let branches = await git.listBranches({ fs, dir });
|
|
5004
|
-
let log = []
|
|
5005
|
-
try {
|
|
5006
|
-
log = await git.log({ fs, dir, depth: 50, ref: req.params.ref }); // fetch last 50 commits
|
|
5007
|
-
} catch (e) {
|
|
5008
|
-
console.log("Log error", e)
|
|
5009
|
-
}
|
|
5010
|
-
|
|
5011
|
-
let config = await this.kernel.git.config(dir)
|
|
5012
|
-
|
|
5013
|
-
let hosts = ""
|
|
5014
|
-
let hosts_file = this.kernel.path("config/gh/hosts.yml")
|
|
5015
|
-
let e = await this.exists(hosts_file)
|
|
5016
|
-
if (e) {
|
|
5017
|
-
hosts = await fs.promises.readFile(hosts_file, "utf8")
|
|
5018
|
-
if (hosts.startsWith("{}")) {
|
|
5019
|
-
hosts = ""
|
|
5020
|
-
}
|
|
5021
|
-
}
|
|
5022
|
-
let connected = (hosts.length > 0)
|
|
5023
|
-
let remote = null
|
|
5024
|
-
if (config["remote \"origin\""]) {
|
|
5025
|
-
remote = config["remote \"origin\""].url
|
|
5026
|
-
}
|
|
5027
|
-
|
|
5028
|
-
let branch = await git.currentBranch({ fs, dir, fullname: false });
|
|
5029
|
-
|
|
5030
|
-
const remote2 = await git.getConfig({
|
|
5031
|
-
fs,
|
|
5032
|
-
dir,
|
|
5033
|
-
path: `branch.${branch}.remote`
|
|
5034
|
-
});
|
|
5035
|
-
|
|
5036
|
-
// if current branch exitss => currengt branch is selected
|
|
5037
|
-
// if current branch does not exist => get logs[0].oid
|
|
5038
|
-
if (branch) {
|
|
5039
|
-
branches = branches.map((b) => {
|
|
5040
|
-
if (b === branch) {
|
|
5041
|
-
return {
|
|
5042
|
-
branch: b,
|
|
5043
|
-
selected: true
|
|
5044
|
-
}
|
|
5045
|
-
} else {
|
|
5046
|
-
return {
|
|
5047
|
-
branch: b,
|
|
5048
|
-
selected: false
|
|
5049
|
-
}
|
|
5050
|
-
}
|
|
5051
|
-
})
|
|
5052
|
-
} else {
|
|
5053
|
-
branches.push(log[0].oid)
|
|
5054
|
-
branches = branches.map((b) => {
|
|
5055
|
-
if (b === log[0].oid) {
|
|
5056
|
-
return {
|
|
5057
|
-
branch: b,
|
|
5058
|
-
selected: true
|
|
5059
|
-
}
|
|
5060
|
-
} else {
|
|
5061
|
-
return {
|
|
5062
|
-
branch: b,
|
|
5063
|
-
selected: false
|
|
5064
|
-
}
|
|
5065
|
-
}
|
|
5066
|
-
})
|
|
5067
|
-
}
|
|
5121
|
+
let { ref, config, remote, connected, log, branch, branches, dir } = await this.getGit(req.params.ref, req.params[0])
|
|
5068
5122
|
|
|
5069
5123
|
res.render("git", {
|
|
5124
|
+
config,
|
|
5125
|
+
remote,
|
|
5126
|
+
connected,
|
|
5127
|
+
log,
|
|
5070
5128
|
branch,
|
|
5071
5129
|
branches,
|
|
5072
|
-
ref
|
|
5130
|
+
ref,
|
|
5073
5131
|
path: req.params[0],
|
|
5074
|
-
log,
|
|
5075
|
-
connected,
|
|
5076
5132
|
// changes,
|
|
5077
5133
|
dir,
|
|
5078
|
-
config,
|
|
5079
|
-
remote,
|
|
5080
5134
|
theme: this.theme,
|
|
5081
5135
|
platform: this.kernel.platform,
|
|
5082
5136
|
agent: this.agent,
|
|
5083
5137
|
})
|
|
5084
5138
|
}))
|
|
5085
5139
|
this.app.get("/d/*", ex(async (req, res) => {
|
|
5086
|
-
console.log("> 1")
|
|
5087
5140
|
let filepath = Util.u2p(req.params[0])
|
|
5088
|
-
let
|
|
5089
|
-
|
|
5141
|
+
let terminal = await this.terminals(filepath)
|
|
5142
|
+
let plugin = await this.getPluginGlobal(req, this.kernel.plugin.config, terminal, filepath)
|
|
5090
5143
|
let html = ""
|
|
5091
5144
|
let plugin_menu
|
|
5092
5145
|
try {
|
|
@@ -5096,105 +5149,74 @@ class Server {
|
|
|
5096
5149
|
plugin_menu = []
|
|
5097
5150
|
}
|
|
5098
5151
|
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
5099
|
-
console.log("> 3")
|
|
5100
5152
|
let retry = false
|
|
5101
5153
|
// if plugin_menu is empty, try again in 1 sec
|
|
5102
5154
|
if (plugin_menu.length === 0) {
|
|
5103
5155
|
retry = true
|
|
5104
5156
|
}
|
|
5105
|
-
let venvs = await Util.find_venv(filepath)
|
|
5106
|
-
console.log("> 4")
|
|
5107
|
-
let terminal
|
|
5108
|
-
if (venvs.length > 0) {
|
|
5109
|
-
let terminals = []
|
|
5110
|
-
try {
|
|
5111
|
-
for(let i=0; i<venvs.length; i++) {
|
|
5112
|
-
let venv = venvs[i]
|
|
5113
|
-
let parsed = path.parse(venv)
|
|
5114
|
-
terminals.push(this.renderShell(filepath, i, 0, {
|
|
5115
|
-
icon: "fa-brands fa-python",
|
|
5116
|
-
title: "Python virtual environment",
|
|
5117
|
-
subtitle: this.kernel.path("api", parsed.name),
|
|
5118
|
-
type: "Start",
|
|
5119
|
-
shell: {
|
|
5120
|
-
venv: venv,
|
|
5121
|
-
input: true,
|
|
5122
|
-
}
|
|
5123
|
-
}))
|
|
5124
|
-
}
|
|
5125
|
-
} catch (e) {
|
|
5126
|
-
console.log(e)
|
|
5127
|
-
}
|
|
5128
|
-
terminal = {
|
|
5129
|
-
icon: "fa-solid fa-terminal",
|
|
5130
|
-
title: "Open web terminal",
|
|
5131
|
-
subtitle: "Open the terminal in the browser",
|
|
5132
|
-
menu: terminals
|
|
5133
|
-
}
|
|
5134
|
-
} else {
|
|
5135
|
-
terminal = {
|
|
5136
|
-
icon: "fa-solid fa-terminal",
|
|
5137
|
-
title: "Open web terminal",
|
|
5138
|
-
subtitle: "Work with the terminal directly in the browser",
|
|
5139
|
-
menu: [this.renderShell(filepath, 0, 0, {
|
|
5140
|
-
icon: "fa-solid fa-terminal",
|
|
5141
|
-
title: "Terminal",
|
|
5142
|
-
subtitle: filepath,
|
|
5143
|
-
type: "Start",
|
|
5144
|
-
shell: {
|
|
5145
|
-
input: true
|
|
5146
|
-
}
|
|
5147
|
-
})]
|
|
5148
|
-
}
|
|
5149
|
-
}
|
|
5150
|
-
console.log("> 5")
|
|
5151
5157
|
|
|
5152
5158
|
let exec_menus = []
|
|
5153
5159
|
let shell_menus = []
|
|
5160
|
+
let href_menus = []
|
|
5154
5161
|
if (plugin_menu.length > 0) {
|
|
5155
5162
|
for(let item of plugin_menu) {
|
|
5156
5163
|
// if shell.run method exists
|
|
5157
5164
|
// if exec method exists
|
|
5158
5165
|
let mode
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5166
|
+
if (item.run) {
|
|
5167
|
+
for(let step of item.run) {
|
|
5168
|
+
if (step.method === "exec") {
|
|
5169
|
+
mode = "exec"
|
|
5170
|
+
break
|
|
5171
|
+
}
|
|
5172
|
+
if (step.method === "shell.run") {
|
|
5173
|
+
mode = "shell"
|
|
5174
|
+
break
|
|
5175
|
+
}
|
|
5163
5176
|
}
|
|
5164
|
-
if (
|
|
5165
|
-
|
|
5166
|
-
|
|
5177
|
+
if (mode === "exec") {
|
|
5178
|
+
item.type = "Open"
|
|
5179
|
+
exec_menus.push(item)
|
|
5180
|
+
} else if (mode === "shell") {
|
|
5181
|
+
item.type = "Start"
|
|
5182
|
+
shell_menus.push(item)
|
|
5167
5183
|
}
|
|
5168
|
-
}
|
|
5169
|
-
|
|
5170
|
-
item.type = "Open"
|
|
5171
|
-
exec_menus.push(item)
|
|
5172
|
-
} else if (mode === "shell") {
|
|
5173
|
-
item.type = "Start"
|
|
5174
|
-
shell_menus.push(item)
|
|
5184
|
+
} else {
|
|
5185
|
+
href_menus.push(item)
|
|
5175
5186
|
}
|
|
5176
5187
|
}
|
|
5177
5188
|
exec_menus.sort((a, b) => { return a > b })
|
|
5178
5189
|
shell_menus.sort((a, b) => { return a > b })
|
|
5190
|
+
href_menus.sort((a, b) => { return a > b })
|
|
5179
5191
|
}
|
|
5180
|
-
|
|
5192
|
+
|
|
5193
|
+
// let terminal = await this.terminals(filepath)
|
|
5194
|
+
// let online_terminal = await this.getPluginGlobal(req, terminal, filepath)
|
|
5195
|
+
// console.log("online_terminal", online_terminal)
|
|
5196
|
+
terminal.menus = href_menus
|
|
5181
5197
|
let dynamic = [
|
|
5182
5198
|
{
|
|
5183
5199
|
icon: "fa-solid fa-robot",
|
|
5184
|
-
title: "
|
|
5185
|
-
subtitle: "
|
|
5200
|
+
title: "AI Engineer",
|
|
5201
|
+
subtitle: "Let AI work on this app",
|
|
5186
5202
|
menu: shell_menus
|
|
5187
5203
|
},
|
|
5188
5204
|
{
|
|
5189
5205
|
icon: "fa-solid fa-arrow-up-right-from-square",
|
|
5190
|
-
title: "
|
|
5206
|
+
title: "External apps",
|
|
5191
5207
|
subtitle: "Open this project in 3rd party apps",
|
|
5192
5208
|
menu: exec_menus
|
|
5193
5209
|
},
|
|
5194
|
-
terminal
|
|
5210
|
+
terminal
|
|
5195
5211
|
]
|
|
5196
|
-
|
|
5212
|
+
let spec = ""
|
|
5213
|
+
try {
|
|
5214
|
+
spec = await fs.promises.readFile(path.resolve(filepath, "SPEC.md"), "utf8")
|
|
5215
|
+
} catch (e) {
|
|
5216
|
+
}
|
|
5197
5217
|
res.render("d", {
|
|
5218
|
+
filepath,
|
|
5219
|
+
spec,
|
|
5198
5220
|
retry,
|
|
5199
5221
|
current_urls,
|
|
5200
5222
|
docs: this.docs,
|
|
@@ -5243,20 +5265,6 @@ class Server {
|
|
|
5243
5265
|
}
|
|
5244
5266
|
res.render("mini", result)
|
|
5245
5267
|
}))
|
|
5246
|
-
this.app.get("/asset/*", ex((req, res) => {
|
|
5247
|
-
let pathComponents = req.params[0].split("/")
|
|
5248
|
-
let filepath = this.kernel.path(...pathComponents)
|
|
5249
|
-
try {
|
|
5250
|
-
if (req.query.frame) {
|
|
5251
|
-
let m = mime.lookup(filepath)
|
|
5252
|
-
res.type("text/plain")
|
|
5253
|
-
}
|
|
5254
|
-
//res.setHeader('Content-Disposition', 'inline');
|
|
5255
|
-
res.sendFile(filepath)
|
|
5256
|
-
} catch (e) {
|
|
5257
|
-
res.status(404).send(e.message);
|
|
5258
|
-
}
|
|
5259
|
-
}))
|
|
5260
5268
|
this.app.get("/raw/*", ex((req, res) => {
|
|
5261
5269
|
let pathComponents = req.params[0].split("/")
|
|
5262
5270
|
let filepath = this.kernel.path("api", ...pathComponents)
|
|
@@ -5324,7 +5332,9 @@ class Server {
|
|
|
5324
5332
|
}
|
|
5325
5333
|
}))
|
|
5326
5334
|
this.app.get("/pinokio/dynamic_global/*", ex(async (req, res) => {
|
|
5327
|
-
let
|
|
5335
|
+
let filepath = Util.u2p(req.params[0])
|
|
5336
|
+
let terminal = await this.terminals(filepath)
|
|
5337
|
+
let plugin = await this.getPluginGlobal(req, this.kernel.plugin.config, terminal, filepath)
|
|
5328
5338
|
if (plugin) {
|
|
5329
5339
|
let html = ""
|
|
5330
5340
|
if (plugin && plugin.menu) {
|
|
@@ -5347,7 +5357,8 @@ class Server {
|
|
|
5347
5357
|
}))
|
|
5348
5358
|
this.app.get("/pinokio/dynamic/:name", ex(async (req, res) => {
|
|
5349
5359
|
// await this.kernel.plugin.init()
|
|
5350
|
-
|
|
5360
|
+
|
|
5361
|
+
let plugin = await this.getPlugin(req, this.kernel.plugin.config, req.params.name)
|
|
5351
5362
|
let html = ""
|
|
5352
5363
|
let plugin_menu
|
|
5353
5364
|
if (plugin) {
|
|
@@ -5399,6 +5410,15 @@ class Server {
|
|
|
5399
5410
|
})
|
|
5400
5411
|
res.send(html)
|
|
5401
5412
|
}))
|
|
5413
|
+
this.app.get("/repos/:name", ex(async (req, res) => {
|
|
5414
|
+
// await this.kernel.plugin.init()
|
|
5415
|
+
let c = this.kernel.path("api", req.params.name)
|
|
5416
|
+
let repos = await this.kernel.git.repos(c)
|
|
5417
|
+
let repos_with_remote = repos.filter((repo) => {
|
|
5418
|
+
return repo.url
|
|
5419
|
+
})
|
|
5420
|
+
res.json(repos_with_remote)
|
|
5421
|
+
}))
|
|
5402
5422
|
this.app.get("/pinokio/repos/:name", ex(async (req, res) => {
|
|
5403
5423
|
// await this.kernel.plugin.init()
|
|
5404
5424
|
let c = this.kernel.path("api", req.params.name)
|
|
@@ -5420,9 +5440,10 @@ class Server {
|
|
|
5420
5440
|
}))
|
|
5421
5441
|
this.app.get("/pinokio/sidebar/:name", ex(async (req, res) => {
|
|
5422
5442
|
let name = req.params.name
|
|
5423
|
-
let
|
|
5443
|
+
let launcher = await this.kernel.api.launcher(name)
|
|
5424
5444
|
let rawpath = "/api/" + name
|
|
5425
|
-
let config
|
|
5445
|
+
let config = launcher.script
|
|
5446
|
+
req.launcher_root = launcher.launcher_root
|
|
5426
5447
|
if (config && config.menu) {
|
|
5427
5448
|
if (typeof config.menu === "function") {
|
|
5428
5449
|
if (config.menu.constructor.name === "AsyncFunction") {
|
|
@@ -5500,81 +5521,72 @@ class Server {
|
|
|
5500
5521
|
// await this.kernel.refresh()
|
|
5501
5522
|
// res.json({ success: true })
|
|
5502
5523
|
// }))
|
|
5503
|
-
|
|
5504
|
-
|
|
5524
|
+
|
|
5525
|
+
|
|
5526
|
+
this.app.get("/info/system", ex(async (req,res) => {
|
|
5505
5527
|
let current_peer_info = await this.kernel.peer.current_host()
|
|
5506
5528
|
res.json(current_peer_info)
|
|
5507
|
-
|
|
5529
|
+
}))
|
|
5530
|
+
this.app.get("/info/api", ex(async (req,res) => {
|
|
5531
|
+
// api related info
|
|
5532
|
+
let repo = this.kernel.git.find(req.query.git)
|
|
5533
|
+
if (repo) {
|
|
5534
|
+
let repos = await this.kernel.git.repos(repo.path)
|
|
5535
|
+
repos = repos.filter((r) => {
|
|
5536
|
+
return r.main
|
|
5537
|
+
})
|
|
5538
|
+
let repos_with_remote = []
|
|
5539
|
+
let main_repo
|
|
5540
|
+
for(let repo of repos) {
|
|
5541
|
+
if (repo.url) {
|
|
5542
|
+
repo.commit = await this.kernel.git.getHead(repo.gitParentPath)
|
|
5543
|
+
let du = await Util.du(repo.gitParentPath)
|
|
5544
|
+
repo.du = du
|
|
5545
|
+
repos_with_remote.push(repo)
|
|
5546
|
+
}
|
|
5547
|
+
if (repo.main) {
|
|
5548
|
+
main_repo = repo
|
|
5549
|
+
}
|
|
5550
|
+
}
|
|
5551
|
+
res.json({
|
|
5552
|
+
repos: repos_with_remote
|
|
5553
|
+
})
|
|
5554
|
+
} else {
|
|
5555
|
+
res.json({
|
|
5556
|
+
repos: []
|
|
5557
|
+
})
|
|
5558
|
+
}
|
|
5559
|
+
}))
|
|
5560
|
+
this.app.get("/info/api/:name", ex(async (req,res) => {
|
|
5561
|
+
// api related info
|
|
5562
|
+
let c = this.kernel.path("api", req.params.name)
|
|
5563
|
+
let repos = await this.kernel.git.repos(c)
|
|
5564
|
+
let repos_with_remote = []
|
|
5565
|
+
let main_repo
|
|
5566
|
+
for(let repo of repos) {
|
|
5567
|
+
if (repo.url) {
|
|
5568
|
+
repo.commit = await this.kernel.git.getHead(repo.gitParentPath)
|
|
5569
|
+
repos_with_remote.push(repo)
|
|
5570
|
+
}
|
|
5571
|
+
if (repo.main) {
|
|
5572
|
+
main_repo = repo
|
|
5573
|
+
}
|
|
5574
|
+
}
|
|
5508
5575
|
res.json({
|
|
5509
|
-
|
|
5510
|
-
arch: this.kernel.arch,
|
|
5511
|
-
platform: this.kernel.platform,
|
|
5512
|
-
name: this.kernel.peer.name,
|
|
5513
|
-
host: this.kernel.peer.host,
|
|
5514
|
-
port_mapping: this.kernel.router.port_mapping,
|
|
5515
|
-
//router: this.kernel.router.info(),
|
|
5516
|
-
proc: this.kernel.processes.info,
|
|
5517
|
-
router: this.kernel.router.published(),
|
|
5518
|
-
memory: this.kernel.memory
|
|
5576
|
+
repos: repos_with_remote
|
|
5519
5577
|
})
|
|
5520
|
-
|
|
5578
|
+
}))
|
|
5579
|
+
|
|
5580
|
+
|
|
5581
|
+
this.app.get("/pinokio/peer", ex(async (req, res) => {
|
|
5582
|
+
let current_peer_info = await this.kernel.peer.current_host()
|
|
5583
|
+
res.json(current_peer_info)
|
|
5521
5584
|
}))
|
|
5522
5585
|
this.app.get("/pinokio/memory", ex((req, res) => {
|
|
5523
5586
|
let filepath = req.query.filepath
|
|
5524
5587
|
let mem = this.getMemory(filepath)
|
|
5525
5588
|
res.json(mem)
|
|
5526
5589
|
}))
|
|
5527
|
-
// this.app.post("/pinokio/tunnel", async (req, res) => {
|
|
5528
|
-
// let port
|
|
5529
|
-
// let local_host
|
|
5530
|
-
// try {
|
|
5531
|
-
// let u = new URL(req.body.url)
|
|
5532
|
-
// port = u.port
|
|
5533
|
-
// local_host = u.hostname
|
|
5534
|
-
// console.log({ local_host, port })
|
|
5535
|
-
// if (req.body.action === "start") {
|
|
5536
|
-
// // Output ngrok url to console
|
|
5537
|
-
//
|
|
5538
|
-
// let url = req.body.url
|
|
5539
|
-
// console.log("tunnel", req.body)
|
|
5540
|
-
// const tunnel = await ngrok.forward({ addr: port, authtoken: req.body.token });
|
|
5541
|
-
// console.log("created", tunnel)
|
|
5542
|
-
// console.log("url", tunnel.url())
|
|
5543
|
-
// this.tunnels[url] = tunnel
|
|
5544
|
-
// res.json({ url: tunnel.url() })
|
|
5545
|
-
//
|
|
5546
|
-
//
|
|
5547
|
-
// // localtunnel
|
|
5548
|
-
// //const tunnel = await localtunnel({ local_host, port: parseInt(port) });
|
|
5549
|
-
// //const tunnel = await localtunnel({ local_host: "127.0.0.1", port: parseInt(port) });
|
|
5550
|
-
//
|
|
5551
|
-
// //const tunnel = await localtunnel({ port: parseInt(port) });
|
|
5552
|
-
// //this.tunnels[url] = tunnel
|
|
5553
|
-
// //tunnel.on('error', (err) => {
|
|
5554
|
-
// // console.log(err)
|
|
5555
|
-
// // delete this.tunnels[url]
|
|
5556
|
-
// //})
|
|
5557
|
-
// //tunnel.on('close', () => {
|
|
5558
|
-
// // // tunnels are closed
|
|
5559
|
-
// // console.log("tunnel closed", { url, tunnel_url: tunnel.url })
|
|
5560
|
-
// // delete this.tunnels[url]
|
|
5561
|
-
// //});
|
|
5562
|
-
// //res.json({ url: tunnel.url })
|
|
5563
|
-
// } else if (req.body.action === "stop") {
|
|
5564
|
-
// let url = req.body.url
|
|
5565
|
-
// await this.tunnels[url].close()
|
|
5566
|
-
// delete this.tunnels[url]
|
|
5567
|
-
// res.json({ url })
|
|
5568
|
-
//// let url = req.body.url
|
|
5569
|
-
//// console.log({ tunnels: this.tunnels, url })
|
|
5570
|
-
//// this.tunnels[url].close()
|
|
5571
|
-
//// res.json({ url })
|
|
5572
|
-
// }
|
|
5573
|
-
// } catch (e) {
|
|
5574
|
-
// console.log("ERROR", e)
|
|
5575
|
-
// res.json({ error: e.message })
|
|
5576
|
-
// }
|
|
5577
|
-
// })
|
|
5578
5590
|
this.app.post("/pinokio/tabs", ex(async (req, res) => {
|
|
5579
5591
|
this.tabs[req.body.name] = req.body.tabs
|
|
5580
5592
|
res.json({ success: true })
|
|
@@ -5600,6 +5612,41 @@ class Server {
|
|
|
5600
5612
|
this.app.get("/pinokio/browser/:name", ex(async (req, res) => {
|
|
5601
5613
|
await this.chrome(req, res, "run")
|
|
5602
5614
|
}))
|
|
5615
|
+
|
|
5616
|
+
|
|
5617
|
+
this.app.get("/p/:name/review", ex(async (req, res) => {
|
|
5618
|
+
let gitRemote = null
|
|
5619
|
+
try {
|
|
5620
|
+
const repositoryPath = path.resolve(this.kernel.api.userdir, req.params.name)
|
|
5621
|
+
console.log({ repositoryPath })
|
|
5622
|
+
gitRemote = await git.getConfig({
|
|
5623
|
+
fs,
|
|
5624
|
+
http,
|
|
5625
|
+
dir: repositoryPath,
|
|
5626
|
+
path: 'remote.origin.url'
|
|
5627
|
+
})
|
|
5628
|
+
} catch (e) {
|
|
5629
|
+
console.log("ERROR", e)
|
|
5630
|
+
}
|
|
5631
|
+
let name = req.params.name
|
|
5632
|
+
let run_tab = "/p/" + name
|
|
5633
|
+
let dev_tab = "/p/" + name + "/dev"
|
|
5634
|
+
let review_tab = "/p/" + name + "/review"
|
|
5635
|
+
res.render("review", {
|
|
5636
|
+
run_tab,
|
|
5637
|
+
dev_tab,
|
|
5638
|
+
review_tab,
|
|
5639
|
+
name: req.params.name,
|
|
5640
|
+
type: "review",
|
|
5641
|
+
title: name,
|
|
5642
|
+
url: gitRemote,
|
|
5643
|
+
//redirect_uri: "http://localhost:3001/apps/redirect?git=" + gitRemote,
|
|
5644
|
+
redirect_uri: "https://app-7pt7.onrender.com/apps/redirect?git=" + gitRemote,
|
|
5645
|
+
platform: this.kernel.platform,
|
|
5646
|
+
theme: this.theme,
|
|
5647
|
+
agent: this.agent,
|
|
5648
|
+
})
|
|
5649
|
+
}))
|
|
5603
5650
|
this.app.get("/p/:name/dev", ex(async (req, res) => {
|
|
5604
5651
|
await this.chrome(req, res, "browse")
|
|
5605
5652
|
}))
|
|
@@ -5623,7 +5670,7 @@ class Server {
|
|
|
5623
5670
|
res.json({ success: true })
|
|
5624
5671
|
} else if (req.body.type === 'env') {
|
|
5625
5672
|
let envpath = this.kernel.path("ENVIRONMENT")
|
|
5626
|
-
let str = await Environment.ENV("system", this.kernel.homedir)
|
|
5673
|
+
let str = await Environment.ENV("system", this.kernel.homedir, this.kernel)
|
|
5627
5674
|
await fs.promises.writeFile(path.resolve(this.kernel.homedir, "ENVIRONMENT"), str)
|
|
5628
5675
|
res.json({ success: true })
|
|
5629
5676
|
} else if (req.body.type === 'browser-cache') {
|
|
@@ -5646,35 +5693,8 @@ class Server {
|
|
|
5646
5693
|
res.json({ error: err.stack })
|
|
5647
5694
|
}
|
|
5648
5695
|
}))
|
|
5649
|
-
// this.app.get("/pinokio/shell_state", (req, res) => {
|
|
5650
|
-
// let states = this.kernel.shell.shells.map((s) => {
|
|
5651
|
-
// return {
|
|
5652
|
-
// state: s.state,
|
|
5653
|
-
// id: s.id,
|
|
5654
|
-
// group: s.group,
|
|
5655
|
-
// env: s.env,
|
|
5656
|
-
// path: s.path,
|
|
5657
|
-
// cmd: s.cmd,
|
|
5658
|
-
// done: s.done,
|
|
5659
|
-
// ready: s.ready,
|
|
5660
|
-
// }
|
|
5661
|
-
// })
|
|
5662
|
-
//
|
|
5663
|
-
// let info = {
|
|
5664
|
-
// platform: this.kernel.platform,
|
|
5665
|
-
// arch: this.kernel.arch,
|
|
5666
|
-
// running: this.kernel.api.running,
|
|
5667
|
-
// home: this.kernel.homedir,
|
|
5668
|
-
// vars: this.kernel.vars,
|
|
5669
|
-
// memory: this.kernel.memory,
|
|
5670
|
-
// procs: this.kernel.procs,
|
|
5671
|
-
// gpu: this.kernel.gpu,
|
|
5672
|
-
// gpus: this.kernel.gpus
|
|
5673
|
-
// }
|
|
5674
|
-
// })
|
|
5675
5696
|
this.app.get("/pinokio/logs.zip", ex((req, res) => {
|
|
5676
5697
|
let zipPath = this.kernel.path("logs.zip")
|
|
5677
|
-
console.log("sendFile", zipPath)
|
|
5678
5698
|
res.download(zipPath)
|
|
5679
5699
|
}))
|
|
5680
5700
|
this.app.post("/pinokio/log", ex(async (req, res) => {
|
|
@@ -5807,7 +5827,7 @@ class Server {
|
|
|
5807
5827
|
await fs.promises.cp(old_path, new_path, { recursive: true })
|
|
5808
5828
|
|
|
5809
5829
|
// 2. edit meta in the new_path
|
|
5810
|
-
await this.updateMeta(formData, formData.new_path)
|
|
5830
|
+
await this.kernel.api.updateMeta(formData, formData.new_path)
|
|
5811
5831
|
|
|
5812
5832
|
}
|
|
5813
5833
|
} else if (formData.move) {
|
|
@@ -5820,11 +5840,11 @@ class Server {
|
|
|
5820
5840
|
}
|
|
5821
5841
|
|
|
5822
5842
|
// 2. edit meta in the new_path
|
|
5823
|
-
await this.updateMeta(formData, formData.new_path)
|
|
5843
|
+
await this.kernel.api.updateMeta(formData, formData.new_path)
|
|
5824
5844
|
} else {
|
|
5825
5845
|
// 1. edit only
|
|
5826
5846
|
if (formData.old_path === formData.new_path) {
|
|
5827
|
-
await this.updateMeta(formData, formData.new_path)
|
|
5847
|
+
await this.kernel.api.updateMeta(formData, formData.new_path)
|
|
5828
5848
|
}
|
|
5829
5849
|
}
|
|
5830
5850
|
} else {
|
|
@@ -5888,6 +5908,56 @@ class Server {
|
|
|
5888
5908
|
res.status(404).send("Missing attribute: path")
|
|
5889
5909
|
}
|
|
5890
5910
|
}))
|
|
5911
|
+
this.app.get("/snapshots", ex(async (req, res) => {
|
|
5912
|
+
let files = []
|
|
5913
|
+
try {
|
|
5914
|
+
files = await fs.promises.readdir(this.kernel.path("screenshots"))
|
|
5915
|
+
files = files.map((file) => {
|
|
5916
|
+
return `/asset/screenshots/${file}`
|
|
5917
|
+
})
|
|
5918
|
+
} catch (e) {
|
|
5919
|
+
}
|
|
5920
|
+
res.json({ files })
|
|
5921
|
+
}))
|
|
5922
|
+
|
|
5923
|
+
this.app.post("/snapshots", ex(async (req, res) => {
|
|
5924
|
+
const { filename } = req.body
|
|
5925
|
+
|
|
5926
|
+
if (!filename) {
|
|
5927
|
+
return res.status(400).json({ error: "Missing filename parameter" })
|
|
5928
|
+
}
|
|
5929
|
+
|
|
5930
|
+
try {
|
|
5931
|
+
// Extract just the filename from the path (security measure)
|
|
5932
|
+
const baseFilename = path.basename(filename.replace('/asset/screenshots/', ''))
|
|
5933
|
+
const fullPath = this.kernel.path("screenshots", baseFilename)
|
|
5934
|
+
|
|
5935
|
+
// Check if file exists before attempting to delete
|
|
5936
|
+
try {
|
|
5937
|
+
await fs.promises.access(fullPath)
|
|
5938
|
+
} catch (e) {
|
|
5939
|
+
return res.status(404).json({ error: "File not found" })
|
|
5940
|
+
}
|
|
5941
|
+
|
|
5942
|
+
// Delete the file
|
|
5943
|
+
await fs.promises.unlink(fullPath)
|
|
5944
|
+
|
|
5945
|
+
res.json({ success: true, message: "File deleted successfully" })
|
|
5946
|
+
|
|
5947
|
+
} catch (e) {
|
|
5948
|
+
console.log("Error deleting screenshot:", e)
|
|
5949
|
+
res.status(500).json({ error: "Failed to delete file: " + e.message })
|
|
5950
|
+
}
|
|
5951
|
+
}))
|
|
5952
|
+
this.app.post("/screenshot", this.upload.any(), ex(async (req, res) => {
|
|
5953
|
+
await fs.promises.mkdir(this.kernel.path("screenshots"), { recursive: true }).catch((e) => { })
|
|
5954
|
+
for(let key in req.files) {
|
|
5955
|
+
let file = req.files[key]
|
|
5956
|
+
console.log({ file, key })
|
|
5957
|
+
let ts = String(Date.now()) + ".png"
|
|
5958
|
+
await fs.promises.writeFile(this.kernel.path("screenshots", ts), file.buffer)
|
|
5959
|
+
}
|
|
5960
|
+
}))
|
|
5891
5961
|
this.app.post("/pinokio/fs", this.upload.any(), ex(async (req, res) => {
|
|
5892
5962
|
/*
|
|
5893
5963
|
Packet format:
|
|
@@ -6079,6 +6149,14 @@ class Server {
|
|
|
6079
6149
|
res.json({ success: true })
|
|
6080
6150
|
}
|
|
6081
6151
|
}))
|
|
6152
|
+
this.app.get("/bin_ready", ex((req, res) => {
|
|
6153
|
+
if (this.kernel.bin && !this.kernel.bin.requirements_pending) {
|
|
6154
|
+
res.json({ success: true })
|
|
6155
|
+
} else {
|
|
6156
|
+
res.json({ success: false })
|
|
6157
|
+
}
|
|
6158
|
+
}))
|
|
6159
|
+
|
|
6082
6160
|
this.app.get("/check", ex((req, res) => {
|
|
6083
6161
|
res.json({ success: true })
|
|
6084
6162
|
}))
|