pinokiod 7.2.17 → 7.3.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/Dockerfile +2 -0
- package/kernel/api/index.js +1 -42
- package/kernel/api/process/index.js +44 -99
- package/kernel/bin/conda-python.js +30 -0
- package/kernel/bin/conda.js +22 -3
- package/kernel/bin/index.js +11 -1
- package/kernel/environment.js +2 -182
- package/kernel/git.js +13 -0
- package/kernel/index.js +1 -64
- package/kernel/plugin.js +58 -6
- package/kernel/shell.js +2 -21
- package/kernel/util.js +0 -60
- package/package.json +1 -1
- package/server/index.js +149 -176
- package/server/lib/content_validation.js +25 -28
- package/server/public/common.js +29 -103
- package/server/public/create-launcher.js +31 -4
- package/server/public/electron.css +6 -0
- package/server/public/style.css +0 -337
- package/server/public/task-launcher.js +32 -5
- package/server/public/universal-launcher.js +26 -3
- package/server/socket.js +11 -22
- package/server/views/app.ejs +30 -167
- package/server/views/d.ejs +33 -0
- package/server/views/editor.ejs +4 -25
- package/server/views/partials/main_sidebar.ejs +0 -1
- package/server/views/shell.ejs +3 -11
- package/server/views/terminal.ejs +3 -23
- package/server/views/terminals.ejs +0 -1
- package/spec/INSTRUCTION_SYNC.md +5 -5
- package/kernel/api/shell_run_template.js +0 -273
- package/kernel/api/uri/index.js +0 -51
- package/kernel/plugin_sources.js +0 -236
- package/kernel/watch/context.js +0 -42
- package/kernel/watch/drivers/fs.js +0 -71
- package/kernel/watch/drivers/poll.js +0 -33
- package/kernel/watch/index.js +0 -158
- package/server/features/drafts/index.js +0 -41
- package/server/features/drafts/parser.js +0 -169
- package/server/features/drafts/public/drafts.js +0 -1504
- package/server/features/drafts/registry_import.js +0 -412
- package/server/features/drafts/routes.js +0 -68
- package/server/features/drafts/service.js +0 -261
- package/server/features/drafts/watcher.js +0 -76
- package/server/features/index.js +0 -13
- package/server/lib/workspace_catalog.js +0 -151
- package/server/lib/workspace_runtime.js +0 -390
- package/server/routes/workspaces.js +0 -44
- package/server/views/partials/workspace_row.ejs +0 -61
- package/server/views/workspaces.ejs +0 -812
- package/system/plugin/antigravity/antigravity.png +0 -0
- package/system/plugin/antigravity/pinokio.js +0 -37
- package/system/plugin/claude/claude.png +0 -0
- package/system/plugin/claude/pinokio.js +0 -63
- package/system/plugin/claude-auto/claude.png +0 -0
- package/system/plugin/claude-auto/pinokio.js +0 -74
- package/system/plugin/claude-desktop/icon.jpeg +0 -0
- package/system/plugin/claude-desktop/pinokio.js +0 -39
- package/system/plugin/codex/openai.webp +0 -0
- package/system/plugin/codex/pinokio.js +0 -58
- package/system/plugin/codex-auto/openai.webp +0 -0
- package/system/plugin/codex-auto/pinokio.js +0 -65
- package/system/plugin/codex-desktop/icon.png +0 -0
- package/system/plugin/codex-desktop/pinokio.js +0 -39
- package/system/plugin/crush/crush.png +0 -0
- package/system/plugin/crush/pinokio.js +0 -31
- package/system/plugin/cursor/cursor.jpeg +0 -0
- package/system/plugin/cursor/pinokio.js +0 -39
- package/system/plugin/gemini/gemini.jpeg +0 -0
- package/system/plugin/gemini/pinokio.js +0 -40
- package/system/plugin/gemini-auto/gemini.jpeg +0 -0
- package/system/plugin/gemini-auto/pinokio.js +0 -43
- package/system/plugin/qwen/pinokio.js +0 -50
- package/system/plugin/qwen/qwen.png +0 -0
- package/system/plugin/vscode/pinokio.js +0 -36
- package/system/plugin/vscode/vscode.png +0 -0
- package/system/plugin/windsurf/pinokio.js +0 -39
- package/system/plugin/windsurf/windsurf.png +0 -0
package/Dockerfile
CHANGED
|
@@ -37,6 +37,8 @@ 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 \
|
|
40
42
|
&& rm -rf /app/.pinokio-seed/prototype/system \
|
|
41
43
|
&& mkdir -p /app/.pinokio-seed/prototype \
|
|
42
44
|
&& git clone --depth 1 https://github.com/pinokiocomputer/proto /app/.pinokio-seed/prototype/system \
|
package/kernel/api/index.js
CHANGED
|
@@ -11,7 +11,6 @@ const fastq = require('fastq')
|
|
|
11
11
|
const Loader = require("../loader")
|
|
12
12
|
const Environment = require("../environment")
|
|
13
13
|
const Util = require('../util')
|
|
14
|
-
const ShellRunTemplate = require('./shell_run_template')
|
|
15
14
|
|
|
16
15
|
class Api {
|
|
17
16
|
constructor(kernel) {
|
|
@@ -29,19 +28,6 @@ class Api {
|
|
|
29
28
|
this.child_procs = {}
|
|
30
29
|
this.lproxy = new Lproxy()
|
|
31
30
|
}
|
|
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
|
-
}
|
|
45
31
|
async launcher_path(name) {
|
|
46
32
|
let root_path = this.kernel.path("api", name)
|
|
47
33
|
let primary_path = path.resolve(root_path, "pinokio.js")
|
|
@@ -430,12 +416,6 @@ class Api {
|
|
|
430
416
|
await this.process(script.on.stop)
|
|
431
417
|
}
|
|
432
418
|
}
|
|
433
|
-
if (this.kernel.watch && typeof this.kernel.watch.stop === "function") {
|
|
434
|
-
if (req.params.id) {
|
|
435
|
-
await this.kernel.watch.stop(req.params.id)
|
|
436
|
-
}
|
|
437
|
-
await this.kernel.watch.stop(requestPath)
|
|
438
|
-
}
|
|
439
419
|
// reset modules
|
|
440
420
|
let modpath = this.resolvePath(cwd, req.params.uri)
|
|
441
421
|
if (this.child_procs[modpath]) {
|
|
@@ -1030,7 +1010,6 @@ class Api {
|
|
|
1030
1010
|
}
|
|
1031
1011
|
// replace {{{ }}} with {{ }}
|
|
1032
1012
|
rpc = this.kernel.template.flatten(rpc)
|
|
1033
|
-
rpc = ShellRunTemplate.renderEnvArgs(this.kernel, rpc, memory)
|
|
1034
1013
|
|
|
1035
1014
|
// 6. rpc must have method names
|
|
1036
1015
|
if (rpc.method) {
|
|
@@ -1199,7 +1178,7 @@ class Api {
|
|
|
1199
1178
|
this.ondata({
|
|
1200
1179
|
id: request.id || request.path,
|
|
1201
1180
|
type: "start",
|
|
1202
|
-
data:
|
|
1181
|
+
data: rpc
|
|
1203
1182
|
})
|
|
1204
1183
|
|
|
1205
1184
|
// DEPRECATED APIS
|
|
@@ -1475,25 +1454,6 @@ class Api {
|
|
|
1475
1454
|
}
|
|
1476
1455
|
return false
|
|
1477
1456
|
}
|
|
1478
|
-
async startWatchersForRequest(request, script, scriptDir, input) {
|
|
1479
|
-
if (!this.kernel.watch || typeof this.kernel.watch.startForScript !== "function") {
|
|
1480
|
-
return
|
|
1481
|
-
}
|
|
1482
|
-
const id = request.id || request.path
|
|
1483
|
-
if (!id) {
|
|
1484
|
-
return
|
|
1485
|
-
}
|
|
1486
|
-
const cwd = request.cwd || scriptDir
|
|
1487
|
-
await this.kernel.watch.startForScript({
|
|
1488
|
-
id,
|
|
1489
|
-
request,
|
|
1490
|
-
script,
|
|
1491
|
-
cwd,
|
|
1492
|
-
dirname: scriptDir,
|
|
1493
|
-
input,
|
|
1494
|
-
args: input
|
|
1495
|
-
})
|
|
1496
|
-
}
|
|
1497
1457
|
createQueue(queue_id, concurrency) {
|
|
1498
1458
|
this.queues[queue_id] = fastq.promise(async ({ request, rawrpc, input, step, total, cwd, args }) => {
|
|
1499
1459
|
try {
|
|
@@ -1735,7 +1695,6 @@ class Api {
|
|
|
1735
1695
|
}
|
|
1736
1696
|
|
|
1737
1697
|
const initialPayload = typeof request.input === "undefined" ? {} : request.input
|
|
1738
|
-
await this.startWatchersForRequest(request, script, cwd, initialPayload)
|
|
1739
1698
|
this.queue(request, steps[0], initialPayload, 0, steps.length, cwd, initialPayload)
|
|
1740
1699
|
|
|
1741
1700
|
} else {
|
|
@@ -34,16 +34,6 @@ 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
|
-
}
|
|
47
37
|
// async start(req, ondata, kernel) {
|
|
48
38
|
// /*
|
|
49
39
|
// req := {
|
|
@@ -169,8 +159,6 @@ class Process {
|
|
|
169
159
|
/*
|
|
170
160
|
params := {
|
|
171
161
|
sec: <SECONDS>,
|
|
172
|
-
title: (optional) Title to display in the footer while waiting,
|
|
173
|
-
description: (optional) Description to display in the footer while waiting,
|
|
174
162
|
message: (optional) Description to display while waiting,
|
|
175
163
|
menu: (optional) menu to display in the modal while waiting,
|
|
176
164
|
// ok: (optional) <ok button text> (if not specified, no ok button),
|
|
@@ -181,8 +169,6 @@ class Process {
|
|
|
181
169
|
|
|
182
170
|
params := {
|
|
183
171
|
min: <MINUTES>,
|
|
184
|
-
title: (optional) Title to display in the footer while waiting,
|
|
185
|
-
description: (optional) Description to display in the footer while waiting,
|
|
186
172
|
message: (optional) Description to display while waiting,
|
|
187
173
|
menu: (optional) menu to display in the modal while waiting,
|
|
188
174
|
// ok: (optional) <ok button text> (if not specified, no ok button),
|
|
@@ -194,8 +180,6 @@ class Process {
|
|
|
194
180
|
params := {
|
|
195
181
|
url: <URL>,
|
|
196
182
|
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,
|
|
199
183
|
message: (optional) the message to display while retrying (default: no message)
|
|
200
184
|
}
|
|
201
185
|
|
|
@@ -214,21 +198,9 @@ class Process {
|
|
|
214
198
|
|
|
215
199
|
or
|
|
216
200
|
|
|
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
|
-
|
|
227
201
|
|
|
228
202
|
params := {
|
|
229
203
|
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,
|
|
232
204
|
message: (optional) Description to display while waiting,
|
|
233
205
|
menu: (optional) menu to display in the modal while waiting,
|
|
234
206
|
// ok: (optional) <ok button text> (if not specified, no ok button),
|
|
@@ -240,84 +212,57 @@ class Process {
|
|
|
240
212
|
if 'cancel' is pressed before the condition is met, stops the script
|
|
241
213
|
|
|
242
214
|
*/
|
|
243
|
-
let ms
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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
|
|
248
220
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
|
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
|
|
267
228
|
}
|
|
268
|
-
|
|
269
|
-
|
|
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
|
|
229
|
+
await new Promise((resolve, reject) => {
|
|
230
|
+
this.resolve = resolve
|
|
278
231
|
|
|
279
|
-
|
|
280
|
-
|
|
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
|
|
281
234
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
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`
|
|
285
254
|
})
|
|
286
|
-
|
|
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)
|
|
255
|
+
ondata(req.params, "wait")
|
|
310
256
|
}
|
|
311
|
-
|
|
312
|
-
await
|
|
313
|
-
|
|
314
|
-
|
|
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")
|
|
257
|
+
console.log("Wait", req.params.on)
|
|
258
|
+
await waitOn(req.params.on)
|
|
259
|
+
console.log("Wait finished")
|
|
260
|
+
ondata(req.params, "wait.end")
|
|
320
261
|
}
|
|
262
|
+
} else {
|
|
263
|
+
await new Promise((resolve, reject) => {
|
|
264
|
+
this.resolve = resolve
|
|
265
|
+
})
|
|
321
266
|
}
|
|
322
267
|
}
|
|
323
268
|
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const semver = require('semver')
|
|
2
|
+
|
|
3
|
+
const WINDOWS_PYTHON_SSL_FIX_SPEC = "python=3.10.20=*_1_cpython"
|
|
4
|
+
const WINDOWS_PYTHON_SSL_FIX_VERSION = "3.10.20"
|
|
5
|
+
|
|
6
|
+
const condaBuildNumber = (build) => {
|
|
7
|
+
const chunks = String(build || "").split("_").reverse()
|
|
8
|
+
const buildNumber = chunks.find((chunk) => /^\d+$/.test(chunk))
|
|
9
|
+
return buildNumber ? Number(buildNumber) : null
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const isWindowsPythonSslFixed = (version, build) => {
|
|
13
|
+
const coerced = semver.coerce(version)
|
|
14
|
+
if (!coerced) {
|
|
15
|
+
return false
|
|
16
|
+
}
|
|
17
|
+
if (!semver.satisfies(coerced, ">=3.10.20 <3.11.0")) {
|
|
18
|
+
return false
|
|
19
|
+
}
|
|
20
|
+
if (semver.eq(coerced, WINDOWS_PYTHON_SSL_FIX_VERSION)) {
|
|
21
|
+
const buildNumber = condaBuildNumber(build)
|
|
22
|
+
return typeof buildNumber === "number" && buildNumber >= 1
|
|
23
|
+
}
|
|
24
|
+
return true
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
WINDOWS_PYTHON_SSL_FIX_SPEC,
|
|
29
|
+
isWindowsPythonSslFixed,
|
|
30
|
+
}
|
package/kernel/bin/conda.js
CHANGED
|
@@ -4,6 +4,11 @@ const fetch = require('cross-fetch')
|
|
|
4
4
|
const { glob } = require('glob')
|
|
5
5
|
const semver = require('semver')
|
|
6
6
|
const { buildCondaListFromMeta } = require('./conda-meta')
|
|
7
|
+
const {
|
|
8
|
+
WINDOWS_PYTHON_SSL_FIX_SPEC,
|
|
9
|
+
isWindowsPythonSslFixed,
|
|
10
|
+
} = require('./conda-python')
|
|
11
|
+
|
|
7
12
|
class Conda {
|
|
8
13
|
description = "Pinokio uses Conda to install various useful programs in an isolated manner."
|
|
9
14
|
urls = {
|
|
@@ -160,6 +165,7 @@ report_errors: false`)
|
|
|
160
165
|
let conda_check = {}
|
|
161
166
|
let conda = new Set()
|
|
162
167
|
let conda_versions = {}
|
|
168
|
+
let conda_builds = {}
|
|
163
169
|
let start = false
|
|
164
170
|
for(let line of lines) {
|
|
165
171
|
if (start) {
|
|
@@ -167,8 +173,10 @@ report_errors: false`)
|
|
|
167
173
|
if (chunks.length > 2) {
|
|
168
174
|
let name = chunks[0]
|
|
169
175
|
let version = chunks[1]
|
|
176
|
+
let build = chunks[2]
|
|
170
177
|
conda.add(name)
|
|
171
178
|
conda_versions[name] = version
|
|
179
|
+
conda_builds[name] = build
|
|
172
180
|
if (name === "conda") {
|
|
173
181
|
conda_check.conda = true
|
|
174
182
|
// //if (String(version) === "24.11.1") {
|
|
@@ -206,6 +214,9 @@ report_errors: false`)
|
|
|
206
214
|
// console.log("semver NOT satisfied")
|
|
207
215
|
//}
|
|
208
216
|
}
|
|
217
|
+
if (name === "python") {
|
|
218
|
+
conda_check.python = this.kernel.platform !== "win32" || isWindowsPythonSslFixed(version, build)
|
|
219
|
+
}
|
|
209
220
|
}
|
|
210
221
|
} else {
|
|
211
222
|
if (/.*name.*version.*build.*channel/i.test(line)) {
|
|
@@ -215,7 +226,8 @@ report_errors: false`)
|
|
|
215
226
|
}
|
|
216
227
|
this.kernel.bin.installed.conda = conda
|
|
217
228
|
this.kernel.bin.installed.conda_versions = conda_versions
|
|
218
|
-
|
|
229
|
+
this.kernel.bin.installed.conda_builds = conda_builds
|
|
230
|
+
return conda_check.conda && conda_check.mamba && conda_check.sqlite && (this.kernel.platform !== "win32" || conda_check.python)
|
|
219
231
|
//return conda_check.conda && conda_check.mamba
|
|
220
232
|
}
|
|
221
233
|
async install(req, ondata) {
|
|
@@ -300,10 +312,18 @@ report_errors: false`)
|
|
|
300
312
|
}).join(" ")
|
|
301
313
|
console.log("Conda dependencies to install", { mods })
|
|
302
314
|
|
|
315
|
+
let condaPackages = [
|
|
316
|
+
`"sqlite=3.47.2"`,
|
|
317
|
+
`"conda-libmamba-solver>=25.4.0"`,
|
|
318
|
+
]
|
|
319
|
+
if (this.kernel.platform === "win32") {
|
|
320
|
+
condaPackages.unshift(`"${WINDOWS_PYTHON_SSL_FIX_SPEC}"`)
|
|
321
|
+
}
|
|
322
|
+
|
|
303
323
|
let cmds = [
|
|
304
324
|
//"conda clean -y --index-cache",
|
|
305
325
|
"conda clean -y --all",
|
|
306
|
-
`conda install -y -c conda-forge
|
|
326
|
+
`conda install -y -c conda-forge ${condaPackages.join(" ")} ${mods}`.trim(),
|
|
307
327
|
|
|
308
328
|
// `conda config --file ${this.kernel.path('condarc')} --set remote_connect_timeout_secs 20`,
|
|
309
329
|
// `conda config --file ${this.kernel.path('condarc')} --set remote_read_timeout_secs 300`,
|
|
@@ -339,7 +359,6 @@ report_errors: false`)
|
|
|
339
359
|
//if (this.kernel.platform === "win32" || this.kernel.platform === "darwin") {
|
|
340
360
|
// cmds.push("conda install -y conda-libmamba-solver=24.7.0 conda=24.7.1 --freeze-installed")
|
|
341
361
|
//}
|
|
342
|
-
|
|
343
362
|
await this.kernel.bin.exec({
|
|
344
363
|
message: cmds,
|
|
345
364
|
env: {
|
package/kernel/bin/index.js
CHANGED
|
@@ -22,6 +22,7 @@ const VS = require("./vs")
|
|
|
22
22
|
const Cuda = require("./cuda")
|
|
23
23
|
const Torch = require("./torch")
|
|
24
24
|
const { buildCondaListFromMeta } = require('./conda-meta')
|
|
25
|
+
const { isWindowsPythonSslFixed } = require('./conda-python')
|
|
25
26
|
const { glob } = require('glob')
|
|
26
27
|
const fakeUa = require('fake-useragent');
|
|
27
28
|
const fse = require('fs-extra')
|
|
@@ -348,6 +349,8 @@ class Bin {
|
|
|
348
349
|
let conda_check = {}
|
|
349
350
|
let conda = new Set()
|
|
350
351
|
let conda_versions = {}
|
|
352
|
+
let conda_builds = {}
|
|
353
|
+
this.correct_conda = false
|
|
351
354
|
|
|
352
355
|
//////////////////////////////////////////////////////////////////
|
|
353
356
|
// exception handling
|
|
@@ -386,8 +389,10 @@ class Bin {
|
|
|
386
389
|
if (chunks.length > 2) {
|
|
387
390
|
let name = chunks[0]
|
|
388
391
|
let version = chunks[1]
|
|
392
|
+
let build = chunks[2]
|
|
389
393
|
conda.add(name)
|
|
390
394
|
conda_versions[name] = version
|
|
395
|
+
conda_builds[name] = build
|
|
391
396
|
if (name === "conda") {
|
|
392
397
|
conda_check.conda = true
|
|
393
398
|
}
|
|
@@ -408,6 +413,9 @@ class Bin {
|
|
|
408
413
|
conda_check.sqlite = true
|
|
409
414
|
}
|
|
410
415
|
}
|
|
416
|
+
if (name === "python") {
|
|
417
|
+
conda_check.python = this.platform !== "win32" || isWindowsPythonSslFixed(version, build)
|
|
418
|
+
}
|
|
411
419
|
}
|
|
412
420
|
} else {
|
|
413
421
|
if (/.*name.*version.*build.*channel/i.test(line)) {
|
|
@@ -416,13 +424,14 @@ class Bin {
|
|
|
416
424
|
}
|
|
417
425
|
}
|
|
418
426
|
|
|
419
|
-
if (conda_check.conda && conda_check.mamba && conda_check.sqlite) {
|
|
427
|
+
if (conda_check.conda && conda_check.mamba && conda_check.sqlite && (this.platform !== "win32" || conda_check.python)) {
|
|
420
428
|
//if (conda_check.conda && conda_check.mamba) {
|
|
421
429
|
this.correct_conda = true
|
|
422
430
|
}
|
|
423
431
|
}
|
|
424
432
|
this.installed.conda = conda
|
|
425
433
|
this.installed.conda_versions = conda_versions
|
|
434
|
+
this.installed.conda_builds = conda_builds
|
|
426
435
|
}
|
|
427
436
|
async refreshInstalled() {
|
|
428
437
|
|
|
@@ -430,6 +439,7 @@ class Bin {
|
|
|
430
439
|
|
|
431
440
|
this.installed_initialized = false
|
|
432
441
|
this.requirements_cache = {}
|
|
442
|
+
this.correct_conda = false
|
|
433
443
|
|
|
434
444
|
//this.installed = {}
|
|
435
445
|
|
package/kernel/environment.js
CHANGED
|
@@ -3,187 +3,7 @@ const portfinder = require('portfinder-cp')
|
|
|
3
3
|
const os = require('os')
|
|
4
4
|
const fs = require('fs')
|
|
5
5
|
const Util = require('./util')
|
|
6
|
-
const
|
|
7
|
-
const CACHE_ENV_KEYS = ["UV_CACHE_DIR", "PIP_CACHE_DIR"]
|
|
8
|
-
const CACHE_PREFLIGHT_KEYS = TEMP_ENV_KEYS.concat(CACHE_ENV_KEYS)
|
|
9
|
-
|
|
10
|
-
const formatCachePreflightError = (error) => {
|
|
11
|
-
if (!error) {
|
|
12
|
-
return ""
|
|
13
|
-
}
|
|
14
|
-
const parts = []
|
|
15
|
-
if (error.code) {
|
|
16
|
-
parts.push(`code=${error.code}`)
|
|
17
|
-
}
|
|
18
|
-
if (typeof error.errno !== "undefined") {
|
|
19
|
-
parts.push(`errno=${error.errno}`)
|
|
20
|
-
}
|
|
21
|
-
if (error.syscall) {
|
|
22
|
-
parts.push(`syscall=${error.syscall}`)
|
|
23
|
-
}
|
|
24
|
-
if (error.path) {
|
|
25
|
-
parts.push(`path=${error.path}`)
|
|
26
|
-
}
|
|
27
|
-
if (error.dest) {
|
|
28
|
-
parts.push(`dest=${error.dest}`)
|
|
29
|
-
}
|
|
30
|
-
if (error.message) {
|
|
31
|
-
parts.push(`message=${error.message}`)
|
|
32
|
-
}
|
|
33
|
-
return parts.join(" ")
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const logCachePreflight = (message) => {
|
|
37
|
-
console.log(`[Pinokio cache preflight] ${message}`)
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const probeCacheDir = async (dirPath) => {
|
|
41
|
-
const probeDir = path.resolve(
|
|
42
|
-
dirPath,
|
|
43
|
-
`.pinokio-cache-probe-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`
|
|
44
|
-
)
|
|
45
|
-
const probeFile = path.resolve(probeDir, "probe.tmp")
|
|
46
|
-
const renamedFile = path.resolve(probeDir, "probe-renamed.tmp")
|
|
47
|
-
const steps = [
|
|
48
|
-
["create probe directory", () => fs.promises.mkdir(probeDir, { recursive: false })],
|
|
49
|
-
["write probe file", () => fs.promises.writeFile(probeFile, "pinokio")],
|
|
50
|
-
["append probe file", () => fs.promises.appendFile(probeFile, "-cache-probe")],
|
|
51
|
-
["rename probe file", () => fs.promises.rename(probeFile, renamedFile)],
|
|
52
|
-
["delete probe file", () => fs.promises.unlink(renamedFile)],
|
|
53
|
-
["remove probe directory", () => fs.promises.rmdir(probeDir)]
|
|
54
|
-
]
|
|
55
|
-
|
|
56
|
-
for (const [step, run] of steps) {
|
|
57
|
-
try {
|
|
58
|
-
await run()
|
|
59
|
-
} catch (error) {
|
|
60
|
-
await fs.promises.rm(probeDir, { recursive: true, force: true }).catch(() => {})
|
|
61
|
-
return { ok: false, step, error }
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return { ok: true }
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
const managedCacheEnvDefaults = () => {
|
|
68
|
-
const defaults = {}
|
|
69
|
-
for (const key of CACHE_PREFLIGHT_KEYS) {
|
|
70
|
-
defaults[key] = `./cache/${key}`
|
|
71
|
-
}
|
|
72
|
-
return defaults
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const ensureCachePreflightDir = async (key, targetPath, options = {}) => {
|
|
76
|
-
logCachePreflight(`${key}: target=${targetPath}`)
|
|
77
|
-
try {
|
|
78
|
-
await fs.promises.mkdir(targetPath, { recursive: true })
|
|
79
|
-
logCachePreflight(`${key}: mkdir ok`)
|
|
80
|
-
} catch (error) {
|
|
81
|
-
logCachePreflight(`${key}: mkdir failed ${formatCachePreflightError(error)}`)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
const firstProbe = await probeCacheDir(targetPath)
|
|
85
|
-
if (firstProbe.ok) {
|
|
86
|
-
logCachePreflight(`${key}: probe ok`)
|
|
87
|
-
return { key, path: targetPath, repaired: false, ok: true }
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
logCachePreflight(`${key}: probe failed step="${firstProbe.step}" ${formatCachePreflightError(firstProbe.error)}`)
|
|
91
|
-
logCachePreflight(`${key}: repair delete start path=${targetPath}`)
|
|
92
|
-
|
|
93
|
-
try {
|
|
94
|
-
await fs.promises.rm(targetPath, { recursive: true, force: true })
|
|
95
|
-
logCachePreflight(`${key}: repair delete ok`)
|
|
96
|
-
} catch (error) {
|
|
97
|
-
logCachePreflight(`${key}: repair delete failed ${formatCachePreflightError(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 }
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
try {
|
|
121
|
-
await fs.promises.mkdir(targetPath, { recursive: true })
|
|
122
|
-
logCachePreflight(`${key}: repair mkdir ok`)
|
|
123
|
-
} catch (error) {
|
|
124
|
-
logCachePreflight(`${key}: repair mkdir failed ${formatCachePreflightError(error)}`)
|
|
125
|
-
return { key, path: targetPath, repaired: true, ok: false, step: "repair mkdir", error }
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const secondProbe = await probeCacheDir(targetPath)
|
|
129
|
-
if (secondProbe.ok) {
|
|
130
|
-
logCachePreflight(`${key}: repair probe ok`)
|
|
131
|
-
return { key, path: targetPath, repaired: true, ok: true }
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
logCachePreflight(`${key}: repair probe failed step="${secondProbe.step}" ${formatCachePreflightError(secondProbe.error)}`)
|
|
135
|
-
return { key, path: targetPath, repaired: true, ok: false, step: secondProbe.step, error: secondProbe.error }
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
const ensurePinokioCacheDirs = async (kernel, options = {}) => {
|
|
139
|
-
if (!kernel || !kernel.homedir) {
|
|
140
|
-
return {}
|
|
141
|
-
}
|
|
142
|
-
const throwOnFailure = !!options.throwOnFailure
|
|
143
|
-
const root = path.resolve(kernel.homedir)
|
|
144
|
-
const cacheRoot = path.resolve(root, "cache")
|
|
145
|
-
const envPath = path.resolve(root, "ENVIRONMENT")
|
|
146
|
-
const defaults = managedCacheEnvDefaults()
|
|
147
|
-
logCachePreflight(`start root=${root}`)
|
|
148
|
-
await Util.update_env(envPath, defaults)
|
|
149
|
-
logCachePreflight(`ENVIRONMENT updated keys=${CACHE_PREFLIGHT_KEYS.join(",")}`)
|
|
150
|
-
try {
|
|
151
|
-
await fs.promises.mkdir(cacheRoot, { recursive: true })
|
|
152
|
-
logCachePreflight(`cache root mkdir ok path=${cacheRoot}`)
|
|
153
|
-
} catch (error) {
|
|
154
|
-
logCachePreflight(`cache root mkdir failed path=${cacheRoot} ${formatCachePreflightError(error)}`)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const errors = []
|
|
158
|
-
const results = []
|
|
159
|
-
|
|
160
|
-
for (const key of CACHE_PREFLIGHT_KEYS) {
|
|
161
|
-
const targetPath = path.resolve(cacheRoot, key)
|
|
162
|
-
const result = await ensureCachePreflightDir(key, targetPath, options)
|
|
163
|
-
results.push(result)
|
|
164
|
-
if (!result.ok) {
|
|
165
|
-
errors.push(result)
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (errors.length > 0) {
|
|
170
|
-
kernel.cacheDirErrors = errors
|
|
171
|
-
const message = errors
|
|
172
|
-
.map((error) => `${error.key}: ${error.path} (${error.step || "unknown"} ${formatCachePreflightError(error.error)})`)
|
|
173
|
-
.join(", ")
|
|
174
|
-
logCachePreflight(`failed ${message}`)
|
|
175
|
-
if (throwOnFailure) {
|
|
176
|
-
throw new Error(`Pinokio could not create writable cache directories: ${message}`)
|
|
177
|
-
}
|
|
178
|
-
} else {
|
|
179
|
-
kernel.cacheDirErrors = []
|
|
180
|
-
logCachePreflight(`complete ok checked=${results.length} repaired=${results.filter((result) => result.repaired).length}`)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
kernel.cacheDirPreflight = results
|
|
184
|
-
const env = await get(root, kernel)
|
|
185
|
-
return { env, errors, results }
|
|
186
|
-
}
|
|
6
|
+
const platform = os.platform()
|
|
187
7
|
const ENVS = async () => {
|
|
188
8
|
// const primary_port = 80
|
|
189
9
|
// const secondary_port = 42000
|
|
@@ -1008,4 +828,4 @@ const init = async (options, kernel) => {
|
|
|
1008
828
|
env_path: current
|
|
1009
829
|
}
|
|
1010
830
|
}
|
|
1011
|
-
module.exports = { ENV, get, get2, init_folders,
|
|
831
|
+
module.exports = { ENV, get, get2, init_folders, requirements, init, get_root }
|
package/kernel/git.js
CHANGED
|
@@ -1378,6 +1378,19 @@ 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
|
+
},
|
|
1381
1394
|
{
|
|
1382
1395
|
kind: "prototype",
|
|
1383
1396
|
root: path.resolve(home, "prototype/system"),
|