pinokiod 3.40.0 → 3.42.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 (82) hide show
  1. package/kernel/api/browser/index.js +3 -1
  2. package/kernel/api/cloudflare/index.js +3 -3
  3. package/kernel/api/index.js +187 -51
  4. package/kernel/api/loading/index.js +15 -0
  5. package/kernel/api/process/index.js +7 -0
  6. package/kernel/api/shell/index.js +0 -2
  7. package/kernel/bin/browserless.js +22 -0
  8. package/kernel/bin/caddy.js +36 -4
  9. package/kernel/bin/index.js +4 -1
  10. package/kernel/bin/setup.js +38 -5
  11. package/kernel/connect/backend.js +110 -0
  12. package/kernel/connect/config.js +171 -0
  13. package/kernel/connect/index.js +18 -7
  14. package/kernel/connect/providers/huggingface/index.js +98 -0
  15. package/kernel/connect/providers/x/index.js +0 -1
  16. package/kernel/environment.js +91 -19
  17. package/kernel/git.js +46 -3
  18. package/kernel/index.js +119 -39
  19. package/kernel/peer.js +40 -5
  20. package/kernel/plugin.js +3 -2
  21. package/kernel/procs.js +27 -20
  22. package/kernel/prototype.js +30 -16
  23. package/kernel/router/common.js +1 -1
  24. package/kernel/router/connector.js +1 -3
  25. package/kernel/router/index.js +38 -4
  26. package/kernel/router/localhost_home_router.js +5 -1
  27. package/kernel/router/localhost_port_router.js +27 -1
  28. package/kernel/router/localhost_static_router.js +93 -0
  29. package/kernel/router/localhost_variable_router.js +14 -9
  30. package/kernel/router/peer_peer_router.js +3 -0
  31. package/kernel/router/peer_static_router.js +43 -0
  32. package/kernel/router/peer_variable_router.js +15 -14
  33. package/kernel/router/processor.js +26 -1
  34. package/kernel/router/rewriter.js +59 -0
  35. package/kernel/scripts/git/commit +11 -1
  36. package/kernel/shell.js +8 -3
  37. package/kernel/util.js +65 -6
  38. package/package.json +2 -1
  39. package/server/index.js +1048 -970
  40. package/server/public/common.js +382 -1
  41. package/server/public/fscreator.js +0 -1
  42. package/server/public/loading.js +17 -0
  43. package/server/public/notifyinput.js +0 -1
  44. package/server/public/opener.js +4 -2
  45. package/server/public/style.css +310 -11
  46. package/server/socket.js +7 -1
  47. package/server/views/app.ejs +1747 -351
  48. package/server/views/columns.ejs +338 -0
  49. package/server/views/connect/huggingface.ejs +353 -0
  50. package/server/views/connect/index.ejs +410 -0
  51. package/server/views/connect/x.ejs +43 -9
  52. package/server/views/connect.ejs +709 -49
  53. package/server/views/container.ejs +357 -0
  54. package/server/views/d.ejs +251 -62
  55. package/server/views/download.ejs +54 -10
  56. package/server/views/editor.ejs +11 -0
  57. package/server/views/explore.ejs +40 -15
  58. package/server/views/file_explorer.ejs +25 -246
  59. package/server/views/form.ejs +44 -1
  60. package/server/views/frame.ejs +39 -1
  61. package/server/views/github.ejs +48 -11
  62. package/server/views/help.ejs +48 -7
  63. package/server/views/index.ejs +119 -58
  64. package/server/views/index2.ejs +3 -4
  65. package/server/views/init/index.ejs +651 -197
  66. package/server/views/install.ejs +1 -1
  67. package/server/views/mini.ejs +47 -18
  68. package/server/views/net.ejs +199 -67
  69. package/server/views/network.ejs +229 -93
  70. package/server/views/network2.ejs +3 -4
  71. package/server/views/old_network.ejs +3 -3
  72. package/server/views/prototype/index.ejs +48 -11
  73. package/server/views/review.ejs +1005 -0
  74. package/server/views/rows.ejs +341 -0
  75. package/server/views/screenshots.ejs +1020 -0
  76. package/server/views/settings.ejs +160 -23
  77. package/server/views/setup.ejs +49 -7
  78. package/server/views/setup_home.ejs +43 -10
  79. package/server/views/shell.ejs +7 -1
  80. package/server/views/start.ejs +14 -9
  81. package/server/views/terminal.ejs +13 -2
  82. package/server/views/tools.ejs +1015 -0
@@ -0,0 +1,1015 @@
1
+ <html>
2
+ <head>
3
+ <meta charset="UTF-8">
4
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
5
+ <link href="/xterm.min.css" rel="stylesheet" />
6
+ <link href="/css/fontawesome.min.css" rel="stylesheet">
7
+ <link href="/css/solid.min.css" rel="stylesheet">
8
+ <link href="/css/regular.min.css" rel="stylesheet">
9
+ <link href="/css/brands.min.css" rel="stylesheet">
10
+ <link href="/markdown.css" rel="stylesheet"/>
11
+ <link href="/noty.css" rel="stylesheet"/>
12
+ <link href="/style.css" rel="stylesheet"/>
13
+ <% if (agent === "electron") { %>
14
+ <link href="/electron.css" rel="stylesheet"/>
15
+ <% } %>
16
+ <style>
17
+ .line2 {
18
+ display: flex;
19
+ align-items: center;
20
+ cursor: pointer;
21
+ background: rgba(0,0,100,0.04);
22
+ }
23
+ .line2 a {
24
+ text-decoration: none;
25
+ color: black;
26
+ }
27
+ .status {
28
+ padding: 10px;
29
+ margin: 10px;
30
+ border-radius: 10px;
31
+ }
32
+ .status.offline {
33
+ background: silver;
34
+ }
35
+ .status.online {
36
+ background: yellowgreen;
37
+ }
38
+ .switch {
39
+ padding: 10px;
40
+ margin: 10px 0;
41
+ }
42
+ .switch[data-online=true] {
43
+ color: yellowgreen;
44
+ }
45
+ .button {
46
+ padding: 10px;
47
+ }
48
+ .on, .off {
49
+ display: flex;
50
+ align-items: center;
51
+ }
52
+ /*
53
+ .btn {
54
+ margin-right: 5px;
55
+ font-weight: normal;
56
+ padding: 5px 15px;
57
+ min-width: 100px;
58
+ text-align: center;
59
+ }
60
+ */
61
+ .items {
62
+ max-width: 600px;
63
+ margin: 50px auto;
64
+ }
65
+ body.dark .item {
66
+ border-left: 5px solid rgba(255,255,255,0.06);
67
+ }
68
+ .item {
69
+ margin: 0;
70
+ /*
71
+ border-top: 1px solid rgba(255,255,255,0.1);
72
+ border-bottom: 1px solid rgba(255,255,255,0.1);
73
+ */
74
+ padding: 10px;
75
+ border-left: 5px solid rgba(0,0,0,0.06);
76
+ }
77
+ .titleview {
78
+ margin: 0;
79
+ padding: 25px;
80
+ max-width: 600px;
81
+ }
82
+ .titleview h1 {
83
+ word-break: break-word;
84
+ font-size: 40px;
85
+ margin-bottom: 10px;
86
+ }
87
+ .item > .d {
88
+ padding-bottom: 10px;
89
+ }
90
+ .item label {
91
+ display: block;
92
+ text-transform: capitalize;
93
+ font-size: 20px;
94
+ font-weight: bold;
95
+ padding-bottom: 5px;
96
+ }
97
+ .item .explanation {
98
+ padding-top: 5px;
99
+ color: #bf411d;
100
+ font-size: 12px;
101
+ }
102
+ .item input[type=text] {
103
+ background: whitesmoke;
104
+ }
105
+ .item select {
106
+ background: whitesmoke;
107
+ }
108
+ /*
109
+ body.dark .item input[type=text] {
110
+ background: rgba(255,255,255,0.1);
111
+ color: white;
112
+ }
113
+ body.dark .item select {
114
+ color: white;
115
+ background: rgba(255,255,255,0.1);
116
+ }
117
+ */
118
+ .item input[type=text] {
119
+ padding: 10px;
120
+ flex-grow: 1;
121
+ border: none;
122
+ /*
123
+ background: rgba(0,0,0,0.05);
124
+ */
125
+ width: 100%;
126
+ }
127
+ .item select {
128
+ /*
129
+ -webkit-appearance: none;
130
+ -moz-appearance: none;
131
+ appearance: none;
132
+ */
133
+
134
+ /*
135
+ background: rgba(0,0,0,0.05);
136
+ */
137
+ padding: 10px;
138
+ box-sizing: border-box;
139
+ width: 100%;
140
+ border: none;
141
+ }
142
+ .item img {
143
+ width: 100px;
144
+ }
145
+ .item .title {
146
+ text-decoration: none;
147
+ color: royalblue;
148
+ }
149
+ .item .col {
150
+ padding: 10px;
151
+ }
152
+ .item .col > * {
153
+ margin: 5px 0;
154
+ }
155
+ .item .stat {
156
+ color: rgba(0,0,0,0.8);
157
+ display: flex;
158
+ }
159
+ .item .stat > * {
160
+ margin-right: 15px;
161
+ }
162
+ .timestamp {
163
+ color: rgba(0,0,0,0.5);
164
+ }
165
+ body.dark .loading {
166
+ background: rgba(255,255,255,0.06);
167
+ }
168
+ .loading {
169
+ padding: 20px;
170
+ text-align: center;
171
+ background: rgba(0,0,0,0.06);
172
+ }
173
+ body.dark .btn {
174
+ color: white;
175
+ background: rgba(255,255,255,0.1);
176
+ }
177
+ body.light {
178
+ /*
179
+ background: var(--light-nav-bg);
180
+ */
181
+ }
182
+ /*
183
+ form {
184
+ text-align: center;
185
+ }
186
+ body.dark header .btn2 {
187
+ color: var(--light-link-color);
188
+ }
189
+ header .btn2 {
190
+ color: var(--light-color);
191
+ }
192
+ */
193
+ /*
194
+ body.dark header .home {
195
+ color: var(--light-link-color);
196
+ }
197
+ */
198
+ header .home {
199
+ color: var(--light-color);
200
+ padding: 10px;
201
+ }
202
+ body.dark hr {
203
+ background: white;
204
+ }
205
+ hr {
206
+ opacity: 0.03;
207
+ background: black;
208
+ margin: 30px 0;
209
+ height: 1px;
210
+ border: none;
211
+ }
212
+ body.dark .config {
213
+ color: white;
214
+ }
215
+ .config {
216
+ color: black;
217
+ padding: 30px;
218
+ margin: 10px 0;
219
+ }
220
+ .config-header {
221
+ }
222
+ .config-body {
223
+ padding-top: 20px;
224
+ margin-top: 20px;
225
+ }
226
+ .config .btn {
227
+ font-size: 16px;
228
+ font-weight: bold;
229
+ width: 100px;
230
+ background: royalblue;
231
+ flex-shrink: 0;
232
+ }
233
+ .config-row {
234
+ padding: 10px 20px 0 0;
235
+ }
236
+ .label {
237
+ padding-bottom: 5px;
238
+ font-weight: bold;
239
+ }
240
+ .config-row input[type=text] {
241
+ padding: 7px;
242
+ }
243
+ .header-label {
244
+ padding: 0;
245
+ font-size: 30px;
246
+ text-transform: capitalize;
247
+ }
248
+ body.dark .container {
249
+ color: white;
250
+ }
251
+ .container {
252
+ }
253
+ .dark .container-row {
254
+ background: rgba(255, 255, 255, 0.04);
255
+ }
256
+ .container-row {
257
+ background: rgba(0, 0, 100, 0.04);
258
+ box-sizing: border-box;
259
+ }
260
+ .header-label-sub h1 {
261
+ font-size: 25px;
262
+ letter-spacing: -1px;
263
+ font-weight: lighter;
264
+ }
265
+ .header-label-sub {
266
+ font-size: 16px;
267
+ padding: 10px 0;
268
+ border-bottom: 1px solid rgba(0,0,0,0.1);
269
+ }
270
+ .header-label-sub .s {
271
+ padding: 10px 0;
272
+ opacity: 0.7;
273
+ }
274
+ body.dark .section-header {
275
+ }
276
+ .section-header {
277
+ font-weight: normal;
278
+ font-size: 14px;
279
+ padding: 15px 5px;
280
+ }
281
+ .section-header h2 {
282
+ font-size: 20px;
283
+ font-weight: lighter;
284
+ margin: 0;
285
+ }
286
+ .section-header .section {
287
+ padding: 0;
288
+ }
289
+ .section-header .section div {
290
+ font-weight: normal;
291
+ opacity: 0.6;
292
+ font-size: 14px;
293
+ }
294
+ .section-header h3 {
295
+ display: flex;
296
+ margin: 0;
297
+ }
298
+ .section-header .col {
299
+ padding-left: 10px;
300
+ flex-grow: 1;
301
+ min-width: 0;
302
+ word-wrap: break-word;
303
+ }
304
+ .tab-content {
305
+ width: 100%;
306
+ display: flex;
307
+ flex-direction: column;
308
+ flex-wrap: wrap;
309
+ gap: 5px;
310
+ }
311
+ .tab:hover {
312
+ color: royalblue;
313
+ }
314
+ .tab-content .tab {
315
+ text-decoration: none;
316
+ display: flex;
317
+ font-size: 14px;
318
+ font-weight: bold;
319
+ color: black;
320
+ overflow: hidden;
321
+ box-sizing: border-box;
322
+ align-items: center;
323
+ gap: 2px;
324
+ background: rgba(0,0,0,0.04);
325
+ border-radius: 5px;
326
+ padding: 5px;
327
+ }
328
+ body.dark .tab {
329
+ color: white;
330
+ background: rgba(255,255,255,0.03);
331
+ }
332
+ .tab h2 {
333
+ margin: 0;
334
+ font-size: 14px;
335
+ }
336
+ .tab .col {
337
+ flex-grow: 1;
338
+ margin-left: 10px;
339
+ }
340
+ .tab .emoji {
341
+ width: 30px;
342
+ height: 30px;
343
+ font-size: 20px;
344
+ box-sizing: border-box;
345
+ text-align:center;
346
+ display: flex;
347
+ justify-content: center;
348
+ align-items: center;
349
+ }
350
+ .tab i.img {
351
+ height: 30px;
352
+ width: 30px;
353
+ display: flex;
354
+ justify-content: center;
355
+ font-size: 20px;
356
+ align-items: center;
357
+ border-radius: 3px;
358
+ }
359
+ .menu-container {
360
+ /*
361
+ max-width: 800px;
362
+ */
363
+ padding: 20px;
364
+ align-items: stretch;
365
+ }
366
+ .menu-container {
367
+ display: flex;
368
+ box-sizing: border-box;
369
+ flex-direction: column;
370
+ }
371
+ .package-tabs {
372
+ display: flex;
373
+ border-bottom: 2px solid rgba(0,0,0,0.1);
374
+ margin-bottom: 20px;
375
+ }
376
+ body.dark .package-tabs {
377
+ border-bottom: 2px solid rgba(255,255,255,0.1);
378
+ }
379
+ .package-tab {
380
+ padding: 10px 20px;
381
+ background: rgba(0,0,0,0.04);
382
+ border: none;
383
+ cursor: pointer;
384
+ font-size: 14px;
385
+ font-weight: bold;
386
+ color: rgba(0,0,0,0.7);
387
+ margin-right: 2px;
388
+ border-radius: 5px 5px 0 0;
389
+ transition: all 0.2s ease;
390
+ }
391
+ body.dark .package-tab {
392
+ background: rgba(255,255,255,0.04);
393
+ color: rgba(255,255,255,0.7);
394
+ }
395
+ .package-tab:hover {
396
+ color: royalblue;
397
+ background: rgba(0,0,100,0.08);
398
+ }
399
+ body.dark .package-tab:hover {
400
+ background: rgba(255,255,255,0.08);
401
+ }
402
+ .package-tab.active {
403
+ background: royalblue;
404
+ color: white;
405
+ }
406
+ .package-tab.active:hover {
407
+ background: royalblue;
408
+ color: white;
409
+ }
410
+ .tab-panel {
411
+ display: none;
412
+ }
413
+ .tab-panel.active {
414
+ display: block;
415
+ }
416
+ .bundles-section {
417
+ margin-bottom: 30px;
418
+ }
419
+ .bundles-header {
420
+ padding: 15px 0;
421
+ border-bottom: 1px solid rgba(0,0,0,0.1);
422
+ margin-bottom: 20px;
423
+ }
424
+ body.dark .bundles-header {
425
+ border-bottom: 1px solid rgba(255,255,255,0.1);
426
+ }
427
+ .bundles-header h3 {
428
+ margin: 0;
429
+ font-size: 18px;
430
+ font-weight: lighter;
431
+ color: rgba(0,0,0,0.8);
432
+ }
433
+ body.dark .bundles-header h3 {
434
+ color: rgba(255,255,255,0.8);
435
+ }
436
+ .bundles-grid {
437
+ display: grid;
438
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
439
+ gap: 15px;
440
+ }
441
+ .bundle-card {
442
+ background: rgba(0,0,0,0.04);
443
+ padding: 15px;
444
+ border-left: 4px solid royalblue;
445
+ }
446
+ body.dark .bundle-card {
447
+ background: rgba(255,255,255,0.04);
448
+ }
449
+ .bundle-card.installed {
450
+ border-left-color: #28a745;
451
+ }
452
+ .bundle-card.pending {
453
+ border-left-color: #ffc107;
454
+ }
455
+ .bundle-header {
456
+ display: flex;
457
+ justify-content: space-between;
458
+ align-items: flex-start;
459
+ margin-bottom: 15px;
460
+ }
461
+ .bundle-title-section {
462
+ display: flex;
463
+ align-items: center;
464
+ gap: 10px;
465
+ flex-grow: 1;
466
+ }
467
+ .bundle-icon {
468
+ width: 40px;
469
+ height: 40px;
470
+ display: flex;
471
+ align-items: center;
472
+ justify-content: center;
473
+ background: royalblue;
474
+ color: white;
475
+ border-radius: 8px;
476
+ font-size: 18px;
477
+ flex-shrink: 0;
478
+ }
479
+ body.dark .bundle-icon {
480
+ background: lightblue;
481
+ color: black;
482
+ }
483
+ .bundle-title-text {
484
+ flex-grow: 1;
485
+ }
486
+ .bundle-name {
487
+ font-size: 16px;
488
+ font-weight: bold;
489
+ color: royalblue;
490
+ margin-bottom: 2px;
491
+ }
492
+ body.dark .bundle-name {
493
+ color: lightblue;
494
+ }
495
+ .bundle-code {
496
+ font-size: 12px;
497
+ color: rgba(0,0,0,0.6);
498
+ font-weight: normal;
499
+ }
500
+ body.dark .bundle-code {
501
+ color: rgba(255,255,255,0.6);
502
+ }
503
+ .bundle-description {
504
+ font-size: 13px;
505
+ color: rgba(0,0,0,0.7);
506
+ margin-bottom: 15px;
507
+ line-height: 1.4;
508
+ }
509
+ body.dark .bundle-description {
510
+ color: rgba(255,255,255,0.7);
511
+ }
512
+ .bundle-status {
513
+ font-size: 12px;
514
+ padding: 3px 8px;
515
+ border-radius: 12px;
516
+ text-transform: uppercase;
517
+ font-weight: bold;
518
+ }
519
+ .bundle-status.installed {
520
+ background: #28a745;
521
+ color: white;
522
+ }
523
+ .bundle-status.pending {
524
+ background: #ffc107;
525
+ color: black;
526
+ }
527
+ .bundle-packages {
528
+ margin-bottom: 15px;
529
+ }
530
+ .bundle-packages-title {
531
+ font-size: 12px;
532
+ font-weight: bold;
533
+ color: rgba(0,0,0,0.6);
534
+ margin-bottom: 5px;
535
+ }
536
+ body.dark .bundle-packages-title {
537
+ color: rgba(255,255,255,0.6);
538
+ }
539
+ .bundle-packages-list {
540
+ display: flex;
541
+ flex-wrap: wrap;
542
+ gap: 5px;
543
+ }
544
+ .package-badge {
545
+ background: rgba(0,0,100,0.1);
546
+ color: rgba(0,0,0,0.8);
547
+ padding: 2px 6px;
548
+ border-radius: 10px;
549
+ font-size: 11px;
550
+ position: relative;
551
+ display: inline-flex;
552
+ align-items: center;
553
+ gap: 3px;
554
+ }
555
+ body.dark .package-badge {
556
+ background: rgba(255,255,255,0.1);
557
+ color: rgba(255,255,255,0.8);
558
+ }
559
+ .package-badge.installed {
560
+ background: rgba(40, 167, 69, 0.2);
561
+ color: #28a745;
562
+ border: 1px solid rgba(40, 167, 69, 0.3);
563
+ }
564
+ body.dark .package-badge.installed {
565
+ background: rgba(40, 167, 69, 0.3);
566
+ color: #4caf50;
567
+ border: 1px solid rgba(40, 167, 69, 0.4);
568
+ }
569
+ .package-badge.not-installed {
570
+ background: rgba(220, 53, 69, 0.2);
571
+ color: #dc3545;
572
+ border: 1px solid rgba(220, 53, 69, 0.3);
573
+ }
574
+ body.dark .package-badge.not-installed {
575
+ background: rgba(220, 53, 69, 0.3);
576
+ color: #f56565;
577
+ border: 1px solid rgba(220, 53, 69, 0.4);
578
+ }
579
+ .package-badge-icon {
580
+ font-size: 8px;
581
+ font-weight: bold;
582
+ }
583
+ .bundle-install-btn {
584
+ background: royalblue;
585
+ color: white;
586
+ border: none;
587
+ padding: 8px 15px;
588
+ border-radius: 5px;
589
+ text-decoration: none;
590
+ display: inline-block;
591
+ font-size: 12px;
592
+ font-weight: bold;
593
+ text-align: center;
594
+ transition: background 0.2s ease;
595
+ width: 100%;
596
+ box-sizing: border-box;
597
+ }
598
+ .bundle-install-btn:hover {
599
+ background: #4169e1;
600
+ color: white;
601
+ }
602
+ .bundle-install-btn.installed {
603
+ background: #28a745;
604
+ cursor: default;
605
+ }
606
+ .bundle-install-btn.installed:hover {
607
+ background: #28a745;
608
+ }
609
+ .loading-container {
610
+ display: flex;
611
+ flex-direction: column;
612
+ align-items: center;
613
+ justify-content: center;
614
+ min-height: 400px;
615
+ text-align: center;
616
+ }
617
+ .loading-spinner {
618
+ width: 50px;
619
+ height: 50px;
620
+ border: 4px solid rgba(0,0,0,0.1);
621
+ border-left: 4px solid royalblue;
622
+ border-radius: 50%;
623
+ animation: spin 1s linear infinite;
624
+ margin-bottom: 20px;
625
+ }
626
+ body.dark .loading-spinner {
627
+ border: 4px solid rgba(255,255,255,0.1);
628
+ border-left: 4px solid lightblue;
629
+ }
630
+ @keyframes spin {
631
+ 0% { transform: rotate(0deg); }
632
+ 100% { transform: rotate(360deg); }
633
+ }
634
+ .loading-text {
635
+ font-size: 16px;
636
+ color: rgba(0,0,0,0.7);
637
+ margin-bottom: 10px;
638
+ }
639
+ body.dark .loading-text {
640
+ color: rgba(255,255,255,0.7);
641
+ }
642
+ .loading-subtext {
643
+ font-size: 14px;
644
+ color: rgba(0,0,0,0.5);
645
+ }
646
+ body.dark .loading-subtext {
647
+ color: rgba(255,255,255,0.5);
648
+ }
649
+ .reset-cache-loading {
650
+ padding: 10px;
651
+ background: rgba(0,0,0,0.1);
652
+ margin-bottom: 10px;
653
+ text-align: center;
654
+ }
655
+ .reset-bin-loading {
656
+ padding: 10px;
657
+ background: rgba(0,0,0,0.1);
658
+ margin-bottom: 10px;
659
+ text-align: center;
660
+ }
661
+ #proxy {
662
+ text-decoration: underline;
663
+ margin-left: 10px;
664
+ display: inline-block;
665
+ cursor: pointer;
666
+ }
667
+ body.dark .keys pre {
668
+ background: rgba(255,255,255,0.02) !important;
669
+ }
670
+ .keys pre {
671
+ padding: 20px;
672
+ margin: 20px 0;
673
+ background: rgba(0,0,100,0.04) !important;
674
+ }
675
+ .swal2-actions {
676
+ justify-content: center !important;
677
+ }
678
+ .swal2-title {
679
+ text-align: center !important;
680
+ }
681
+ main {
682
+ display: flex;
683
+ }
684
+ aside {
685
+ width: 200px;
686
+ display: block;
687
+ flex-shrink: 0;
688
+ }
689
+ aside .tab i {
690
+ width: 20px;
691
+ text-align: center;
692
+ }
693
+ body.dark aside .tab {
694
+ color: white;
695
+ }
696
+ body.dark aside .tab:hover, aside .tab:hover {
697
+ color: royalblue !important;
698
+ opacity: 1;
699
+ }
700
+ aside .tab {
701
+ display: flex;
702
+ align-items: center;
703
+ gap: 5px;
704
+ color: black;
705
+ text-decoration: none;
706
+ padding: 10px;
707
+ font-size: 12px;
708
+ opacity: 0.5;
709
+ border-left: 10px solid transparent;
710
+ }
711
+ body.dark aside .tab.selected {
712
+ color: white;
713
+ }
714
+ aside .selected {
715
+ font-weight: bold;
716
+ opacity: 1;
717
+ }
718
+ @media only screen and (max-width: 600px) {
719
+ aside {
720
+ width: unset;
721
+ flex-shrink: unset;
722
+ }
723
+ aside {
724
+ padding: 0 10px;
725
+ }
726
+ aside .tab i {
727
+ width: 100%;
728
+ }
729
+ aside .tab .caption {
730
+ display: none;
731
+ }
732
+ aside .tab {
733
+ margin: 0;
734
+ padding: 10px;
735
+ border-left: none;
736
+ }
737
+ aside .btn-tab {
738
+ flex-direction: column;
739
+ padding: 10px 0;
740
+ }
741
+ aside .btn-tab .btn {
742
+ display: flex;
743
+ justify-content: center;
744
+ }
745
+ aside .btn-tab .btn .caption {
746
+ display: none;
747
+ }
748
+ header .flexible {
749
+ min-width: unset;
750
+ }
751
+ }
752
+ @media only screen and (max-width: 480px) {
753
+ .btn2 {
754
+ padding: 5px;
755
+ font-size: 11px;
756
+ }
757
+ .nav-btns {
758
+ flex-grow: 1;
759
+ justify-content: center;
760
+ padding: 0;
761
+ }
762
+ }
763
+
764
+ @media only screen and (max-width: 800px) {
765
+ body {
766
+ display: flex !important;
767
+ flex-direction: row !important;
768
+ }
769
+ }
770
+ @media only screen and (max-width: 600px) {
771
+ aside {
772
+ width: unset;
773
+ flex-shrink: unset;
774
+ }
775
+ aside {
776
+ padding: 0 10px;
777
+ }
778
+ aside .tab i {
779
+ width: 100%;
780
+ }
781
+ aside .tab .caption {
782
+ display: none;
783
+ }
784
+ aside .tab {
785
+ margin: 0;
786
+ padding: 10px;
787
+ border-left: none;
788
+ }
789
+ aside .btn-tab {
790
+ flex-direction: column;
791
+ padding: 10px 0;
792
+ }
793
+ aside .btn-tab .btn {
794
+ display: flex;
795
+ justify-content: center;
796
+ }
797
+ aside .btn-tab .btn .caption {
798
+ display: none;
799
+ }
800
+ header .flexible {
801
+ min-width: unset;
802
+ }
803
+ }
804
+ </style>
805
+ <script src="/popper.min.js"></script>
806
+ <script src="/tippy-bundle.umd.min.js"></script>
807
+ <script src="/hotkeys.min.js"></script>
808
+ <script src="/sweetalert2.js"></script>
809
+ <script src="/noty.js"></script>
810
+ <script src="/notyq.js"></script>
811
+ <script src="/xterm.js"></script>
812
+ <script src="/xterm-addon-fit.js"></script>
813
+ <script src="/xterm-addon-web-links.js"></script>
814
+ <script src="/xterm-theme.js"></script>
815
+ <script src="/install.js"></script>
816
+ <script src="/timeago.min.js"></script>
817
+ <script src="/common.js"></script>
818
+ <script src="/opener.js"></script>
819
+ <script src="/nav.js"></script>
820
+ <script src="/report.js"></script>
821
+ </head>
822
+ <body class='<%=theme%>' data-agent="<%=agent%>">
823
+ <!--
824
+ <nav>
825
+ <a class='logo' href="/">dal</a>
826
+ </nav>
827
+ -->
828
+ <header class='navheader grabbable'>
829
+ <h1>
830
+ <a class='home' href="/"><img class='icon' src="/pinokio-black.png"></a>
831
+ <button class='btn2' id='back' data-tippy-content="back"><div><i class="fa-solid fa-chevron-left"></i></div></button>
832
+ <button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
833
+ <button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
834
+ <button class='btn2' id='screenshot' data-tippy-content="take a screenshot"><i class="fa-solid fa-camera"></i></button>
835
+ <form class='urlbar'><input type='url' placeholder='enter a local url'></form>
836
+ <a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
837
+ <div><i class="fa-solid fa-table-columns"></i></div>
838
+ </a>
839
+ <a class='btn2' href="/rows" data-tippy-content="split into 2 rows">
840
+ <div><i class="fa-solid fa-table-columns fa-rotate-270"></i></div>
841
+ </a>
842
+ <div class="dropdown btn2">
843
+ <button class='btn2' id='window-management'>
844
+ <div><i class="fa-solid fa-plus"></i></div>
845
+ </button>
846
+ <div class="dropdown-content" id="dropdown-content">
847
+ <button class='btn2' id='clone-win' data-tippy-content="clone this window">
848
+ <div><i class="fa-solid fa-clone"></i><div>clone this window</div></div>
849
+ </button>
850
+ <button id='new-window' data-tippy-content="open a new window" title='open a new window' class='btn2' data-agent="<%=agent%>">
851
+ <div><i class="fa-solid fa-plus"></i><div>new window</div></div>
852
+ </button>
853
+ </div>
854
+ </div>
855
+ <button class='btn2 hidden' id='close-window' data-tippy-content='close this section'>
856
+ <div><i class="fa-solid fa-xmark"></i></div>
857
+ </button>
858
+ </h1>
859
+ </header>
860
+ <main>
861
+ <div class='container'>
862
+ <div class='config'>
863
+ <div class='config-header'>
864
+ <div class='header-label'><i class="fa-solid fa-toolbox"></i> Installed Tools</div>
865
+ <div class='desc'>Package managers and their installed modules.</div>
866
+ </div>
867
+ </div>
868
+ <div class='menu-container'>
869
+ <% if (pending) { %>
870
+ <div class="loading-container">
871
+ <div class="loading-spinner"></div>
872
+ <div class="loading-text">Loading installed tools...</div>
873
+ <div class="loading-subtext">Scanning package managers and modules</div>
874
+ </div>
875
+ <% } else { %>
876
+ <div class="bundles-section">
877
+ <div class="bundles-header">
878
+ <h3>Package Bundles</h3>
879
+ </div>
880
+ <div class="bundles-grid">
881
+ <% bundles.forEach((bundle) => { %>
882
+ <div class="bundle-card <%= !bundle.install_required ? 'installed' : 'pending' %>">
883
+ <div class="bundle-header">
884
+ <div class="bundle-title-section">
885
+ <div class="bundle-icon">
886
+ <i class="<%= bundle.icon %>"></i>
887
+ </div>
888
+ <div class="bundle-title-text">
889
+ <div class="bundle-name"><%= bundle.title %></div>
890
+ <div class="bundle-code">(<%= bundle.name %>)</div>
891
+ </div>
892
+ </div>
893
+ <div class="bundle-status <%= !bundle.install_required ? 'installed' : 'pending' %>">
894
+ <%= !bundle.install_required ? 'Installed' : 'Not installed' %>
895
+ </div>
896
+ </div>
897
+
898
+ <div class="bundle-description">
899
+ <%= bundle.description %>
900
+ </div>
901
+
902
+ <div class="bundle-packages">
903
+ <div class="bundle-packages-title">Included packages:</div>
904
+ <div class="bundle-packages-list">
905
+ <% bundle.requirements.forEach((req) => { %>
906
+ <span class="package-badge <%= req.installed ? 'installed' : 'not-installed' %>">
907
+ <span class="package-badge-icon">
908
+ <%= req.installed ? '✓' : '✗' %>
909
+ </span>
910
+ <%= req.name %>
911
+ </span>
912
+ <% }) %>
913
+ </div>
914
+ </div>
915
+
916
+ <% if (bundle.install_required) { %>
917
+ <a href="<%= bundle.setup %>" class="bundle-install-btn">Install Bundle</a>
918
+ <% } %>
919
+ </div>
920
+ <% }) %>
921
+ </div>
922
+ </div>
923
+
924
+ <div class="package-tabs">
925
+ <% installs.forEach((install, index) => { %>
926
+ <button class="package-tab <%= index === 0 ? 'active' : '' %>" data-tab="<%= install.package_manager %>">
927
+ <%= install.package_manager.toUpperCase() %> (<%= install.modules.length %>)
928
+ </button>
929
+ <% }) %>
930
+ </div>
931
+
932
+ <% installs.forEach((install, index) => { %>
933
+ <div class="tab-panel <%= index === 0 ? 'active' : '' %>" id="<%= install.package_manager %>-panel">
934
+ <div class="section-header">
935
+ <h2><%= install.package_manager.toUpperCase() %></h2>
936
+ <div class="section">
937
+ <div><%= install.modules.length %> modules installed</div>
938
+ </div>
939
+ </div>
940
+ <div class='tab-content'>
941
+ <% install.modules.forEach((module) => { %>
942
+ <div class="tab">
943
+ <div class='emoji'><i class="fa-solid fa-cube"></i></div>
944
+ <div class='col'>
945
+ <h2><%= module %></h2>
946
+ </div>
947
+ </div>
948
+ <% }) %>
949
+ </div>
950
+ </div>
951
+ <% }) %>
952
+ <% } %>
953
+ </div>
954
+ </div>
955
+ <aside>
956
+ <div class='btn-tab'>
957
+ <a href="/init" class='btn'><i class="fa-solid fa-plus"></i><div class='caption'>Create</div></a>
958
+ <a class='btn' id='explore' href="/?mode=explore"><i class="fa-solid fa-globe"></i><div class='caption'>Discover</div></a>
959
+ </div>
960
+ <a href="/" class='tab'><i class='fas fa-laptop-code'></i><div class='caption'>This machine</div></a>
961
+ <a href="/network" class='tab'><i class="fa-solid fa-wifi"></i><div class='caption'>Local network</div></a>
962
+ <% if (list.length > 0) { %>
963
+ <% let brands = { win32: "windows", darwin: "apple", linux: "Linux" } %>
964
+ <% list.forEach(({ host, name, platform, processes }, index) => { %>
965
+ <a href="/net/<%=name%>" class='submenu tab'><i class="fa-brands fa-<%=brands[platform]%>"></i><div class='caption'><%=name%> (<%=current_host === host ? 'this machine' : host%>)</div></a>
966
+ <% }) %>
967
+ <% } %>
968
+ <a href="/connect" class='tab'><i class="fa-solid fa-plug"></i><div class='caption'>Login</div></a>
969
+ <a class='tab' href="<%=portal%>" target="_blank"><i class="fa-solid fa-question"></i><div class='caption'>Help</div></a>
970
+ <a class='tab' id='genlog'><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
971
+ <a id='downloadlogs' download class='hidden btn2' href="/pinokio/logs.zip"><i class="fa-solid fa-download"></i><div class='caption'>Download logs</div></a>
972
+ <a class='tab' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
973
+ <a class='tab selected' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
974
+ <a class='tab' href="/?mode=settings"><i class="fa-solid fa-gear"></i><div class='caption'>Settings</div></a>
975
+ </aside>
976
+ </main>
977
+ <script>
978
+ document.addEventListener('DOMContentLoaded', function() {
979
+ const isPending = <%= pending ? 'true' : 'false' %>;
980
+
981
+ // Auto-refresh when pending
982
+ if (isPending) {
983
+ setTimeout(function() {
984
+ window.location.reload();
985
+ }, 3000);
986
+ }
987
+
988
+ // Tab functionality (only when not pending)
989
+ if (!isPending) {
990
+ const tabs = document.querySelectorAll('.package-tab');
991
+ const panels = document.querySelectorAll('.tab-panel');
992
+
993
+ tabs.forEach(tab => {
994
+ tab.addEventListener('click', function() {
995
+ const targetTab = this.getAttribute('data-tab');
996
+
997
+ // Remove active class from all tabs and panels
998
+ tabs.forEach(t => t.classList.remove('active'));
999
+ panels.forEach(p => p.classList.remove('active'));
1000
+
1001
+ // Add active class to clicked tab
1002
+ this.classList.add('active');
1003
+
1004
+ // Show corresponding panel
1005
+ const targetPanel = document.getElementById(targetTab + '-panel');
1006
+ if (targetPanel) {
1007
+ targetPanel.classList.add('active');
1008
+ }
1009
+ });
1010
+ });
1011
+ }
1012
+ });
1013
+ </script>
1014
+ </body>
1015
+ </html>