pinokiod 3.86.0 → 3.87.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.
Files changed (67) hide show
  1. package/Dockerfile +61 -0
  2. package/docker-entrypoint.sh +75 -0
  3. package/kernel/api/hf/index.js +1 -1
  4. package/kernel/api/index.js +1 -1
  5. package/kernel/api/shell/index.js +6 -0
  6. package/kernel/api/terminal/index.js +166 -0
  7. package/kernel/bin/conda.js +3 -2
  8. package/kernel/bin/index.js +53 -2
  9. package/kernel/bin/setup.js +32 -0
  10. package/kernel/bin/vs.js +11 -2
  11. package/kernel/index.js +42 -2
  12. package/kernel/info.js +36 -0
  13. package/kernel/peer.js +42 -15
  14. package/kernel/router/index.js +23 -15
  15. package/kernel/router/localhost_static_router.js +0 -3
  16. package/kernel/router/pinokio_domain_router.js +333 -0
  17. package/kernel/shells.js +21 -1
  18. package/kernel/util.js +2 -2
  19. package/package.json +2 -1
  20. package/script/install-mode.js +33 -0
  21. package/script/pinokio.json +7 -0
  22. package/server/index.js +513 -173
  23. package/server/public/Socket.js +48 -0
  24. package/server/public/common.js +1441 -276
  25. package/server/public/fseditor.js +71 -12
  26. package/server/public/install.js +1 -1
  27. package/server/public/layout.js +740 -0
  28. package/server/public/modalinput.js +0 -1
  29. package/server/public/style.css +97 -105
  30. package/server/public/tab-idle-notifier.js +629 -0
  31. package/server/public/terminal_input_tracker.js +63 -0
  32. package/server/public/urldropdown.css +319 -53
  33. package/server/public/urldropdown.js +615 -159
  34. package/server/public/window_storage.js +97 -28
  35. package/server/socket.js +40 -9
  36. package/server/views/500.ejs +2 -2
  37. package/server/views/app.ejs +3136 -1367
  38. package/server/views/bookmarklet.ejs +1 -1
  39. package/server/views/bootstrap.ejs +1 -1
  40. package/server/views/columns.ejs +2 -13
  41. package/server/views/connect.ejs +3 -4
  42. package/server/views/container.ejs +1 -2
  43. package/server/views/d.ejs +223 -53
  44. package/server/views/editor.ejs +1 -1
  45. package/server/views/file_explorer.ejs +1 -1
  46. package/server/views/index.ejs +12 -11
  47. package/server/views/index2.ejs +4 -4
  48. package/server/views/init/index.ejs +4 -5
  49. package/server/views/install.ejs +1 -1
  50. package/server/views/layout.ejs +105 -0
  51. package/server/views/net.ejs +39 -7
  52. package/server/views/network.ejs +20 -6
  53. package/server/views/network2.ejs +1 -1
  54. package/server/views/old_network.ejs +2 -2
  55. package/server/views/partials/dynamic.ejs +3 -5
  56. package/server/views/partials/menu.ejs +3 -5
  57. package/server/views/partials/running.ejs +1 -1
  58. package/server/views/pro.ejs +1 -1
  59. package/server/views/prototype/index.ejs +1 -1
  60. package/server/views/review.ejs +11 -23
  61. package/server/views/rows.ejs +2 -13
  62. package/server/views/screenshots.ejs +293 -138
  63. package/server/views/settings.ejs +3 -4
  64. package/server/views/setup.ejs +1 -2
  65. package/server/views/shell.ejs +277 -26
  66. package/server/views/terminal.ejs +322 -49
  67. package/server/views/tools.ejs +448 -4
package/kernel/peer.js CHANGED
@@ -40,20 +40,26 @@ class PeerDiscovery {
40
40
  }
41
41
  }
42
42
  async check(kernel) {
43
- let env = await Environment.get(kernel.homedir, kernel)
44
- let peer_active = true
45
- //let peer_active = false
46
- if (env && env.PINOKIO_NETWORK_ACTIVE && (env.PINOKIO_NETWORK_ACTIVE==="1" || env.PINOKIO_NETWORK_ACTIVE.toLowerCase()==="true")) {
47
- //if (env && env.PINOKIO_NETWORK_ACTIVE && (env.PINOKIO_NETWORK_ACTIVE==="0" || env.PINOKIO_NETWORK_ACTIVE.toLowerCase()==="false")) {
48
- peer_active = true
49
- }
50
- //let https_active = true
51
- let https_active = false
52
- if (env && env.PINOKIO_HTTPS_ACTIVE && (env.PINOKIO_HTTPS_ACTIVE==="1" || env.PINOKIO_HTTPS_ACTIVE.toLowerCase()==="true")) {
53
- //if (env && env.PINOKIO_HTTPS_ACTIVE && (env.PINOKIO_HTTPS_ACTIVE==="0" || env.PINOKIO_HTTPS_ACTIVE.toLowerCase()==="false")) {
54
- https_active = true
55
- //https_active = false
43
+ const env = await Environment.get(kernel.homedir, kernel)
44
+ const resolveFlag = (key, fallback) => {
45
+ const fromEnvFile = env && typeof env[key] !== 'undefined' ? String(env[key]) : undefined
46
+ const fromProcess = typeof process.env[key] !== 'undefined' ? String(process.env[key]) : undefined
47
+ const value = typeof fromProcess !== 'undefined' ? fromProcess : fromEnvFile
48
+ if (typeof value === 'undefined' || value === null) {
49
+ return fallback
50
+ }
51
+ const normalized = value.trim().toLowerCase()
52
+ if (normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on') {
53
+ return true
54
+ }
55
+ if (normalized === '0' || normalized === 'false' || normalized === 'no' || normalized === 'off') {
56
+ return false
57
+ }
58
+ return fallback
56
59
  }
60
+
61
+ const peer_active = resolveFlag('PINOKIO_NETWORK_ACTIVE', true)
62
+ const https_active = resolveFlag('PINOKIO_HTTPS_ACTIVE', false)
57
63
  // console.log("kernel.refresh", { active, notify_peers })
58
64
 
59
65
  //this.name = os.userInfo().username
@@ -276,8 +282,6 @@ class PeerDiscovery {
276
282
  // let ip =
277
283
  // if (router[proc.ip]) {
278
284
  // }proc.
279
-
280
-
281
285
  let info = {
282
286
  external_router: router[external_ip] || [],
283
287
  internal_router,
@@ -286,6 +290,29 @@ class PeerDiscovery {
286
290
  internal_port: parseInt(internal_port),
287
291
  ...proc,
288
292
  }
293
+ const usingCustomDomain = this.kernel.router_kind === 'custom-domain'
294
+ if (usingCustomDomain) {
295
+ if ((!info.external_router || info.external_router.length === 0)) {
296
+ const fallbackKeys = new Set([
297
+ proc.ip,
298
+ `${internal_host}:${proc.port}`,
299
+ `127.0.0.1:${proc.port}`,
300
+ `0.0.0.0:${proc.port}`,
301
+ `localhost:${proc.port}`
302
+ ])
303
+ for (const key of fallbackKeys) {
304
+ if (key && router[key] && router[key].length > 0) {
305
+ info.external_router = router[key]
306
+ break
307
+ }
308
+ }
309
+ }
310
+ if (info.external_router && info.external_router.length > 0) {
311
+ info.external_router = Array.from(new Set(info.external_router))
312
+ } else if (internal_router.length > 0) {
313
+ info.external_router = Array.from(new Set(internal_router))
314
+ }
315
+ }
289
316
  let cached = this.router_info_cache[pid]
290
317
  let cached_str = JSON.stringify(cached)
291
318
  let info_str = JSON.stringify(info)
@@ -100,11 +100,18 @@ class Router {
100
100
  }
101
101
  }
102
102
 
103
- let env = await Environment.get(this.kernel.homedir, this.kernel)
104
- this.active = false
105
- if (env && env.PINOKIO_HTTPS_ACTIVE && (env.PINOKIO_HTTPS_ACTIVE==="1" || env.PINOKIO_HTTPS_ACTIVE.toLowerCase()==="true")) {
106
- this.active = true
107
- }
103
+ const env = await Environment.get(this.kernel.homedir, this.kernel)
104
+ const httpsFlag = (() => {
105
+ const fromEnvFile = env && typeof env.PINOKIO_HTTPS_ACTIVE !== 'undefined' ? String(env.PINOKIO_HTTPS_ACTIVE) : undefined
106
+ const fromProcess = typeof process.env.PINOKIO_HTTPS_ACTIVE !== 'undefined' ? String(process.env.PINOKIO_HTTPS_ACTIVE) : undefined
107
+ const value = typeof fromProcess !== 'undefined' ? fromProcess : fromEnvFile
108
+ if (typeof value === 'undefined') {
109
+ return false
110
+ }
111
+ const normalized = value.trim().toLowerCase()
112
+ return normalized === '1' || normalized === 'true' || normalized === 'yes' || normalized === 'on'
113
+ })()
114
+ this.active = httpsFlag
108
115
 
109
116
 
110
117
  }
@@ -217,16 +224,16 @@ class Router {
217
224
  }
218
225
 
219
226
  async static() {
220
- // this.localhost_static_router.handle()
221
- // for(let host in this.kernel.peer.info) {
222
- // let info = this.kernel.peer.info[host]
223
- // if (info.rewrite_mapping) {
224
- // for(let name in info.rewrite_mapping) {
225
- // this.peer_static_router.handle(info.rewrite_mapping[name])
226
- // }
227
- // }
228
- // }
229
- // this.mapping = this._mapping
227
+ this.localhost_static_router.handle()
228
+ for(let host in this.kernel.peer.info) {
229
+ let info = this.kernel.peer.info[host]
230
+ if (info.rewrite_mapping) {
231
+ for(let name in info.rewrite_mapping) {
232
+ this.peer_static_router.handle(info.rewrite_mapping[name])
233
+ }
234
+ }
235
+ }
236
+ this.mapping = this._mapping
230
237
  }
231
238
 
232
239
  // set local config
@@ -300,6 +307,7 @@ class Router {
300
307
  // console.log("######### caddy config has updated. refresh")
301
308
  // console.log("Old", JSON.stringify(this.old_config, null, 2))
302
309
  // console.log("New", JSON.stringify(this.config, null, 2))
310
+ console.log('[router] detected config changes, posting update to caddy (default router)')
303
311
  try {
304
312
  console.log("Try loading caddy config")
305
313
  let response = await axios.post('http://127.0.0.1:2019/load', this.config, {
@@ -12,7 +12,6 @@ class LocalhostStaticRouter extends Processor {
12
12
  this.rewriter = new Rewriter(router)
13
13
  }
14
14
  handle () {
15
- console.log("LOCALHOST STATIC ROUTER")
16
15
  let configs = []
17
16
  for(let api_name in this.router.kernel.pinokio_configs) {
18
17
  let config = this.router.kernel.pinokio_configs[api_name]
@@ -42,13 +41,11 @@ class LocalhostStaticRouter extends Processor {
42
41
  let local_dial = `${this.router.default_host}:${this.router.default_port}`
43
42
  let peer_dial = `${this.router.kernel.peer.host}:${this.router.default_port}`
44
43
  let rewrite = `/asset/api/${api_name}`
45
- console.log("LOCALHOST REWRITE HANDLE", { rewrite, localhost_match, local_dial })
46
44
  this.rewriter.handle({
47
45
  route: rewrite,
48
46
  match: [localhost_match],
49
47
  dial: local_dial,
50
48
  })
51
- console.log("LOCALHOST REWRITE HANDLE", { rewrite, peer_match, peer_dial })
52
49
  this.rewriter.handle({
53
50
  route: rewrite,
54
51
  match: [peer_match],
@@ -0,0 +1,333 @@
1
+ const axios = require('axios')
2
+ const Environment = require('../environment')
3
+ const Common = require('./common')
4
+
5
+ class PinokioDomainRouter {
6
+ constructor(kernel) {
7
+ this.kernel = kernel
8
+ this.common = new Common(this)
9
+ this.domainSuffix = ''
10
+ this.custom_routers = {}
11
+ this.resetState()
12
+ this.old_config = null
13
+ this.info = {}
14
+ this.active = false
15
+ }
16
+
17
+ resetState() {
18
+ this._mapping = {}
19
+ this.mapping = {}
20
+ this.rewrite_mapping = {}
21
+ this.port_mapping = {}
22
+ this.local_network_mapping = {}
23
+ this.port_cache = {}
24
+ }
25
+
26
+ async init() {
27
+ this.resetState()
28
+ await this.loadDomainSuffix()
29
+ this.setupBaseConfig()
30
+ }
31
+
32
+ async loadDomainSuffix() {
33
+ const envDomain = (process.env.PINOKIO_DOMAIN || '').trim()
34
+ if (envDomain) {
35
+ this.domainSuffix = envDomain.toLowerCase()
36
+ } else {
37
+ const env = await Environment.get(this.kernel.homedir, this.kernel)
38
+ this.domainSuffix = (env.PINOKIO_DOMAIN || '').trim().toLowerCase()
39
+ }
40
+ this.active = this.domainSuffix.length > 0
41
+ }
42
+
43
+ setupBaseConfig() {
44
+ this.config = {
45
+ apps: {
46
+ http: {
47
+ servers: {
48
+ main: {
49
+ listen: [':8080'],
50
+ automatic_https: {
51
+ disable: true
52
+ },
53
+ routes: [
54
+ {
55
+ match: [{ method: ['OPTIONS'] }],
56
+ handle: [
57
+ {
58
+ handler: 'headers',
59
+ response: {
60
+ set: {
61
+ 'Access-Control-Allow-Origin': ['*'],
62
+ 'Access-Control-Allow-Methods': ['GET, POST, OPTIONS, PUT, DELETE'],
63
+ 'Access-Control-Allow-Headers': ['*'],
64
+ Vary: ['Origin']
65
+ }
66
+ }
67
+ },
68
+ {
69
+ handler: 'static_response',
70
+ status_code: 204
71
+ }
72
+ ]
73
+ }
74
+ ]
75
+ }
76
+ }
77
+ }
78
+ },
79
+ logging: {
80
+ logs: {
81
+ default: {
82
+ writer: {
83
+ output: 'file',
84
+ filename: this.kernel.path('logs/caddy.log'),
85
+ roll: true,
86
+ roll_size_mb: 1,
87
+ roll_keep: 1,
88
+ roll_keep_days: 1,
89
+ roll_gzip: false,
90
+ roll_local_time: true
91
+ },
92
+ level: 'INFO'
93
+ }
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ normalizeLabel(value) {
100
+ if (!value || typeof value !== 'string') {
101
+ return ''
102
+ }
103
+ return value
104
+ .toLowerCase()
105
+ .replace(/[^a-z0-9-]/g, '-')
106
+ .replace(/-+/g, '-')
107
+ .replace(/^-|-$/g, '')
108
+ }
109
+
110
+ domainFor(apiName) {
111
+ if (!this.active) {
112
+ return null
113
+ }
114
+ const label = this.normalizeLabel(apiName)
115
+ if (!label) {
116
+ return null
117
+ }
118
+ return `${label}-${this.domainSuffix}`
119
+ }
120
+
121
+ extractPrimaryUrl(local) {
122
+ if (!local || typeof local !== 'object') {
123
+ return null
124
+ }
125
+ const preferredKeys = ['url', 'public_url', 'local_url']
126
+ for (const key of preferredKeys) {
127
+ const val = local[key]
128
+ if (typeof val === 'string' && this.isHttp(val)) {
129
+ return val
130
+ }
131
+ }
132
+
133
+ const queue = [local]
134
+ const visited = new Set()
135
+ while (queue.length > 0) {
136
+ const current = queue.shift()
137
+ if (!current || typeof current !== 'object') {
138
+ continue
139
+ }
140
+ if (visited.has(current)) {
141
+ continue
142
+ }
143
+ visited.add(current)
144
+ const iterable = Array.isArray(current) ? current : Object.values(current)
145
+ for (const val of iterable) {
146
+ if (typeof val === 'string' && this.isHttp(val)) {
147
+ return val
148
+ }
149
+ if (val && typeof val === 'object') {
150
+ queue.push(val)
151
+ }
152
+ }
153
+ }
154
+ return null
155
+ }
156
+
157
+ isHttp(value) {
158
+ return /^https?:\/\//i.test(value)
159
+ }
160
+
161
+ firstUrl(entries) {
162
+ if (!Array.isArray(entries)) {
163
+ return null
164
+ }
165
+ for (const entry of entries) {
166
+ const local = entry && entry.local
167
+ const url = this.extractPrimaryUrl(local)
168
+ if (url) {
169
+ return url
170
+ }
171
+ }
172
+ return null
173
+ }
174
+
175
+ attachRoute({ domain, url }) {
176
+ if (!domain || !url) {
177
+ return
178
+ }
179
+ let parsed
180
+ try {
181
+ parsed = new URL(url)
182
+ } catch (error) {
183
+ return
184
+ }
185
+
186
+ const isHttps = /^https:/i.test(parsed.protocol || '')
187
+ const port = parsed.port || (isHttps ? '443' : '80')
188
+ let hostname = parsed.hostname || ''
189
+ if (!hostname) {
190
+ return
191
+ }
192
+
193
+ if (hostname.includes(':') && !hostname.startsWith('[')) {
194
+ hostname = `[${hostname}]`
195
+ }
196
+
197
+ const dial = `${hostname}:${port}`
198
+ const match = domain.toLowerCase()
199
+ this.common.handle({
200
+ match,
201
+ dial,
202
+ host: this.kernel.peer.host
203
+ })
204
+ }
205
+
206
+ async local() {
207
+ if (!this.active) {
208
+ this.mapping = {}
209
+ this.info = {}
210
+ return
211
+ }
212
+
213
+ this.setupBaseConfig()
214
+
215
+ const baseDomain = this.domainSuffix ? this.domainSuffix.toLowerCase() : ''
216
+ if (baseDomain) {
217
+ this.common.handle({
218
+ match: baseDomain,
219
+ dial: '127.0.0.1:42000',
220
+ host: this.kernel.peer.host
221
+ })
222
+ }
223
+
224
+ const scriptsByApi = this.kernel.info && typeof this.kernel.info.scriptsByApi === 'function'
225
+ ? this.kernel.info.scriptsByApi()
226
+ : {}
227
+
228
+ const usedDomains = new Set()
229
+ for (const [apiName, entries] of Object.entries(scriptsByApi)) {
230
+ const domain = this.domainFor(apiName)
231
+ if (!domain || usedDomains.has(domain)) {
232
+ continue
233
+ }
234
+ const url = this.firstUrl(entries)
235
+ if (!url) {
236
+ continue
237
+ }
238
+ this.attachRoute({ domain, url })
239
+ usedDomains.add(domain)
240
+ }
241
+
242
+ this.mapping = this._mapping
243
+ this.info = this._info()
244
+ }
245
+
246
+ async remote() {
247
+ // no-op for custom domain router
248
+ }
249
+
250
+ async static() {
251
+ // no-op for custom domain router
252
+ }
253
+
254
+ async custom_domain() {
255
+ // no-op for custom domain router
256
+ }
257
+
258
+ fallback() {
259
+ // no default fallback required for custom domain router
260
+ }
261
+
262
+ add({ host, dial, match }) {
263
+ if (!this._mapping[host]) {
264
+ this._mapping[host] = {}
265
+ }
266
+ if (!this._mapping[host][dial]) {
267
+ this._mapping[host][dial] = new Set()
268
+ }
269
+ if (Array.isArray(match)) {
270
+ for (const m of match) {
271
+ this._mapping[host][dial].add(m)
272
+ }
273
+ } else {
274
+ this._mapping[host][dial].add(match)
275
+ }
276
+ }
277
+
278
+ _info() {
279
+ const mapping = {}
280
+ for (const host in this.mapping) {
281
+ const internal = this.mapping[host]
282
+ if (!mapping[host]) {
283
+ mapping[host] = {}
284
+ }
285
+ for (const url in internal) {
286
+ mapping[host][url] = Array.from(internal[url])
287
+ }
288
+ }
289
+ return mapping
290
+ }
291
+
292
+ published() {
293
+ const pub = {}
294
+ if (this.info) {
295
+ const routes = this.info[this.kernel.peer.host]
296
+ if (routes) {
297
+ for (const dial in routes) {
298
+ pub[dial] = routes[dial]
299
+ }
300
+ }
301
+ }
302
+ return pub
303
+ }
304
+
305
+ async update() {
306
+ if (JSON.stringify(this.config) === JSON.stringify(this.old_config)) {
307
+ return
308
+ }
309
+ console.log('[router] detected config changes, posting update to caddy (custom domain router)')
310
+ try {
311
+ console.log('Try loading caddy config [custom domain]')
312
+ await axios.post('http://127.0.0.1:2019/load', this.config, {
313
+ headers: { 'Content-Type': 'application/json' }
314
+ })
315
+ this.old_config = this.config
316
+ } catch (error) {
317
+ console.log('Caddy Request Failed [custom domain]', error)
318
+ }
319
+ }
320
+
321
+ async check() {
322
+ try {
323
+ const res = await axios.get('http://localhost:2019/config/', {
324
+ timeout: 2000
325
+ })
326
+ return res.data
327
+ } catch (error) {
328
+ return null
329
+ }
330
+ }
331
+ }
332
+
333
+ module.exports = PinokioDomainRouter
package/kernel/shells.js CHANGED
@@ -50,6 +50,23 @@ class Shells {
50
50
  }
51
51
 
52
52
  }
53
+ info() {
54
+ return this.shells.map((s) => {
55
+ return {
56
+ EOL: s.EOL,
57
+ shell: s.shell,
58
+ args: s.args,
59
+ cols: s.cols,
60
+ rows: s.rows,
61
+ id: s.id,
62
+ group: s.group,
63
+ start_time: s.start_time,
64
+ cmd: s.cmd,
65
+ done: s.done,
66
+ state: s.state
67
+ }
68
+ })
69
+ }
53
70
  async launch(params, options, ondata) {
54
71
  // if array, duplicate the action
55
72
  if (Array.isArray(params.message)) {
@@ -96,7 +113,10 @@ class Shells {
96
113
  let cwd = (options && options.cwd ? options.cwd : this.kernel.homedir) // if cwd exists, use it. Otherwise the cwd is pinokio home folder (~/pinokio)
97
114
  params.path = this.kernel.api.resolvePath(cwd, exec_path)
98
115
  let sh = new Shell(this.kernel)
99
- if (options) params.group = options.group // set group
116
+ if (options) {
117
+ params.group = options.group // set group
118
+ params.$title = options.title
119
+ }
100
120
 
101
121
  let m
102
122
  let matched_index
package/kernel/util.js CHANGED
@@ -212,9 +212,9 @@ const exists= (abspath) => {
212
212
  }
213
213
  const log = async (filepath, str, session) => {
214
214
  if (str && str.trim().length > 0) {
215
- try {
215
+ let e = await exists(filepath)
216
+ if (!e) {
216
217
  await fs.promises.mkdir(filepath, { recursive: true })
217
- } catch (e) {
218
218
  }
219
219
 
220
220
  let output = '';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "3.86.0",
3
+ "version": "3.87.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -68,6 +68,7 @@
68
68
  "portfinder-cp": "^1.0.34",
69
69
  "proxy-agent": "^6.5.0",
70
70
  "qrcode": "^1.5.3",
71
+ "querystring": "^0.2.1",
71
72
  "random-useragent": "^0.5.0",
72
73
  "rimraf": "^5.0.0",
73
74
  "sanitize-filename": "^1.6.3",
@@ -0,0 +1,33 @@
1
+ const path = require('path')
2
+ const Kernel = require('../kernel')
3
+
4
+ async function main() {
5
+ const mode = process.env.PINOKIO_SETUP_MODE || 'prod_dev'
6
+ const home = process.env.PINOKIO_HOME || path.resolve(process.cwd(), '.pinokio')
7
+
8
+ console.log(`[seed] mode=${mode} home=${home}`)
9
+
10
+ const kernel = new Kernel({ store: {} })
11
+ await kernel.init({})
12
+ await kernel.shell.init()
13
+ await kernel.bin.init()
14
+ await kernel.bin.refreshInstalled()
15
+
16
+ if (kernel.refresh_interval) {
17
+ clearInterval(kernel.refresh_interval)
18
+ }
19
+ kernel.server_running = true
20
+
21
+ await kernel.bin.check({ bin: kernel.bin.preset(mode) })
22
+ await kernel.bin.install({ mode }, () => {})
23
+ if (kernel.refresh_interval) {
24
+ clearInterval(kernel.refresh_interval)
25
+ }
26
+ console.log('[seed] completed')
27
+ process.exit(0)
28
+ }
29
+
30
+ main().catch((error) => {
31
+ console.error('[seed] failed', error)
32
+ process.exit(1)
33
+ })
@@ -0,0 +1,7 @@
1
+ {
2
+ "theme": "light",
3
+ "version": "3.86.0",
4
+ "HTTP_PROXY": "",
5
+ "HTTPS_PROXY": "",
6
+ "NO_PROXY": ""
7
+ }