pinokiod 3.8.148 → 3.8.150

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 (45) hide show
  1. package/kernel/api/index.js +0 -10
  2. package/kernel/api/script/index.js +0 -2
  3. package/kernel/bin/caddy.js +6 -9
  4. package/kernel/bin/conda.js +4 -9
  5. package/kernel/bin/index.js +213 -81
  6. package/kernel/bin/setup.js +130 -0
  7. package/kernel/environment.js +50 -1
  8. package/kernel/index.js +15 -60
  9. package/kernel/info.js +0 -3
  10. package/kernel/kv.js +3 -0
  11. package/kernel/loader.js +3 -12
  12. package/kernel/peer.js +11 -16
  13. package/kernel/procs.js +1 -4
  14. package/kernel/prototype.js +12 -9
  15. package/kernel/router/common.js +31 -41
  16. package/kernel/router/connector.js +33 -64
  17. package/kernel/router/index.js +51 -124
  18. package/kernel/router/localhost_home_router.js +7 -18
  19. package/kernel/router/localhost_variable_router.js +0 -1
  20. package/kernel/router/peer_port_router.js +2 -3
  21. package/kernel/router/processor.js +0 -3
  22. package/kernel/shell.js +0 -23
  23. package/kernel/shells.js +0 -16
  24. package/package.json +1 -1
  25. package/server/index.js +145 -318
  26. package/server/public/fscreator.js +1 -1
  27. package/server/public/install.js +2 -2
  28. package/server/public/style.css +4 -0
  29. package/server/socket.js +0 -27
  30. package/server/views/bootstrap.ejs +6 -1
  31. package/server/views/download.ejs +7 -1
  32. package/server/views/editor.ejs +7 -3
  33. package/server/views/file_explorer.ejs +7 -1
  34. package/server/views/index.ejs +7 -1
  35. package/server/views/install.ejs +8 -5
  36. package/server/views/minterm.ejs +7 -3
  37. package/server/views/network.ejs +3 -1
  38. package/server/views/prototypes.ejs +1 -1
  39. package/server/views/setup.ejs +254 -0
  40. package/server/views/setup_home.ejs +181 -0
  41. package/server/views/terminal.ejs +7 -4
  42. package/kernel/caddy2.js +0 -666
  43. package/kernel/peer2.js +0 -83
  44. package/kernel/router/root.js +0 -54
  45. package/kernel/tree-kill.js +0 -167
@@ -119,10 +119,8 @@ class Api {
119
119
  return result
120
120
  }
121
121
  async stop(req, ondata) {
122
- console.log(">>>>>>>>>>>>>>>>>> STOP")
123
122
  // 1. set the "stop" flag for the uri, so the next execution in the queue for the uri will NOT queue another task
124
123
  // 2. stream a message closing the socket
125
- console.time("stop 1")
126
124
 
127
125
  let requestPath = this.filePath(req.params.uri)
128
126
 
@@ -132,9 +130,6 @@ class Api {
132
130
  await this.process(script.on.stop)
133
131
  }
134
132
  }
135
- console.timeEnd("stop 1")
136
-
137
- console.time("stop 2")
138
133
  // reset modules
139
134
  let modpath = this.resolvePath(cwd, req.params.uri)
140
135
  console.log("STOP modpath", modpath)
@@ -160,15 +155,11 @@ class Api {
160
155
 
161
156
  // stop all proxies
162
157
  this.stopProxy({ script: requestPath })
163
- console.timeEnd("stop 2")
164
158
 
165
159
  // stop all cloudflare tunnels
166
160
 
167
- console.time("stop 3")
168
161
  await this.kernel.stopCloudflare({ path: requestPath })
169
- console.timeEnd("stop 3")
170
162
 
171
- console.time("stop 4")
172
163
 
173
164
  // if there are any pending waiters, delete them
174
165
 
@@ -185,7 +176,6 @@ class Api {
185
176
  id: requestPath,
186
177
  type: "disconnect"
187
178
  })
188
- console.timeEnd("stop 4")
189
179
  this.kernel.refresh(true)
190
180
  return true
191
181
  }
@@ -1,7 +1,6 @@
1
1
  const path = require('path')
2
2
  class Script {
3
3
  async start(req, ondata, kernel) {
4
- console.log(">>>>>>>>> script.start", req)
5
4
  let res = await this.run(req, ondata, kernel)
6
5
  return res
7
6
  }
@@ -44,7 +43,6 @@ class Script {
44
43
  */
45
44
  // if already running, print that it's already running
46
45
  let id = kernel.api.filePath(req.params.uri, req.cwd)
47
- console.log({ id , uri: req.params.uri, cwd: req.cwd })
48
46
  if (kernel.api.running[id]) {
49
47
  let msg = `${req.params.uri} already running. Continuing...\r\n`
50
48
  ondata({ raw: msg })
@@ -20,9 +20,11 @@ class Caddy {
20
20
  }
21
21
  }
22
22
  async start() {
23
+ // console.log(">> proc", this.kernel.processes.caddy_pid, this.kernel.processes.info)
23
24
  // let running = await this.running()
24
25
  // console.log("Running", running)
25
26
  // if (running) {
27
+ // // kill first
26
28
  // return
27
29
  // }
28
30
  let installed = await this.installed()
@@ -77,7 +79,6 @@ class Caddy {
77
79
  ondata(e)
78
80
  })
79
81
  } else {
80
- console.log("req", req)
81
82
  ondata({
82
83
  title: "Password",
83
84
  description: "Enter your system password to add the HTTPS certificate",
@@ -88,9 +89,7 @@ class Caddy {
88
89
  placeholder: "System password",
89
90
  }]
90
91
  }, "input")
91
- console.log("Wait until", id)
92
92
  let response = await this.kernel.api.wait(id)
93
- console.log({ response })
94
93
  await this.kernel.exec({
95
94
  message: `echo ${response.password} | sudo -S caddy trust`,
96
95
  path: this.kernel.homedir
@@ -102,15 +101,9 @@ class Caddy {
102
101
  // }
103
102
  })
104
103
  }
105
- console.log("FINISHED")
106
104
  }
107
105
  async installed() {
108
- // let e = true
109
106
  let e = await this.kernel.exists(this.kernel.path("cache/XDG_DATA_HOME/caddy/pki/authorities/local/root.crt"))
110
- // let exists = await this.kernel.exists(this.kernel.path("cache/XDG_DATA_HOME/caddy/certificates/local/pinokio.localhost/pinokio.localhost.crt"))
111
- // let exists2 = await this.kernel.exists(this.kernel.path("cache/XDG_DATA_HOME/caddy/certificates/local/pinokio.localhost/pinokio.localhost.key"))
112
- // if (exists && exists2) {
113
- console.log("checking installed", e)
114
107
  if (e) {
115
108
  if (this.kernel.platform === "win32") {
116
109
  return this.kernel.bin.installed.conda.has("caddy")
@@ -122,9 +115,13 @@ class Caddy {
122
115
  }
123
116
  }
124
117
  async uninstall(req, ondata) {
118
+ ondata({ raw: "cleaning up\r\n" })
125
119
  await this.kernel.bin.exec({
126
120
  message: `conda remove ${this.cmd()}`,
127
121
  }, ondata)
122
+ const folder = this.kernel.path("cache/XDG_DATA_HOME/caddy")
123
+ await rimraf(folder)
124
+ ondata({ raw: "finished cleaning up\r\n" })
128
125
  }
129
126
  }
130
127
  module.exports = Caddy
@@ -120,10 +120,9 @@ report_errors: false`)
120
120
  // }
121
121
  async check() {
122
122
  let res = await this.kernel.bin.exec({ message: `conda list` }, (stream) => {
123
- process.stdout.write(stream.raw)
123
+ // process.stdout.write(stream.raw)
124
124
  // console.log("conda list check", { stream })
125
125
  })
126
- console.log("2 conda list check", res)
127
126
 
128
127
  let lines = res.response.split(/[\r\n]+/)
129
128
  let conda_check = {}
@@ -179,7 +178,6 @@ report_errors: false`)
179
178
  }
180
179
  }
181
180
  }
182
- console.log("> Check", { conda_check, conda })
183
181
  this.kernel.bin.installed.conda = conda
184
182
  return conda_check.conda && conda_check.mamba && conda_check.sqlite
185
183
  //return conda_check.conda && conda_check.mamba
@@ -254,16 +252,16 @@ report_errors: false`)
254
252
  // 3. so after conda update --all, it should be conda-libmamba-solver=24.11.1
255
253
 
256
254
  let mods = this.kernel.bin.mods.filter((m) => {
257
- return ["zip", "uv", "node", "huggingface", "gxx", "git", "ffmpeg", "caddy"].includes(m.name)
255
+ return req.dependencies.includes(m.name)
256
+ // return ["zip", "uv", "node", "huggingface", "gxx", "git", "ffmpeg", "caddy"].includes(m.name)
258
257
  }).map((m) => {
259
258
  return m.mod.cmd()
260
259
  }).join(" ")
261
- console.log("To install", { mods })
260
+ console.log("Conda dependencies to install", { mods })
262
261
 
263
262
  let cmds = [
264
263
  //"conda clean -y --index-cache",
265
264
  "conda clean -y --all",
266
- //"conda install -y -c conda-forge sqlite=3.47.2",
267
265
  `conda install -y -c conda-forge sqlite=3.47.2 ${mods}`,
268
266
 
269
267
  // `conda config --file ${this.kernel.path('condarc')} --set remote_connect_timeout_secs 20`,
@@ -377,9 +375,6 @@ report_errors: false`)
377
375
  let e
378
376
  for(let p of this.paths[this.kernel.platform]) {
379
377
  let e = await this.kernel.bin.exists(p)
380
- console.log("kernel.bin.conda.installed")
381
- console.log("e", e)
382
- console.log("correct_conda", this.kernel.bin.correct_conda)
383
378
  if (e && this.kernel.bin.correct_conda) return true
384
379
  }
385
380
  return false
@@ -28,6 +28,7 @@ const semver = require('semver')
28
28
  const Environment = require('../environment')
29
29
  //const imageToAscii = require("image-to-ascii");
30
30
 
31
+ const Setup = require('./setup')
31
32
 
32
33
 
33
34
  //const Puppet = require("./puppeteer")
@@ -344,11 +345,8 @@ class Bin {
344
345
  this.correct_conda = false
345
346
  } else {
346
347
  res = await this.exec({ message: `conda list` }, (stream) => {
347
- process.stdout.write(stream.raw)
348
348
  // console.log("conda list check", { stream })
349
349
  })
350
- console.log("1 conda list check", res)
351
-
352
350
 
353
351
  let lines = res.response.split(/[\r\n]+/)
354
352
  for(let line of lines) {
@@ -401,7 +399,6 @@ class Bin {
401
399
  }
402
400
  }
403
401
  }
404
- console.log("conda_check", conda_check)
405
402
 
406
403
  if (conda_check.conda && conda_check.mamba && conda_check.sqlite) {
407
404
  //if (conda_check.conda && conda_check.mamba) {
@@ -440,33 +437,6 @@ class Bin {
440
437
  }
441
438
  }
442
439
 
443
- // // 2. pip
444
- // let pip = new Set()
445
- // if (conda_exists) {
446
- // // conda comes with pip
447
- // console.log("## check pip")
448
- // start = false
449
- // res = await this.exec({ message: `pip list` }, (stream) => {
450
- //// console.log("pip list check", { stream })
451
- // })
452
- // console.log("PIP", res.response)
453
- // lines = res.response.split(/[\r\n]+/)
454
- // for(let line of lines) {
455
- // if (start) {
456
- // let chunks = line.split(/\s+/).filter(x => x)
457
- // if (chunks.length > 1) {
458
- // pip.add(chunks[0])
459
- // }
460
- // } else {
461
- // if (/-------.*/i.test(line)) {
462
- // start = true
463
- // }
464
- // }
465
- // }
466
- // }
467
- // this.installed.pip = pip
468
-
469
-
470
440
  if (this.platform === "darwin") {
471
441
  // 3. brew
472
442
  console.log("## check brew")
@@ -668,11 +638,11 @@ class Bin {
668
638
  }
669
639
  }
670
640
  async install2(req, ondata) {
671
- let { requirements, install_required, requirements_pending, error } = await this.check_bin()
641
+ let { requirements, install_required, requirements_pending, error } = await this.check({
642
+ bin: this.preset("ai")
643
+ })
672
644
  req.params = JSON.stringify(requirements)
673
- console.log(">>>>> 1")
674
645
  if (this.install_required) {
675
- console.log(">>>>> 2")
676
646
  let res = await this.install(req, ondata)
677
647
  return res
678
648
  }
@@ -695,13 +665,7 @@ class Bin {
695
665
  } else {
696
666
  this.client = null
697
667
  }
698
-
699
- console.log("install", req)
700
-
701
668
  let requirements = JSON.parse(req.params)
702
-
703
- console.time("### Total Install")
704
-
705
669
  for(let x=0; x<10; x++) {
706
670
  console.log(`## Install Attempt ${x}`)
707
671
  let i = 0;
@@ -715,9 +679,7 @@ class Bin {
715
679
  console.log("already installed. skip.")
716
680
  } else {
717
681
  console.log("not installed. install.")
718
- console.time("############# Install " +requirement.name)
719
682
  await this.tryInstall(req.id, requirement, x, i, requirements.length, ondata)
720
- console.timeEnd("############# Install " +requirement.name)
721
683
  }
722
684
  }
723
685
 
@@ -773,28 +735,38 @@ class Bin {
773
735
  // }
774
736
  // }
775
737
  //}
776
- console.timeEnd("### Total Install")
777
738
  if (this.kernel.shell) {
778
739
  console.log(">>> shell reset")
779
740
  this.kernel.shell.reset()
780
741
  }
781
742
  await this.init()
782
743
  }
783
- async installed(r) {
744
+ async check_installed(r, dependencies) {
784
745
  if (Array.isArray(r.name)) {
785
746
  for(let name of r.name) {
786
- let installed = await this._installed(name, r.type)
747
+ let installed = await this._installed(name, r.type, dependencies)
787
748
  if (!installed) return false
788
749
  }
789
750
  return true
790
751
  } else {
791
- let installed = await this._installed(r.name, r.type)
752
+ let installed = await this._installed(r.name, r.type, dependencies)
792
753
  return installed
793
754
  }
794
755
  }
795
- async _installed(name, type) {
756
+ async _installed(name, type, dependencies) {
796
757
  if (type === "conda") {
797
- return this.installed.conda.has(name)
758
+ let conda_installed = this.installed.conda.has(name)
759
+ console.log({ dependencies })
760
+ let dependencies_installed = true
761
+ for(let d of dependencies) {
762
+ console.log("checking dependency", d)
763
+ if(!this.installed.conda.has(d)) {
764
+ dependencies_installed = false
765
+ console.log("not installed", d)
766
+ break
767
+ }
768
+ }
769
+ return conda_installed && dependencies_installed
798
770
  } else if (type === "pip") {
799
771
  return this.installed.pip && this.installed.pip.has(name)
800
772
  } else if (type === "brew") {
@@ -810,50 +782,205 @@ class Bin {
810
782
  return installed
811
783
  }
812
784
  }
813
- async check_bin() {
814
- let requirements = [
815
- { name: "conda", },
816
- { name: "git", },
817
- { name: "zip", },
818
- { name: "node", },
819
- { name: "ffmpeg", },
820
- { name: "caddy", }
821
- ]
785
+ preset(mode) {
786
+ return Setup[mode](this.kernel)
787
+ }
788
+ requirements(config) {
789
+ let requirements = config.bin.requirements
790
+ if (config.script && config.script.requires && config.script.requires.length > 0) {
791
+ /*********************************************************************
792
+
793
+ {
794
+ requires: [{
795
+ platform,
796
+ type,
797
+ name,
798
+ args
799
+ }, {
800
+ platform,
801
+ type,
802
+ name,
803
+ args
804
+ }],
805
+ run: [{
806
+ ...
807
+ }]
808
+ }
809
+
810
+ syntax :=
811
+
812
+ {
813
+ platform: <win32|darwin|linux>,
814
+ type: <conda|pip|brew|none>,
815
+ name: <package name>, (example: "ffmpeg", "git")
816
+ args: <install command flags> (example: "-c conda-forge")
817
+ }
818
+
819
+
820
+ 1. pinokio native install: no need for specifying platforms since they are included
821
+
822
+ {
823
+ name: "conda"
824
+ }
825
+
826
+
827
+ 2. non native install (conda, pip, brew)
828
+
829
+ 2.1. Same on all platforms
830
+
831
+ [{
832
+ type: "conda",
833
+ name: "ffmpeg",
834
+ args: "-c conda-forge"
835
+ }]
836
+
837
+ 2.2. Specify per platform
838
+
839
+
840
+ [
841
+ { name: "conda" },
842
+ { platform: "darwin", type: "brew", name: "llvm" },
843
+ { platform: "linux", tyoe: "conda", name: "llvm", args: "-c conda-forge llvm" },
844
+ { platform: "win32", tyoe: "conda", name: "llvm", args: "-c conda-forge llvm" }
845
+ ]
846
+
847
+ [
848
+ { name: "conda" },
849
+ { platform: ["darwin", "linux"], type: "brew", name: "llvm" },
850
+ { platform: "win32", tyoe: "conda", name: "llvm", args: "-c conda-forge llvm" }
851
+ ]
852
+
853
+
854
+
855
+ *********************************************************************/
856
+ let type_name_set = new Set()
857
+ for(let r of config.script.requires) {
858
+ // if no platform specified, or if the specified platform matches the current platform
859
+ if (!r.platform || platform === r.platform || Array.isArray(r.platform) && r.platform.includes(platform) ) {
860
+ if (Array.isArray(r.name)) {
861
+ // if array, just add it
862
+ requirements.push(r)
863
+ } else {
864
+ let type_name = `${r.type ? r.type : ''}/${r.name}`
865
+ if (!type_name_set.has(type_name)) {
866
+ type_name_set.add(type_name)
867
+ requirements.push(r)
868
+ }
869
+ }
870
+ }
871
+ }
872
+
873
+ }
874
+ return requirements
875
+ }
876
+ relevant(r) {
877
+ /*
878
+ single platform
879
+ [
880
+ { name: "conda" },
881
+ { platform: "darwin", type: "brew", name: "llvm" },
882
+ { platform: "linux", tyoe: "conda", name: "llvm", args: "-c conda-forge llvm" },
883
+ { platform: "win32", tyoe: "conda", name: "llvm", args: "-c conda-forge llvm" }
884
+ ]
885
+
886
+ multiple platforms
887
+ [
888
+ { name: "conda" },
889
+ { platform: ["darwin", "linux"], type: "brew", name: "llvm" },
890
+ { platform: "win32", tyoe: "conda", name: "llvm", args: "-c conda-forge llvm" }
891
+ ]
892
+
893
+
894
+ platform & arch
895
+ [
896
+ { name: "conda" },
897
+ { platform: "darwin", arch: ["arm64", "x64"], type: "brew", name: "llvm" },
898
+ ]
899
+ */
900
+
822
901
  let platform = os.platform()
823
- if (platform === "win32") {
824
- requirements.push({ name: "registry" })
825
- requirements.push({ name: "vs" })
902
+ let arch = os.arch()
903
+ let gpu = this.kernel.gpu
904
+ let relevant = {
905
+ platform: false,
906
+ arch: false,
907
+ gpu: false,
826
908
  }
827
- if (platform === "darwin") {
828
- requirements.push({ name: "brew" })
909
+ if (r.platform) {
910
+ if (Array.isArray(r.platform)) {
911
+ // multiple items
912
+ if (r.platform.includes(platform)) {
913
+ relevant.platform = true
914
+ }
915
+ } else {
916
+ // one item
917
+ if (r.platform === platform) {
918
+ relevant.platform = true
919
+ }
920
+ }
921
+ } else {
922
+ // all platforms
923
+ relevant.platform = true
829
924
  }
830
- if (platform === "linux") {
831
- requirements.push({ name: "gxx" })
925
+ if (r.arch) {
926
+ if (Array.isArray(r.arch)) {
927
+ // multiple items
928
+ if (r.arch.includes(arch)) {
929
+ relevant.arch = true
930
+ }
931
+ } else {
932
+ // one item
933
+ if (r.arch === arch) {
934
+ relevant.arch = true
935
+ }
936
+ }
937
+ } else {
938
+ // all platforms
939
+ relevant.arch = true
832
940
  }
833
- if (this.kernel.gpu === "nvidia") {
834
- requirements.push({ name: "cuda", })
941
+ if (r.gpu) {
942
+ if (Array.isArray(r.gpu)) {
943
+ // multiple items
944
+ if (r.gpu.includes(gpu)) {
945
+ relevant.gpu = true
946
+ }
947
+ } else {
948
+ // one item
949
+ if (r.gpu === gpu) {
950
+ relevant.gpu = true
951
+ }
952
+ }
953
+ } else {
954
+ // all platforms
955
+ relevant.gpu = true
835
956
  }
836
- requirements = requirements.concat([
837
- { name: "cloudflared" },
838
- // { name: "playwright" },
839
- { name: "huggingface" },
840
- { name: "uv" },
841
- { name: "py" },
842
- ])
843
-
957
+ return relevant.platform && relevant.arch && relevant.gpu
958
+ }
959
+ async check(config) {
960
+ let requirements = this.requirements(config)
844
961
  let requirements_pending = !this.installed_initialized
845
962
  let install_required = true
846
963
  if (!requirements_pending) {
847
964
  install_required = false
848
965
  for(let i=0; i<requirements.length; i++) {
849
966
  let r = requirements[i]
850
- console.time(r.name)
851
- let installed = await this.installed(r)
852
- console.log({ r, installed })
853
- console.timeEnd(r.name)
854
- requirements[i].installed = installed
855
- if (!installed) {
856
- install_required = true
967
+ //let installed = await this.installed(r)
968
+ //requirements[i].installed = installed
969
+ //if (!installed) {
970
+ // install_required = true
971
+ //}
972
+ let relevant = this.relevant(r)
973
+ requirements[i].relevant = relevant
974
+ if (relevant) {
975
+ let dependencies
976
+ if (r.name === "conda") {
977
+ dependencies = config.bin.conda_requirements
978
+ }
979
+ let installed = await this.check_installed(r, dependencies)
980
+ requirements[i].installed = installed
981
+ if (!installed) {
982
+ install_required = true
983
+ }
857
984
  }
858
985
  }
859
986
  }
@@ -870,6 +997,11 @@ class Bin {
870
997
  this.requirements_pending = requirements_pending
871
998
 
872
999
  console.log("check_bin finished 2")
1000
+
1001
+ requirements = requirements.filter((r) => {
1002
+ return r.relevant
1003
+ })
1004
+
873
1005
  return {
874
1006
  error,
875
1007
  requirements,
@@ -0,0 +1,130 @@
1
+ const os = require('os')
2
+ let platform = os.platform()
3
+ module.exports = {
4
+ ai: (kernel) => {
5
+ let conda_requirements = [
6
+ "uv",
7
+ "node",
8
+ "huggingface",
9
+ "git",
10
+ "ffmpeg",
11
+ // "caddy"
12
+ ]
13
+ let requirements = [
14
+ { name: "conda", },
15
+ { name: "git", },
16
+ // { name: "zip", },
17
+ { name: "node", },
18
+ { name: "ffmpeg", },
19
+ // { name: "caddy", }
20
+ ]
21
+ if (platform === "win32") {
22
+ requirements.push({ name: "registry" })
23
+ requirements.push({ name: "vs" })
24
+ }
25
+ if (platform === "darwin") {
26
+ requirements.push({ name: "brew" })
27
+ }
28
+ if (platform === "linux") {
29
+ requirements.push({ name: "gxx" })
30
+ conda_requirements.push("gxx")
31
+ }
32
+ if (kernel.gpu === "nvidia") {
33
+ requirements.push({ name: "cuda", })
34
+ conda_requirements.push("cuda")
35
+ }
36
+ requirements = requirements.concat([
37
+ { name: "cloudflared" },
38
+ // { name: "playwright" },
39
+ { name: "huggingface" },
40
+ { name: "uv" },
41
+ { name: "py" },
42
+ ])
43
+ return {
44
+ icon: "fa-solid fa-brain",
45
+ title: "AI",
46
+ description: "Install common modules required for running AI locally",
47
+ requirements,
48
+ conda_requirements
49
+ }
50
+ },
51
+ javascript: (kernel) => {
52
+ return {
53
+ icon: "fa-brands fa-js",
54
+ title: "Node.js",
55
+ description: "Set up self-contained node.js development environment",
56
+ requirements: [
57
+ { name: "conda", },
58
+ { name: "git", },
59
+ { name: "node", },
60
+ ],
61
+ conda_requirements: [
62
+ "node",
63
+ "git",
64
+ ]
65
+ }
66
+ },
67
+ python: (kernel) => {
68
+ return {
69
+ icon: "fa-brands fa-python",
70
+ title: "Python",
71
+ description: "Set up self-contained python development environment",
72
+ requirements: [
73
+ { name: "conda", },
74
+ { name: "git", },
75
+ { name: "uv", },
76
+ ],
77
+ conda_requirements: [
78
+ "uv",
79
+ "git",
80
+ ]
81
+ }
82
+ },
83
+ dev: (kernel) => {
84
+ let requirements = [
85
+ { name: "conda", },
86
+ { name: "git", },
87
+ { name: "node", },
88
+ { name: "uv", },
89
+ ]
90
+ let conda_requirements = [
91
+ "uv",
92
+ "node",
93
+ "git",
94
+ ]
95
+ if (platform === "win32") {
96
+ requirements.push({ name: "registry" })
97
+ requirements.push({ name: "vs" })
98
+ }
99
+ if (platform === "darwin") {
100
+ requirements.push({ name: "brew" })
101
+ }
102
+ if (platform === "linux") {
103
+ requirements.push({ name: "gxx" })
104
+ conda_requirements.push("gxx")
105
+ }
106
+ return {
107
+ icon: "fa-solid fa-laptop-code",
108
+ title: "Coding",
109
+ description: "Install common modules required for development (Node.js, python, Visual Studio Developer Tools (Windows), Xcode build tools (Mac)",
110
+ requirements,
111
+ conda_requirements,
112
+ }
113
+ },
114
+ network: (kernel) => {
115
+ return {
116
+ icon: "fa-solid fa-wifi",
117
+ title: "Network",
118
+ description: "Automatic HTTPS and local network sharing for ALL local apps",
119
+ requirements: [
120
+ { name: "conda", },
121
+ { name: "git", },
122
+ { name: "caddy", },
123
+ ],
124
+ conda_requirements: [
125
+ "git",
126
+ "caddy"
127
+ ]
128
+ }
129
+ }
130
+ }