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.
- package/Dockerfile +0 -2
- package/kernel/api/index.js +14 -1
- package/kernel/api/process/index.js +99 -44
- package/kernel/api/uri/index.js +51 -0
- package/kernel/environment.js +22 -3
- package/kernel/git.js +0 -13
- package/kernel/index.js +61 -1
- package/kernel/plugin.js +6 -58
- package/kernel/plugin_sources.js +236 -0
- package/kernel/util.js +60 -0
- package/package.json +1 -1
- package/server/features/drafts/public/drafts.js +35 -12
- package/server/index.js +120 -142
- package/server/lib/content_validation.js +28 -25
- package/server/public/common.js +95 -29
- package/server/public/create-launcher.js +4 -31
- package/server/public/electron.css +1 -1
- package/server/public/style.css +337 -0
- package/server/public/task-launcher.js +5 -32
- package/server/public/universal-launcher.js +3 -26
- package/server/views/app.ejs +8 -29
- package/server/views/d.ejs +0 -33
- package/server/views/editor.ejs +25 -4
- package/server/views/shell.ejs +11 -3
- package/server/views/terminal.ejs +15 -3
- package/spec/INSTRUCTION_SYNC.md +5 -5
- package/system/plugin/antigravity/antigravity.png +0 -0
- package/system/plugin/antigravity/pinokio.js +37 -0
- package/system/plugin/claude/claude.png +0 -0
- package/system/plugin/claude/pinokio.js +63 -0
- package/system/plugin/claude-auto/claude.png +0 -0
- package/system/plugin/claude-auto/pinokio.js +74 -0
- package/system/plugin/claude-desktop/icon.jpeg +0 -0
- package/system/plugin/claude-desktop/pinokio.js +39 -0
- package/system/plugin/codex/openai.webp +0 -0
- package/system/plugin/codex/pinokio.js +58 -0
- package/system/plugin/codex-auto/openai.webp +0 -0
- package/system/plugin/codex-auto/pinokio.js +65 -0
- package/system/plugin/codex-desktop/icon.png +0 -0
- package/system/plugin/codex-desktop/pinokio.js +39 -0
- package/system/plugin/crush/crush.png +0 -0
- package/system/plugin/crush/pinokio.js +31 -0
- package/system/plugin/cursor/cursor.jpeg +0 -0
- package/system/plugin/cursor/pinokio.js +39 -0
- package/system/plugin/gemini/gemini.jpeg +0 -0
- package/system/plugin/gemini/pinokio.js +40 -0
- package/system/plugin/gemini-auto/gemini.jpeg +0 -0
- package/system/plugin/gemini-auto/pinokio.js +43 -0
- package/system/plugin/qwen/pinokio.js +50 -0
- package/system/plugin/qwen/qwen.png +0 -0
- package/system/plugin/vscode/pinokio.js +36 -0
- package/system/plugin/vscode/vscode.png +0 -0
- package/system/plugin/windsurf/pinokio.js +39 -0
- 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 \
|
package/kernel/api/index.js
CHANGED
|
@@ -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
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
|
|
230
|
-
|
|
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
|
-
|
|
233
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
-
|
|
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
|
-
|
|
258
|
-
await
|
|
259
|
-
|
|
260
|
-
|
|
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
|
package/kernel/environment.js
CHANGED
|
@@ -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
|
-
|
|
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
|
|
2
|
-
const
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|