pinokiod 3.8.153 → 3.8.1530
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/bin/git.js +8 -7
- package/kernel/bin/index.js +1 -0
- package/kernel/peer.js +0 -2
- package/kernel/router/index.js +1 -1
- package/kernel/shell.js +4 -0
- package/package.json +1 -1
- package/server/index.js +104 -0
- package/server/views/keys.ejs +276 -0
- package/server/views/network.ejs +53 -2
- package/server/views/prototypes.ejs +3 -2
- package/server/views/settings.ejs +23 -0
- package/server/views/shell.ejs +36 -4
package/kernel/bin/git.js
CHANGED
|
@@ -14,6 +14,7 @@ class Git {
|
|
|
14
14
|
`conda install -y -c conda-forge ${this.cmd()}`
|
|
15
15
|
]
|
|
16
16
|
}, ondata)
|
|
17
|
+
await fs.promises.mkdir(this.kernel.path("config/gh"), { recursive: true }).catch((e) => { })
|
|
17
18
|
// if (this.kernel.platform === 'win32') {
|
|
18
19
|
// let gitconfig_path = path.resolve(this.kernel.homedir, "gitconfig")
|
|
19
20
|
// // check if gitconfig exists
|
|
@@ -28,18 +29,18 @@ class Git {
|
|
|
28
29
|
// }
|
|
29
30
|
}
|
|
30
31
|
async installed() {
|
|
31
|
-
|
|
32
|
+
let gh_config_exists = await this.kernel.exists("config/gh")
|
|
33
|
+
return this.kernel.bin.installed.conda && this.kernel.bin.installed.conda.has("git") && this.kernel.bin.installed.conda.has("gh") && gh_config_exists
|
|
32
34
|
}
|
|
33
35
|
async uninstall(req, ondata) {
|
|
34
36
|
await this.kernel.bin.exec({ message: "conda remove git gh" }, ondata)
|
|
35
37
|
}
|
|
36
38
|
env() {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
// }
|
|
39
|
+
let gitconfig_path = path.resolve(this.kernel.homedir, "gitconfig")
|
|
40
|
+
return {
|
|
41
|
+
GIT_CONFIG_GLOBAL: gitconfig_path,
|
|
42
|
+
GH_CONFIG_DIR: this.kernel.path("config/gh")
|
|
43
|
+
}
|
|
43
44
|
}
|
|
44
45
|
async requires() {
|
|
45
46
|
return ["conda"]
|
package/kernel/bin/index.js
CHANGED
package/kernel/peer.js
CHANGED
|
@@ -106,7 +106,6 @@ class PeerDiscovery {
|
|
|
106
106
|
}
|
|
107
107
|
// refresh peer info
|
|
108
108
|
async refresh(peers) {
|
|
109
|
-
console.log("*Refresh")
|
|
110
109
|
// if (this.active) {
|
|
111
110
|
this.refreshing = true
|
|
112
111
|
let refresh_peers
|
|
@@ -119,7 +118,6 @@ class PeerDiscovery {
|
|
|
119
118
|
let peer_info = await Promise.all(refresh_peers.map((host) => {
|
|
120
119
|
return this._refresh(host)
|
|
121
120
|
}))
|
|
122
|
-
console.log("*Peer.refresh", { peer_info })
|
|
123
121
|
for(let i=0; i<peer_info.length; i++) {
|
|
124
122
|
let peer = peer_info[i]
|
|
125
123
|
if (peer) {
|
package/kernel/router/index.js
CHANGED
|
@@ -214,7 +214,7 @@ class Router {
|
|
|
214
214
|
let response = await axios.post('http://127.0.0.1:2019/load', this.config, {
|
|
215
215
|
headers: { 'Content-Type': 'application/json' }
|
|
216
216
|
})
|
|
217
|
-
console.log("Caddy Response", { response })
|
|
217
|
+
// console.log("Caddy Response", { response })
|
|
218
218
|
this.old_config = this.config
|
|
219
219
|
} catch (e) {
|
|
220
220
|
console.log("EEEEEEEEEEEEE", e)
|
package/kernel/shell.js
CHANGED
|
@@ -923,6 +923,7 @@ class Shell {
|
|
|
923
923
|
this.done = false
|
|
924
924
|
this.ptyProcess = pty.spawn(this.shell, this.args, config)
|
|
925
925
|
this.ptyProcess.onData((data) => {
|
|
926
|
+
console.log({ data, done: this.done })
|
|
926
927
|
if (!this.done) {
|
|
927
928
|
this.queue.push(data)
|
|
928
929
|
}
|
|
@@ -985,6 +986,7 @@ class Shell {
|
|
|
985
986
|
// automatically remove the shell from this.kernel.shells
|
|
986
987
|
this.kernel.shell.rm(this.id)
|
|
987
988
|
this.ondata({ raw: `\r\n\r\n██ Terminated Shell ${this.id}\r\n████\r\n` })
|
|
989
|
+
this.ondata({ raw: "", type: "shell.kill" })
|
|
988
990
|
console.log("before cb 1")
|
|
989
991
|
cb()
|
|
990
992
|
} else {
|
|
@@ -994,10 +996,12 @@ class Shell {
|
|
|
994
996
|
// automatically remove the shell from this.kernel.shells
|
|
995
997
|
this.kernel.shell.rm(this.id)
|
|
996
998
|
this.ondata({ raw: `\r\n\r\n██ Terminated Shell ${this.id}\r\n████\r\n` })
|
|
999
|
+
this.ondata({ raw: "", type: "shell.kill" })
|
|
997
1000
|
}
|
|
998
1001
|
} else {
|
|
999
1002
|
this.kernel.shell.rm(this.id)
|
|
1000
1003
|
this.ondata({ raw: `\r\n\r\n██ Terminated Shell ${this.id}\r\n████\r\n` })
|
|
1004
|
+
this.ondata({ raw: "", type: "shell.kill" })
|
|
1001
1005
|
}
|
|
1002
1006
|
|
|
1003
1007
|
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -1468,12 +1468,20 @@ class Server {
|
|
|
1468
1468
|
if (rendered.venv) params.set("venv", encodeURIComponent(rendered.venv))
|
|
1469
1469
|
if (rendered.input) params.set("input", true)
|
|
1470
1470
|
if (rendered.callback) params.set("callback", encodeURIComponent(rendered.callback))
|
|
1471
|
+
if (rendered.kill) params.set("kill", encodeURIComponent(rendered.kill))
|
|
1472
|
+
if (rendered.done) params.set("done", encodeURIComponent(rendered.done))
|
|
1471
1473
|
if (rendered.env) {
|
|
1472
1474
|
for(let key in rendered.env) {
|
|
1473
1475
|
let env_key = "env." + key
|
|
1474
1476
|
params.set(env_key, rendered.env[key])
|
|
1475
1477
|
}
|
|
1476
1478
|
}
|
|
1479
|
+
if (rendered.conda) {
|
|
1480
|
+
for(let key in rendered.conda) {
|
|
1481
|
+
let conda_key = "conda." + key
|
|
1482
|
+
params.set(conda_key, rendered.conda[key])
|
|
1483
|
+
}
|
|
1484
|
+
}
|
|
1477
1485
|
|
|
1478
1486
|
// deterministic shell id generation
|
|
1479
1487
|
// `${api_path}_${i}_${hash}`
|
|
@@ -2464,6 +2472,43 @@ class Server {
|
|
|
2464
2472
|
Util.openfs(req.body.path, req.body, this.kernel)
|
|
2465
2473
|
res.json({ success: true })
|
|
2466
2474
|
}))
|
|
2475
|
+
this.app.post("/keys", ex(async (req, res) => {
|
|
2476
|
+
let p = this.kernel.path("key.json")
|
|
2477
|
+
let keys = (await this.kernel.loader.load(p)).resolved
|
|
2478
|
+
console.log("update", req.body)
|
|
2479
|
+
for(let host in req.body) {
|
|
2480
|
+
let updated = req.body[host]
|
|
2481
|
+
for(let indexStr in updated) {
|
|
2482
|
+
let index = parseInt(indexStr)
|
|
2483
|
+
keys[host][index] = updated[indexStr]
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
await fs.promises.writeFile(p, JSON.stringify(keys, null, 2))
|
|
2487
|
+
res.json({ success: true })
|
|
2488
|
+
}))
|
|
2489
|
+
this.app.get("/keys", ex(async (req, res) => {
|
|
2490
|
+
let p = this.kernel.path("key.json")
|
|
2491
|
+
let keys = (await this.kernel.loader.load(p)).resolved
|
|
2492
|
+
console.log({ keys })
|
|
2493
|
+
let items = []
|
|
2494
|
+
if (keys) {
|
|
2495
|
+
let sorted_keys = Object.keys(keys)
|
|
2496
|
+
sorted_keys.sort((a, b) => { return a > b })
|
|
2497
|
+
for(let key of sorted_keys) {
|
|
2498
|
+
console.log({ key })
|
|
2499
|
+
items.push({
|
|
2500
|
+
host: key,
|
|
2501
|
+
vals: keys[key]
|
|
2502
|
+
})
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
res.render("keys", {
|
|
2506
|
+
filepath: p,
|
|
2507
|
+
theme: this.theme,
|
|
2508
|
+
agent: this.agent,
|
|
2509
|
+
items
|
|
2510
|
+
})
|
|
2511
|
+
}))
|
|
2467
2512
|
this.app.get("/docs", ex(async (req, res) => {
|
|
2468
2513
|
let url = req.query.url
|
|
2469
2514
|
const possiblePaths = [
|
|
@@ -2524,6 +2569,28 @@ class Server {
|
|
|
2524
2569
|
})
|
|
2525
2570
|
}
|
|
2526
2571
|
}))
|
|
2572
|
+
this.app.get("/github/login", ex(async (req, res) => {
|
|
2573
|
+
let params = new URLSearchParams()
|
|
2574
|
+
let delimiter
|
|
2575
|
+
if (this.kernel.platform === "win32") {
|
|
2576
|
+
delimiter = " && "; // must use &&. & doesn't necessariliy wait until the curruent command finishes
|
|
2577
|
+
} else {
|
|
2578
|
+
delimiter = " ; ";
|
|
2579
|
+
}
|
|
2580
|
+
let message = [
|
|
2581
|
+
"gh auth setup-git --hostname github.com --force",
|
|
2582
|
+
"gh auth login --web --git-protocol https"
|
|
2583
|
+
].join(delimiter)
|
|
2584
|
+
params.set("message", encodeURIComponent(message))
|
|
2585
|
+
params.set("input", true)
|
|
2586
|
+
params.set("path", this.kernel.homedir)
|
|
2587
|
+
params.set("kill", "/Logged in/i")
|
|
2588
|
+
params.set("kill_message", "Your Github account is now connected.")
|
|
2589
|
+
params.set("callback", encodeURIComponent("/"))
|
|
2590
|
+
params.set("id", "github")
|
|
2591
|
+
let url = "/shell/github?" + params.toString()
|
|
2592
|
+
res.redirect(url)
|
|
2593
|
+
}))
|
|
2527
2594
|
this.app.get("/shell/:id", ex(async (req, res) => {
|
|
2528
2595
|
/*
|
|
2529
2596
|
req.query := {
|
|
@@ -2532,6 +2599,8 @@ class Server {
|
|
|
2532
2599
|
venv,
|
|
2533
2600
|
callback,
|
|
2534
2601
|
kill, // regex for killing
|
|
2602
|
+
on.<regex1>: <key>,
|
|
2603
|
+
on.<regex2>: <key>,
|
|
2535
2604
|
env.<key1>,
|
|
2536
2605
|
env.<key2>,
|
|
2537
2606
|
...
|
|
@@ -2543,9 +2612,15 @@ class Server {
|
|
|
2543
2612
|
let id = decodeURIComponent(req.params.id)
|
|
2544
2613
|
let cwd = this.kernel.path(this.kernel.api.filePath(decodeURIComponent(req.query.path)))
|
|
2545
2614
|
let message = req.query.message ? decodeURIComponent(req.query.message) : null
|
|
2615
|
+
//let message = req.query.message ? req.query.message : null
|
|
2616
|
+
console.log({ message })
|
|
2546
2617
|
let venv = req.query.venv ? decodeURIComponent(req.query.venv) : null
|
|
2547
2618
|
let input = req.query.input ? true : false
|
|
2548
2619
|
let callback = req.query.callback ? decodeURIComponent(req.query.callback) : null
|
|
2620
|
+
let kill_message = req.query.kill_message ? decodeURIComponent(req.query.kill_message) : null
|
|
2621
|
+
let done_message = req.query.done_message ? decodeURIComponent(req.query.done_message) : null
|
|
2622
|
+
let kill = req.query.kill ? decodeURIComponent(req.query.kill) : null
|
|
2623
|
+
let done = req.query.done ? decodeURIComponent(req.query.done) : null
|
|
2549
2624
|
let env = {}
|
|
2550
2625
|
for(let env_key in req.query) {
|
|
2551
2626
|
if (env_key.startsWith("env.")) {
|
|
@@ -2554,6 +2629,24 @@ class Server {
|
|
|
2554
2629
|
env[key] = req.query[env_key]
|
|
2555
2630
|
}
|
|
2556
2631
|
}
|
|
2632
|
+
let conda = {}
|
|
2633
|
+
let conda_exists = false
|
|
2634
|
+
for(let conda_key in req.query) {
|
|
2635
|
+
if (conda_key.startsWith("conda.")) {
|
|
2636
|
+
let chunks = conda_key.split(".")
|
|
2637
|
+
let key = chunks.slice(1).join(".")
|
|
2638
|
+
conda[key] = req.query[conda_key]
|
|
2639
|
+
conda_exists = true
|
|
2640
|
+
}
|
|
2641
|
+
}
|
|
2642
|
+
// let pattern = {}
|
|
2643
|
+
// for(let pattern_key in req.query) {
|
|
2644
|
+
// if (pattern_key.startsWith("pattern.")) {
|
|
2645
|
+
// let chunks = pattern_key.split(".")
|
|
2646
|
+
// let key = chunks.slice(1).join(".")
|
|
2647
|
+
// pattern[key] = req.query[pattern_key]
|
|
2648
|
+
// }
|
|
2649
|
+
// }
|
|
2557
2650
|
|
|
2558
2651
|
let shell = this.kernel.shell.get(id)
|
|
2559
2652
|
console.log({ shell })
|
|
@@ -2564,8 +2657,14 @@ class Server {
|
|
|
2564
2657
|
cwd,
|
|
2565
2658
|
message,
|
|
2566
2659
|
venv,
|
|
2660
|
+
conda: (conda_exists ? conda: null),
|
|
2567
2661
|
env,
|
|
2662
|
+
// pattern,
|
|
2568
2663
|
input,
|
|
2664
|
+
kill,
|
|
2665
|
+
kill_message,
|
|
2666
|
+
done,
|
|
2667
|
+
done_message,
|
|
2569
2668
|
callback,
|
|
2570
2669
|
running: (shell ? true : false)
|
|
2571
2670
|
})
|
|
@@ -2640,6 +2739,11 @@ class Server {
|
|
|
2640
2739
|
agent: this.agent,
|
|
2641
2740
|
})
|
|
2642
2741
|
}))
|
|
2742
|
+
this.app.post("/network/reset", ex(async (req, res) => {
|
|
2743
|
+
let caddy_path = this.kernel.path("cache/XDG_DATA_HOME/caddy")
|
|
2744
|
+
await rimraf(caddy_path)
|
|
2745
|
+
res.json({ success: true })
|
|
2746
|
+
}))
|
|
2643
2747
|
this.app.get("/network", ex(async (req, res) => {
|
|
2644
2748
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
2645
2749
|
bin: this.kernel.bin.preset("network"),
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
<html class='columns'>
|
|
2
|
+
<head>
|
|
3
|
+
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
|
|
4
|
+
<script src="/hotkeys.min.js"></script>
|
|
5
|
+
<script src="/ace/ace.js"></script>
|
|
6
|
+
<script src="/noty.js"></script>
|
|
7
|
+
<script src="/notyq.js"></script>
|
|
8
|
+
<script src="/xterm.js"></script>
|
|
9
|
+
<script src="/xterm-addon-fit.js"></script>
|
|
10
|
+
<script src="/xterm-addon-web-links.js"></script>
|
|
11
|
+
<script src="/xterm-theme.js"></script>
|
|
12
|
+
<script src="/xterm-addon-search.js"></script>
|
|
13
|
+
<script src="/xterm-addon-search-bar.js"></script>
|
|
14
|
+
<script src="/sweetalert2.js"></script>
|
|
15
|
+
<script src="/Socket.js"></script>
|
|
16
|
+
<script src="/common.js"></script>
|
|
17
|
+
<script src="/he.js"></script>
|
|
18
|
+
<script src="/opener.js"></script>
|
|
19
|
+
<script src="/nav.js"></script>
|
|
20
|
+
<script src="/autoexpand.js"></script>
|
|
21
|
+
<script src="/modalinput.js"></script>
|
|
22
|
+
<script src="/simplemodal.js"></script>
|
|
23
|
+
<script src="/waitmodal.js"></script>
|
|
24
|
+
<script src="/notifyinput.js"></script>
|
|
25
|
+
<script src="/report.js"></script>
|
|
26
|
+
<link href="/xterm.min.css" rel="stylesheet" />
|
|
27
|
+
<link href="/css/fontawesome.min.css" rel="stylesheet">
|
|
28
|
+
<link href="/css/solid.min.css" rel="stylesheet">
|
|
29
|
+
<link href="/css/regular.min.css" rel="stylesheet">
|
|
30
|
+
<link href="/css/brands.min.css" rel="stylesheet">
|
|
31
|
+
<link href="/style.css" rel="stylesheet"/>
|
|
32
|
+
<link href="/noty.css" rel="stylesheet"/>
|
|
33
|
+
<% if (agent === "electron") { %>
|
|
34
|
+
<link href="/electron.css" rel="stylesheet"/>
|
|
35
|
+
<% } %>
|
|
36
|
+
<style>
|
|
37
|
+
body.frozen {
|
|
38
|
+
display: flex;
|
|
39
|
+
flex-direction: column;
|
|
40
|
+
height: 100%;
|
|
41
|
+
}
|
|
42
|
+
#table > table {
|
|
43
|
+
border-left: 2px solid black;
|
|
44
|
+
padding-left: 5px;
|
|
45
|
+
margin: 10px 0;
|
|
46
|
+
}
|
|
47
|
+
.highlight {
|
|
48
|
+
background: yellow;
|
|
49
|
+
width: 100px;
|
|
50
|
+
}
|
|
51
|
+
th {
|
|
52
|
+
background: rgba(0,0,0,0.1);
|
|
53
|
+
padding: 10px;
|
|
54
|
+
font-size: 12px;
|
|
55
|
+
}
|
|
56
|
+
td {
|
|
57
|
+
font-size: 12px;
|
|
58
|
+
padding: 10px;
|
|
59
|
+
}
|
|
60
|
+
td.val {
|
|
61
|
+
background: rgba(0,0,0,0.06);
|
|
62
|
+
}
|
|
63
|
+
td.key {
|
|
64
|
+
background: rgba(0,0,0,0.1);
|
|
65
|
+
}
|
|
66
|
+
.button {
|
|
67
|
+
cursor: pointer;
|
|
68
|
+
background: rgba(0,0,0,0.8);
|
|
69
|
+
color: white;
|
|
70
|
+
padding: 5px 10px;
|
|
71
|
+
border-radius: 4px;
|
|
72
|
+
}
|
|
73
|
+
.button:hover {
|
|
74
|
+
|
|
75
|
+
}
|
|
76
|
+
#editor {
|
|
77
|
+
width: 100%;
|
|
78
|
+
box-sizing: border-box;
|
|
79
|
+
max-width: 600px;
|
|
80
|
+
padding: 20px;
|
|
81
|
+
margin: 0 auto;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
header .btn {
|
|
85
|
+
font-family: Sans-serif;
|
|
86
|
+
display: block;
|
|
87
|
+
margin-left: 10px;
|
|
88
|
+
font-style: normal;
|
|
89
|
+
font-size: 12px;
|
|
90
|
+
font-weight: normal;
|
|
91
|
+
padding: 5px 10px;
|
|
92
|
+
}
|
|
93
|
+
.disabled {
|
|
94
|
+
opacity: 0.7;
|
|
95
|
+
}
|
|
96
|
+
body.dark .env-item input[type=text] {
|
|
97
|
+
background: white;
|
|
98
|
+
}
|
|
99
|
+
.env-item input[type=text] {
|
|
100
|
+
width: 100%;
|
|
101
|
+
padding: 10px;
|
|
102
|
+
box-sizing: border-box;
|
|
103
|
+
border: none;
|
|
104
|
+
background: rgba(0,0,100, 0.1);
|
|
105
|
+
}
|
|
106
|
+
body.dark .env-item label {
|
|
107
|
+
color: cornflowerblue;
|
|
108
|
+
}
|
|
109
|
+
.env-item label {
|
|
110
|
+
color: royalblue;
|
|
111
|
+
display: block;
|
|
112
|
+
margin-bottom: 5px;
|
|
113
|
+
font-weight: bold;
|
|
114
|
+
font-size: 18px;
|
|
115
|
+
}
|
|
116
|
+
.env-item.highlighted {
|
|
117
|
+
border: 5px solid red;
|
|
118
|
+
}
|
|
119
|
+
.env-item {
|
|
120
|
+
/*
|
|
121
|
+
padding-top: 10px;
|
|
122
|
+
padding-bottom: 30px;
|
|
123
|
+
*/
|
|
124
|
+
padding: 10px;
|
|
125
|
+
margin-bottom: 20px;
|
|
126
|
+
}
|
|
127
|
+
body.dark .comment {
|
|
128
|
+
border-left: 2px solid white;
|
|
129
|
+
}
|
|
130
|
+
.comment {
|
|
131
|
+
opacity: 0.8;
|
|
132
|
+
border-left: 2px solid black;
|
|
133
|
+
padding-left: 10px;
|
|
134
|
+
}
|
|
135
|
+
#save {
|
|
136
|
+
background: royalblue;
|
|
137
|
+
}
|
|
138
|
+
a#customize {
|
|
139
|
+
text-decoration: underline;
|
|
140
|
+
cursor: pointer;
|
|
141
|
+
}
|
|
142
|
+
.e {
|
|
143
|
+
padding: 10px 0;
|
|
144
|
+
}
|
|
145
|
+
#editor {
|
|
146
|
+
padding: 20px 0;
|
|
147
|
+
}
|
|
148
|
+
.center {
|
|
149
|
+
display: flex;
|
|
150
|
+
align-items: center;
|
|
151
|
+
justify-content: center;
|
|
152
|
+
}
|
|
153
|
+
body {
|
|
154
|
+
display: block;
|
|
155
|
+
}
|
|
156
|
+
.card {
|
|
157
|
+
display: flex;
|
|
158
|
+
padding: 10px 0;
|
|
159
|
+
box-sizing: border-box;
|
|
160
|
+
}
|
|
161
|
+
.card img {
|
|
162
|
+
width: 100px;
|
|
163
|
+
border-radius: 10px;
|
|
164
|
+
}
|
|
165
|
+
.card .description {
|
|
166
|
+
opacity: 0.8;
|
|
167
|
+
}
|
|
168
|
+
.card .title {
|
|
169
|
+
font-weight: bold;
|
|
170
|
+
font-size: 30px;
|
|
171
|
+
letter-spacing: -1px;
|
|
172
|
+
}
|
|
173
|
+
.card .col {
|
|
174
|
+
padding-left: 10px;
|
|
175
|
+
}
|
|
176
|
+
h1 {
|
|
177
|
+
font-size: 50px;
|
|
178
|
+
padding-bottom: 20px;
|
|
179
|
+
}
|
|
180
|
+
footer {
|
|
181
|
+
background: none;
|
|
182
|
+
padding: 0;
|
|
183
|
+
text-align: right;
|
|
184
|
+
display: flex;
|
|
185
|
+
margin: 10px 0 20px 0;
|
|
186
|
+
}
|
|
187
|
+
footer .btn {
|
|
188
|
+
margin-left: 10px;
|
|
189
|
+
display: inline-block;
|
|
190
|
+
-webkit-appearance: button;
|
|
191
|
+
-moz-appearance: button;
|
|
192
|
+
appearance: button;
|
|
193
|
+
|
|
194
|
+
}
|
|
195
|
+
footer .btn.go-home {
|
|
196
|
+
margin-left: 0px;
|
|
197
|
+
}
|
|
198
|
+
.btn.home-button {
|
|
199
|
+
background: none !important;
|
|
200
|
+
margin: 0 !important;
|
|
201
|
+
font-size: 16px !important;
|
|
202
|
+
}
|
|
203
|
+
#editor {
|
|
204
|
+
height: auto;
|
|
205
|
+
}
|
|
206
|
+
.env-title {
|
|
207
|
+
font-weight: bold;
|
|
208
|
+
}
|
|
209
|
+
.env-description {
|
|
210
|
+
margin-bottom: 10px;
|
|
211
|
+
}
|
|
212
|
+
input[type=text] {
|
|
213
|
+
margin-bottom: 5px;
|
|
214
|
+
}
|
|
215
|
+
</style>
|
|
216
|
+
<script>
|
|
217
|
+
document.addEventListener("DOMContentLoaded", async () => {
|
|
218
|
+
const n = new N()
|
|
219
|
+
let updated = {}
|
|
220
|
+
document.addEventListener("input", (e) => {
|
|
221
|
+
let host = e.target.getAttribute("data-host")
|
|
222
|
+
let index = e.target.getAttribute("data-index")
|
|
223
|
+
if (!updated[host]) {
|
|
224
|
+
updated[host] = {}
|
|
225
|
+
}
|
|
226
|
+
updated[host][index] = e.target.value
|
|
227
|
+
})
|
|
228
|
+
document.querySelector("#save").addEventListener("click", async (e) => {
|
|
229
|
+
console.log({ updated })
|
|
230
|
+
let res = await fetch("/keys", {
|
|
231
|
+
method: "POST",
|
|
232
|
+
headers: {
|
|
233
|
+
"Content-Type": "application/json"
|
|
234
|
+
},
|
|
235
|
+
body: JSON.stringify(updated)
|
|
236
|
+
}).then((res) => {
|
|
237
|
+
return res.json()
|
|
238
|
+
})
|
|
239
|
+
console.log("res" ,res)
|
|
240
|
+
n.Noty({
|
|
241
|
+
text: `Updated!`
|
|
242
|
+
})
|
|
243
|
+
setTimeout(() => {
|
|
244
|
+
location.href = location.href
|
|
245
|
+
}, 1000)
|
|
246
|
+
})
|
|
247
|
+
})
|
|
248
|
+
</script>
|
|
249
|
+
</head>
|
|
250
|
+
<body class='<%=theme%>'>
|
|
251
|
+
<main>
|
|
252
|
+
<header class='navheader grabbable'>
|
|
253
|
+
<h1>
|
|
254
|
+
<a class='home-button home' href="/"><i class='fa-solid fa-home'></i></a>
|
|
255
|
+
<div class='flexible'></div>
|
|
256
|
+
<div class='nav-btns'>
|
|
257
|
+
<button class='btn' id='open-fs' data-filepath="<%=filepath%>"><i class="fa-solid fa-eye"></i> Open in File Explorer</button>
|
|
258
|
+
<div id='save' class='btn'>
|
|
259
|
+
<span class='save'><i class="fa-solid fa-check"></i> Save</span>
|
|
260
|
+
</div>
|
|
261
|
+
</div>
|
|
262
|
+
</h1>
|
|
263
|
+
</header>
|
|
264
|
+
<div id='editor'>
|
|
265
|
+
<% items.forEach((item) => { %>
|
|
266
|
+
<div class='env-item'>
|
|
267
|
+
<label for="<%=item.host%>"><%=item.host%></label>
|
|
268
|
+
<% item.vals.forEach((val, index) => { %>
|
|
269
|
+
<input data-host="<%=item.host%>" data-index="<%=index%>" type="text" value="<%=val%>">
|
|
270
|
+
<% }) %>
|
|
271
|
+
</div>
|
|
272
|
+
<% }) %>
|
|
273
|
+
</div>
|
|
274
|
+
</main>
|
|
275
|
+
</body>
|
|
276
|
+
</html>
|
package/server/views/network.ejs
CHANGED
|
@@ -214,13 +214,18 @@ a.ln:hover {
|
|
|
214
214
|
*/
|
|
215
215
|
padding: 10px 0;
|
|
216
216
|
}
|
|
217
|
-
#
|
|
217
|
+
#reset-label {
|
|
218
|
+
color: firebrick;
|
|
219
|
+
}
|
|
220
|
+
.link-label {
|
|
221
|
+
margin-right: 10px;
|
|
218
222
|
text-decoration: underline;
|
|
219
223
|
color: royalblue;
|
|
220
224
|
cursor: pointer;
|
|
221
225
|
}
|
|
222
226
|
.container-row table {
|
|
223
227
|
width: 100%;
|
|
228
|
+
table-layout: fixed;
|
|
224
229
|
}
|
|
225
230
|
table a {
|
|
226
231
|
text-decoration: none;
|
|
@@ -235,6 +240,7 @@ td:first-child, th:first-child {
|
|
|
235
240
|
text-transform: uppercase;
|
|
236
241
|
}
|
|
237
242
|
.container-row th {
|
|
243
|
+
vertical-align: top;
|
|
238
244
|
border-bottom: 1px solid rgba(0,0,0,0.05);
|
|
239
245
|
text-align: left;
|
|
240
246
|
padding: 20px 0;
|
|
@@ -249,6 +255,7 @@ td:first-child, th:first-child {
|
|
|
249
255
|
vertical-align: top;
|
|
250
256
|
font-size: 14px;
|
|
251
257
|
padding: 5px 2px;
|
|
258
|
+
word-wrap: break-word;
|
|
252
259
|
}
|
|
253
260
|
|
|
254
261
|
.config {
|
|
@@ -440,7 +447,8 @@ input:checked + .slider:before {
|
|
|
440
447
|
</div>
|
|
441
448
|
<div class='advanced'>
|
|
442
449
|
<div class='row'>
|
|
443
|
-
<div id='advanced-label' class='label'>Advanced</div>
|
|
450
|
+
<div id='advanced-label' class='link-label label'>Advanced</div>
|
|
451
|
+
<div id='reset-label' class='link-label label'>Reset HTTPS Certificates</div>
|
|
444
452
|
</div>
|
|
445
453
|
<!--
|
|
446
454
|
<div id='advanced-input' class='row hidden'>
|
|
@@ -595,7 +603,50 @@ input:checked + .slider:before {
|
|
|
595
603
|
</div>
|
|
596
604
|
</main>
|
|
597
605
|
<script>
|
|
606
|
+
document.querySelector("#reset-label").addEventListener("click", async (e) => {
|
|
607
|
+
e.preventDefault()
|
|
608
|
+
e.stopPropagation()
|
|
609
|
+
let ok = confirm("are you sure you want to re-generate http certificates?")
|
|
610
|
+
if (ok) {
|
|
611
|
+
let r = await fetch("/network/reset", {
|
|
612
|
+
method: "post",
|
|
613
|
+
headers: {
|
|
614
|
+
"Content-Type": "application/json"
|
|
615
|
+
}
|
|
616
|
+
}).then((res) => {
|
|
617
|
+
return res.json()
|
|
618
|
+
})
|
|
619
|
+
if (r.success) {
|
|
620
|
+
//alert("Successfully updated the pinokio home to " + val)
|
|
621
|
+
document.querySelector(".loading").classList.remove("hidden")
|
|
622
|
+
document.querySelector(".save").classList.add("hidden")
|
|
623
|
+
fetch("/restart", {
|
|
624
|
+
method: "post"
|
|
625
|
+
}, () => {
|
|
626
|
+
})
|
|
627
|
+
setInterval(async () => {
|
|
628
|
+
try {
|
|
629
|
+
let res = await fetch("/check_peer").then((res) => {
|
|
630
|
+
return res.json()
|
|
631
|
+
})
|
|
632
|
+
if (res.success) {
|
|
633
|
+
document.querySelector(".loading").classList.add("hidden")
|
|
634
|
+
location.href = location.href
|
|
635
|
+
}
|
|
636
|
+
} catch (e) {
|
|
637
|
+
console.log(e)
|
|
638
|
+
}
|
|
639
|
+
}, 1000)
|
|
640
|
+
} else if (r.error) {
|
|
641
|
+
alert(r.error)
|
|
642
|
+
location.href = location.href
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
})
|
|
598
647
|
document.querySelector("#advanced-label").addEventListener("click", (e) => {
|
|
648
|
+
e.preventDefault()
|
|
649
|
+
e.stopPropagation()
|
|
599
650
|
//document.querySelector("#advanced-input").classList.toggle("hidden")
|
|
600
651
|
Commander({
|
|
601
652
|
callback: "/network",
|
|
@@ -137,9 +137,10 @@ body.dark .badge {
|
|
|
137
137
|
font-weight: bold;
|
|
138
138
|
}
|
|
139
139
|
.folder-templates .folder img {
|
|
140
|
-
width:
|
|
141
|
-
height:
|
|
140
|
+
width: 30px;
|
|
141
|
+
height: 30px;
|
|
142
142
|
margin-right: 10px;
|
|
143
|
+
border-radius: 10px;
|
|
143
144
|
}
|
|
144
145
|
.prototype-header {
|
|
145
146
|
padding: 10px;
|
|
@@ -200,6 +200,11 @@ hr {
|
|
|
200
200
|
display: inline-block;
|
|
201
201
|
cursor: pointer;
|
|
202
202
|
}
|
|
203
|
+
.keys pre {
|
|
204
|
+
padding: 20px;
|
|
205
|
+
margin-top: 20px;
|
|
206
|
+
background: rgba(0,0,200,0.1) !important;
|
|
207
|
+
}
|
|
203
208
|
</style>
|
|
204
209
|
<script src="/hotkeys.min.js"></script>
|
|
205
210
|
<script src="/sweetalert2.js"></script>
|
|
@@ -371,6 +376,24 @@ hr {
|
|
|
371
376
|
</div>
|
|
372
377
|
</div>
|
|
373
378
|
<hr/>
|
|
379
|
+
<div class='keys'>
|
|
380
|
+
<h1>Keys</h1>
|
|
381
|
+
<br>
|
|
382
|
+
<br>
|
|
383
|
+
<div>Keys are array values stored for unique host names, stored at <code>~/pinokio/key.json</code>, and can be set through <code>pre</code> attributes in pinokio scripts. Here's an example:</div>
|
|
384
|
+
<pre>{
|
|
385
|
+
"openai.com": [
|
|
386
|
+
"sk-proj-2najBvCGFx18belpjf13T3BlbkFJIAR5KXK031n41WzAsPEn"
|
|
387
|
+
],
|
|
388
|
+
"x.com": [
|
|
389
|
+
"12345678-FAKEaccesstoken1234567890abcdef",
|
|
390
|
+
"FAKEaccesstokensecret0987654321abcdef"
|
|
391
|
+
]
|
|
392
|
+
}</pre>
|
|
393
|
+
<br>
|
|
394
|
+
<a class='btn' href="/keys"><i class="fa-solid fa-key"></i> Edit Keys</a>
|
|
395
|
+
</div>
|
|
396
|
+
<hr/>
|
|
374
397
|
<div class='advanced'>
|
|
375
398
|
<h1>Advanced Settings</h1>
|
|
376
399
|
<br>
|
package/server/views/shell.ejs
CHANGED
|
@@ -205,17 +205,32 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
205
205
|
//method: "kernel.bin.shell_start",
|
|
206
206
|
method: "kernel.bin.exec",
|
|
207
207
|
<% if (message) { %>
|
|
208
|
-
message: "
|
|
208
|
+
message: "<%-message%>",
|
|
209
209
|
<% } %>
|
|
210
210
|
<% if (venv) { %>
|
|
211
211
|
venv: "<%=venv%>",
|
|
212
212
|
<% } %>
|
|
213
|
+
<% if (kill) { %>
|
|
214
|
+
on: [{
|
|
215
|
+
event: "<%=kill%>",
|
|
216
|
+
kill: true
|
|
217
|
+
}],
|
|
218
|
+
<% } %>
|
|
219
|
+
<% if (done) { %>
|
|
220
|
+
on: [{
|
|
221
|
+
event: "<%=done%>",
|
|
222
|
+
done: true
|
|
223
|
+
}],
|
|
224
|
+
<% } %>
|
|
213
225
|
<% if (input) { %>
|
|
214
226
|
input: true,
|
|
215
227
|
<% } %>
|
|
216
228
|
<% if (env) { %>
|
|
217
229
|
env: <%-JSON.stringify(env)%>,
|
|
218
230
|
<% } %>
|
|
231
|
+
<% if (conda) { %>
|
|
232
|
+
conda: <%-JSON.stringify(conda)%>,
|
|
233
|
+
<% } %>
|
|
219
234
|
id: "<%=id%>",
|
|
220
235
|
path: "<%=cwd%>",
|
|
221
236
|
client: {
|
|
@@ -279,6 +294,9 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
279
294
|
this.write(JSON.stringify(packet.data.json2, null, 2).replace(/\n/g, "\r\n"))
|
|
280
295
|
this.write("\r\n")
|
|
281
296
|
}
|
|
297
|
+
if (packet.data.type === "shell.kill") {
|
|
298
|
+
this.socket.close()
|
|
299
|
+
}
|
|
282
300
|
document.querySelector(".play-btn").classList.add("hidden")
|
|
283
301
|
document.querySelector(".starting-btn").classList.add("hidden")
|
|
284
302
|
document.querySelector(".stop-btn").classList.remove("hidden")
|
|
@@ -437,7 +455,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
437
455
|
n.Noty(payload)
|
|
438
456
|
}
|
|
439
457
|
} else if (packet.type === "result") {
|
|
440
|
-
this.socket.close()
|
|
458
|
+
// this.socket.close()
|
|
441
459
|
} else if (packet.type === "info") {
|
|
442
460
|
n.Noty({
|
|
443
461
|
text: `${packet.data}`,
|
|
@@ -551,8 +569,22 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
551
569
|
})
|
|
552
570
|
document.querySelector(".stop-btn").classList.add("hidden")
|
|
553
571
|
document.querySelector(".stopped-btn").classList.remove("hidden")
|
|
554
|
-
<% if (
|
|
555
|
-
|
|
572
|
+
<% if (kill_message) { %>
|
|
573
|
+
n.Noty({
|
|
574
|
+
text: "<%-kill_message%>",
|
|
575
|
+
// timeout: 3000,
|
|
576
|
+
<% if (callback) { %>
|
|
577
|
+
callbacks: {
|
|
578
|
+
onClose: () => {
|
|
579
|
+
window.open("<%=callback%>", "_blank")
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
<% } %>
|
|
583
|
+
})
|
|
584
|
+
<% } else { %>
|
|
585
|
+
<% if (callback) { %>
|
|
586
|
+
location.href = "<%=callback%>"
|
|
587
|
+
<% } %>
|
|
556
588
|
<% } %>
|
|
557
589
|
})
|
|
558
590
|
})
|