pinokiod 3.24.0 → 3.26.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/exec/index.js +67 -0
- package/kernel/api/index.js +1 -0
- package/kernel/bin/caddy.js +1 -1
- package/kernel/index.js +1 -6
- package/kernel/peer.js +23 -5
- package/kernel/plugin.js +24 -41
- package/kernel/prototype.js +25 -0
- package/kernel/router/index.js +13 -0
- package/kernel/router/localhost_home_router.js +11 -0
- package/kernel/shell.js +13 -10
- package/kernel/shells.js +52 -47
- package/kernel/util.js +0 -1
- package/package.json +2 -1
- package/server/index.js +307 -220
- package/server/public/modalinput.js +3 -1
- package/server/public/style.css +1 -1
- package/server/socket.js +0 -19
- package/server/views/500.ejs +7 -6
- package/server/views/app.ejs +76 -11
- package/server/views/d.ejs +123 -12
- package/server/views/index.ejs +69 -1
- package/server/views/init/index.ejs +299 -92
- package/server/views/install.ejs +7 -1
- package/server/views/net.ejs +94 -166
- package/server/views/network.ejs +3 -2
- package/server/views/partials/dynamic.ejs +1 -1
- package/server/views/start.ejs +268 -0
package/server/index.js
CHANGED
|
@@ -188,16 +188,9 @@ class Server {
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
} else if (key === "shell") {
|
|
191
|
-
console.log("CHECK SHELL", { name, indexPath, key })
|
|
192
|
-
console.log("obj", obj)
|
|
193
|
-
console.log("running", this.kernel.api.running)
|
|
194
191
|
let unix_path = Util.p2u(this.kernel.path("api", name))
|
|
195
|
-
console.log({ unix_path })
|
|
196
192
|
let shell_id = this.get_shell_id(unix_path, indexPath, obj[key])
|
|
197
|
-
|
|
198
|
-
console.log("SHELL ID 2", shell_id)
|
|
199
193
|
let decoded_shell_id = decodeURIComponent(shell_id)
|
|
200
|
-
console.log({ shell_id, decoded_shell_id })
|
|
201
194
|
if (this.kernel.api.running["shell/" + decoded_shell_id]) {
|
|
202
195
|
obj.running = true
|
|
203
196
|
obj.display = "indent"
|
|
@@ -391,6 +384,20 @@ class Server {
|
|
|
391
384
|
}
|
|
392
385
|
// console.timeEnd("1 chrome " + d)
|
|
393
386
|
|
|
387
|
+
|
|
388
|
+
console.log("req.query", req.query)
|
|
389
|
+
if (req.query.autolaunch === "1") {
|
|
390
|
+
let fullpath = path.resolve(this.kernel.homedir, "ENVIRONMENT")
|
|
391
|
+
await Util.update_env(fullpath, {
|
|
392
|
+
PINOKIO_ONDEMAND_AUTOLAUNCH: "1"
|
|
393
|
+
})
|
|
394
|
+
} else if (req.query.autolaunch === "0") {
|
|
395
|
+
let fullpath = path.resolve(this.kernel.homedir, "ENVIRONMENT")
|
|
396
|
+
await Util.update_env(fullpath, {
|
|
397
|
+
PINOKIO_ONDEMAND_AUTOLAUNCH: "0"
|
|
398
|
+
})
|
|
399
|
+
}
|
|
400
|
+
|
|
394
401
|
let name = req.params.name
|
|
395
402
|
let config = await this.kernel.api.meta(name)
|
|
396
403
|
|
|
@@ -431,34 +438,8 @@ class Server {
|
|
|
431
438
|
// }
|
|
432
439
|
|
|
433
440
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
return
|
|
437
|
-
|
|
438
|
-
// // none of the pinokio.js, pinokio.json, pinokio_meta.json exists => need to initialize
|
|
439
|
-
// // if there is no menu, display all files
|
|
440
|
-
// let p = this.kernel.path("api", name)
|
|
441
|
-
// let files = await fs.promises.readdir(p, { withFileTypes: true })
|
|
442
|
-
// files = files.filter((file) => {
|
|
443
|
-
// return file.name.endsWith(".json") || file.name.endsWith(".js")
|
|
444
|
-
// }).filter((file) => {
|
|
445
|
-
// return file.name !== "pinokio.js" && file.name !== "pinokio.json" && file.name !== "pinokio_meta.json"
|
|
446
|
-
// })
|
|
447
|
-
// config = {
|
|
448
|
-
// init_required: true,
|
|
449
|
-
// icon: config.icon,
|
|
450
|
-
// title: name,
|
|
451
|
-
// menu: files.map((file) => {
|
|
452
|
-
// return {
|
|
453
|
-
// text: file.name,
|
|
454
|
-
// href: file.name
|
|
455
|
-
// }
|
|
456
|
-
// })
|
|
457
|
-
// }
|
|
458
|
-
// let uri = this.kernel.path("api")
|
|
459
|
-
// await this.renderMenu(uri, name, config, [])
|
|
460
|
-
} else {
|
|
461
|
-
let menu = config.menu || []
|
|
441
|
+
let menu = config.menu || []
|
|
442
|
+
try {
|
|
462
443
|
if (typeof config.menu === "function") {
|
|
463
444
|
if (config.menu.constructor.name === "AsyncFunction") {
|
|
464
445
|
config.menu = await config.menu(this.kernel, this.kernel.info)
|
|
@@ -466,12 +447,20 @@ class Server {
|
|
|
466
447
|
config.menu = config.menu(this.kernel, this.kernel.info)
|
|
467
448
|
}
|
|
468
449
|
}
|
|
450
|
+
} catch (e) {
|
|
451
|
+
err = e.stack
|
|
452
|
+
config.menu = []
|
|
453
|
+
}
|
|
469
454
|
|
|
470
|
-
|
|
455
|
+
let uri = this.kernel.path("api")
|
|
456
|
+
try {
|
|
471
457
|
await this.renderMenu(uri, name, config, [])
|
|
472
|
-
|
|
458
|
+
} catch(e) {
|
|
459
|
+
config.menu = []
|
|
460
|
+
err = e.stack
|
|
473
461
|
}
|
|
474
462
|
|
|
463
|
+
|
|
475
464
|
let platform = os.platform()
|
|
476
465
|
|
|
477
466
|
// if (config.icon) {
|
|
@@ -585,18 +574,10 @@ class Server {
|
|
|
585
574
|
|
|
586
575
|
let plugin_menu = null
|
|
587
576
|
let plugin = await this.getPlugin(name)
|
|
588
|
-
console.log(">>> Plugin", plugin)
|
|
589
577
|
if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
590
|
-
console.log(">>> 2")
|
|
591
578
|
plugin = structuredClone(plugin)
|
|
592
579
|
plugin_menu = this.running_dynamic(name, plugin.menu)
|
|
593
|
-
console.log("GOT THE PLUGIN MENU")
|
|
594
|
-
|
|
595
|
-
// plugin_menu = plugin.menu
|
|
596
580
|
}
|
|
597
|
-
console.log("PLUGIN_MENU", plugin_menu)
|
|
598
|
-
|
|
599
|
-
|
|
600
581
|
let menu_hidden = false
|
|
601
582
|
if (this.menu_hidden[name] && this.menu_hidden[name][type]) {
|
|
602
583
|
menu_hidden = true
|
|
@@ -686,7 +667,6 @@ class Server {
|
|
|
686
667
|
is_subpath(parent, child) {
|
|
687
668
|
const relative = path.relative(parent, child);
|
|
688
669
|
let check = !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);
|
|
689
|
-
console.log({ relative, parent, child, check })
|
|
690
670
|
return check
|
|
691
671
|
}
|
|
692
672
|
async render(req, res, pathComponents, meta) {
|
|
@@ -1375,7 +1355,6 @@ class Server {
|
|
|
1375
1355
|
}
|
|
1376
1356
|
// check if there is a running process with this folder name
|
|
1377
1357
|
let runningApps = new Set()
|
|
1378
|
-
console.log("RUNNING", this.kernel.api.running)
|
|
1379
1358
|
for(let key in this.kernel.api.running) {
|
|
1380
1359
|
//let p = this.kernel.path("api", items[i].name) + path.sep
|
|
1381
1360
|
let p = this.kernel.path("api", items[i].name)
|
|
@@ -1396,23 +1375,17 @@ class Server {
|
|
|
1396
1375
|
} else {
|
|
1397
1376
|
// shell sessions
|
|
1398
1377
|
if (key.startsWith("shell/")) {
|
|
1399
|
-
// if (!path.isAbsolute(key)) {
|
|
1400
1378
|
let unix_path = key.slice(6)
|
|
1401
1379
|
let native_path = Util.u2p(unix_path)
|
|
1402
1380
|
let chunks = native_path.split("_")
|
|
1403
1381
|
if (chunks.length > 1) {
|
|
1404
1382
|
let folder = chunks[0]
|
|
1405
|
-
console.log({ chunks, folder, item: items[i] })
|
|
1406
1383
|
/// if the folder name matches, it's running
|
|
1407
1384
|
let item_path = this.kernel.path("api", items[i].name)
|
|
1408
|
-
console.log({ item_path, folder })
|
|
1409
1385
|
if (item_path === folder) {
|
|
1410
|
-
console.log("is_running = true")
|
|
1411
|
-
// if (folder === items[i].name) {
|
|
1412
1386
|
is_running = true
|
|
1413
1387
|
}
|
|
1414
1388
|
}
|
|
1415
|
-
|
|
1416
1389
|
}
|
|
1417
1390
|
}
|
|
1418
1391
|
}
|
|
@@ -1423,7 +1396,6 @@ class Server {
|
|
|
1423
1396
|
// => check inlcludes and endsWith
|
|
1424
1397
|
|
|
1425
1398
|
//if (key.includes(p) && key.endsWith(p)) {
|
|
1426
|
-
console.log("is_running", is_running)
|
|
1427
1399
|
if (is_running) {
|
|
1428
1400
|
// add to running
|
|
1429
1401
|
running.push(items[i])
|
|
@@ -1453,10 +1425,8 @@ class Server {
|
|
|
1453
1425
|
} else {
|
|
1454
1426
|
let shell = this.kernel.shell.find({
|
|
1455
1427
|
filter: (shell) => {
|
|
1456
|
-
//return shell.id.startsWith(items[i].name + "_")
|
|
1457
1428
|
let item_path = this.kernel.path("api", items[i].name)
|
|
1458
1429
|
let unix_item_path = Util.p2u(item_path)
|
|
1459
|
-
console.log("startsWith", { item_path, unix_item_path, id: shell.id })
|
|
1460
1430
|
return shell.id.startsWith("shell/" + unix_item_path + "_")
|
|
1461
1431
|
}
|
|
1462
1432
|
})
|
|
@@ -1747,6 +1717,86 @@ class Server {
|
|
|
1747
1717
|
}
|
|
1748
1718
|
return config
|
|
1749
1719
|
}
|
|
1720
|
+
renderShell(cwd, indexPath, subIndexPath, menuitem) {
|
|
1721
|
+
if (menuitem.shell) {
|
|
1722
|
+
/*
|
|
1723
|
+
shell :- {
|
|
1724
|
+
id (optional),
|
|
1725
|
+
path (required), // api, bin, quick, network, api/
|
|
1726
|
+
message (optional), // if not specified, start an empty shell
|
|
1727
|
+
venv,
|
|
1728
|
+
input, // input mode if true
|
|
1729
|
+
callback, // callback url after shutting down
|
|
1730
|
+
kill, // when to kill (regular expression)
|
|
1731
|
+
}
|
|
1732
|
+
*/
|
|
1733
|
+
|
|
1734
|
+
let rendered = this.kernel.template.render(menuitem.shell, {})
|
|
1735
|
+
let params = new URLSearchParams()
|
|
1736
|
+
// if (rendered.id) {
|
|
1737
|
+
// params.set("id", encodeURIComponent(rendered.id))
|
|
1738
|
+
// } else {
|
|
1739
|
+
// let shell_id = "sh_" + name + "_" + i
|
|
1740
|
+
// params.set("id", encodeURIComponent(shell_id))
|
|
1741
|
+
// }
|
|
1742
|
+
if (rendered.path) {
|
|
1743
|
+
params.set("path", encodeURIComponent(this.kernel.api.filePath(rendered.path, cwd)))
|
|
1744
|
+
} else {
|
|
1745
|
+
params.set("path", encodeURIComponent(cwd))
|
|
1746
|
+
}
|
|
1747
|
+
if (rendered.message) params.set("message", encodeURIComponent(rendered.message))
|
|
1748
|
+
if (rendered.venv) params.set("venv", encodeURIComponent(rendered.venv))
|
|
1749
|
+
if (rendered.input) params.set("input", true)
|
|
1750
|
+
if (rendered.callback) params.set("callback", encodeURIComponent(rendered.callback))
|
|
1751
|
+
if (rendered.callback_target) params.set("callback_target", rendered_callback_target)
|
|
1752
|
+
if (rendered.kill) params.set("kill", encodeURIComponent(rendered.kill))
|
|
1753
|
+
if (rendered.done) params.set("done", encodeURIComponent(rendered.done))
|
|
1754
|
+
if (rendered.env) {
|
|
1755
|
+
for(let key in rendered.env) {
|
|
1756
|
+
let env_key = "env." + key
|
|
1757
|
+
params.set(env_key, rendered.env[key])
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
if (rendered.conda) {
|
|
1761
|
+
for(let key in rendered.conda) {
|
|
1762
|
+
let conda_key = "conda." + key
|
|
1763
|
+
params.set(conda_key, rendered.conda[key])
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
// deterministic shell id generation
|
|
1768
|
+
// `${api_path}_${i}_${hash}`
|
|
1769
|
+
let currentIndexPath
|
|
1770
|
+
if (indexPath) {
|
|
1771
|
+
currentIndexPath = indexPath + "." + subIndexPath
|
|
1772
|
+
} else {
|
|
1773
|
+
currentIndexPath = "" + subIndexPath
|
|
1774
|
+
}
|
|
1775
|
+
let unix_path = Util.p2u(cwd)
|
|
1776
|
+
let shell_id = this.get_shell_id(unix_path, currentIndexPath, rendered)
|
|
1777
|
+
|
|
1778
|
+
// let hash = crypto.createHash('md5').update(JSON.stringify(rendered)).digest('hex')
|
|
1779
|
+
// let shell_id
|
|
1780
|
+
// if (rendered.id) {
|
|
1781
|
+
// shell_id = encodeURIComponent(`${name}_${rendered.id}`)
|
|
1782
|
+
// } else {
|
|
1783
|
+
// shell_id = encodeURIComponent(`${name}_${i}_${hash}`)
|
|
1784
|
+
// }
|
|
1785
|
+
menuitem.href = "/shell/" + shell_id + "?" + params.toString()
|
|
1786
|
+
let decoded_shell_id = decodeURIComponent(shell_id)
|
|
1787
|
+
let shell = this.kernel.shell.get(decoded_shell_id)
|
|
1788
|
+
menuitem.shell_id = "shell/" + decoded_shell_id
|
|
1789
|
+
if (shell) {
|
|
1790
|
+
menuitem.running = true
|
|
1791
|
+
} else {
|
|
1792
|
+
let shell = this.kernel.shell.get(decoded_shell_id)
|
|
1793
|
+
if (shell) {
|
|
1794
|
+
menuitem.running = true
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
}
|
|
1798
|
+
return menuitem
|
|
1799
|
+
}
|
|
1750
1800
|
|
|
1751
1801
|
async renderMenu(uri, name, config, pathComponents, indexPath) {
|
|
1752
1802
|
if (config.menu) {
|
|
@@ -1830,84 +1880,8 @@ class Server {
|
|
|
1830
1880
|
|
|
1831
1881
|
|
|
1832
1882
|
if (menuitem.shell) {
|
|
1833
|
-
/*
|
|
1834
|
-
shell :- {
|
|
1835
|
-
id (optional),
|
|
1836
|
-
path (required), // api, bin, quick, network, api/
|
|
1837
|
-
message (optional), // if not specified, start an empty shell
|
|
1838
|
-
venv,
|
|
1839
|
-
input, // input mode if true
|
|
1840
|
-
callback, // callback url after shutting down
|
|
1841
|
-
kill, // when to kill (regular expression)
|
|
1842
|
-
}
|
|
1843
|
-
*/
|
|
1844
|
-
|
|
1845
|
-
let rendered = this.kernel.template.render(menuitem.shell, {})
|
|
1846
|
-
let params = new URLSearchParams()
|
|
1847
|
-
// if (rendered.id) {
|
|
1848
|
-
// params.set("id", encodeURIComponent(rendered.id))
|
|
1849
|
-
// } else {
|
|
1850
|
-
// let shell_id = "sh_" + name + "_" + i
|
|
1851
|
-
// params.set("id", encodeURIComponent(shell_id))
|
|
1852
|
-
// }
|
|
1853
1883
|
let basePath = this.kernel.path("api", name)
|
|
1854
|
-
|
|
1855
|
-
params.set("path", encodeURIComponent(this.kernel.api.filePath(rendered.path, basePath)))
|
|
1856
|
-
} else {
|
|
1857
|
-
params.set("path", encodeURIComponent(basePath))
|
|
1858
|
-
}
|
|
1859
|
-
if (rendered.message) params.set("message", encodeURIComponent(rendered.message))
|
|
1860
|
-
if (rendered.venv) params.set("venv", encodeURIComponent(rendered.venv))
|
|
1861
|
-
if (rendered.input) params.set("input", true)
|
|
1862
|
-
if (rendered.callback) params.set("callback", encodeURIComponent(rendered.callback))
|
|
1863
|
-
if (rendered.callback_target) params.set("callback_target", rendered_callback_target)
|
|
1864
|
-
if (rendered.kill) params.set("kill", encodeURIComponent(rendered.kill))
|
|
1865
|
-
if (rendered.done) params.set("done", encodeURIComponent(rendered.done))
|
|
1866
|
-
if (rendered.env) {
|
|
1867
|
-
for(let key in rendered.env) {
|
|
1868
|
-
let env_key = "env." + key
|
|
1869
|
-
params.set(env_key, rendered.env[key])
|
|
1870
|
-
}
|
|
1871
|
-
}
|
|
1872
|
-
if (rendered.conda) {
|
|
1873
|
-
for(let key in rendered.conda) {
|
|
1874
|
-
let conda_key = "conda." + key
|
|
1875
|
-
params.set(conda_key, rendered.conda[key])
|
|
1876
|
-
}
|
|
1877
|
-
}
|
|
1878
|
-
|
|
1879
|
-
// deterministic shell id generation
|
|
1880
|
-
// `${api_path}_${i}_${hash}`
|
|
1881
|
-
let currentIndexPath
|
|
1882
|
-
if (indexPath) {
|
|
1883
|
-
currentIndexPath = indexPath + "." + i
|
|
1884
|
-
} else {
|
|
1885
|
-
currentIndexPath = "" + i
|
|
1886
|
-
}
|
|
1887
|
-
let unix_path = Util.p2u(this.kernel.path("api", name))
|
|
1888
|
-
let shell_id = this.get_shell_id(unix_path, currentIndexPath, rendered)
|
|
1889
|
-
|
|
1890
|
-
console.log("SHELL ID 1", shell_id)
|
|
1891
|
-
|
|
1892
|
-
// let hash = crypto.createHash('md5').update(JSON.stringify(rendered)).digest('hex')
|
|
1893
|
-
// let shell_id
|
|
1894
|
-
// if (rendered.id) {
|
|
1895
|
-
// shell_id = encodeURIComponent(`${name}_${rendered.id}`)
|
|
1896
|
-
// } else {
|
|
1897
|
-
// shell_id = encodeURIComponent(`${name}_${i}_${hash}`)
|
|
1898
|
-
// }
|
|
1899
|
-
menuitem.href = "/shell/" + shell_id + "?" + params.toString()
|
|
1900
|
-
let decoded_shell_id = decodeURIComponent(shell_id)
|
|
1901
|
-
let shell = this.kernel.shell.get(decoded_shell_id)
|
|
1902
|
-
menuitem.shell_id = "shell/" + decoded_shell_id
|
|
1903
|
-
if (shell) {
|
|
1904
|
-
menuitem.running = true
|
|
1905
|
-
} else {
|
|
1906
|
-
let shell = this.kernel.shell.get(decoded_shell_id)
|
|
1907
|
-
if (shell) {
|
|
1908
|
-
menuitem.running = true
|
|
1909
|
-
}
|
|
1910
|
-
}
|
|
1884
|
+
this.renderShell(basePath, indexPath, i, menuitem)
|
|
1911
1885
|
}
|
|
1912
1886
|
|
|
1913
1887
|
if (menuitem.href) {
|
|
@@ -2022,9 +1996,7 @@ class Server {
|
|
|
2022
1996
|
config.menu[i].btn = menuitem.html
|
|
2023
1997
|
}
|
|
2024
1998
|
} else if (menuitem.hasOwnProperty("text")) {
|
|
2025
|
-
if (menuitem.hasOwnProperty("
|
|
2026
|
-
menuitem.html = `<i class="${menuitem.icon}"></i> ${menuitem.text}`
|
|
2027
|
-
} else if (menuitem.hasOwnProperty("image")) {
|
|
1999
|
+
if (menuitem.hasOwnProperty("image")) {
|
|
2028
2000
|
let imagePath
|
|
2029
2001
|
if (menuitem.image.startsWith("/")) {
|
|
2030
2002
|
imagePath = menuitem.image
|
|
@@ -2032,6 +2004,8 @@ class Server {
|
|
|
2032
2004
|
imagePath = `/api/${name}/${menuitem.image}?raw=true`
|
|
2033
2005
|
}
|
|
2034
2006
|
menuitem.html = `<img class='menu-item-image' src='${imagePath}' /> ${menuitem.text}`
|
|
2007
|
+
} else if (menuitem.hasOwnProperty("icon")) {
|
|
2008
|
+
menuitem.html = `<i class="${menuitem.icon}"></i> ${menuitem.text}`
|
|
2035
2009
|
} else {
|
|
2036
2010
|
menuitem.html = `${menuitem.text}`
|
|
2037
2011
|
}
|
|
@@ -2546,7 +2520,6 @@ class Server {
|
|
|
2546
2520
|
...item
|
|
2547
2521
|
}
|
|
2548
2522
|
})
|
|
2549
|
-
console.log("MENU 1", JSON.stringify(menu, null, 2))
|
|
2550
2523
|
// let menu = await this.kernel.plugin.config.menu(this.kernel, info)
|
|
2551
2524
|
let plugin = { menu }
|
|
2552
2525
|
let uri = filepath
|
|
@@ -2594,9 +2567,6 @@ class Server {
|
|
|
2594
2567
|
...item
|
|
2595
2568
|
}
|
|
2596
2569
|
})
|
|
2597
|
-
|
|
2598
|
-
console.log("MENU 2", JSON.stringify(menu, null, 2))
|
|
2599
|
-
|
|
2600
2570
|
let plugin = { menu }
|
|
2601
2571
|
let uri = this.kernel.path("api")
|
|
2602
2572
|
await this.renderMenu(uri, name, plugin, [])
|
|
@@ -2913,6 +2883,52 @@ class Server {
|
|
|
2913
2883
|
|
|
2914
2884
|
//let home = this.kernel.homedir
|
|
2915
2885
|
//let home = this.kernel.store.get("home")
|
|
2886
|
+
this.app.get("/launch", ex(async (req, res) => {
|
|
2887
|
+
// parse the url
|
|
2888
|
+
/*
|
|
2889
|
+
is it https://<name>.localhost ?
|
|
2890
|
+
- is <name> already installed?
|
|
2891
|
+
- yes: display
|
|
2892
|
+
- no: 404
|
|
2893
|
+
else: 404
|
|
2894
|
+
*/
|
|
2895
|
+
let url = req.query.url
|
|
2896
|
+
let u = new URL(url)
|
|
2897
|
+
let host = u.host
|
|
2898
|
+
if (host.endsWith(".localhost")) {
|
|
2899
|
+
let name = host.replace(/\.localhost$/, '')
|
|
2900
|
+
let env = await Environment.get(this.kernel.homedir)
|
|
2901
|
+
let autolaunch = false
|
|
2902
|
+
if (env && env.PINOKIO_ONDEMAND_AUTOLAUNCH === "1") {
|
|
2903
|
+
autolaunch = true
|
|
2904
|
+
}
|
|
2905
|
+
let api_path = this.kernel.path("api", name)
|
|
2906
|
+
let exists = await this.exists(api_path)
|
|
2907
|
+
if (exists) {
|
|
2908
|
+
let meta = await this.kernel.api.meta(name)
|
|
2909
|
+
console.log({ autolaunch })
|
|
2910
|
+
res.render("start", {
|
|
2911
|
+
autolaunch,
|
|
2912
|
+
logo: this.logo,
|
|
2913
|
+
theme: this.theme,
|
|
2914
|
+
agent: this.agent,
|
|
2915
|
+
name: meta.title,
|
|
2916
|
+
image: meta.icon,
|
|
2917
|
+
//link: autolaunch ? "/p/" + name : "/p/" + name + "?autolaunch"
|
|
2918
|
+
link: autolaunch ? "/p/" + name + "?autolaunch=1" : "/p/" + name + "?autolaunch=0"
|
|
2919
|
+
})
|
|
2920
|
+
return
|
|
2921
|
+
}
|
|
2922
|
+
}
|
|
2923
|
+
res.render("start", {
|
|
2924
|
+
logo: this.logo,
|
|
2925
|
+
theme: this.theme,
|
|
2926
|
+
agent: this.agent,
|
|
2927
|
+
name: "Does not exist",
|
|
2928
|
+
image: "/pinokio-black.png",
|
|
2929
|
+
link: null
|
|
2930
|
+
})
|
|
2931
|
+
}))
|
|
2916
2932
|
this.app.get("/", ex(async (req, res) => {
|
|
2917
2933
|
// check bin folder
|
|
2918
2934
|
// let bin_path = this.kernel.path("bin/miniconda")
|
|
@@ -3128,8 +3144,17 @@ class Server {
|
|
|
3128
3144
|
// console.log("this.kernel.proto.init")
|
|
3129
3145
|
// await this.kernel.proto.init()
|
|
3130
3146
|
let list = this.getPeerInfo()
|
|
3147
|
+
let ai = await this.kernel.proto.ai()
|
|
3148
|
+
ai.push({
|
|
3149
|
+
title: "Use your own AI recipe",
|
|
3150
|
+
description: "Enter your own markdown instruction for AI",
|
|
3151
|
+
meta: {},
|
|
3152
|
+
content: ""
|
|
3153
|
+
})
|
|
3154
|
+
console.log("ai", ai)
|
|
3131
3155
|
res.render("init/index", {
|
|
3132
3156
|
list,
|
|
3157
|
+
ai,
|
|
3133
3158
|
current_host: this.kernel.peer.host,
|
|
3134
3159
|
cwd: this.kernel.path("api"),
|
|
3135
3160
|
name: null,
|
|
@@ -3758,6 +3783,25 @@ class Server {
|
|
|
3758
3783
|
agent: this.agent,
|
|
3759
3784
|
})
|
|
3760
3785
|
}))
|
|
3786
|
+
this.app.post("/plugin/update", ex(async (req, res) => {
|
|
3787
|
+
console.time("/plugin/update")
|
|
3788
|
+
try {
|
|
3789
|
+
await this.kernel.exec({
|
|
3790
|
+
message: "git pull",
|
|
3791
|
+
path: this.kernel.path("plugin/code")
|
|
3792
|
+
}, (e) => {
|
|
3793
|
+
console.log(e)
|
|
3794
|
+
})
|
|
3795
|
+
console.timeEnd("/plugin/update")
|
|
3796
|
+
res.json({
|
|
3797
|
+
success: true
|
|
3798
|
+
})
|
|
3799
|
+
} catch (e) {
|
|
3800
|
+
res.json({
|
|
3801
|
+
error: e.stack
|
|
3802
|
+
})
|
|
3803
|
+
}
|
|
3804
|
+
}))
|
|
3761
3805
|
this.app.post("/network/reset", ex(async (req, res) => {
|
|
3762
3806
|
let caddy_path = this.kernel.path("cache/XDG_DATA_HOME/caddy")
|
|
3763
3807
|
await rimraf(caddy_path)
|
|
@@ -3780,6 +3824,7 @@ class Server {
|
|
|
3780
3824
|
})
|
|
3781
3825
|
}))
|
|
3782
3826
|
this.app.get("/net/:name", ex(async (req, res) => {
|
|
3827
|
+
let protocol = req.get('X-Forwarded-Proto')
|
|
3783
3828
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
3784
3829
|
bin: this.kernel.bin.preset("network"),
|
|
3785
3830
|
})
|
|
@@ -3791,21 +3836,19 @@ class Server {
|
|
|
3791
3836
|
}
|
|
3792
3837
|
|
|
3793
3838
|
let list = this.getPeerInfo()
|
|
3794
|
-
let processes
|
|
3839
|
+
let processes = []
|
|
3795
3840
|
let host
|
|
3796
3841
|
let peer
|
|
3797
3842
|
for(let item of list) {
|
|
3798
3843
|
if (item.name === req.params.name) {
|
|
3799
3844
|
processes = item.processes
|
|
3800
3845
|
host = item.host
|
|
3801
|
-
console.log("matched", processes)
|
|
3802
3846
|
peer = item
|
|
3803
3847
|
}
|
|
3804
3848
|
}
|
|
3805
3849
|
let favicons = {}
|
|
3806
3850
|
let titles = {}
|
|
3807
3851
|
let descriptions = {}
|
|
3808
|
-
console.time("Favicon")
|
|
3809
3852
|
//await Promise.all(peer.processes.map((proc) => {
|
|
3810
3853
|
// console.log("Proc", proc)
|
|
3811
3854
|
// return new Promise(async (resolve, reject) => {
|
|
@@ -3816,55 +3859,63 @@ class Server {
|
|
|
3816
3859
|
// }
|
|
3817
3860
|
// })
|
|
3818
3861
|
//}))
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
|
|
3822
|
-
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3826
|
-
|
|
3827
|
-
|
|
3828
|
-
//
|
|
3829
|
-
let
|
|
3830
|
-
|
|
3831
|
-
let
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
let
|
|
3836
|
-
if (
|
|
3837
|
-
|
|
3838
|
-
|
|
3839
|
-
|
|
3840
|
-
|
|
3862
|
+
|
|
3863
|
+
if (peer && peer.processes) {
|
|
3864
|
+
let pinokio_ip
|
|
3865
|
+
for(let proc of peer.processes) {
|
|
3866
|
+
if (proc.internal_port === 42000) {
|
|
3867
|
+
// pinokio ip
|
|
3868
|
+
pinokio_ip = proc.external_ip
|
|
3869
|
+
}
|
|
3870
|
+
if (proc.external_router) {
|
|
3871
|
+
// try to get icons from pinokio
|
|
3872
|
+
for(let router of proc.external_router) {
|
|
3873
|
+
// replace the root domain: facefusion-pinokio.git.x.localhost => facefusion-pinokio.git
|
|
3874
|
+
let pattern = `.${req.params.name}.localhost`
|
|
3875
|
+
if (router.endsWith(pattern)) {
|
|
3876
|
+
let name = router.replace(pattern, "")
|
|
3877
|
+
let api_path = this.kernel.path("api", name)
|
|
3878
|
+
let exists = await this.exists(api_path)
|
|
3879
|
+
if (exists) {
|
|
3880
|
+
let meta = await this.kernel.api.meta(name)
|
|
3881
|
+
if (meta.icon) {
|
|
3882
|
+
favicons[proc.external_ip] = meta.icon
|
|
3883
|
+
}
|
|
3884
|
+
if (meta.title) {
|
|
3885
|
+
titles[proc.external_ip] = meta.title
|
|
3886
|
+
}
|
|
3887
|
+
if (meta.description) {
|
|
3888
|
+
descriptions[proc.external_ip] = meta.description
|
|
3889
|
+
}
|
|
3841
3890
|
}
|
|
3842
|
-
|
|
3843
|
-
|
|
3891
|
+
}
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
// if not an app running inside pinokio, try to fetch and infer the favicon
|
|
3895
|
+
if (!favicons[proc.external_ip]) {
|
|
3896
|
+
if (protocol === "https") {
|
|
3897
|
+
if (proc.external_router.length > 0) {
|
|
3898
|
+
let favicon = await this.kernel.favicon.get("https://" + proc.external_router[0])
|
|
3899
|
+
if (favicon) {
|
|
3900
|
+
favicons[proc.external_ip] = favicon
|
|
3844
3901
|
}
|
|
3845
3902
|
}
|
|
3903
|
+
} else {
|
|
3904
|
+
let favicon = await this.kernel.favicon.get("http://" + proc.external_ip)
|
|
3905
|
+
if (favicon) {
|
|
3906
|
+
favicons[proc.external_ip] = favicon
|
|
3907
|
+
}
|
|
3846
3908
|
}
|
|
3847
3909
|
}
|
|
3848
3910
|
}
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
favicons[proc.external_ip] = favicon
|
|
3911
|
+
for (let external_ip in favicons) {
|
|
3912
|
+
let favicon_path = favicons[external_ip]
|
|
3913
|
+
if (!favicon_path.startsWith("http")) {
|
|
3914
|
+
favicons[external_ip] = "http://" + pinokio_ip + favicon_path
|
|
3854
3915
|
}
|
|
3855
3916
|
}
|
|
3856
3917
|
}
|
|
3857
|
-
for (let external_ip in favicons) {
|
|
3858
|
-
let favicon_path = favicons[external_ip]
|
|
3859
|
-
if (!favicon_path.startsWith("http")) {
|
|
3860
|
-
favicons[external_ip] = "http://" + pinokio_ip + favicon_path
|
|
3861
|
-
}
|
|
3862
|
-
}
|
|
3863
|
-
console.timeEnd("Favicon")
|
|
3864
|
-
console.log("favicons", favicons)
|
|
3865
|
-
|
|
3866
3918
|
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
3867
|
-
console.log("LIST", JSON.stringify(list, null, 2))
|
|
3868
3919
|
res.render("net", {
|
|
3869
3920
|
selected_name: req.params.name,
|
|
3870
3921
|
favicons,
|
|
@@ -4025,7 +4076,6 @@ class Server {
|
|
|
4025
4076
|
})
|
|
4026
4077
|
}))
|
|
4027
4078
|
this.app.post("/state", ex(async (req, res) => {
|
|
4028
|
-
console.log("POST /state", req.body)
|
|
4029
4079
|
/*
|
|
4030
4080
|
req.body := {
|
|
4031
4081
|
name: <name>,
|
|
@@ -4051,7 +4101,6 @@ class Server {
|
|
|
4051
4101
|
this.menu_hidden[req.body.name][req.body.type] = true
|
|
4052
4102
|
}
|
|
4053
4103
|
}
|
|
4054
|
-
console.log("select", req.body)
|
|
4055
4104
|
res.json({
|
|
4056
4105
|
success: true
|
|
4057
4106
|
})
|
|
@@ -4524,9 +4573,6 @@ class Server {
|
|
|
4524
4573
|
} catch (e) {
|
|
4525
4574
|
console.log("ERROR", e)
|
|
4526
4575
|
}
|
|
4527
|
-
|
|
4528
|
-
console.log("gitRemote", gitRemote)
|
|
4529
|
-
|
|
4530
4576
|
res.render("env_editor", {
|
|
4531
4577
|
gitRemote,
|
|
4532
4578
|
home: null,
|
|
@@ -4965,11 +5011,12 @@ console.log("gitRemote", gitRemote)
|
|
|
4965
5011
|
})
|
|
4966
5012
|
}))
|
|
4967
5013
|
this.app.get("/d/*", ex(async (req, res) => {
|
|
5014
|
+
console.log("> 1")
|
|
4968
5015
|
let filepath = Util.u2p(req.params[0])
|
|
4969
5016
|
let plugin = await this.getPluginGlobal(filepath)
|
|
5017
|
+
console.log("> 2")
|
|
4970
5018
|
let html = ""
|
|
4971
5019
|
let plugin_menu
|
|
4972
|
-
console.log("*********** plugin", plugin)
|
|
4973
5020
|
try {
|
|
4974
5021
|
plugin_menu = plugin.menu
|
|
4975
5022
|
//plugin_menu = plugin.menu[0].menu
|
|
@@ -4977,65 +5024,104 @@ console.log("gitRemote", gitRemote)
|
|
|
4977
5024
|
plugin_menu = []
|
|
4978
5025
|
}
|
|
4979
5026
|
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
4980
|
-
|
|
4981
|
-
console.log("DYNAMIC", JSON.stringify(plugin_menu, null, 2))
|
|
5027
|
+
console.log("> 3")
|
|
4982
5028
|
let retry = false
|
|
4983
5029
|
// if plugin_menu is empty, try again in 1 sec
|
|
4984
5030
|
if (plugin_menu.length === 0) {
|
|
4985
5031
|
retry = true
|
|
4986
5032
|
}
|
|
4987
|
-
|
|
4988
5033
|
let venvs = await Util.find_venv(filepath)
|
|
4989
|
-
|
|
5034
|
+
console.log("> 4")
|
|
4990
5035
|
let terminal
|
|
4991
|
-
|
|
4992
5036
|
if (venvs.length > 0) {
|
|
4993
5037
|
let terminals = []
|
|
4994
5038
|
try {
|
|
4995
|
-
for(let
|
|
5039
|
+
for(let i=0; i<venvs.length; i++) {
|
|
5040
|
+
let venv = venvs[i]
|
|
4996
5041
|
let parsed = path.parse(venv)
|
|
4997
|
-
terminals.push({
|
|
5042
|
+
terminals.push(this.renderShell(filepath, i, 0, {
|
|
4998
5043
|
icon: "fa-brands fa-python",
|
|
4999
|
-
title: "
|
|
5044
|
+
title: "Python virtual environment",
|
|
5045
|
+
subtitle: this.kernel.path("api", parsed.name),
|
|
5046
|
+
type: "Start",
|
|
5000
5047
|
shell: {
|
|
5001
5048
|
venv: venv,
|
|
5002
5049
|
input: true,
|
|
5003
5050
|
}
|
|
5004
|
-
})
|
|
5051
|
+
}))
|
|
5005
5052
|
}
|
|
5006
5053
|
} catch (e) {
|
|
5007
5054
|
console.log(e)
|
|
5008
5055
|
}
|
|
5009
5056
|
terminal = {
|
|
5010
5057
|
icon: "fa-solid fa-terminal",
|
|
5011
|
-
|
|
5058
|
+
title: "Open web terminal",
|
|
5059
|
+
subtitle: "Open the terminal in the browser",
|
|
5012
5060
|
menu: terminals
|
|
5013
5061
|
}
|
|
5014
5062
|
} else {
|
|
5015
5063
|
terminal = {
|
|
5016
5064
|
icon: "fa-solid fa-terminal",
|
|
5017
|
-
|
|
5018
|
-
|
|
5065
|
+
title: "Open web terminal",
|
|
5066
|
+
subtitle: "Work with the terminal directly in the browser",
|
|
5067
|
+
menu: [this.renderShell(filepath, 0, 0, {
|
|
5019
5068
|
icon: "fa-solid fa-terminal",
|
|
5020
|
-
title:
|
|
5069
|
+
title: "Terminal",
|
|
5070
|
+
subtitle: filepath,
|
|
5071
|
+
type: "Start",
|
|
5021
5072
|
shell: {
|
|
5022
5073
|
input: true
|
|
5023
5074
|
}
|
|
5024
|
-
}]
|
|
5075
|
+
})]
|
|
5025
5076
|
}
|
|
5026
5077
|
}
|
|
5027
|
-
|
|
5078
|
+
console.log("> 5")
|
|
5079
|
+
|
|
5080
|
+
let exec_menus = []
|
|
5081
|
+
let shell_menus = []
|
|
5082
|
+
if (plugin_menu.length > 0) {
|
|
5083
|
+
for(let item of plugin_menu) {
|
|
5084
|
+
// if shell.run method exists
|
|
5085
|
+
// if exec method exists
|
|
5086
|
+
let mode
|
|
5087
|
+
for(let step of item.run) {
|
|
5088
|
+
if (step.method === "exec") {
|
|
5089
|
+
mode = "exec"
|
|
5090
|
+
break
|
|
5091
|
+
}
|
|
5092
|
+
if (step.method === "shell.run") {
|
|
5093
|
+
mode = "shell"
|
|
5094
|
+
break
|
|
5095
|
+
}
|
|
5096
|
+
}
|
|
5097
|
+
if (mode === "exec") {
|
|
5098
|
+
item.type = "Open"
|
|
5099
|
+
exec_menus.push(item)
|
|
5100
|
+
} else if (mode === "shell") {
|
|
5101
|
+
item.type = "Start"
|
|
5102
|
+
shell_menus.push(item)
|
|
5103
|
+
}
|
|
5104
|
+
}
|
|
5105
|
+
exec_menus.sort((a, b) => { return a > b })
|
|
5106
|
+
shell_menus.sort((a, b) => { return a > b })
|
|
5107
|
+
}
|
|
5108
|
+
console.log("> 6")
|
|
5028
5109
|
let dynamic = [
|
|
5029
|
-
terminal,
|
|
5030
5110
|
{
|
|
5031
5111
|
icon: "fa-solid fa-robot",
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5112
|
+
title: "Get started building with AI",
|
|
5113
|
+
subtitle: "Start making changes to this project using AI",
|
|
5114
|
+
menu: shell_menus
|
|
5115
|
+
},
|
|
5116
|
+
{
|
|
5117
|
+
icon: "fa-solid fa-arrow-up-right-from-square",
|
|
5118
|
+
title: "Open in external apps",
|
|
5119
|
+
subtitle: "Open this project in 3rd party apps",
|
|
5120
|
+
menu: exec_menus
|
|
5121
|
+
},
|
|
5122
|
+
terminal,
|
|
5035
5123
|
]
|
|
5036
|
-
|
|
5037
|
-
console.log("### dynamic", JSON.stringify(dynamic, null, 2))
|
|
5038
|
-
|
|
5124
|
+
console.log("> 7")
|
|
5039
5125
|
res.render("d", {
|
|
5040
5126
|
retry,
|
|
5041
5127
|
current_urls,
|
|
@@ -5191,7 +5277,6 @@ console.log("gitRemote", gitRemote)
|
|
|
5191
5277
|
// await this.kernel.plugin.init()
|
|
5192
5278
|
let plugin = await this.getPlugin(req.params.name)
|
|
5193
5279
|
let html = ""
|
|
5194
|
-
console.log("plugin", JSON.stringify(plugin, null, 2))
|
|
5195
5280
|
let plugin_menu
|
|
5196
5281
|
if (plugin) {
|
|
5197
5282
|
if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
@@ -5203,9 +5288,7 @@ console.log("gitRemote", gitRemote)
|
|
|
5203
5288
|
})
|
|
5204
5289
|
})
|
|
5205
5290
|
}
|
|
5206
|
-
} else {
|
|
5207
5291
|
}
|
|
5208
|
-
console.log({ html })
|
|
5209
5292
|
res.send(html)
|
|
5210
5293
|
}))
|
|
5211
5294
|
this.app.get("/pinokio/ai/:name", ex(async (req, res) => {
|
|
@@ -5326,6 +5409,9 @@ console.log("gitRemote", gitRemote)
|
|
|
5326
5409
|
}))
|
|
5327
5410
|
this.app.get("/pinokio/peer", ex(async (req, res) => {
|
|
5328
5411
|
// await this.kernel.refresh()
|
|
5412
|
+
let current_peer_info = this.kernel.peer.current_host(this.kernel)
|
|
5413
|
+
res.json(current_peer_info)
|
|
5414
|
+
/*
|
|
5329
5415
|
res.json({
|
|
5330
5416
|
home: this.kernel.homedir,
|
|
5331
5417
|
arch: this.kernel.arch,
|
|
@@ -5338,6 +5424,7 @@ console.log("gitRemote", gitRemote)
|
|
|
5338
5424
|
router: this.kernel.router.published(),
|
|
5339
5425
|
memory: this.kernel.memory
|
|
5340
5426
|
})
|
|
5427
|
+
*/
|
|
5341
5428
|
}))
|
|
5342
5429
|
this.app.get("/pinokio/memory", ex((req, res) => {
|
|
5343
5430
|
let filepath = req.query.filepath
|
|
@@ -5409,25 +5496,25 @@ console.log("gitRemote", gitRemote)
|
|
|
5409
5496
|
}
|
|
5410
5497
|
}))
|
|
5411
5498
|
this.app.get("/pinokio/launch/:name", ex(async (req, res) => {
|
|
5412
|
-
this.chrome(req, res, "launch")
|
|
5499
|
+
await this.chrome(req, res, "launch")
|
|
5413
5500
|
}))
|
|
5414
5501
|
this.app.get("/pinokio/browser/:name/dev", ex(async (req, res) => {
|
|
5415
|
-
this.chrome(req, res, "browse")
|
|
5502
|
+
await this.chrome(req, res, "browse")
|
|
5416
5503
|
}))
|
|
5417
5504
|
this.app.get("/pinokio/browser/:name/browse", ex(async (req, res) => {
|
|
5418
|
-
this.chrome(req, res, "browse")
|
|
5505
|
+
await this.chrome(req, res, "browse")
|
|
5419
5506
|
}))
|
|
5420
5507
|
this.app.get("/pinokio/browser/:name", ex(async (req, res) => {
|
|
5421
|
-
this.chrome(req, res, "run")
|
|
5508
|
+
await this.chrome(req, res, "run")
|
|
5422
5509
|
}))
|
|
5423
5510
|
this.app.get("/p/:name/dev", ex(async (req, res) => {
|
|
5424
|
-
this.chrome(req, res, "browse")
|
|
5511
|
+
await this.chrome(req, res, "browse")
|
|
5425
5512
|
}))
|
|
5426
5513
|
this.app.get("/p/:name/browse", ex(async (req, res) => {
|
|
5427
|
-
this.chrome(req, res, "browse")
|
|
5514
|
+
await this.chrome(req, res, "browse")
|
|
5428
5515
|
}))
|
|
5429
5516
|
this.app.get("/p/:name", ex(async (req, res) => {
|
|
5430
|
-
this.chrome(req, res, "run")
|
|
5517
|
+
await this.chrome(req, res, "run")
|
|
5431
5518
|
}))
|
|
5432
5519
|
this.app.post("/pinokio/delete", ex(async (req, res) => {
|
|
5433
5520
|
try {
|