pinokiod 3.270.0 → 3.272.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 (56) hide show
  1. package/kernel/ansi_stream_tracker.js +115 -0
  2. package/kernel/api/app/index.js +422 -0
  3. package/kernel/api/htmlmodal/index.js +94 -0
  4. package/kernel/app_launcher/index.js +115 -0
  5. package/kernel/app_launcher/platform/base.js +276 -0
  6. package/kernel/app_launcher/platform/linux.js +229 -0
  7. package/kernel/app_launcher/platform/macos.js +163 -0
  8. package/kernel/app_launcher/platform/unsupported.js +34 -0
  9. package/kernel/app_launcher/platform/windows.js +247 -0
  10. package/kernel/bin/conda-meta.js +93 -0
  11. package/kernel/bin/conda.js +2 -4
  12. package/kernel/bin/index.js +2 -4
  13. package/kernel/index.js +9 -2
  14. package/kernel/peer.js +186 -19
  15. package/kernel/shell.js +212 -1
  16. package/package.json +1 -1
  17. package/server/index.js +491 -6
  18. package/server/public/common.js +224 -741
  19. package/server/public/create-launcher.js +754 -0
  20. package/server/public/htmlmodal.js +292 -0
  21. package/server/public/logs.js +715 -0
  22. package/server/public/resizeSync.js +117 -0
  23. package/server/public/style.css +651 -6
  24. package/server/public/tab-idle-notifier.js +34 -59
  25. package/server/public/tab-link-popover.js +7 -10
  26. package/server/public/terminal-settings.js +723 -9
  27. package/server/public/terminal_input_utils.js +72 -0
  28. package/server/public/terminal_key_caption.js +187 -0
  29. package/server/public/urldropdown.css +120 -3
  30. package/server/public/xterm-inline-bridge.js +116 -0
  31. package/server/socket.js +29 -0
  32. package/server/views/agents.ejs +1 -2
  33. package/server/views/app.ejs +55 -28
  34. package/server/views/bookmarklet.ejs +1 -1
  35. package/server/views/bootstrap.ejs +1 -0
  36. package/server/views/connect.ejs +1 -2
  37. package/server/views/create.ejs +63 -0
  38. package/server/views/editor.ejs +36 -4
  39. package/server/views/index.ejs +1 -2
  40. package/server/views/index2.ejs +1 -2
  41. package/server/views/init/index.ejs +36 -28
  42. package/server/views/install.ejs +20 -22
  43. package/server/views/layout.ejs +2 -8
  44. package/server/views/logs.ejs +155 -0
  45. package/server/views/mini.ejs +0 -18
  46. package/server/views/net.ejs +2 -2
  47. package/server/views/network.ejs +1 -2
  48. package/server/views/network2.ejs +1 -2
  49. package/server/views/old_network.ejs +1 -2
  50. package/server/views/pro.ejs +26 -23
  51. package/server/views/prototype/index.ejs +30 -34
  52. package/server/views/screenshots.ejs +1 -2
  53. package/server/views/settings.ejs +1 -20
  54. package/server/views/shell.ejs +59 -66
  55. package/server/views/terminal.ejs +118 -73
  56. package/server/views/tools.ejs +1 -2
@@ -6,6 +6,7 @@
6
6
  <script src="/noty.js"></script>
7
7
  <script src="/notyq.js"></script>
8
8
  <script src="/xterm.js"></script>
9
+ <script src="/xterm-inline-bridge.js"></script>
9
10
  <script src="/xterm-addon-fit.js"></script>
10
11
  <script src="/xterm-addon-web-links.js"></script>
11
12
  <script src="/xterm-theme.js"></script>
@@ -13,7 +14,10 @@
13
14
  <script src="/xterm-addon-search-bar.js"></script>
14
15
  <script src="/sweetalert2.js"></script>
15
16
  <script src="/Socket.js"></script>
17
+ <script src="/resizeSync.js"></script>
16
18
  <script src="/terminal_input_tracker.js"></script>
19
+ <script src="/terminal_input_utils.js"></script>
20
+ <script src="/terminal_key_caption.js"></script>
17
21
  <script src="/terminal-settings.js"></script>
18
22
  <script src="/pinokio-touch.js"></script>
19
23
  <script src="/common.js"></script>
@@ -24,6 +28,7 @@
24
28
  -->
25
29
  <script src="/autoexpand.js"></script>
26
30
  <script src="/modalinput.js"></script>
31
+ <script src="/htmlmodal.js"></script>
27
32
  <script src="/simplemodal.js"></script>
28
33
  <script src="/waitmodal.js"></script>
29
34
  <script src="/notifyinput.js"></script>
@@ -294,11 +299,27 @@ function buildBinaryRpcPayload(rpc, fileEntries) {
294
299
  }
295
300
  return combined.buffer
296
301
  }
302
+ const fallbackPreviewSanitizer = (value) => {
303
+ if (typeof value !== "string" || value.length === 0) {
304
+ return ""
305
+ }
306
+ return value.replace(/[\x00-\x1F\x7F]/g, "")
307
+ }
308
+ const sanitizePreviewLine = (value) => {
309
+ const sanitizer = (typeof window !== "undefined" && typeof window.PinokioSanitizePreviewLine === "function")
310
+ ? window.PinokioSanitizePreviewLine
311
+ : fallbackPreviewSanitizer
312
+ return sanitizer(value || "")
313
+ }
297
314
  document.addEventListener("DOMContentLoaded", async () => {
298
315
  const n = new N()
299
316
  class RPC {
300
317
  constructor() {
301
318
  this.socket = new Socket()
319
+ this.resizeSync = window.PinokioResizeSync.create({
320
+ socket: this.socket,
321
+ getShellId: () => shell_id
322
+ })
302
323
  this.buffer = []
303
324
  this.uploadContext = {
304
325
  cwd: "~" + location.pathname
@@ -352,7 +373,7 @@ document.addEventListener("DOMContentLoaded", async () => {
352
373
  this.inputTracker.submit(line)
353
374
  return
354
375
  }
355
- const safeLine = (line || "").replace(/[\x00-\x1F\x7F]/g, "")
376
+ const safeLine = sanitizePreviewLine(line || "")
356
377
  const preview = safeLine.trim()
357
378
  const limit = 200
358
379
  const truncated = preview.length > limit ? preview.slice(0, limit) + "..." : preview
@@ -393,6 +414,7 @@ document.addEventListener("DOMContentLoaded", async () => {
393
414
  let cwd = "~" + location.pathname
394
415
 
395
416
  this.socket.close()
417
+ this.resizeSync.reset()
396
418
  this.socket.run({
397
419
  method: "fs.write",
398
420
  params: {
@@ -498,7 +520,11 @@ document.addEventListener("DOMContentLoaded", async () => {
498
520
  refreshParent(packet)
499
521
  // set the current shell id
500
522
  if (packet.data.id) {
523
+ const previousShellId = shell_id
501
524
  shell_id = packet.data.id
525
+ if (!previousShellId) {
526
+ this.resizeSync.sendInitial()
527
+ }
502
528
  notifyShellSession(shell_id)
503
529
  }
504
530
  if (packet.data.raw) {
@@ -537,6 +563,7 @@ document.addEventListener("DOMContentLoaded", async () => {
537
563
  this.socket.close()
538
564
  document.querySelector(".play-btn").classList.remove("hidden")
539
565
  document.querySelector(".stop-btn").classList.add("hidden")
566
+ this.resizeSync.reset()
540
567
  } else if (packet.type === 'connect') {
541
568
  console.log("refreshParent", packet)
542
569
  refreshParent(packet)
@@ -545,6 +572,9 @@ document.addEventListener("DOMContentLoaded", async () => {
545
572
  shell_id = packet.data.shell
546
573
  notifyShellSession(shell_id)
547
574
  }
575
+ if (shell_id) {
576
+ this.resizeSync.sendInitial()
577
+ }
548
578
  if (packet.data.state) {
549
579
  this.write(packet.data.state)
550
580
  }
@@ -552,6 +582,8 @@ document.addEventListener("DOMContentLoaded", async () => {
552
582
  document.querySelector(".play-btn").classList.add("hidden")
553
583
  document.querySelector(".starting-btn").classList.add("hidden")
554
584
  document.querySelector(".stop-btn").classList.remove("hidden")
585
+ } else if (packet.type === 'resize') {
586
+ this.resizeSync.handleResizePacket(packet)
555
587
  } else if (packet.type === 'wait.end') {
556
588
  try {
557
589
  Swal.close()
@@ -564,6 +596,10 @@ document.addEventListener("DOMContentLoaded", async () => {
564
596
  })
565
597
  } else if (packet.type === 'wait') {
566
598
  await WaitModal(packet.data)
599
+ } else if (packet.type === "htmlmodal") {
600
+ if (window.HtmlModal && typeof window.HtmlModal.handle === 'function') {
601
+ window.HtmlModal.handle(packet, this.socket)
602
+ }
567
603
  } else if (packet.type === "modal") {
568
604
  await SimpleModal(packet.data)
569
605
  this.socket.respond({
@@ -722,9 +758,13 @@ document.addEventListener("DOMContentLoaded", async () => {
722
758
  document.querySelector("#error-screen").classList.add("hidden")
723
759
  })
724
760
  */
725
- instance.mark(packet.event)
726
- let element = document.querySelector("mark")
727
- element.scrollIntoView({ behavior: "smooth", block: "center" });
761
+ if (packet.event) {
762
+ instance.mark(packet.event)
763
+ let element = document.querySelector("#error-screen mark")
764
+ if (element) {
765
+ element.scrollIntoView({ behavior: "smooth", block: "center" })
766
+ }
767
+ }
728
768
 
729
769
  this.stop()
730
770
 
@@ -1505,17 +1545,7 @@ document.addEventListener("DOMContentLoaded", async () => {
1505
1545
  }
1506
1546
  if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
1507
1547
  if (!suppressClipboardText) {
1508
- navigator.clipboard.readText().then((text) => {
1509
- console.log('[clipboard paste][shell][text]', text)
1510
- this.socket.run({
1511
- //key: "\x1b[200~" + text + "\x1b[201~",
1512
- key: text,
1513
- id: shell_id,
1514
- paste: true
1515
- })
1516
- this.captureTextInput(text)
1517
-
1518
- })
1548
+ return true
1519
1549
  }
1520
1550
  suppressClipboardText = false
1521
1551
  return false
@@ -1529,50 +1559,23 @@ document.addEventListener("DOMContentLoaded", async () => {
1529
1559
  ////term.resize(cols, rows-5);
1530
1560
  //term.resize(cols, rows);
1531
1561
 
1532
- term.onKey(({ key, domEvent }) => {
1562
+ term.onData((data) => {
1533
1563
  if (this.socket && shell_id) {
1534
1564
  this.socket.run({
1535
- key,
1565
+ key: data,
1536
1566
  id: shell_id
1537
1567
  })
1538
1568
  }
1539
- if (!domEvent) {
1540
- return
1541
- }
1542
- if (domEvent.key === "Backspace") {
1543
- this.handleBackspace()
1544
- return
1545
- }
1546
- if (domEvent.key === "Enter") {
1547
- this.captureTextInput("\n")
1548
- return
1549
- }
1550
- if (domEvent.key === "Tab") {
1551
- this.captureTextInput("\t")
1552
- return
1553
- }
1554
- if (domEvent.key === "Escape") {
1555
- this.resetInputBuffer()
1556
- return
1557
- }
1558
- if (domEvent.ctrlKey || domEvent.metaKey || domEvent.altKey) {
1559
- if (key === "\u0015" || key === "\u0017" || key === "\u000b" || key === "\u0003" || domEvent.key === "c" || domEvent.key === "C" || domEvent.key === "u" || domEvent.key === "U") {
1560
- this.resetInputBuffer()
1561
- }
1562
- return
1563
- }
1564
- if (key === "\u0015" || key === "\u0017" || key === "\u000b") {
1565
- this.resetInputBuffer()
1566
- return
1567
- }
1568
- if (key === "\u0008") {
1569
- this.handleBackspace()
1570
- return
1571
- }
1572
- if (typeof key === "string" && key.length === 1 && key >= " ") {
1573
- this.captureTextInput(key)
1569
+ if (typeof window.processTerminalInputData === "function") {
1570
+ window.processTerminalInputData(data, {
1571
+ capture: (chunk) => this.captureTextInput(chunk),
1572
+ backspace: () => this.handleBackspace(),
1573
+ reset: () => this.resetInputBuffer()
1574
+ })
1575
+ } else {
1576
+ this.captureTextInput(data)
1574
1577
  }
1575
- });
1578
+ })
1576
1579
 
1577
1580
  const fitAddon = new FitAddon.FitAddon();
1578
1581
  // const searchAddon = new SearchAddon.SearchAddon();
@@ -1591,24 +1594,14 @@ document.addEventListener("DOMContentLoaded", async () => {
1591
1594
  fitAddon.fit();
1592
1595
  this.term = term
1593
1596
  this.fit = fitAddon
1597
+ this.resizeSync.updateTerm(this.term, this.fit, this.socket)
1598
+ this.tabCaptionHelper = window.PinokioTabCaptionHelper.attach(term, { tracker: this.inputTracker })
1594
1599
 
1595
1600
  }
1596
1601
  this.term.focus()
1597
1602
  this.observer = new ResizeObserver(() => {
1598
1603
  this.fit.fit()
1599
- console.log(`Resized to ${this.term.cols}x${this.term.rows}`);
1600
- // Trigger your custom handler here
1601
- if (this.socket) {
1602
- if (shell_id) {
1603
- this.socket.run({
1604
- resize: {
1605
- cols: this.term.cols,
1606
- rows: this.term.rows,
1607
- },
1608
- id: shell_id
1609
- })
1610
- }
1611
- }
1604
+ this.resizeSync.sendResize(this.term.cols, this.term.rows)
1612
1605
  });
1613
1606
  this.observer.observe(document.body)
1614
1607
  }
@@ -6,6 +6,7 @@
6
6
  <script src="/noty.js"></script>
7
7
  <script src="/notyq.js"></script>
8
8
  <script src="/xterm.js"></script>
9
+ <script src="/xterm-inline-bridge.js"></script>
9
10
  <script src="/xterm-addon-fit.js"></script>
10
11
  <script src="/xterm-addon-web-links.js"></script>
11
12
  <script src="/xterm-theme.js"></script>
@@ -13,7 +14,10 @@
13
14
  <script src="/xterm-addon-search-bar.js"></script>
14
15
  <script src="/sweetalert2.js"></script>
15
16
  <script src="/Socket.js"></script>
17
+ <script src="/resizeSync.js"></script>
16
18
  <script src="/terminal_input_tracker.js"></script>
19
+ <script src="/terminal_input_utils.js"></script>
20
+ <script src="/terminal_key_caption.js"></script>
17
21
  <script src="/terminal-settings.js"></script>
18
22
  <script src="/pinokio-touch.js"></script>
19
23
  <script src="/common.js"></script>
@@ -25,6 +29,7 @@
25
29
  -->
26
30
  <script src="/autoexpand.js"></script>
27
31
  <script src="/modalinput.js"></script>
32
+ <script src="/htmlmodal.js"></script>
28
33
  <script src="/simplemodal.js"></script>
29
34
  <script src="/waitmodal.js"></script>
30
35
  <script src="/notifyinput.js"></script>
@@ -260,6 +265,18 @@ function buildBinaryRpcPayload(rpc, fileEntries) {
260
265
  }
261
266
  return combined.buffer
262
267
  }
268
+ const fallbackPreviewSanitizer = (value) => {
269
+ if (typeof value !== "string" || value.length === 0) {
270
+ return ""
271
+ }
272
+ return value.replace(/[\x00-\x1F\x7F]/g, "")
273
+ }
274
+ const sanitizePreviewLine = (value) => {
275
+ const sanitizer = (typeof window !== "undefined" && typeof window.PinokioSanitizePreviewLine === "function")
276
+ ? window.PinokioSanitizePreviewLine
277
+ : fallbackPreviewSanitizer
278
+ return sanitizer(value || "")
279
+ }
263
280
  document.addEventListener("DOMContentLoaded", async () => {
264
281
  <% if (error) { %>
265
282
  document.querySelector(".requirements .content").innerHTML = '<div class="loading"><i class="fa-solid fa-circle-exclamation"></i> <%=error%></div>'
@@ -289,6 +306,10 @@ document.addEventListener("DOMContentLoaded", async () => {
289
306
  class RPC {
290
307
  constructor() {
291
308
  this.socket = new Socket()
309
+ this.resizeSync = window.PinokioResizeSync.create({
310
+ socket: this.socket,
311
+ getShellId: () => shell_id
312
+ })
292
313
  this.buffer = []
293
314
  this.uploadContext = {
294
315
  cwd: "~" + location.pathname
@@ -344,7 +365,7 @@ document.addEventListener("DOMContentLoaded", async () => {
344
365
  this.inputTracker.submit(line, meta)
345
366
  return
346
367
  }
347
- const safeLine = (line || "").replace(/[\x00-\x1F\x7F]/g, "")
368
+ const safeLine = sanitizePreviewLine(line || "")
348
369
  const preview = safeLine.trim()
349
370
  const limit = 200
350
371
  const truncated = preview.length > limit ? preview.slice(0, limit) + "..." : preview
@@ -443,6 +464,7 @@ document.addEventListener("DOMContentLoaded", async () => {
443
464
  payload.id = runId
444
465
  payload.useId = true
445
466
  }
467
+ this.resizeSync.reset()
446
468
  this.socket.run(payload, async (packet) => {
447
469
  if (packet.type === 'start') {
448
470
  refreshParent(packet)
@@ -473,9 +495,13 @@ document.addEventListener("DOMContentLoaded", async () => {
473
495
  } else if (packet.type === "stream") {
474
496
  refreshParent(packet)
475
497
  // set the current shell id
498
+ const previousShellId = shell_id
476
499
  if (packet.data.id) {
477
500
  shell_id = packet.data.id
478
501
  }
502
+ if (!previousShellId && shell_id) {
503
+ this.resizeSync.sendInitial()
504
+ }
479
505
  if (packet.data.raw) {
480
506
  this.write(packet.data.raw)
481
507
  } else if (packet.data.json) {
@@ -507,6 +533,7 @@ document.addEventListener("DOMContentLoaded", async () => {
507
533
  this.socket.close()
508
534
  document.querySelector(".run .play").classList.remove("hidden")
509
535
  document.querySelector(".run .stop").classList.add("hidden")
536
+ this.resizeSync.reset()
510
537
 
511
538
  <% if (kill_message) { %>
512
539
  n.Noty({
@@ -580,6 +607,9 @@ document.addEventListener("DOMContentLoaded", async () => {
580
607
  if (packet.data.shell) {
581
608
  shell_id = packet.data.shell
582
609
  }
610
+ if (shell_id) {
611
+ this.resizeSync.sendInitial()
612
+ }
583
613
  if (packet.data.state) {
584
614
  this.write(packet.data.state)
585
615
  }
@@ -597,6 +627,8 @@ document.addEventListener("DOMContentLoaded", async () => {
597
627
  document.querySelector(".run .play").classList.add("hidden")
598
628
  document.querySelector(".run .starting").classList.add("hidden")
599
629
  document.querySelector(".run .stop").classList.remove("hidden")
630
+ } else if (packet.type === 'resize') {
631
+ this.resizeSync.handleResizePacket(packet)
600
632
  // } else if (packet.type === "key.set") {
601
633
  // let keys = await fetch("/pinokio/keys").then((res) => {
602
634
  // return res.json()
@@ -631,6 +663,10 @@ document.addEventListener("DOMContentLoaded", async () => {
631
663
  })
632
664
  } else if (packet.type === 'wait') {
633
665
  await WaitModal(packet.data)
666
+ } else if (packet.type === "htmlmodal") {
667
+ if (window.HtmlModal && typeof window.HtmlModal.handle === 'function') {
668
+ window.HtmlModal.handle(packet, this.socket)
669
+ }
634
670
  } else if (packet.type === "modal") {
635
671
  await SimpleModal(packet.data)
636
672
  this.socket.respond({
@@ -844,9 +880,13 @@ document.addEventListener("DOMContentLoaded", async () => {
844
880
  document.querySelector("#error-screen").classList.add("hidden")
845
881
  })
846
882
  */
847
- instance.mark(packet.event)
848
- let element = document.querySelector("mark")
849
- element.scrollIntoView({ behavior: "smooth", block: "center" });
883
+ if (packet.event) {
884
+ instance.mark(packet.event)
885
+ let element = document.querySelector("#error-screen mark")
886
+ if (element) {
887
+ element.scrollIntoView({ behavior: "smooth", block: "center" })
888
+ }
889
+ }
850
890
 
851
891
  this.error = true
852
892
 
@@ -1495,6 +1535,64 @@ document.addEventListener("DOMContentLoaded", async () => {
1495
1535
  return false
1496
1536
  }
1497
1537
  let suppressClipboardText = false
1538
+ let dragDepth = 0
1539
+ const prevent = (event) => {
1540
+ event.preventDefault()
1541
+ event.stopPropagation()
1542
+ }
1543
+ terminalContainer.addEventListener("dragenter", (event) => {
1544
+ prevent(event)
1545
+ dragDepth += 1
1546
+ dropOverlay.classList.add("active")
1547
+ })
1548
+ terminalContainer.addEventListener("dragover", prevent)
1549
+ terminalContainer.addEventListener("dragleave", (event) => {
1550
+ prevent(event)
1551
+ dragDepth = Math.max(0, dragDepth - 1)
1552
+ if (dragDepth === 0) {
1553
+ dropOverlay.classList.remove("active")
1554
+ }
1555
+ })
1556
+ terminalContainer.addEventListener("drop", async (event) => {
1557
+ prevent(event)
1558
+ dragDepth = 0
1559
+ dropOverlay.classList.remove("active")
1560
+ const files = Array.from(event.dataTransfer ? event.dataTransfer.files || [] : [])
1561
+ let remoteResources = []
1562
+ try {
1563
+ const extra = await this.collectFilesFromDataTransfer(event.dataTransfer)
1564
+ if (extra && Array.isArray(extra.urls) && extra.urls.length) {
1565
+ const seenUrls = new Set()
1566
+ remoteResources = extra.urls.filter((item) => {
1567
+ if (!item || typeof item.href !== "string") {
1568
+ return false
1569
+ }
1570
+ const key = item.href.trim()
1571
+ if (!key || seenUrls.has(key)) {
1572
+ return false
1573
+ }
1574
+ seenUrls.add(key)
1575
+ return true
1576
+ })
1577
+ }
1578
+ } catch (error) {
1579
+ console.warn("Failed to collect files from drop payload", error)
1580
+ }
1581
+ if (!files.length && (!remoteResources || remoteResources.length === 0)) {
1582
+ return
1583
+ }
1584
+ try {
1585
+ if (remoteResources && remoteResources.length > 0) {
1586
+ await this.uploadRemoteResources(remoteResources, dropOverlay)
1587
+ }
1588
+ } catch (error) {
1589
+ console.warn("Remote upload failed", error)
1590
+ }
1591
+ if (files.length > 0) {
1592
+ await this.uploadFiles(files, dropOverlay)
1593
+ }
1594
+ this.term.focus()
1595
+ })
1498
1596
  terminalContainer.addEventListener("paste", async (event) => {
1499
1597
  const clipboard = event && event.clipboardData ? event.clipboardData : null
1500
1598
  const { files: directFiles, hasFileFlavor } = collectClipboardFiles(clipboard)
@@ -1544,23 +1642,7 @@ document.addEventListener("DOMContentLoaded", async () => {
1544
1642
  }
1545
1643
  if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
1546
1644
  if (!suppressClipboardText) {
1547
- navigator.clipboard.readText().then((text) => {
1548
- console.log('[clipboard paste][terminal][text]', text)
1549
- this.socket.run({
1550
- //key: "\x1b[200~" + text + "\x1b[201~",
1551
- key: text,
1552
- id: shell_id,
1553
- paste: true
1554
- })
1555
- this.captureTextInput(text)
1556
-
1557
-
1558
- // this.socket.run({
1559
- // //key: "\x1b[200~" + text + "\x1b[201~",
1560
- // key: text,
1561
- // id: shell_id
1562
- // })
1563
- })
1645
+ return true
1564
1646
  }
1565
1647
  suppressClipboardText = false
1566
1648
  return false
@@ -1574,50 +1656,23 @@ document.addEventListener("DOMContentLoaded", async () => {
1574
1656
  ////term.resize(cols, rows-5);
1575
1657
  //term.resize(cols, rows);
1576
1658
 
1577
- term.onKey(({ key, domEvent }) => {
1659
+ term.onData((data) => {
1578
1660
  if (this.socket && shell_id) {
1579
1661
  this.socket.run({
1580
- key,
1662
+ key: data,
1581
1663
  id: shell_id
1582
1664
  })
1583
1665
  }
1584
- if (!domEvent) {
1585
- return
1586
- }
1587
- if (domEvent.key === "Backspace") {
1588
- this.handleBackspace()
1589
- return
1590
- }
1591
- if (domEvent.key === "Enter") {
1592
- this.captureTextInput("\n")
1593
- return
1594
- }
1595
- if (domEvent.key === "Tab") {
1596
- this.captureTextInput("\t")
1597
- return
1598
- }
1599
- if (domEvent.key === "Escape") {
1600
- this.resetInputBuffer()
1601
- return
1602
- }
1603
- if (domEvent.ctrlKey || domEvent.metaKey || domEvent.altKey) {
1604
- if (key === "\u0015" || key === "\u0017" || key === "\u000b" || key === "\u0003" || domEvent.key === "c" || domEvent.key === "C" || domEvent.key === "u" || domEvent.key === "U") {
1605
- this.resetInputBuffer()
1606
- }
1607
- return
1608
- }
1609
- if (key === "\u0015" || key === "\u0017" || key === "\u000b") {
1610
- this.resetInputBuffer()
1611
- return
1612
- }
1613
- if (key === "\u0008") {
1614
- this.handleBackspace()
1615
- return
1616
- }
1617
- if (typeof key === "string" && key.length === 1 && key >= " ") {
1618
- this.captureTextInput(key)
1666
+ if (typeof window.processTerminalInputData === "function") {
1667
+ window.processTerminalInputData(data, {
1668
+ capture: (chunk) => this.captureTextInput(chunk),
1669
+ backspace: () => this.handleBackspace(),
1670
+ reset: () => this.resetInputBuffer()
1671
+ })
1672
+ } else {
1673
+ this.captureTextInput(data)
1619
1674
  }
1620
- });
1675
+ })
1621
1676
 
1622
1677
  const fitAddon = new FitAddon.FitAddon();
1623
1678
  // const searchAddon = new SearchAddon.SearchAddon();
@@ -1636,24 +1691,14 @@ document.addEventListener("DOMContentLoaded", async () => {
1636
1691
  fitAddon.fit();
1637
1692
  this.term = term
1638
1693
  this.fit = fitAddon
1694
+ this.resizeSync.updateTerm(this.term, this.fit, this.socket)
1695
+ this.tabCaptionHelper = window.PinokioTabCaptionHelper.attach(term, { tracker: this.inputTracker })
1639
1696
 
1640
1697
  }
1641
1698
  this.term.focus()
1642
1699
  this.observer = new ResizeObserver(() => {
1643
1700
  this.fit.fit()
1644
- console.log(`Resized to ${this.term.cols}x${this.term.rows}`);
1645
- // Trigger your custom handler here
1646
- if (this.socket) {
1647
- if (shell_id) {
1648
- this.socket.run({
1649
- resize: {
1650
- cols: this.term.cols,
1651
- rows: this.term.rows,
1652
- },
1653
- id: shell_id
1654
- })
1655
- }
1656
- }
1701
+ this.resizeSync.sendResize(this.term.cols, this.term.rows)
1657
1702
  });
1658
1703
  this.observer.observe(document.body)
1659
1704
  }
@@ -1827,7 +1872,7 @@ const reloadMemory = async () => {
1827
1872
  <span class='stop hidden'><i class="fa-solid fa-stop"></i> Stop</span>
1828
1873
  </div>
1829
1874
  <% if (locals.filepath) { %>
1830
- <button class='btn' id='open-fs' data-filepath="<%=filepath%>"><i class="fa-solid fa-eye"></i> View File</button>
1875
+ <button class='btn' id='open-fs' data-filepath="<%=filepath%>"><i class="fa-solid fa-eye"></i> Script</button>
1831
1876
  <% } %>
1832
1877
  <div id='status-window'></div>
1833
1878
  <div id='progress-window' class='hidden'><div id='progress-bar'></div></div>
@@ -1279,8 +1279,7 @@ document.addEventListener('DOMContentLoaded', function() {
1279
1279
  <% } %>
1280
1280
  <a href="/connect" class='tab'><i class="fa-solid fa-plug"></i><div class='caption'>Login</div></a>
1281
1281
  <a class='tab' href="<%=portal%>" target="_blank"><i class="fa-solid fa-question"></i><div class='caption'>Help</div></a>
1282
- <a class='tab' id='genlog'><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
1283
- <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>
1282
+ <a class='tab' id='genlog' href="/logs"><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
1284
1283
  <a class='tab' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
1285
1284
  <a class='tab selected' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
1286
1285
  <a class='tab' href="/agents"><i class="fa-solid fa-robot"></i><div class='caption'>Agents</div></a>