pinokiod 3.271.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 (55) 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 +7 -0
  14. package/kernel/shell.js +212 -1
  15. package/package.json +1 -1
  16. package/server/index.js +491 -6
  17. package/server/public/common.js +224 -741
  18. package/server/public/create-launcher.js +754 -0
  19. package/server/public/htmlmodal.js +292 -0
  20. package/server/public/logs.js +715 -0
  21. package/server/public/resizeSync.js +117 -0
  22. package/server/public/style.css +651 -6
  23. package/server/public/tab-idle-notifier.js +34 -59
  24. package/server/public/tab-link-popover.js +7 -10
  25. package/server/public/terminal-settings.js +723 -9
  26. package/server/public/terminal_input_utils.js +72 -0
  27. package/server/public/terminal_key_caption.js +187 -0
  28. package/server/public/urldropdown.css +120 -3
  29. package/server/public/xterm-inline-bridge.js +116 -0
  30. package/server/socket.js +29 -0
  31. package/server/views/agents.ejs +1 -2
  32. package/server/views/app.ejs +55 -28
  33. package/server/views/bookmarklet.ejs +1 -1
  34. package/server/views/bootstrap.ejs +1 -0
  35. package/server/views/connect.ejs +1 -2
  36. package/server/views/create.ejs +63 -0
  37. package/server/views/editor.ejs +36 -4
  38. package/server/views/index.ejs +1 -2
  39. package/server/views/index2.ejs +1 -2
  40. package/server/views/init/index.ejs +36 -28
  41. package/server/views/install.ejs +20 -22
  42. package/server/views/layout.ejs +2 -8
  43. package/server/views/logs.ejs +155 -0
  44. package/server/views/mini.ejs +0 -18
  45. package/server/views/net.ejs +2 -2
  46. package/server/views/network.ejs +1 -2
  47. package/server/views/network2.ejs +1 -2
  48. package/server/views/old_network.ejs +1 -2
  49. package/server/views/pro.ejs +26 -23
  50. package/server/views/prototype/index.ejs +30 -34
  51. package/server/views/screenshots.ejs +1 -2
  52. package/server/views/settings.ejs +1 -20
  53. package/server/views/shell.ejs +59 -66
  54. package/server/views/terminal.ejs +118 -73
  55. package/server/views/tools.ejs +1 -2
@@ -0,0 +1,155 @@
1
+ <html>
2
+ <head>
3
+ <title>Logs</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
+ <% if (agent === "electron") { %>
15
+ <link href="/electron.css" rel="stylesheet"/>
16
+ <% } %>
17
+ <script src="/window_storage.js"></script>
18
+ <script src="/popper.min.js"></script>
19
+ <script src="/tippy-bundle.umd.min.js"></script>
20
+ <script src="/hotkeys.min.js"></script>
21
+ <script src="/sweetalert2.js"></script>
22
+ <script src="/noty.js"></script>
23
+ <script src="/notyq.js"></script>
24
+ <script src="/xterm.js"></script>
25
+ <script src="/xterm-addon-fit.js"></script>
26
+ <script src="/xterm-addon-web-links.js"></script>
27
+ <script src="/xterm-theme.js"></script>
28
+ <script src="/install.js"></script>
29
+ <script src="/timeago.min.js"></script>
30
+ <script src="/common.js"></script>
31
+ <script src="/opener.js"></script>
32
+ <script src="/nav.js"></script>
33
+ <script src="/report.js"></script>
34
+ </head>
35
+ <body class='<%=theme%>' data-agent="<%=agent%>">
36
+ <header class='navheader grabbable'>
37
+ <h1>
38
+ <a class='home' href="/home"><img class='icon' src="/pinokio-black.png"></a>
39
+ <button class='btn2' id='minimize-header' data-tippy-content="fullscreen" title='fullscreen'>
40
+ <div><i class="fa-solid fa-expand"></i></div>
41
+ </button>
42
+ <button class='btn2' id='back' data-tippy-content="back"><div><i class="fa-solid fa-chevron-left"></i></div></button>
43
+ <button class='btn2' id='forward' data-tippy-content="forward"><div><i class="fa-solid fa-chevron-right"></i></div></button>
44
+ <button class='btn2' id='refresh-page' data-tippy-content="refresh"><div><i class="fa-solid fa-rotate-right"></i></div></button>
45
+ <button class='btn2' id='screenshot' data-tippy-content="screen capture"><i class="fa-solid fa-camera"></i></button>
46
+ <button class='btn2' id='inspector' data-tippy-content="X-ray mode"><i class="fa-solid fa-eye"></i></button>
47
+ <div class='mobile-flexible'></div>
48
+ <a class='btn2' href="/columns" data-tippy-content="split into 2 columns">
49
+ <div><i class="fa-solid fa-table-columns"></i></div>
50
+ </a>
51
+ <a class='btn2' href="/rows" data-tippy-content="split into 2 rows">
52
+ <div><i class="fa-solid fa-table-columns fa-rotate-270"></i></div>
53
+ </a>
54
+ <button class='btn2' id='new-window' data-tippy-content="open a new window" title='open a new window' data-agent="<%=agent%>">
55
+ <div><i class="fa-solid fa-plus"></i></div>
56
+ </button>
57
+ <button class='btn2 hidden' id='close-window' data-tippy-content='close this section'>
58
+ <div><i class="fa-solid fa-xmark"></i></div>
59
+ </button>
60
+ </h1>
61
+ </header>
62
+ <main>
63
+ <div class='container'>
64
+ <% if (!logsError) { %>
65
+ <section class="logs-page" id="logs-root" data-workspace="<%= logsWorkspace ? logsWorkspace : '' %>">
66
+ <div class="logs-sidebar" aria-label="Log folders">
67
+ <div class="logs-sidebar-header">
68
+ <div>
69
+ <p class="logs-sidebar-eyebrow">Logs directory</p>
70
+ <h2>Logs</h2>
71
+ <% if (logsTitle) { %>
72
+ <div class="logs-workspace-chip" title="<%= logsTitle %>">
73
+ <i class="fa-solid fa-box"></i>
74
+ <span><%= logsTitle %></span>
75
+ </div>
76
+ <% } %>
77
+ </div>
78
+ <div class="logs-root-path" title="<%= logsRootDisplay %>">
79
+ <i class="fa-solid fa-folder-tree"></i>
80
+ <span><%= logsRootDisplay %></span>
81
+ </div>
82
+ </div>
83
+ <div class="logs-zip-actions">
84
+ <button type="button" class="logs-primary-button" id="logs-generate-archive">
85
+ <i class="fa-solid fa-file-zipper"></i>
86
+ <span>Generate a zip archive</span>
87
+ </button>
88
+ <a id="logs-download-archive" class="logs-secondary-button hidden" href="<%= typeof logsDownloadUrl !== 'undefined' ? logsDownloadUrl : '/pinokio/logs.zip' %>" download>
89
+ <i class="fa-solid fa-download"></i>
90
+ <span>Download latest archive</span>
91
+ </a>
92
+ <div class="logs-zip-status" id="logs-zip-status" role="status" aria-live="polite"></div>
93
+ </div>
94
+ <div class="logs-tree-toolbar">
95
+ <button type="button" class="logs-flat-button" id="logs-refresh-tree">
96
+ <i class="fa-solid fa-arrows-rotate"></i>
97
+ <span>Refresh tree</span>
98
+ </button>
99
+ <p class="logs-tree-hint">Streaming works for every file inside this folder.</p>
100
+ </div>
101
+ <div class="logs-tree-wrapper">
102
+ <div class="logs-tree" id="logs-tree" role="tree" aria-label="Pinokio logs"></div>
103
+ </div>
104
+ </div>
105
+ <div class="logs-resizer" id="logs-resizer" role="separator" aria-orientation="vertical" aria-valuemin="220" aria-valuemax="560" aria-valuenow="320" tabindex="0" aria-label="Resize or collapse log navigation">
106
+ <button type="button" class="logs-resizer-toggle" aria-label="Collapse log navigation">
107
+ <i class="fa-solid fa-chevron-left" aria-hidden="true"></i>
108
+ </button>
109
+ </div>
110
+ <div class="logs-main" aria-live="polite">
111
+ <div class="logs-viewer-panel">
112
+ <div class="logs-viewer-header">
113
+ <div>
114
+ <p class="logs-viewer-eyebrow">Live log viewer</p>
115
+ <div class="logs-viewer-path" id="logs-viewer-path">Select a log file to start streaming.</div>
116
+ </div>
117
+ <div class="logs-viewer-controls">
118
+ <label class="logs-autoscroll-toggle">
119
+ <input type="checkbox" id="logs-autoscroll" checked>
120
+ <span>Auto-scroll</span>
121
+ </label>
122
+ <button type="button" class="logs-flat-button" id="logs-clear-viewer" disabled>
123
+ <i class="fa-solid fa-eraser"></i>
124
+ <span>Clear</span>
125
+ </button>
126
+ </div>
127
+ </div>
128
+ <div class="logs-viewer-status" id="logs-viewer-status">Waiting for selection…</div>
129
+ <pre class="logs-viewer-output" id="logs-viewer-output" role="log" aria-live="polite" tabindex="0"></pre>
130
+ </div>
131
+ </div>
132
+ </section>
133
+ <% } else { %>
134
+ <section class="logs-page logs-page--error" id="logs-root-error">
135
+ <div class="logs-empty-state">
136
+ <div class="logs-empty-icon"><i class="fa-solid fa-triangle-exclamation"></i></div>
137
+ <h2>Unable to open logs for this workspace</h2>
138
+ <p><%= logsError %></p>
139
+ <div class="logs-empty-actions">
140
+ <a class="btn" href="/logs"><i class="fa-solid fa-laptop-code"></i> View system logs</a>
141
+ <% if (logsWorkspace) { %>
142
+ <a class="btn" href="/logs?workspace=<%= encodeURIComponent(logsWorkspace) %>"><i class="fa-solid fa-rotate-right"></i> Retry</a>
143
+ <% } %>
144
+ </div>
145
+ </div>
146
+ </section>
147
+ <% } %>
148
+ </div>
149
+ </main>
150
+ <script>
151
+ window.LOGS_PAGE_DATA = <%- JSON.stringify({ rootDisplay: logsRootDisplay || '', downloadUrl: logsDownloadUrl || '/pinokio/logs.zip', workspace: logsWorkspace || '', workspaceTitle: logsTitle || '' }) %>
152
+ </script>
153
+ <script src="/logs.js"></script>
154
+ </body>
155
+ </html>
@@ -1465,24 +1465,6 @@ body.dark .appcanvas {
1465
1465
  document.querySelector(".dynamic").innerHTML = dynamic
1466
1466
  }
1467
1467
  }
1468
- if (document.querySelector("#genlog")) {
1469
- document.querySelector("#genlog").addEventListener("click", (e) => {
1470
- e.preventDefault()
1471
- e.stopPropagation()
1472
- e.target.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i>'
1473
- fetch("/pinokio/log", {
1474
- method: "post",
1475
- }).then((res) => {
1476
- console.log("RES", res)
1477
- let btn = document.querySelector("#genlog")
1478
- let btn2 = document.querySelector("#downloadlogs")
1479
- btn2.classList.remove("hidden")
1480
- btn.classList.add("hidden")
1481
- btn.innerHTML = '<i class="fa-solid fa-circle-check"></i> Generated!'
1482
- //btn.classList.add("hidden")
1483
- })
1484
- })
1485
- }
1486
1468
  let init = document.querySelector("[data-init]")
1487
1469
  if (init) {
1488
1470
  init.click()
@@ -613,6 +613,7 @@ body.dark .net .mark {
613
613
  <script src="/noty.js"></script>
614
614
  <script src="/notyq.js"></script>
615
615
  <script src="/xterm.js"></script>
616
+ <script src="/xterm-inline-bridge.js"></script>
616
617
  <script src="/xterm-addon-fit.js"></script>
617
618
  <script src="/xterm-addon-web-links.js"></script>
618
619
  <script src="/xterm-theme.js"></script>
@@ -1003,8 +1004,7 @@ document.addEventListener('DOMContentLoaded', function() {
1003
1004
  <% } %>
1004
1005
  <a href="/connect" class='tab'><i class="fa-solid fa-plug"></i><div class='caption'>Login</div></a>
1005
1006
  <a class='tab' href="<%=portal%>" target="_blank"><i class="fa-solid fa-question"></i><div class='caption'>Help</div></a>
1006
- <a class='tab' id='genlog'><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
1007
- <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>
1007
+ <a class='tab' id='genlog' href="/logs"><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
1008
1008
  <a class='tab' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
1009
1009
  <a class='tab' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
1010
1010
  <a class='tab' href="/agents"><i class="fa-solid fa-robot"></i><div class='caption'>Agents</div></a>
@@ -1204,8 +1204,7 @@ document.addEventListener('DOMContentLoaded', function() {
1204
1204
  <% } %>
1205
1205
  <a href="/connect" class='tab'><i class="fa-solid fa-plug"></i><div class='caption'>Login</div></a>
1206
1206
  <a class='tab' href="<%=portal%>" target="_blank"><i class="fa-solid fa-question"></i><div class='caption'>Help</div></a>
1207
- <a class='tab' id='genlog'><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
1208
- <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>
1207
+ <a class='tab' id='genlog' href="/logs"><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
1209
1208
  <a class='tab' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
1210
1209
  <a class='tab' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
1211
1210
  <a class='tab' href="/agents"><i class="fa-solid fa-robot"></i><div class='caption'>Agents</div></a>
@@ -428,8 +428,7 @@ table h3 {
428
428
  <div class='flexible'></div>
429
429
  <div class='nav-btns'>
430
430
  <a class='btn2' href="<%=portal%>" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
431
- <button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></button>
432
- <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>
431
+ <a class='btn2' id='genlog' href="/logs"><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></a>
433
432
  <a class='btn2' href="/home?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
434
433
  <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>
435
434
  </div>
@@ -414,8 +414,7 @@ input:checked + .slider:before {
414
414
  <div class='nav-btns'>
415
415
  <a class='btn2' id='explore' href="/home?mode=explore"><div><i class="fa-solid fa-magnifying-glass"></i></div><div>Discover</div></a>
416
416
  <a class='btn2' href="<%=portal%>" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
417
- <button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></button>
418
- <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>
417
+ <a class='btn2' id='genlog' href="/logs"><div><i class="fa-solid fa-laptop-code"></i></div><div>Logs</div></a>
419
418
  <a class='btn2' href="/home?mode=settings"><div><i class="fa-solid fa-gear"></i></div><div>Settings</div></a>
420
419
  <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>
421
420
  </div>
@@ -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>
@@ -211,6 +212,10 @@ body.dark #status-window b {
211
212
  <script>
212
213
  let shell_id
213
214
  let socket = new Socket()
215
+ const resizeSync = window.PinokioResizeSync.create({
216
+ socket,
217
+ getShellId: () => shell_id
218
+ })
214
219
  const createTerm = async (_theme) => {
215
220
  const theme = Object.assign({ }, _theme, {
216
221
  selectionBackground: "red",
@@ -262,35 +267,21 @@ const createTerm = async (_theme) => {
262
267
  term.loadAddon(new WebLinksAddon.WebLinksAddon());
263
268
  <% } %>
264
269
  fitAddon.fit();
270
+ resizeSync.updateTerm(term, fitAddon, socket)
265
271
 
266
- term.onKey(({ key }) => {
267
- console.log({ key, shell_id })
268
- if (socket) {
269
- if (shell_id) {
270
- socket.run({
271
- key,
272
- id: shell_id
273
- })
274
- }
272
+ term.onData((data) => {
273
+ console.log({ key: data, shell_id })
274
+ if (socket && shell_id) {
275
+ socket.run({
276
+ key: data,
277
+ id: shell_id
278
+ })
275
279
  }
276
280
  });
277
281
 
278
282
  let observer = new ResizeObserver(() => {
279
283
  fitAddon.fit()
280
- console.log(`Resized to ${term.cols}x${term.rows}`);
281
- // Trigger your custom handler here
282
- if (socket) {
283
- if (shell_id) {
284
- console.log("RESIZE", { shell_id, cols: term.cols, rows: term.rows })
285
- socket.run({
286
- resize: {
287
- cols: term.cols,
288
- rows: term.rows,
289
- },
290
- id: shell_id
291
- })
292
- }
293
- }
284
+ resizeSync.sendResize(term.cols, term.rows)
294
285
  });
295
286
  observer.observe(document.body)
296
287
 
@@ -310,6 +301,7 @@ async function displayResults(config) {
310
301
  term.write(text)
311
302
  }
312
303
  }
304
+ resizeSync.reset()
313
305
  socket.run({
314
306
  id: "kernel.proto.create",
315
307
  method: "kernel.proto.create",
@@ -334,9 +326,13 @@ async function displayResults(config) {
334
326
  }
335
327
  } else if (packet.type === "stream") {
336
328
  // set the current shell id
329
+ const previousShellId = shell_id
337
330
  if (packet.data.id) {
338
331
  shell_id = packet.data.id
339
332
  }
333
+ if (!previousShellId && shell_id) {
334
+ resizeSync.sendInitial()
335
+ }
340
336
  if (packet.data.raw) {
341
337
  write(packet.data.raw)
342
338
  } else if (packet.data.json) {
@@ -350,12 +346,19 @@ async function displayResults(config) {
350
346
  } else if (packet.type === 'disconnect') {
351
347
  term.write("\r\nDisconnected...\r\n")
352
348
  socket.close()
349
+ resizeSync.reset()
353
350
  } else if (packet.type === 'connect') {
354
351
  if (packet.data) {
355
352
  if (packet.data.shell) {
356
353
  shell_id = packet.data.shell
357
354
  }
355
+ resizeSync.sendInitial()
356
+ if (packet.data.state) {
357
+ write(packet.data.state)
358
+ }
358
359
  }
360
+ } else if (packet.type === 'resize') {
361
+ resizeSync.handleResizePacket(packet)
359
362
  }
360
363
  }).then((res) => {
361
364
  console.log("Ended", res)
@@ -981,11 +981,13 @@ body.dark .appcanvas {
981
981
  <script src="/report.js"></script>
982
982
  <script src="/normalize.js"></script>
983
983
  <script src="/Socket.js"></script>
984
+ <script src="/resizeSync.js"></script>
984
985
  <script src="/terminal-settings.js"></script>
985
986
  <script src="/pinokio-touch.js"></script>
986
987
  <script src="/noty.js"></script>
987
988
  <script src="/notyq.js"></script>
988
989
  <script src="/xterm.js"></script>
990
+ <script src="/xterm-inline-bridge.js"></script>
989
991
  <script src="/xterm-addon-fit.js"></script>
990
992
  <script src="/xterm-addon-web-links.js"></script>
991
993
  <script src="/xterm-theme.js"></script>
@@ -1573,6 +1575,10 @@ async function displayResults(config) {
1573
1575
  term_config = res.config
1574
1576
  }
1575
1577
  let socket = new Socket()
1578
+ const resizeSync = window.PinokioResizeSync.create({
1579
+ socket,
1580
+ getShellId: () => shell_id
1581
+ })
1576
1582
  const baseConfig = Object.assign({}, term_config)
1577
1583
  if (window.PinokioTerminalSettings && typeof window.PinokioTerminalSettings.applyToConfig === 'function') {
1578
1584
  term_config = window.PinokioTerminalSettings.applyToConfig(term_config)
@@ -1594,50 +1600,27 @@ async function displayResults(config) {
1594
1600
  }
1595
1601
  }
1596
1602
  if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
1597
- navigator.clipboard.readText().then((text) => {
1598
- console.log({ text })
1599
- socket.run({
1600
- //key: "\x1b[200~" + text + "\x1b[201~",
1601
- key: text,
1602
- id: shell_id,
1603
- paste: true
1604
- })
1605
-
1606
- })
1607
- return false
1603
+ return true
1608
1604
  }
1609
1605
  return true;
1610
1606
  });
1611
- term.onKey(({ key }) => {
1612
- console.log({ key, shell_id })
1613
- if (socket) {
1614
- if (shell_id) {
1615
- socket.run({
1616
- key,
1617
- id: shell_id
1618
- })
1619
- }
1607
+ term.onData((data) => {
1608
+ console.log({ key: data, shell_id })
1609
+ if (socket && shell_id) {
1610
+ socket.run({
1611
+ key: data,
1612
+ id: shell_id
1613
+ })
1620
1614
  }
1621
1615
  });
1622
1616
  const fitAddon = new FitAddon.FitAddon();
1623
1617
  term.loadAddon(fitAddon);
1624
1618
  fitAddon.fit();
1619
+ resizeSync.updateTerm(term, fitAddon, socket)
1625
1620
  term.focus()
1626
1621
  let observer = new ResizeObserver(() => {
1627
1622
  fitAddon.fit()
1628
- console.log(`Resized to ${term.cols}x${term.rows}`);
1629
- // Trigger your custom handler here
1630
- if (socket) {
1631
- if (shell_id) {
1632
- socket.run({
1633
- resize: {
1634
- cols: term.cols,
1635
- rows: term.rows,
1636
- },
1637
- id: shell_id
1638
- })
1639
- }
1640
- }
1623
+ resizeSync.sendResize(term.cols, term.rows)
1641
1624
  });
1642
1625
  observer.observe(document.body)
1643
1626
  const write = (text) => {
@@ -1645,6 +1628,7 @@ async function displayResults(config) {
1645
1628
  term.write(text)
1646
1629
  }
1647
1630
  }
1631
+ resizeSync.reset()
1648
1632
  socket.run({
1649
1633
  method: "kernel.bin.init_launcher",
1650
1634
  cwd: "<%-JSON.stringify(cwd).slice(1, -1)%>",
@@ -1665,7 +1649,12 @@ async function displayResults(config) {
1665
1649
  } else if (packet.type === "stream") {
1666
1650
  // set the current shell id
1667
1651
  if (packet.data.id) {
1668
- shell_id = packet.data.id
1652
+ if (!shell_id) {
1653
+ shell_id = packet.data.id
1654
+ resizeSync.sendInitial()
1655
+ } else {
1656
+ shell_id = packet.data.id
1657
+ }
1669
1658
  }
1670
1659
  if (packet.data.raw) {
1671
1660
  write(packet.data.raw)
@@ -1680,12 +1669,19 @@ async function displayResults(config) {
1680
1669
  } else if (packet.type === 'disconnect') {
1681
1670
  term.write("\r\nDisconnected...\r\n")
1682
1671
  socket.close()
1672
+ resizeSync.reset()
1683
1673
  } else if (packet.type === 'connect') {
1684
1674
  if (packet.data) {
1685
1675
  if (packet.data.shell) {
1686
1676
  shell_id = packet.data.shell
1687
1677
  }
1678
+ resizeSync.sendInitial()
1679
+ if (packet.data.state) {
1680
+ write(packet.data.state)
1681
+ }
1688
1682
  }
1683
+ } else if (packet.type === 'resize') {
1684
+ resizeSync.handleResizePacket(packet)
1689
1685
  }
1690
1686
  }).then((res) => {
1691
1687
  console.log("Ended", res)
@@ -771,8 +771,7 @@ document.addEventListener('DOMContentLoaded', function() {
771
771
  <% } %>
772
772
  <a href="/connect" class='tab'><i class="fa-solid fa-plug"></i><div class='caption'>Login</div></a>
773
773
  <a class='tab' href="<%=portal%>" target="_blank"><i class="fa-solid fa-question"></i><div class='caption'>Help</div></a>
774
- <a class='tab' id='genlog'><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
775
- <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>
774
+ <a class='tab' id='genlog' href="/logs"><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
776
775
  <a class='tab selected' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
777
776
  <a class='tab' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
778
777
  <a class='tab' href="/agents"><i class="fa-solid fa-robot"></i><div class='caption'>Agents</div></a>
@@ -566,8 +566,7 @@ document.addEventListener('DOMContentLoaded', function() {
566
566
  <% } %>
567
567
  <a href="/connect" class='tab'><i class="fa-solid fa-plug"></i><div class='caption'>Login</div></a>
568
568
  <a class='tab' href="<%=portal%>" target="_blank"><i class="fa-solid fa-question"></i><div class='caption'>Help</div></a>
569
- <a class='tab' id='genlog'><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
570
- <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>
569
+ <a class='tab' id='genlog' href="/logs"><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
571
570
  <a class='tab' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
572
571
  <a class='tab' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
573
572
  <a class='tab' href="/agents"><i class="fa-solid fa-robot"></i><div class='caption'>Agents</div></a>
@@ -720,24 +719,6 @@ document.addEventListener("DOMContentLoaded", async () => {
720
719
  el.classList.remove("hidden")
721
720
  })
722
721
  })
723
- if (document.querySelector("#genlog")) {
724
- document.querySelector("#genlog").addEventListener("click", (e) => {
725
- e.preventDefault()
726
- e.stopPropagation()
727
- e.target.innerHTML = '<i class="fa-solid fa-circle-notch fa-spin"></i>'
728
- fetch("/pinokio/log", {
729
- method: "post",
730
- }).then((res) => {
731
- console.log("RES", res)
732
- let btn = document.querySelector("#genlog")
733
- let btn2 = document.querySelector("#downloadlogs")
734
- btn2.classList.remove("hidden")
735
- btn.classList.add("hidden")
736
- btn.innerHTML = '<i class="fa-solid fa-circle-check"></i> Generated!'
737
- //btn.classList.add("hidden")
738
- })
739
- })
740
- }
741
722
  document.querySelector("main form").addEventListener("submit", async (e) => {
742
723
  e.preventDefault()
743
724
  e.stopPropagation()