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.
package/kernel/util.js CHANGED
@@ -14,6 +14,9 @@ const groupReplacement = "$$$";
14
14
  const h = "[^\\S\\r\\n]"; // simulate `\h`
15
15
  const returnPattern = /\r/g;
16
16
  const returnReplacement = "\\r";
17
+ const {
18
+ glob
19
+ } = require('glob')
17
20
 
18
21
 
19
22
  // asar handling for go-get-folder-size
@@ -36,26 +39,20 @@ const du = async (folderpath) => {
36
39
  const is_port_available = async (port) => {
37
40
  return new Promise((resolve) => {
38
41
  const server = http.createServer();
39
- // console.log("> Checking port availability", port)
40
42
  try {
41
43
  server.listen(port, (err) => {
42
44
  if (err) {
43
- // console.log("> [1 port not available]", err)
44
45
  resolve(false); // Port is occupied
45
46
  } else {
46
- // console.log("> [2 port available] test server started. closing test server now.")
47
47
  server.close(() => {
48
- // console.log("> Test server closed.")
49
48
  resolve(true); // Port is free
50
49
  }); // Close the server immediately after testing
51
50
  }
52
51
  });
53
52
  server.on('error', (err) => {
54
- // console.log("> [3 port not available]", err);
55
53
  resolve(false); // Port is occupied
56
54
  });
57
55
  } catch (e) {
58
- // console.log("> [4 port not available]", err)
59
56
  resolve(false) // port not available
60
57
  }
61
58
  });
@@ -199,6 +196,30 @@ const escapeStringRegexp = (string) => {
199
196
  .replace(/-/g, '\\x2d');
200
197
  }
201
198
 
199
+ const find_python = async (root) => {
200
+ let python_pattern
201
+ if (os.platform() === "win32") {
202
+ python_pattern = "**/python.exe";
203
+ } else {
204
+ python_pattern = "**/python"; // Matches python, python3, python3.x
205
+ }
206
+ const pythonBinaries = await glob(python_pattern, { nodir: true, cwd: root });
207
+ return pythonBinaries
208
+ }
209
+ const find_venv = async (root) => {
210
+ let python_pattern
211
+ if (os.platform() === "win32") {
212
+ python_pattern = "**/python.exe";
213
+ } else {
214
+ python_pattern = "**/python"; // Matches python, python3, python3.x
215
+ }
216
+ const pythonBinaries = await glob(python_pattern, { nodir: true, cwd: root, absolute: true });
217
+ const venvs = pythonBinaries.map((p) => {
218
+ return path.resolve(p, "../..")
219
+ })
220
+ return venvs
221
+ }
222
+
202
223
  const update_env = async (filepath, changes) => {
203
224
  const env = await fs.promises.readFile(filepath, "utf8")
204
225
  let append = false;
@@ -236,5 +257,5 @@ const update_env = async (filepath, changes) => {
236
257
  await fs.promises.writeFile(filepath, newval)
237
258
  };
238
259
  module.exports = {
239
- parse_env, log_path, api_path, update_env, parse_env_detail, openfs, port_running, du, is_port_available
260
+ parse_env, log_path, api_path, update_env, parse_env_detail, openfs, port_running, du, is_port_available, find_python, find_venv
240
261
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "3.6.28",
3
+ "version": "3.6.30",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -86,30 +86,6 @@ class Server {
86
86
  exists (s) {
87
87
  return new Promise(r=>fs.access(s, fs.constants.F_OK, e => r(!e)))
88
88
  }
89
- winBuildNumber() {
90
- let osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release());
91
- let buildNumber = 0;
92
- if (osVersion && osVersion.length === 4) {
93
- buildNumber = parseInt(osVersion[3]);
94
- }
95
- return buildNumber;
96
- }
97
- compatible() {
98
- if (this.kernel.platform === "win32") {
99
- let buildNumber = this.winBuildNumber()
100
- if (buildNumber < 18309) {
101
- // must use conpty for node-pty, and conpty is only supported in win>=18309
102
- console.log("Windows buildNumber", buildNumber)
103
- throw new Error(`Pinokio supports Windows release 18309 and up (current system: ${buildNumber}`)
104
- }
105
-
106
- // if (buildNumber > 25000) {
107
- // console.log("Windows buildNumber", buildNumber)
108
- // throw new Error(`Pinokio does not currently support Windows Canary (versions 25000 and up). The current system is ${buildNumber}`)
109
- //
110
- // }
111
- }
112
- }
113
89
  getMemory(filepath) {
114
90
  let localMem = this.kernel.memory.local[filepath]
115
91
  let globalMem = this.kernel.memory.global[filepath]
@@ -145,7 +121,7 @@ class Server {
145
121
  return items.map((x) => {
146
122
  let name
147
123
  let description
148
- let icon
124
+ let icon = "/pinokio-black.png"
149
125
  let uri
150
126
  if (meta) {
151
127
  let m = meta[x.name]
@@ -154,7 +130,8 @@ class Server {
154
130
  if (m && m.icon) {
155
131
  icon = m.icon
156
132
  } else {
157
- icon = null
133
+ icon = "/pinokio-black.png"
134
+ //icon = null
158
135
  }
159
136
  uri = x.name
160
137
  } else {
@@ -194,6 +171,60 @@ class Server {
194
171
  }
195
172
  })
196
173
  }
174
+ async init_shells(dir) {
175
+ let current = this.kernel.path(dir, "SHELLS")
176
+ let exists = await this.exists(current)
177
+ if (exists) {
178
+ // SHELLS folder exists, skip
179
+ } else {
180
+ // if SHELLS doesn't exist, need to create one
181
+ // 1. if _SHELLS exists, create SHELLS by copying the contents of _SHELLS into SHELLS
182
+ // 2. if _SHELLS doesn't exist, just write SHELLS
183
+ // if _ENVIRONMENT exists,
184
+ let _shells = this.kernel.path(dir, "_SHELLS")
185
+ let _dest_shells = this.kernel.path(dir, "SHELLS")
186
+ await fs.promises.mkdir(_dest_shells).catch((e) => { })
187
+
188
+ // write _.json
189
+ let defaultShell = path.resolve(_dest_shells, "_.json")
190
+ let default_shell_exists = await this.exists(_shells)
191
+ if (!default_shell_exists) {
192
+ await fs.promises.writeFile(defaultShell, JSON.stringify({
193
+ run: [{
194
+ method: "shell.run",
195
+ params: {
196
+ message: [
197
+ "npm install -g @anthropic-ai/claude-code",
198
+ ],
199
+ }
200
+ }, {
201
+ method: "shell.run",
202
+ params: {
203
+ message: [
204
+ "claude"
205
+ ],
206
+ input: true
207
+ }
208
+ }]
209
+ }, null, 2))
210
+ }
211
+
212
+ let _exists = await this.exists(_shells)
213
+ if (_exists) {
214
+ let files = await fs.promises.readdir(_shells)
215
+ for(let file of files) {
216
+ try {
217
+ let src = path.resolve(_shells, file)
218
+ let dest = path.resolve(_dest_shells, file)
219
+ await fs.promises.cp(src, dest, { errorOnExist: true, force: false });
220
+ } catch (err) {
221
+ }
222
+ }
223
+ // } else {
224
+ // await fs.cp(_shells, _dest_shells, { recursive: true });
225
+ }
226
+ }
227
+ }
197
228
  async init_env(env_dir_path, options) {
198
229
  let current = this.kernel.path(env_dir_path, "ENVIRONMENT")
199
230
  // if environment.json doesn't exist,
@@ -301,6 +332,12 @@ class Server {
301
332
  }
302
333
  let platform = os.platform()
303
334
 
335
+ if (config.icon) {
336
+ config.icon = `${rawpath}/${config.icon}?raw=true`
337
+ } else {
338
+ config.icon = "/pinokio-black.png"
339
+ }
340
+
304
341
 
305
342
  // get all memory variable stied to the current repository
306
343
  let api_path = this.kernel.path("api", name)
@@ -323,6 +360,7 @@ class Server {
323
360
 
324
361
  await this.init_env("api/" + name)
325
362
 
363
+ await this.init_shells("api/" + name)
326
364
 
327
365
  let mode = "run"
328
366
  if (req.query && req.query.mode) {
@@ -330,7 +368,34 @@ class Server {
330
368
  }
331
369
  const env = await this.kernel.env("api/" + name)
332
370
 
371
+ let shell_path = this.kernel.path("api", name, "SHELLS")
372
+ let shells = []
373
+ try {
374
+ shells = await fs.promises.readdir(shell_path)
375
+ shells = shells.filter((s) => {
376
+ return s.endsWith(".json")
377
+ })
378
+
379
+ let s = []
380
+ for(let shell of shells) {
381
+ try {
382
+ let p = path.resolve(shell_path, shell)
383
+ console.log("3p", p)
384
+ let json = (await this.kernel.loader.load(p)).resolved
385
+ console.log(">>", { json })
386
+ if (json && json.run && Array.isArray(json.run)) {
387
+ s.push(`/api/${name}/SHELLS/${shell}`)
388
+ }
389
+ } catch (e) {
390
+ }
391
+ }
392
+ shells = s
393
+ } catch (e) {
394
+ }
395
+ console.log({ shells })
396
+
333
397
  res.render("app", {
398
+ shells,
334
399
  error,
335
400
  env,
336
401
  mode,
@@ -482,84 +547,8 @@ class Server {
482
547
  display: ["form"]
483
548
  })
484
549
  } else if (pathComponents.length === 0 && req.query.mode === "download") {
485
-
486
- let requirements = [{
487
- name: "conda",
488
- }, {
489
- name: "git",
490
- }, {
491
- name: "zip",
492
- }, {
493
- name: "node",
494
- }, {
495
- name: "ffmpeg",
496
- // type: "conda",
497
- // name: "ffmpeg",
498
- // args: "-c conda-forge"
499
- }]
500
- let platform = os.platform()
501
- if (platform === "win32") {
502
- requirements.push({
503
- name: "registry"
504
- })
505
- requirements.push({
506
- name: "vs"
507
- })
508
- }
509
- if (platform === "darwin") {
510
- requirements.push({
511
- name: "brew"
512
- })
513
- }
514
- if (platform === "linux") {
515
- requirements.push({
516
- name: "gxx"
517
- })
518
- }
519
- if (this.kernel.gpu === "nvidia") {
520
- requirements.push({
521
- name: "cuda",
522
- })
523
- }
524
- requirements = requirements.concat([{
525
- name: "py"
526
- }, {
527
- name: "cloudflared"
528
- }, {
529
- name: "playwright"
530
- }, {
531
- name: "huggingface"
532
- }, {
533
- name: "uv"
534
- }])
535
-
536
- let requirements_pending = !this.kernel.bin.installed_initialized
537
-
538
-
539
- let install_required = true
540
- if (!requirements_pending) {
541
- install_required = false
542
- for(let i=0; i<requirements.length; i++) {
543
- let r = requirements[i]
544
- console.time(r.name)
545
- let installed = await this.installed(r)
546
- console.log({ r, installed })
547
- console.timeEnd(r.name)
548
- requirements[i].installed = installed
549
- if (!installed) {
550
- install_required = true
551
- }
552
- }
553
- }
554
-
555
- let error = null
556
- try {
557
- this.compatible()
558
- } catch (e) {
559
- error = e.message
560
- install_required = true
561
- }
562
-
550
+ let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check_bin()
551
+ console.log({ requirements, install_required, requirements_pending })
563
552
 
564
553
  res.render("download", {
565
554
  error,
@@ -919,7 +908,7 @@ class Server {
919
908
 
920
909
  let error = null
921
910
  try {
922
- this.compatible()
911
+ this.kernel.bin.compatible()
923
912
  } catch (e) {
924
913
  error = e.message
925
914
  install_required = true
@@ -1281,7 +1270,7 @@ class Server {
1281
1270
  //let name = (x.name.startsWith("0x") ? Buffer.from(x.name.slice(2), "hex").toString() : x.name)
1282
1271
  let name
1283
1272
  let description
1284
- let icon
1273
+ let icon = "/pinokio-black.png"
1285
1274
  let uri
1286
1275
  if (meta) {
1287
1276
  let m = meta[x.name]
@@ -1290,7 +1279,8 @@ class Server {
1290
1279
  if (m && m.icon) {
1291
1280
  icon = m.icon
1292
1281
  } else {
1293
- icon = null
1282
+ //icon = null
1283
+ icon = "/pinokio-black.png"
1294
1284
  }
1295
1285
  uri = x.name
1296
1286
  } else {
@@ -2065,6 +2055,7 @@ class Server {
2065
2055
  }
2066
2056
  }
2067
2057
  async start(options) {
2058
+ console.time("###### ALL")
2068
2059
 
2069
2060
  // // ONLY start if not already running
2070
2061
  // let is_running = await this.running(this.port || DEFAULT_PORT)
@@ -2074,6 +2065,7 @@ class Server {
2074
2065
  // }
2075
2066
  //
2076
2067
 
2068
+ console.time("######### 1")
2077
2069
  this.debug = false
2078
2070
  if (options) {
2079
2071
  this.debug = options.debug
@@ -2105,10 +2097,14 @@ class Server {
2105
2097
  // } catch (e) {
2106
2098
  // }
2107
2099
  }
2100
+ console.timeEnd("######### 1")
2108
2101
 
2109
2102
  // configure from kernel.store
2103
+ console.time("###### 2 syncConfig")
2110
2104
  await this.syncConfig()
2105
+ console.timeEnd("###### 2 syncConfig")
2111
2106
 
2107
+ console.time("###### 3 startLogging")
2112
2108
  try {
2113
2109
  let _home = this.kernel.store.get("home")
2114
2110
  console.log({ _home })
@@ -2118,6 +2114,7 @@ class Server {
2118
2114
  } catch (e) {
2119
2115
  console.log("start logging attempt", e)
2120
2116
  }
2117
+ console.timeEnd("###### 3 startLogging")
2121
2118
 
2122
2119
  // determine port if port is not passed in
2123
2120
 
@@ -2172,15 +2169,19 @@ class Server {
2172
2169
  console.log("[DONE] Updating to the new version")
2173
2170
  }
2174
2171
  }
2175
-
2172
+ console.time("###### 4 kernel.init")
2176
2173
  // initialize kernel
2177
2174
  await this.kernel.init({ port: this.port})
2175
+ console.timeEnd("###### 4 kernel.init")
2178
2176
 
2179
2177
  console.log({ needInitHome })
2178
+ console.time("###### 5 initHome")
2180
2179
  if (needInitHome) {
2181
2180
  await this.kernel.initHome()
2182
2181
  }
2182
+ console.timeEnd("###### 5 initHome")
2183
2183
 
2184
+ console.time("###### 6")
2184
2185
  if (this.kernel.homedir) {
2185
2186
  let ex = await this.kernel.exists(this.kernel.homedir, "ENVIRONMENT")
2186
2187
  if (!ex) {
@@ -2188,6 +2189,7 @@ class Server {
2188
2189
  await fs.promises.writeFile(path.resolve(this.kernel.homedir, "ENVIRONMENT"), str)
2189
2190
  }
2190
2191
  }
2192
+ console.timeEnd("###### 6")
2191
2193
 
2192
2194
 
2193
2195
 
@@ -2272,6 +2274,7 @@ class Server {
2272
2274
 
2273
2275
 
2274
2276
  //await this.configure()
2277
+ console.time("###### 7")
2275
2278
 
2276
2279
  this.started = false
2277
2280
  this.app = express();
@@ -2518,6 +2521,20 @@ class Server {
2518
2521
  let str = await fs.promises.readFile(req.query.logpath, "utf8")
2519
2522
  res.send(str)
2520
2523
  }))
2524
+ this.app.post("/mkdir", ex(async (req, res) => {
2525
+ let folder = req.body.folder
2526
+ let folder_path = path.resolve(this.kernel.api.userdir, req.body.folder)
2527
+ try {
2528
+ await fs.promises.mkdir(folder_path)
2529
+ res.json({
2530
+ success: "/pinokio/browser/"+folder
2531
+ })
2532
+ } catch (e) {
2533
+ res.json({
2534
+ error: e.message
2535
+ })
2536
+ }
2537
+ }))
2521
2538
  this.app.post("/proxy", ex(async (req, res) => {
2522
2539
  /*
2523
2540
  req.body := {
@@ -2655,6 +2672,8 @@ class Server {
2655
2672
  }
2656
2673
  if (config.icon) {
2657
2674
  config.icon = `/${env_path}/${config.icon}?raw=true`
2675
+ } else {
2676
+ config.icon = "/pinokio-black.png"
2658
2677
  }
2659
2678
 
2660
2679
  let name
@@ -2715,6 +2734,8 @@ class Server {
2715
2734
  config.pre.forEach((item) => {
2716
2735
  if (item.icon) {
2717
2736
  item.icon = `/api/${req.params.name}/${item.icon}?raw=true`
2737
+ } else {
2738
+ item.icon = "/pinokio-black.png"
2718
2739
  }
2719
2740
  if (!item.href.startsWith("http")) {
2720
2741
  item.href = path.resolve(this.kernel.homedir, "api", req.params.name, item.href)
@@ -2823,6 +2844,43 @@ class Server {
2823
2844
  }
2824
2845
  res.json({ config: this.xterm })
2825
2846
  }))
2847
+ // this.app.get("/shell", ex(async (req, res) => {
2848
+ // console.log("req.query", req.query)
2849
+ // res.render("terminal", {
2850
+ // memory: [],
2851
+ // logo: this.logo,
2852
+ // theme: this.theme,
2853
+ // run: true,
2854
+ // stop: false,
2855
+ // runnable: true,
2856
+ // agent: this.agent,
2857
+ //// uri,
2858
+ // mod: true,
2859
+ // json: true,
2860
+ // js: false,
2861
+ // install_required: false,
2862
+ // current: req.originalUrl,
2863
+ // })
2864
+ // }))
2865
+ this.app.get("/shells/:name", ex(async (req, res) => {
2866
+ let p = this.kernel.path("api", req.params.name)
2867
+ let venv_folders = await Util.find_venv(p)
2868
+ console.log({ venv_folders })
2869
+ let items = venv_folders.map((f) => {
2870
+ let args = {
2871
+ message: "",
2872
+ venv: f
2873
+ }
2874
+ return {
2875
+ name: f,
2876
+ cmd: new URLSearchParams(args).toString()
2877
+ }
2878
+ })
2879
+ console.log({ items })
2880
+ res.json({
2881
+ items
2882
+ })
2883
+ }))
2826
2884
  this.app.get("/du/:name", ex(async (req, res) => {
2827
2885
  let p = this.kernel.path("api", req.params.name)
2828
2886
  let d1 = await Util.du(p)
@@ -3442,6 +3500,8 @@ class Server {
3442
3500
  // install
3443
3501
  this.server = httpserver.createServer(this.app);
3444
3502
  this.socket = new Socket(this)
3503
+ console.timeEnd("###### 7")
3504
+ console.time("###### 8")
3445
3505
  await new Promise((resolve, reject) => {
3446
3506
  this.listening = this.server.listen(this.port, () => {
3447
3507
  console.log(`Server listening on port ${this.port}`)
@@ -3451,6 +3511,8 @@ class Server {
3451
3511
  server: this.listening
3452
3512
  });
3453
3513
  })
3514
+ console.timeEnd("###### 8")
3515
+ console.timeEnd("###### ALL")
3454
3516
 
3455
3517
  }
3456
3518
  }
Binary file
Binary file
@@ -1701,6 +1701,11 @@ footer.status {
1701
1701
  text-transform: uppercase;
1702
1702
  }
1703
1703
 
1704
+ #fsmenu {
1705
+ background: rgba(0,0,100,0.04);
1706
+ display: flex;
1707
+ padding: 20px 20px 0;
1708
+ }
1704
1709
  mark{
1705
1710
  background: firebrick;
1706
1711
  color: white;