pinokiod 3.41.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 +1037 -964
- 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 +220 -94
- 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,8 +4181,6 @@ class Server {
|
|
|
3996
4181
|
})
|
|
3997
4182
|
}
|
|
3998
4183
|
|
|
3999
|
-
console.log("Info", this.kernel.peer.info)
|
|
4000
|
-
|
|
4001
4184
|
// if (peers.length === 0) {
|
|
4002
4185
|
// console.log("network not yet ready")
|
|
4003
4186
|
// res.redirect("/")
|
|
@@ -4052,11 +4235,13 @@ class Server {
|
|
|
4052
4235
|
// App sharing
|
|
4053
4236
|
let apipath = this.kernel.path("api")
|
|
4054
4237
|
let files = await fs.promises.readdir(apipath, { withFileTypes: true })
|
|
4055
|
-
let folders =
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
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
|
+
}
|
|
4060
4245
|
let apps = []
|
|
4061
4246
|
for(let folder of folders) {
|
|
4062
4247
|
let meta = await this.kernel.api.meta(folder)
|
|
@@ -4077,14 +4262,16 @@ class Server {
|
|
|
4077
4262
|
|
|
4078
4263
|
let processes = []
|
|
4079
4264
|
try {
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
if (
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
|
|
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
|
+
}
|
|
4088
4275
|
}
|
|
4089
4276
|
}
|
|
4090
4277
|
}
|
|
@@ -4101,8 +4288,12 @@ class Server {
|
|
|
4101
4288
|
|
|
4102
4289
|
let list = this.getPeers()
|
|
4103
4290
|
let installed = this.kernel.peer.info && this.kernel.peer.info[host] ? this.kernel.peer.info[host].installed : []
|
|
4104
|
-
res.render("network", {
|
|
4105
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,
|
|
4106
4297
|
host,
|
|
4107
4298
|
favicons,
|
|
4108
4299
|
titles,
|
|
@@ -4142,78 +4333,16 @@ class Server {
|
|
|
4142
4333
|
let str = await fs.promises.readFile(req.query.logpath, "utf8")
|
|
4143
4334
|
res.send(str)
|
|
4144
4335
|
}))
|
|
4145
|
-
this.app.get("/state/:type/:name", ex(async (req,res) => {
|
|
4146
|
-
let selected = null
|
|
4147
|
-
try {
|
|
4148
|
-
selected = this.selected[req.params.name][req.params.type]
|
|
4149
|
-
} catch (e) {
|
|
4150
|
-
}
|
|
4151
|
-
res.json({
|
|
4152
|
-
selected,
|
|
4153
|
-
})
|
|
4154
|
-
}))
|
|
4155
|
-
this.app.post("/state", ex(async (req, res) => {
|
|
4156
|
-
/*
|
|
4157
|
-
req.body := {
|
|
4158
|
-
name: <name>,
|
|
4159
|
-
type: "browse"|"run",
|
|
4160
|
-
method: "toggleMenu"|"select",
|
|
4161
|
-
params: {
|
|
4162
|
-
<url>,
|
|
4163
|
-
}
|
|
4164
|
-
}
|
|
4165
|
-
*/
|
|
4166
|
-
if (req.body.method === "select") {
|
|
4167
|
-
if (!this.selected[req.body.name]) {
|
|
4168
|
-
this.selected[req.body.name] = {}
|
|
4169
|
-
}
|
|
4170
|
-
this.selected[req.body.name][req.body.type] = req.body.params.url
|
|
4171
|
-
} else if (req.body.method === "toggleMenu") {
|
|
4172
|
-
if (!this.menu_hidden[req.body.name]) {
|
|
4173
|
-
this.menu_hidden[req.body.name] = {}
|
|
4174
|
-
}
|
|
4175
|
-
if (this.menu_hidden[req.body.name][req.body.type]) {
|
|
4176
|
-
this.menu_hidden[req.body.name][req.body.type] = false
|
|
4177
|
-
} else {
|
|
4178
|
-
this.menu_hidden[req.body.name][req.body.type] = true
|
|
4179
|
-
}
|
|
4180
|
-
}
|
|
4181
|
-
res.json({
|
|
4182
|
-
success: true
|
|
4183
|
-
})
|
|
4184
|
-
}))
|
|
4185
4336
|
this.app.post("/mkdir", ex(async (req, res) => {
|
|
4186
4337
|
let folder = req.body.folder
|
|
4187
4338
|
let folder_path = path.resolve(this.kernel.api.userdir, req.body.folder)
|
|
4188
4339
|
try {
|
|
4189
4340
|
// mkdir
|
|
4190
4341
|
await fs.promises.mkdir(folder_path)
|
|
4191
|
-
|
|
4192
|
-
// create basic pinokio.json
|
|
4193
|
-
|
|
4194
|
-
// add default icon
|
|
4195
|
-
|
|
4196
4342
|
let default_icon_path = path.resolve(__dirname, "public/pinokio-black.png")
|
|
4197
4343
|
let icon_path = path.resolve(folder_path, "icon.png")
|
|
4198
4344
|
await fs.promises.cp(default_icon_path, icon_path)
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
// write title/description to pinokio.json
|
|
4202
|
-
// let meta_path = path.resolve(folder_path, "pinokio.json")
|
|
4203
|
-
// let meta = {
|
|
4204
|
-
// title: "No title",
|
|
4205
|
-
// description: "",
|
|
4206
|
-
// icon: "icon.png",
|
|
4207
|
-
// plugin: {
|
|
4208
|
-
// menu: []
|
|
4209
|
-
// }
|
|
4210
|
-
// }
|
|
4211
|
-
// console.log({ folder_path, default_icon_path, icon_path, meta_path, meta })
|
|
4212
|
-
// await fs.promises.writeFile(meta_path, JSON.stringify(meta, null, 2))
|
|
4213
|
-
|
|
4214
4345
|
res.json({
|
|
4215
|
-
//success: "/pinokio/browser/"+folder
|
|
4216
|
-
//success: "/p/"+folder
|
|
4217
4346
|
success: "/init/"+folder
|
|
4218
4347
|
})
|
|
4219
4348
|
} catch (e) {
|
|
@@ -4296,7 +4425,7 @@ class Server {
|
|
|
4296
4425
|
*/
|
|
4297
4426
|
if (req.body.type) {
|
|
4298
4427
|
if (req.body.type === "local") {
|
|
4299
|
-
let env = await Environment.get(this.kernel.homedir)
|
|
4428
|
+
let env = await Environment.get(this.kernel.homedir, this.kernel)
|
|
4300
4429
|
if (env && env.PINOKIO_SHARE_LOCAL_PORT) {
|
|
4301
4430
|
let port = env.PINOKIO_SHARE_LOCAL_PORT.trim()
|
|
4302
4431
|
if (port.length > 0) {
|
|
@@ -4325,244 +4454,217 @@ class Server {
|
|
|
4325
4454
|
res.json({ error: "type must be 'local' or 'cloudflare'" })
|
|
4326
4455
|
}
|
|
4327
4456
|
}))
|
|
4328
|
-
this.app.get("/prototype/run/*", ex(async (req, res) => {
|
|
4329
|
-
let pathComponents = req.params[0].split("/").concat("pinokio.js")
|
|
4330
|
-
let config = await this.kernel.api.meta({ path: req.query.path })
|
|
4331
|
-
let pinokiojson_path = path.resolve(req.query.path, "pinokio.json")
|
|
4332
|
-
let pinokiojson = await this.kernel.require(pinokiojson_path)
|
|
4333
|
-
if (pinokiojson) {
|
|
4334
|
-
if (pinokiojson.plugin) {
|
|
4335
|
-
if (pinokiojson.plugin.menu) {
|
|
4336
|
-
} else {
|
|
4337
|
-
pinokiojson.plugin.menu = []
|
|
4338
|
-
await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
4339
|
-
}
|
|
4340
|
-
} else {
|
|
4341
|
-
pinokiojson.plugin = { menu: [] }
|
|
4342
|
-
await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
4343
|
-
}
|
|
4344
|
-
} else {
|
|
4345
|
-
pinokiojson = {
|
|
4346
|
-
plugin: {
|
|
4347
|
-
menu: []
|
|
4348
|
-
}
|
|
4349
|
-
}
|
|
4350
|
-
await fs.promises.writeFile(pinokiojson_path, JSON.stringify(pinokiojson, null, 2))
|
|
4351
|
-
}
|
|
4352
|
-
req.base = this.kernel.path("prototype")
|
|
4353
|
-
req.query.callback = config.ui
|
|
4354
|
-
//req.query.callback = config.browse
|
|
4355
|
-
req.query.cwd = req.query.path
|
|
4356
|
-
await this.render(req, res, pathComponents, null)
|
|
4357
|
-
}))
|
|
4358
|
-
this.app.get("/prototype/show/*", ex(async (req, res) => {
|
|
4359
|
-
let name = req.params[0].split("/").filter((x) => { return x }).join("/")
|
|
4360
|
-
|
|
4361
|
-
// print readme
|
|
4362
|
-
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
let paths = req.params[0].split("/")
|
|
4367
|
-
let item
|
|
4368
|
-
let config = this.kernel.proto.config
|
|
4369
|
-
for(let key of paths) {
|
|
4370
|
-
config = config.menu[key]
|
|
4371
|
-
}
|
|
4372
|
-
console.log("config.shell", config.shell)
|
|
4373
|
-
if (config.shell) {
|
|
4374
|
-
|
|
4375
|
-
let rendered = this.kernel.template.render(config.shell, {})
|
|
4376
|
-
let params = new URLSearchParams()
|
|
4377
|
-
if (rendered.path) params.set("path", encodeURIComponent(rendered.path))
|
|
4378
|
-
if (rendered.message) params.set("message", encodeURIComponent(rendered.message))
|
|
4379
|
-
if (rendered.venv) params.set("venv", encodeURIComponent(rendered.venv))
|
|
4380
|
-
if (rendered.input) params.set("input", true)
|
|
4381
|
-
if (rendered.callback) params.set("callback", encodeURIComponent(rendered.callback))
|
|
4382
|
-
if (rendered.kill) params.set("kill", encodeURIComponent(rendered.kill))
|
|
4383
|
-
if (rendered.done) params.set("done", encodeURIComponent(rendered.done))
|
|
4384
|
-
if (rendered.env) {
|
|
4385
|
-
for(let key in rendered.env) {
|
|
4386
|
-
let env_key = "env." + key
|
|
4387
|
-
params.set(env_key, rendered.env[key])
|
|
4388
|
-
}
|
|
4389
|
-
}
|
|
4390
|
-
if (rendered.conda) {
|
|
4391
|
-
for(let key in rendered.conda) {
|
|
4392
|
-
let conda_key = "conda." + key
|
|
4393
|
-
params.set(conda_key, rendered.conda[key])
|
|
4394
|
-
}
|
|
4395
|
-
}
|
|
4396
|
-
let shell_id = Math.floor("SH_" + 1000000000000 * Math.random())
|
|
4397
|
-
let href = "/shell/" + shell_id + "?" + params.toString()
|
|
4398
|
-
res.redirect(href)
|
|
4399
|
-
} else {
|
|
4400
|
-
let run_path = "/run/prototype/system/" + config.href + "?cwd=" + req.query.path
|
|
4401
|
-
let readme_path = this.kernel.path("prototype/system", config.readme)
|
|
4402
|
-
let md = await fs.promises.readFile(readme_path, "utf8")
|
|
4403
|
-
let baseUrl = "/asset/prototype/system/" + (config.readme.split("/").slice(0, -1).join("/")) + "/"
|
|
4404
|
-
let readme = marked.parse(md, {
|
|
4405
|
-
baseUrl
|
|
4406
|
-
})
|
|
4407
|
-
res.render("prototype/show", {
|
|
4408
|
-
run_path,
|
|
4409
|
-
portal: this.portal,
|
|
4410
|
-
readme,
|
|
4411
|
-
logo: this.logo,
|
|
4412
|
-
theme: this.theme,
|
|
4413
|
-
agent: this.agent,
|
|
4414
|
-
kernel: this.kernel,
|
|
4415
|
-
})
|
|
4416
|
-
}
|
|
4417
|
-
|
|
4418
|
-
}))
|
|
4419
|
-
this.app.get("/prototype", ex(async (req, res) => {
|
|
4420
|
-
// load meta
|
|
4457
|
+
// this.app.get("/prototype/run/*", ex(async (req, res) => {
|
|
4458
|
+
// let pathComponents = req.params[0].split("/").concat("pinokio.js")
|
|
4421
4459
|
// let config = await this.kernel.api.meta({ path: req.query.path })
|
|
4422
|
-
// let
|
|
4423
|
-
//
|
|
4424
|
-
//
|
|
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))
|
|
4425
4480
|
// }
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
}
|
|
4435
|
-
|
|
4436
|
-
let config = structuredClone(this.kernel.proto.config)
|
|
4437
|
-
config = this.renderMenu2(config, {
|
|
4438
|
-
cwd: req.query.path,
|
|
4439
|
-
href: "/prototype/show",
|
|
4440
|
-
path: this.kernel.path("prototype/system"),
|
|
4441
|
-
web_path: "/asset/prototype/system"
|
|
4442
|
-
})
|
|
4443
|
-
|
|
4444
|
-
// {
|
|
4445
|
-
// "icon": "fa-solid fa-power-off",
|
|
4446
|
-
// "text": "Run Default",
|
|
4447
|
-
// "href": "/api/facefusion-pinokio.git/run.js?run=true&fullscreen=true&mode=Default",
|
|
4448
|
-
// "params": {
|
|
4449
|
-
// "run": true,
|
|
4450
|
-
// "fullscreen": true,
|
|
4451
|
-
// "mode": "Default"
|
|
4452
|
-
// },
|
|
4453
|
-
// "src": "/api/facefusion-pinokio.git/run.js",
|
|
4454
|
-
// "html": "<i class=\"fa-solid fa-power-off\"></i> Run Default",
|
|
4455
|
-
// "btn": "<i class=\"fa-solid fa-power-off\"></i> Run Default",
|
|
4456
|
-
// "target": "@/api/facefusion-pinokio.git/run.js"
|
|
4457
|
-
// },
|
|
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("/")
|
|
4458
4489
|
//
|
|
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
|
-
|
|
4541
|
-
|
|
4542
|
-
|
|
4543
|
-
|
|
4544
|
-
|
|
4545
|
-
|
|
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
|
+
// }))
|
|
4546
4652
|
this.app.post("/env", ex(async (req, res) => {
|
|
4547
4653
|
let fullpath = path.resolve(this.kernel.homedir, req.body.filepath, "ENVIRONMENT")
|
|
4548
4654
|
let updated = req.body.vals
|
|
4549
4655
|
let hosts = req.body.hosts
|
|
4550
|
-
console.log("Util.update_env", { fullpath, filepath: req.body.filepath, updated })
|
|
4551
4656
|
await Util.update_env(fullpath, updated)
|
|
4552
4657
|
// for all environment variables that have hosts, save the key as well
|
|
4553
4658
|
// hosts := { env_key: host }
|
|
4554
4659
|
for(let env in hosts) {
|
|
4555
4660
|
let host = hosts[env]
|
|
4556
4661
|
let val = updated[env]
|
|
4557
|
-
console.log({ hosts, updated, host, val })
|
|
4558
4662
|
await this.kernel.kv.set(host.value, val, host.index)
|
|
4559
4663
|
}
|
|
4560
4664
|
res.json({})
|
|
4561
4665
|
}))
|
|
4562
4666
|
this.app.get("/env", ex(async (req, res) => {
|
|
4563
|
-
|
|
4564
|
-
await this.init_env(env_path)
|
|
4565
|
-
|
|
4667
|
+
await Environment.init({}, this.kernel)
|
|
4566
4668
|
let filepath = path.resolve(this.kernel.homedir, "ENVIRONMENT")
|
|
4567
4669
|
let editorpath = "/edit/ENVIRONMENT"
|
|
4568
4670
|
|
|
@@ -4581,41 +4683,47 @@ class Server {
|
|
|
4581
4683
|
})
|
|
4582
4684
|
}))
|
|
4583
4685
|
this.app.get("/env/*", ex(async (req, res) => {
|
|
4584
|
-
|
|
4585
4686
|
let env_path = req.params[0]
|
|
4586
|
-
// let p = path.resolve(this.kernel.homedir, env_path, "pinokio.js")
|
|
4587
|
-
// let config = (await this.kernel.loader.load(p)).resolved
|
|
4588
4687
|
let api_path
|
|
4589
4688
|
if (env_path.startsWith("api/")) {
|
|
4590
4689
|
api_path = env_path.slice(4)
|
|
4591
4690
|
}
|
|
4592
4691
|
let config = await this.kernel.api.meta(api_path)
|
|
4692
|
+
let env_result
|
|
4593
4693
|
if (config.run) {
|
|
4594
|
-
await
|
|
4694
|
+
env_result = await Environment.init({
|
|
4695
|
+
name: api_path,
|
|
4696
|
+
no_inherit: true
|
|
4697
|
+
}, this.kernel)
|
|
4595
4698
|
} else {
|
|
4596
|
-
await
|
|
4699
|
+
env_result = await Environment.init({
|
|
4700
|
+
name: api_path,
|
|
4701
|
+
}, this.kernel)
|
|
4597
4702
|
}
|
|
4598
4703
|
|
|
4599
|
-
|
|
4600
|
-
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")
|
|
4601
4709
|
|
|
4602
4710
|
let items = []
|
|
4603
4711
|
let e = await this.exists(filepath)
|
|
4604
4712
|
if (e) {
|
|
4605
4713
|
items = await Util.parse_env_detail(filepath)
|
|
4606
4714
|
}
|
|
4607
|
-
// if (config.icon) {
|
|
4608
|
-
// config.icon = `/${env_path}/${config.icon}?raw=true`
|
|
4609
|
-
// } else {
|
|
4610
|
-
// config.icon = "/pinokio-black.png"
|
|
4611
|
-
// }
|
|
4612
4715
|
|
|
4613
4716
|
let name
|
|
4614
4717
|
if (env_path.startsWith("api")) {
|
|
4615
4718
|
name = env_path.split("/")[1]
|
|
4616
4719
|
}
|
|
4617
|
-
let editorpath = "/edit/" + req.params[0] + "/ENVIRONMENT"
|
|
4618
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
|
+
}
|
|
4619
4727
|
if (config.run) {
|
|
4620
4728
|
let configStr = await fs.promises.readFile(p, "utf8")
|
|
4621
4729
|
res.render("task", {
|
|
@@ -4676,9 +4784,8 @@ class Server {
|
|
|
4676
4784
|
//})
|
|
4677
4785
|
}))
|
|
4678
4786
|
this.app.get("/pre/api/:name", ex(async (req, res) => {
|
|
4679
|
-
let
|
|
4680
|
-
let
|
|
4681
|
-
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
|
|
4682
4789
|
if (config && config.pre) {
|
|
4683
4790
|
config.pre.forEach((item) => {
|
|
4684
4791
|
if (item.icon) {
|
|
@@ -4690,6 +4797,7 @@ class Server {
|
|
|
4690
4797
|
item.href = path.resolve(this.kernel.homedir, "api", req.params.name, item.href)
|
|
4691
4798
|
}
|
|
4692
4799
|
})
|
|
4800
|
+
let p2 = launcher.root
|
|
4693
4801
|
let env = await Environment.get2(p2, this.kernel)
|
|
4694
4802
|
res.render("pre", {
|
|
4695
4803
|
name: req.params.name,
|
|
@@ -4704,8 +4812,8 @@ class Server {
|
|
|
4704
4812
|
}
|
|
4705
4813
|
}))
|
|
4706
4814
|
this.app.get("/initialize/:name", ex(async (req, res) => {
|
|
4707
|
-
let
|
|
4708
|
-
let config
|
|
4815
|
+
let launcher = await this.kernel.api.launcher(req.params.name)
|
|
4816
|
+
let config = launcher.script
|
|
4709
4817
|
if (config) {
|
|
4710
4818
|
// if pinokio.js exists
|
|
4711
4819
|
if (config.pre && Array.isArray(config.pre)) {
|
|
@@ -4822,8 +4930,8 @@ class Server {
|
|
|
4822
4930
|
this.app.get("/gitcommit/:ref/*", ex(async (req, res) => {
|
|
4823
4931
|
// return git log
|
|
4824
4932
|
let dir = this.kernel.path("api", req.params[0])
|
|
4825
|
-
let changes = []
|
|
4826
4933
|
let d = Date.now()
|
|
4934
|
+
let changes = []
|
|
4827
4935
|
if (req.params.ref === "HEAD") {
|
|
4828
4936
|
try {
|
|
4829
4937
|
let statusMatrix = await git.statusMatrix({ dir, fs });
|
|
@@ -4846,6 +4954,7 @@ class Server {
|
|
|
4846
4954
|
webpath,
|
|
4847
4955
|
file: filepath,
|
|
4848
4956
|
path: fullPath,
|
|
4957
|
+
diffpath: `/gitdiff/${req.params.ref}/${req.params[0]}/${filepath}`,
|
|
4849
4958
|
status: Util.classifyChange(head, workdir, stage),
|
|
4850
4959
|
});
|
|
4851
4960
|
}
|
|
@@ -4905,6 +5014,7 @@ class Server {
|
|
|
4905
5014
|
webpath,
|
|
4906
5015
|
file: filepath,
|
|
4907
5016
|
path: fullPath,
|
|
5017
|
+
diffpath: `/gitdiff/${req.params.ref}/${req.params[0]}/${filepath}`,
|
|
4908
5018
|
status: type,
|
|
4909
5019
|
});
|
|
4910
5020
|
}
|
|
@@ -4912,7 +5022,8 @@ class Server {
|
|
|
4912
5022
|
console.log("git diff error", err);
|
|
4913
5023
|
}
|
|
4914
5024
|
}
|
|
4915
|
-
|
|
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 })
|
|
4916
5027
|
}))
|
|
4917
5028
|
this.app.get("/gitdiff/:ref/*", ex(async (req, res) => {
|
|
4918
5029
|
let fullpath = this.kernel.path("api", req.params[0])
|
|
@@ -4992,6 +5103,10 @@ class Server {
|
|
|
4992
5103
|
}
|
|
4993
5104
|
res.json(response)
|
|
4994
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
|
+
}))
|
|
4995
5110
|
this.app.get("/git/:ref/*", ex(async (req, res) => {
|
|
4996
5111
|
|
|
4997
5112
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
@@ -5003,95 +5118,28 @@ class Server {
|
|
|
5003
5118
|
}
|
|
5004
5119
|
|
|
5005
5120
|
|
|
5006
|
-
|
|
5007
|
-
let dir = this.kernel.path("api", req.params[0])
|
|
5008
|
-
let branches = await git.listBranches({ fs, dir });
|
|
5009
|
-
let log = []
|
|
5010
|
-
try {
|
|
5011
|
-
log = await git.log({ fs, dir, depth: 50, ref: req.params.ref }); // fetch last 50 commits
|
|
5012
|
-
} catch (e) {
|
|
5013
|
-
console.log("Log error", e)
|
|
5014
|
-
}
|
|
5015
|
-
|
|
5016
|
-
let config = await this.kernel.git.config(dir)
|
|
5017
|
-
|
|
5018
|
-
let hosts = ""
|
|
5019
|
-
let hosts_file = this.kernel.path("config/gh/hosts.yml")
|
|
5020
|
-
let e = await this.exists(hosts_file)
|
|
5021
|
-
if (e) {
|
|
5022
|
-
hosts = await fs.promises.readFile(hosts_file, "utf8")
|
|
5023
|
-
if (hosts.startsWith("{}")) {
|
|
5024
|
-
hosts = ""
|
|
5025
|
-
}
|
|
5026
|
-
}
|
|
5027
|
-
let connected = (hosts.length > 0)
|
|
5028
|
-
let remote = null
|
|
5029
|
-
if (config["remote \"origin\""]) {
|
|
5030
|
-
remote = config["remote \"origin\""].url
|
|
5031
|
-
}
|
|
5032
|
-
|
|
5033
|
-
let branch = await git.currentBranch({ fs, dir, fullname: false });
|
|
5034
|
-
|
|
5035
|
-
const remote2 = await git.getConfig({
|
|
5036
|
-
fs,
|
|
5037
|
-
dir,
|
|
5038
|
-
path: `branch.${branch}.remote`
|
|
5039
|
-
});
|
|
5040
|
-
|
|
5041
|
-
// if current branch exitss => currengt branch is selected
|
|
5042
|
-
// if current branch does not exist => get logs[0].oid
|
|
5043
|
-
if (branch) {
|
|
5044
|
-
branches = branches.map((b) => {
|
|
5045
|
-
if (b === branch) {
|
|
5046
|
-
return {
|
|
5047
|
-
branch: b,
|
|
5048
|
-
selected: true
|
|
5049
|
-
}
|
|
5050
|
-
} else {
|
|
5051
|
-
return {
|
|
5052
|
-
branch: b,
|
|
5053
|
-
selected: false
|
|
5054
|
-
}
|
|
5055
|
-
}
|
|
5056
|
-
})
|
|
5057
|
-
} else {
|
|
5058
|
-
branches.push(log[0].oid)
|
|
5059
|
-
branches = branches.map((b) => {
|
|
5060
|
-
if (b === log[0].oid) {
|
|
5061
|
-
return {
|
|
5062
|
-
branch: b,
|
|
5063
|
-
selected: true
|
|
5064
|
-
}
|
|
5065
|
-
} else {
|
|
5066
|
-
return {
|
|
5067
|
-
branch: b,
|
|
5068
|
-
selected: false
|
|
5069
|
-
}
|
|
5070
|
-
}
|
|
5071
|
-
})
|
|
5072
|
-
}
|
|
5121
|
+
let { ref, config, remote, connected, log, branch, branches, dir } = await this.getGit(req.params.ref, req.params[0])
|
|
5073
5122
|
|
|
5074
5123
|
res.render("git", {
|
|
5124
|
+
config,
|
|
5125
|
+
remote,
|
|
5126
|
+
connected,
|
|
5127
|
+
log,
|
|
5075
5128
|
branch,
|
|
5076
5129
|
branches,
|
|
5077
|
-
ref
|
|
5130
|
+
ref,
|
|
5078
5131
|
path: req.params[0],
|
|
5079
|
-
log,
|
|
5080
|
-
connected,
|
|
5081
5132
|
// changes,
|
|
5082
5133
|
dir,
|
|
5083
|
-
config,
|
|
5084
|
-
remote,
|
|
5085
5134
|
theme: this.theme,
|
|
5086
5135
|
platform: this.kernel.platform,
|
|
5087
5136
|
agent: this.agent,
|
|
5088
5137
|
})
|
|
5089
5138
|
}))
|
|
5090
5139
|
this.app.get("/d/*", ex(async (req, res) => {
|
|
5091
|
-
console.log("> 1")
|
|
5092
5140
|
let filepath = Util.u2p(req.params[0])
|
|
5093
|
-
let
|
|
5094
|
-
|
|
5141
|
+
let terminal = await this.terminals(filepath)
|
|
5142
|
+
let plugin = await this.getPluginGlobal(req, this.kernel.plugin.config, terminal, filepath)
|
|
5095
5143
|
let html = ""
|
|
5096
5144
|
let plugin_menu
|
|
5097
5145
|
try {
|
|
@@ -5101,105 +5149,74 @@ class Server {
|
|
|
5101
5149
|
plugin_menu = []
|
|
5102
5150
|
}
|
|
5103
5151
|
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
5104
|
-
console.log("> 3")
|
|
5105
5152
|
let retry = false
|
|
5106
5153
|
// if plugin_menu is empty, try again in 1 sec
|
|
5107
5154
|
if (plugin_menu.length === 0) {
|
|
5108
5155
|
retry = true
|
|
5109
5156
|
}
|
|
5110
|
-
let venvs = await Util.find_venv(filepath)
|
|
5111
|
-
console.log("> 4")
|
|
5112
|
-
let terminal
|
|
5113
|
-
if (venvs.length > 0) {
|
|
5114
|
-
let terminals = []
|
|
5115
|
-
try {
|
|
5116
|
-
for(let i=0; i<venvs.length; i++) {
|
|
5117
|
-
let venv = venvs[i]
|
|
5118
|
-
let parsed = path.parse(venv)
|
|
5119
|
-
terminals.push(this.renderShell(filepath, i, 0, {
|
|
5120
|
-
icon: "fa-brands fa-python",
|
|
5121
|
-
title: "Python virtual environment",
|
|
5122
|
-
subtitle: this.kernel.path("api", parsed.name),
|
|
5123
|
-
type: "Start",
|
|
5124
|
-
shell: {
|
|
5125
|
-
venv: venv,
|
|
5126
|
-
input: true,
|
|
5127
|
-
}
|
|
5128
|
-
}))
|
|
5129
|
-
}
|
|
5130
|
-
} catch (e) {
|
|
5131
|
-
console.log(e)
|
|
5132
|
-
}
|
|
5133
|
-
terminal = {
|
|
5134
|
-
icon: "fa-solid fa-terminal",
|
|
5135
|
-
title: "Open web terminal",
|
|
5136
|
-
subtitle: "Open the terminal in the browser",
|
|
5137
|
-
menu: terminals
|
|
5138
|
-
}
|
|
5139
|
-
} else {
|
|
5140
|
-
terminal = {
|
|
5141
|
-
icon: "fa-solid fa-terminal",
|
|
5142
|
-
title: "Open web terminal",
|
|
5143
|
-
subtitle: "Work with the terminal directly in the browser",
|
|
5144
|
-
menu: [this.renderShell(filepath, 0, 0, {
|
|
5145
|
-
icon: "fa-solid fa-terminal",
|
|
5146
|
-
title: "Terminal",
|
|
5147
|
-
subtitle: filepath,
|
|
5148
|
-
type: "Start",
|
|
5149
|
-
shell: {
|
|
5150
|
-
input: true
|
|
5151
|
-
}
|
|
5152
|
-
})]
|
|
5153
|
-
}
|
|
5154
|
-
}
|
|
5155
|
-
console.log("> 5")
|
|
5156
5157
|
|
|
5157
5158
|
let exec_menus = []
|
|
5158
5159
|
let shell_menus = []
|
|
5160
|
+
let href_menus = []
|
|
5159
5161
|
if (plugin_menu.length > 0) {
|
|
5160
5162
|
for(let item of plugin_menu) {
|
|
5161
5163
|
// if shell.run method exists
|
|
5162
5164
|
// if exec method exists
|
|
5163
5165
|
let mode
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
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
|
+
}
|
|
5168
5176
|
}
|
|
5169
|
-
if (
|
|
5170
|
-
|
|
5171
|
-
|
|
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)
|
|
5172
5183
|
}
|
|
5173
|
-
}
|
|
5174
|
-
|
|
5175
|
-
item.type = "Open"
|
|
5176
|
-
exec_menus.push(item)
|
|
5177
|
-
} else if (mode === "shell") {
|
|
5178
|
-
item.type = "Start"
|
|
5179
|
-
shell_menus.push(item)
|
|
5184
|
+
} else {
|
|
5185
|
+
href_menus.push(item)
|
|
5180
5186
|
}
|
|
5181
5187
|
}
|
|
5182
5188
|
exec_menus.sort((a, b) => { return a > b })
|
|
5183
5189
|
shell_menus.sort((a, b) => { return a > b })
|
|
5190
|
+
href_menus.sort((a, b) => { return a > b })
|
|
5184
5191
|
}
|
|
5185
|
-
|
|
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
|
|
5186
5197
|
let dynamic = [
|
|
5187
5198
|
{
|
|
5188
5199
|
icon: "fa-solid fa-robot",
|
|
5189
|
-
title: "
|
|
5190
|
-
subtitle: "
|
|
5200
|
+
title: "AI Engineer",
|
|
5201
|
+
subtitle: "Let AI work on this app",
|
|
5191
5202
|
menu: shell_menus
|
|
5192
5203
|
},
|
|
5193
5204
|
{
|
|
5194
5205
|
icon: "fa-solid fa-arrow-up-right-from-square",
|
|
5195
|
-
title: "
|
|
5206
|
+
title: "External apps",
|
|
5196
5207
|
subtitle: "Open this project in 3rd party apps",
|
|
5197
5208
|
menu: exec_menus
|
|
5198
5209
|
},
|
|
5199
|
-
terminal
|
|
5210
|
+
terminal
|
|
5200
5211
|
]
|
|
5201
|
-
|
|
5212
|
+
let spec = ""
|
|
5213
|
+
try {
|
|
5214
|
+
spec = await fs.promises.readFile(path.resolve(filepath, "SPEC.md"), "utf8")
|
|
5215
|
+
} catch (e) {
|
|
5216
|
+
}
|
|
5202
5217
|
res.render("d", {
|
|
5218
|
+
filepath,
|
|
5219
|
+
spec,
|
|
5203
5220
|
retry,
|
|
5204
5221
|
current_urls,
|
|
5205
5222
|
docs: this.docs,
|
|
@@ -5248,20 +5265,6 @@ class Server {
|
|
|
5248
5265
|
}
|
|
5249
5266
|
res.render("mini", result)
|
|
5250
5267
|
}))
|
|
5251
|
-
this.app.get("/asset/*", ex((req, res) => {
|
|
5252
|
-
let pathComponents = req.params[0].split("/")
|
|
5253
|
-
let filepath = this.kernel.path(...pathComponents)
|
|
5254
|
-
try {
|
|
5255
|
-
if (req.query.frame) {
|
|
5256
|
-
let m = mime.lookup(filepath)
|
|
5257
|
-
res.type("text/plain")
|
|
5258
|
-
}
|
|
5259
|
-
//res.setHeader('Content-Disposition', 'inline');
|
|
5260
|
-
res.sendFile(filepath)
|
|
5261
|
-
} catch (e) {
|
|
5262
|
-
res.status(404).send(e.message);
|
|
5263
|
-
}
|
|
5264
|
-
}))
|
|
5265
5268
|
this.app.get("/raw/*", ex((req, res) => {
|
|
5266
5269
|
let pathComponents = req.params[0].split("/")
|
|
5267
5270
|
let filepath = this.kernel.path("api", ...pathComponents)
|
|
@@ -5329,7 +5332,9 @@ class Server {
|
|
|
5329
5332
|
}
|
|
5330
5333
|
}))
|
|
5331
5334
|
this.app.get("/pinokio/dynamic_global/*", ex(async (req, res) => {
|
|
5332
|
-
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)
|
|
5333
5338
|
if (plugin) {
|
|
5334
5339
|
let html = ""
|
|
5335
5340
|
if (plugin && plugin.menu) {
|
|
@@ -5352,7 +5357,8 @@ class Server {
|
|
|
5352
5357
|
}))
|
|
5353
5358
|
this.app.get("/pinokio/dynamic/:name", ex(async (req, res) => {
|
|
5354
5359
|
// await this.kernel.plugin.init()
|
|
5355
|
-
|
|
5360
|
+
|
|
5361
|
+
let plugin = await this.getPlugin(req, this.kernel.plugin.config, req.params.name)
|
|
5356
5362
|
let html = ""
|
|
5357
5363
|
let plugin_menu
|
|
5358
5364
|
if (plugin) {
|
|
@@ -5404,6 +5410,15 @@ class Server {
|
|
|
5404
5410
|
})
|
|
5405
5411
|
res.send(html)
|
|
5406
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
|
+
}))
|
|
5407
5422
|
this.app.get("/pinokio/repos/:name", ex(async (req, res) => {
|
|
5408
5423
|
// await this.kernel.plugin.init()
|
|
5409
5424
|
let c = this.kernel.path("api", req.params.name)
|
|
@@ -5425,9 +5440,10 @@ class Server {
|
|
|
5425
5440
|
}))
|
|
5426
5441
|
this.app.get("/pinokio/sidebar/:name", ex(async (req, res) => {
|
|
5427
5442
|
let name = req.params.name
|
|
5428
|
-
let
|
|
5443
|
+
let launcher = await this.kernel.api.launcher(name)
|
|
5429
5444
|
let rawpath = "/api/" + name
|
|
5430
|
-
let config
|
|
5445
|
+
let config = launcher.script
|
|
5446
|
+
req.launcher_root = launcher.launcher_root
|
|
5431
5447
|
if (config && config.menu) {
|
|
5432
5448
|
if (typeof config.menu === "function") {
|
|
5433
5449
|
if (config.menu.constructor.name === "AsyncFunction") {
|
|
@@ -5505,81 +5521,72 @@ class Server {
|
|
|
5505
5521
|
// await this.kernel.refresh()
|
|
5506
5522
|
// res.json({ success: true })
|
|
5507
5523
|
// }))
|
|
5508
|
-
|
|
5509
|
-
|
|
5524
|
+
|
|
5525
|
+
|
|
5526
|
+
this.app.get("/info/system", ex(async (req,res) => {
|
|
5510
5527
|
let current_peer_info = await this.kernel.peer.current_host()
|
|
5511
5528
|
res.json(current_peer_info)
|
|
5512
|
-
|
|
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
|
+
}
|
|
5513
5575
|
res.json({
|
|
5514
|
-
|
|
5515
|
-
arch: this.kernel.arch,
|
|
5516
|
-
platform: this.kernel.platform,
|
|
5517
|
-
name: this.kernel.peer.name,
|
|
5518
|
-
host: this.kernel.peer.host,
|
|
5519
|
-
port_mapping: this.kernel.router.port_mapping,
|
|
5520
|
-
//router: this.kernel.router.info(),
|
|
5521
|
-
proc: this.kernel.processes.info,
|
|
5522
|
-
router: this.kernel.router.published(),
|
|
5523
|
-
memory: this.kernel.memory
|
|
5576
|
+
repos: repos_with_remote
|
|
5524
5577
|
})
|
|
5525
|
-
|
|
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)
|
|
5526
5584
|
}))
|
|
5527
5585
|
this.app.get("/pinokio/memory", ex((req, res) => {
|
|
5528
5586
|
let filepath = req.query.filepath
|
|
5529
5587
|
let mem = this.getMemory(filepath)
|
|
5530
5588
|
res.json(mem)
|
|
5531
5589
|
}))
|
|
5532
|
-
// this.app.post("/pinokio/tunnel", async (req, res) => {
|
|
5533
|
-
// let port
|
|
5534
|
-
// let local_host
|
|
5535
|
-
// try {
|
|
5536
|
-
// let u = new URL(req.body.url)
|
|
5537
|
-
// port = u.port
|
|
5538
|
-
// local_host = u.hostname
|
|
5539
|
-
// console.log({ local_host, port })
|
|
5540
|
-
// if (req.body.action === "start") {
|
|
5541
|
-
// // Output ngrok url to console
|
|
5542
|
-
//
|
|
5543
|
-
// let url = req.body.url
|
|
5544
|
-
// console.log("tunnel", req.body)
|
|
5545
|
-
// const tunnel = await ngrok.forward({ addr: port, authtoken: req.body.token });
|
|
5546
|
-
// console.log("created", tunnel)
|
|
5547
|
-
// console.log("url", tunnel.url())
|
|
5548
|
-
// this.tunnels[url] = tunnel
|
|
5549
|
-
// res.json({ url: tunnel.url() })
|
|
5550
|
-
//
|
|
5551
|
-
//
|
|
5552
|
-
// // localtunnel
|
|
5553
|
-
// //const tunnel = await localtunnel({ local_host, port: parseInt(port) });
|
|
5554
|
-
// //const tunnel = await localtunnel({ local_host: "127.0.0.1", port: parseInt(port) });
|
|
5555
|
-
//
|
|
5556
|
-
// //const tunnel = await localtunnel({ port: parseInt(port) });
|
|
5557
|
-
// //this.tunnels[url] = tunnel
|
|
5558
|
-
// //tunnel.on('error', (err) => {
|
|
5559
|
-
// // console.log(err)
|
|
5560
|
-
// // delete this.tunnels[url]
|
|
5561
|
-
// //})
|
|
5562
|
-
// //tunnel.on('close', () => {
|
|
5563
|
-
// // // tunnels are closed
|
|
5564
|
-
// // console.log("tunnel closed", { url, tunnel_url: tunnel.url })
|
|
5565
|
-
// // delete this.tunnels[url]
|
|
5566
|
-
// //});
|
|
5567
|
-
// //res.json({ url: tunnel.url })
|
|
5568
|
-
// } else if (req.body.action === "stop") {
|
|
5569
|
-
// let url = req.body.url
|
|
5570
|
-
// await this.tunnels[url].close()
|
|
5571
|
-
// delete this.tunnels[url]
|
|
5572
|
-
// res.json({ url })
|
|
5573
|
-
//// let url = req.body.url
|
|
5574
|
-
//// console.log({ tunnels: this.tunnels, url })
|
|
5575
|
-
//// this.tunnels[url].close()
|
|
5576
|
-
//// res.json({ url })
|
|
5577
|
-
// }
|
|
5578
|
-
// } catch (e) {
|
|
5579
|
-
// console.log("ERROR", e)
|
|
5580
|
-
// res.json({ error: e.message })
|
|
5581
|
-
// }
|
|
5582
|
-
// })
|
|
5583
5590
|
this.app.post("/pinokio/tabs", ex(async (req, res) => {
|
|
5584
5591
|
this.tabs[req.body.name] = req.body.tabs
|
|
5585
5592
|
res.json({ success: true })
|
|
@@ -5605,6 +5612,41 @@ class Server {
|
|
|
5605
5612
|
this.app.get("/pinokio/browser/:name", ex(async (req, res) => {
|
|
5606
5613
|
await this.chrome(req, res, "run")
|
|
5607
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
|
+
}))
|
|
5608
5650
|
this.app.get("/p/:name/dev", ex(async (req, res) => {
|
|
5609
5651
|
await this.chrome(req, res, "browse")
|
|
5610
5652
|
}))
|
|
@@ -5628,7 +5670,7 @@ class Server {
|
|
|
5628
5670
|
res.json({ success: true })
|
|
5629
5671
|
} else if (req.body.type === 'env') {
|
|
5630
5672
|
let envpath = this.kernel.path("ENVIRONMENT")
|
|
5631
|
-
let str = await Environment.ENV("system", this.kernel.homedir)
|
|
5673
|
+
let str = await Environment.ENV("system", this.kernel.homedir, this.kernel)
|
|
5632
5674
|
await fs.promises.writeFile(path.resolve(this.kernel.homedir, "ENVIRONMENT"), str)
|
|
5633
5675
|
res.json({ success: true })
|
|
5634
5676
|
} else if (req.body.type === 'browser-cache') {
|
|
@@ -5651,35 +5693,8 @@ class Server {
|
|
|
5651
5693
|
res.json({ error: err.stack })
|
|
5652
5694
|
}
|
|
5653
5695
|
}))
|
|
5654
|
-
// this.app.get("/pinokio/shell_state", (req, res) => {
|
|
5655
|
-
// let states = this.kernel.shell.shells.map((s) => {
|
|
5656
|
-
// return {
|
|
5657
|
-
// state: s.state,
|
|
5658
|
-
// id: s.id,
|
|
5659
|
-
// group: s.group,
|
|
5660
|
-
// env: s.env,
|
|
5661
|
-
// path: s.path,
|
|
5662
|
-
// cmd: s.cmd,
|
|
5663
|
-
// done: s.done,
|
|
5664
|
-
// ready: s.ready,
|
|
5665
|
-
// }
|
|
5666
|
-
// })
|
|
5667
|
-
//
|
|
5668
|
-
// let info = {
|
|
5669
|
-
// platform: this.kernel.platform,
|
|
5670
|
-
// arch: this.kernel.arch,
|
|
5671
|
-
// running: this.kernel.api.running,
|
|
5672
|
-
// home: this.kernel.homedir,
|
|
5673
|
-
// vars: this.kernel.vars,
|
|
5674
|
-
// memory: this.kernel.memory,
|
|
5675
|
-
// procs: this.kernel.procs,
|
|
5676
|
-
// gpu: this.kernel.gpu,
|
|
5677
|
-
// gpus: this.kernel.gpus
|
|
5678
|
-
// }
|
|
5679
|
-
// })
|
|
5680
5696
|
this.app.get("/pinokio/logs.zip", ex((req, res) => {
|
|
5681
5697
|
let zipPath = this.kernel.path("logs.zip")
|
|
5682
|
-
console.log("sendFile", zipPath)
|
|
5683
5698
|
res.download(zipPath)
|
|
5684
5699
|
}))
|
|
5685
5700
|
this.app.post("/pinokio/log", ex(async (req, res) => {
|
|
@@ -5812,7 +5827,7 @@ class Server {
|
|
|
5812
5827
|
await fs.promises.cp(old_path, new_path, { recursive: true })
|
|
5813
5828
|
|
|
5814
5829
|
// 2. edit meta in the new_path
|
|
5815
|
-
await this.updateMeta(formData, formData.new_path)
|
|
5830
|
+
await this.kernel.api.updateMeta(formData, formData.new_path)
|
|
5816
5831
|
|
|
5817
5832
|
}
|
|
5818
5833
|
} else if (formData.move) {
|
|
@@ -5825,11 +5840,11 @@ class Server {
|
|
|
5825
5840
|
}
|
|
5826
5841
|
|
|
5827
5842
|
// 2. edit meta in the new_path
|
|
5828
|
-
await this.updateMeta(formData, formData.new_path)
|
|
5843
|
+
await this.kernel.api.updateMeta(formData, formData.new_path)
|
|
5829
5844
|
} else {
|
|
5830
5845
|
// 1. edit only
|
|
5831
5846
|
if (formData.old_path === formData.new_path) {
|
|
5832
|
-
await this.updateMeta(formData, formData.new_path)
|
|
5847
|
+
await this.kernel.api.updateMeta(formData, formData.new_path)
|
|
5833
5848
|
}
|
|
5834
5849
|
}
|
|
5835
5850
|
} else {
|
|
@@ -5893,6 +5908,56 @@ class Server {
|
|
|
5893
5908
|
res.status(404).send("Missing attribute: path")
|
|
5894
5909
|
}
|
|
5895
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
|
+
}))
|
|
5896
5961
|
this.app.post("/pinokio/fs", this.upload.any(), ex(async (req, res) => {
|
|
5897
5962
|
/*
|
|
5898
5963
|
Packet format:
|
|
@@ -6084,6 +6149,14 @@ class Server {
|
|
|
6084
6149
|
res.json({ success: true })
|
|
6085
6150
|
}
|
|
6086
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
|
+
|
|
6087
6160
|
this.app.get("/check", ex((req, res) => {
|
|
6088
6161
|
res.json({ success: true })
|
|
6089
6162
|
}))
|