pinokiod 7.2.18 → 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.
Files changed (89) hide show
  1. package/Dockerfile +2 -0
  2. package/kernel/api/index.js +13 -179
  3. package/kernel/api/process/index.js +44 -99
  4. package/kernel/bin/conda-python.js +30 -0
  5. package/kernel/bin/conda.js +22 -3
  6. package/kernel/bin/huggingface.js +1 -1
  7. package/kernel/bin/index.js +11 -1
  8. package/kernel/environment.js +11 -205
  9. package/kernel/git.js +13 -0
  10. package/kernel/index.js +1 -64
  11. package/kernel/plugin.js +58 -6
  12. package/kernel/prototype.js +0 -4
  13. package/kernel/shell.js +2 -23
  14. package/kernel/util.js +0 -60
  15. package/package.json +1 -1
  16. package/server/index.js +171 -229
  17. package/server/lib/content_validation.js +33 -47
  18. package/server/public/common.js +29 -103
  19. package/server/public/create-launcher.js +31 -4
  20. package/server/public/electron.css +6 -0
  21. package/server/public/style.css +0 -337
  22. package/server/public/task-launcher.css +3 -11
  23. package/server/public/task-launcher.js +32 -5
  24. package/server/public/universal-launcher.js +26 -3
  25. package/server/socket.js +11 -22
  26. package/server/views/app.ejs +30 -167
  27. package/server/views/d.ejs +35 -33
  28. package/server/views/editor.ejs +4 -25
  29. package/server/views/partials/main_sidebar.ejs +0 -1
  30. package/server/views/partials/menu.ejs +1 -1
  31. package/server/views/pre.ejs +1 -1
  32. package/server/views/shell.ejs +3 -11
  33. package/server/views/task_launch.ejs +10 -10
  34. package/server/views/terminal.ejs +5 -34
  35. package/spec/INSTRUCTION_SYNC.md +5 -5
  36. package/kernel/agent_instructions.js +0 -166
  37. package/kernel/api/shell_run_template.js +0 -273
  38. package/kernel/api/uri/index.js +0 -51
  39. package/kernel/plugin_sources.js +0 -289
  40. package/kernel/watch/context.js +0 -42
  41. package/kernel/watch/drivers/fs.js +0 -71
  42. package/kernel/watch/drivers/poll.js +0 -33
  43. package/kernel/watch/index.js +0 -185
  44. package/server/features/index.js +0 -13
  45. package/server/features/notes/index.js +0 -41
  46. package/server/features/notes/parser.js +0 -174
  47. package/server/features/notes/public/notes.css +0 -955
  48. package/server/features/notes/public/notes.js +0 -1149
  49. package/server/features/notes/registry_import.js +0 -412
  50. package/server/features/notes/routes.js +0 -156
  51. package/server/features/notes/service.js +0 -326
  52. package/server/features/notes/watcher.js +0 -74
  53. package/server/lib/workspace_catalog.js +0 -151
  54. package/server/lib/workspace_runtime.js +0 -390
  55. package/server/public/tasker.css +0 -336
  56. package/server/public/tasker.js +0 -407
  57. package/server/routes/workspaces.js +0 -44
  58. package/server/views/partials/workspace_row.ejs +0 -61
  59. package/server/views/tasker.ejs +0 -40
  60. package/server/views/workspaces.ejs +0 -813
  61. package/system/plugin/antigravity/antigravity.png +0 -0
  62. package/system/plugin/antigravity/pinokio.js +0 -35
  63. package/system/plugin/claude/claude.png +0 -0
  64. package/system/plugin/claude/pinokio.js +0 -61
  65. package/system/plugin/claude-auto/claude.png +0 -0
  66. package/system/plugin/claude-auto/pinokio.js +0 -72
  67. package/system/plugin/claude-desktop/icon.jpeg +0 -0
  68. package/system/plugin/claude-desktop/pinokio.js +0 -37
  69. package/system/plugin/codex/openai.webp +0 -0
  70. package/system/plugin/codex/pinokio.js +0 -56
  71. package/system/plugin/codex-auto/openai.webp +0 -0
  72. package/system/plugin/codex-auto/pinokio.js +0 -63
  73. package/system/plugin/codex-desktop/icon.png +0 -0
  74. package/system/plugin/codex-desktop/pinokio.js +0 -37
  75. package/system/plugin/crush/crush.png +0 -0
  76. package/system/plugin/crush/pinokio.js +0 -29
  77. package/system/plugin/cursor/cursor.jpeg +0 -0
  78. package/system/plugin/cursor/pinokio.js +0 -37
  79. package/system/plugin/gemini/gemini.jpeg +0 -0
  80. package/system/plugin/gemini/pinokio.js +0 -38
  81. package/system/plugin/gemini-auto/gemini.jpeg +0 -0
  82. package/system/plugin/gemini-auto/pinokio.js +0 -41
  83. package/system/plugin/qwen/pinokio.js +0 -48
  84. package/system/plugin/qwen/qwen.png +0 -0
  85. package/system/plugin/vscode/pinokio.js +0 -34
  86. package/system/plugin/vscode/vscode.png +0 -0
  87. package/system/plugin/windsurf/pinokio.js +0 -37
  88. package/system/plugin/windsurf/windsurf.png +0 -0
  89. package/test/plugin-sources.test.js +0 -45
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 \
@@ -11,8 +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
- const AgentInstructions = require("../agent_instructions")
16
14
 
17
15
  class Api {
18
16
  constructor(kernel) {
@@ -28,22 +26,8 @@ class Api {
28
26
  this.proxies = {}
29
27
  this.mods = {}
30
28
  this.child_procs = {}
31
- this.resolved_actions = {}
32
29
  this.lproxy = new Lproxy()
33
30
  }
34
- startData(rpc) {
35
- if (rpc && rpc.method === "process.wait" && rpc.params && typeof rpc.params === "object" && !Array.isArray(rpc.params)) {
36
- let data = rpc
37
- if (typeof data.title === "undefined" && typeof rpc.params.title !== "undefined") {
38
- data = { ...data, title: rpc.params.title }
39
- }
40
- if (typeof data.description === "undefined" && typeof rpc.params.description !== "undefined") {
41
- data = { ...data, description: rpc.params.description }
42
- }
43
- return data
44
- }
45
- return rpc
46
- }
47
31
  async launcher_path(name) {
48
32
  let root_path = this.kernel.path("api", name)
49
33
  let primary_path = path.resolve(root_path, "pinokio.js")
@@ -235,7 +219,7 @@ class Api {
235
219
  meta.ui = `/p/${api_name}`
236
220
  meta.browse = `/p/${api_name}/dev`
237
221
  } else {
238
- meta.icon = meta.icon ? `/asset/api/${api_name}/${relpath}/${meta.icon}` : "/pinokio-black.png"
222
+ meta.icon = meta.icon ? `/asset/api/${api_name}/${meta.icon}` : "/pinokio-black.png"
239
223
  meta.link = `/p/${api_name}/${relpath}/dev#n1`
240
224
  meta.web_path = `/api/${api_name}/${relpath}`
241
225
  meta.ui = `/p/${api_name}/${relpath}`
@@ -414,84 +398,6 @@ class Api {
414
398
  let result = await endpoint(rpc, ondata, this.kernel)
415
399
  return result
416
400
  }
417
- requestId(request) {
418
- return request ? (request.id || request.path) : null
419
- }
420
- clearResolvedAction(requestOrId) {
421
- const id = typeof requestOrId === "string" ? requestOrId : this.requestId(requestOrId)
422
- if (id) {
423
- delete this.resolved_actions[id]
424
- }
425
- }
426
- setRunning(request, done) {
427
- const id = this.requestId(request)
428
- if (!id) {
429
- return
430
- }
431
- this.running[id] = true
432
- this.done[id] = done
433
- }
434
- isActionCandidate(action) {
435
- return (Array.isArray(action) && action.length > 0) || typeof action === "function"
436
- }
437
- async actionContext({ request, script, scriptDir, actionKey, input, args }) {
438
- const cwd = request.cwd || scriptDir
439
- const id = this.requestId(request)
440
- const env = await Environment.get2(request.path, this.kernel)
441
- this.kernel.template.update({ envs: env, env })
442
- const port = await this.kernel.port()
443
- const name = path.relative(this.kernel.path("api"), scriptDir)
444
- return {
445
- kernel: this.kernel,
446
- info: this.kernel.info,
447
- script: this.kernel.script,
448
- action: actionKey,
449
- input,
450
- args,
451
- global: (this.kernel.memory.global[id] || {}),
452
- local: (this.kernel.memory.local[id] || {}),
453
- key: this.kernel.memory.key,
454
- uri: request.uri,
455
- cwd,
456
- dirname: scriptDir,
457
- exists: (...args) => {
458
- return fs.existsSync(path.resolve(cwd, ...args))
459
- },
460
- running: (...args) => {
461
- let fullpath = path.resolve(cwd, ...args)
462
- return this.running[fullpath]
463
- },
464
- name,
465
- self: script,
466
- port,
467
- env,
468
- envs: env,
469
- ...this.kernel.vars,
470
- }
471
- }
472
- async resolveActionSteps({ request, script, scriptDir, actionKey, input, args }) {
473
- const id = this.requestId(request)
474
- const cached = id ? this.resolved_actions[id] : null
475
- if (cached && cached.actionKey === actionKey && Array.isArray(cached.steps)) {
476
- return cached.steps
477
- }
478
-
479
- const action = script ? script[actionKey] : null
480
- let steps
481
- if (Array.isArray(action)) {
482
- steps = action
483
- } else if (typeof action === "function") {
484
- const context = await this.actionContext({ request, script, scriptDir, actionKey, input, args })
485
- steps = await action.call(script, this.kernel, this.kernel.info, context)
486
- } else {
487
- steps = null
488
- }
489
-
490
- if (id && Array.isArray(steps)) {
491
- this.resolved_actions[id] = { actionKey, steps }
492
- }
493
- return steps
494
- }
495
401
  async stop(req, ondata) {
496
402
  // 1. set the "stop" flag for the uri, so the next execution in the queue for the uri will NOT queue another task
497
403
  // 2. stream a message closing the socket
@@ -500,24 +406,16 @@ class Api {
500
406
  // /Users/x/pinokio/prototype/system/aicode/template/claude.json?cwd=/Users/x/pinokio/api/MMAudio.git
501
407
  // take the first part only since the rest is the cwd
502
408
  req.params.uri = req.params.id.split("?")[0]
503
- this.clearResolvedAction(req.params.id)
504
409
  }
505
410
 
506
411
  // 1. if the scropt has 'on.stop', run it when stopping
507
412
  let requestPath = this.filePath(req.params.uri)
508
- this.clearResolvedAction(requestPath)
509
413
  let { cwd, script } = await this.resolveScript(requestPath)
510
414
  if (script.on) {
511
415
  if (script.on.stop) {
512
416
  await this.process(script.on.stop)
513
417
  }
514
418
  }
515
- if (this.kernel.watch && typeof this.kernel.watch.stop === "function") {
516
- if (req.params.id) {
517
- await this.kernel.watch.stop(req.params.id)
518
- }
519
- await this.kernel.watch.stop(requestPath)
520
- }
521
419
  // reset modules
522
420
  let modpath = this.resolvePath(cwd, req.params.uri)
523
421
  if (this.child_procs[modpath]) {
@@ -992,7 +890,7 @@ class Api {
992
890
 
993
891
  let { cwd: scriptDir, script } = await this.resolveScript(request.path)
994
892
  const actionKey = request.action || 'run'
995
- const steps = await this.resolveActionSteps({ request, script, scriptDir, actionKey, input, args }) || []
893
+ const steps = (script && Array.isArray(script[actionKey])) ? script[actionKey] : []
996
894
  const totalSteps = steps.length
997
895
 
998
896
  let name = path.relative(this.kernel.path("api"), scriptDir)
@@ -1112,7 +1010,6 @@ class Api {
1112
1010
  }
1113
1011
  // replace {{{ }}} with {{ }}
1114
1012
  rpc = this.kernel.template.flatten(rpc)
1115
- rpc = ShellRunTemplate.renderEnvArgs(this.kernel, rpc, memory)
1116
1013
 
1117
1014
  // 6. rpc must have method names
1118
1015
  if (rpc.method) {
@@ -1281,7 +1178,7 @@ class Api {
1281
1178
  this.ondata({
1282
1179
  id: request.id || request.path,
1283
1180
  type: "start",
1284
- data: this.startData(rpc)
1181
+ data: rpc
1285
1182
  })
1286
1183
 
1287
1184
  // DEPRECATED APIS
@@ -1557,41 +1454,6 @@ class Api {
1557
1454
  }
1558
1455
  return false
1559
1456
  }
1560
- async startWatchersForRequest(request, script, scriptDir, input) {
1561
- if (!this.kernel.watch || typeof this.kernel.watch.startForScript !== "function") {
1562
- return
1563
- }
1564
- const id = request.id || request.path
1565
- if (!id) {
1566
- return
1567
- }
1568
- const cwd = request.cwd || scriptDir
1569
- await this.kernel.watch.startForScript({
1570
- id,
1571
- request,
1572
- script,
1573
- cwd,
1574
- dirname: scriptDir,
1575
- input,
1576
- args: input
1577
- })
1578
- }
1579
- async ensurePluginAgentInstructions(request) {
1580
- if (!request || !request.cwd || !request.path) {
1581
- return
1582
- }
1583
- if (!AgentInstructions.isPluginScriptPath(this.kernel, request.path)) {
1584
- return
1585
- }
1586
- try {
1587
- await AgentInstructions.ensureNoteInstructionsForCwd({
1588
- kernel: this.kernel,
1589
- cwd: request.cwd,
1590
- })
1591
- } catch (e) {
1592
- console.warn("[agent-instructions] failed to update note instructions:", e && e.message ? e.message : e)
1593
- }
1594
- }
1595
1457
  createQueue(queue_id, concurrency) {
1596
1458
  this.queues[queue_id] = fastq.promise(async ({ request, rawrpc, input, step, total, cwd, args }) => {
1597
1459
  try {
@@ -1809,12 +1671,18 @@ class Api {
1809
1671
  } else {
1810
1672
  const actionKey = request.action || 'run'
1811
1673
  request.action = actionKey
1812
- const action = script ? script[actionKey] : null
1674
+ const steps = script ? script[actionKey] : null
1813
1675
 
1814
- // 3. Check if the resolved endpoint has the requested action attribute and resolve it to steps.
1815
- if (this.isActionCandidate(action)) {
1676
+ // 3. Check if the resolved endpoint has the requested action attribute and it's an array
1677
+ if (Array.isArray(steps) && steps.length > 0) {
1816
1678
 
1817
- this.setRunning(request, done)
1679
+ if (request.id) {
1680
+ this.running[request.id] = true
1681
+ this.done[request.id] = done
1682
+ } else if (request.path) {
1683
+ this.running[request.path] = true
1684
+ this.done[request.path] = done
1685
+ }
1818
1686
 
1819
1687
  // set DNS
1820
1688
 
@@ -1827,40 +1695,6 @@ class Api {
1827
1695
  }
1828
1696
 
1829
1697
  const initialPayload = typeof request.input === "undefined" ? {} : request.input
1830
- let steps
1831
- try {
1832
- steps = await this.resolveActionSteps({
1833
- request,
1834
- script,
1835
- scriptDir: cwd,
1836
- actionKey,
1837
- input: initialPayload,
1838
- args: initialPayload
1839
- })
1840
- } catch (e) {
1841
- this.clearResolvedAction(request)
1842
- delete this.running[this.requestId(request)]
1843
- this.ondata({
1844
- id: request.id || request.path,
1845
- type: "error",
1846
- data: e.stack,
1847
- })
1848
- return
1849
- }
1850
-
1851
- if (!Array.isArray(steps) || steps.length === 0) {
1852
- this.clearResolvedAction(request)
1853
- delete this.running[this.requestId(request)]
1854
- this.ondata({
1855
- id: request.id || request.path,
1856
- type: "error",
1857
- data: `missing or invalid attribute: ${actionKey}`
1858
- })
1859
- return
1860
- }
1861
-
1862
- await this.ensurePluginAgentInstructions(request)
1863
- await this.startWatchersForRequest(request, script, cwd, initialPayload)
1864
1698
  this.queue(request, steps[0], initialPayload, 0, steps.length, cwd, initialPayload)
1865
1699
 
1866
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
- const waitPath = req && req.parent && req.parent.path
245
- if (waitPath && kernel) {
246
- if (!kernel.activeProcessWaits) {
247
- kernel.activeProcessWaits = {}
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
- 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
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
- // 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
229
+ await new Promise((resolve, reject) => {
230
+ this.resolve = resolve
278
231
 
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
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
- setTimeout(() => {
283
- this.resolve()
284
- }, ms)
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
- } 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)
255
+ ondata(req.params, "wait")
310
256
  }
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")
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
+ }
@@ -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
- return conda_check.conda && conda_check.mamba && conda_check.sqlite
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 "sqlite=3.47.2" "conda-libmamba-solver>=25.4.0" ${mods}`,
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: {
@@ -18,7 +18,7 @@ class Huggingface {
18
18
  let version = this.kernel.bin.installed.conda_versions.huggingface_hub
19
19
  if (version) {
20
20
  let coerced = semver.coerce(version)
21
- if (coerced && semver.eq(coerced, "1.0.1")) {
21
+ if (semver.satisfies(coerced, ">=1.0.1")) {
22
22
  return true
23
23
  }
24
24
  }
@@ -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