pinokiod 5.1.5 → 5.1.11

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 (54) hide show
  1. package/kernel/api/fs/download_worker.js +158 -0
  2. package/kernel/api/fs/index.js +95 -91
  3. package/kernel/api/index.js +3 -0
  4. package/kernel/bin/index.js +5 -2
  5. package/kernel/environment.js +19 -2
  6. package/kernel/git.js +972 -1
  7. package/kernel/index.js +65 -30
  8. package/kernel/peer.js +1 -2
  9. package/kernel/plugin.js +0 -8
  10. package/kernel/procs.js +92 -36
  11. package/kernel/prototype.js +45 -22
  12. package/kernel/shells.js +30 -6
  13. package/kernel/sysinfo.js +33 -13
  14. package/kernel/util.js +61 -24
  15. package/kernel/workspace_status.js +131 -7
  16. package/package.json +1 -1
  17. package/pipe/index.js +1 -1
  18. package/server/index.js +1173 -348
  19. package/server/public/create-launcher.js +157 -2
  20. package/server/public/install.js +135 -41
  21. package/server/public/style.css +32 -1
  22. package/server/public/tab-link-popover.js +45 -14
  23. package/server/public/terminal-settings.js +51 -35
  24. package/server/public/urldropdown.css +89 -3
  25. package/server/socket.js +12 -7
  26. package/server/views/agents.ejs +4 -3
  27. package/server/views/app.ejs +798 -30
  28. package/server/views/bootstrap.ejs +2 -1
  29. package/server/views/checkpoints.ejs +1014 -0
  30. package/server/views/checkpoints_registry_beta.ejs +260 -0
  31. package/server/views/columns.ejs +4 -4
  32. package/server/views/connect.ejs +1 -0
  33. package/server/views/d.ejs +74 -4
  34. package/server/views/download.ejs +28 -28
  35. package/server/views/editor.ejs +4 -5
  36. package/server/views/env_editor.ejs +1 -1
  37. package/server/views/file_explorer.ejs +1 -1
  38. package/server/views/index.ejs +3 -1
  39. package/server/views/init/index.ejs +2 -1
  40. package/server/views/install.ejs +2 -1
  41. package/server/views/net.ejs +9 -7
  42. package/server/views/network.ejs +15 -14
  43. package/server/views/pro.ejs +5 -2
  44. package/server/views/prototype/index.ejs +2 -1
  45. package/server/views/registry_link.ejs +76 -0
  46. package/server/views/rows.ejs +4 -4
  47. package/server/views/screenshots.ejs +1 -0
  48. package/server/views/settings.ejs +1 -0
  49. package/server/views/shell.ejs +4 -6
  50. package/server/views/terminal.ejs +528 -38
  51. package/server/views/tools.ejs +1 -0
  52. package/undefined/logs/dev/plugin/cursor-agent.git/pinokio.js/1764297248545 +0 -45
  53. package/undefined/logs/dev/plugin/cursor-agent.git/pinokio.js/events +0 -4
  54. package/undefined/logs/dev/plugin/cursor-agent.git/pinokio.js/latest +0 -45
@@ -0,0 +1,260 @@
1
+ <html>
2
+ <head>
3
+ <meta charset="UTF-8" />
4
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
5
+ <style>
6
+ :root {
7
+ --bg: #f5f5f5;
8
+ --card: #ffffff;
9
+ --text: #0f172a;
10
+ --muted: #64748b;
11
+ --border: rgba(15, 23, 42, 0.08);
12
+ --btn: #111827;
13
+ --btn-text: #ffffff;
14
+ --btn-secondary: #e2e8f0;
15
+ --btn-secondary-text: #0f172a;
16
+ --badge-on: #16a34a;
17
+ --badge-off: #dc2626;
18
+ }
19
+ body.dark {
20
+ --bg: #0b1120;
21
+ --card: #111827;
22
+ --text: #e2e8f0;
23
+ --muted: #94a3b8;
24
+ --border: rgba(148, 163, 184, 0.2);
25
+ --btn: #e2e8f0;
26
+ --btn-text: #0b1120;
27
+ --btn-secondary: #1f2937;
28
+ --btn-secondary-text: #e2e8f0;
29
+ --badge-on: #22c55e;
30
+ --badge-off: #f87171;
31
+ }
32
+ body {
33
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
34
+ background: var(--bg);
35
+ color: var(--text);
36
+ display: flex;
37
+ align-items: center;
38
+ justify-content: center;
39
+ min-height: 100vh;
40
+ margin: 0;
41
+ padding: 24px;
42
+ }
43
+ .card {
44
+ background: var(--card);
45
+ border: 1px solid var(--border);
46
+ border-radius: 16px;
47
+ box-shadow: 0 12px 30px rgba(15, 23, 42, 0.08);
48
+ padding: 28px;
49
+ max-width: 520px;
50
+ width: 100%;
51
+ }
52
+ .title {
53
+ font-size: 22px;
54
+ font-weight: 700;
55
+ margin: 0 0 6px 0;
56
+ }
57
+ .subtitle {
58
+ margin: 0 0 18px 0;
59
+ color: var(--muted);
60
+ font-size: 14px;
61
+ }
62
+ .status-row {
63
+ display: flex;
64
+ align-items: center;
65
+ gap: 12px;
66
+ margin-bottom: 18px;
67
+ }
68
+ .field {
69
+ display: flex;
70
+ flex-direction: column;
71
+ gap: 6px;
72
+ margin-bottom: 18px;
73
+ }
74
+ .field label {
75
+ font-size: 13px;
76
+ color: var(--muted);
77
+ text-transform: uppercase;
78
+ letter-spacing: 0.08em;
79
+ }
80
+ .field input {
81
+ border: 1px solid var(--border);
82
+ background: transparent;
83
+ color: var(--text);
84
+ padding: 10px 12px;
85
+ border-radius: 10px;
86
+ font-size: 14px;
87
+ }
88
+ .field-hint {
89
+ font-size: 12px;
90
+ color: var(--muted);
91
+ }
92
+ .status-label {
93
+ font-size: 13px;
94
+ color: var(--muted);
95
+ text-transform: uppercase;
96
+ letter-spacing: 0.08em;
97
+ }
98
+ .status-badge {
99
+ padding: 6px 12px;
100
+ border-radius: 999px;
101
+ font-weight: 600;
102
+ font-size: 12px;
103
+ border: 1px solid transparent;
104
+ }
105
+ .status-badge.enabled {
106
+ color: var(--badge-on);
107
+ border-color: rgba(22, 163, 74, 0.3);
108
+ background: rgba(22, 163, 74, 0.12);
109
+ }
110
+ .status-badge.disabled {
111
+ color: var(--badge-off);
112
+ border-color: rgba(220, 38, 38, 0.3);
113
+ background: rgba(220, 38, 38, 0.12);
114
+ }
115
+ .actions {
116
+ display: flex;
117
+ gap: 10px;
118
+ flex-wrap: wrap;
119
+ }
120
+ .btn {
121
+ border: none;
122
+ border-radius: 10px;
123
+ padding: 10px 16px;
124
+ font-weight: 600;
125
+ cursor: pointer;
126
+ transition: transform 0.05s ease, opacity 0.15s ease;
127
+ }
128
+ .btn:disabled {
129
+ opacity: 0.6;
130
+ cursor: not-allowed;
131
+ }
132
+ .btn:active {
133
+ transform: translateY(1px);
134
+ }
135
+ .btn-primary {
136
+ background: var(--btn);
137
+ color: var(--btn-text);
138
+ }
139
+ .btn-secondary {
140
+ background: var(--btn-secondary);
141
+ color: var(--btn-secondary-text);
142
+ }
143
+ .note {
144
+ margin-top: 16px;
145
+ font-size: 13px;
146
+ color: var(--muted);
147
+ }
148
+ .message {
149
+ margin-top: 10px;
150
+ font-size: 13px;
151
+ min-height: 18px;
152
+ }
153
+ .message.success {
154
+ color: var(--badge-on);
155
+ }
156
+ .message.error {
157
+ color: var(--badge-off);
158
+ }
159
+ </style>
160
+ </head>
161
+ <body class="<%= theme %>" data-agent="<%= agent %>">
162
+ <div class="card">
163
+ <div class="title">Registry Beta</div>
164
+ <div class="subtitle">Enable or disable registry publish features for this Pinokio install.</div>
165
+ <div class="status-row">
166
+ <div class="status-label">Status</div>
167
+ <div
168
+ id="registry-beta-status"
169
+ class="status-badge <%= registryBetaEnabled ? 'enabled' : 'disabled' %>"
170
+ data-enabled="<%= registryBetaEnabled ? '1' : '0' %>"
171
+ >
172
+ <%= registryBetaEnabled ? 'Enabled' : 'Disabled' %>
173
+ </div>
174
+ </div>
175
+ <div class="field">
176
+ <label for="registry-connect-url">Registry connect URL</label>
177
+ <input
178
+ id="registry-connect-url"
179
+ type="url"
180
+ placeholder="http://localhost:3000/connect/pinokio"
181
+ value="<%= registryUrlPrefill || registryConnectUrl || '' %>"
182
+ autocomplete="off"
183
+ />
184
+ <div class="field-hint">Used for connect prompts and published links.</div>
185
+ </div>
186
+ <div class="actions">
187
+ <button id="registry-beta-enable" class="btn btn-primary" type="button">Enable</button>
188
+ <button id="registry-beta-disable" class="btn btn-secondary" type="button">Disable</button>
189
+ </div>
190
+ <div class="note">Writes PINOKIO_REGISTRY_BETA and PINOKIO_REGISTRY_CONNECT_URL in ENVIRONMENT. Reload other pages to see changes.</div>
191
+ <div id="registry-beta-message" class="message" aria-live="polite"></div>
192
+ </div>
193
+ <script>
194
+ document.addEventListener("DOMContentLoaded", () => {
195
+ const statusEl = document.getElementById("registry-beta-status")
196
+ const messageEl = document.getElementById("registry-beta-message")
197
+ const enableBtn = document.getElementById("registry-beta-enable")
198
+ const disableBtn = document.getElementById("registry-beta-disable")
199
+ const connectInput = document.getElementById("registry-connect-url")
200
+ if (!statusEl || !enableBtn || !disableBtn) return
201
+
202
+ let enabled = statusEl.getAttribute("data-enabled") === "1"
203
+
204
+ const setMessage = (text, isError) => {
205
+ if (!messageEl) return
206
+ messageEl.textContent = text || ""
207
+ messageEl.classList.toggle("error", !!isError)
208
+ messageEl.classList.toggle("success", !isError && !!text)
209
+ }
210
+
211
+ const setState = (next) => {
212
+ enabled = !!next
213
+ statusEl.textContent = enabled ? "Enabled" : "Disabled"
214
+ statusEl.setAttribute("data-enabled", enabled ? "1" : "0")
215
+ statusEl.classList.toggle("enabled", enabled)
216
+ statusEl.classList.toggle("disabled", !enabled)
217
+ enableBtn.textContent = enabled ? "Save" : "Enable"
218
+ enableBtn.disabled = false
219
+ disableBtn.disabled = !enabled
220
+ }
221
+
222
+ const update = async (next, includeEndpoint) => {
223
+ setMessage("")
224
+ enableBtn.disabled = true
225
+ disableBtn.disabled = true
226
+ try {
227
+ const connectUrl = connectInput ? String(connectInput.value || "").trim() : ""
228
+ const res = await fetch("/checkpoints/registry_beta", {
229
+ method: "POST",
230
+ headers: {
231
+ "Content-Type": "application/json",
232
+ "Accept": "application/json"
233
+ },
234
+ body: JSON.stringify({
235
+ enabled: next ? "1" : "0",
236
+ ...(includeEndpoint ? { connectUrl } : {})
237
+ })
238
+ })
239
+ const payload = res.ok ? await res.json().catch(() => null) : null
240
+ if (!payload || !payload.ok) {
241
+ throw new Error("Update failed")
242
+ }
243
+ setState(!!payload.enabled)
244
+ setMessage("Updated.")
245
+ } catch (_) {
246
+ setState(enabled)
247
+ setMessage("Could not update setting.", true)
248
+ } finally {
249
+ enableBtn.disabled = enabled
250
+ disableBtn.disabled = !enabled
251
+ }
252
+ }
253
+
254
+ setState(enabled)
255
+ enableBtn.addEventListener("click", () => update(true, true))
256
+ disableBtn.addEventListener("click", () => update(false, true))
257
+ })
258
+ </script>
259
+ </body>
260
+ </html>
@@ -62,9 +62,9 @@ body[data-agent='electron'] {
62
62
  <script src="/window_storage.js"></script>
63
63
  </head>
64
64
  <body class='<%=theme%>' data-agent="<%=agent%>">
65
- <iframe id='col0' data-src="<%= originSrc || '/' %>"></iframe>
65
+ <iframe id='col0' data-src="<%= originSrc || '/home' %>"></iframe>
66
66
  <div id="gutter" class="gutter" tabindex="0" role="separator" aria-orientation="vertical" aria-label="Resize panels" aria-valuemin="120" aria-valuemax="0" aria-valuenow="0"></div>
67
- <iframe id='col1' data-src="<%= targetSrc || originSrc || '/' %>"></iframe>
67
+ <iframe id='col1' data-src="<%= targetSrc || originSrc || '/home' %>"></iframe>
68
68
 
69
69
  <script>
70
70
  if (window !== window.top) {
@@ -201,7 +201,7 @@ body[data-agent='electron'] {
201
201
  }, "*")
202
202
  } else {
203
203
  // if this is the top window, everything has been removed, so just redirect to home
204
- location.href = "/"
204
+ location.href = "/home"
205
205
  }
206
206
  }
207
207
  }
@@ -325,7 +325,7 @@ body[data-agent='electron'] {
325
325
 
326
326
  if (!sourceFrameId) {
327
327
  windowStorage.removeItem(splitKey)
328
- location.href = "/"
328
+ location.href = "/home"
329
329
  return
330
330
  }
331
331
 
@@ -926,6 +926,7 @@ document.addEventListener('DOMContentLoaded', function() {
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
928
  <a class='tab' id='genlog' href="/logs"><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
929
+ <a class='tab' href="/checkpoints"><i class="fa-solid fa-clock-rotate-left"></i><div class='caption'>Checkpoints</div></a>
929
930
  <a class='tab' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
930
931
  <a class='tab' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
931
932
  <a class='tab' href="/agents"><i class="fa-solid fa-robot"></i><div class='caption'>Agents</div></a>
@@ -131,6 +131,27 @@ body.dark .tab:hover .disclosure-indicator,
131
131
  body.dark .tab:focus-visible .disclosure-indicator {
132
132
  color: rgba(255, 255, 255, 0.9);
133
133
  }
134
+ .ai-perm-link {
135
+ border: none;
136
+ background: none;
137
+ color: rgba(0, 0, 0, 0.55);
138
+ padding: 6px;
139
+ border-radius: 8px;
140
+ cursor: pointer;
141
+ }
142
+ .ai-perm-link:hover,
143
+ .ai-perm-link:focus-visible {
144
+ background: rgba(0, 0, 0, 0.08);
145
+ color: rgba(0, 0, 0, 0.85);
146
+ }
147
+ body.dark .ai-perm-link {
148
+ color: rgba(255, 255, 255, 0.75);
149
+ }
150
+ body.dark .ai-perm-link:hover,
151
+ body.dark .ai-perm-link:focus-visible {
152
+ background: rgba(255, 255, 255, 0.12);
153
+ color: rgba(255, 255, 255, 0.95);
154
+ }
134
155
  /*
135
156
  body.dark .tab i {
136
157
  background: rgba(0,0,0,0.1);
@@ -444,8 +465,11 @@ body.dark #update-spec {
444
465
  <% } %>
445
466
  <div class='flexible'></div>
446
467
  <% if (i.link) { %>
447
- <div target="_blank" data-href="<%= i.link %>"><i class="fa-solid fa-circle-info"></i></div>
468
+ <div target="_blank" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs"><i class="fa-solid fa-circle-info"></i></div>
448
469
  <% } %>
470
+ <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions">
471
+ <i class="fa-solid fa-shield-halved"></i>
472
+ </button>
449
473
  <div class='disclosure-indicator' aria-hidden="true">
450
474
  <i class="fa-solid fa-chevron-right"></i>
451
475
  </div>
@@ -477,8 +501,11 @@ body.dark #update-spec {
477
501
  <% } %>
478
502
  <div class='flexible'></div>
479
503
  <% if (i.link) { %>
480
- <div target="_blank" data-href="<%= i.link %>"><i class="fa-solid fa-circle-info"></i></div>
504
+ <div target="_blank" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs"><i class="fa-solid fa-circle-info"></i></div>
481
505
  <% } %>
506
+ <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions">
507
+ <i class="fa-solid fa-shield-halved"></i>
508
+ </button>
482
509
  <div class='disclosure-indicator' aria-hidden="true">
483
510
  <i class="fa-solid fa-chevron-right"></i>
484
511
  </div>
@@ -510,8 +537,11 @@ body.dark #update-spec {
510
537
  <% } %>
511
538
  <div class='flexible'></div>
512
539
  <% if (i.link) { %>
513
- <div target="_blank" data-href="<%= i.link %>"><i class="fa-solid fa-circle-info"></i></div>
540
+ <div target="_blank" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs"><i class="fa-solid fa-circle-info"></i></div>
514
541
  <% } %>
542
+ <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions">
543
+ <i class="fa-solid fa-shield-halved"></i>
544
+ </button>
515
545
  <div class='disclosure-indicator' aria-hidden="true">
516
546
  <i class="fa-solid fa-chevron-right"></i>
517
547
  </div>
@@ -542,8 +572,11 @@ body.dark #update-spec {
542
572
  <% } %>
543
573
  <div class='flexible'></div>
544
574
  <% if (i.link) { %>
545
- <div target="_blank" data-href="<%= i.link %>"><i class="fa-solid fa-circle-info"></i></div>
575
+ <div target="_blank" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs"><i class="fa-solid fa-circle-info"></i></div>
546
576
  <% } %>
577
+ <button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions">
578
+ <i class="fa-solid fa-shield-halved"></i>
579
+ </button>
547
580
  <div class='disclosure-indicator' aria-hidden="true">
548
581
  <i class="fa-solid fa-chevron-right"></i>
549
582
  </div>
@@ -709,6 +742,28 @@ const appendSessionParam = (value, session) => {
709
742
  const delimiter = value.includes('?') ? '&' : '?'
710
743
  return `${value}${delimiter}session=${session}`
711
744
  }
745
+ const normalizeConsentSource = (value) => {
746
+ if (!value || typeof value !== "string") return ""
747
+ return value.trim().replace(/\\/g, "/").replace(/\/+$/, "")
748
+ }
749
+ const revokeConsentForHref = (href) => {
750
+ try {
751
+ if (!href || typeof href !== "string") return { ok: false }
752
+ const store = window.localStorage
753
+ if (!store) return { ok: false }
754
+ const url = new URL(href, window.location.origin)
755
+ const cwd = url.searchParams.get("cwd")
756
+ if (!cwd) return { ok: false }
757
+ const folder = normalizeConsentSource(cwd)
758
+ if (!folder) return { ok: false }
759
+ const key = `pinokio:ai-consent:${encodeURIComponent(folder)}`
760
+ const existed = store.getItem(key) !== null
761
+ store.removeItem(key)
762
+ return { ok: true, folder, existed }
763
+ } catch (_) {
764
+ return { ok: false }
765
+ }
766
+ }
712
767
  const START_ICON_HTML = '<i class="fa-solid fa-chevron-right"></i>'
713
768
  const STARTING_ICON_HTML = '<i class="fa-solid fa-circle-notch fa-spin"></i>'
714
769
  const setTabLaunchState = (tab, state) => {
@@ -770,6 +825,21 @@ document.querySelector("form input[type=search]").addEventListener("input", (e)
770
825
  })
771
826
  document.querySelector("form input[type=search]").focus()
772
827
  document.addEventListener("click", (e) => {
828
+ const permTarget = e.target.closest('[data-ai-consent]')
829
+ if (permTarget) {
830
+ e.preventDefault()
831
+ e.stopPropagation()
832
+ const href = permTarget.getAttribute('data-ai-consent') || ''
833
+ const result = revokeConsentForHref(href)
834
+ if (result && result.ok) {
835
+ const folderLabel = result.folder || 'this folder'
836
+ alert(`Cleared AI permission for ${folderLabel}. You will be prompted again next time.`)
837
+ } else {
838
+ alert('Unable to change AI permission for this item.')
839
+ }
840
+ return
841
+ }
842
+
773
843
  const infoTarget = e.target.closest('[data-href][target="_blank"]')
774
844
  if (infoTarget) {
775
845
  e.preventDefault()
@@ -217,34 +217,34 @@ document.addEventListener("DOMContentLoaded", async () => {
217
217
  location.href = location.href
218
218
  <% } else { %>
219
219
  <% if (!install_required) { %>
220
- let term
221
- const n = new N()
222
- let socket = new Socket()
223
- let url = "<%=query.uri%>"
224
- // let name = "0x" + url.split("").map(c => c.charCodeAt(0).toString(16).padStart(2, "0")).join("");
225
- let name = await installname(url)
226
- if (name) {
227
- if (!term) {
228
- <% if (theme === "dark") { %>
229
- term = await createTerm(xtermTheme.FrontEndDelight)
230
- <% } else { %>
231
- term = await createTerm(xtermTheme.Tomorrow)
232
- <% } %>
233
- }
234
- let params = new URLSearchParams(location.search)
235
- let entries = [...params.entries()]
236
- let options;
237
- if (entries.length > 0) {
238
- options = {}
239
- for(const [key, value] of entries) {
240
- options[key] = value;
241
- }
242
- }
243
- await install(name, url, term, socket, options)
244
- } else {
245
- alert("something went wrong")
246
- }
247
- <% } %>
220
+ let term
221
+ const n = new N()
222
+ let socket = new Socket()
223
+ let url = "<%=query.uri%>"
224
+ let params = new URLSearchParams(location.search)
225
+ let entries = [...params.entries()]
226
+ let options;
227
+ if (entries.length > 0) {
228
+ options = {}
229
+ for(const [key, value] of entries) {
230
+ options[key] = value;
231
+ }
232
+ }
233
+ // let name = "0x" + url.split("").map(c => c.charCodeAt(0).toString(16).padStart(2, "0")).join("");
234
+ let name = await installname(url, null, options)
235
+ if (name) {
236
+ if (!term) {
237
+ <% if (theme === "dark") { %>
238
+ term = await createTerm(xtermTheme.FrontEndDelight)
239
+ <% } else { %>
240
+ term = await createTerm(xtermTheme.Tomorrow)
241
+ <% } %>
242
+ }
243
+ await install(name, url, term, socket, options)
244
+ } else {
245
+ alert("something went wrong")
246
+ }
247
+ <% } %>
248
248
  <% } %>
249
249
  if (document.querySelector("#del-bin")) {
250
250
  document.querySelector("#del-bin").addEventListener("click", async (e) => {
@@ -295,10 +295,9 @@ document.addEventListener("DOMContentLoaded", async () => {
295
295
  })
296
296
  })
297
297
  }
298
- start(mode) {
299
- return new Promise(async (resolve, reject) => {
298
+ async start(mode) {
300
299
  // await this.save()
301
- await this.socket.close()
300
+ this.socket.close()
302
301
  // document.querySelector(".terminal-container").classList.add("hidden")
303
302
  let query = Object.fromEntries(new URLSearchParams(location.search))
304
303
  // document.querySelector(".containers").classList.add("running")
@@ -669,7 +668,6 @@ document.addEventListener("DOMContentLoaded", async () => {
669
668
  }
670
669
  }
671
670
  })
672
- })
673
671
  }
674
672
  async run (mode) {
675
673
  this.mode = (mode ? mode : "run")
@@ -696,7 +694,8 @@ document.addEventListener("DOMContentLoaded", async () => {
696
694
  })
697
695
  let config = {
698
696
  scrollback: 9999999,
699
- fontSize: 12,
697
+ fontSize: 14,
698
+ fontFamily: 'monospace',
700
699
  theme,
701
700
  }
702
701
  let res = await fetch("/xterm_config").then((res) => {
@@ -311,7 +311,7 @@ document.addEventListener("DOMContentLoaded", async () => {
311
311
  }).then((response) => response.json())
312
312
  Swal.close()
313
313
  if (res && res.success) {
314
- location.href = "/"
314
+ location.href = "/home"
315
315
  } else if (res && res.error) {
316
316
  alert(res.error)
317
317
  } else {
@@ -649,7 +649,7 @@ document.addEventListener("click", async (e) => {
649
649
  Swal.close()
650
650
  if (res) {
651
651
  if (res.success) {
652
- location.href = "/"
652
+ location.href = "/home"
653
653
  } else if (res.error) {
654
654
  alert(res.error)
655
655
  }
@@ -744,6 +744,7 @@ body.dark aside .current.selected {
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
746
  <a class='tab' id='genlog' href="/logs"><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
747
+ <a class='tab' href="/checkpoints"><i class="fa-solid fa-clock-rotate-left"></i><div class='caption'>Checkpoints</div></a>
747
748
  <a class='tab' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
748
749
  <a class='tab' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
749
750
  <a class='tab' href="/agents"><i class="fa-solid fa-robot"></i><div class='caption'>Agents</div></a>
@@ -1488,8 +1489,9 @@ document.addEventListener("click", async (e) => {
1488
1489
  console.log("res", res)
1489
1490
  Swal.close()
1490
1491
  if (res) {
1492
+ debugger
1491
1493
  if (res.success) {
1492
- location.href = "/"
1494
+ location.href = "/home"
1493
1495
  } else if (res.error) {
1494
1496
  alert(res.error)
1495
1497
  }
@@ -2647,7 +2647,8 @@ const createTerm = async (_theme) => {
2647
2647
  <% } %>
2648
2648
  let config = {
2649
2649
  scrollback: 9999999,
2650
- fontSize: 12,
2650
+ fontSize: 14,
2651
+ fontFamily: 'monospace',
2651
2652
  theme,
2652
2653
  }
2653
2654
  let res = await fetch("/xterm_config").then((res) => {
@@ -163,7 +163,8 @@ const createTerm = async (_theme) => {
163
163
  <% } %>
164
164
  let config = {
165
165
  scrollback: 9999999,
166
- fontSize: 12,
166
+ fontSize: 14,
167
+ fontFamily: 'monospace',
167
168
  theme,
168
169
  }
169
170
  let res = await fetch("/xterm_config").then((res) => {
@@ -708,7 +708,7 @@ document.addEventListener('DOMContentLoaded', function() {
708
708
  </div>
709
709
  <% } else { %>
710
710
  <div class='placeholder-icon'>
711
- <i class="fa-solid fa-database"></i>
711
+ <i class="fa-solid fa-clock-rotate-left"></i>
712
712
  </div>
713
713
  <% } %>
714
714
  </div>
@@ -811,7 +811,7 @@ document.addEventListener('DOMContentLoaded', function() {
811
811
  <h3>
812
812
  <div class='item-icon'>
813
813
  <div class='placeholder-icon'>
814
- <i class="fa-solid fa-database"></i>
814
+ <i class="fa-solid fa-clock-rotate-left"></i>
815
815
  </div>
816
816
  </div>
817
817
  <div class='col'>
@@ -866,7 +866,7 @@ document.addEventListener('DOMContentLoaded', function() {
866
866
  <img src="<%=item[`${protocol}_icon`]%>" onerror="this.src='/pinokio-black.png'"/>
867
867
  <% } else { %>
868
868
  <div class='placeholder-icon'>
869
- <i class="fa-solid fa-database"></i>
869
+ <i class="fa-solid fa-clock-rotate-left"></i>
870
870
  </div>
871
871
  <% } %>
872
872
  </div>
@@ -909,7 +909,7 @@ document.addEventListener('DOMContentLoaded', function() {
909
909
  <img src="<%=item[`${protocol}_icon`]%>" onerror="this.src='/pinokio-black.png'"/>
910
910
  <% } else { %>
911
911
  <div class='placeholder-icon'>
912
- <i class="fa-solid fa-database"></i>
912
+ <i class="fa-solid fa-clock-rotate-left"></i>
913
913
  </div>
914
914
  <% } %>
915
915
  </div>
@@ -949,7 +949,7 @@ document.addEventListener('DOMContentLoaded', function() {
949
949
  <h3>
950
950
  <div class='item-icon'>
951
951
  <div class='placeholder-icon'>
952
- <i class="fa-solid fa-database"></i>
952
+ <i class="fa-solid fa-clock-rotate-left"></i>
953
953
  </div>
954
954
  </div>
955
955
  <div class='col'>
@@ -1005,6 +1005,7 @@ document.addEventListener('DOMContentLoaded', function() {
1005
1005
  <a href="/connect" class='tab'><i class="fa-solid fa-plug"></i><div class='caption'>Login</div></a>
1006
1006
  <a class='tab' href="<%=portal%>" target="_blank"><i class="fa-solid fa-question"></i><div class='caption'>Help</div></a>
1007
1007
  <a class='tab' id='genlog' href="/logs"><i class="fa-solid fa-laptop-code"></i><div class='caption'>Logs</div></a>
1008
+ <a class='tab' href="/checkpoints"><i class="fa-solid fa-clock-rotate-left"></i><div class='caption'>Checkpoints</div></a>
1008
1009
  <a class='tab' href="/screenshots"><i class="fa-solid fa-camera"></i><div class='caption'>Screenshots</div></a>
1009
1010
  <a class='tab' href="/tools"><i class="fa-solid fa-toolbox"></i><div class='caption'>Installed Tools</div></a>
1010
1011
  <a class='tab' href="/agents"><i class="fa-solid fa-robot"></i><div class='caption'>Agents</div></a>
@@ -1167,7 +1168,8 @@ const createDnsTerminal = async (container) => {
1167
1168
  }
1168
1169
  let config = {
1169
1170
  scrollback: 9999999,
1170
- fontSize: 12,
1171
+ fontSize: 14,
1172
+ fontFamily: 'monospace',
1171
1173
  theme: document.body.classList.contains('dark') ? xtermTheme.FrontEndDelight : xtermTheme.Tomorrow,
1172
1174
  }
1173
1175
  try {
@@ -1702,7 +1704,7 @@ document.addEventListener("click", async (e) => {
1702
1704
  Swal.close()
1703
1705
  if (res) {
1704
1706
  if (res.success) {
1705
- location.href = "/"
1707
+ location.href = "/home"
1706
1708
  } else if (res.error) {
1707
1709
  alert(res.error)
1708
1710
  }