pinokiod 7.3.14 → 7.4.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/index.js +111 -15
- package/kernel/api/script/index.js +10 -0
- package/kernel/autolaunch.js +111 -0
- package/kernel/environment.js +89 -1
- package/kernel/git.js +9 -19
- package/kernel/index.js +142 -43
- package/kernel/launch_requirements.js +1115 -0
- package/kernel/ready.js +231 -0
- package/kernel/script.js +16 -0
- package/kernel/shells.js +9 -1
- package/kernel/workspace_status.js +111 -45
- package/package.json +1 -1
- package/server/autolaunch.js +725 -0
- package/server/index.js +244 -411
- package/server/public/logs.js +15 -1
- package/server/public/style.css +99 -31
- package/server/views/app.ejs +263 -159
- package/server/views/autolaunch.ejs +363 -75
- package/server/views/index.ejs +550 -26
- package/server/views/logs.ejs +14 -12
- package/server/views/partials/app_autolaunch_dependency_events.ejs +99 -0
- package/server/views/partials/app_autolaunch_dependency_save.ejs +10 -0
- package/server/views/partials/app_autolaunch_dependency_styles.ejs +357 -0
- package/server/views/partials/app_autolaunch_modal_helpers.ejs +347 -0
- package/server/views/partials/autolaunch_dependency_helpers.ejs +204 -0
- package/server/views/partials/autolaunch_dependency_save.ejs +13 -0
- package/server/views/partials/autolaunch_dependency_styles.ejs +347 -0
- package/server/views/partials/home_action_modal.ejs +4 -1
- package/server/views/partials/launch_requirements_status_client.ejs +271 -0
- package/server/views/partials/launch_requirements_status_styles.ejs +171 -0
- package/server/views/partials/launch_settings_dependency_save_factory.ejs +45 -0
- package/server/views/partials/launch_settings_dependency_script_loader_factory.ejs +25 -0
- package/server/views/terminal.ejs +196 -2
- package/test/home-autolaunch-live-ui.test.js +455 -0
- package/test/launch-requirements-browser.test.js +579 -0
- package/test/launch-requirements-contract-coverage.test.js +627 -0
- package/test/launch-requirements-real-browser.js +625 -0
- package/test/launch-requirements-status-client.test.js +132 -0
- package/test/launch-requirements.test.js +1806 -0
- package/test/launch-settings-ui.test.js +370 -0
- package/test/ready-state.test.js +49 -0
- package/test/server-autolaunch.test.js +1052 -0
- package/test/startup-git-index-benchmark.js +409 -0
- package/test/startup-git-index-browser.js +320 -0
- package/test/startup-git-index-performance.test.js +380 -0
- package/test/startup-git-index-refactor.test.js +450 -0
- package/test/startup-git-index-route.test.js +588 -0
- package/test/universal-launcher.smoke.spec.js +10 -9
- package/test/workspace-gitignore-benchmark.js +815 -0
- package/test/workspace-gitignore-path-scoped.test.js +256 -0
- package/spec/INSTRUCTION_SYNC.md +0 -432
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
.launch-requirements-status {
|
|
2
|
+
position: absolute;
|
|
3
|
+
inset: 0;
|
|
4
|
+
z-index: 10001;
|
|
5
|
+
display: grid;
|
|
6
|
+
place-items: center;
|
|
7
|
+
box-sizing: border-box;
|
|
8
|
+
padding: 24px;
|
|
9
|
+
pointer-events: none;
|
|
10
|
+
color: rgba(17, 24, 39, 0.92);
|
|
11
|
+
}
|
|
12
|
+
.launch-requirements-status[hidden] {
|
|
13
|
+
display: none !important;
|
|
14
|
+
}
|
|
15
|
+
.launch-requirements-card {
|
|
16
|
+
width: min(520px, calc(100vw - 64px));
|
|
17
|
+
box-sizing: border-box;
|
|
18
|
+
padding: 0;
|
|
19
|
+
text-align: center;
|
|
20
|
+
pointer-events: auto;
|
|
21
|
+
}
|
|
22
|
+
body.dark .launch-requirements-card {
|
|
23
|
+
color: rgba(248, 250, 252, 0.92);
|
|
24
|
+
}
|
|
25
|
+
.launch-requirements-title {
|
|
26
|
+
display: flex;
|
|
27
|
+
justify-content: center;
|
|
28
|
+
align-items: center;
|
|
29
|
+
gap: 8px;
|
|
30
|
+
margin-bottom: 6px;
|
|
31
|
+
font-size: 14px;
|
|
32
|
+
font-weight: 750;
|
|
33
|
+
}
|
|
34
|
+
.launch-requirements-title i {
|
|
35
|
+
color: #2563eb;
|
|
36
|
+
}
|
|
37
|
+
.launch-requirements-detail {
|
|
38
|
+
color: rgba(100, 116, 139, 0.96);
|
|
39
|
+
font-size: 12px;
|
|
40
|
+
line-height: 1.35;
|
|
41
|
+
margin-bottom: 12px;
|
|
42
|
+
}
|
|
43
|
+
body.dark .launch-requirements-detail {
|
|
44
|
+
color: rgba(203, 213, 225, 0.86);
|
|
45
|
+
}
|
|
46
|
+
.launch-requirements-list {
|
|
47
|
+
display: grid;
|
|
48
|
+
gap: 6px;
|
|
49
|
+
margin-top: 14px;
|
|
50
|
+
text-align: left;
|
|
51
|
+
}
|
|
52
|
+
.launch-requirements-row {
|
|
53
|
+
display: grid;
|
|
54
|
+
grid-template-columns: 26px minmax(0, 1fr) auto;
|
|
55
|
+
align-items: center;
|
|
56
|
+
gap: 8px;
|
|
57
|
+
min-height: 38px;
|
|
58
|
+
padding: 6px 8px;
|
|
59
|
+
border: 1px solid rgba(148, 163, 184, 0.18);
|
|
60
|
+
border-radius: 8px;
|
|
61
|
+
background: rgba(148, 163, 184, 0.08);
|
|
62
|
+
}
|
|
63
|
+
body.dark .launch-requirements-row {
|
|
64
|
+
border-color: rgba(148, 163, 184, 0.12);
|
|
65
|
+
background: rgba(148, 163, 184, 0.07);
|
|
66
|
+
}
|
|
67
|
+
.launch-requirements-row img {
|
|
68
|
+
width: 26px;
|
|
69
|
+
height: 26px;
|
|
70
|
+
border-radius: 6px;
|
|
71
|
+
object-fit: cover;
|
|
72
|
+
}
|
|
73
|
+
.launch-requirements-name {
|
|
74
|
+
min-width: 0;
|
|
75
|
+
overflow: hidden;
|
|
76
|
+
text-overflow: ellipsis;
|
|
77
|
+
white-space: nowrap;
|
|
78
|
+
font-size: 12px;
|
|
79
|
+
font-weight: 700;
|
|
80
|
+
}
|
|
81
|
+
.launch-requirements-state {
|
|
82
|
+
display: inline-flex;
|
|
83
|
+
align-items: center;
|
|
84
|
+
justify-content: flex-end;
|
|
85
|
+
gap: 6px;
|
|
86
|
+
color: rgba(100, 116, 139, 0.96);
|
|
87
|
+
font-size: 11px;
|
|
88
|
+
white-space: nowrap;
|
|
89
|
+
}
|
|
90
|
+
.launch-requirements-choose-script {
|
|
91
|
+
appearance: none;
|
|
92
|
+
border: 1px solid rgba(148, 163, 184, 0.34);
|
|
93
|
+
border-radius: 6px;
|
|
94
|
+
background: rgba(255, 255, 255, 0.72);
|
|
95
|
+
color: rgba(30, 41, 59, 0.92);
|
|
96
|
+
display: inline-flex;
|
|
97
|
+
align-items: center;
|
|
98
|
+
justify-content: center;
|
|
99
|
+
gap: 5px;
|
|
100
|
+
min-height: 24px;
|
|
101
|
+
margin-left: 2px;
|
|
102
|
+
padding: 0 8px;
|
|
103
|
+
font: inherit;
|
|
104
|
+
font-size: 11px;
|
|
105
|
+
font-weight: 750;
|
|
106
|
+
line-height: 1;
|
|
107
|
+
cursor: pointer;
|
|
108
|
+
white-space: nowrap;
|
|
109
|
+
}
|
|
110
|
+
.launch-requirements-choose-script i {
|
|
111
|
+
color: rgba(71, 85, 105, 0.9);
|
|
112
|
+
font-size: 10px;
|
|
113
|
+
}
|
|
114
|
+
.launch-requirements-choose-script:hover {
|
|
115
|
+
border-color: rgba(100, 116, 139, 0.5);
|
|
116
|
+
background: rgba(248, 250, 252, 0.96);
|
|
117
|
+
color: rgba(15, 23, 42, 0.96);
|
|
118
|
+
}
|
|
119
|
+
.launch-requirements-choose-script:focus-visible {
|
|
120
|
+
outline: 2px solid rgba(37, 99, 235, 0.34);
|
|
121
|
+
outline-offset: 2px;
|
|
122
|
+
}
|
|
123
|
+
.launch-requirements-state.is-active i {
|
|
124
|
+
color: #2563eb;
|
|
125
|
+
}
|
|
126
|
+
.launch-requirements-state.is-ready i {
|
|
127
|
+
color: #16a34a;
|
|
128
|
+
}
|
|
129
|
+
body.dark .launch-requirements-state {
|
|
130
|
+
color: rgba(203, 213, 225, 0.82);
|
|
131
|
+
}
|
|
132
|
+
body.dark .launch-requirements-choose-script {
|
|
133
|
+
border-color: rgba(148, 163, 184, 0.22);
|
|
134
|
+
background: rgba(15, 23, 42, 0.7);
|
|
135
|
+
color: rgba(226, 232, 240, 0.92);
|
|
136
|
+
}
|
|
137
|
+
body.dark .launch-requirements-choose-script i {
|
|
138
|
+
color: rgba(203, 213, 225, 0.82);
|
|
139
|
+
}
|
|
140
|
+
body.dark .launch-requirements-choose-script:hover {
|
|
141
|
+
border-color: rgba(148, 163, 184, 0.36);
|
|
142
|
+
background: rgba(30, 41, 59, 0.78);
|
|
143
|
+
color: rgba(248, 250, 252, 0.96);
|
|
144
|
+
}
|
|
145
|
+
.launch-requirements-actions {
|
|
146
|
+
display: flex;
|
|
147
|
+
justify-content: center;
|
|
148
|
+
margin-top: 12px;
|
|
149
|
+
}
|
|
150
|
+
.launch-requirements-stop {
|
|
151
|
+
display: inline-flex;
|
|
152
|
+
align-items: center;
|
|
153
|
+
justify-content: center;
|
|
154
|
+
gap: 7px;
|
|
155
|
+
min-height: 30px;
|
|
156
|
+
padding: 0 11px;
|
|
157
|
+
border: 1px solid rgba(148, 163, 184, 0.28);
|
|
158
|
+
border-radius: 8px;
|
|
159
|
+
color: inherit;
|
|
160
|
+
background: rgba(148, 163, 184, 0.1);
|
|
161
|
+
font-size: 12px;
|
|
162
|
+
font-weight: 700;
|
|
163
|
+
cursor: pointer;
|
|
164
|
+
}
|
|
165
|
+
.launch-requirements-stop:hover {
|
|
166
|
+
background: rgba(148, 163, 184, 0.16);
|
|
167
|
+
}
|
|
168
|
+
.launch-requirements-stop:disabled {
|
|
169
|
+
cursor: default;
|
|
170
|
+
opacity: 0.65;
|
|
171
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const createLaunchSettingsDependencySaver = ({
|
|
2
|
+
getAppId,
|
|
3
|
+
isSaving,
|
|
4
|
+
setSaving,
|
|
5
|
+
setBusy,
|
|
6
|
+
setFeedback,
|
|
7
|
+
onSaved,
|
|
8
|
+
render
|
|
9
|
+
}) => async (dependencies, successMessage = "Dependencies saved.") => {
|
|
10
|
+
const appId = typeof getAppId === "function" ? getAppId() : ""
|
|
11
|
+
if (!appId || (typeof isSaving === "function" && isSaving())) return
|
|
12
|
+
if (typeof setSaving === "function") setSaving(true)
|
|
13
|
+
if (typeof setBusy === "function") setBusy(true)
|
|
14
|
+
if (typeof setFeedback === "function") setFeedback("Saving dependencies...")
|
|
15
|
+
let feedbackMessage = successMessage
|
|
16
|
+
let feedbackError = false
|
|
17
|
+
let saved = false
|
|
18
|
+
try {
|
|
19
|
+
const response = await fetch("/autolaunch/dependencies", {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: {
|
|
22
|
+
"Content-Type": "application/json",
|
|
23
|
+
"Accept": "application/json"
|
|
24
|
+
},
|
|
25
|
+
body: JSON.stringify({
|
|
26
|
+
app: appId,
|
|
27
|
+
dependencies: Array.isArray(dependencies) ? dependencies : []
|
|
28
|
+
})
|
|
29
|
+
})
|
|
30
|
+
const data = await response.json()
|
|
31
|
+
if (!response.ok || !data.ok) {
|
|
32
|
+
throw new Error(data.error || "Failed to save dependencies.")
|
|
33
|
+
}
|
|
34
|
+
if (typeof onSaved === "function") onSaved(data.app)
|
|
35
|
+
saved = true
|
|
36
|
+
} catch (error) {
|
|
37
|
+
feedbackMessage = error && error.message ? error.message : "Failed to save dependencies."
|
|
38
|
+
feedbackError = true
|
|
39
|
+
} finally {
|
|
40
|
+
if (typeof setSaving === "function") setSaving(false)
|
|
41
|
+
if (typeof render === "function") render()
|
|
42
|
+
if (typeof setFeedback === "function") setFeedback(feedbackMessage, feedbackError)
|
|
43
|
+
}
|
|
44
|
+
return saved
|
|
45
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
const createLaunchSettingsDependencyScriptLoader = ({
|
|
2
|
+
getCache,
|
|
3
|
+
render
|
|
4
|
+
}) => async (appId) => {
|
|
5
|
+
const cache = typeof getCache === "function" ? getCache() : null
|
|
6
|
+
if (!appId || !cache || cache[appId]) return
|
|
7
|
+
cache[appId] = { loading: true }
|
|
8
|
+
if (typeof render === "function") render()
|
|
9
|
+
try {
|
|
10
|
+
const response = await fetch(`/autolaunch/candidates?app=${encodeURIComponent(appId)}`, {
|
|
11
|
+
headers: { "Accept": "application/json" }
|
|
12
|
+
})
|
|
13
|
+
const data = await response.json()
|
|
14
|
+
if (!response.ok || !data.ok) {
|
|
15
|
+
throw new Error(data.error || "Failed to load script choices.")
|
|
16
|
+
}
|
|
17
|
+
cache[appId] = data
|
|
18
|
+
} catch (error) {
|
|
19
|
+
cache[appId] = {
|
|
20
|
+
error: error && error.message ? error.message : "Failed to load script choices."
|
|
21
|
+
}
|
|
22
|
+
} finally {
|
|
23
|
+
if (typeof render === "function") render()
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
<link href="/electron.css" rel="stylesheet"/>
|
|
63
63
|
<% } %>
|
|
64
64
|
<style>
|
|
65
|
+
<%- include('./partials/launch_requirements_status_styles') %>
|
|
65
66
|
html {
|
|
66
67
|
scroll-behavior: smooth;
|
|
67
68
|
height: 100%;
|
|
@@ -1491,6 +1492,83 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1491
1492
|
if (activeProcessWait && (activeProcessWait.title || activeProcessWait.description || activeProcessWait.message) && window.PinokioWaitFooterStatus) {
|
|
1492
1493
|
window.PinokioWaitFooterStatus.show(activeProcessWait)
|
|
1493
1494
|
}
|
|
1495
|
+
const resolveCurrentApiScript = () => {
|
|
1496
|
+
let parsed
|
|
1497
|
+
try {
|
|
1498
|
+
parsed = new URL(window.location.href)
|
|
1499
|
+
} catch (_) {
|
|
1500
|
+
return null
|
|
1501
|
+
}
|
|
1502
|
+
const prefix = "/api/"
|
|
1503
|
+
if (!parsed.pathname.startsWith(prefix)) {
|
|
1504
|
+
return null
|
|
1505
|
+
}
|
|
1506
|
+
const parts = parsed.pathname.slice(prefix.length).split("/").filter(Boolean).map((part) => {
|
|
1507
|
+
try {
|
|
1508
|
+
return decodeURIComponent(part)
|
|
1509
|
+
} catch (_) {
|
|
1510
|
+
return part
|
|
1511
|
+
}
|
|
1512
|
+
})
|
|
1513
|
+
if (parts.length < 2) {
|
|
1514
|
+
return null
|
|
1515
|
+
}
|
|
1516
|
+
const appId = parts[0]
|
|
1517
|
+
const script = parts.slice(1).join("/")
|
|
1518
|
+
if (!appId || !script) {
|
|
1519
|
+
return null
|
|
1520
|
+
}
|
|
1521
|
+
return {
|
|
1522
|
+
appId,
|
|
1523
|
+
script,
|
|
1524
|
+
homePath: `api/${appId}/${script}`
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
const fetchJsonNoStore = async (url) => {
|
|
1528
|
+
try {
|
|
1529
|
+
const response = await fetch(url, {
|
|
1530
|
+
cache: "no-store",
|
|
1531
|
+
headers: {
|
|
1532
|
+
"Accept": "application/json"
|
|
1533
|
+
}
|
|
1534
|
+
})
|
|
1535
|
+
if (!response.ok) {
|
|
1536
|
+
return null
|
|
1537
|
+
}
|
|
1538
|
+
return response.json().catch(() => null)
|
|
1539
|
+
} catch (_) {
|
|
1540
|
+
return null
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
const findRunningScriptEntry = (status, scriptInfo) => {
|
|
1544
|
+
const runningScripts = status && Array.isArray(status.running_scripts) ? status.running_scripts : []
|
|
1545
|
+
return runningScripts.find((entry) => {
|
|
1546
|
+
if (!entry || typeof entry !== "object") {
|
|
1547
|
+
return false
|
|
1548
|
+
}
|
|
1549
|
+
if (entry.home_path === scriptInfo.homePath) {
|
|
1550
|
+
return true
|
|
1551
|
+
}
|
|
1552
|
+
return entry.app === scriptInfo.appId && entry.script_path === scriptInfo.script
|
|
1553
|
+
}) || null
|
|
1554
|
+
}
|
|
1555
|
+
const hasLiveShellForScript = (shells, runningEntry) => {
|
|
1556
|
+
if (!runningEntry || !runningEntry.id || !Array.isArray(shells)) {
|
|
1557
|
+
return false
|
|
1558
|
+
}
|
|
1559
|
+
const scriptId = String(runningEntry.id)
|
|
1560
|
+
return shells.some((shell) => {
|
|
1561
|
+
if (!shell || shell.done === true) {
|
|
1562
|
+
return false
|
|
1563
|
+
}
|
|
1564
|
+
const group = typeof shell.group === "string" ? shell.group : ""
|
|
1565
|
+
const id = typeof shell.id === "string" ? shell.id : ""
|
|
1566
|
+
return group === scriptId || id === scriptId || id.startsWith(`${scriptId}?`)
|
|
1567
|
+
})
|
|
1568
|
+
}
|
|
1569
|
+
const normalizeLogText = (value) => {
|
|
1570
|
+
return String(value || "").replace(/\r\n/g, "\n").replace(/\r/g, "\n").replace(/\n/g, "\r\n")
|
|
1571
|
+
}
|
|
1494
1572
|
const shouldBypassAiConsent = () => {
|
|
1495
1573
|
const normalize = (value) => (typeof value === "string" ? value.replace(/\\/g, "/") : "")
|
|
1496
1574
|
const uri = normalize(scriptUri || "")
|
|
@@ -1518,6 +1596,33 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1518
1596
|
initialEnabled: initialProtectionEnabled,
|
|
1519
1597
|
runControls
|
|
1520
1598
|
})
|
|
1599
|
+
const settleLaunchRequirementsControl = (packet) => {
|
|
1600
|
+
refreshParent(packet || {})
|
|
1601
|
+
pluginTerminalDiscoveryRefresher.clear()
|
|
1602
|
+
document.querySelector("#status-window").innerHTML = "<b>Ready</b>"
|
|
1603
|
+
document.querySelector("#progress-window").classList.add("hidden")
|
|
1604
|
+
document.querySelector("#progress-bar").style.width = "0%"
|
|
1605
|
+
runControls.set("idle")
|
|
1606
|
+
if (rpc && rpc.resizeSync) {
|
|
1607
|
+
rpc.resizeSync.reset()
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
window.addEventListener("pinokio:launch-requirements-control", (event) => {
|
|
1611
|
+
settleLaunchRequirementsControl({
|
|
1612
|
+
type: "launch.requirements.control",
|
|
1613
|
+
data: event && event.detail ? event.detail : {}
|
|
1614
|
+
})
|
|
1615
|
+
})
|
|
1616
|
+
window.addEventListener("message", (event) => {
|
|
1617
|
+
const data = event && event.data ? event.data : null
|
|
1618
|
+
if (!data || data.type !== "pinokio:launch-requirements-control") {
|
|
1619
|
+
return
|
|
1620
|
+
}
|
|
1621
|
+
settleLaunchRequirementsControl({
|
|
1622
|
+
type: "launch.requirements.control",
|
|
1623
|
+
data: data.detail || {}
|
|
1624
|
+
})
|
|
1625
|
+
})
|
|
1521
1626
|
consentManager.showChipIfRemembered()
|
|
1522
1627
|
class RPC {
|
|
1523
1628
|
constructor() {
|
|
@@ -1532,6 +1637,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1532
1637
|
}
|
|
1533
1638
|
this.baseScriptId = baseScriptId
|
|
1534
1639
|
this.currentId = baseScriptId
|
|
1640
|
+
this.latestLogFallbackActive = false
|
|
1535
1641
|
this.pendingInput = []
|
|
1536
1642
|
this.inputBuffer = ""
|
|
1537
1643
|
this.inputTracker = window.TerminalInputTracker ? new window.TerminalInputTracker({
|
|
@@ -1636,6 +1742,39 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1636
1742
|
if (runId) {
|
|
1637
1743
|
params.id = runId
|
|
1638
1744
|
}
|
|
1745
|
+
if (this.latestLogFallbackActive) {
|
|
1746
|
+
let settled = false
|
|
1747
|
+
const settleFallbackStop = (packet) => {
|
|
1748
|
+
if (settled) {
|
|
1749
|
+
return
|
|
1750
|
+
}
|
|
1751
|
+
settled = true
|
|
1752
|
+
this.latestLogFallbackActive = false
|
|
1753
|
+
if (packet) {
|
|
1754
|
+
refreshParent(packet)
|
|
1755
|
+
}
|
|
1756
|
+
pluginTerminalDiscoveryRefresher.clear()
|
|
1757
|
+
document.querySelector("#status-window").innerHTML = "<b>Ready</b>"
|
|
1758
|
+
document.querySelector("#progress-window").classList.add("hidden")
|
|
1759
|
+
document.querySelector("#progress-bar").style.width = "0%"
|
|
1760
|
+
runControls.set("idle")
|
|
1761
|
+
this.resizeSync.reset()
|
|
1762
|
+
this.socket.close()
|
|
1763
|
+
}
|
|
1764
|
+
this.socket.run({
|
|
1765
|
+
method: "kernel.api.stop",
|
|
1766
|
+
params
|
|
1767
|
+
}, (packet) => {
|
|
1768
|
+
if (packet && (packet.type === "disconnect" || packet.type === "event" || packet.type === "result" || packet.type === "error")) {
|
|
1769
|
+
settleFallbackStop(packet)
|
|
1770
|
+
}
|
|
1771
|
+
}).then(() => {
|
|
1772
|
+
settleFallbackStop()
|
|
1773
|
+
}).catch(() => {
|
|
1774
|
+
settleFallbackStop()
|
|
1775
|
+
})
|
|
1776
|
+
return
|
|
1777
|
+
}
|
|
1639
1778
|
this.socket.run({
|
|
1640
1779
|
method: "kernel.api.stop",
|
|
1641
1780
|
params
|
|
@@ -1903,6 +2042,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
1903
2042
|
}
|
|
1904
2043
|
*/
|
|
1905
2044
|
runControls.set("running")
|
|
2045
|
+
} else if (packet.type === "launch.requirements.control") {
|
|
2046
|
+
settleLaunchRequirementsControl(packet)
|
|
1906
2047
|
} else if (packet.type === 'resize') {
|
|
1907
2048
|
this.resizeSync.handleResizePacket(packet)
|
|
1908
2049
|
// } else if (packet.type === "key.set") {
|
|
@@ -2242,8 +2383,57 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
2242
2383
|
// pageBottom.scrollIntoView()
|
|
2243
2384
|
})
|
|
2244
2385
|
}
|
|
2245
|
-
async
|
|
2386
|
+
async showLatestLogFallback() {
|
|
2387
|
+
try {
|
|
2388
|
+
const scriptInfo = resolveCurrentApiScript()
|
|
2389
|
+
if (!scriptInfo) {
|
|
2390
|
+
return false
|
|
2391
|
+
}
|
|
2392
|
+
const status = await fetchJsonNoStore("/pinokio/home_status")
|
|
2393
|
+
const runningEntry = findRunningScriptEntry(status, scriptInfo)
|
|
2394
|
+
if (!runningEntry) {
|
|
2395
|
+
return false
|
|
2396
|
+
}
|
|
2397
|
+
const shells = await fetchJsonNoStore("/info/shells")
|
|
2398
|
+
if (hasLiveShellForScript(shells, runningEntry)) {
|
|
2399
|
+
return false
|
|
2400
|
+
}
|
|
2401
|
+
const logUrl = `/apps/logs/${encodeURIComponent(scriptInfo.appId)}?script=${encodeURIComponent(scriptInfo.script)}&tail=400`
|
|
2402
|
+
const logData = await fetchJsonNoStore(logUrl)
|
|
2403
|
+
const text = logData && typeof logData.text === "string" ? logData.text : ""
|
|
2404
|
+
if (!text.trim()) {
|
|
2405
|
+
return false
|
|
2406
|
+
}
|
|
2407
|
+
this.currentId = runningEntry.id || this.baseScriptId || null
|
|
2408
|
+
<% if (theme === "dark") { %>
|
|
2409
|
+
await this.createTerm(xtermTheme.FrontEndDelight)
|
|
2410
|
+
<% } else { %>
|
|
2411
|
+
await this.createTerm(xtermTheme.Tomorrow)
|
|
2412
|
+
<% } %>
|
|
2413
|
+
const fileLabel = logData.file || `logs/api/${scriptInfo.script}/latest`
|
|
2414
|
+
this.write(`Latest log: ${fileLabel}\r\nNo live terminal session is available for this running script.\r\n\r\n`)
|
|
2415
|
+
this.write(normalizeLogText(text))
|
|
2416
|
+
this.write("\r\n")
|
|
2417
|
+
document.querySelector("#status-window").innerHTML = "<b>Latest log</b><div class='flexible content'>No live terminal session</div>"
|
|
2418
|
+
document.querySelector("#progress-window").classList.add("hidden")
|
|
2419
|
+
document.querySelector("#progress-bar").style.width = "0%"
|
|
2420
|
+
this.latestLogFallbackActive = true
|
|
2421
|
+
runControls.set("running")
|
|
2422
|
+
return true
|
|
2423
|
+
} catch (_) {
|
|
2424
|
+
this.latestLogFallbackActive = false
|
|
2425
|
+
return false
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
async run (mode, options = {}) {
|
|
2246
2429
|
this.mode = (mode ? mode : "run")
|
|
2430
|
+
if (options && options.allowLatestLogFallback) {
|
|
2431
|
+
const showedFallback = await this.showLatestLogFallback()
|
|
2432
|
+
if (showedFallback) {
|
|
2433
|
+
return true
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
this.latestLogFallbackActive = false
|
|
2247
2437
|
const allowed = aiConsentRequired ? await consentManager.ensureAllowed() : true
|
|
2248
2438
|
if (!allowed) {
|
|
2249
2439
|
pluginTerminalDiscoveryRefresher.clear()
|
|
@@ -3086,7 +3276,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|
|
3086
3276
|
<% } else { %>
|
|
3087
3277
|
<% if (run) { %>
|
|
3088
3278
|
// run (query params run=true)
|
|
3089
|
-
await rpc.run()
|
|
3279
|
+
await rpc.run(undefined, { allowLatestLogFallback: true })
|
|
3090
3280
|
<% } else { %>
|
|
3091
3281
|
await rpc.run("listen")
|
|
3092
3282
|
<% } %>
|
|
@@ -3280,6 +3470,7 @@ const reloadMemory = async () => {
|
|
|
3280
3470
|
</div>
|
|
3281
3471
|
<% } else { %>
|
|
3282
3472
|
<div class='terminal-container'>
|
|
3473
|
+
<div id="launch-requirements-status" class="launch-requirements-status" data-launch-requirements-status hidden aria-live="polite"></div>
|
|
3283
3474
|
<% if (memory.length > 0) { %>
|
|
3284
3475
|
<div class='memory'>
|
|
3285
3476
|
<div class='memory-header'>
|
|
@@ -3334,5 +3525,8 @@ const reloadMemory = async () => {
|
|
|
3334
3525
|
</a>
|
|
3335
3526
|
</div>
|
|
3336
3527
|
</div>
|
|
3528
|
+
<script>
|
|
3529
|
+
<%- include('partials/launch_requirements_status_client') %>
|
|
3530
|
+
</script>
|
|
3337
3531
|
</body>
|
|
3338
3532
|
</html>
|