pinokiod 7.1.12 → 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/kernel/util.js +11 -2
- package/package.json +1 -1
- package/server/index.js +28 -32
- package/server/public/common.js +0 -3
- package/server/public/create-launcher.js +3 -1
- package/server/public/urldropdown.css +15 -0
- package/server/views/app.ejs +44 -55
- 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/kernel/util.js
CHANGED
|
@@ -626,7 +626,11 @@ const find_python = async (root) => {
|
|
|
626
626
|
} else {
|
|
627
627
|
python_pattern = "**/python"; // Matches python, python3, python3.x
|
|
628
628
|
}
|
|
629
|
-
const pythonBinaries = await glob(python_pattern, {
|
|
629
|
+
const pythonBinaries = await glob(python_pattern, {
|
|
630
|
+
nodir: true,
|
|
631
|
+
cwd: root,
|
|
632
|
+
ignore: ["**/.git/**", "**/node_modules/**"],
|
|
633
|
+
});
|
|
630
634
|
return pythonBinaries
|
|
631
635
|
}
|
|
632
636
|
const find_venv = async (root) => {
|
|
@@ -636,7 +640,12 @@ const find_venv = async (root) => {
|
|
|
636
640
|
} else {
|
|
637
641
|
python_pattern = "**/python"; // Matches python, python3, python3.x
|
|
638
642
|
}
|
|
639
|
-
const pythonBinaries = await glob(python_pattern, {
|
|
643
|
+
const pythonBinaries = await glob(python_pattern, {
|
|
644
|
+
nodir: true,
|
|
645
|
+
cwd: root,
|
|
646
|
+
absolute: true,
|
|
647
|
+
ignore: ["**/.git/**", "**/node_modules/**"],
|
|
648
|
+
});
|
|
640
649
|
const venvs = pythonBinaries.map((p) => {
|
|
641
650
|
return path.resolve(p, "../..")
|
|
642
651
|
})
|
package/package.json
CHANGED
package/server/index.js
CHANGED
|
@@ -969,7 +969,7 @@ class Server {
|
|
|
969
969
|
async chrome(req, res, type, options) {
|
|
970
970
|
console.log("Chrome")
|
|
971
971
|
|
|
972
|
-
let
|
|
972
|
+
let name = req.params.name
|
|
973
973
|
console.time("bin check")
|
|
974
974
|
let { requirements, install_required, requirements_pending, error } = await this.kernel.bin.check({
|
|
975
975
|
bin: this.kernel.bin.preset("dev"),
|
|
@@ -992,7 +992,6 @@ class Server {
|
|
|
992
992
|
})
|
|
993
993
|
}
|
|
994
994
|
|
|
995
|
-
let name = req.params.name
|
|
996
995
|
let config = await this.kernel.api.meta(name)
|
|
997
996
|
|
|
998
997
|
if (options && options.requestPermissions && req.agent === "electron" && this.browser && typeof this.browser.requestPermissions === "function") {
|
|
@@ -1090,33 +1089,8 @@ class Server {
|
|
|
1090
1089
|
// feed = this.newsfeed(gitRemote)
|
|
1091
1090
|
// }
|
|
1092
1091
|
|
|
1093
|
-
// git
|
|
1094
|
-
|
|
1095
|
-
let c = this.kernel.path("api", name)
|
|
1096
|
-
|
|
1097
|
-
// await this.kernel.plugin.init()
|
|
1098
|
-
// let plugin = await this.getPlugin(name)
|
|
1099
|
-
// let plugin_menu = null
|
|
1100
|
-
// if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
1101
|
-
// let running_dynamic = this.running_dynamic(name, plugin.menu)
|
|
1102
|
-
// plugin_menu = plugin.menu.concat(running_dynamic)
|
|
1103
|
-
// }
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
1092
|
let current_urls = await this.current_urls(req.originalUrl.slice(1))
|
|
1107
1093
|
|
|
1108
|
-
let plugin_menu = null
|
|
1109
|
-
let plugin_config = safeStructuredClone(this.kernel.plugin.config)
|
|
1110
|
-
let plugin = await this.getPlugin(req, plugin_config, name)
|
|
1111
|
-
if (plugin && plugin.menu && Array.isArray(plugin.menu)) {
|
|
1112
|
-
plugin = safeStructuredClone(plugin)
|
|
1113
|
-
let default_plugin_query
|
|
1114
|
-
if (req.query) {
|
|
1115
|
-
default_plugin_query = req.query
|
|
1116
|
-
}
|
|
1117
|
-
plugin_menu = this.running_dynamic(name, plugin.menu, default_plugin_query)
|
|
1118
|
-
}
|
|
1119
|
-
|
|
1120
1094
|
let posix_path = Util.p2u(this.kernel.path("api", name))
|
|
1121
1095
|
let dev_link
|
|
1122
1096
|
if (posix_path.startsWith("/")) {
|
|
@@ -1187,7 +1161,7 @@ class Server {
|
|
|
1187
1161
|
current_urls,
|
|
1188
1162
|
path: this.kernel.path("api", name),
|
|
1189
1163
|
log_path: this.kernel.path("api", name, "logs"),
|
|
1190
|
-
plugin_menu:
|
|
1164
|
+
plugin_menu: null,
|
|
1191
1165
|
portal: this.portal,
|
|
1192
1166
|
install: this.install,
|
|
1193
1167
|
error: err,
|
|
@@ -4790,8 +4764,12 @@ class Server {
|
|
|
4790
4764
|
// }
|
|
4791
4765
|
}
|
|
4792
4766
|
}
|
|
4793
|
-
async terminals(filepath) {
|
|
4794
|
-
|
|
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
|
+
}
|
|
4795
4773
|
let terminal
|
|
4796
4774
|
const windowsBashPath = await this.resolveWindowsBashPath()
|
|
4797
4775
|
const hasWindowsBashOption = this.kernel.platform === "win32" && typeof windowsBashPath === "string" && windowsBashPath.length > 0
|
|
@@ -10791,7 +10769,7 @@ class Server {
|
|
|
10791
10769
|
}))
|
|
10792
10770
|
this.app.get("/d/*", ex(async (req, res) => {
|
|
10793
10771
|
let filepath = Util.u2p(req.params[0])
|
|
10794
|
-
let terminal = await this.terminals(filepath)
|
|
10772
|
+
let terminal = await this.terminals(filepath, { includeVenvs: false })
|
|
10795
10773
|
let plugin = await this.getPluginGlobal(req, this.kernel.plugin.config, terminal, filepath)
|
|
10796
10774
|
let html = ""
|
|
10797
10775
|
let plugin_menu
|
|
@@ -10934,6 +10912,7 @@ class Server {
|
|
|
10934
10912
|
install: this.install,
|
|
10935
10913
|
agent: req.agent,
|
|
10936
10914
|
theme: this.theme,
|
|
10915
|
+
terminals_url: "/pinokio/d-terminals/" + req.params[0],
|
|
10937
10916
|
//dynamic: plugin_menu
|
|
10938
10917
|
dynamic,
|
|
10939
10918
|
})
|
|
@@ -11076,6 +11055,23 @@ class Server {
|
|
|
11076
11055
|
res.send("")
|
|
11077
11056
|
}
|
|
11078
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
|
+
}))
|
|
11079
11075
|
this.app.get("/pinokio/dynamic/:name", ex(async (req, res) => {
|
|
11080
11076
|
// await this.kernel.plugin.init()
|
|
11081
11077
|
|
|
@@ -12493,7 +12489,7 @@ class Server {
|
|
|
12493
12489
|
this.socket = new Socket(this)
|
|
12494
12490
|
await new Promise((resolve, reject) => {
|
|
12495
12491
|
this.listening = this.server.listen(this.port, () => {
|
|
12496
|
-
console.log(`Server listening on
|
|
12492
|
+
console.log(`Server listening on http://localhost:${this.port}`)
|
|
12497
12493
|
this.kernel.server_running = true
|
|
12498
12494
|
resolve()
|
|
12499
12495
|
});
|
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
|
}
|
|
@@ -1105,7 +1105,9 @@
|
|
|
1105
1105
|
ui.templateManager.syncTemplateFields(ui.promptTextarea.value, defaults.templateValues || {});
|
|
1106
1106
|
|
|
1107
1107
|
requestAnimationFrame(() => {
|
|
1108
|
-
ui.promptTextarea.
|
|
1108
|
+
if (!ui.promptTextarea.value.trim()) {
|
|
1109
|
+
ui.promptTextarea.focus();
|
|
1110
|
+
}
|
|
1109
1111
|
});
|
|
1110
1112
|
|
|
1111
1113
|
return ui;
|
|
@@ -928,6 +928,21 @@ body.dark .create-launcher-page-card {
|
|
|
928
928
|
gap: 12px;
|
|
929
929
|
}
|
|
930
930
|
|
|
931
|
+
.create-launcher-page-card .create-launcher-modal-input:focus,
|
|
932
|
+
.create-launcher-page-card .create-launcher-modal-textarea:focus,
|
|
933
|
+
.create-launcher-page-card .create-launcher-modal-template-input:focus {
|
|
934
|
+
outline: none;
|
|
935
|
+
border-color: rgba(79, 70, 229, 0.7);
|
|
936
|
+
box-shadow: 0 0 0 2px rgba(79, 70, 229, 0.16);
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
body.dark .create-launcher-page-card .create-launcher-modal-input:focus,
|
|
940
|
+
body.dark .create-launcher-page-card .create-launcher-modal-textarea:focus,
|
|
941
|
+
body.dark .create-launcher-page-card .create-launcher-modal-template-input:focus {
|
|
942
|
+
border-color: rgba(129, 140, 248, 0.75);
|
|
943
|
+
box-shadow: 0 0 0 2px rgba(129, 140, 248, 0.2);
|
|
944
|
+
}
|
|
945
|
+
|
|
931
946
|
.create-launcher-page-card .create-launcher-modal-button.cancel {
|
|
932
947
|
display: none;
|
|
933
948
|
}
|
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,10 +7989,16 @@ 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
|
-
|
|
8003
|
-
|
|
8004
|
-
const try_dynamic = async () => {
|
|
8001
|
+
const try_dynamic = async (options = {}) => {
|
|
8005
8002
|
let rendered
|
|
8006
8003
|
let status
|
|
8007
8004
|
const dynamicUrl = window.__pinokioDynamicUrl || "<%-dynamic%>"
|
|
@@ -8035,18 +8032,10 @@ const rerenderMenuSection = (container, html) => {
|
|
|
8035
8032
|
rendered = false
|
|
8036
8033
|
}
|
|
8037
8034
|
if (rendered) {
|
|
8038
|
-
// if (dynamic_loaded) {
|
|
8039
|
-
// // already loaded, don't touch the UI
|
|
8040
|
-
// } else {
|
|
8041
|
-
// // first time being loaded
|
|
8042
|
-
// dynamic_loaded = true
|
|
8043
|
-
// if (document.querySelector(".dynamic .reveal")) {
|
|
8044
|
-
// console.log("click")
|
|
8045
|
-
//
|
|
8046
|
-
//// document.querySelector(".dynamic .reveal").click()
|
|
8047
|
-
// }
|
|
8048
|
-
// }
|
|
8049
8035
|
} else {
|
|
8036
|
+
if (options.retryOnEmpty === false) {
|
|
8037
|
+
return
|
|
8038
|
+
}
|
|
8050
8039
|
setTimeout(() => {
|
|
8051
8040
|
try_dynamic()
|
|
8052
8041
|
}, 1000)
|
|
@@ -8100,10 +8089,11 @@ const rerenderMenuSection = (container, html) => {
|
|
|
8100
8089
|
renderSelection()
|
|
8101
8090
|
}
|
|
8102
8091
|
}
|
|
8103
|
-
|
|
8104
|
-
|
|
8105
|
-
|
|
8106
|
-
|
|
8092
|
+
<% if (type === 'browse') { %>
|
|
8093
|
+
setTimeout(() => {
|
|
8094
|
+
try_dynamic()
|
|
8095
|
+
}, 0)
|
|
8096
|
+
<% } %>
|
|
8107
8097
|
window.addEventListener('message', (event) => {
|
|
8108
8098
|
// only process the event it's coming from pinokio
|
|
8109
8099
|
let origin = event.origin
|
|
@@ -8161,6 +8151,8 @@ const rerenderMenuSection = (container, html) => {
|
|
|
8161
8151
|
if (event.data.type === 'stream') {
|
|
8162
8152
|
const frameName = resolveFrameName(null, event.source)
|
|
8163
8153
|
updateTabTimestamp(frameName, Date.now())
|
|
8154
|
+
} else if (event.data.type === 'idle') {
|
|
8155
|
+
return
|
|
8164
8156
|
} else if (event.data.type === 'restart') {
|
|
8165
8157
|
<% if (type === 'run') { %>
|
|
8166
8158
|
clearPersistedFrameLinkSelection()
|
|
@@ -8189,8 +8181,6 @@ const rerenderMenuSection = (container, html) => {
|
|
|
8189
8181
|
|
|
8190
8182
|
|
|
8191
8183
|
});
|
|
8192
|
-
refresh_du()
|
|
8193
|
-
refresh_du("logs")
|
|
8194
8184
|
renderSelection({ force: true })
|
|
8195
8185
|
<% if (type === "browse" || type === "files") { %>
|
|
8196
8186
|
const repoStatusCache = new Map()
|
|
@@ -12411,7 +12401,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
12411
12401
|
if (!normalized) {
|
|
12412
12402
|
return false
|
|
12413
12403
|
}
|
|
12414
|
-
refreshTerminalSessions(normalized, workspaceCwd)
|
|
12415
12404
|
pickerRequestId += 1
|
|
12416
12405
|
currentUrl = normalized
|
|
12417
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({
|