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
@@ -3082,6 +3082,14 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
3082
3082
  </span>
3083
3083
  </button>
3084
3084
  </div>
3085
+ <div class='fs-status-dropdown fs-logs'>
3086
+ <button class='fs-status-btn' type='button'>
3087
+ <span class='fs-status-label'>
3088
+ <i class="fa-solid fa-laptop-code"></i>
3089
+ <span class='fs-status-title'>Logs</span>
3090
+ </span>
3091
+ </button>
3092
+ </div>
3085
3093
  <div class='fs-status-dropdown git-changes'>
3086
3094
  <button id='fs-changes-btn' class='fs-status-btn revealer' data-group='#fs-changes-menu' type='button'>
3087
3095
  <span class='fs-status-label'><i class="fa-solid fa-code-compare"></i> Changes</span>
@@ -3130,6 +3138,14 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
3130
3138
  </span>
3131
3139
  </button>
3132
3140
  </div>
3141
+ <div class='fs-status-dropdown fs-logs'>
3142
+ <button class='fs-status-btn' type='button'>
3143
+ <span class='fs-status-label'>
3144
+ <i class="fa-solid fa-laptop-code"></i>
3145
+ <span class='fs-status-title'>Logs</span>
3146
+ </span>
3147
+ </button>
3148
+ </div>
3133
3149
  <div class='fs-status-dropdown git-changes'>
3134
3150
  <button id='fs-changes-btn' class='fs-status-btn revealer' data-group='#fs-changes-menu' type='button'>
3135
3151
  <span class='fs-status-label'><i class="fa-solid fa-code-compare"></i> Changes</span>
@@ -3391,10 +3407,6 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
3391
3407
  return
3392
3408
  }
3393
3409
  storage.setItem(key, JSON.stringify(payload))
3394
- console.log('[PinokioApp] persisted frame link selection', {
3395
- key,
3396
- payload,
3397
- })
3398
3410
  } catch (_) {}
3399
3411
  }
3400
3412
  const restorePersistedFrameLink = (providedPayload = null) => {
@@ -3459,11 +3471,6 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
3459
3471
  if (!node && payload.href) {
3460
3472
  node = findLinkByAbsoluteHref(payload.href)
3461
3473
  }
3462
- console.log('[PinokioApp] restoring frame link selection', {
3463
- key,
3464
- payload,
3465
- found: Boolean(node),
3466
- })
3467
3474
  return node
3468
3475
  }
3469
3476
  const persistTabStateStore = () => {
@@ -4546,7 +4553,8 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
4546
4553
  })
4547
4554
  })
4548
4555
  }
4549
- const addTab = async (url) => {
4556
+ const addTab = async (url, options = {}) => {
4557
+ const label = typeof options.label === 'string' && options.label.trim().length > 0 ? options.label.trim() : null
4550
4558
  let item = document.createElement("a")
4551
4559
  //let id = "ts" + Date.now()
4552
4560
  let index = document.querySelectorAll("aside .s .frame-link").length
@@ -4557,7 +4565,8 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
4557
4565
  item.href = url
4558
4566
  item.setAttribute("data-index", index)
4559
4567
  item.className = "btn header-item frame-link"
4560
- item.innerHTML = `<div class='tab'><i class="fa-solid fa-link"></i><div class='display'>${url}</div><div class='flexible'></div><button class='btn2 del'><i class="fa-solid fa-xmark"></i></button></div>`
4568
+ const displayText = label || url
4569
+ item.innerHTML = `<div class='tab'><i class="fa-solid fa-link"></i><div class='display'>${escapeHtml(displayText)}</div><div class='flexible'></div><button class='btn2 del'><i class="fa-solid fa-xmark"></i></button></div>`
4561
4570
 
4562
4571
  document.querySelector(".temp-menu").appendChild(item)
4563
4572
 
@@ -5426,23 +5435,6 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
5426
5435
  renderSelection()
5427
5436
  }
5428
5437
  }
5429
- if (document.querySelector("#genlog")) {
5430
- document.querySelector("#genlog").addEventListener("click", (e) => {
5431
- e.preventDefault()
5432
- e.stopPropagation()
5433
- e.target.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i>'
5434
- fetch("/pinokio/log", {
5435
- method: "post",
5436
- }).then((res) => {
5437
- let btn = document.querySelector("#genlog")
5438
- let btn2 = document.querySelector("#downloadlogs")
5439
- btn2.classList.remove("hidden")
5440
- btn.classList.add("hidden")
5441
- btn.innerHTML = '<i class="fa-solid fa-circle-check"></i> Generated!'
5442
- //btn.classList.add("hidden")
5443
- })
5444
- })
5445
- }
5446
5438
  let init = document.querySelector("[data-init]")
5447
5439
  if (init) {
5448
5440
  init.click()
@@ -5567,6 +5559,41 @@ body.dark .pinokio-fork-dropdown-remote, body.dark .pinokio-publish-dropdown-rem
5567
5559
  const defaultPushUri = readDataAttr(fsStatusEl, 'data-push-uri')
5568
5560
  const defaultForkUri = readDataAttr(fsStatusEl, 'data-fork-uri')
5569
5561
 
5562
+ const buildWorkspaceLogsUrl = () => {
5563
+ if (workspaceName && workspaceName.length > 0) {
5564
+ return `/logs?workspace=${encodeURIComponent(workspaceName)}`
5565
+ }
5566
+ return '/logs'
5567
+ }
5568
+
5569
+ const focusOrCreateLogsTab = async () => {
5570
+ const relativeUrl = buildWorkspaceLogsUrl()
5571
+ const absoluteUrl = new URL(relativeUrl, window.location.origin).toString()
5572
+ const existingLink = Array.from(document.querySelectorAll('.temp-menu .frame-link')).find((link) => {
5573
+ return link.href === absoluteUrl
5574
+ })
5575
+ if (existingLink) {
5576
+ const display = existingLink.querySelector('.display')
5577
+ if (display) {
5578
+ display.textContent = 'Logs'
5579
+ }
5580
+ existingLink.click()
5581
+ return
5582
+ }
5583
+ const { tab } = await addTab(relativeUrl, { label: 'Logs' })
5584
+ requestAnimationFrame(() => {
5585
+ tab.click()
5586
+ })
5587
+ }
5588
+
5589
+ document.querySelectorAll('#fs-status .fs-logs .fs-status-btn').forEach((button) => {
5590
+ button.addEventListener('click', async (event) => {
5591
+ event.preventDefault()
5592
+ event.stopPropagation()
5593
+ await focusOrCreateLogsTab()
5594
+ })
5595
+ })
5596
+
5570
5597
  const encodeRepoPath = (value) => {
5571
5598
  if (typeof value !== 'string' || value.length === 0) {
5572
5599
  return ''
@@ -141,7 +141,7 @@
141
141
  <ol class="steps">
142
142
  <li>Make sure your bookmarks bar is visible (View → Toolbars → Bookmarks Toolbar, or press <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> + <kbd>Shift</kbd> + <kbd>B</kbd>).</li>
143
143
  <li>Drag the “Pinokio Create” button above to the bar.</li>
144
- <li>When you are on a page you want to automate, click the bookmark. Pinokio will open at <code><%= baseUrl %>/home?create=1</code> with the current page URL in the prompt field.</li>
144
+ <li>When you are on a page you want to automate, click the bookmark. Pinokio will open at <code><%= baseUrl %>/create</code> with the current page URL in the prompt field.</li>
145
145
  </ol>
146
146
  </section>
147
147
 
@@ -82,6 +82,7 @@ body {
82
82
  <script src="/notyq.js"></script>
83
83
  <script src="/pinokio-touch.js"></script>
84
84
  <script src="/xterm.js"></script>
85
+ <script src="/xterm-inline-bridge.js"></script>
85
86
  <script src="/xterm-addon-fit.js"></script>
86
87
  <script src="/xterm-addon-web-links.js"></script>
87
88
  <script src="/xterm-theme.js"></script>
@@ -925,8 +925,7 @@ document.addEventListener('DOMContentLoaded', function() {
925
925
  <% } %>
926
926
  <a href="/connect" class='tab selected'><i class="fa-solid fa-plug"></i><div class='caption'>Login</div></a>
927
927
  <a class='tab' href="<%=portal%>" target="_blank"><i class="fa-solid fa-question"></i><div class='caption'>Help</div></a>
928
- <a class='tab' id='genlog'><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
929
- <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>
928
+ <a class='tab' id='genlog' href="/logs"><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
930
929
  <a class='tab' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
931
930
  <a class='tab' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
932
931
  <a class='tab' href="/agents"><i class="fa-solid fa-robot"></i><div class='caption'>Agents</div></a>
@@ -0,0 +1,63 @@
1
+ <html>
2
+ <head>
3
+ <title>Create Launcher</title>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
6
+ <link href="/xterm.min.css" rel="stylesheet" />
7
+ <link href="/css/fontawesome.min.css" rel="stylesheet" />
8
+ <link href="/css/solid.min.css" rel="stylesheet" />
9
+ <link href="/css/regular.min.css" rel="stylesheet" />
10
+ <link href="/css/brands.min.css" rel="stylesheet" />
11
+ <link href="/markdown.css" rel="stylesheet" />
12
+ <link href="/noty.css" rel="stylesheet" />
13
+ <link href="/style.css" rel="stylesheet" />
14
+ <link href="/urldropdown.css" rel="stylesheet" />
15
+ <% if (agent === "electron") { %>
16
+ <link href="/electron.css" rel="stylesheet" />
17
+ <% } %>
18
+ </head>
19
+ <body class="<%= theme %>" data-agent="<%= agent %>">
20
+ <header class="navheader grabbable">
21
+ <h1>
22
+ <a class="home" href="/home"><img class="icon" src="/pinokio-black.png" /></a>
23
+ </h1>
24
+ </header>
25
+ <main>
26
+ <div class="container create-page">
27
+ <div id="create-page-root" class="create-page-root" aria-live="polite"></div>
28
+ </div>
29
+ </main>
30
+ <script src="/Socket.js"></script>
31
+ <script src="/urldropdown.js"></script>
32
+ <script src="/create-launcher.js"></script>
33
+ <script src="/common.js"></script>
34
+ <script>
35
+ (function() {
36
+ const defaults = <%- JSON.stringify(defaults || {}) %>;
37
+ document.addEventListener('DOMContentLoaded', function() {
38
+ if (typeof initUrlDropdown === 'function') {
39
+ initUrlDropdown({ clearBehavior: 'empty' });
40
+ }
41
+ let mounted = false;
42
+ const mount = () => {
43
+ if (mounted) {
44
+ return;
45
+ }
46
+ if (window.CreateLauncher && typeof window.CreateLauncher.mountPage === 'function') {
47
+ const root = document.getElementById('create-page-root');
48
+ window.CreateLauncher.mountPage(root, defaults);
49
+ mounted = true;
50
+ }
51
+ };
52
+ if (window.CreateLauncher) {
53
+ mount();
54
+ } else {
55
+ window.addEventListener('CreateLauncherReady', mount, { once: true });
56
+ // Fallback: try again after a tick in case the script loads without emitting
57
+ setTimeout(mount, 0);
58
+ }
59
+ });
60
+ })();
61
+ </script>
62
+ </body>
63
+ </html>
@@ -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,6 +14,7 @@
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-settings.js"></script>
17
19
  <script src="/pinokio-touch.js"></script>
18
20
  <script src="/common.js"></script>
@@ -21,6 +23,7 @@
21
23
  <script src="/nav.js"></script>
22
24
  <script src="/autoexpand.js"></script>
23
25
  <script src="/modalinput.js"></script>
26
+ <script src="/htmlmodal.js"></script>
24
27
  <script src="/simplemodal.js"></script>
25
28
  <script src="/waitmodal.js"></script>
26
29
  <script src="/notifyinput.js"></script>
@@ -242,6 +245,10 @@ document.addEventListener("DOMContentLoaded", async () => {
242
245
  class RPC {
243
246
  constructor() {
244
247
  this.socket = new Socket()
248
+ this.resizeSync = window.PinokioResizeSync.create({
249
+ socket: this.socket,
250
+ getShellId: () => shell_id
251
+ })
245
252
  }
246
253
  finished() {
247
254
  /*
@@ -271,6 +278,7 @@ document.addEventListener("DOMContentLoaded", async () => {
271
278
  //let cwd = "<%=execUrl%>"
272
279
  //let cwd = "~" + location.pathname
273
280
  this.socket.close()
281
+ this.resizeSync.reset()
274
282
  this.socket.run({
275
283
  method: "fs.write",
276
284
  params: {
@@ -362,6 +370,7 @@ document.addEventListener("DOMContentLoaded", async () => {
362
370
  this.socket.close()
363
371
  document.querySelector(".run .play").classList.remove("hidden")
364
372
  document.querySelector(".run .stop").classList.add("hidden")
373
+ this.resizeSync.reset()
365
374
 
366
375
  <% if (kill_message) { %>
367
376
  n.Noty({
@@ -383,13 +392,18 @@ document.addEventListener("DOMContentLoaded", async () => {
383
392
 
384
393
  } else if (packet.type === 'connect') {
385
394
  // document.querySelector(".terminal-container").classList.remove("hidden")
395
+ const previousShellId = shell_id
386
396
  if (packet.data.id) {
387
397
  shell_id = packet.data.id
388
398
  }
399
+ if (!previousShellId && shell_id) {
400
+ this.resizeSync.sendInitial()
401
+ }
389
402
  if (packet.data) {
390
403
  if (packet.data.shell) {
391
404
  shell_id = packet.data.shell
392
405
  }
406
+ this.resizeSync.sendInitial()
393
407
  if (packet.data.state) {
394
408
  this.write(packet.data.state)
395
409
  }
@@ -407,6 +421,8 @@ document.addEventListener("DOMContentLoaded", async () => {
407
421
  document.querySelector(".run .play").classList.add("hidden")
408
422
  document.querySelector(".run .starting").classList.add("hidden")
409
423
  document.querySelector(".run .stop").classList.remove("hidden")
424
+ } else if (packet.type === 'resize') {
425
+ this.resizeSync.handleResizePacket(packet)
410
426
  } else if (packet.type === 'wait.end') {
411
427
  try {
412
428
  Swal.close()
@@ -418,6 +434,10 @@ document.addEventListener("DOMContentLoaded", async () => {
418
434
  })
419
435
  } else if (packet.type === 'wait') {
420
436
  await WaitModal(packet.data)
437
+ } else if (packet.type === "htmlmodal") {
438
+ if (window.HtmlModal && typeof window.HtmlModal.handle === 'function') {
439
+ window.HtmlModal.handle(packet, this.socket)
440
+ }
421
441
  } else if (packet.type === "modal") {
422
442
  await SimpleModal(packet.data)
423
443
  this.socket.respond({
@@ -594,9 +614,13 @@ document.addEventListener("DOMContentLoaded", async () => {
594
614
  document.querySelector("#error-screen").classList.add("hidden")
595
615
  })
596
616
  */
597
- instance.mark(packet.event)
598
- let element = document.querySelector("mark")
599
- element.scrollIntoView({ behavior: "smooth", block: "center" });
617
+ if (packet.event) {
618
+ instance.mark(packet.event)
619
+ let element = document.querySelector("#error-screen mark")
620
+ if (element) {
621
+ element.scrollIntoView({ behavior: "smooth", block: "center" })
622
+ }
623
+ }
600
624
 
601
625
  } else if (packet.type === "event") {
602
626
  if (packet.data === "stop") {
@@ -721,8 +745,16 @@ document.addEventListener("DOMContentLoaded", async () => {
721
745
  fitAddon.fit();
722
746
  this.fit = fitAddon
723
747
  this.term = term
748
+ this.resizeSync.updateTerm(this.term, this.fit, this.socket)
724
749
  }
725
750
  this.term.focus()
751
+ if (!this.observer) {
752
+ this.observer = new ResizeObserver(() => {
753
+ this.fit.fit()
754
+ this.resizeSync.sendResize(this.term.cols, this.term.rows)
755
+ })
756
+ this.observer.observe(document.body)
757
+ }
726
758
  }
727
759
  }
728
760
  <% if (!install_required) { %>
@@ -920,7 +952,7 @@ const reloadMemory = async () => {
920
952
  <span class='starting hidden'><i class="fa-solid fa-circle-notch fa-spin"></i> Starting...</span>
921
953
  <span class='stop hidden'><i class="fa-solid fa-stop"></i> Stop</span>
922
954
  </div>
923
- <button class='btn' id='open-fs' data-filepath="<%=filepath%>"><i class="fa-solid fa-eye"></i> View File</button>
955
+ <button class='btn' id='open-fs' data-filepath="<%=filepath%>"><i class="fa-solid fa-eye"></i> Script</button>
924
956
  <!--
925
957
  <button class='btn' id='open-log' data-logpath="<%=logpath%>"><i class="fa-solid fa-align-left"></i> View Logs</button>
926
958
  -->
@@ -743,8 +743,7 @@ body.dark aside .current.selected {
743
743
  <% } %>
744
744
  <a href="/connect" class='tab'><i class="fa-solid fa-plug"></i><div class='caption'>Login</div></a>
745
745
  <a class='tab' href="<%=portal%>" target="_blank"><i class="fa-solid fa-question"></i><div class='caption'>Help</div></a>
746
- <a class='tab' id='genlog'><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
747
- <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>
746
+ <a class='tab' id='genlog' href="/logs"><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
748
747
  <a class='tab' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
749
748
  <a class='tab' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
750
749
  <a class='tab' href="/agents"><i class="fa-solid fa-robot"></i><div class='caption'>Agents</div></a>
@@ -274,8 +274,7 @@ body.dark .open-menu, body.dark .browse {
274
274
  </button>
275
275
  <div class='nav-btns'>
276
276
  <a class='btn2' href="<%=portal%>" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
277
- <button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></button>
278
- <a id='downloadlogs' download class='hidden btn2' href="/pinokio/logs.zip"><div><i class="fa-solid fa-download"></i></div><div>Download logs</div></a>
277
+ <a class='btn2' id='genlog' href="/logs"><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></a>
279
278
  <a class='btn2' href="/home?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
280
279
  <button id='new-window' title='open a new window' class='btn2' data-agent="<%=agent%>"><div><i class="fa-solid fa-plus"></i></div><div>Window</div></button>
281
280
  </div>
@@ -1497,11 +1497,13 @@ body.dark .ace-editor {
1497
1497
  <script src="/report.js"></script>
1498
1498
  <script src="/normalize.js"></script>
1499
1499
  <script src="/Socket.js"></script>
1500
+ <script src="/resizeSync.js"></script>
1500
1501
  <script src="/terminal-settings.js"></script>
1501
1502
  <script src="/pinokio-touch.js"></script>
1502
1503
  <script src="/noty.js"></script>
1503
1504
  <script src="/notyq.js"></script>
1504
1505
  <script src="/xterm.js"></script>
1506
+ <script src="/xterm-inline-bridge.js"></script>
1505
1507
  <script src="/xterm-addon-fit.js"></script>
1506
1508
  <script src="/xterm-addon-web-links.js"></script>
1507
1509
  <script src="/xterm-theme.js"></script>
@@ -1948,8 +1950,7 @@ body.dark .ace-editor {
1948
1950
  <% } %>
1949
1951
  <a href="/connect" class='tab'><i class="fa-solid fa-plug"></i><div class='caption'>Login</div></a>
1950
1952
  <a class='tab' href="<%=portal%>" target="_blank"><i class="fa-solid fa-question"></i><div class='caption'>Help</div></a>
1951
- <a class='tab' id='genlog'><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
1952
- <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>
1953
+ <a class='tab' id='genlog' href="/logs"><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
1953
1954
  <a class='tab' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
1954
1955
  <a class='tab' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
1955
1956
  <a class='tab' href="/agents"><i class="fa-solid fa-robot"></i><div class='caption'>Agents</div></a>
@@ -1963,6 +1964,10 @@ body.dark .ace-editor {
1963
1964
  <script>
1964
1965
  let shell_id
1965
1966
  let socket = new Socket()
1967
+ const resizeSync = window.PinokioResizeSync.create({
1968
+ socket,
1969
+ getShellId: () => shell_id
1970
+ })
1966
1971
  const resizeAITextarea = () => {
1967
1972
  let textarea = document.querySelector(".ai-container .ai-tab-content.selected textarea")
1968
1973
  textarea.style.height = "";
@@ -2684,35 +2689,21 @@ const createTerm = async (_theme) => {
2684
2689
  term.loadAddon(new WebLinksAddon.WebLinksAddon());
2685
2690
  <% } %>
2686
2691
  fitAddon.fit();
2687
-
2688
- term.onKey(({ key }) => {
2689
- console.log({ key, shell_id })
2690
- if (socket) {
2691
- if (shell_id) {
2692
- socket.run({
2693
- key,
2694
- id: shell_id
2695
- })
2696
- }
2692
+ resizeSync.updateTerm(term, fitAddon, socket)
2693
+
2694
+ term.onData((data) => {
2695
+ console.log({ key: data, shell_id })
2696
+ if (socket && shell_id) {
2697
+ socket.run({
2698
+ key: data,
2699
+ id: shell_id
2700
+ })
2697
2701
  }
2698
2702
  });
2699
2703
 
2700
2704
  let observer = new ResizeObserver(() => {
2701
2705
  fitAddon.fit()
2702
- console.log(`Resized to ${term.cols}x${term.rows}`);
2703
- // Trigger your custom handler here
2704
- if (socket) {
2705
- if (shell_id) {
2706
- console.log("RESIZE", { shell_id, cols: term.cols, rows: term.rows })
2707
- socket.run({
2708
- resize: {
2709
- cols: term.cols,
2710
- rows: term.rows,
2711
- },
2712
- id: shell_id
2713
- })
2714
- }
2715
- }
2706
+ resizeSync.sendResize(term.cols, term.rows)
2716
2707
  });
2717
2708
  observer.observe(document.body)
2718
2709
 
@@ -2732,6 +2723,7 @@ async function displayResults(config) {
2732
2723
  term.write(text)
2733
2724
  }
2734
2725
  }
2726
+ resizeSync.reset()
2735
2727
  socket.run({
2736
2728
  id: "kernel.proto.create",
2737
2729
  method: "kernel.proto.create",
@@ -2758,7 +2750,12 @@ async function displayResults(config) {
2758
2750
  } else if (packet.type === "stream") {
2759
2751
  // set the current shell id
2760
2752
  if (packet.data.id) {
2761
- shell_id = packet.data.id
2753
+ if (!shell_id) {
2754
+ shell_id = packet.data.id
2755
+ resizeSync.sendInitial()
2756
+ } else {
2757
+ shell_id = packet.data.id
2758
+ }
2762
2759
  }
2763
2760
  if (packet.data.raw) {
2764
2761
  write(packet.data.raw)
@@ -2773,12 +2770,23 @@ async function displayResults(config) {
2773
2770
  } else if (packet.type === 'disconnect') {
2774
2771
  term.write("\r\nDisconnected...\r\n")
2775
2772
  socket.close()
2773
+ resizeSync.reset()
2776
2774
  } else if (packet.type === 'connect') {
2777
2775
  if (packet.data) {
2778
2776
  if (packet.data.shell) {
2779
- shell_id = packet.data.shell
2777
+ if (!shell_id) {
2778
+ shell_id = packet.data.shell
2779
+ resizeSync.sendInitial()
2780
+ } else {
2781
+ shell_id = packet.data.shell
2782
+ }
2783
+ }
2784
+ if (packet.data.state) {
2785
+ write(packet.data.state)
2780
2786
  }
2781
2787
  }
2788
+ } else if (packet.type === 'resize') {
2789
+ resizeSync.handleResizePacket(packet)
2782
2790
  }
2783
2791
  }).then((res) => {
2784
2792
  console.log("Ended", res)
@@ -120,10 +120,12 @@ body {
120
120
  <script src="/noty.js"></script>
121
121
  <script src="/notyq.js"></script>
122
122
  <script src="/xterm.js"></script>
123
+ <script src="/xterm-inline-bridge.js"></script>
123
124
  <script src="/xterm-addon-fit.js"></script>
124
125
  <script src="/xterm-addon-web-links.js"></script>
125
126
  <script src="/xterm-theme.js"></script>
126
127
  <script src="/Socket.js"></script>
128
+ <script src="/resizeSync.js"></script>
127
129
  <script src="/terminal-settings.js"></script>
128
130
  <script src="/pinokio-touch.js"></script>
129
131
  <!--
@@ -209,11 +211,16 @@ const createTerm = async (_theme) => {
209
211
  document.addEventListener("DOMContentLoaded", async () => {
210
212
  const n = new N()
211
213
  let socket = new Socket()
214
+ const resizeSync = window.PinokioResizeSync.create({
215
+ socket,
216
+ getShellId: () => shell_id
217
+ })
212
218
  <% if (theme === "dark") { %>
213
219
  let term = await createTerm(xtermTheme.FrontEndDelight)
214
220
  <% } else { %>
215
221
  let term = await createTerm(xtermTheme.Tomorrow)
216
222
  <% } %>
223
+ resizeSync.updateTerm(term, fitAddon, socket)
217
224
  let params = new URLSearchParams(location.search)
218
225
  let entries = [...params.entries()]
219
226
  let options;
@@ -223,37 +230,20 @@ document.addEventListener("DOMContentLoaded", async () => {
223
230
  options[key] = value;
224
231
  }
225
232
  }
226
- term.onKey((e) => {
233
+ term.onData((data) => {
227
234
  if (shell_id) {
228
235
  socket.emit({
229
236
  id: shell_id,
230
- key: e.key
237
+ key: data
231
238
  })
232
239
  }
233
- //console.log({ e })
234
- //socket.emit({
235
- // id: location.pathname,
236
- // emit: e.key
237
- //})
238
240
  })
239
241
  let observer = new ResizeObserver(() => {
240
242
  fitAddon.fit()
241
- console.log(`Resized to ${term.cols}x${term.rows}`);
242
- // Trigger your custom handler here
243
- if (socket) {
244
- console.log({ shell_id, cols: term.cols, rows: term.rows })
245
- if (shell_id) {
246
- socket.run({
247
- resize: {
248
- cols: term.cols,
249
- rows: term.rows,
250
- },
251
- id: shell_id
252
- })
253
- }
254
- }
243
+ resizeSync.sendResize(term.cols, term.rows)
255
244
  });
256
245
  observer.observe(document.body)
246
+ resizeSync.reset()
257
247
  await new Promise((resolve, reject) => {
258
248
  console.log({ cols: term.cols, rows: term.rows })
259
249
  socket.run({
@@ -269,11 +259,17 @@ document.addEventListener("DOMContentLoaded", async () => {
269
259
  console.log("packet", packet)
270
260
  if (packet.type === "stream") {
271
261
  if (packet.data.id) {
272
- shell_id = packet.data.id
262
+ if (!shell_id) {
263
+ shell_id = packet.data.id
264
+ resizeSync.sendInitial()
265
+ } else {
266
+ shell_id = packet.data.id
267
+ }
273
268
  }
274
269
  term.write(packet.data.raw)
275
270
  } else if (packet.type === "shell.kill") {
276
271
  socket.close()
272
+ resizeSync.reset()
277
273
  } else if (packet.type === "result") {
278
274
  resolve()
279
275
  } else if (packet.type === "error") {
@@ -327,6 +323,8 @@ document.addEventListener("DOMContentLoaded", async () => {
327
323
  }
328
324
  n.Noty(payload)
329
325
  }
326
+ } else if (packet.type === "resize") {
327
+ resizeSync.handleResizePacket(packet)
330
328
  } else if (packet.type === "input") {
331
329
  let params = packet.data
332
330
  /*
@@ -16,8 +16,7 @@
16
16
  }
17
17
 
18
18
  html, body {
19
- height: var(--layout-viewport-height);
20
- min-height: var(--layout-viewport-height);
19
+ height: 100%;
21
20
  width: 100%;
22
21
  margin: 0;
23
22
  padding: 0;
@@ -38,11 +37,6 @@
38
37
  background: var(--layout-gutter-bg);
39
38
  }
40
39
 
41
- body {
42
- display: flex;
43
- flex-direction: column;
44
- }
45
-
46
40
  body[data-agent="electron"] > #dragger {
47
41
  display: block;
48
42
  }
@@ -62,7 +56,7 @@
62
56
  #layout-root {
63
57
  position: relative;
64
58
  width: 100%;
65
- flex-grow: 1;
59
+ height: 100%;
66
60
  background: var(--layout-background);
67
61
  overflow: hidden;
68
62
  }