pinokiod 7.2.11 → 7.2.13

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 (54) hide show
  1. package/Dockerfile +0 -2
  2. package/kernel/api/index.js +14 -1
  3. package/kernel/api/process/index.js +99 -44
  4. package/kernel/api/uri/index.js +51 -0
  5. package/kernel/environment.js +22 -3
  6. package/kernel/git.js +0 -13
  7. package/kernel/index.js +61 -1
  8. package/kernel/plugin.js +6 -58
  9. package/kernel/plugin_sources.js +236 -0
  10. package/kernel/util.js +60 -0
  11. package/package.json +1 -1
  12. package/server/features/drafts/public/drafts.js +35 -12
  13. package/server/index.js +120 -142
  14. package/server/lib/content_validation.js +28 -25
  15. package/server/public/common.js +95 -29
  16. package/server/public/create-launcher.js +4 -31
  17. package/server/public/electron.css +1 -1
  18. package/server/public/style.css +337 -0
  19. package/server/public/task-launcher.js +5 -32
  20. package/server/public/universal-launcher.js +3 -26
  21. package/server/views/app.ejs +8 -29
  22. package/server/views/d.ejs +0 -33
  23. package/server/views/editor.ejs +25 -4
  24. package/server/views/shell.ejs +11 -3
  25. package/server/views/terminal.ejs +15 -3
  26. package/spec/INSTRUCTION_SYNC.md +5 -5
  27. package/system/plugin/antigravity/antigravity.png +0 -0
  28. package/system/plugin/antigravity/pinokio.js +37 -0
  29. package/system/plugin/claude/claude.png +0 -0
  30. package/system/plugin/claude/pinokio.js +63 -0
  31. package/system/plugin/claude-auto/claude.png +0 -0
  32. package/system/plugin/claude-auto/pinokio.js +74 -0
  33. package/system/plugin/claude-desktop/icon.jpeg +0 -0
  34. package/system/plugin/claude-desktop/pinokio.js +39 -0
  35. package/system/plugin/codex/openai.webp +0 -0
  36. package/system/plugin/codex/pinokio.js +58 -0
  37. package/system/plugin/codex-auto/openai.webp +0 -0
  38. package/system/plugin/codex-auto/pinokio.js +65 -0
  39. package/system/plugin/codex-desktop/icon.png +0 -0
  40. package/system/plugin/codex-desktop/pinokio.js +39 -0
  41. package/system/plugin/crush/crush.png +0 -0
  42. package/system/plugin/crush/pinokio.js +31 -0
  43. package/system/plugin/cursor/cursor.jpeg +0 -0
  44. package/system/plugin/cursor/pinokio.js +39 -0
  45. package/system/plugin/gemini/gemini.jpeg +0 -0
  46. package/system/plugin/gemini/pinokio.js +40 -0
  47. package/system/plugin/gemini-auto/gemini.jpeg +0 -0
  48. package/system/plugin/gemini-auto/pinokio.js +43 -0
  49. package/system/plugin/qwen/pinokio.js +50 -0
  50. package/system/plugin/qwen/qwen.png +0 -0
  51. package/system/plugin/vscode/pinokio.js +36 -0
  52. package/system/plugin/vscode/vscode.png +0 -0
  53. package/system/plugin/windsurf/pinokio.js +39 -0
  54. package/system/plugin/windsurf/windsurf.png +0 -0
package/Dockerfile CHANGED
@@ -37,8 +37,6 @@ RUN mkdir -p /app/.pinokio-seed \
37
37
  && rm -rf /app/.pinokio-seed/network/system/.git \
38
38
  && rm -rf /app/.pinokio-seed/plugin \
39
39
  && mkdir -p /app/.pinokio-seed/plugin \
40
- && git clone --depth 1 https://github.com/pinokiocomputer/code /app/.pinokio-seed/plugin/code \
41
- && rm -rf /app/.pinokio-seed/plugin/code/.git \
42
40
  && rm -rf /app/.pinokio-seed/prototype/system \
43
41
  && mkdir -p /app/.pinokio-seed/prototype \
44
42
  && git clone --depth 1 https://github.com/pinokiocomputer/proto /app/.pinokio-seed/prototype/system \
@@ -29,6 +29,19 @@ class Api {
29
29
  this.child_procs = {}
30
30
  this.lproxy = new Lproxy()
31
31
  }
32
+ startData(rpc) {
33
+ if (rpc && rpc.method === "process.wait" && rpc.params && typeof rpc.params === "object" && !Array.isArray(rpc.params)) {
34
+ let data = rpc
35
+ if (typeof data.title === "undefined" && typeof rpc.params.title !== "undefined") {
36
+ data = { ...data, title: rpc.params.title }
37
+ }
38
+ if (typeof data.description === "undefined" && typeof rpc.params.description !== "undefined") {
39
+ data = { ...data, description: rpc.params.description }
40
+ }
41
+ return data
42
+ }
43
+ return rpc
44
+ }
32
45
  async launcher_path(name) {
33
46
  let root_path = this.kernel.path("api", name)
34
47
  let primary_path = path.resolve(root_path, "pinokio.js")
@@ -1186,7 +1199,7 @@ class Api {
1186
1199
  this.ondata({
1187
1200
  id: request.id || request.path,
1188
1201
  type: "start",
1189
- data: rpc
1202
+ data: this.startData(rpc)
1190
1203
  })
1191
1204
 
1192
1205
  // DEPRECATED APIS
@@ -34,6 +34,16 @@ class Process {
34
34
  constructor() {
35
35
  this.appApi = new AppAPI()
36
36
  }
37
+ async waitIndefinitely(req, kernel) {
38
+ await new Promise((resolve, reject) => {
39
+ this.resolve = resolve
40
+
41
+ // register the process with the root uri so it can be manually resolved (with this.resolve()) later
42
+ if (kernel && kernel.procs && req && req.parent && req.parent.path) {
43
+ kernel.procs[req.parent.path] = this
44
+ }
45
+ })
46
+ }
37
47
  // async start(req, ondata, kernel) {
38
48
  // /*
39
49
  // req := {
@@ -159,6 +169,8 @@ class Process {
159
169
  /*
160
170
  params := {
161
171
  sec: <SECONDS>,
172
+ title: (optional) Title to display in the footer while waiting,
173
+ description: (optional) Description to display in the footer while waiting,
162
174
  message: (optional) Description to display while waiting,
163
175
  menu: (optional) menu to display in the modal while waiting,
164
176
  // ok: (optional) <ok button text> (if not specified, no ok button),
@@ -169,6 +181,8 @@ class Process {
169
181
 
170
182
  params := {
171
183
  min: <MINUTES>,
184
+ title: (optional) Title to display in the footer while waiting,
185
+ description: (optional) Description to display in the footer while waiting,
172
186
  message: (optional) Description to display while waiting,
173
187
  menu: (optional) menu to display in the modal while waiting,
174
188
  // ok: (optional) <ok button text> (if not specified, no ok button),
@@ -180,6 +194,8 @@ class Process {
180
194
  params := {
181
195
  url: <URL>,
182
196
  interval: (optional) how often to retry checking (in seconds)
197
+ title: (optional) Title to display in the footer while waiting,
198
+ description: (optional) Description to display in the footer while waiting,
183
199
  message: (optional) the message to display while retrying (default: no message)
184
200
  }
185
201
 
@@ -198,9 +214,21 @@ class Process {
198
214
 
199
215
  or
200
216
 
217
+ params := {
218
+ title: (optional) Title to display in the footer while waiting,
219
+ description: (optional) Description to display in the footer while waiting,
220
+ }
221
+
222
+ This waits indefinitely until the script is stopped or the wait is manually
223
+ resolved.
224
+
225
+ or
226
+
201
227
 
202
228
  params := {
203
229
  on: <wait-on condition https://github.com/jeffbski/wait-on>,
230
+ title: (optional) Title to display in the footer while waiting,
231
+ description: (optional) Description to display in the footer while waiting,
204
232
  message: (optional) Description to display while waiting,
205
233
  menu: (optional) menu to display in the modal while waiting,
206
234
  // ok: (optional) <ok button text> (if not specified, no ok button),
@@ -212,57 +240,84 @@ class Process {
212
240
  if 'cancel' is pressed before the condition is met, stops the script
213
241
 
214
242
  */
215
- let ms
216
- if (req.params) {
217
- if (req.params.app || req.params.id || req.params.name) {
218
- await this.appApi.waitForAppPresence(req, ondata, kernel)
219
- return
243
+ let ms
244
+ const waitPath = req && req.parent && req.parent.path
245
+ if (waitPath && kernel) {
246
+ if (!kernel.activeProcessWaits) {
247
+ kernel.activeProcessWaits = {}
220
248
  }
221
- // Display modal
222
- if (req.params.sec || req.params.min) {
223
- // Wait
224
- if (req.params.sec) {
225
- ms = req.params.sec * 1000
226
- } else if (req.params.min) {
227
- ms = req.params.min * 60 * 1000
249
+ kernel.activeProcessWaits[waitPath] = {
250
+ path: waitPath,
251
+ params: req.params || {},
252
+ title: req.params && req.params.title,
253
+ description: req.params && req.params.description,
254
+ message: req.params && req.params.message,
255
+ started: Date.now()
256
+ }
257
+ }
258
+ const showFooter = req.params && (req.params.title || req.params.description)
259
+ if (showFooter && typeof ondata === "function") {
260
+ ondata(req.params, "process.wait.start")
261
+ }
262
+ try {
263
+ if (req.params) {
264
+ if (req.params.app || req.params.id || req.params.name) {
265
+ await this.appApi.waitForAppPresence(req, ondata, kernel)
266
+ return
228
267
  }
229
- await new Promise((resolve, reject) => {
230
- this.resolve = resolve
268
+ // Display modal
269
+ if (req.params.sec || req.params.min) {
270
+ // Wait
271
+ if (req.params.sec) {
272
+ ms = req.params.sec * 1000
273
+ } else if (req.params.min) {
274
+ ms = req.params.min * 60 * 1000
275
+ }
276
+ await new Promise((resolve, reject) => {
277
+ this.resolve = resolve
231
278
 
232
- // register the process with the root uri so it can be manually resolved (with this.resolve()) later
233
- kernel.procs[req.parent.path] = this
279
+ // register the process with the root uri so it can be manually resolved (with this.resolve()) later
280
+ kernel.procs[req.parent.path] = this
234
281
 
235
- setTimeout(() => {
236
- this.resolve()
237
- }, ms)
238
- })
239
- } else if (req.params.uri) {
240
- let interval = req.params.interval ? req.params.interval * 1000 : 1000
241
- ondata(req.params, "loading.start")
242
- await waitForUrl(req.params.uri, req.params.message, interval, ondata)
243
- ondata(req.params, "loading.end")
244
- } else if (req.params.url) {
245
- let interval = req.params.interval ? req.params.interval * 1000 : 1000
246
- ondata(req.params, "loading.start")
247
- await waitForUrl(req.params.url, req.params.message, interval, ondata)
248
- ondata(req.params, "loading.end")
249
- } else if (req.params.on) {
250
- // Wait
251
- if (req.params.message) {
252
- ondata({
253
- raw: `\r\nWaiting: ${JSON.stringify(req.params.on)}\r\n`
282
+ setTimeout(() => {
283
+ this.resolve()
284
+ }, ms)
254
285
  })
255
- ondata(req.params, "wait")
286
+ } else if (req.params.uri) {
287
+ let interval = req.params.interval ? req.params.interval * 1000 : 1000
288
+ ondata(req.params, "loading.start")
289
+ await waitForUrl(req.params.uri, req.params.message, interval, ondata)
290
+ ondata(req.params, "loading.end")
291
+ } else if (req.params.url) {
292
+ let interval = req.params.interval ? req.params.interval * 1000 : 1000
293
+ ondata(req.params, "loading.start")
294
+ await waitForUrl(req.params.url, req.params.message, interval, ondata)
295
+ ondata(req.params, "loading.end")
296
+ } else if (req.params.on) {
297
+ // Wait
298
+ if (req.params.message) {
299
+ ondata({
300
+ raw: `\r\nWaiting: ${JSON.stringify(req.params.on)}\r\n`
301
+ })
302
+ ondata(req.params, "wait")
303
+ }
304
+ console.log("Wait", req.params.on)
305
+ await waitOn(req.params.on)
306
+ console.log("Wait finished")
307
+ ondata(req.params, "wait.end")
308
+ } else {
309
+ await this.waitIndefinitely(req, kernel)
256
310
  }
257
- console.log("Wait", req.params.on)
258
- await waitOn(req.params.on)
259
- console.log("Wait finished")
260
- ondata(req.params, "wait.end")
311
+ } else {
312
+ await this.waitIndefinitely(req, kernel)
313
+ }
314
+ } finally {
315
+ if (waitPath && kernel && kernel.activeProcessWaits) {
316
+ delete kernel.activeProcessWaits[waitPath]
317
+ }
318
+ if (showFooter && typeof ondata === "function") {
319
+ ondata(req.params, "process.wait.end")
261
320
  }
262
- } else {
263
- await new Promise((resolve, reject) => {
264
- this.resolve = resolve
265
- })
266
321
  }
267
322
  }
268
323
  }
@@ -0,0 +1,51 @@
1
+ const Util = require('../../util')
2
+
3
+ const appendQueryParams = (uri, params) => {
4
+ if (!params || typeof params !== 'object' || Array.isArray(params)) {
5
+ return uri
6
+ }
7
+
8
+ const entries = []
9
+ for (const [key, value] of Object.entries(params)) {
10
+ const values = Array.isArray(value) ? value : [value]
11
+ for (const item of values) {
12
+ if (item === undefined || item === null) {
13
+ continue
14
+ }
15
+ const serialized = typeof item === 'object' ? JSON.stringify(item) : String(item)
16
+ entries.push(`${encodeURIComponent(key)}=${encodeURIComponent(serialized)}`)
17
+ }
18
+ }
19
+
20
+ if (entries.length === 0) {
21
+ return uri
22
+ }
23
+
24
+ const hashIndex = uri.indexOf('#')
25
+ const base = hashIndex === -1 ? uri : uri.slice(0, hashIndex)
26
+ const hash = hashIndex === -1 ? '' : uri.slice(hashIndex)
27
+ const separator = base.includes('?')
28
+ ? (base.endsWith('?') || base.endsWith('&') ? '' : '&')
29
+ : '?'
30
+
31
+ return `${base}${separator}${entries.join('&')}${hash}`
32
+ }
33
+
34
+ class URI {
35
+ build(params = {}) {
36
+ const uri = typeof params.uri === 'string' ? params.uri.trim() : ''
37
+ if (!uri) {
38
+ throw new Error('uri.open requires params.uri')
39
+ }
40
+ return appendQueryParams(uri, params.params)
41
+ }
42
+
43
+ async open(req, ondata, kernel) {
44
+ const uri = this.build(req.params)
45
+ ondata({ raw: `\r\nopening uri: ${uri}\r\n` })
46
+ const result = await Util.openURI(uri)
47
+ return { uri, result }
48
+ }
49
+ }
50
+
51
+ module.exports = URI
@@ -72,7 +72,7 @@ const managedCacheEnvDefaults = () => {
72
72
  return defaults
73
73
  }
74
74
 
75
- const ensureCachePreflightDir = async (key, targetPath) => {
75
+ const ensureCachePreflightDir = async (key, targetPath, options = {}) => {
76
76
  logCachePreflight(`${key}: target=${targetPath}`)
77
77
  try {
78
78
  await fs.promises.mkdir(targetPath, { recursive: true })
@@ -95,7 +95,26 @@ const ensureCachePreflightDir = async (key, targetPath) => {
95
95
  logCachePreflight(`${key}: repair delete ok`)
96
96
  } catch (error) {
97
97
  logCachePreflight(`${key}: repair delete failed ${formatCachePreflightError(error)}`)
98
- return { key, path: targetPath, repaired: false, ok: false, step: "repair delete", error }
98
+ if (typeof options.elevatedRepair !== "function") {
99
+ return { key, path: targetPath, repaired: false, ok: false, step: "repair delete", error }
100
+ }
101
+ logCachePreflight(`${key}: elevated repair start path=${targetPath}`)
102
+ let elevatedRepair
103
+ try {
104
+ elevatedRepair = await options.elevatedRepair(targetPath, logCachePreflight)
105
+ } catch (repairError) {
106
+ elevatedRepair = { ok: false, error: repairError }
107
+ }
108
+ if (!elevatedRepair || !elevatedRepair.ok) {
109
+ return { key, path: targetPath, repaired: false, elevated: true, ok: false, step: "elevated repair", error: elevatedRepair && elevatedRepair.error ? elevatedRepair.error : error }
110
+ }
111
+ const elevatedProbe = await probeCacheDir(targetPath)
112
+ if (elevatedProbe.ok) {
113
+ logCachePreflight(`${key}: elevated repair probe ok`)
114
+ return { key, path: targetPath, repaired: true, elevated: true, ok: true }
115
+ }
116
+ logCachePreflight(`${key}: elevated repair probe failed step="${elevatedProbe.step}" ${formatCachePreflightError(elevatedProbe.error)}`)
117
+ return { key, path: targetPath, repaired: true, elevated: true, ok: false, step: elevatedProbe.step, error: elevatedProbe.error }
99
118
  }
100
119
 
101
120
  try {
@@ -140,7 +159,7 @@ const ensurePinokioCacheDirs = async (kernel, options = {}) => {
140
159
 
141
160
  for (const key of CACHE_PREFLIGHT_KEYS) {
142
161
  const targetPath = path.resolve(cacheRoot, key)
143
- const result = await ensureCachePreflightDir(key, targetPath)
162
+ const result = await ensureCachePreflightDir(key, targetPath, options)
144
163
  results.push(result)
145
164
  if (!result.ok) {
146
165
  errors.push(result)
package/kernel/git.js CHANGED
@@ -1378,19 +1378,6 @@ class Git {
1378
1378
  const absoluteTarget = path.resolve(targetPath)
1379
1379
  const home = path.resolve(this.kernel.homedir)
1380
1380
  const managedTargets = [
1381
- {
1382
- kind: "plugin",
1383
- root: path.resolve(home, "plugin/code"),
1384
- matches: (root, target) => target === root || target.startsWith(`${root}${path.sep}`),
1385
- bootstrap: async () => {
1386
- await fs.promises.rm(path.resolve(home, "plugin/code"), { recursive: true, force: true })
1387
- this.dirs.delete(path.resolve(home, "plugin/code"))
1388
- if (this.kernel.plugin && typeof this.kernel.plugin.init === "function") {
1389
- await this.kernel.plugin.init()
1390
- }
1391
- },
1392
- exists: async () => this.kernel.exists("plugin/code")
1393
- },
1394
1381
  {
1395
1382
  kind: "prototype",
1396
1383
  root: path.resolve(home, "prototype/system"),
package/kernel/index.js CHANGED
@@ -44,6 +44,7 @@ const WatchManager = require('./watch')
44
44
  const { DownloaderHelper } = require('node-downloader-helper');
45
45
  const { ProxyAgent } = require('proxy-agent');
46
46
  const fakeUa = require('fake-useragent');
47
+ const sudo = process.platform === "win32" ? require("sudo-prompt-programfiles-x86") : null
47
48
  //const kill = require('./tree-kill');
48
49
  const kill = require('kill-sync')
49
50
  const ejs = require('ejs');
@@ -55,6 +56,34 @@ const VARS = {
55
56
  }
56
57
  }
57
58
 
59
+ const powershellSingleQuote = (value) => {
60
+ return `'${String(value).replace(/'/g, "''")}'`
61
+ }
62
+
63
+ const windowsCacheRepairCommand = (targetPath) => {
64
+ const psPath = powershellSingleQuote(targetPath)
65
+ return [
66
+ "powershell.exe",
67
+ "-NoProfile",
68
+ "-ExecutionPolicy Bypass",
69
+ "-Command",
70
+ `"`,
71
+ "$ErrorActionPreference = 'Stop';",
72
+ `$p = ${psPath};`,
73
+ "$account = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name;",
74
+ "$grant = $account + ':(OI)(CI)F';",
75
+ "if (Test-Path -LiteralPath $p) {",
76
+ " & takeown.exe /F $p /R /D Y;",
77
+ " & icacls.exe $p /reset /T /C;",
78
+ " & icacls.exe $p /grant $grant /T /C;",
79
+ " Remove-Item -LiteralPath $p -Recurse -Force;",
80
+ "}",
81
+ "New-Item -ItemType Directory -Force -Path $p | Out-Null;",
82
+ "& icacls.exe $p /grant $grant /T /C;",
83
+ `"`
84
+ ].join(" ")
85
+ }
86
+
58
87
  //const memwatch = require('@airbnb/node-memwatch');
59
88
  class Kernel {
60
89
  schema = "<=7.0.0"
@@ -386,6 +415,9 @@ class Kernel {
386
415
  path(...args) {
387
416
  return path.resolve(this.homedir, ...args)
388
417
  }
418
+ systemPath(...args) {
419
+ return path.resolve(__dirname, "..", "system", ...args)
420
+ }
389
421
  exists(...args) {
390
422
  if (args) {
391
423
  let abspath = this.path(...args)
@@ -465,6 +497,30 @@ class Kernel {
465
497
  return ''
466
498
  }
467
499
  }
500
+ async elevatedCacheRepair(targetPath, log = console.log) {
501
+ if (this.platform !== "win32" || !sudo) {
502
+ return { ok: false, error: new Error("Elevated cache repair is only available on Windows") }
503
+ }
504
+ const command = windowsCacheRepairCommand(targetPath)
505
+ log(`elevated repair command=${command}`)
506
+ return new Promise((resolve) => {
507
+ sudo.exec(command, { name: "Pinokio" }, (error, stdout, stderr) => {
508
+ if (stdout && stdout.trim()) {
509
+ log(`elevated repair stdout ${stdout.trim()}`)
510
+ }
511
+ if (stderr && stderr.trim()) {
512
+ log(`elevated repair stderr ${stderr.trim()}`)
513
+ }
514
+ if (error) {
515
+ log(`elevated repair failed ${error.message || error}`)
516
+ resolve({ ok: false, error, stdout, stderr })
517
+ } else {
518
+ log(`elevated repair ok path=${targetPath}`)
519
+ resolve({ ok: true, stdout, stderr })
520
+ }
521
+ })
522
+ })
523
+ }
468
524
  async ensureRouterMode() {
469
525
  const domain = await this.resolvePinokioDomain()
470
526
  const shouldUseCustom = domain.length > 0
@@ -1007,6 +1063,7 @@ class Kernel {
1007
1063
  args: {},
1008
1064
  }
1009
1065
  this.procs = {}
1066
+ this.activeProcessWaits = {}
1010
1067
  this.template = new Template()
1011
1068
  try {
1012
1069
  if (this.homedir) {
@@ -1053,7 +1110,10 @@ class Kernel {
1053
1110
 
1054
1111
  // 2. mkdir all the folders if not already created
1055
1112
  await Environment.init_folders(this.homedir, this)
1056
- await Environment.ensurePinokioCacheDirs(this)
1113
+ await Environment.ensurePinokioCacheDirs(this, {
1114
+ throwOnFailure: true,
1115
+ elevatedRepair: this.elevatedCacheRepair.bind(this)
1116
+ })
1057
1117
 
1058
1118
  // if key.json doesn't exist, create an empty json file
1059
1119
  let ee = await this.exists(this.homedir, "key.json")
package/kernel/plugin.js CHANGED
@@ -1,39 +1,14 @@
1
- const path = require('path')
2
- const { glob } = require('glob')
3
- const Info = require("./info")
1
+ const fs = require('fs')
2
+ const PluginSources = require("./plugin_sources")
3
+
4
4
  class Plugin {
5
5
  constructor(kernel) {
6
6
  this.kernel = kernel
7
7
  }
8
8
  async setConfig() {
9
- let plugin_dir = path.resolve(this.kernel.homedir, "plugin")
10
9
  this.cache = {}
11
10
 
12
- let plugin_paths = await glob('**/pinokio.js', { cwd: plugin_dir })
13
-
14
- let plugins = []
15
- for(let plugin_path of plugin_paths) {
16
- let config = await this.kernel.require(path.resolve(plugin_dir, plugin_path))
17
- if (config && config.run && Array.isArray(config.run)) {
18
- let invalid
19
- for(let key in config) {
20
- if (typeof config[key] === "function") {
21
- invalid = true
22
- }
23
- }
24
- if (invalid) {
25
- continue
26
- }
27
-
28
- let chunks = plugin_path.split(path.sep)
29
- let cwd = chunks.slice(0, -1).join("/")
30
- config.image = "/asset/plugin/" + cwd + "/" + config.icon
31
- plugins.push({
32
- href: "/run/plugin/" + chunks.join("/"),
33
- ...config
34
- })
35
- }
36
- }
11
+ const plugins = await PluginSources.loadPluginMenu(this.kernel)
37
12
 
38
13
  this.config = {
39
14
  menu: plugins.map((plugin) => {
@@ -48,37 +23,10 @@ class Plugin {
48
23
  if (!exists) {
49
24
  await fs.promises.mkdir(this.kernel.path("plugin"), { recursive: true }).catch((e) => {})
50
25
  }
51
- let code_exists = await this.kernel.exists("plugin/code")
52
- console.log({ code_exists })
53
- if (!code_exists) {
54
- if (this.kernel.bin.installed && this.kernel.bin.installed.conda && this.kernel.bin.installed.conda.has("git")) {
55
- await this.kernel.exec({
56
- //message: "git clone https://github.com/peanutcocktail/plugin",
57
- //message: "git clone https://github.com/pinokiocomputer/plugin",
58
- message: "git clone https://github.com/pinokiocomputer/code",
59
- path: this.kernel.path("plugin")
60
- }, (e) => {
61
- process.stdout.write(e.raw)
62
- })
63
- await this.setConfig()
64
- return
65
- }
66
- } else {
67
- await this.setConfig()
68
- }
26
+ await this.setConfig()
69
27
  }
70
28
  async update() {
71
- if (this.kernel.bin.installed && this.kernel.bin.installed.conda && this.kernel.bin.installed.conda.has("git")) {
72
- let exists = await this.kernel.exists("plugin")
73
- if (!exists) {
74
- await this.kernel.exec({
75
- message: "git pull",
76
- path: this.kernel.path("plugin")
77
- }, (e) => {
78
- process.stdout.write(e.raw)
79
- })
80
- }
81
- }
29
+ await this.setConfig()
82
30
  }
83
31
  }
84
32
  module.exports = Plugin