pinokiod 3.6.28 → 3.6.30

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.
@@ -121,8 +121,10 @@ class Api {
121
121
  async stop(req, ondata) {
122
122
  // 1. set the "stop" flag for the uri, so the next execution in the queue for the uri will NOT queue another task
123
123
  // 2. stream a message closing the socket
124
+ console.log("> stop", req)
124
125
 
125
126
  let requestPath = this.filePath(req.params.uri)
127
+ console.log({ requestPath })
126
128
 
127
129
 
128
130
 
@@ -352,13 +354,20 @@ class Api {
352
354
  let modpath
353
355
  if (matched_repo.length > 0) {
354
356
  let repo_uri = matched_repo[0]
355
-
356
- let relative_path = uri
357
- .replace(repo_uri, "") // remove the git repo uri
358
- .slice(1) // remove the leading '/' for relative path
357
+ if (!repo_uri.endsWith(".git")) {
358
+ repo_uri = repo_uri + ".git"
359
+ }
359
360
 
360
361
  let repopath = this.gitPath[repo_uri]
361
- modpath = path.resolve(repopath, relative_path)
362
+ if (uri === repo_uri) {
363
+ modpath = path.resolve(repopath)
364
+ } else {
365
+ let relative_path = uri
366
+ .replace(repo_uri, "") // remove the git repo uri
367
+ .slice(1) // remove the leading '/' for relative path
368
+ modpath = path.resolve(repopath, relative_path)
369
+ }
370
+
362
371
  } else {
363
372
  //console.log("no matching gitpath")
364
373
  }
@@ -568,9 +577,13 @@ class Api {
568
577
  }
569
578
  async step (request, rawrpc, input, i, total, args) {
570
579
 
571
- await this.init()
580
+ await Promise.all([this.init, this.kernel.update_sysinfo])
572
581
 
573
- await this.kernel.update_sysinfo()
582
+ // await this.init()
583
+ //
584
+ // console.time("api.update_sysinfo")
585
+ // await this.kernel.update_sysinfo()
586
+ // console.timeEnd("api.update_sysinfo")
574
587
 
575
588
  // clear global regular expression object RegExp.lastMatch (memory leak prevention)
576
589
  let r = /\s*/g.exec("");
@@ -795,7 +808,6 @@ class Api {
795
808
  } else {
796
809
  // 11. actually make the rpc call
797
810
  result = await this.run(resolved.method, rpc, (stream, type) => {
798
- console.log("RUN RESULT", { stream ,type })
799
811
  let m = {
800
812
  id: request.path,
801
813
  caller: request.caller,
@@ -1124,6 +1136,35 @@ class Api {
1124
1136
  this.process(request, resolve)
1125
1137
  })
1126
1138
  }
1139
+ async get_default(repo_path) {
1140
+ let p = path.resolve(repo_path, "pinokio.js")
1141
+ // call 'process' based on the current status
1142
+ let config = (await this.loader.load(p)).resolved
1143
+ if (config && config.menu) {
1144
+ if (typeof config.menu === "function") {
1145
+ if (config.menu.constructor.name === "AsyncFunction") {
1146
+ config.menu = await config.menu(this.kernel, this.kernel.info)
1147
+ } else {
1148
+ config.menu = config.menu(this.kernel, this.kernel.info)
1149
+ }
1150
+ }
1151
+ // find the default item in the menu
1152
+ let running = config.menu.filter((item) => {
1153
+ return item.default
1154
+ })
1155
+ if (running.length > 0) {
1156
+ let r = running[0]
1157
+ if (r.href) {
1158
+ if (r.href.startsWith("http")) {
1159
+ return r.href
1160
+ } else {
1161
+ let href = path.resolve(repo_path, r.href)
1162
+ return href
1163
+ }
1164
+ }
1165
+ }
1166
+ }
1167
+ }
1127
1168
  async process(request, done) {
1128
1169
  /**************************************************************
1129
1170
  *
@@ -1165,41 +1206,69 @@ class Api {
1165
1206
  // this.kernel.keys = (await this.loader.load(keypath)).resolved
1166
1207
 
1167
1208
  // init shell before running just to make sure the environment variables are fresh
1209
+ console.time("shell.init")
1168
1210
  await this.kernel.shell.init()
1211
+ console.timeEnd("shell.init")
1169
1212
 
1170
1213
  if (request.uri){
1214
+
1171
1215
  this.counter++;
1172
1216
  // API Call
1173
1217
 
1174
1218
  request.path = this.resolvePath(this.userdir, request.uri)
1175
- let { cwd, script } = await this.resolveScript(request.path)
1176
- request.cwd = cwd
1177
1219
 
1178
- if (!script) {
1179
- this.ondata({
1180
- id: request.path,
1181
- type: "error",
1182
- data: "the endpoint does not exist: " + request.uri,
1183
- })
1184
- } else {
1185
- // 3. Check if the resolved endpoint has the "run" attribute and it's an array
1186
- //if (script.run && Array.isArray(script.run)) {
1187
- if (script.run) {
1188
-
1189
- this.running[request.path] = true
1190
-
1191
- this.done[request.path] = done
1192
-
1193
- this.queue(request, script.run[0], request.input, 0, script.run.length, cwd, request.input)
1194
1220
 
1221
+ // if the path is
1222
+ let relative = path.relative(this.kernel.homedir, request.path)
1223
+ let chunks = relative.split(path.sep)
1224
+ console.log({ chunks })
1225
+ if (chunks.length == 2) {
1226
+ // the script is requesting a uri of the git repo
1227
+ // look for pinokio.js
1228
+ let p = path.resolve(request.path, "pinokio.js")
1229
+ let exists = await this.exists(p)
1230
+ console.log({ p, exists })
1231
+ if (exists) {
1232
+ await this.launch(request, p)
1195
1233
  } else {
1196
1234
  this.ondata({
1197
1235
  id: request.path,
1198
1236
  type: "error",
1199
- data: "missing attribute: run"
1237
+ data: "uri doesn't exist \r\n" + JSON.stringify(request, null, 2)
1200
1238
  })
1201
1239
  }
1240
+ } else {
1241
+ console.log({ request })
1242
+ let { cwd, script } = await this.resolveScript(request.path)
1243
+ request.cwd = cwd
1244
+
1245
+ if (!script) {
1246
+ this.ondata({
1247
+ id: request.path,
1248
+ type: "error",
1249
+ data: "the endpoint does not exist: " + request.uri,
1250
+ })
1251
+ } else {
1252
+ // 3. Check if the resolved endpoint has the "run" attribute and it's an array
1253
+ //if (script.run && Array.isArray(script.run)) {
1254
+ if (script.run) {
1255
+
1256
+ this.running[request.path] = true
1257
+
1258
+ this.done[request.path] = done
1259
+
1260
+ this.queue(request, script.run[0], request.input, 0, script.run.length, cwd, request.input)
1261
+
1262
+ } else {
1263
+ this.ondata({
1264
+ id: request.path,
1265
+ type: "error",
1266
+ data: "missing attribute: run"
1267
+ })
1268
+ }
1269
+ }
1202
1270
  }
1271
+
1203
1272
  } else if (request.method) {
1204
1273
  let pass = 0;
1205
1274
  while(true) {
@@ -588,56 +588,23 @@ class Bin {
588
588
  }
589
589
  // }
590
590
  }
591
- async install2(req, ondata) {
592
- let requirements = [{
593
- name: "conda",
594
- }, {
595
- name: "git",
596
- }, {
597
- name: "zip",
598
- }, {
599
- name: "node",
600
- }, {
601
- name: "ffmpeg",
602
- }]
603
- let platform = os.platform()
604
- if (platform === "win32") {
605
- requirements.push({
606
- name: "registry"
607
- })
608
- requirements.push({
609
- name: "vs"
610
- })
611
- }
612
- if (platform === "darwin") {
613
- requirements.push({
614
- name: "brew"
615
- })
616
- }
617
- if (platform === "linux") {
618
- requirements.push({
619
- name: "gxx"
620
- })
621
- }
622
- if (this.kernel.gpu === "nvidia") {
623
- requirements.push({
624
- name: "cuda"
625
- })
591
+ async path_exists(req, ondata) {
592
+ let abspath = this.kernel.api.resolvePath(this.kernel.api.userdir, req.params.uri)
593
+ if (abspath) {
594
+ console.log({ abspath })
595
+ let exists = await new Promise(r=>fs.access(abspath, fs.constants.F_OK, e => r(!e)))
596
+ return exists
597
+ } else {
598
+ return false
626
599
  }
627
- requirements = requirements.concat([{
628
- name: "py"
629
- }, {
630
- name: "cloudflared"
631
- }, {
632
- name: "playwright"
633
- }, {
634
- name: "huggingface"
635
- }, {
636
- name: "uv"
637
- }])
600
+ }
601
+ async install2(req, ondata) {
602
+ let { requirements, install_required, requirements_pending, error } = await this.check_bin()
638
603
  req.params = JSON.stringify(requirements)
639
- let res = await this.install(req, ondata)
640
- return res
604
+ if (this.install_required) {
605
+ let res = await this.install(req, ondata)
606
+ return res
607
+ }
641
608
  }
642
609
  async install(req, ondata) {
643
610
  /*
@@ -733,17 +700,29 @@ class Bin {
733
700
  //}
734
701
  await this.init()
735
702
  }
703
+ async installed(r) {
704
+ if (Array.isArray(r.name)) {
705
+ for(let name of r.name) {
706
+ let installed = await this._installed(name, r.type)
707
+ if (!installed) return false
708
+ }
709
+ return true
710
+ } else {
711
+ let installed = await this._installed(r.name, r.type)
712
+ return installed
713
+ }
714
+ }
736
715
  async _installed(name, type) {
737
716
  if (type === "conda") {
738
- return this.kernel.bin.installed.conda.has(name)
717
+ return this.installed.conda.has(name)
739
718
  } else if (type === "pip") {
740
- return this.kernel.bin.installed.pip && this.kernel.bin.installed.pip.has(name)
719
+ return this.installed.pip && this.installed.pip.has(name)
741
720
  } else if (type === "brew") {
742
- return this.kernel.bin.installed.brew.has(name)
721
+ return this.installed.brew.has(name)
743
722
  } else {
744
723
  // check kernel/bin/<module>.installed()
745
724
  let filepath = path.resolve(__dirname, "..", "kernel", "bin", name + ".js")
746
- let mod = this.kernel.bin.mod[name]
725
+ let mod = this.mod[name]
747
726
  let installed = false
748
727
  if (mod.installed) {
749
728
  installed = await mod.installed()
@@ -751,6 +730,97 @@ class Bin {
751
730
  return installed
752
731
  }
753
732
  }
733
+ async check_bin() {
734
+ let requirements = [
735
+ { name: "conda", },
736
+ { name: "git", },
737
+ { name: "zip", },
738
+ { name: "node", },
739
+ { name: "ffmpeg", }
740
+ ]
741
+ let platform = os.platform()
742
+ if (platform === "win32") {
743
+ requirements.push({ name: "registry" })
744
+ requirements.push({ name: "vs" })
745
+ }
746
+ if (platform === "darwin") {
747
+ requirements.push({ name: "brew" })
748
+ }
749
+ if (platform === "linux") {
750
+ requirements.push({ name: "gxx" })
751
+ }
752
+ if (this.kernel.gpu === "nvidia") {
753
+ requirements.push({ name: "cuda", })
754
+ }
755
+ requirements = requirements.concat([
756
+ { name: "py" },
757
+ { name: "cloudflared" },
758
+ { name: "playwright" },
759
+ { name: "huggingface" },
760
+ { name: "uv" }
761
+ ])
762
+
763
+ let requirements_pending = !this.installed_initialized
764
+ let install_required = true
765
+ if (!requirements_pending) {
766
+ install_required = false
767
+ for(let i=0; i<requirements.length; i++) {
768
+ let r = requirements[i]
769
+ console.time(r.name)
770
+ let installed = await this.installed(r)
771
+ console.log({ r, installed })
772
+ console.timeEnd(r.name)
773
+ requirements[i].installed = installed
774
+ if (!installed) {
775
+ install_required = true
776
+ }
777
+ }
778
+ }
779
+
780
+ let error = null
781
+ try {
782
+ this.compatible()
783
+ } catch (e) {
784
+ error = e.message
785
+ install_required = true
786
+ }
787
+
788
+ this.install_required = install_required
789
+ this.requirements_pending = requirements_pending
790
+
791
+ console.log("check_bin finished 2")
792
+ return {
793
+ error,
794
+ requirements,
795
+ install_required,
796
+ requirements_pending
797
+ }
798
+
799
+ }
800
+ winBuildNumber() {
801
+ let osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release());
802
+ let buildNumber = 0;
803
+ if (osVersion && osVersion.length === 4) {
804
+ buildNumber = parseInt(osVersion[3]);
805
+ }
806
+ return buildNumber;
807
+ }
808
+ compatible() {
809
+ if (this.kernel.platform === "win32") {
810
+ let buildNumber = this.winBuildNumber()
811
+ if (buildNumber < 18309) {
812
+ // must use conpty for node-pty, and conpty is only supported in win>=18309
813
+ console.log("Windows buildNumber", buildNumber)
814
+ throw new Error(`Pinokio supports Windows release 18309 and up (current system: ${buildNumber}`)
815
+ }
816
+
817
+ // if (buildNumber > 25000) {
818
+ // console.log("Windows buildNumber", buildNumber)
819
+ // throw new Error(`Pinokio does not currently support Windows Canary (versions 25000 and up). The current system is ${buildNumber}`)
820
+ //
821
+ // }
822
+ }
823
+ }
754
824
  async sh(params, ondata) {
755
825
  let response = await this.kernel.shell.run(params, null, ondata)
756
826
  return response
@@ -19,6 +19,11 @@ class Node {
19
19
  async installed() {
20
20
  return this.kernel.bin.installed.conda.has("nodejs") && this.kernel.bin.installed.conda.has("pnpm")
21
21
  }
22
+ env() {
23
+ return {
24
+ PATH: [this.kernel.path("bin/npm/bin")]
25
+ }
26
+ }
22
27
  async uninstall(req, ondata) {
23
28
  await this.kernel.bin.exec({
24
29
  message: "conda remove nodejs pnpm",
package/kernel/index.js CHANGED
@@ -40,7 +40,7 @@ class Kernel {
40
40
  //schema = ">=1.0.0"
41
41
  //schema = "<=2.1.0"
42
42
  //schema = "<=3.2.0"
43
- schema = "<=3.6.0"
43
+ schema = "<=3.7.0"
44
44
  constructor(store) {
45
45
  this.fetch = fetch
46
46
 
@@ -409,6 +409,7 @@ class Kernel {
409
409
  }
410
410
  }
411
411
  async init(options) {
412
+ console.time(">>>>>>>>>>>>>> A")
412
413
  let home = this.store.get("home")
413
414
 
414
415
  // reset shells if they exist
@@ -475,7 +476,9 @@ class Kernel {
475
476
  }
476
477
  this.procs = {}
477
478
  this.template = new Template()
479
+ console.timeEnd(">>>>>>>>>>>>>> A")
478
480
  try {
481
+ console.time(">>>>>>>>>>>>>> B")
479
482
  if (this.homedir) {
480
483
 
481
484
  // 0. create homedir
@@ -513,14 +516,17 @@ class Kernel {
513
516
 
514
517
 
515
518
  }
519
+ console.timeEnd(">>>>>>>>>>>>>> B")
516
520
 
517
521
  // let contents = await fs.promises.readdir(this.homedir)
518
522
  //await this.bin.init()
519
523
  let ts = Date.now()
524
+ console.time(">>>>>>>>>>>>>> C bin.init")
520
525
  this.bin.init().then(() => {
521
526
  console.log("bin init finished")
522
527
  if (this.homedir) {
523
528
  this.shell.init().then(async () => {
529
+ this.bin.check_bin()
524
530
  if (this.envs) {
525
531
  this.template.update({
526
532
  env: this.envs,
@@ -587,12 +593,16 @@ class Kernel {
587
593
  })
588
594
  }
589
595
  })
596
+ console.timeEnd(">>>>>>>>>>>>>> C bin.init")
590
597
  let ts2 = Date.now()
598
+ console.time(">>>>>>>>>>>>>> D api.init")
591
599
  await this.api.init()
600
+ console.timeEnd(">>>>>>>>>>>>>> D api.init")
592
601
 
593
602
  //await this.shell.init()
594
603
 
595
604
  if (this.homedir) {
605
+ console.time(">>>>>>>>>>>>>> E template.init")
596
606
  await this.template.init({
597
607
  kernel: this,
598
608
  system,
@@ -602,13 +612,18 @@ class Kernel {
602
612
  return this.api.get_proxy_url("/proxy", port)
603
613
  },
604
614
  })
615
+ console.timeEnd(">>>>>>>>>>>>>> E template.init")
616
+ console.time(">>>>>>>>>>>>>> F sys.init")
605
617
  this.sys = new Sysinfo()
606
618
  await this.sys.init(this)
619
+ console.timeEnd(">>>>>>>>>>>>>> F sys.init")
607
620
  let info = this.sys.info
608
621
 
609
622
  this.sysinfo = info
610
623
 
624
+ console.time(">>>>>>>>>>>>>> G getInfo")
611
625
  await this.getInfo()
626
+ console.timeEnd(">>>>>>>>>>>>>> G getInfo")
612
627
 
613
628
  await fs.promises.mkdir(this.path("logs"), { recursive: true }).catch((e) => { })
614
629
  await fs.promises.writeFile(this.path("logs/system.json"), JSON.stringify(this.i, null, 2))
@@ -692,6 +707,7 @@ class Kernel {
692
707
  this.template.update(info)
693
708
  this.sysinfo = info
694
709
  this.gpu = info.gpu
710
+ this.gpu_model = info.gpu_model
695
711
  this.gpus = info.gpus
696
712
  } catch (e) {
697
713
  console.log("sysinfo error", e)
package/kernel/shell.js CHANGED
@@ -103,6 +103,9 @@ class Shell {
103
103
  if (this.env.CMAKE_GENERATOR) {
104
104
  delete this.env.CMAKE_GENERATOR
105
105
  }
106
+
107
+ this.env.NPM_CONFIG_PREFIX = this.kernel.path("bin/npm")
108
+ this.env.npm_config_prefix = this.kernel.path("bin/npm")
106
109
 
107
110
  // if (this.env.CUDA_HOME) {
108
111
  // delete this.env.CUDA_HOME
@@ -288,7 +291,7 @@ class Shell {
288
291
  }
289
292
  emit(message) {
290
293
  if (this.ptyProcess) {
291
- console.log("write", { message, input: this.input })
294
+ // console.log("write", { message, input: this.input })
292
295
  if (this.input) {
293
296
  this.ptyProcess.write(message)
294
297
  }
@@ -1015,7 +1018,11 @@ ${cleaned}
1015
1018
 
1016
1019
  }
1017
1020
  stream(msg, callback) {
1018
- console.log("vt write", msg)
1021
+ if (msg === "\u0007") {
1022
+ // Ignore bell sound escape character because it slows down everything and makes redundant sound
1023
+ callback()
1024
+ return
1025
+ }
1019
1026
  this.vt.write(msg, () => {
1020
1027
  let buf = this.vts.serialize()
1021
1028
  let cleaned = this.stripAnsi(buf)
@@ -1023,9 +1030,10 @@ ${cleaned}
1023
1030
  id: this.id,
1024
1031
  raw: msg,
1025
1032
  cleaned,
1026
- state: cleaned
1033
+ state: cleaned,
1034
+ shell_id: this.id
1027
1035
  }
1028
- console.log({ response })
1036
+ this.state = cleaned
1029
1037
  if (this.cb) this.cb(response)
1030
1038
 
1031
1039
  // Decide whether to kill or continue
package/kernel/sysinfo.js CHANGED
@@ -5,48 +5,68 @@ class Sysinfo {
5
5
  async init(kernel) {
6
6
  this.kernel = kernel
7
7
  this.info = {}
8
- await this.static()
9
- await this.refresh()
8
+ await Promise.all([this.static, this.refresh])
9
+ // await this.static()
10
+ // await this.refresh()
10
11
  }
11
12
  async static() {
12
- await this.gpus()
13
- await this.system()
14
- await this.cpu()
15
- await this.os()
16
- await this.audio()
17
- await this.env()
13
+ await Promise.all([this.gpus, this.system, this.cpu, this.os, this.audio, this.env])
14
+ // await this.gpus()
15
+ // await this.system()
16
+ // await this.cpu()
17
+ // await this.os()
18
+ // await this.audio()
19
+ // await this.env()
20
+
21
+
18
22
  // await this.disk()
19
23
  }
20
24
  async refresh() {
21
25
  // await this.time()
22
- await this.memory()
23
- await this.battery()
24
- await this.proc()
25
- await this.bluetooth()
26
+
27
+
28
+ await Promise.all([this.memory, this.battery, this.proc, this.bluetooth])
29
+ // await this.memory()
30
+ // await this.battery()
31
+ // await this.proc()
32
+ // await this.bluetooth()
33
+ //
34
+
35
+
26
36
  // await this.net()
27
37
  }
28
38
  async gpus() {
29
39
  let g = await system.graphics()
30
40
  let gpus
31
41
  if (g && g.controllers && g.controllers.length > 0) {
32
- gpus = g.controllers.map((x) => { return x.vendor.toLowerCase() })
42
+ gpus = g.controllers.map((x) => {
43
+ return {
44
+ name: x.vendor.toLowerCase(),
45
+ model: x.model.toLowerCase()
46
+ }
47
+ })
33
48
  } else {
34
49
  gpus = []
35
50
  }
36
51
 
37
- let is_nvidia = gpus.find(gpu => /nvidia/i.test(gpu))
38
- let is_amd = gpus.find(gpu => /(amd|advanced micro devices)/i.test(gpu))
39
- let is_apple = gpus.find(gpu => /apple/i.test(gpu))
52
+ let is_nvidia = gpus.find(gpu => /nvidia/i.test(gpu.name))
53
+ let is_amd = gpus.find(gpu => /(amd|advanced micro devices)/i.test(gpu.name))
54
+ let is_apple = gpus.find(gpu => /apple/i.test(gpu.name))
40
55
 
41
56
  let gpu
57
+ let gpu_model
42
58
  if (is_nvidia) {
43
59
  gpu = "nvidia"
60
+ gpu_model = is_nvidia.model
44
61
  } else if (is_amd) {
45
62
  gpu = "amd"
63
+ gpu_model = is_amd.model
46
64
  } else if (is_apple) {
47
65
  gpu = "apple"
66
+ gpu_model = is_apple.model
48
67
  } else if (gpus.length > 0) {
49
- gpu = gpus[0]
68
+ gpu = gpus[0].name
69
+ gpu_model = gpus[0].model
50
70
  } else {
51
71
  gpu = "none"
52
72
  }
@@ -54,6 +74,7 @@ class Sysinfo {
54
74
  this.info.graphics = g
55
75
  this.info.gpus = gpus
56
76
  this.info.gpu = gpu
77
+ this.info.gpu_model = gpu_model
57
78
 
58
79
  }
59
80
  // async time() {