pinokiod 3.23.0 → 3.25.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/exec/index.js +67 -0
- package/kernel/api/index.js +1 -0
- package/kernel/plugin.js +40 -10
- package/kernel/prototype.js +23 -0
- package/kernel/router/index.js +13 -0
- package/kernel/router/localhost_home_router.js +11 -0
- package/kernel/shell.js +30 -6
- package/kernel/shell_parser.js +267 -0
- package/kernel/shells.js +52 -45
- package/kernel/util.js +5 -1
- package/package.json +2 -1
- package/server/index.js +335 -136
- package/server/public/style.css +26 -1
- package/server/socket.js +13 -9
- package/server/views/app.ejs +122 -32
- package/server/views/d.ejs +284 -0
- package/server/views/env_editor.ejs +12 -0
- package/server/views/index.ejs +94 -14
- package/server/views/init/index.ejs +248 -81
- package/server/views/net.ejs +13 -8
- package/server/views/network.ejs +10 -3
- package/server/views/partials/dynamic.ejs +4 -1
- package/server/views/partials/menu.ejs +3 -0
- package/server/views/partials/running.ejs +22 -0
- package/server/views/settings.ejs +1 -1
- package/server/views/start.ejs +233 -0
|
@@ -55,8 +55,21 @@ img.appicon {
|
|
|
55
55
|
margin-bottom: 10px;
|
|
56
56
|
opacity: 0.7;
|
|
57
57
|
}
|
|
58
|
+
.explain .well {
|
|
59
|
+
margin-top: 20px;
|
|
60
|
+
background: rgba(0,0,0,0.04);
|
|
61
|
+
/*
|
|
62
|
+
border-left: 5px solid rgba(0,0,0,0.1);
|
|
63
|
+
*/
|
|
64
|
+
padding: 20px;
|
|
65
|
+
}
|
|
66
|
+
.explain ol {
|
|
67
|
+
padding-inline-start: 15px;
|
|
68
|
+
}
|
|
58
69
|
.container {
|
|
70
|
+
/*
|
|
59
71
|
max-width: 800px;
|
|
72
|
+
*/
|
|
60
73
|
/*
|
|
61
74
|
margin: 0 auto;
|
|
62
75
|
padding: 2rem;
|
|
@@ -169,9 +182,19 @@ body.dark .tab-nav {
|
|
|
169
182
|
}
|
|
170
183
|
|
|
171
184
|
*/
|
|
185
|
+
.tab-button h5 {
|
|
186
|
+
font-size: 15px;
|
|
187
|
+
width: 100%;
|
|
188
|
+
}
|
|
172
189
|
.tab-button {
|
|
190
|
+
/*
|
|
173
191
|
display: block;
|
|
174
|
-
|
|
192
|
+
*/
|
|
193
|
+
display: flex;
|
|
194
|
+
flex-direction: column;
|
|
195
|
+
width: 220px !important;
|
|
196
|
+
gap: 5px;
|
|
197
|
+
padding: 20px;
|
|
175
198
|
background: none;
|
|
176
199
|
border: none;
|
|
177
200
|
cursor: pointer;
|
|
@@ -186,9 +209,17 @@ body.dark .tab-nav {
|
|
|
186
209
|
border-bottom: 2px solid rgba(0,0,0,0.1);
|
|
187
210
|
*/
|
|
188
211
|
}
|
|
212
|
+
.tab-button .col {
|
|
213
|
+
display: block;
|
|
214
|
+
}
|
|
215
|
+
/*
|
|
216
|
+
.tab-button i {
|
|
217
|
+
padding: 5px;
|
|
218
|
+
}
|
|
219
|
+
*/
|
|
189
220
|
|
|
190
221
|
body.dark .tab-button {
|
|
191
|
-
color: rgba(255,255,255,0.
|
|
222
|
+
color: rgba(255,255,255,0.5);
|
|
192
223
|
}
|
|
193
224
|
|
|
194
225
|
.tab-button:hover {
|
|
@@ -213,6 +244,12 @@ body.dark .tab-button:hover {
|
|
|
213
244
|
|
|
214
245
|
body.dark .tab-button.active {
|
|
215
246
|
background: rgba(255,255,255,0.06);
|
|
247
|
+
color: white;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
.row {
|
|
251
|
+
display: flex;
|
|
252
|
+
align-items: center;
|
|
216
253
|
}
|
|
217
254
|
|
|
218
255
|
.tab-content {
|
|
@@ -441,9 +478,6 @@ textarea:focus, input[type="url"]:focus, input[type="text"]:focus {
|
|
|
441
478
|
|
|
442
479
|
|
|
443
480
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
481
|
.online {
|
|
448
482
|
width: 10px;
|
|
449
483
|
height: 10px;
|
|
@@ -499,7 +533,7 @@ body.dark .m {
|
|
|
499
533
|
flex-direction: column;
|
|
500
534
|
flex-grow: 1;
|
|
501
535
|
margin: 0 auto;
|
|
502
|
-
padding:
|
|
536
|
+
padding: 20px;
|
|
503
537
|
}
|
|
504
538
|
body aside {
|
|
505
539
|
/*
|
|
@@ -1106,6 +1140,61 @@ body.dark .bubble {
|
|
|
1106
1140
|
body.dark .bubble:before {
|
|
1107
1141
|
border-color: transparent rgba(0,0,0,0.4) transparent transparent;
|
|
1108
1142
|
}
|
|
1143
|
+
.ai-prompt-section {
|
|
1144
|
+
display: flex;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
.ai-tabs {
|
|
1148
|
+
display: flex;
|
|
1149
|
+
flex-direction: column;
|
|
1150
|
+
gap: 5px;
|
|
1151
|
+
margin-bottom: 10px;
|
|
1152
|
+
}
|
|
1153
|
+
.ai-tab:hover {
|
|
1154
|
+
color: royalblue;
|
|
1155
|
+
}
|
|
1156
|
+
.ai-tab {
|
|
1157
|
+
cursor: pointer;
|
|
1158
|
+
color: silver;
|
|
1159
|
+
padding: 10px 20px;
|
|
1160
|
+
font-size: 14px;
|
|
1161
|
+
width: 200px;
|
|
1162
|
+
}
|
|
1163
|
+
.ai-tab.selected {
|
|
1164
|
+
color: white;
|
|
1165
|
+
background: rgba(0,0,0,0.1);
|
|
1166
|
+
border-top-left-radius: 20px;
|
|
1167
|
+
border-bottom-left-radius: 20px;
|
|
1168
|
+
font-weight: bold;
|
|
1169
|
+
}
|
|
1170
|
+
.ai-tab-content.selected {
|
|
1171
|
+
display: flex;
|
|
1172
|
+
flex-direction: column;
|
|
1173
|
+
gap: 10px;
|
|
1174
|
+
background: rgba(0,0,0,0.1);
|
|
1175
|
+
}
|
|
1176
|
+
.ai-tab-content .ai-input {
|
|
1177
|
+
background: white !important;
|
|
1178
|
+
color: black !important;
|
|
1179
|
+
}
|
|
1180
|
+
.ai-tab-content {
|
|
1181
|
+
border-top-right-radius: 20px;
|
|
1182
|
+
border-bottom-right-radius: 20px;
|
|
1183
|
+
display: none;
|
|
1184
|
+
padding: 20px;
|
|
1185
|
+
}
|
|
1186
|
+
.ai-container {
|
|
1187
|
+
flex-grow: 1;
|
|
1188
|
+
}
|
|
1189
|
+
.ai-container h1 {
|
|
1190
|
+
padding: 0;
|
|
1191
|
+
font-weight: bold;
|
|
1192
|
+
font-size: 25px;
|
|
1193
|
+
}
|
|
1194
|
+
.md-desc {
|
|
1195
|
+
padding-left: 10px;
|
|
1196
|
+
border-left: 10px solid white;
|
|
1197
|
+
}
|
|
1109
1198
|
|
|
1110
1199
|
|
|
1111
1200
|
@media only screen and (max-width: 480px) {
|
|
@@ -1244,18 +1333,34 @@ body.dark .ace-editor {
|
|
|
1244
1333
|
-->
|
|
1245
1334
|
<div class="tab-container">
|
|
1246
1335
|
<div class="tab-nav">
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
<
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
</
|
|
1336
|
+
<button type="button" class="tab-button active" data-tab="launcher">
|
|
1337
|
+
<div class='row'>
|
|
1338
|
+
<i class="fa-solid fa-cloud-arrow-down" style="margin-right: 5px;"></i>
|
|
1339
|
+
<h5>Git Launcher</h5>
|
|
1340
|
+
</div>
|
|
1341
|
+
<div class='row'>Launch any git-based open source project</div>
|
|
1342
|
+
</button>
|
|
1343
|
+
<button type="button" class="tab-button" data-tab="cli">
|
|
1344
|
+
<div class='row'>
|
|
1345
|
+
<i class="fa-solid fa-terminal" style="margin-right: 5px;"></i>
|
|
1346
|
+
<h5>CLI App Launcher</h5>
|
|
1347
|
+
</div>
|
|
1348
|
+
<div class='row'>Run any Terminal app in the browser.</div>
|
|
1349
|
+
</button>
|
|
1350
|
+
<button type="button" class="tab-button" data-tab="project">
|
|
1351
|
+
<div class='row'>
|
|
1352
|
+
<i class="fa-regular fa-star" style="margin-right: 5px;"></i>
|
|
1353
|
+
<h5>Empty Launcher</h5>
|
|
1354
|
+
</div>
|
|
1355
|
+
<div class='row'>Start a new project with a built-in 1-click launcher.</div>
|
|
1356
|
+
</button>
|
|
1357
|
+
<button type="button" class="tab-button" data-tab="quickcreate">
|
|
1358
|
+
<div class='row'>
|
|
1359
|
+
<i class="fa-solid fa-robot" style="margin-right: 5px;"></i>
|
|
1360
|
+
<h5>AI Engineer</h5>
|
|
1361
|
+
</div>
|
|
1362
|
+
<div class='row'>Let AI build a launcher for anything.</div>
|
|
1363
|
+
</button>
|
|
1259
1364
|
</div>
|
|
1260
1365
|
|
|
1261
1366
|
<form id="bootstrap-form">
|
|
@@ -1264,16 +1369,12 @@ body.dark .ace-editor {
|
|
|
1264
1369
|
<!--
|
|
1265
1370
|
<h2>Create a 1-Click Launcher</h2>
|
|
1266
1371
|
-->
|
|
1372
|
+
<!--
|
|
1267
1373
|
<div class="header-description">
|
|
1268
1374
|
<img class='logo2' src="/pinokio-black.png"/>
|
|
1269
1375
|
<div class='bubble'>Create a launcher for any open source project via git.</div>
|
|
1270
1376
|
</div>
|
|
1271
|
-
|
|
1272
|
-
<blockquote>Name</blockquote>
|
|
1273
|
-
<div class='explain'>Enter a new folder name to create.</div>
|
|
1274
|
-
<input type="text" name="foldername-launcher" id="foldername-launcher" placeholder="folder name">
|
|
1275
|
-
</div>
|
|
1276
|
-
|
|
1377
|
+
-->
|
|
1277
1378
|
<div class="git-url-input">
|
|
1278
1379
|
<blockquote>Git URL</blockquote>
|
|
1279
1380
|
<div class='explain'>Enter a git repository URL to clone from.</div>
|
|
@@ -1358,15 +1459,12 @@ body.dark .ace-editor {
|
|
|
1358
1459
|
|
|
1359
1460
|
<!-- CLI Tab -->
|
|
1360
1461
|
<div class="tab-content" id="cli-tab">
|
|
1462
|
+
<!--
|
|
1361
1463
|
<div class="header-description">
|
|
1362
1464
|
<img class='logo2' src="/pinokio-black.png"/>
|
|
1363
1465
|
<div class='bubble'>Create a launcher for any terminal apps (npx, uvx, etc.)</div>
|
|
1364
1466
|
</div>
|
|
1365
|
-
|
|
1366
|
-
<blockquote>Name</blockquote>
|
|
1367
|
-
<div class='explain'>Enter a new folder name to create.</div>
|
|
1368
|
-
<input type="text" name="foldername-cli" id="foldername-cli" placeholder="folder name">
|
|
1369
|
-
</div>
|
|
1467
|
+
-->
|
|
1370
1468
|
<blockquote>Type</blockquote>
|
|
1371
1469
|
<div class='explain'>Single-command apps vs. Installable apps.</div>
|
|
1372
1470
|
<div class="project-options">
|
|
@@ -1413,15 +1511,12 @@ body.dark .ace-editor {
|
|
|
1413
1511
|
|
|
1414
1512
|
<!-- Project Tab -->
|
|
1415
1513
|
<div class="tab-content" id="project-tab">
|
|
1514
|
+
<!--
|
|
1416
1515
|
<div class="header-description">
|
|
1417
1516
|
<img class='logo2' src="/pinokio-black.png"/>
|
|
1418
1517
|
<div class='bubble'>Create a new project with a built-in 1-click launcher</div>
|
|
1419
1518
|
</div>
|
|
1420
|
-
|
|
1421
|
-
<blockquote>Name</blockquote>
|
|
1422
|
-
<div class='explain'>Enter a new folder name to create.</div>
|
|
1423
|
-
<input type="text" name="foldername-new" id="foldername-new" placeholder="folder name">
|
|
1424
|
-
</div>
|
|
1519
|
+
-->
|
|
1425
1520
|
<blockquote>Type</blockquote>
|
|
1426
1521
|
<div class='explain'>Set up a new 1-click launcher project.</div>
|
|
1427
1522
|
<div class="project-options">
|
|
@@ -1499,18 +1594,47 @@ body.dark .ace-editor {
|
|
|
1499
1594
|
|
|
1500
1595
|
</div>
|
|
1501
1596
|
|
|
1502
|
-
<!--
|
|
1503
|
-
<div class="
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1597
|
+
<!-- Quick Create Tab -->
|
|
1598
|
+
<div class="tab-content" id="quickcreate-tab">
|
|
1599
|
+
<div class="ai-prompt-section">
|
|
1600
|
+
<div class='ai-tabs'>
|
|
1601
|
+
<% ai.forEach((item, i) => { %>
|
|
1602
|
+
<div data-title="<%=item.title%>" class='ai-tab <%=i===0 ? "selected" : ""%>'><%=item.title%></div>
|
|
1603
|
+
<% }) %>
|
|
1604
|
+
</div>
|
|
1605
|
+
<div class='ai-container'>
|
|
1606
|
+
<% ai.forEach((item, i) => { %>
|
|
1607
|
+
<div class='ai-tab-content <%=i===0 ? "selected" : ""%>' data-title="<%=item.title%>">
|
|
1608
|
+
<h1><%=item.title%></h1>
|
|
1609
|
+
<div class='md-desc'><%=item.description%></div>
|
|
1610
|
+
<% Object.keys(item.meta).forEach((key) => { %>
|
|
1611
|
+
<input class='ai-input' type='text' placeholder='<%=item.meta[key]%>' name='<%=key%>'>
|
|
1612
|
+
<% }) %>
|
|
1613
|
+
<textarea><%=item.content%></textarea>
|
|
1614
|
+
<pre class='hidden'><%=item.content%></pre>
|
|
1615
|
+
</div>
|
|
1616
|
+
<% }) %>
|
|
1617
|
+
</div>
|
|
1510
1618
|
<!--
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1619
|
+
<blockquote>What do you want to build?</blockquote>
|
|
1620
|
+
-->
|
|
1621
|
+
<textarea class='hidden' id='aiPrompt' data-name="aiPrompt" data-placeholder="Describe what you want to build..." placeholder="What do you want to build?"></textarea>
|
|
1622
|
+
<!--
|
|
1623
|
+
<div id="aiPrompt" class="ace-editor" data-name="aiPrompt" data-placeholder="Describe what you want to build..." style="height: 150px;"></div>
|
|
1624
|
+
-->
|
|
1625
|
+
|
|
1626
|
+
<!--
|
|
1627
|
+
<div class='explain'>
|
|
1628
|
+
<div class='well'>
|
|
1629
|
+
<ol>
|
|
1630
|
+
<li>Describe what the project should do, and click "create".</li>
|
|
1631
|
+
<li>This will be saved inside README.md.</li>
|
|
1632
|
+
<li>AI coding tools will automatically read the README.md file to figure out what to build. You just need to tell them to "build".</li>
|
|
1633
|
+
</ol>
|
|
1634
|
+
</div>
|
|
1635
|
+
</div>
|
|
1636
|
+
-->
|
|
1637
|
+
</div>
|
|
1514
1638
|
</div>
|
|
1515
1639
|
|
|
1516
1640
|
<div class="button-group" style="margin-top: 2rem;">
|
|
@@ -1523,9 +1647,48 @@ body.dark .ace-editor {
|
|
|
1523
1647
|
</div>
|
|
1524
1648
|
</main>
|
|
1525
1649
|
<script>
|
|
1650
|
+
const resizeAITextarea = () => {
|
|
1651
|
+
let textarea = document.querySelector(".ai-container .ai-tab-content.selected textarea")
|
|
1652
|
+
textarea.style.height = "";
|
|
1653
|
+
textarea.style.height = textarea.scrollHeight + "px";
|
|
1654
|
+
}
|
|
1526
1655
|
document.addEventListener('DOMContentLoaded', function() {
|
|
1527
1656
|
// Initialize tabs
|
|
1528
1657
|
initializeTabs();
|
|
1658
|
+
|
|
1659
|
+
document.querySelector(".ai-tabs").addEventListener("click", (e) => {
|
|
1660
|
+
document.querySelectorAll(".ai-tab").forEach((el) => {
|
|
1661
|
+
el.classList.remove('selected')
|
|
1662
|
+
})
|
|
1663
|
+
e.target.classList.add("selected")
|
|
1664
|
+
document.querySelectorAll(`.ai-tab-content`).forEach((el) => {
|
|
1665
|
+
el.classList.remove("selected")
|
|
1666
|
+
})
|
|
1667
|
+
let title = e.target.getAttribute("data-title")
|
|
1668
|
+
document.querySelector(`.ai-tab-content[data-title="${title}"]`).classList.add('selected')
|
|
1669
|
+
resizeAITextarea()
|
|
1670
|
+
})
|
|
1671
|
+
document.querySelectorAll(".ai-tab-content").forEach((tab) => {
|
|
1672
|
+
tab.addEventListener("input", (e) => {
|
|
1673
|
+
if (e.target.classList.contains("ai-input")) {
|
|
1674
|
+
let name = e.target.name
|
|
1675
|
+
// get all values from all ai-input and replace
|
|
1676
|
+
let els = e.target.closest(".ai-tab-content").querySelectorAll(".ai-input")
|
|
1677
|
+
let vals = {}
|
|
1678
|
+
let pre = e.target.closest(".ai-tab-content").querySelector("pre")
|
|
1679
|
+
let textarea = e.target.closest(".ai-tab-content").querySelector("textarea")
|
|
1680
|
+
resizeAITextarea()
|
|
1681
|
+
let md = pre.textContent
|
|
1682
|
+
for(let el of els) {
|
|
1683
|
+
let pattern = `{{${el.name}}}`
|
|
1684
|
+
md = md.replaceAll(pattern, el.value)
|
|
1685
|
+
}
|
|
1686
|
+
textarea.value = md
|
|
1687
|
+
document.querySelector("#aiPrompt").value = md
|
|
1688
|
+
}
|
|
1689
|
+
})
|
|
1690
|
+
})
|
|
1691
|
+
|
|
1529
1692
|
|
|
1530
1693
|
// Show launcher tab by default
|
|
1531
1694
|
showTab('launcher');
|
|
@@ -1680,6 +1843,11 @@ function showTab(tabName) {
|
|
|
1680
1843
|
if (tabName !== 'cli') {
|
|
1681
1844
|
clearCliInputs();
|
|
1682
1845
|
}
|
|
1846
|
+
|
|
1847
|
+
if (tabName === "quickcreate") {
|
|
1848
|
+
resizeAITextarea()
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1683
1851
|
}
|
|
1684
1852
|
|
|
1685
1853
|
function hideAllConditionalOptions() {
|
|
@@ -1878,7 +2046,8 @@ function validateForm() {
|
|
|
1878
2046
|
const activeTab = document.querySelector('.tab-content.active').id;
|
|
1879
2047
|
const isLauncher = activeTab === 'launcher-tab';
|
|
1880
2048
|
const isCli = activeTab === 'cli-tab';
|
|
1881
|
-
|
|
2049
|
+
const isQuickCreate = activeTab === 'quickcreate-tab';
|
|
2050
|
+
const gitUrl = document.getElementById('gitUrl').value.trim();
|
|
1882
2051
|
|
|
1883
2052
|
// Validate Git URL for launcher tab
|
|
1884
2053
|
if (isLauncher) {
|
|
@@ -1887,15 +2056,6 @@ function validateForm() {
|
|
|
1887
2056
|
alert('Please enter a Git repository URL.');
|
|
1888
2057
|
return false;
|
|
1889
2058
|
}
|
|
1890
|
-
const name = document.getElementById('foldername-launcher').value.trim();
|
|
1891
|
-
if (!name) {
|
|
1892
|
-
alert('Please enter a folder name.');
|
|
1893
|
-
return false;
|
|
1894
|
-
}
|
|
1895
|
-
if (name.includes(" ")) {
|
|
1896
|
-
alert('No spaces allowed');
|
|
1897
|
-
return false;
|
|
1898
|
-
}
|
|
1899
2059
|
|
|
1900
2060
|
const projectType = document.querySelector('input[name="projectType"]:checked');
|
|
1901
2061
|
if (!projectType) {
|
|
@@ -1911,16 +2071,6 @@ function validateForm() {
|
|
|
1911
2071
|
alert('Please select a CLI type.');
|
|
1912
2072
|
return false;
|
|
1913
2073
|
}
|
|
1914
|
-
|
|
1915
|
-
const name = document.getElementById('foldername-cli').value.trim();
|
|
1916
|
-
if (!name) {
|
|
1917
|
-
alert('Please enter a folder name.');
|
|
1918
|
-
return false;
|
|
1919
|
-
}
|
|
1920
|
-
if (name.includes(" ")) {
|
|
1921
|
-
alert('No spaces allowed');
|
|
1922
|
-
return false;
|
|
1923
|
-
}
|
|
1924
2074
|
|
|
1925
2075
|
if (cliType.value === 'instant') {
|
|
1926
2076
|
const launchCommand = document.querySelector('input[name="launchCommand"]').value.trim();
|
|
@@ -1942,23 +2092,18 @@ function validateForm() {
|
|
|
1942
2092
|
}
|
|
1943
2093
|
}
|
|
1944
2094
|
|
|
2095
|
+
// Validate quick create tab
|
|
2096
|
+
if (isQuickCreate) {
|
|
2097
|
+
// No additional validation needed for quick create
|
|
2098
|
+
}
|
|
2099
|
+
|
|
1945
2100
|
// Validate project tab
|
|
1946
|
-
if (!isLauncher && !isCli) {
|
|
2101
|
+
if (!isLauncher && !isCli && !isQuickCreate) {
|
|
1947
2102
|
const projectType = document.querySelector('input[name="projectType"]:checked');
|
|
1948
2103
|
if (!projectType) {
|
|
1949
2104
|
alert('Please select a project type.');
|
|
1950
2105
|
return false;
|
|
1951
2106
|
}
|
|
1952
|
-
|
|
1953
|
-
const name = document.getElementById('foldername-new').value.trim();
|
|
1954
|
-
if (!name) {
|
|
1955
|
-
alert('Please enter a folder name.');
|
|
1956
|
-
return false;
|
|
1957
|
-
}
|
|
1958
|
-
if (name.includes(" ")) {
|
|
1959
|
-
alert('No spaces allowed');
|
|
1960
|
-
return false;
|
|
1961
|
-
}
|
|
1962
2107
|
|
|
1963
2108
|
// Validate Documentation options
|
|
1964
2109
|
if (projectType.value === 'documentation') {
|
|
@@ -1994,10 +2139,28 @@ function handleSubmit(event) {
|
|
|
1994
2139
|
return;
|
|
1995
2140
|
}
|
|
1996
2141
|
|
|
2142
|
+
// Prompt for folder name
|
|
2143
|
+
let name = prompt('Enter a folder name to create:');
|
|
2144
|
+
if (!name) {
|
|
2145
|
+
return; // User cancelled or entered empty name
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
name = name.trim();
|
|
2149
|
+
if (!name) {
|
|
2150
|
+
alert('Please enter a valid folder name.');
|
|
2151
|
+
return;
|
|
2152
|
+
}
|
|
2153
|
+
|
|
2154
|
+
if (name.includes(' ')) {
|
|
2155
|
+
alert('No spaces allowed in folder names.');
|
|
2156
|
+
return;
|
|
2157
|
+
}
|
|
2158
|
+
|
|
1997
2159
|
const formData = new FormData(event.target);
|
|
1998
2160
|
const activeTab = document.querySelector('.tab-content.active').id;
|
|
1999
2161
|
const isLauncher = activeTab === 'launcher-tab';
|
|
2000
2162
|
const isCli = activeTab === 'cli-tab';
|
|
2163
|
+
const isQuickCreate = activeTab === 'quickcreate-tab';
|
|
2001
2164
|
const gitUrl = isLauncher ? formData.get('gitUrl').trim() : '';
|
|
2002
2165
|
|
|
2003
2166
|
// Get values from Ace editors and clean them
|
|
@@ -2005,22 +2168,26 @@ function handleSubmit(event) {
|
|
|
2005
2168
|
const cloneStartCommandText = aceEditors['cloneStartCommand'] ? aceEditors['cloneStartCommand'].getValue().trim() : '';
|
|
2006
2169
|
const installCommandText = aceEditors['installCommand'] ? aceEditors['installCommand'].getValue().trim() : '';
|
|
2007
2170
|
const installableLaunchCommandText = aceEditors['installableLaunchCommand'] ? aceEditors['installableLaunchCommand'].getValue().trim() : '';
|
|
2008
|
-
|
|
2171
|
+
|
|
2172
|
+
// Only get AI prompt text if Quick Create tab is active
|
|
2173
|
+
// const aiPromptText = isQuickCreate && aceEditors['aiPrompt'] ? aceEditors['aiPrompt'].getValue().trim() : '';
|
|
2174
|
+
const aiPromptText = isQuickCreate && document.querySelector("#aiPrompt") ? document.querySelector("#aiPrompt").value.trim() : '';
|
|
2009
2175
|
|
|
2010
2176
|
// Set startType and projectType based on active tab
|
|
2011
|
-
let startType, projectType
|
|
2177
|
+
let startType, projectType;
|
|
2012
2178
|
if (isLauncher) {
|
|
2013
2179
|
startType = 'clone';
|
|
2014
2180
|
projectType = formData.get('projectType');
|
|
2015
|
-
name = formData.get("foldername-launcher").trim();
|
|
2016
2181
|
} else if (isCli) {
|
|
2017
2182
|
startType = 'new';
|
|
2018
2183
|
projectType = 'cli';
|
|
2019
|
-
|
|
2184
|
+
} else if (isQuickCreate) {
|
|
2185
|
+
startType = 'new';
|
|
2186
|
+
//projectType = 'empty';
|
|
2187
|
+
projectType = 'ai';
|
|
2020
2188
|
} else {
|
|
2021
2189
|
startType = 'new';
|
|
2022
2190
|
projectType = formData.get('projectType');
|
|
2023
|
-
name = formData.get("foldername-new").trim();
|
|
2024
2191
|
}
|
|
2025
2192
|
|
|
2026
2193
|
// For CLI category, map the projectType to cliType for backwards compatibility
|
package/server/views/net.ejs
CHANGED
|
@@ -430,16 +430,13 @@ body.dark .net {
|
|
|
430
430
|
</div>
|
|
431
431
|
</h1>
|
|
432
432
|
</header>
|
|
433
|
-
<form class='search'>
|
|
434
|
-
<div class='app-btns'>
|
|
435
|
-
<a class='btn create-new' href="/init"><i class="fa-solid fa-plus"></i> Build</a>
|
|
436
|
-
<a class='btn' id='explore' href="/?mode=explore"><i class="fa-solid fa-magnifying-glass"></i> Discover</a>
|
|
437
|
-
</div>
|
|
438
|
-
<input type='search' class="flexible" placeholder='Filter network apps'>
|
|
439
|
-
</form>
|
|
440
433
|
<main>
|
|
441
434
|
<div id='terminal' class='hidden'></div>
|
|
442
435
|
<aside>
|
|
436
|
+
<div class='btn-tab'>
|
|
437
|
+
<a href="/init" class='btn'><i class="fa-solid fa-plus"></i> Create</a>
|
|
438
|
+
<a class='btn' id='explore' href="/?mode=explore"><i class="fa-solid fa-globe"></i> Discover</a>
|
|
439
|
+
</div>
|
|
443
440
|
<a href="/" class='tab'><i class='fas fa-laptop-code'></i> Local</a>
|
|
444
441
|
<a href="/network" class='tab'><i class="fa-solid fa-wifi"></i> Network</a>
|
|
445
442
|
<% if (list.length > 0) { %>
|
|
@@ -452,9 +449,17 @@ body.dark .net {
|
|
|
452
449
|
<% } %>
|
|
453
450
|
<% }) %>
|
|
454
451
|
<% } %>
|
|
455
|
-
<div class='tab'><i class="fa-solid fa-code"></i> Dev</div>
|
|
456
452
|
</aside>
|
|
457
453
|
<div class='container'>
|
|
454
|
+
<form class='search'>
|
|
455
|
+
<!--
|
|
456
|
+
<div class='app-btns'>
|
|
457
|
+
<a class='btn create-new' href="/init"><i class="fa-solid fa-plus"></i> Build</a>
|
|
458
|
+
<a class='btn' id='explore' href="/?mode=explore"><i class="fa-solid fa-magnifying-glass"></i> Discover</a>
|
|
459
|
+
</div>
|
|
460
|
+
-->
|
|
461
|
+
<input type='search' class="flexible" placeholder='Search apps'>
|
|
462
|
+
</form>
|
|
458
463
|
<div class='running-apps'>
|
|
459
464
|
<% if (current_host === host) { %>
|
|
460
465
|
<div class='section-header'>
|
package/server/views/network.ejs
CHANGED
|
@@ -131,8 +131,10 @@ a.badge {
|
|
|
131
131
|
text-decoration: none;
|
|
132
132
|
}
|
|
133
133
|
body.dark .btn {
|
|
134
|
-
|
|
134
|
+
background: rgba(255,255,255,0.05) !important;
|
|
135
|
+
/*
|
|
135
136
|
border: 1px solid rgba(255,255,255,0.3);
|
|
137
|
+
*/
|
|
136
138
|
}
|
|
137
139
|
body.dark .badge {
|
|
138
140
|
background: rgba(255,255,255,0.1);
|
|
@@ -278,7 +280,7 @@ body.dark .config {
|
|
|
278
280
|
background: rgba(0,0,0,0.9);
|
|
279
281
|
*/
|
|
280
282
|
color: black;
|
|
281
|
-
padding:
|
|
283
|
+
padding: 50px 50px 0;
|
|
282
284
|
text-align: left;
|
|
283
285
|
}
|
|
284
286
|
.config-header {
|
|
@@ -565,6 +567,7 @@ input[type=search] {
|
|
|
565
567
|
</div>
|
|
566
568
|
</h1>
|
|
567
569
|
</header>
|
|
570
|
+
<!--
|
|
568
571
|
<form class='search'>
|
|
569
572
|
<div class='app-btns'>
|
|
570
573
|
<a class='btn create-new' href="/init"><i class="fa-solid fa-plus"></i> Build</a>
|
|
@@ -572,8 +575,13 @@ input[type=search] {
|
|
|
572
575
|
</div>
|
|
573
576
|
<input type='search' class="flexible" placeholder='Filter network apps'>
|
|
574
577
|
</form>
|
|
578
|
+
-->
|
|
575
579
|
<main>
|
|
576
580
|
<aside>
|
|
581
|
+
<div class='btn-tab'>
|
|
582
|
+
<a href="/init" class='btn'><i class="fa-solid fa-plus"></i> Create</a>
|
|
583
|
+
<a class='btn' id='explore' href="/?mode=explore"><i class="fa-solid fa-globe"></i> Discover</a>
|
|
584
|
+
</div>
|
|
577
585
|
<a href="/" class='tab'><i class='fas fa-laptop-code'></i> Local</a>
|
|
578
586
|
<a href="/network" class='tab selected'><i class="fa-solid fa-wifi"></i> Network</a>
|
|
579
587
|
<% if (list.length > 0) { %>
|
|
@@ -582,7 +590,6 @@ input[type=search] {
|
|
|
582
590
|
<a href="/net/<%=name%>" class='submenu tab'><i class="fa-brands fa-<%=brands[platform]%>"></i> <%=name%> (<%=current_host === host ? 'this machine' : host%>)</a>
|
|
583
591
|
<% }) %>
|
|
584
592
|
<% } %>
|
|
585
|
-
<div class='tab'><i class="fa-solid fa-code"></i> Dev</div>
|
|
586
593
|
</aside>
|
|
587
594
|
<div class='container'>
|
|
588
595
|
<div class='config'>
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
<div <%=item.default ? 'data-default' : ''%> data-action="<%=JSON.stringify(item.action)%>" class='btn header-item frame-link <%=item.display || ""%>'>
|
|
16
16
|
<div class='tab'><%-item.btn%></div>
|
|
17
17
|
</div>
|
|
18
|
-
<% } else if (item.run) { %>
|
|
18
|
+
<% } else if (item.run && typeof item.run === 'string') { %>
|
|
19
19
|
<div data-run="<%=item.run%>" data-cwd="<%=item.cwd%>" class='btn header-item frame-link <%=item.display || ""%>'>
|
|
20
20
|
<div class='tab'><%-item.btn%></div>
|
|
21
21
|
</div>
|
|
@@ -36,6 +36,9 @@
|
|
|
36
36
|
</a>
|
|
37
37
|
<% } else { %>
|
|
38
38
|
<a <%=item.default ? 'data-default' : ''%> data-confirm="<%=item.confirm%>" data-index="<%=index+4%>" target="<%=item.target%>" data-mode="<%=item.mode%>" href="<%=item.href%>" class='btn header-item frame-link <%=item.display || ""%>' <%=item.shell_id ? `data-shell=${item.shell_id}` : ""%> <%=item.script_id ? `data-script=${item.script_id}` : ''%>>
|
|
39
|
+
<% if (item.running) { %>
|
|
40
|
+
<i class="fa-solid fa-circle"></i>
|
|
41
|
+
<% } %>
|
|
39
42
|
<div class='tab'><%-item.btn%></div>
|
|
40
43
|
<% if (item.running) { %>
|
|
41
44
|
<% if (item.online) { %>
|
|
@@ -51,6 +51,9 @@
|
|
|
51
51
|
</a>
|
|
52
52
|
<% } else { %>
|
|
53
53
|
<a <%=item.default ? 'data-default' : ''%> data-confirm="<%=item.confirm%>" data-index="<%=index%>" target="<%=item.target%>" data-mode="<%=item.mode%>" href="<%=item.href%>" class='btn header-item frame-link <%=item.display || ""%>' <%=item.shell_id ? `data-shell=${item.shell_id}` : ""%> <%=item.script_id ? `data-script=${item.script_id}` : ''%>>
|
|
54
|
+
<% if (item.running) { %>
|
|
55
|
+
<i class="fa-solid fa-circle"></i>
|
|
56
|
+
<% } %>
|
|
54
57
|
<div class='tab'><%-item.btn%></div>
|
|
55
58
|
<% if (item.running) { %>
|
|
56
59
|
<!--
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<% dynamic.forEach((item, index) => { %>
|
|
2
|
+
<a <%=item.default ? 'data-default' : ''%> data-confirm="<%=item.confirm%>" data-index="<%=index+4%>" target="<%=item.target%>" data-mode="<%=item.mode%>" href="<%=item.href%>" class='btn header-item frame-link <%=item.display || ""%>' <%=item.shell_id ? `data-shell=${item.shell_id}` : ""%> <%=item.script_id ? `data-script=${item.script_id}` : ''%>>
|
|
3
|
+
<% if (item.running) { %>
|
|
4
|
+
<i class="fa-solid fa-circle"></i>
|
|
5
|
+
<% } %>
|
|
6
|
+
<div class='tab'><%-item.btn%></div>
|
|
7
|
+
<% if (item.running) { %>
|
|
8
|
+
<% if (item.online) { %>
|
|
9
|
+
<div class='loader shutdown online'>
|
|
10
|
+
</div>
|
|
11
|
+
<% } else { %>
|
|
12
|
+
<div class='loader shutdown'>
|
|
13
|
+
<button class='btn'>
|
|
14
|
+
<i class="fa-solid fa-square"></i> Stop
|
|
15
|
+
</button>
|
|
16
|
+
</div>
|
|
17
|
+
<% } %>
|
|
18
|
+
<% } else { %>
|
|
19
|
+
<i class="fa-solid fa-angle-right"></i>
|
|
20
|
+
<% } %>
|
|
21
|
+
</a>
|
|
22
|
+
<% }) %>
|
|
@@ -417,7 +417,7 @@ body.dark .keys pre {
|
|
|
417
417
|
<div>Keys are array values stored for unique host names, stored at <code>~/pinokio/key.json</code>, and can be set through <code>pre</code> attributes in pinokio scripts. Here's an example:</div>
|
|
418
418
|
<pre>{
|
|
419
419
|
"openai.com": [
|
|
420
|
-
"
|
|
420
|
+
"12345678-FAKEaccesstoken1234567890abcdef"
|
|
421
421
|
],
|
|
422
422
|
"x.com": [
|
|
423
423
|
"12345678-FAKEaccesstoken1234567890abcdef",
|