pinokiod 3.23.0 → 3.25.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/plugin.js +40 -10
- package/kernel/prototype.js +23 -0
- package/kernel/router/index.js +13 -0
- package/kernel/router/localhost_home_router.js +11 -0
- package/kernel/shell.js +30 -6
- package/kernel/shell_parser.js +267 -0
- package/kernel/shells.js +52 -45
- package/kernel/util.js +5 -1
- package/package.json +2 -1
- package/server/index.js +335 -136
- package/server/public/style.css +26 -1
- package/server/socket.js +13 -9
- package/server/views/app.ejs +122 -32
- package/server/views/d.ejs +284 -0
- package/server/views/env_editor.ejs +12 -0
- package/server/views/index.ejs +94 -14
- package/server/views/init/index.ejs +248 -81
- package/server/views/net.ejs +13 -8
- package/server/views/network.ejs +10 -3
- package/server/views/partials/dynamic.ejs +4 -1
- package/server/views/partials/menu.ejs +3 -0
- package/server/views/partials/running.ejs +22 -0
- package/server/views/settings.ejs +1 -1
- package/server/views/start.ejs +233 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pinokiod",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.25.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -36,6 +36,7 @@
|
|
|
36
36
|
"glob": "^10.3.3",
|
|
37
37
|
"glob-gitignore": "^1.0.14",
|
|
38
38
|
"go-get-folder-size": "^0.5.5",
|
|
39
|
+
"gray-matter": "^4.0.3",
|
|
39
40
|
"http-proxy": "^1.18.1",
|
|
40
41
|
"http-proxy-middleware": "^3.0.0",
|
|
41
42
|
"http-terminator": "^3.2.0",
|
package/server/index.js
CHANGED
|
@@ -188,8 +188,10 @@ class Server {
|
|
|
188
188
|
}
|
|
189
189
|
}
|
|
190
190
|
} else if (key === "shell") {
|
|
191
|
-
let
|
|
192
|
-
|
|
191
|
+
let unix_path = Util.p2u(this.kernel.path("api", name))
|
|
192
|
+
let shell_id = this.get_shell_id(unix_path, indexPath, obj[key])
|
|
193
|
+
let decoded_shell_id = decodeURIComponent(shell_id)
|
|
194
|
+
if (this.kernel.api.running["shell/" + decoded_shell_id]) {
|
|
193
195
|
obj.running = true
|
|
194
196
|
obj.display = "indent"
|
|
195
197
|
running_dynamic.push(obj)
|
|
@@ -422,34 +424,8 @@ class Server {
|
|
|
422
424
|
// }
|
|
423
425
|
|
|
424
426
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
return
|
|
428
|
-
|
|
429
|
-
// // none of the pinokio.js, pinokio.json, pinokio_meta.json exists => need to initialize
|
|
430
|
-
// // if there is no menu, display all files
|
|
431
|
-
// let p = this.kernel.path("api", name)
|
|
432
|
-
// let files = await fs.promises.readdir(p, { withFileTypes: true })
|
|
433
|
-
// files = files.filter((file) => {
|
|
434
|
-
// return file.name.endsWith(".json") || file.name.endsWith(".js")
|
|
435
|
-
// }).filter((file) => {
|
|
436
|
-
// return file.name !== "pinokio.js" && file.name !== "pinokio.json" && file.name !== "pinokio_meta.json"
|
|
437
|
-
// })
|
|
438
|
-
// config = {
|
|
439
|
-
// init_required: true,
|
|
440
|
-
// icon: config.icon,
|
|
441
|
-
// title: name,
|
|
442
|
-
// menu: files.map((file) => {
|
|
443
|
-
// return {
|
|
444
|
-
// text: file.name,
|
|
445
|
-
// href: file.name
|
|
446
|
-
// }
|
|
447
|
-
// })
|
|
448
|
-
// }
|
|
449
|
-
// let uri = this.kernel.path("api")
|
|
450
|
-
// await this.renderMenu(uri, name, config, [])
|
|
451
|
-
} else {
|
|
452
|
-
let menu = config.menu || []
|
|
427
|
+
let menu = config.menu || []
|
|
428
|
+
try {
|
|
453
429
|
if (typeof config.menu === "function") {
|
|
454
430
|
if (config.menu.constructor.name === "AsyncFunction") {
|
|
455
431
|
config.menu = await config.menu(this.kernel, this.kernel.info)
|
|
@@ -457,11 +433,14 @@ class Server {
|
|
|
457
433
|
config.menu = config.menu(this.kernel, this.kernel.info)
|
|
458
434
|
}
|
|
459
435
|
}
|
|
436
|
+
} catch (e) {
|
|
437
|
+
err = e.stack
|
|
438
|
+
config.menu = []
|
|
439
|
+
}
|
|
460
440
|
|
|
461
|
-
|
|
462
|
-
|
|
441
|
+
let uri = this.kernel.path("api")
|
|
442
|
+
await this.renderMenu(uri, name, config, [])
|
|
463
443
|
|
|
464
|
-
}
|
|
465
444
|
|
|
466
445
|
let platform = os.platform()
|
|
467
446
|
|
|
@@ -578,16 +557,23 @@ class Server {
|
|
|
578
557
|
let plugin = await this.getPlugin(name)
|
|
579
558
|
if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
580
559
|
plugin = structuredClone(plugin)
|
|
581
|
-
this.running_dynamic(name, plugin.menu)
|
|
582
|
-
plugin_menu = plugin.menu
|
|
560
|
+
plugin_menu = this.running_dynamic(name, plugin.menu)
|
|
583
561
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
562
|
let menu_hidden = false
|
|
587
563
|
if (this.menu_hidden[name] && this.menu_hidden[name][type]) {
|
|
588
564
|
menu_hidden = true
|
|
589
565
|
}
|
|
566
|
+
|
|
567
|
+
let posix_path = Util.p2u(this.kernel.path("api", name))
|
|
568
|
+
let dev_link
|
|
569
|
+
if (posix_path.startsWith("/")) {
|
|
570
|
+
dev_link = "/d" + posix_path
|
|
571
|
+
} else {
|
|
572
|
+
dev_link = "/d/" + posix_path
|
|
573
|
+
}
|
|
574
|
+
|
|
590
575
|
const result = {
|
|
576
|
+
dev_link,
|
|
591
577
|
minimized: menu_hidden,
|
|
592
578
|
// repos,
|
|
593
579
|
current_urls,
|
|
@@ -662,7 +648,6 @@ class Server {
|
|
|
662
648
|
is_subpath(parent, child) {
|
|
663
649
|
const relative = path.relative(parent, child);
|
|
664
650
|
let check = !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);
|
|
665
|
-
console.log({ relative, parent, child, check })
|
|
666
651
|
return check
|
|
667
652
|
}
|
|
668
653
|
async render(req, res, pathComponents, meta) {
|
|
@@ -1360,23 +1345,28 @@ class Server {
|
|
|
1360
1345
|
let is_running
|
|
1361
1346
|
let api_path = this.kernel.path("api")
|
|
1362
1347
|
if (this.is_subpath(api_path, key)) {
|
|
1348
|
+
// normal api script at path p
|
|
1363
1349
|
if (this.is_subpath(p, key)) {
|
|
1364
1350
|
is_running = true
|
|
1365
1351
|
}
|
|
1366
1352
|
} else {
|
|
1367
1353
|
if (key.endsWith(p)) {
|
|
1354
|
+
// global scripts that run in the path p
|
|
1368
1355
|
is_running = true
|
|
1369
1356
|
} else {
|
|
1370
|
-
|
|
1371
|
-
|
|
1357
|
+
// shell sessions
|
|
1358
|
+
if (key.startsWith("shell/")) {
|
|
1359
|
+
let unix_path = key.slice(6)
|
|
1360
|
+
let native_path = Util.u2p(unix_path)
|
|
1361
|
+
let chunks = native_path.split("_")
|
|
1372
1362
|
if (chunks.length > 1) {
|
|
1373
1363
|
let folder = chunks[0]
|
|
1374
1364
|
/// if the folder name matches, it's running
|
|
1375
|
-
|
|
1365
|
+
let item_path = this.kernel.path("api", items[i].name)
|
|
1366
|
+
if (item_path === folder) {
|
|
1376
1367
|
is_running = true
|
|
1377
1368
|
}
|
|
1378
1369
|
}
|
|
1379
|
-
|
|
1380
1370
|
}
|
|
1381
1371
|
}
|
|
1382
1372
|
}
|
|
@@ -1416,7 +1406,9 @@ class Server {
|
|
|
1416
1406
|
} else {
|
|
1417
1407
|
let shell = this.kernel.shell.find({
|
|
1418
1408
|
filter: (shell) => {
|
|
1419
|
-
|
|
1409
|
+
let item_path = this.kernel.path("api", items[i].name)
|
|
1410
|
+
let unix_item_path = Util.p2u(item_path)
|
|
1411
|
+
return shell.id.startsWith("shell/" + unix_item_path + "_")
|
|
1420
1412
|
}
|
|
1421
1413
|
})
|
|
1422
1414
|
if (shell.length > 0) {
|
|
@@ -1706,6 +1698,89 @@ class Server {
|
|
|
1706
1698
|
}
|
|
1707
1699
|
return config
|
|
1708
1700
|
}
|
|
1701
|
+
renderShell(cwd, indexPath, subIndexPath, menuitem) {
|
|
1702
|
+
if (menuitem.shell) {
|
|
1703
|
+
/*
|
|
1704
|
+
shell :- {
|
|
1705
|
+
id (optional),
|
|
1706
|
+
path (required), // api, bin, quick, network, api/
|
|
1707
|
+
message (optional), // if not specified, start an empty shell
|
|
1708
|
+
venv,
|
|
1709
|
+
input, // input mode if true
|
|
1710
|
+
callback, // callback url after shutting down
|
|
1711
|
+
kill, // when to kill (regular expression)
|
|
1712
|
+
}
|
|
1713
|
+
*/
|
|
1714
|
+
|
|
1715
|
+
let rendered = this.kernel.template.render(menuitem.shell, {})
|
|
1716
|
+
let params = new URLSearchParams()
|
|
1717
|
+
// if (rendered.id) {
|
|
1718
|
+
// params.set("id", encodeURIComponent(rendered.id))
|
|
1719
|
+
// } else {
|
|
1720
|
+
// let shell_id = "sh_" + name + "_" + i
|
|
1721
|
+
// params.set("id", encodeURIComponent(shell_id))
|
|
1722
|
+
// }
|
|
1723
|
+
if (rendered.path) {
|
|
1724
|
+
params.set("path", encodeURIComponent(this.kernel.api.filePath(rendered.path, cwd)))
|
|
1725
|
+
} else {
|
|
1726
|
+
params.set("path", encodeURIComponent(cwd))
|
|
1727
|
+
}
|
|
1728
|
+
if (rendered.message) params.set("message", encodeURIComponent(rendered.message))
|
|
1729
|
+
if (rendered.venv) params.set("venv", encodeURIComponent(rendered.venv))
|
|
1730
|
+
if (rendered.input) params.set("input", true)
|
|
1731
|
+
if (rendered.callback) params.set("callback", encodeURIComponent(rendered.callback))
|
|
1732
|
+
if (rendered.callback_target) params.set("callback_target", rendered_callback_target)
|
|
1733
|
+
if (rendered.kill) params.set("kill", encodeURIComponent(rendered.kill))
|
|
1734
|
+
if (rendered.done) params.set("done", encodeURIComponent(rendered.done))
|
|
1735
|
+
if (rendered.env) {
|
|
1736
|
+
for(let key in rendered.env) {
|
|
1737
|
+
let env_key = "env." + key
|
|
1738
|
+
params.set(env_key, rendered.env[key])
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1741
|
+
if (rendered.conda) {
|
|
1742
|
+
for(let key in rendered.conda) {
|
|
1743
|
+
let conda_key = "conda." + key
|
|
1744
|
+
params.set(conda_key, rendered.conda[key])
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
|
|
1748
|
+
// deterministic shell id generation
|
|
1749
|
+
// `${api_path}_${i}_${hash}`
|
|
1750
|
+
let currentIndexPath
|
|
1751
|
+
if (indexPath) {
|
|
1752
|
+
currentIndexPath = indexPath + "." + subIndexPath
|
|
1753
|
+
} else {
|
|
1754
|
+
currentIndexPath = "" + subIndexPath
|
|
1755
|
+
}
|
|
1756
|
+
let unix_path = Util.p2u(cwd)
|
|
1757
|
+
let shell_id = this.get_shell_id(unix_path, currentIndexPath, rendered)
|
|
1758
|
+
|
|
1759
|
+
console.log("SHELL ID 1", shell_id)
|
|
1760
|
+
|
|
1761
|
+
// let hash = crypto.createHash('md5').update(JSON.stringify(rendered)).digest('hex')
|
|
1762
|
+
// let shell_id
|
|
1763
|
+
// if (rendered.id) {
|
|
1764
|
+
// shell_id = encodeURIComponent(`${name}_${rendered.id}`)
|
|
1765
|
+
// } else {
|
|
1766
|
+
// shell_id = encodeURIComponent(`${name}_${i}_${hash}`)
|
|
1767
|
+
// }
|
|
1768
|
+
menuitem.href = "/shell/" + shell_id + "?" + params.toString()
|
|
1769
|
+
let decoded_shell_id = decodeURIComponent(shell_id)
|
|
1770
|
+
let shell = this.kernel.shell.get(decoded_shell_id)
|
|
1771
|
+
menuitem.shell_id = "shell/" + decoded_shell_id
|
|
1772
|
+
if (shell) {
|
|
1773
|
+
menuitem.running = true
|
|
1774
|
+
} else {
|
|
1775
|
+
let shell = this.kernel.shell.get(decoded_shell_id)
|
|
1776
|
+
if (shell) {
|
|
1777
|
+
menuitem.running = true
|
|
1778
|
+
}
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
console.log("renderShell", menuitem)
|
|
1782
|
+
return menuitem
|
|
1783
|
+
}
|
|
1709
1784
|
|
|
1710
1785
|
async renderMenu(uri, name, config, pathComponents, indexPath) {
|
|
1711
1786
|
if (config.menu) {
|
|
@@ -1789,81 +1864,8 @@ class Server {
|
|
|
1789
1864
|
|
|
1790
1865
|
|
|
1791
1866
|
if (menuitem.shell) {
|
|
1792
|
-
/*
|
|
1793
|
-
shell :- {
|
|
1794
|
-
id (optional),
|
|
1795
|
-
path (required), // api, bin, quick, network, api/
|
|
1796
|
-
message (optional), // if not specified, start an empty shell
|
|
1797
|
-
venv,
|
|
1798
|
-
input, // input mode if true
|
|
1799
|
-
callback, // callback url after shutting down
|
|
1800
|
-
kill, // when to kill (regular expression)
|
|
1801
|
-
}
|
|
1802
|
-
*/
|
|
1803
|
-
|
|
1804
|
-
let rendered = this.kernel.template.render(menuitem.shell, {})
|
|
1805
|
-
let params = new URLSearchParams()
|
|
1806
|
-
// if (rendered.id) {
|
|
1807
|
-
// params.set("id", encodeURIComponent(rendered.id))
|
|
1808
|
-
// } else {
|
|
1809
|
-
// let shell_id = "sh_" + name + "_" + i
|
|
1810
|
-
// params.set("id", encodeURIComponent(shell_id))
|
|
1811
|
-
// }
|
|
1812
1867
|
let basePath = this.kernel.path("api", name)
|
|
1813
|
-
|
|
1814
|
-
params.set("path", encodeURIComponent(this.kernel.api.filePath(rendered.path, basePath)))
|
|
1815
|
-
} else {
|
|
1816
|
-
params.set("path", encodeURIComponent(basePath))
|
|
1817
|
-
}
|
|
1818
|
-
if (rendered.message) params.set("message", encodeURIComponent(rendered.message))
|
|
1819
|
-
if (rendered.venv) params.set("venv", encodeURIComponent(rendered.venv))
|
|
1820
|
-
if (rendered.input) params.set("input", true)
|
|
1821
|
-
if (rendered.callback) params.set("callback", encodeURIComponent(rendered.callback))
|
|
1822
|
-
if (rendered.callback_target) params.set("callback_target", rendered_callback_target)
|
|
1823
|
-
if (rendered.kill) params.set("kill", encodeURIComponent(rendered.kill))
|
|
1824
|
-
if (rendered.done) params.set("done", encodeURIComponent(rendered.done))
|
|
1825
|
-
if (rendered.env) {
|
|
1826
|
-
for(let key in rendered.env) {
|
|
1827
|
-
let env_key = "env." + key
|
|
1828
|
-
params.set(env_key, rendered.env[key])
|
|
1829
|
-
}
|
|
1830
|
-
}
|
|
1831
|
-
if (rendered.conda) {
|
|
1832
|
-
for(let key in rendered.conda) {
|
|
1833
|
-
let conda_key = "conda." + key
|
|
1834
|
-
params.set(conda_key, rendered.conda[key])
|
|
1835
|
-
}
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
// deterministic shell id generation
|
|
1839
|
-
// `${api_path}_${i}_${hash}`
|
|
1840
|
-
let currentIndexPath
|
|
1841
|
-
if (indexPath) {
|
|
1842
|
-
currentIndexPath = indexPath + "." + i
|
|
1843
|
-
} else {
|
|
1844
|
-
currentIndexPath = "" + i
|
|
1845
|
-
}
|
|
1846
|
-
let shell_id = this.get_shell_id(name, currentIndexPath, rendered)
|
|
1847
|
-
|
|
1848
|
-
// let hash = crypto.createHash('md5').update(JSON.stringify(rendered)).digest('hex')
|
|
1849
|
-
// let shell_id
|
|
1850
|
-
// if (rendered.id) {
|
|
1851
|
-
// shell_id = encodeURIComponent(`${name}_${rendered.id}`)
|
|
1852
|
-
// } else {
|
|
1853
|
-
// shell_id = encodeURIComponent(`${name}_${i}_${hash}`)
|
|
1854
|
-
// }
|
|
1855
|
-
menuitem.href = "/shell/" + shell_id + "?" + params.toString()
|
|
1856
|
-
menuitem.shell_id = shell_id
|
|
1857
|
-
let shell = this.kernel.shell.get(shell_id)
|
|
1858
|
-
if (shell) {
|
|
1859
|
-
menuitem.running = true
|
|
1860
|
-
} else {
|
|
1861
|
-
let decoded_shell_id = decodeURIComponent(shell_id)
|
|
1862
|
-
let shell = this.kernel.shell.get(decoded_shell_id)
|
|
1863
|
-
if (shell) {
|
|
1864
|
-
menuitem.running = true
|
|
1865
|
-
}
|
|
1866
|
-
}
|
|
1868
|
+
this.renderShell(basePath, indexPath, i, menuitem)
|
|
1867
1869
|
}
|
|
1868
1870
|
|
|
1869
1871
|
if (menuitem.href) {
|
|
@@ -1978,9 +1980,7 @@ class Server {
|
|
|
1978
1980
|
config.menu[i].btn = menuitem.html
|
|
1979
1981
|
}
|
|
1980
1982
|
} else if (menuitem.hasOwnProperty("text")) {
|
|
1981
|
-
if (menuitem.hasOwnProperty("
|
|
1982
|
-
menuitem.html = `<i class="${menuitem.icon}"></i> ${menuitem.text}`
|
|
1983
|
-
} else if (menuitem.hasOwnProperty("image")) {
|
|
1983
|
+
if (menuitem.hasOwnProperty("image")) {
|
|
1984
1984
|
let imagePath
|
|
1985
1985
|
if (menuitem.image.startsWith("/")) {
|
|
1986
1986
|
imagePath = menuitem.image
|
|
@@ -1988,6 +1988,8 @@ class Server {
|
|
|
1988
1988
|
imagePath = `/api/${name}/${menuitem.image}?raw=true`
|
|
1989
1989
|
}
|
|
1990
1990
|
menuitem.html = `<img class='menu-item-image' src='${imagePath}' /> ${menuitem.text}`
|
|
1991
|
+
} else if (menuitem.hasOwnProperty("icon")) {
|
|
1992
|
+
menuitem.html = `<i class="${menuitem.icon}"></i> ${menuitem.text}`
|
|
1991
1993
|
} else {
|
|
1992
1994
|
menuitem.html = `${menuitem.text}`
|
|
1993
1995
|
}
|
|
@@ -2494,7 +2496,15 @@ class Server {
|
|
|
2494
2496
|
info.cwd = () => {
|
|
2495
2497
|
return filepath
|
|
2496
2498
|
}
|
|
2497
|
-
let menu =
|
|
2499
|
+
let menu = this.kernel.plugin.config.menu.map((item) => {
|
|
2500
|
+
return {
|
|
2501
|
+
params: {
|
|
2502
|
+
cwd: filepath
|
|
2503
|
+
},
|
|
2504
|
+
...item
|
|
2505
|
+
}
|
|
2506
|
+
})
|
|
2507
|
+
// let menu = await this.kernel.plugin.config.menu(this.kernel, info)
|
|
2498
2508
|
let plugin = { menu }
|
|
2499
2509
|
let uri = filepath
|
|
2500
2510
|
await this.renderMenu(uri, filepath, plugin, [])
|
|
@@ -2526,11 +2536,21 @@ class Server {
|
|
|
2526
2536
|
let cached = this.kernel.plugin.cache[name]
|
|
2527
2537
|
return cached
|
|
2528
2538
|
} else {
|
|
2529
|
-
let info = new Info(this.kernel)
|
|
2530
|
-
info.caller = () => {
|
|
2531
|
-
return this.kernel.path("api", name, "pinokio.js")
|
|
2532
|
-
}
|
|
2533
|
-
let menu = await this.kernel.plugin.config.menu(this.kernel, info)
|
|
2539
|
+
// let info = new Info(this.kernel)
|
|
2540
|
+
// info.caller = () => {
|
|
2541
|
+
// return this.kernel.path("api", name, "pinokio.js")
|
|
2542
|
+
// }
|
|
2543
|
+
// let menu = await this.kernel.plugin.config.menu(this.kernel, info)
|
|
2544
|
+
|
|
2545
|
+
let menu = this.kernel.plugin.config.menu.map((item) => {
|
|
2546
|
+
return {
|
|
2547
|
+
params: {
|
|
2548
|
+
//cwd: this.kernel.path("api", name, "pinokio.js")
|
|
2549
|
+
cwd: this.kernel.path("api", name)
|
|
2550
|
+
},
|
|
2551
|
+
...item
|
|
2552
|
+
}
|
|
2553
|
+
})
|
|
2534
2554
|
let plugin = { menu }
|
|
2535
2555
|
let uri = this.kernel.path("api")
|
|
2536
2556
|
await this.renderMenu(uri, name, plugin, [])
|
|
@@ -2847,6 +2867,44 @@ class Server {
|
|
|
2847
2867
|
|
|
2848
2868
|
//let home = this.kernel.homedir
|
|
2849
2869
|
//let home = this.kernel.store.get("home")
|
|
2870
|
+
this.app.get("/launch", ex(async (req, res) => {
|
|
2871
|
+
// parse the url
|
|
2872
|
+
/*
|
|
2873
|
+
is it https://<name>.localhost ?
|
|
2874
|
+
- is <name> already installed?
|
|
2875
|
+
- yes: display
|
|
2876
|
+
- no: 404
|
|
2877
|
+
else: 404
|
|
2878
|
+
*/
|
|
2879
|
+
let url = req.query.url
|
|
2880
|
+
let u = new URL(url)
|
|
2881
|
+
let host = u.host
|
|
2882
|
+
if (host.endsWith(".localhost")) {
|
|
2883
|
+
let name = host.replace(/\.localhost$/, '')
|
|
2884
|
+
let api_path = this.kernel.path("api", name)
|
|
2885
|
+
let exists = await this.exists(api_path)
|
|
2886
|
+
if (exists) {
|
|
2887
|
+
let meta = await this.kernel.api.meta(name)
|
|
2888
|
+
res.render("start", {
|
|
2889
|
+
logo: this.logo,
|
|
2890
|
+
theme: this.theme,
|
|
2891
|
+
agent: this.agent,
|
|
2892
|
+
name: meta.title,
|
|
2893
|
+
image: meta.icon,
|
|
2894
|
+
link: "/p/" + name
|
|
2895
|
+
})
|
|
2896
|
+
return
|
|
2897
|
+
}
|
|
2898
|
+
}
|
|
2899
|
+
res.render("start", {
|
|
2900
|
+
logo: this.logo,
|
|
2901
|
+
theme: this.theme,
|
|
2902
|
+
agent: this.agent,
|
|
2903
|
+
name: "Does not exist",
|
|
2904
|
+
image: "/pinokio-black.png",
|
|
2905
|
+
link: null
|
|
2906
|
+
})
|
|
2907
|
+
}))
|
|
2850
2908
|
this.app.get("/", ex(async (req, res) => {
|
|
2851
2909
|
// check bin folder
|
|
2852
2910
|
// let bin_path = this.kernel.path("bin/miniconda")
|
|
@@ -3061,7 +3119,13 @@ class Server {
|
|
|
3061
3119
|
|
|
3062
3120
|
// console.log("this.kernel.proto.init")
|
|
3063
3121
|
// await this.kernel.proto.init()
|
|
3122
|
+
let list = this.getPeerInfo()
|
|
3123
|
+
let ai = await this.kernel.proto.ai()
|
|
3124
|
+
console.log("ai", ai)
|
|
3064
3125
|
res.render("init/index", {
|
|
3126
|
+
list,
|
|
3127
|
+
ai,
|
|
3128
|
+
current_host: this.kernel.peer.host,
|
|
3065
3129
|
cwd: this.kernel.path("api"),
|
|
3066
3130
|
name: null,
|
|
3067
3131
|
// name: req.params.name,
|
|
@@ -3527,7 +3591,12 @@ class Server {
|
|
|
3527
3591
|
*/
|
|
3528
3592
|
|
|
3529
3593
|
// create a new term from cwd
|
|
3530
|
-
|
|
3594
|
+
|
|
3595
|
+
/*
|
|
3596
|
+
GET /shell/:unix_path => shell id: 'shell/:unix_path'
|
|
3597
|
+
*/
|
|
3598
|
+
|
|
3599
|
+
let id = "shell/" + decodeURIComponent(req.params.id)
|
|
3531
3600
|
let target = req.query.target ? req.query.target : null
|
|
3532
3601
|
let cwd = this.kernel.path(this.kernel.api.filePath(decodeURIComponent(req.query.path)))
|
|
3533
3602
|
let message = req.query.message ? decodeURIComponent(req.query.message) : null
|
|
@@ -3724,7 +3793,6 @@ class Server {
|
|
|
3724
3793
|
if (item.name === req.params.name) {
|
|
3725
3794
|
processes = item.processes
|
|
3726
3795
|
host = item.host
|
|
3727
|
-
console.log("matched", processes)
|
|
3728
3796
|
peer = item
|
|
3729
3797
|
}
|
|
3730
3798
|
}
|
|
@@ -4368,7 +4436,6 @@ class Server {
|
|
|
4368
4436
|
|
|
4369
4437
|
const items = await Util.parse_env_detail(filepath)
|
|
4370
4438
|
|
|
4371
|
-
|
|
4372
4439
|
res.render("env_editor", {
|
|
4373
4440
|
home: true,
|
|
4374
4441
|
config: null,
|
|
@@ -4436,8 +4503,23 @@ class Server {
|
|
|
4436
4503
|
})
|
|
4437
4504
|
} else {
|
|
4438
4505
|
|
|
4439
|
-
|
|
4506
|
+
let gitRemote = null
|
|
4507
|
+
try {
|
|
4508
|
+
//const repositoryPath = this.kernel.path(pathComponents[0], pathComponents[1])
|
|
4509
|
+
//const repositoryPath = this.kernel.path(pathComponents[0])
|
|
4510
|
+
const repositoryPath = path.resolve(this.kernel.api.userdir, api_path)
|
|
4511
|
+
console.log({ repositoryPath })
|
|
4512
|
+
gitRemote = await git.getConfig({
|
|
4513
|
+
fs,
|
|
4514
|
+
http,
|
|
4515
|
+
dir: repositoryPath,
|
|
4516
|
+
path: 'remote.origin.url'
|
|
4517
|
+
})
|
|
4518
|
+
} catch (e) {
|
|
4519
|
+
console.log("ERROR", e)
|
|
4520
|
+
}
|
|
4440
4521
|
res.render("env_editor", {
|
|
4522
|
+
gitRemote,
|
|
4441
4523
|
home: null,
|
|
4442
4524
|
config,
|
|
4443
4525
|
name,
|
|
@@ -4873,6 +4955,123 @@ class Server {
|
|
|
4873
4955
|
agent: this.agent,
|
|
4874
4956
|
})
|
|
4875
4957
|
}))
|
|
4958
|
+
this.app.get("/d/*", ex(async (req, res) => {
|
|
4959
|
+
let filepath = Util.u2p(req.params[0])
|
|
4960
|
+
let plugin = await this.getPluginGlobal(filepath)
|
|
4961
|
+
let html = ""
|
|
4962
|
+
let plugin_menu
|
|
4963
|
+
try {
|
|
4964
|
+
plugin_menu = plugin.menu
|
|
4965
|
+
//plugin_menu = plugin.menu[0].menu
|
|
4966
|
+
} catch (e) {
|
|
4967
|
+
plugin_menu = []
|
|
4968
|
+
}
|
|
4969
|
+
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
4970
|
+
let retry = false
|
|
4971
|
+
// if plugin_menu is empty, try again in 1 sec
|
|
4972
|
+
if (plugin_menu.length === 0) {
|
|
4973
|
+
retry = true
|
|
4974
|
+
}
|
|
4975
|
+
let venvs = await Util.find_venv(filepath)
|
|
4976
|
+
let terminal
|
|
4977
|
+
if (venvs.length > 0) {
|
|
4978
|
+
let terminals = []
|
|
4979
|
+
try {
|
|
4980
|
+
for(let i=0; i<venvs.length; i++) {
|
|
4981
|
+
let venv = venvs[i]
|
|
4982
|
+
let parsed = path.parse(venv)
|
|
4983
|
+
terminals.push(this.renderShell(filepath, i, 0, {
|
|
4984
|
+
icon: "fa-brands fa-python",
|
|
4985
|
+
title: "Python virtual environment",
|
|
4986
|
+
subtitle: this.kernel.path("api", parsed.name),
|
|
4987
|
+
type: "Start",
|
|
4988
|
+
shell: {
|
|
4989
|
+
venv: venv,
|
|
4990
|
+
input: true,
|
|
4991
|
+
}
|
|
4992
|
+
}))
|
|
4993
|
+
}
|
|
4994
|
+
} catch (e) {
|
|
4995
|
+
console.log(e)
|
|
4996
|
+
}
|
|
4997
|
+
terminal = {
|
|
4998
|
+
icon: "fa-solid fa-terminal",
|
|
4999
|
+
title: "Open web terminal",
|
|
5000
|
+
subtitle: "Open the terminal in the browser",
|
|
5001
|
+
menu: terminals
|
|
5002
|
+
}
|
|
5003
|
+
} else {
|
|
5004
|
+
terminal = {
|
|
5005
|
+
icon: "fa-solid fa-terminal",
|
|
5006
|
+
title: "Open web terminal",
|
|
5007
|
+
subtitle: "Work with the terminal directly in the browser",
|
|
5008
|
+
menu: [this.renderShell(filepath, 0, 0, {
|
|
5009
|
+
icon: "fa-solid fa-terminal",
|
|
5010
|
+
title: "Terminal",
|
|
5011
|
+
subtitle: filepath,
|
|
5012
|
+
type: "Start",
|
|
5013
|
+
shell: {
|
|
5014
|
+
input: true
|
|
5015
|
+
}
|
|
5016
|
+
})]
|
|
5017
|
+
}
|
|
5018
|
+
}
|
|
5019
|
+
|
|
5020
|
+
let exec_menus = []
|
|
5021
|
+
let shell_menus = []
|
|
5022
|
+
if (plugin_menu.length > 0) {
|
|
5023
|
+
for(let item of plugin_menu) {
|
|
5024
|
+
// if shell.run method exists
|
|
5025
|
+
// if exec method exists
|
|
5026
|
+
let mode
|
|
5027
|
+
for(let step of item.run) {
|
|
5028
|
+
if (step.method === "exec") {
|
|
5029
|
+
mode = "exec"
|
|
5030
|
+
break
|
|
5031
|
+
}
|
|
5032
|
+
if (step.method === "shell.run") {
|
|
5033
|
+
mode = "shell"
|
|
5034
|
+
break
|
|
5035
|
+
}
|
|
5036
|
+
}
|
|
5037
|
+
if (mode === "exec") {
|
|
5038
|
+
item.type = "Open"
|
|
5039
|
+
exec_menus.push(item)
|
|
5040
|
+
} else if (mode === "shell") {
|
|
5041
|
+
item.type = "Start"
|
|
5042
|
+
shell_menus.push(item)
|
|
5043
|
+
}
|
|
5044
|
+
}
|
|
5045
|
+
exec_menus.sort((a, b) => { return a > b })
|
|
5046
|
+
shell_menus.sort((a, b) => { return a > b })
|
|
5047
|
+
}
|
|
5048
|
+
let dynamic = [
|
|
5049
|
+
{
|
|
5050
|
+
icon: "fa-solid fa-robot",
|
|
5051
|
+
title: "Get started building with AI",
|
|
5052
|
+
subtitle: "Start making changes to this project using AI",
|
|
5053
|
+
menu: shell_menus
|
|
5054
|
+
},
|
|
5055
|
+
{
|
|
5056
|
+
icon: "fa-solid fa-arrow-up-right-from-square",
|
|
5057
|
+
title: "Open in external apps",
|
|
5058
|
+
subtitle: "Open this project in 3rd party apps",
|
|
5059
|
+
menu: exec_menus
|
|
5060
|
+
},
|
|
5061
|
+
terminal,
|
|
5062
|
+
]
|
|
5063
|
+
res.render("d", {
|
|
5064
|
+
retry,
|
|
5065
|
+
current_urls,
|
|
5066
|
+
docs: this.docs,
|
|
5067
|
+
portal: this.portal,
|
|
5068
|
+
install: this.install,
|
|
5069
|
+
agent: this.agent,
|
|
5070
|
+
theme: this.theme,
|
|
5071
|
+
//dynamic: plugin_menu
|
|
5072
|
+
dynamic,
|
|
5073
|
+
})
|
|
5074
|
+
}))
|
|
4876
5075
|
this.app.get("/dev/*", ex(async (req, res) => {
|
|
4877
5076
|
console.log("GET /dev/*", req.params)
|
|
4878
5077
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
@@ -5015,21 +5214,21 @@ class Server {
|
|
|
5015
5214
|
this.app.get("/pinokio/dynamic/:name", ex(async (req, res) => {
|
|
5016
5215
|
// await this.kernel.plugin.init()
|
|
5017
5216
|
let plugin = await this.getPlugin(req.params.name)
|
|
5217
|
+
let html = ""
|
|
5218
|
+
console.log("plugin", JSON.stringify(plugin, null, 2))
|
|
5219
|
+
let plugin_menu
|
|
5018
5220
|
if (plugin) {
|
|
5019
|
-
let html = ""
|
|
5020
5221
|
if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
5021
5222
|
plugin = structuredClone(plugin)
|
|
5022
|
-
this.running_dynamic(req.params.name, plugin.menu)
|
|
5223
|
+
plugin_menu = this.running_dynamic(req.params.name, plugin.menu)
|
|
5023
5224
|
html = await new Promise((resolve, reject) => {
|
|
5024
|
-
ejs.renderFile(path.resolve(__dirname, "views/partials/dynamic.ejs"), { dynamic:
|
|
5225
|
+
ejs.renderFile(path.resolve(__dirname, "views/partials/dynamic.ejs"), { dynamic: plugin_menu }, (err, html) => {
|
|
5025
5226
|
resolve(html)
|
|
5026
5227
|
})
|
|
5027
5228
|
})
|
|
5028
5229
|
}
|
|
5029
|
-
res.send(html)
|
|
5030
|
-
} else {
|
|
5031
|
-
res.send("")
|
|
5032
5230
|
}
|
|
5231
|
+
res.send(html)
|
|
5033
5232
|
}))
|
|
5034
5233
|
this.app.get("/pinokio/ai/:name", ex(async (req, res) => {
|
|
5035
5234
|
/*
|