pinokiod 3.41.0 → 3.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/kernel/api/browser/index.js +3 -1
- package/kernel/api/cloudflare/index.js +3 -3
- package/kernel/api/index.js +187 -51
- package/kernel/api/loading/index.js +15 -0
- package/kernel/api/process/index.js +7 -0
- package/kernel/api/shell/index.js +0 -2
- package/kernel/bin/browserless.js +22 -0
- package/kernel/bin/caddy.js +36 -4
- package/kernel/bin/index.js +4 -1
- package/kernel/bin/setup.js +38 -5
- package/kernel/connect/backend.js +110 -0
- package/kernel/connect/config.js +171 -0
- package/kernel/connect/index.js +18 -7
- package/kernel/connect/providers/huggingface/index.js +98 -0
- package/kernel/connect/providers/x/index.js +0 -1
- package/kernel/environment.js +91 -19
- package/kernel/git.js +46 -3
- package/kernel/index.js +119 -39
- package/kernel/peer.js +40 -5
- package/kernel/plugin.js +3 -2
- package/kernel/procs.js +27 -20
- package/kernel/prototype.js +30 -16
- package/kernel/router/common.js +1 -1
- package/kernel/router/connector.js +1 -3
- package/kernel/router/index.js +38 -4
- package/kernel/router/localhost_home_router.js +5 -1
- package/kernel/router/localhost_port_router.js +27 -1
- package/kernel/router/localhost_static_router.js +93 -0
- package/kernel/router/localhost_variable_router.js +14 -9
- package/kernel/router/peer_peer_router.js +3 -0
- package/kernel/router/peer_static_router.js +43 -0
- package/kernel/router/peer_variable_router.js +15 -14
- package/kernel/router/processor.js +26 -1
- package/kernel/router/rewriter.js +59 -0
- package/kernel/scripts/git/commit +11 -1
- package/kernel/shell.js +8 -3
- package/kernel/util.js +65 -6
- package/package.json +2 -1
- package/server/index.js +1037 -964
- package/server/public/common.js +382 -1
- package/server/public/fscreator.js +0 -1
- package/server/public/loading.js +17 -0
- package/server/public/notifyinput.js +0 -1
- package/server/public/opener.js +4 -2
- package/server/public/style.css +310 -11
- package/server/socket.js +7 -1
- package/server/views/app.ejs +1747 -351
- package/server/views/columns.ejs +338 -0
- package/server/views/connect/huggingface.ejs +353 -0
- package/server/views/connect/index.ejs +410 -0
- package/server/views/connect/x.ejs +43 -9
- package/server/views/connect.ejs +709 -49
- package/server/views/container.ejs +357 -0
- package/server/views/d.ejs +251 -62
- package/server/views/download.ejs +54 -10
- package/server/views/editor.ejs +11 -0
- package/server/views/explore.ejs +40 -15
- package/server/views/file_explorer.ejs +25 -246
- package/server/views/form.ejs +44 -1
- package/server/views/frame.ejs +39 -1
- package/server/views/github.ejs +48 -11
- package/server/views/help.ejs +48 -7
- package/server/views/index.ejs +119 -58
- package/server/views/index2.ejs +3 -4
- package/server/views/init/index.ejs +651 -197
- package/server/views/install.ejs +1 -1
- package/server/views/mini.ejs +47 -18
- package/server/views/net.ejs +199 -67
- package/server/views/network.ejs +220 -94
- package/server/views/network2.ejs +3 -4
- package/server/views/old_network.ejs +3 -3
- package/server/views/prototype/index.ejs +48 -11
- package/server/views/review.ejs +1005 -0
- package/server/views/rows.ejs +341 -0
- package/server/views/screenshots.ejs +1020 -0
- package/server/views/settings.ejs +160 -23
- package/server/views/setup.ejs +49 -7
- package/server/views/setup_home.ejs +43 -10
- package/server/views/shell.ejs +7 -1
- package/server/views/start.ejs +14 -9
- package/server/views/terminal.ejs +13 -2
- package/server/views/tools.ejs +1015 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
<html>
|
|
2
|
+
<head>
|
|
3
|
+
<style>
|
|
4
|
+
html, body {
|
|
5
|
+
width: 100%;
|
|
6
|
+
height: 100%;
|
|
7
|
+
margin: 0;
|
|
8
|
+
}
|
|
9
|
+
body.single {
|
|
10
|
+
display: block;
|
|
11
|
+
}
|
|
12
|
+
body {
|
|
13
|
+
display: grid;
|
|
14
|
+
grid-template-rows: var(--row0, 1fr) 6px var(--row1, 1fr);
|
|
15
|
+
gap: 0px;
|
|
16
|
+
}
|
|
17
|
+
body iframe {
|
|
18
|
+
border: none;
|
|
19
|
+
width: 100%;
|
|
20
|
+
height: 100%;
|
|
21
|
+
}
|
|
22
|
+
/* Splitter (gutter) styles */
|
|
23
|
+
body.dark {
|
|
24
|
+
background: #1B1C1D;
|
|
25
|
+
}
|
|
26
|
+
body.dark .gutter {
|
|
27
|
+
background: #111111;
|
|
28
|
+
}
|
|
29
|
+
.gutter {
|
|
30
|
+
background: whitesmoke;
|
|
31
|
+
cursor: row-resize;
|
|
32
|
+
position: relative;
|
|
33
|
+
}
|
|
34
|
+
body.resizing, .gutter:hover {
|
|
35
|
+
cursor: row-resize;
|
|
36
|
+
}
|
|
37
|
+
body.resizing {
|
|
38
|
+
user-select: none;
|
|
39
|
+
}
|
|
40
|
+
/* Visible handle */
|
|
41
|
+
.gutter::before {
|
|
42
|
+
content: '';
|
|
43
|
+
position: absolute;
|
|
44
|
+
top: 50%;
|
|
45
|
+
left: 50%;
|
|
46
|
+
transform: translate(-50%, -50%);
|
|
47
|
+
width: 32px;
|
|
48
|
+
height: 4px;
|
|
49
|
+
border-radius: 2px;
|
|
50
|
+
/*
|
|
51
|
+
background: #bdbdbd;
|
|
52
|
+
*/
|
|
53
|
+
}
|
|
54
|
+
.gutter:hover::before, body.resizing .gutter::before { background: #9e9e9e; }
|
|
55
|
+
.gutter:focus { outline: none; box-shadow: inset 0 0 0 2px #90caf9; }
|
|
56
|
+
</style>
|
|
57
|
+
</head>
|
|
58
|
+
<body class='<%=theme%>'>
|
|
59
|
+
<iframe id='row0' data-src="<%=src%>"></iframe>
|
|
60
|
+
<div id="gutter" class="gutter" tabindex="0" role="separator" aria-orientation="horizontal" aria-label="Resize panels" aria-valuemin="120" aria-valuemax="0" aria-valuenow="0"></div>
|
|
61
|
+
<iframe id='row1' data-src="<%=src%>"></iframe>
|
|
62
|
+
|
|
63
|
+
<script>
|
|
64
|
+
(function() {
|
|
65
|
+
const gutter = document.getElementById('gutter');
|
|
66
|
+
const topPane = document.getElementById('row0');
|
|
67
|
+
const bottomPane = document.getElementById('row1');
|
|
68
|
+
const body = document.body;
|
|
69
|
+
const GUTTER = gutter ? gutter.getBoundingClientRect().height || 6 : 6;
|
|
70
|
+
const MIN = 120; // minimum height for each pane in px
|
|
71
|
+
|
|
72
|
+
// Stable instance path for recursive panes
|
|
73
|
+
// Prefer parent-assigned iframe name; fallback to window.name; else 'root' for top-level
|
|
74
|
+
const PATH = (window.frameElement && window.frameElement.name) || window.name || 'root';
|
|
75
|
+
if (!window.name) { try { window.name = PATH; } catch(_) {} }
|
|
76
|
+
// Assign deterministic names to child panes before loading
|
|
77
|
+
topPane.name = `${PATH}.0`;
|
|
78
|
+
bottomPane.name = `${PATH}.1`;
|
|
79
|
+
|
|
80
|
+
const splitKey = `splitRatio:${PATH}`;
|
|
81
|
+
const KEY_STEP = 20;
|
|
82
|
+
const KEY_STEP_BIG = 100;
|
|
83
|
+
const urlKeyFor = (paneName) => `paneUrl:${paneName}`;
|
|
84
|
+
|
|
85
|
+
function setRows(topPx) {
|
|
86
|
+
console.log("setRows", topPx)
|
|
87
|
+
document.body.style.gridTemplateRows = `${topPx}px ${GUTTER}px 1fr`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function computeTotal() {
|
|
91
|
+
const bodyRect = body.getBoundingClientRect();
|
|
92
|
+
return bodyRect.height - GUTTER;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function clamp(val, min, max) { return Math.max(min, Math.min(max, val)); }
|
|
96
|
+
|
|
97
|
+
function updateAria(topPx, total) {
|
|
98
|
+
if (!gutter) return;
|
|
99
|
+
gutter.setAttribute('aria-valuemin', String(MIN));
|
|
100
|
+
gutter.setAttribute('aria-valuemax', String(Math.max(MIN, total - MIN)));
|
|
101
|
+
gutter.setAttribute('aria-valuenow', String(Math.max(MIN, Math.min(total - MIN, Math.round(topPx)))));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function saveRatioFromTopPx(topPx) {
|
|
105
|
+
const total = computeTotal();
|
|
106
|
+
if (total > 0) {
|
|
107
|
+
const ratio = clamp(topPx / total, 0, 1);
|
|
108
|
+
try { sessionStorage.setItem(splitKey, String(ratio)); } catch (_) {}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function applyFromRatio(ratio) {
|
|
113
|
+
console.log("applyFromRatio", ratio)
|
|
114
|
+
const total = computeTotal();
|
|
115
|
+
let topPx = clamp(Math.round(total * ratio), MIN, total - MIN);
|
|
116
|
+
setRows(topPx);
|
|
117
|
+
updateAria(topPx, total);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// --- Per-window URL persistence with deterministic pane paths ---
|
|
121
|
+
function restorePaneURL(pane) {
|
|
122
|
+
const key = urlKeyFor(pane.name);
|
|
123
|
+
try {
|
|
124
|
+
const saved = sessionStorage.getItem(key);
|
|
125
|
+
const fallback = pane.getAttribute('data-src') || pane.getAttribute('src') || '';
|
|
126
|
+
const target = (saved && typeof saved === 'string') ? saved : fallback;
|
|
127
|
+
if (target && pane.src !== target) pane.src = target;
|
|
128
|
+
} catch (_) { /* ignore */ }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function attachSameOriginRouteHooks(pane) {
|
|
132
|
+
const key = urlKeyFor(pane.name);
|
|
133
|
+
try {
|
|
134
|
+
const cw = pane.contentWindow;
|
|
135
|
+
if (!cw) return;
|
|
136
|
+
const notify = () => {
|
|
137
|
+
try { sessionStorage.setItem(key, cw.location.href); } catch (_) {}
|
|
138
|
+
};
|
|
139
|
+
// Hook SPA navigations
|
|
140
|
+
const _ps = cw.history.pushState;
|
|
141
|
+
cw.history.pushState = function() { const r = _ps.apply(this, arguments); notify(); return r; };
|
|
142
|
+
const _rs = cw.history.replaceState;
|
|
143
|
+
cw.history.replaceState = function() { const r = _rs.apply(this, arguments); notify(); return r; };
|
|
144
|
+
cw.addEventListener('popstate', notify);
|
|
145
|
+
cw.addEventListener('hashchange', notify);
|
|
146
|
+
if (cw.document?.readyState === 'loading') cw.document.addEventListener('DOMContentLoaded', notify, { once: true });
|
|
147
|
+
else notify();
|
|
148
|
+
} catch (err) {
|
|
149
|
+
// Cross-origin: fall back to saving src only
|
|
150
|
+
try { sessionStorage.setItem(key, pane.src); } catch (_) {}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function onPaneLoadFactory(pane) {
|
|
155
|
+
return function onPaneLoad() {
|
|
156
|
+
attachSameOriginRouteHooks(pane);
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Overlay to avoid iframe stealing events in Chrome
|
|
161
|
+
function createOverlay() {
|
|
162
|
+
const el = document.createElement('div');
|
|
163
|
+
el.style.position = 'fixed';
|
|
164
|
+
el.style.inset = '0';
|
|
165
|
+
el.style.cursor = 'row-resize';
|
|
166
|
+
el.style.zIndex = '2147483647';
|
|
167
|
+
el.style.background = 'transparent';
|
|
168
|
+
return el;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
let startY = 0;
|
|
172
|
+
let startTop = 0;
|
|
173
|
+
let total = 0;
|
|
174
|
+
let overlay = null;
|
|
175
|
+
|
|
176
|
+
function refreshLayout (splitKey) {
|
|
177
|
+
let val = sessionStorage.getItem(splitKey)
|
|
178
|
+
let id = splitKey.replace("splitRatio:", "")
|
|
179
|
+
if (val === "1" || val === "0") {
|
|
180
|
+
if (val === "1") {
|
|
181
|
+
id_to_hide = id + ".1"
|
|
182
|
+
} else if (val === "0") {
|
|
183
|
+
id_to_hide = id + ".0"
|
|
184
|
+
}
|
|
185
|
+
const el = document.querySelector(`iframe[name='${id_to_hide}']`)
|
|
186
|
+
el.remove()
|
|
187
|
+
document.body.className = "single"
|
|
188
|
+
document.querySelector("#gutter").remove()
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
function onPointerMove(e) {
|
|
194
|
+
const delta = e.clientY - startY;
|
|
195
|
+
let newTop = startTop + delta;
|
|
196
|
+
newTop = Math.max(MIN, Math.min(total - MIN, newTop));
|
|
197
|
+
setRows(newTop);
|
|
198
|
+
updateAria(newTop, total);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function endDrag(e) {
|
|
202
|
+
if (gutter && e && e.pointerId != null && gutter.hasPointerCapture?.(e.pointerId)) {
|
|
203
|
+
try { gutter.releasePointerCapture(e.pointerId); } catch (_) {}
|
|
204
|
+
}
|
|
205
|
+
window.removeEventListener('pointermove', onPointerMove, true);
|
|
206
|
+
window.removeEventListener('pointerup', endDrag, true);
|
|
207
|
+
window.removeEventListener('pointercancel', endDrag, true);
|
|
208
|
+
if (overlay) {
|
|
209
|
+
overlay.remove();
|
|
210
|
+
overlay = null;
|
|
211
|
+
}
|
|
212
|
+
body.classList.remove('resizing');
|
|
213
|
+
// Persist position as ratio
|
|
214
|
+
try {
|
|
215
|
+
const topRect = topPane.getBoundingClientRect();
|
|
216
|
+
saveRatioFromTopPx(topRect.height);
|
|
217
|
+
} catch (_) {}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Restore child pane URLs before any interaction (override hardcoded src)
|
|
221
|
+
restorePaneURL(topPane);
|
|
222
|
+
restorePaneURL(bottomPane);
|
|
223
|
+
|
|
224
|
+
// Track navigations for each pane
|
|
225
|
+
topPane.addEventListener('load', onPaneLoadFactory(topPane));
|
|
226
|
+
bottomPane.addEventListener('load', onPaneLoadFactory(bottomPane));
|
|
227
|
+
|
|
228
|
+
if (gutter) {
|
|
229
|
+
gutter.addEventListener('pointerdown', (e) => {
|
|
230
|
+
e.preventDefault();
|
|
231
|
+
const bodyRect = body.getBoundingClientRect();
|
|
232
|
+
const topRect = topPane.getBoundingClientRect();
|
|
233
|
+
total = bodyRect.height - GUTTER; // total available for both iframes
|
|
234
|
+
startTop = topRect.height;
|
|
235
|
+
startY = e.clientY;
|
|
236
|
+
|
|
237
|
+
// Ensure we keep receiving events even over iframes
|
|
238
|
+
try { gutter.setPointerCapture(e.pointerId); } catch (_) {}
|
|
239
|
+
overlay = createOverlay();
|
|
240
|
+
document.body.appendChild(overlay);
|
|
241
|
+
|
|
242
|
+
window.addEventListener('pointermove', onPointerMove, true);
|
|
243
|
+
window.addEventListener('pointerup', endDrag, true);
|
|
244
|
+
window.addEventListener('pointercancel', endDrag, true);
|
|
245
|
+
body.classList.add('resizing');
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// Keyboard resizing for accessibility
|
|
249
|
+
gutter.addEventListener('keydown', (e) => {
|
|
250
|
+
const { key } = e;
|
|
251
|
+
if (key !== 'ArrowUp' && key !== 'ArrowDown' && key !== 'Home' && key !== 'End') return;
|
|
252
|
+
e.preventDefault();
|
|
253
|
+
const totalNow = computeTotal();
|
|
254
|
+
const rect = topPane.getBoundingClientRect();
|
|
255
|
+
const step = e.shiftKey ? KEY_STEP_BIG : KEY_STEP;
|
|
256
|
+
let topPx = rect.height;
|
|
257
|
+
if (key === 'ArrowUp') topPx -= step;
|
|
258
|
+
else if (key === 'ArrowDown') topPx += step;
|
|
259
|
+
else if (key === 'Home') topPx = MIN;
|
|
260
|
+
else if (key === 'End') topPx = totalNow - MIN;
|
|
261
|
+
topPx = clamp(topPx, MIN, totalNow - MIN);
|
|
262
|
+
setRows(topPx);
|
|
263
|
+
updateAria(topPx, totalNow);
|
|
264
|
+
saveRatioFromTopPx(topPx);
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Initialize from saved ratio if available and set ARIA
|
|
269
|
+
try {
|
|
270
|
+
const saved = parseFloat(sessionStorage.getItem(splitKey) || '');
|
|
271
|
+
console.log({ saved })
|
|
272
|
+
if (!Number.isNaN(saved) && saved > 0 && saved < 1) {
|
|
273
|
+
console.log("< 1")
|
|
274
|
+
applyFromRatio(saved);
|
|
275
|
+
} else {
|
|
276
|
+
console.log("< 2")
|
|
277
|
+
updateAria(topPane.getBoundingClientRect().height, computeTotal());
|
|
278
|
+
refreshLayout(splitKey)
|
|
279
|
+
}
|
|
280
|
+
} catch (_) {
|
|
281
|
+
console.log("< 3")
|
|
282
|
+
updateAria(topPane.getBoundingClientRect().height, computeTotal());
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Re-apply on window resize to keep ratio
|
|
286
|
+
window.addEventListener('resize', () => {
|
|
287
|
+
try {
|
|
288
|
+
const saved = parseFloat(sessionStorage.getItem(splitKey) || '');
|
|
289
|
+
if (!Number.isNaN(saved) && saved > 0 && saved < 1) {
|
|
290
|
+
applyFromRatio(saved);
|
|
291
|
+
} else {
|
|
292
|
+
updateAria(topPane.getBoundingClientRect().height, computeTotal());
|
|
293
|
+
}
|
|
294
|
+
} catch (_) {
|
|
295
|
+
updateAria(topPane.getBoundingClientRect().height, computeTotal());
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
window.addEventListener('message', (event) => {
|
|
299
|
+
if (event.data && event.data.e === "close") {
|
|
300
|
+
// find the frame
|
|
301
|
+
// Find which iframe sent the message
|
|
302
|
+
const row0 = document.getElementById('row0');
|
|
303
|
+
const row1 = document.getElementById('row1');
|
|
304
|
+
|
|
305
|
+
let sourceFrameId = null;
|
|
306
|
+
|
|
307
|
+
if (event.source === row0.contentWindow) {
|
|
308
|
+
sourceFrameId = 'row0';
|
|
309
|
+
} else if (event.source === row1.contentWindow) {
|
|
310
|
+
sourceFrameId = 'row1';
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
console.log('Message received from iframe:', sourceFrameId);
|
|
314
|
+
|
|
315
|
+
// Or use this approach to loop through all iframes
|
|
316
|
+
const iframes = document.querySelectorAll('iframe');
|
|
317
|
+
console.log({ splitKey })
|
|
318
|
+
for (let iframe of iframes) {
|
|
319
|
+
if (event.source === iframe.contentWindow) {
|
|
320
|
+
// const splitKey = `splitRatio:${iframe.name}`
|
|
321
|
+
if (iframe.id === "row0") {
|
|
322
|
+
// hide row0 => ratio:; 0
|
|
323
|
+
// row0.src = "about:blank"
|
|
324
|
+
try { sessionStorage.setItem(splitKey, "0"); } catch (_) { console.log("> e", _)}
|
|
325
|
+
refreshLayout(splitKey)
|
|
326
|
+
} else if (iframe.id === "row1") {
|
|
327
|
+
// hide row1 => ratio:; 1
|
|
328
|
+
// row1.src = "about:blank"
|
|
329
|
+
try { sessionStorage.setItem(splitKey, "1"); } catch (_) {console.log(">>> e", _)}
|
|
330
|
+
refreshLayout(splitKey)
|
|
331
|
+
}
|
|
332
|
+
console.log('Message from iframe with id:', iframe.id);
|
|
333
|
+
break;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
})
|
|
338
|
+
})();
|
|
339
|
+
</script>
|
|
340
|
+
</body>
|
|
341
|
+
</html>
|