pinokiod 7.1.13 → 7.1.14
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/package.json +1 -1
- package/server/index.js +27 -6
- package/server/public/common.js +0 -3
- package/server/views/app.ejs +38 -43
- package/server/views/d.ejs +39 -50
- package/server/views/partials/d_terminal_column.ejs +46 -0
- package/server/views/terminal.ejs +76 -4
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -970,12 +970,11 @@ class Server {
|
|
|
970
970
|
console.log("Chrome")
|
|
971
971
|
|
|
972
972
|
let name = req.params.name
|
|
973
|
-
|
|
974
|
-
console.time(binCheckLabel)
|
|
973
|
+
console.time("bin check")
|
|
975
974
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
976
975
|
bin: this.kernel.bin.preset("dev"),
|
|
977
976
|
})
|
|
978
|
-
console.timeEnd(
|
|
977
|
+
console.timeEnd("bin check")
|
|
979
978
|
if (!requirements_pending && install_required) {
|
|
980
979
|
res.redirect(`/setup/dev?callback=${req.originalUrl}`)
|
|
981
980
|
return
|
|
@@ -4765,8 +4764,12 @@ class Server {
|
|
|
4765
4764
|
// }
|
|
4766
4765
|
}
|
|
4767
4766
|
}
|
|
4768
|
-
async terminals(filepath) {
|
|
4769
|
-
|
|
4767
|
+
async terminals(filepath, options = {}) {
|
|
4768
|
+
const includeVenvs = options.includeVenvs !== false
|
|
4769
|
+
let venvs = []
|
|
4770
|
+
if (includeVenvs) {
|
|
4771
|
+
venvs = await Util.find_venv(filepath)
|
|
4772
|
+
}
|
|
4770
4773
|
let terminal
|
|
4771
4774
|
const windowsBashPath = await this.resolveWindowsBashPath()
|
|
4772
4775
|
const hasWindowsBashOption = this.kernel.platform === "win32" && typeof windowsBashPath === "string" && windowsBashPath.length > 0
|
|
@@ -10766,7 +10769,7 @@ class Server {
|
|
|
10766
10769
|
}))
|
|
10767
10770
|
this.app.get("/d/*", ex(async (req, res) => {
|
|
10768
10771
|
let filepath = Util.u2p(req.params[0])
|
|
10769
|
-
let terminal = await this.terminals(filepath)
|
|
10772
|
+
let terminal = await this.terminals(filepath, { includeVenvs: false })
|
|
10770
10773
|
let plugin = await this.getPluginGlobal(req, this.kernel.plugin.config, terminal, filepath)
|
|
10771
10774
|
let html = ""
|
|
10772
10775
|
let plugin_menu
|
|
@@ -10909,6 +10912,7 @@ class Server {
|
|
|
10909
10912
|
install: this.install,
|
|
10910
10913
|
agent: req.agent,
|
|
10911
10914
|
theme: this.theme,
|
|
10915
|
+
terminals_url: "/pinokio/d-terminals/" + req.params[0],
|
|
10912
10916
|
//dynamic: plugin_menu
|
|
10913
10917
|
dynamic,
|
|
10914
10918
|
})
|
|
@@ -11051,6 +11055,23 @@ class Server {
|
|
|
11051
11055
|
res.send("")
|
|
11052
11056
|
}
|
|
11053
11057
|
}))
|
|
11058
|
+
this.app.get("/pinokio/d-terminals/*", ex(async (req, res) => {
|
|
11059
|
+
let filepath = Util.u2p(req.params[0])
|
|
11060
|
+
let terminal = await this.terminals(filepath)
|
|
11061
|
+
const html = await new Promise((resolve, reject) => {
|
|
11062
|
+
ejs.renderFile(path.resolve(__dirname, "views/partials/d_terminal_column.ejs"), {
|
|
11063
|
+
userTerminal: terminal,
|
|
11064
|
+
terminals_url: null,
|
|
11065
|
+
}, (err, html) => {
|
|
11066
|
+
if (err) {
|
|
11067
|
+
reject(err)
|
|
11068
|
+
return
|
|
11069
|
+
}
|
|
11070
|
+
resolve(html)
|
|
11071
|
+
})
|
|
11072
|
+
})
|
|
11073
|
+
res.send(html)
|
|
11074
|
+
}))
|
|
11054
11075
|
this.app.get("/pinokio/dynamic/:name", ex(async (req, res) => {
|
|
11055
11076
|
// await this.kernel.plugin.init()
|
|
11056
11077
|
|
package/server/public/common.js
CHANGED
|
@@ -3928,9 +3928,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
3928
3928
|
}
|
|
3929
3929
|
const fallbackUrl = buildAskAiLaunchUrl(tool.href, workspaceCwd);
|
|
3930
3930
|
if (fallbackUrl) {
|
|
3931
|
-
refreshTerminalSessions(fallbackUrl, workspaceCwd, {
|
|
3932
|
-
retryDelays: []
|
|
3933
|
-
});
|
|
3934
3931
|
window.location.href = fallbackUrl;
|
|
3935
3932
|
}
|
|
3936
3933
|
}
|
package/server/views/app.ejs
CHANGED
|
@@ -5302,6 +5302,7 @@ header.navheader .mode-selector .community-mode-toggle {
|
|
|
5302
5302
|
let interacted = false
|
|
5303
5303
|
let global_selector
|
|
5304
5304
|
let pendingSelectionRetry = null
|
|
5305
|
+
let initialWorkspaceDiskUsageRequested = false
|
|
5305
5306
|
const scheduleSelectionRetry = (delay = 100) => {
|
|
5306
5307
|
if (pendingSelectionRetry !== null) {
|
|
5307
5308
|
return
|
|
@@ -5470,10 +5471,12 @@ header.navheader .mode-selector .community-mode-toggle {
|
|
|
5470
5471
|
})
|
|
5471
5472
|
let frame = document.createElement("iframe")
|
|
5472
5473
|
frame.name = name
|
|
5473
|
-
refreshTerminalSessions(href)
|
|
5474
5474
|
frame.src = href
|
|
5475
5475
|
frame.classList.add("selected")
|
|
5476
5476
|
iframe_onerror(frame)
|
|
5477
|
+
frame.addEventListener("load", () => {
|
|
5478
|
+
requestInitialWorkspaceDiskUsage()
|
|
5479
|
+
}, { once: true })
|
|
5477
5480
|
frame.setAttribute(
|
|
5478
5481
|
"allow",
|
|
5479
5482
|
"clipboard-read *; clipboard-write *; accelerometer *; ambient-light-sensor *; autoplay *; battery *; camera *; display-capture *; fullscreen *; gamepad *; geolocation *; gyroscope *; hid *; identity-credentials-get *; microphone *; midi *; otp-credentials *; serial *;"
|
|
@@ -5484,17 +5487,6 @@ header.navheader .mode-selector .community-mode-toggle {
|
|
|
5484
5487
|
document.querySelector("main").appendChild(frame)
|
|
5485
5488
|
loaded[name] = true
|
|
5486
5489
|
}
|
|
5487
|
-
function refreshTerminalSessions(rawUrl, workspaceCwd = "", options = {}) {
|
|
5488
|
-
try {
|
|
5489
|
-
const discovery = window.PinokioTerminalsDiscovery
|
|
5490
|
-
if (!discovery || typeof discovery.refreshTerminalSessions !== "function") {
|
|
5491
|
-
return false
|
|
5492
|
-
}
|
|
5493
|
-
return discovery.refreshTerminalSessions(rawUrl, workspaceCwd, options)
|
|
5494
|
-
} catch (_) {
|
|
5495
|
-
return false
|
|
5496
|
-
}
|
|
5497
|
-
}
|
|
5498
5490
|
installBrowserviewInjectTargetObserver()
|
|
5499
5491
|
document.addEventListener("click", (e) => {
|
|
5500
5492
|
interacted = true
|
|
@@ -6579,14 +6571,10 @@ const rerenderMenuSection = (container, html) => {
|
|
|
6579
6571
|
|
|
6580
6572
|
|
|
6581
6573
|
// Instantiate a frame with the selected target's href
|
|
6582
|
-
let url = target.href
|
|
6583
6574
|
const targetInjectDescriptors = readLinkInjectDescriptors(target)
|
|
6584
|
-
if (!
|
|
6575
|
+
if (!target.href) {
|
|
6585
6576
|
return
|
|
6586
6577
|
}
|
|
6587
|
-
// document.querySelector("#open-browser").href = url
|
|
6588
|
-
// document.querySelector("#clone-tab").setAttribute("data-href", url)
|
|
6589
|
-
|
|
6590
6578
|
//document.querySelector("#location").value = url
|
|
6591
6579
|
|
|
6592
6580
|
// document.querySelector("#open-location").setAttribute('href', target.href)
|
|
@@ -6634,6 +6622,7 @@ const rerenderMenuSection = (container, html) => {
|
|
|
6634
6622
|
eventParam.preventDefault()
|
|
6635
6623
|
eventParam.stopPropagation()
|
|
6636
6624
|
}
|
|
6625
|
+
requestInitialWorkspaceDiskUsage()
|
|
6637
6626
|
browserPopoutSurface.show(target)
|
|
6638
6627
|
return
|
|
6639
6628
|
}
|
|
@@ -6709,7 +6698,6 @@ const rerenderMenuSection = (container, html) => {
|
|
|
6709
6698
|
let mode = target.getAttribute("data-mode")
|
|
6710
6699
|
if (mode === "refresh") {
|
|
6711
6700
|
if (targetFrame.src !== target.href) {
|
|
6712
|
-
refreshTerminalSessions(target.href)
|
|
6713
6701
|
targetFrame.src = target.href
|
|
6714
6702
|
}
|
|
6715
6703
|
} else {
|
|
@@ -6720,7 +6708,6 @@ const rerenderMenuSection = (container, html) => {
|
|
|
6720
6708
|
let sub = subUrlOf(target.href, targetFrame.src)
|
|
6721
6709
|
if (!sub) {
|
|
6722
6710
|
if (targetFrame.src !== target.href) {
|
|
6723
|
-
refreshTerminalSessions(target.href)
|
|
6724
6711
|
targetFrame.src = target.href
|
|
6725
6712
|
}
|
|
6726
6713
|
}
|
|
@@ -6736,7 +6723,6 @@ const rerenderMenuSection = (container, html) => {
|
|
|
6736
6723
|
} else {
|
|
6737
6724
|
if (force) {
|
|
6738
6725
|
if (targetFrame.src !== target.href) {
|
|
6739
|
-
refreshTerminalSessions(target.href)
|
|
6740
6726
|
targetFrame.src = target.href
|
|
6741
6727
|
}
|
|
6742
6728
|
}
|
|
@@ -6758,15 +6744,17 @@ const rerenderMenuSection = (container, html) => {
|
|
|
6758
6744
|
} else {
|
|
6759
6745
|
let frame = document.createElement("iframe")
|
|
6760
6746
|
frame.name = target.target
|
|
6761
|
-
refreshTerminalSessions(target.href)
|
|
6762
6747
|
frame.src = target.href
|
|
6763
|
-
|
|
6764
|
-
|
|
6765
|
-
|
|
6766
|
-
|
|
6748
|
+
iframe_onerror(frame)
|
|
6749
|
+
frame.addEventListener("load", () => {
|
|
6750
|
+
requestInitialWorkspaceDiskUsage()
|
|
6751
|
+
}, { once: true })
|
|
6752
|
+
frame.setAttribute(
|
|
6753
|
+
"allow",
|
|
6754
|
+
"clipboard-read *; clipboard-write *; accelerometer *; ambient-light-sensor *; autoplay *; battery *; camera *; display-capture *; fullscreen *; gamepad *; geolocation *; gyroscope *; hid *; identity-credentials-get *; microphone *; midi *; otp-credentials *; serial *;"
|
|
6767
6755
|
)
|
|
6768
6756
|
frame.setAttribute("allowfullscreen", "")
|
|
6769
|
-
|
|
6757
|
+
writeFrameInjectDescriptors(frame, targetInjectDescriptors)
|
|
6770
6758
|
publishBrowserviewInjectTargets([frame], { sync: true })
|
|
6771
6759
|
document.querySelector("main").appendChild(frame)
|
|
6772
6760
|
loaded[target.target] = true
|
|
@@ -6922,14 +6910,17 @@ const rerenderMenuSection = (container, html) => {
|
|
|
6922
6910
|
|
|
6923
6911
|
document.querySelector(".temp-menu").appendChild(item)
|
|
6924
6912
|
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6913
|
+
let frame = document.createElement("iframe")
|
|
6914
|
+
frame.name = id
|
|
6915
|
+
frame.src = item.href
|
|
6916
|
+
iframe_onerror(frame)
|
|
6917
|
+
frame.addEventListener("load", () => {
|
|
6918
|
+
requestInitialWorkspaceDiskUsage()
|
|
6919
|
+
}, { once: true })
|
|
6920
|
+
frame.setAttribute(
|
|
6921
|
+
"allow",
|
|
6922
|
+
"clipboard-read *; clipboard-write *; accelerometer *; ambient-light-sensor *; autoplay *; battery *; camera *; display-capture *; fullscreen *; gamepad *; geolocation *; gyroscope *; hid *; identity-credentials-get *; microphone *; midi *; otp-credentials *; serial *;"
|
|
6923
|
+
)
|
|
6933
6924
|
frame.setAttribute("allowfullscreen", "")
|
|
6934
6925
|
document.querySelector("main").appendChild(frame)
|
|
6935
6926
|
|
|
@@ -7998,6 +7989,14 @@ const rerenderMenuSection = (container, html) => {
|
|
|
7998
7989
|
})
|
|
7999
7990
|
}
|
|
8000
7991
|
}
|
|
7992
|
+
const requestInitialWorkspaceDiskUsage = () => {
|
|
7993
|
+
if (initialWorkspaceDiskUsageRequested) {
|
|
7994
|
+
return
|
|
7995
|
+
}
|
|
7996
|
+
initialWorkspaceDiskUsageRequested = true
|
|
7997
|
+
refresh_du()
|
|
7998
|
+
refresh_du("logs")
|
|
7999
|
+
}
|
|
8001
8000
|
|
|
8002
8001
|
const try_dynamic = async (options = {}) => {
|
|
8003
8002
|
let rendered
|
|
@@ -8032,7 +8031,8 @@ const rerenderMenuSection = (container, html) => {
|
|
|
8032
8031
|
} else {
|
|
8033
8032
|
rendered = false
|
|
8034
8033
|
}
|
|
8035
|
-
if (
|
|
8034
|
+
if (rendered) {
|
|
8035
|
+
} else {
|
|
8036
8036
|
if (options.retryOnEmpty === false) {
|
|
8037
8037
|
return
|
|
8038
8038
|
}
|
|
@@ -8089,13 +8089,9 @@ const rerenderMenuSection = (container, html) => {
|
|
|
8089
8089
|
renderSelection()
|
|
8090
8090
|
}
|
|
8091
8091
|
}
|
|
8092
|
-
let init = document.querySelector("[data-init]")
|
|
8093
|
-
if (init) {
|
|
8094
|
-
init.click()
|
|
8095
|
-
}
|
|
8096
8092
|
<% if (type === 'browse') { %>
|
|
8097
8093
|
setTimeout(() => {
|
|
8098
|
-
try_dynamic(
|
|
8094
|
+
try_dynamic()
|
|
8099
8095
|
}, 0)
|
|
8100
8096
|
<% } %>
|
|
8101
8097
|
window.addEventListener('message', (event) => {
|
|
@@ -8155,6 +8151,8 @@ const rerenderMenuSection = (container, html) => {
|
|
|
8155
8151
|
if (event.data.type === 'stream') {
|
|
8156
8152
|
const frameName = resolveFrameName(null, event.source)
|
|
8157
8153
|
updateTabTimestamp(frameName, Date.now())
|
|
8154
|
+
} else if (event.data.type === 'idle') {
|
|
8155
|
+
return
|
|
8158
8156
|
} else if (event.data.type === 'restart') {
|
|
8159
8157
|
<% if (type === 'run') { %>
|
|
8160
8158
|
clearPersistedFrameLinkSelection()
|
|
@@ -8183,8 +8181,6 @@ const rerenderMenuSection = (container, html) => {
|
|
|
8183
8181
|
|
|
8184
8182
|
|
|
8185
8183
|
});
|
|
8186
|
-
refresh_du()
|
|
8187
|
-
refresh_du("logs")
|
|
8188
8184
|
renderSelection({ force: true })
|
|
8189
8185
|
<% if (type === "browse" || type === "files") { %>
|
|
8190
8186
|
const repoStatusCache = new Map()
|
|
@@ -12405,7 +12401,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
12405
12401
|
if (!normalized) {
|
|
12406
12402
|
return false
|
|
12407
12403
|
}
|
|
12408
|
-
refreshTerminalSessions(normalized, workspaceCwd)
|
|
12409
12404
|
pickerRequestId += 1
|
|
12410
12405
|
currentUrl = normalized
|
|
12411
12406
|
setLocation(normalized)
|
package/server/views/d.ejs
CHANGED
|
@@ -524,51 +524,7 @@ body.dark #update-spec {
|
|
|
524
524
|
|
|
525
525
|
<div class='menu-grid <%= primaryColumnCount === 3 ? "menu-grid--triptych" : "" %>'>
|
|
526
526
|
<% if (userTerminal && userTerminal.menu && userTerminal.menu.length) { %>
|
|
527
|
-
|
|
528
|
-
<div class='tab-header'>
|
|
529
|
-
<h3><i class='<%= userTerminal.icon %>'></i> <%= userTerminal.title %></h3>
|
|
530
|
-
</div>
|
|
531
|
-
<% if (userTerminal.subtitle || userTerminal.subtitle_link_href) { %>
|
|
532
|
-
<div class='column-subtitle'>
|
|
533
|
-
<% if (userTerminal.subtitle) { %>
|
|
534
|
-
<span><%= userTerminal.subtitle %></span><% if (userTerminal.subtitle_link_href && userTerminal.subtitle_link_label) { %> <% } %>
|
|
535
|
-
<% } %>
|
|
536
|
-
<% if (userTerminal.subtitle_link_href && userTerminal.subtitle_link_label) { %>
|
|
537
|
-
<a class='column-subtitle-link' href="<%= userTerminal.subtitle_link_href %>" target="_parent"><%= userTerminal.subtitle_link_label %></a>
|
|
538
|
-
<% } %>
|
|
539
|
-
</div>
|
|
540
|
-
<% } %>
|
|
541
|
-
<div class='tab-content'>
|
|
542
|
-
<% userTerminal.menu.forEach((i) => { %>
|
|
543
|
-
<div class='tab' role="button" tabindex="0" data-index="<%= index++ %>" data-target="@<%= i.href %>" data-href="<%= i.href %>">
|
|
544
|
-
<% if (i.image) { %>
|
|
545
|
-
<img src="<%= i.image %>">
|
|
546
|
-
<% } else if (i.icon) { %>
|
|
547
|
-
<i class="img <%= i.icon %>"></i>
|
|
548
|
-
<% } %>
|
|
549
|
-
<div class='tab-copy'>
|
|
550
|
-
<h2 class='tab-title'><%= i.title %></h2>
|
|
551
|
-
<% if (i.subtitle) { %>
|
|
552
|
-
<div class='tab-subtitle subtitle'><%= i.subtitle %></div>
|
|
553
|
-
<% } %>
|
|
554
|
-
</div>
|
|
555
|
-
<div class='tab-actions'>
|
|
556
|
-
<% if (i.link) { %>
|
|
557
|
-
<button class="tab-action-link" type="button" data-doc-link="true" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs" aria-label="Open docs">
|
|
558
|
-
<i class="fa-solid fa-circle-info"></i>
|
|
559
|
-
</button>
|
|
560
|
-
<% } %>
|
|
561
|
-
<button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions" aria-label="AI permissions">
|
|
562
|
-
<i class="fa-solid fa-shield-halved"></i>
|
|
563
|
-
</button>
|
|
564
|
-
<div class='disclosure-indicator' aria-hidden="true">
|
|
565
|
-
<i class="fa-solid fa-chevron-right"></i>
|
|
566
|
-
</div>
|
|
567
|
-
</div>
|
|
568
|
-
</div>
|
|
569
|
-
<% }) %>
|
|
570
|
-
</div>
|
|
571
|
-
</div>
|
|
527
|
+
<%- include('./partials/d_terminal_column', { userTerminal, terminals_url }) %>
|
|
572
528
|
<% } %>
|
|
573
529
|
|
|
574
530
|
<% if (cliMenu && cliMenu.menu && cliMenu.menu.length) { %>
|
|
@@ -797,12 +753,16 @@ document.querySelector("#update-spec").addEventListener("click", (e) => {
|
|
|
797
753
|
})
|
|
798
754
|
*/
|
|
799
755
|
let list = []
|
|
800
|
-
|
|
801
|
-
list
|
|
802
|
-
|
|
803
|
-
|
|
756
|
+
const rebuildTabList = () => {
|
|
757
|
+
list = []
|
|
758
|
+
document.querySelectorAll(".tab").forEach((el, index) => {
|
|
759
|
+
el.setAttribute("data-index", String(index))
|
|
760
|
+
list.push({
|
|
761
|
+
index,
|
|
762
|
+
text: el.textContent,
|
|
763
|
+
})
|
|
804
764
|
})
|
|
805
|
-
}
|
|
765
|
+
}
|
|
806
766
|
const search = (items, value) => {
|
|
807
767
|
let filtered = []
|
|
808
768
|
for(let i=0; i<items.length; i++) {
|
|
@@ -848,6 +808,7 @@ const renderSearch = () => {
|
|
|
848
808
|
}
|
|
849
809
|
}
|
|
850
810
|
}
|
|
811
|
+
rebuildTabList()
|
|
851
812
|
renderSearch()
|
|
852
813
|
const workspaceCwd = (() => {
|
|
853
814
|
const node = document.querySelector(".file-open")
|
|
@@ -973,6 +934,34 @@ document.querySelector("form input[type=search]").addEventListener("input", (e)
|
|
|
973
934
|
renderSearch()
|
|
974
935
|
})
|
|
975
936
|
document.querySelector("form input[type=search]").focus()
|
|
937
|
+
const hydrateTerminalColumn = async () => {
|
|
938
|
+
const terminalColumn = document.querySelector("[data-dev-terminals-column][data-terminals-url]")
|
|
939
|
+
if (!terminalColumn) {
|
|
940
|
+
return
|
|
941
|
+
}
|
|
942
|
+
const url = terminalColumn.getAttribute("data-terminals-url")
|
|
943
|
+
if (!url) {
|
|
944
|
+
return
|
|
945
|
+
}
|
|
946
|
+
try {
|
|
947
|
+
const html = await fetch(url).then((res) => res.text())
|
|
948
|
+
if (!html || html.trim().length === 0) {
|
|
949
|
+
return
|
|
950
|
+
}
|
|
951
|
+
const wrapper = document.createElement("div")
|
|
952
|
+
wrapper.innerHTML = html
|
|
953
|
+
const nextColumn = wrapper.firstElementChild
|
|
954
|
+
if (!nextColumn) {
|
|
955
|
+
return
|
|
956
|
+
}
|
|
957
|
+
terminalColumn.replaceWith(nextColumn)
|
|
958
|
+
rebuildTabList()
|
|
959
|
+
renderSearch()
|
|
960
|
+
} catch (_) {}
|
|
961
|
+
}
|
|
962
|
+
setTimeout(() => {
|
|
963
|
+
hydrateTerminalColumn()
|
|
964
|
+
}, 0)
|
|
976
965
|
document.addEventListener("click", (e) => {
|
|
977
966
|
const permTarget = e.target.closest('[data-ai-consent]')
|
|
978
967
|
if (permTarget) {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<div class='menu-container menu-column user-terminal' data-dev-terminals-column="true"<% if (terminals_url) { %> data-terminals-url="<%= terminals_url %>"<% } %>>
|
|
2
|
+
<div class='tab-header'>
|
|
3
|
+
<h3><i class='<%= userTerminal.icon %>'></i> <%= userTerminal.title %></h3>
|
|
4
|
+
</div>
|
|
5
|
+
<% if (userTerminal.subtitle || userTerminal.subtitle_link_href) { %>
|
|
6
|
+
<div class='column-subtitle'>
|
|
7
|
+
<% if (userTerminal.subtitle) { %>
|
|
8
|
+
<span><%= userTerminal.subtitle %></span><% if (userTerminal.subtitle_link_href && userTerminal.subtitle_link_label) { %> <% } %>
|
|
9
|
+
<% } %>
|
|
10
|
+
<% if (userTerminal.subtitle_link_href && userTerminal.subtitle_link_label) { %>
|
|
11
|
+
<a class='column-subtitle-link' href="<%= userTerminal.subtitle_link_href %>" target="_parent"><%= userTerminal.subtitle_link_label %></a>
|
|
12
|
+
<% } %>
|
|
13
|
+
</div>
|
|
14
|
+
<% } %>
|
|
15
|
+
<div class='tab-content'>
|
|
16
|
+
<% let localIndex = 0 %>
|
|
17
|
+
<% userTerminal.menu.forEach((i) => { %>
|
|
18
|
+
<div class='tab' role="button" tabindex="0" data-index="<%= localIndex++ %>" data-target="@<%= i.href %>" data-href="<%= i.href %>">
|
|
19
|
+
<% if (i.image) { %>
|
|
20
|
+
<img src="<%= i.image %>">
|
|
21
|
+
<% } else if (i.icon) { %>
|
|
22
|
+
<i class="img <%= i.icon %>"></i>
|
|
23
|
+
<% } %>
|
|
24
|
+
<div class='tab-copy'>
|
|
25
|
+
<h2 class='tab-title'><%= i.title %></h2>
|
|
26
|
+
<% if (i.subtitle) { %>
|
|
27
|
+
<div class='tab-subtitle subtitle'><%= i.subtitle %></div>
|
|
28
|
+
<% } %>
|
|
29
|
+
</div>
|
|
30
|
+
<div class='tab-actions'>
|
|
31
|
+
<% if (i.link) { %>
|
|
32
|
+
<button class="tab-action-link" type="button" data-doc-link="true" data-href="<%= i.link %>" title="Open docs" data-tippy-content="Open docs" aria-label="Open docs">
|
|
33
|
+
<i class="fa-solid fa-circle-info"></i>
|
|
34
|
+
</button>
|
|
35
|
+
<% } %>
|
|
36
|
+
<button class="ai-perm-link" type="button" data-ai-consent="<%= i.href %>" title="AI permissions" data-tippy-content="AI permissions" aria-label="AI permissions">
|
|
37
|
+
<i class="fa-solid fa-shield-halved"></i>
|
|
38
|
+
</button>
|
|
39
|
+
<div class='disclosure-indicator' aria-hidden="true">
|
|
40
|
+
<i class="fa-solid fa-chevron-right"></i>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
<% }) %>
|
|
45
|
+
</div>
|
|
46
|
+
</div>
|
|
@@ -552,6 +552,67 @@ const createRunControls = () => {
|
|
|
552
552
|
}
|
|
553
553
|
return { set }
|
|
554
554
|
}
|
|
555
|
+
const PLUGIN_TERMINAL_IDLE_WINDOW_MS = 1200
|
|
556
|
+
const createPluginTerminalDiscoveryRefresher = (context = {}) => {
|
|
557
|
+
const enabled = (() => {
|
|
558
|
+
try {
|
|
559
|
+
return window.location.pathname.startsWith("/run/plugin/")
|
|
560
|
+
} catch (_) {
|
|
561
|
+
return false
|
|
562
|
+
}
|
|
563
|
+
})()
|
|
564
|
+
let idleTimer = null
|
|
565
|
+
let armed = false
|
|
566
|
+
let sawStream = false
|
|
567
|
+
const clearIdleTimer = () => {
|
|
568
|
+
if (idleTimer) {
|
|
569
|
+
clearTimeout(idleTimer)
|
|
570
|
+
idleTimer = null
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
const refresh = () => {
|
|
574
|
+
if (!enabled || !armed || !sawStream) {
|
|
575
|
+
return
|
|
576
|
+
}
|
|
577
|
+
armed = false
|
|
578
|
+
sawStream = false
|
|
579
|
+
try {
|
|
580
|
+
const discovery = window.PinokioTerminalsDiscovery
|
|
581
|
+
if (!discovery || typeof discovery.refreshTerminalSessions !== "function") {
|
|
582
|
+
return
|
|
583
|
+
}
|
|
584
|
+
discovery.refreshTerminalSessions(window.location.href, context.cwd || "", {
|
|
585
|
+
retryDelays: []
|
|
586
|
+
})
|
|
587
|
+
} catch (_) {}
|
|
588
|
+
}
|
|
589
|
+
return {
|
|
590
|
+
arm(meaningful) {
|
|
591
|
+
if (!enabled || !meaningful) {
|
|
592
|
+
return
|
|
593
|
+
}
|
|
594
|
+
armed = true
|
|
595
|
+
sawStream = false
|
|
596
|
+
clearIdleTimer()
|
|
597
|
+
},
|
|
598
|
+
markActivity() {
|
|
599
|
+
if (!enabled || !armed) {
|
|
600
|
+
return
|
|
601
|
+
}
|
|
602
|
+
sawStream = true
|
|
603
|
+
clearIdleTimer()
|
|
604
|
+
idleTimer = setTimeout(() => {
|
|
605
|
+
idleTimer = null
|
|
606
|
+
refresh()
|
|
607
|
+
}, PLUGIN_TERMINAL_IDLE_WINDOW_MS)
|
|
608
|
+
},
|
|
609
|
+
clear() {
|
|
610
|
+
armed = false
|
|
611
|
+
sawStream = false
|
|
612
|
+
clearIdleTimer()
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
555
616
|
const createAiConsentManager = (context = {}) => {
|
|
556
617
|
const storage = getSafeLocalStorage()
|
|
557
618
|
const storageSupported = !!storage
|
|
@@ -848,6 +909,9 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
848
909
|
uri: scriptUri || ("~" + location.pathname)
|
|
849
910
|
})
|
|
850
911
|
const runControls = createRunControls()
|
|
912
|
+
const pluginTerminalDiscoveryRefresher = createPluginTerminalDiscoveryRefresher({
|
|
913
|
+
cwd: scriptCwd
|
|
914
|
+
})
|
|
851
915
|
consentManager.showChipIfRemembered()
|
|
852
916
|
class RPC {
|
|
853
917
|
constructor() {
|
|
@@ -923,16 +987,17 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
923
987
|
}
|
|
924
988
|
}
|
|
925
989
|
notifyLineSubmitted(line, meta = {}) {
|
|
926
|
-
if (this.inputTracker) {
|
|
927
|
-
this.inputTracker.submit(line, meta)
|
|
928
|
-
return
|
|
929
|
-
}
|
|
930
990
|
const safeLine = sanitizePreviewLine(line || "")
|
|
931
991
|
const preview = safeLine.trim()
|
|
932
992
|
const limit = 200
|
|
933
993
|
const truncated = preview.length > limit ? preview.slice(0, limit) + "..." : preview
|
|
934
994
|
const hadLineBreak = Boolean(meta && meta.hadLineBreak)
|
|
935
995
|
const meaningful = truncated.length > 0 || hadLineBreak
|
|
996
|
+
pluginTerminalDiscoveryRefresher.arm(meaningful)
|
|
997
|
+
if (this.inputTracker) {
|
|
998
|
+
this.inputTracker.submit(line, meta)
|
|
999
|
+
return
|
|
1000
|
+
}
|
|
936
1001
|
postMessageToAncestors({
|
|
937
1002
|
type: "terminal-input",
|
|
938
1003
|
frame: window.name || null,
|
|
@@ -1096,6 +1161,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1096
1161
|
}
|
|
1097
1162
|
} else if (packet.type === "stream") {
|
|
1098
1163
|
refreshParent(packet)
|
|
1164
|
+
pluginTerminalDiscoveryRefresher.markActivity()
|
|
1099
1165
|
// set the current shell id
|
|
1100
1166
|
const previousShellId = shell_id
|
|
1101
1167
|
if (packet.data.id) {
|
|
@@ -1128,6 +1194,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1128
1194
|
runControls.set("running")
|
|
1129
1195
|
} else if (packet.type === 'disconnect') {
|
|
1130
1196
|
refreshParent(packet)
|
|
1197
|
+
pluginTerminalDiscoveryRefresher.clear()
|
|
1131
1198
|
reloadMemory()
|
|
1132
1199
|
this.term.write("\r\nDisconnected...\r\n")
|
|
1133
1200
|
document.querySelector("#status-window").innerHTML = "<b>Ready</b>"
|
|
@@ -1423,6 +1490,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1423
1490
|
n.Noty(payload)
|
|
1424
1491
|
}
|
|
1425
1492
|
} else if (packet.type === "restart") {
|
|
1493
|
+
pluginTerminalDiscoveryRefresher.clear()
|
|
1426
1494
|
try {
|
|
1427
1495
|
if (window.parent && window.parent !== window && typeof window.parent.postMessage === "function") {
|
|
1428
1496
|
window.parent.postMessage(packet, "*")
|
|
@@ -1469,6 +1537,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1469
1537
|
text: `${packet.data}`,
|
|
1470
1538
|
})
|
|
1471
1539
|
} else if (packet.type === "error") {
|
|
1540
|
+
pluginTerminalDiscoveryRefresher.clear()
|
|
1472
1541
|
runControls.set("idle")
|
|
1473
1542
|
|
|
1474
1543
|
|
|
@@ -1547,6 +1616,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1547
1616
|
type: 'success'
|
|
1548
1617
|
})
|
|
1549
1618
|
*/
|
|
1619
|
+
pluginTerminalDiscoveryRefresher.clear()
|
|
1550
1620
|
runControls.set("idle")
|
|
1551
1621
|
}, 0)
|
|
1552
1622
|
//this.socket.close()
|
|
@@ -1575,6 +1645,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1575
1645
|
this.mode = (mode ? mode : "run")
|
|
1576
1646
|
const allowed = aiConsentRequired ? await consentManager.ensureAllowed() : true
|
|
1577
1647
|
if (!allowed) {
|
|
1648
|
+
pluginTerminalDiscoveryRefresher.clear()
|
|
1578
1649
|
runControls.set("idle")
|
|
1579
1650
|
n.Noty({
|
|
1580
1651
|
text: "Run canceled; AI agents remain blocked for this folder.",
|
|
@@ -1601,6 +1672,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1601
1672
|
await this.start(mode)
|
|
1602
1673
|
return true
|
|
1603
1674
|
} catch (error) {
|
|
1675
|
+
pluginTerminalDiscoveryRefresher.clear()
|
|
1604
1676
|
runControls.set("idle")
|
|
1605
1677
|
const message = error && error.message ? error.message : "Failed to start"
|
|
1606
1678
|
n.Noty({
|