pinokiod 3.231.0 → 3.233.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/bin/cuda.js +83 -76
- package/kernel/bin/index.js +1 -1
- package/kernel/bin/setup.js +6 -0
- package/kernel/index.js +1 -1
- package/kernel/prototype.js +13 -0
- package/kernel/router/index.js +41 -0
- package/package.json +1 -1
- package/server/index.js +95 -33
- package/server/public/container-tab-link.js +115 -0
- package/server/public/style.css +6 -0
- package/server/public/tab-link-popover.css +118 -0
- package/server/public/tab-link-popover.js +1391 -0
- package/server/views/app.ejs +78 -1625
- package/server/views/container.ejs +3 -0
- package/server/views/index.ejs +6 -0
- package/server/views/net.ejs +449 -8
- package/server/views/network.ejs +5 -3
- package/server/views/partials/dynamic.ejs +1 -1
- package/server/views/partials/menu.ejs +1 -1
- package/server/views/partials/running.ejs +1 -1
package/kernel/bin/cuda.js
CHANGED
|
@@ -3,100 +3,107 @@ const fs = require('fs')
|
|
|
3
3
|
const path = require('path')
|
|
4
4
|
class Cuda {
|
|
5
5
|
async install(req, ondata) {
|
|
6
|
-
if (this.kernel.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
for(let item of deactivate_list) {
|
|
26
|
-
const old_name = path.resolve(folder, item)
|
|
27
|
-
const new_name = path.resolve(folder, item + ".disabled")
|
|
28
|
-
console.log("rename", { old_name, new_name })
|
|
29
|
-
await fs.promises.rename(old_name, new_name)
|
|
30
|
-
}
|
|
31
|
-
} else {
|
|
32
|
-
await this.kernel.bin.exec({
|
|
33
|
-
message: [
|
|
34
|
-
"conda clean -y --all",
|
|
35
|
-
"conda install -y cudnn -c conda-forge",
|
|
36
|
-
]
|
|
37
|
-
}, ondata)
|
|
38
|
-
await this.kernel.bin.exec({
|
|
39
|
-
message: [
|
|
40
|
-
"conda clean -y --all",
|
|
41
|
-
"conda install -y nvidia/label/cuda-12.8.1::cuda"
|
|
6
|
+
if (this.kernel.gpu === "nvidia") {
|
|
7
|
+
if (this.kernel.platform === "win32") {
|
|
8
|
+
await this.kernel.bin.exec({
|
|
9
|
+
message: [
|
|
10
|
+
"conda clean -y --all",
|
|
11
|
+
"conda install -y cudnn libzlib-wapi -c conda-forge",
|
|
12
|
+
]
|
|
13
|
+
}, ondata)
|
|
14
|
+
await this.kernel.bin.exec({
|
|
15
|
+
message: [
|
|
16
|
+
"conda clean -y --all",
|
|
17
|
+
"conda install -y nvidia/label/cuda-12.8.1::cuda"
|
|
18
|
+
]
|
|
19
|
+
}, ondata)
|
|
20
|
+
const folder = this.kernel.bin.path("miniconda/etc/conda/activate.d")
|
|
21
|
+
let deactivate_list = [
|
|
22
|
+
"~cuda-nvcc_activate.bat",
|
|
23
|
+
"vs2019_compiler_vars.bat",
|
|
24
|
+
"vs2022_compiler_vars.bat",
|
|
42
25
|
]
|
|
43
|
-
|
|
44
|
-
|
|
26
|
+
for(let item of deactivate_list) {
|
|
27
|
+
const old_name = path.resolve(folder, item)
|
|
28
|
+
const new_name = path.resolve(folder, item + ".disabled")
|
|
29
|
+
console.log("rename", { old_name, new_name })
|
|
30
|
+
await fs.promises.rename(old_name, new_name)
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
45
33
|
await this.kernel.bin.exec({
|
|
46
34
|
message: [
|
|
47
|
-
"conda
|
|
35
|
+
"conda clean -y --all",
|
|
36
|
+
"conda install -y cudnn -c conda-forge",
|
|
48
37
|
]
|
|
49
38
|
}, ondata)
|
|
39
|
+
await this.kernel.bin.exec({
|
|
40
|
+
message: [
|
|
41
|
+
"conda clean -y --all",
|
|
42
|
+
"conda install -y nvidia/label/cuda-12.8.1::cuda"
|
|
43
|
+
]
|
|
44
|
+
}, ondata)
|
|
45
|
+
if (this.kernel.platform === "linux") {
|
|
46
|
+
await this.kernel.bin.exec({
|
|
47
|
+
message: [
|
|
48
|
+
"conda install -y -c conda-forge nccl"
|
|
49
|
+
]
|
|
50
|
+
}, ondata)
|
|
51
|
+
}
|
|
50
52
|
}
|
|
51
53
|
}
|
|
52
54
|
}
|
|
53
55
|
async installed() {
|
|
54
|
-
if (this.kernel.
|
|
55
|
-
if (this.kernel.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
let
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
56
|
+
if (this.kernel.gpu === "nvidia") {
|
|
57
|
+
if (this.kernel.platform === 'win32') {
|
|
58
|
+
if (this.kernel.bin.installed.conda.has("cudnn") && this.kernel.bin.installed.conda.has("cuda") && this.kernel.bin.installed.conda.has("libzlib-wapi")) {
|
|
59
|
+
let version = this.kernel.bin.installed.conda_versions.cuda
|
|
60
|
+
if (version) {
|
|
61
|
+
let coerced = semver.coerce(version)
|
|
62
|
+
console.log("cuda version", coerced)
|
|
63
|
+
if (semver.satisfies(coerced, ">=12.8.1")) {
|
|
64
|
+
console.log("cuda satisfied")
|
|
65
|
+
let deactivate_list = [
|
|
66
|
+
"~cuda-nvcc_activate.bat",
|
|
67
|
+
"vs2019_compiler_vars.bat",
|
|
68
|
+
"vs2022_compiler_vars.bat",
|
|
69
|
+
]
|
|
70
|
+
const folder = this.kernel.bin.path("miniconda/etc/conda/activate.d")
|
|
71
|
+
let at_least_one_exists = false
|
|
72
|
+
for(let item of deactivate_list) {
|
|
73
|
+
let exists = await this.kernel.exists("bin/miniconda/etc/conda/activate.d/" + item)
|
|
74
|
+
if (exists) {
|
|
75
|
+
// break if at least one exists
|
|
76
|
+
at_least_one_exists = true
|
|
77
|
+
break
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
console.log("nvcc_activate exists?", at_least_one_exists)
|
|
81
|
+
if (at_least_one_exists) {
|
|
82
|
+
return false
|
|
83
|
+
} else {
|
|
84
|
+
return true
|
|
75
85
|
}
|
|
76
86
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
if (this.kernel.bin.installed.conda.has("cudnn") && this.kernel.bin.installed.conda.has("cuda")) {
|
|
91
|
+
let version = this.kernel.bin.installed.conda_versions.cuda
|
|
92
|
+
if (version) {
|
|
93
|
+
let coerced = semver.coerce(version)
|
|
94
|
+
console.log("cuda version", coerced)
|
|
95
|
+
if (semver.satisfies(coerced, ">=12.8.1")) {
|
|
96
|
+
console.log("satisfied")
|
|
81
97
|
return true
|
|
82
98
|
}
|
|
83
99
|
}
|
|
84
100
|
}
|
|
85
101
|
}
|
|
102
|
+
return false
|
|
86
103
|
} else {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
if (version) {
|
|
90
|
-
let coerced = semver.coerce(version)
|
|
91
|
-
console.log("cuda version", coerced)
|
|
92
|
-
if (semver.satisfies(coerced, ">=12.8.1")) {
|
|
93
|
-
console.log("satisfied")
|
|
94
|
-
return true
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
104
|
+
// just return true for all other gpus so they can be avoided
|
|
105
|
+
return true
|
|
98
106
|
}
|
|
99
|
-
return false
|
|
100
107
|
}
|
|
101
108
|
env() {
|
|
102
109
|
return {
|
package/kernel/bin/index.js
CHANGED
|
@@ -625,7 +625,7 @@ class Bin {
|
|
|
625
625
|
}
|
|
626
626
|
async install2(req, ondata) {
|
|
627
627
|
let { requirements, install_required, requirements_pending, error } = await this.check({
|
|
628
|
-
bin: this.preset("
|
|
628
|
+
bin: this.preset("dev")
|
|
629
629
|
})
|
|
630
630
|
req.params = JSON.stringify(requirements)
|
|
631
631
|
if (this.install_required) {
|
package/kernel/bin/setup.js
CHANGED
|
@@ -157,13 +157,17 @@ module.exports = {
|
|
|
157
157
|
{ name: "cli", },
|
|
158
158
|
{ name: "uv", },
|
|
159
159
|
{ name: "py", },
|
|
160
|
+
{ name: "huggingface" },
|
|
161
|
+
{ name: "ffmpeg", },
|
|
160
162
|
{ name: "browserless" },
|
|
161
163
|
])
|
|
162
164
|
let conda_requirements = [
|
|
163
165
|
zip_cmd,
|
|
164
166
|
"uv",
|
|
165
167
|
"node",
|
|
168
|
+
"huggingface",
|
|
166
169
|
"git",
|
|
170
|
+
"ffmpeg",
|
|
167
171
|
]
|
|
168
172
|
return {
|
|
169
173
|
icon: "fa-solid fa-laptop-code",
|
|
@@ -188,6 +192,7 @@ module.exports = {
|
|
|
188
192
|
{ name: "uv", },
|
|
189
193
|
{ name: "caddy", },
|
|
190
194
|
{ name: "huggingface" },
|
|
195
|
+
{ name: "ffmpeg", },
|
|
191
196
|
{ name: "py", },
|
|
192
197
|
{ name: "browserless" },
|
|
193
198
|
])
|
|
@@ -197,6 +202,7 @@ module.exports = {
|
|
|
197
202
|
"node",
|
|
198
203
|
"huggingface",
|
|
199
204
|
"git",
|
|
205
|
+
"ffmpeg",
|
|
200
206
|
"caddy",
|
|
201
207
|
]
|
|
202
208
|
if (platform === "win32") {
|
package/kernel/index.js
CHANGED
package/kernel/prototype.js
CHANGED
|
@@ -109,6 +109,19 @@ class Proto {
|
|
|
109
109
|
let mod = await this.kernel.require(mod_path)
|
|
110
110
|
let response = await mod(payload, ondata, this.kernel)
|
|
111
111
|
|
|
112
|
+
if (projectType === 'dns') {
|
|
113
|
+
try {
|
|
114
|
+
await this.kernel.dns({ path: payload.cwd })
|
|
115
|
+
} catch (dnsError) {
|
|
116
|
+
console.log('[proto] dns update failed', dnsError)
|
|
117
|
+
}
|
|
118
|
+
try {
|
|
119
|
+
await this.kernel.refresh(true)
|
|
120
|
+
} catch (refreshError) {
|
|
121
|
+
console.log('[proto] refresh failed after dns create', refreshError)
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
112
125
|
// // copy readme
|
|
113
126
|
// let readme_path = this.kernel.path("prototype/PINOKIO.md")
|
|
114
127
|
// await fs.promises.cp(readme_path, path.resolve(cwd, name, "PINOKIO.md"))
|
package/kernel/router/index.js
CHANGED
|
@@ -38,6 +38,7 @@ class Router {
|
|
|
38
38
|
this.local_network_mapping = {}
|
|
39
39
|
this.custom_routers = {}
|
|
40
40
|
this.rewrite_mapping = {}
|
|
41
|
+
this.stream_close_delay = '10m'
|
|
41
42
|
}
|
|
42
43
|
async init() {
|
|
43
44
|
// if ~/pinokio/network doesn't exist, clone
|
|
@@ -258,6 +259,14 @@ class Router {
|
|
|
258
259
|
}
|
|
259
260
|
}
|
|
260
261
|
this.mapping = this._mapping
|
|
262
|
+
|
|
263
|
+
// set self origins => used for detecting all IPs resembling pinokiod itself
|
|
264
|
+
const basePort = Number(this.kernel.server_port || this.default_port)
|
|
265
|
+
const mappedPort = this.port_mapping && basePort ? Number(this.port_mapping[String(basePort)]) : null
|
|
266
|
+
const lanHost = (this.kernel.peer && this.kernel.peer.host) ? String(this.kernel.peer.host).trim() : ''
|
|
267
|
+
const hosts = ['127.0.0.1', 'localhost', lanHost].filter(Boolean)
|
|
268
|
+
const ports = [basePort, mappedPort].filter((value) => Number.isFinite(value))
|
|
269
|
+
this.kernel.selfOrigins = hosts.flatMap((host) => ports.map((port) => `${host}:${port}`))
|
|
261
270
|
}
|
|
262
271
|
|
|
263
272
|
fallback() {
|
|
@@ -299,8 +308,40 @@ class Router {
|
|
|
299
308
|
this.mapping = this._mapping
|
|
300
309
|
}
|
|
301
310
|
|
|
311
|
+
ensureStreamCloseDelay(target) {
|
|
312
|
+
const delay = this.stream_close_delay
|
|
313
|
+
if (!delay || !target) {
|
|
314
|
+
return
|
|
315
|
+
}
|
|
316
|
+
const seen = new WeakSet()
|
|
317
|
+
const visit = (node) => {
|
|
318
|
+
if (!node || (typeof node === 'object' && seen.has(node))) {
|
|
319
|
+
return
|
|
320
|
+
}
|
|
321
|
+
if (typeof node === 'object') {
|
|
322
|
+
seen.add(node)
|
|
323
|
+
}
|
|
324
|
+
if (Array.isArray(node)) {
|
|
325
|
+
for (const item of node) {
|
|
326
|
+
visit(item)
|
|
327
|
+
}
|
|
328
|
+
return
|
|
329
|
+
}
|
|
330
|
+
if (typeof node === 'object') {
|
|
331
|
+
if (node.handler === 'reverse_proxy' && typeof node.stream_close_delay === 'undefined') {
|
|
332
|
+
node.stream_close_delay = delay
|
|
333
|
+
}
|
|
334
|
+
for (const key of Object.keys(node)) {
|
|
335
|
+
visit(node[key])
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
visit(target)
|
|
340
|
+
}
|
|
341
|
+
|
|
302
342
|
// update caddy config
|
|
303
343
|
async update() {
|
|
344
|
+
this.ensureStreamCloseDelay(this.config)
|
|
304
345
|
if (JSON.stringify(this.config) === JSON.stringify(this.old_config)) {
|
|
305
346
|
// console.log("######### config hasn't updated")
|
|
306
347
|
} else {
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -441,6 +441,7 @@ class Server {
|
|
|
441
441
|
//browser_url = "/pinokio/browser/" + x.name
|
|
442
442
|
browser_url = "/p/" + x.name
|
|
443
443
|
}
|
|
444
|
+
let view_url = "/v/" + x.name
|
|
444
445
|
let dev_url = browser_url + "/dev"
|
|
445
446
|
let review_url = browser_url + "/review"
|
|
446
447
|
let files_url = "/asset/api/" + x.name
|
|
@@ -469,6 +470,7 @@ class Server {
|
|
|
469
470
|
url: browser_url,
|
|
470
471
|
path: uri,
|
|
471
472
|
dev_url,
|
|
473
|
+
view_url,
|
|
472
474
|
review_url,
|
|
473
475
|
files_url,
|
|
474
476
|
}
|
|
@@ -703,16 +705,14 @@ class Server {
|
|
|
703
705
|
// return current_urls
|
|
704
706
|
}
|
|
705
707
|
|
|
706
|
-
async chrome(req, res, type) {
|
|
708
|
+
async chrome(req, res, type, options) {
|
|
707
709
|
|
|
708
710
|
let d = Date.now()
|
|
709
711
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
710
|
-
|
|
711
|
-
bin: this.kernel.bin.preset("ai"),
|
|
712
|
+
bin: this.kernel.bin.preset("dev"),
|
|
712
713
|
})
|
|
713
714
|
if (!requirements_pending && install_required) {
|
|
714
|
-
|
|
715
|
-
res.redirect(`/setup/ai?callback=${req.originalUrl}`)
|
|
715
|
+
res.redirect(`/setup/dev?callback=${req.originalUrl}`)
|
|
716
716
|
return
|
|
717
717
|
}
|
|
718
718
|
|
|
@@ -850,7 +850,20 @@ class Server {
|
|
|
850
850
|
dev_link = "/d/" + posix_path
|
|
851
851
|
}
|
|
852
852
|
|
|
853
|
-
let
|
|
853
|
+
let autoselect
|
|
854
|
+
let run_tab
|
|
855
|
+
if (type === "run") {
|
|
856
|
+
if (options && options.no_autoselect) {
|
|
857
|
+
run_tab = "/v/" + name
|
|
858
|
+
autoselect = false
|
|
859
|
+
} else {
|
|
860
|
+
run_tab = "/p/" + name
|
|
861
|
+
autoselect = true
|
|
862
|
+
}
|
|
863
|
+
} else {
|
|
864
|
+
run_tab = "/p/" + name
|
|
865
|
+
autoselect = false
|
|
866
|
+
}
|
|
854
867
|
let dev_tab = "/p/" + name + "/dev"
|
|
855
868
|
let review_tab = "/p/" + name + "/review"
|
|
856
869
|
let files_tab = "/p/" + name + "/files"
|
|
@@ -889,6 +902,7 @@ class Server {
|
|
|
889
902
|
port: this.port,
|
|
890
903
|
// mem,
|
|
891
904
|
type,
|
|
905
|
+
autoselect,
|
|
892
906
|
platform,
|
|
893
907
|
running:this.kernel.api.running,
|
|
894
908
|
memory: this.kernel.memory,
|
|
@@ -1429,7 +1443,7 @@ class Server {
|
|
|
1429
1443
|
})
|
|
1430
1444
|
} else if (pathComponents.length === 0 && req.query.mode === "download") {
|
|
1431
1445
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
1432
|
-
bin: this.kernel.bin.preset("
|
|
1446
|
+
bin: this.kernel.bin.preset("dev"),
|
|
1433
1447
|
})
|
|
1434
1448
|
let sanitizedPath = null
|
|
1435
1449
|
if (typeof req.query.path === 'string') {
|
|
@@ -1677,12 +1691,29 @@ class Server {
|
|
|
1677
1691
|
template = "editor"
|
|
1678
1692
|
}
|
|
1679
1693
|
|
|
1694
|
+
let requires_bundle = null
|
|
1695
|
+
if (resolved && resolved.requires && !Array.isArray(resolved.requires)) {
|
|
1696
|
+
const bundle = resolved.requires.bundle
|
|
1697
|
+
if (typeof bundle === "string" && typeof Setup[bundle] === "function") {
|
|
1698
|
+
requires_bundle = bundle
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
const preset = requires_bundle ? this.kernel.bin.preset(requires_bundle) : this.kernel.bin.preset("dev")
|
|
1680
1703
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
1681
|
-
|
|
1682
|
-
bin: this.kernel.bin.preset("dev"),
|
|
1704
|
+
bin: preset,
|
|
1683
1705
|
script: resolved
|
|
1684
1706
|
})
|
|
1685
1707
|
|
|
1708
|
+
if (requires_bundle) {
|
|
1709
|
+
console.log({ requires_bundle, requirements_pending, install_required, })
|
|
1710
|
+
}
|
|
1711
|
+
|
|
1712
|
+
if (requires_bundle && !requirements_pending && install_required) {
|
|
1713
|
+
res.redirect(`/setup/${requires_bundle}?callback=${req.originalUrl}`)
|
|
1714
|
+
return
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1686
1717
|
//let requirements = this.kernel.bin.requirements(resolved)
|
|
1687
1718
|
//let requirements_pending = !this.kernel.bin.installed_initialized
|
|
1688
1719
|
//let install_required = true
|
|
@@ -3019,7 +3050,8 @@ class Server {
|
|
|
3019
3050
|
}
|
|
3020
3051
|
} else {
|
|
3021
3052
|
this.colors = {
|
|
3022
|
-
color: "white",
|
|
3053
|
+
//color: "white",
|
|
3054
|
+
color: "#F4F4F4",
|
|
3023
3055
|
// color: "#F5F4FA",
|
|
3024
3056
|
symbolColor: "black",
|
|
3025
3057
|
}
|
|
@@ -3368,7 +3400,7 @@ class Server {
|
|
|
3368
3400
|
]
|
|
3369
3401
|
pushEntry({
|
|
3370
3402
|
host: hostMeta,
|
|
3371
|
-
name: `[
|
|
3403
|
+
name: `[Website] ${rewrite.name || key}`,
|
|
3372
3404
|
ip: externalIp || null,
|
|
3373
3405
|
httpUrl: externalIp,
|
|
3374
3406
|
httpsUrls: Array.from(new Set(httpsSources))
|
|
@@ -3401,26 +3433,26 @@ class Server {
|
|
|
3401
3433
|
})
|
|
3402
3434
|
}
|
|
3403
3435
|
|
|
3404
|
-
const installedApps = Array.isArray(hostInfo.installed) ? hostInfo.installed : []
|
|
3405
|
-
for (const app of installedApps) {
|
|
3406
|
-
if (!app) {
|
|
3407
|
-
continue
|
|
3408
|
-
}
|
|
3409
|
-
const httpHref = Array.isArray(app.http_href) ? app.http_href[0] : app.http_href
|
|
3410
|
-
const httpsCandidates = Array.from(new Set([
|
|
3411
|
-
...ensureArray(app.app_href),
|
|
3412
|
-
...ensureArray(app.https_href)
|
|
3413
|
-
]))
|
|
3414
|
-
pushEntry({
|
|
3415
|
-
host: hostMeta,
|
|
3416
|
-
name: app.title || app.name || app.folder,
|
|
3417
|
-
ip: httpHref ? httpHref.replace(/^https?:\/\//i, '') : null,
|
|
3418
|
-
httpUrl: httpHref || null,
|
|
3419
|
-
httpsUrls: httpsCandidates,
|
|
3420
|
-
description: app.description,
|
|
3421
|
-
icon: app.https_icon || app.http_icon || app.icon
|
|
3422
|
-
})
|
|
3423
|
-
}
|
|
3436
|
+
// const installedApps = Array.isArray(hostInfo.installed) ? hostInfo.installed : []
|
|
3437
|
+
// for (const app of installedApps) {
|
|
3438
|
+
// if (!app) {
|
|
3439
|
+
// continue
|
|
3440
|
+
// }
|
|
3441
|
+
// const httpHref = Array.isArray(app.http_href) ? app.http_href[0] : app.http_href
|
|
3442
|
+
// const httpsCandidates = Array.from(new Set([
|
|
3443
|
+
// ...ensureArray(app.app_href),
|
|
3444
|
+
// ...ensureArray(app.https_href)
|
|
3445
|
+
// ]))
|
|
3446
|
+
// pushEntry({
|
|
3447
|
+
// host: hostMeta,
|
|
3448
|
+
// name: app.title || app.name || app.folder,
|
|
3449
|
+
// ip: httpHref ? httpHref.replace(/^https?:\/\//i, '') : null,
|
|
3450
|
+
// httpUrl: httpHref || null,
|
|
3451
|
+
// httpsUrls: httpsCandidates,
|
|
3452
|
+
// description: app.description,
|
|
3453
|
+
// icon: app.https_icon || app.http_icon || app.icon
|
|
3454
|
+
// })
|
|
3455
|
+
// }
|
|
3424
3456
|
}
|
|
3425
3457
|
}
|
|
3426
3458
|
async terminals(filepath) {
|
|
@@ -3728,6 +3760,7 @@ class Server {
|
|
|
3728
3760
|
|
|
3729
3761
|
|
|
3730
3762
|
await this.kernel.init({ port: this.port})
|
|
3763
|
+
this.kernel.server_port = this.port
|
|
3731
3764
|
this.kernel.peer.start(this.kernel)
|
|
3732
3765
|
|
|
3733
3766
|
|
|
@@ -5494,6 +5527,18 @@ class Server {
|
|
|
5494
5527
|
requirements_pending,
|
|
5495
5528
|
})
|
|
5496
5529
|
}))
|
|
5530
|
+
this.app.get("/net/:name/diff", ex(async (req, res) => {
|
|
5531
|
+
try {
|
|
5532
|
+
let processes = this.kernel.peer.info[this.kernel.peer.host].router_info
|
|
5533
|
+
let last_proc = JSON.stringify(this.kernel.last_processes)
|
|
5534
|
+
let current_proc = JSON.stringify(processes)
|
|
5535
|
+
this.kernel.last_processes = processes
|
|
5536
|
+
res.json({ diff: last_proc !== current_proc })
|
|
5537
|
+
} catch (e) {
|
|
5538
|
+
console.log("ERROR", e)
|
|
5539
|
+
res.json({ diff: true })
|
|
5540
|
+
}
|
|
5541
|
+
}))
|
|
5497
5542
|
this.app.get("/net/:name", ex(async (req, res) => {
|
|
5498
5543
|
let protocol = req.get('X-Forwarded-Proto') || "http"
|
|
5499
5544
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
@@ -5547,6 +5592,7 @@ class Server {
|
|
|
5547
5592
|
const peer_url = `http://${this.kernel.peer.host}:${DEFAULT_PORT}`
|
|
5548
5593
|
let peer_qr = null
|
|
5549
5594
|
try { peer_qr = await QRCode.toDataURL(peer_url) } catch (_) {}
|
|
5595
|
+
const allow_dns_creation = req.params.name === this.kernel.peer.name
|
|
5550
5596
|
res.render("net", {
|
|
5551
5597
|
static_routes,
|
|
5552
5598
|
selected_name: req.params.name,
|
|
@@ -5567,6 +5613,8 @@ class Server {
|
|
|
5567
5613
|
current_host: this.kernel.peer.host,
|
|
5568
5614
|
peer_url,
|
|
5569
5615
|
peer_qr,
|
|
5616
|
+
cwd: this.kernel.path("api"),
|
|
5617
|
+
allow_dns_creation,
|
|
5570
5618
|
})
|
|
5571
5619
|
}))
|
|
5572
5620
|
this.app.get("/network", ex(async (req, res) => {
|
|
@@ -7103,7 +7151,13 @@ class Server {
|
|
|
7103
7151
|
return hosts[0]
|
|
7104
7152
|
}
|
|
7105
7153
|
|
|
7106
|
-
const
|
|
7154
|
+
const processes = Array.isArray(this.kernel.processes.info) ? this.kernel.processes.info : []
|
|
7155
|
+
const serverPid = Number(process.pid)
|
|
7156
|
+
const filteredProcesses = Number.isFinite(serverPid)
|
|
7157
|
+
? processes.filter((item) => Number(item && item.pid) !== serverPid)
|
|
7158
|
+
: processes.slice()
|
|
7159
|
+
|
|
7160
|
+
let info = filteredProcesses.map((item) => {
|
|
7107
7161
|
const httpUrl = item.ip ? `http://${item.ip}` : null
|
|
7108
7162
|
let httpsHosts = []
|
|
7109
7163
|
if (preferHttps) {
|
|
@@ -7149,6 +7203,12 @@ class Server {
|
|
|
7149
7203
|
|
|
7150
7204
|
this.add_extra_urls(info)
|
|
7151
7205
|
|
|
7206
|
+
if (Array.isArray(this.kernel.selfOrigins) && this.kernel.selfOrigins.length > 0) {
|
|
7207
|
+
info = info.filter((entry) => {
|
|
7208
|
+
return !this.kernel.selfOrigins.includes(entry.ip)
|
|
7209
|
+
})
|
|
7210
|
+
}
|
|
7211
|
+
|
|
7152
7212
|
const toArray = (value) => {
|
|
7153
7213
|
if (!value) return []
|
|
7154
7214
|
return Array.isArray(value) ? value.filter(Boolean) : [value].filter(Boolean)
|
|
@@ -7429,7 +7489,9 @@ class Server {
|
|
|
7429
7489
|
this.app.get("/pinokio/browser/:name", ex(async (req, res) => {
|
|
7430
7490
|
await this.chrome(req, res, "run")
|
|
7431
7491
|
}))
|
|
7432
|
-
|
|
7492
|
+
this.app.get("/v/:name", ex(async (req, res) => {
|
|
7493
|
+
await this.chrome(req, res, "run", { no_autoselect: true })
|
|
7494
|
+
}))
|
|
7433
7495
|
|
|
7434
7496
|
this.app.get("/p/:name/review", ex(async (req, res) => {
|
|
7435
7497
|
let gitRemote = null
|