pinokiod 3.20.2 → 3.20.4

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.
@@ -22,18 +22,43 @@
22
22
  padding: 0;
23
23
  box-sizing: border-box;
24
24
  }
25
+ #create-button {
26
+ width: 100%;
27
+ background: royalblue;
28
+ font-size: 16px;
29
+ font-weight: bold;
30
+ border: none;
31
+ }
32
+ #bootstrap-form {
33
+ padding: 20px;
34
+ flex-grow: 1;
35
+ background: rgba(0,0,100,0.04);
36
+ border-top-right-radius: 20px;
37
+ border-bottom-right-radius: 20px;
38
+ border-bottom-left-radius: 20px;
39
+
40
+ }
41
+ body.dark #bootstrap-form {
42
+ background: rgba(255,255,255,0.06);
43
+ }
25
44
  img.appicon {
26
- width: 40px;
27
- height: 40px;
28
- margin-right: 5px;
45
+ width: 30px;
46
+ height: 30px;
29
47
  padding: 5px;
30
48
  border-radius: 4px;
31
49
  background: white;
32
50
  }
51
+ .explain {
52
+ margin-bottom: 10px;
53
+ opacity: 0.7;
54
+ }
33
55
  .container {
34
56
  max-width: 800px;
57
+ /*
35
58
  margin: 0 auto;
36
59
  padding: 2rem;
60
+ */
61
+
37
62
  }
38
63
  img.logo2 {
39
64
  height: 50px;
@@ -58,17 +83,23 @@ h2 {
58
83
  h1 {
59
84
  letter-spacing: 0px;
60
85
  font-size:40px;
61
- text-align: center;
62
86
  text-transform: uppercase;
87
+ padding-bottom: 20px;
63
88
  }
64
89
 
65
90
  body.dark blockquote {
66
- border-left: 10px solid rgba(255,255,255,0.1);
91
+ border-left: 10px solid white;
67
92
  }
68
93
  blockquote {
69
- padding: 10px;
70
- border-left: 10px solid rgba(0, 0, 0, 0.05);
71
- margin: 10px 0;
94
+ text-transform: uppercase;
95
+ /*
96
+ */
97
+
98
+ padding-left: 5px;
99
+ border-left: 10px solid black;
100
+ font-size: 16px;
101
+ margin-bottom: 5px;
102
+ font-weight: bold;
72
103
  }
73
104
 
74
105
  .progress-bar {
@@ -112,7 +143,81 @@ body.dark .progress-bar .step.active {
112
143
  }
113
144
 
114
145
  .step-content h2 {
115
- margin-bottom: 1.5rem;
146
+ margin-bottom: 10px;
147
+ }
148
+
149
+ /* Tab Styles */
150
+ .tab-container {
151
+ display: flex;
152
+ }
153
+
154
+ .tab-nav {
155
+ flex-shrink: 0;
156
+ /*
157
+ display: flex;
158
+ border-bottom: 2px solid rgba(0,0,0,0.1);
159
+ margin: 0 0 30px 0;
160
+ */
161
+ }
162
+
163
+ /*
164
+ body.dark .tab-nav {
165
+ border-bottom: 2px solid rgba(255,255,255,0.1);
166
+ }
167
+
168
+ */
169
+ .tab-button {
170
+ display: block;
171
+ padding: 10px 20px;
172
+ background: none;
173
+ border: none;
174
+ cursor: pointer;
175
+ font-size: 14px;
176
+ font-weight: 500;
177
+ color: rgba(0,0,0,0.6);
178
+ transition: all 0.3s ease;
179
+ width: 100%;
180
+ text-align: left;
181
+ /*
182
+
183
+ border-bottom: 2px solid rgba(0,0,0,0.1);
184
+ */
185
+ }
186
+
187
+ body.dark .tab-button {
188
+ color: rgba(255,255,255,0.6);
189
+ }
190
+
191
+ .tab-button:hover {
192
+ color: rgba(0,0,0,0.8);
193
+ background: rgba(0,0,0,0.02);
194
+ }
195
+
196
+ body.dark .tab-button:hover {
197
+ color: rgba(255,255,255,0.8);
198
+ background: rgba(255,255,255,0.02);
199
+ }
200
+
201
+ .tab-button.active {
202
+ color: #000;
203
+ background: rgba(0,0,100,0.04);
204
+ border-top-left-radius: 20px;
205
+ border-bottom-left-radius: 20px;
206
+ /*
207
+ background: rgba(0,0,0,0.02);
208
+ */
209
+ }
210
+
211
+ body.dark .tab-button.active {
212
+ background: rgba(255,255,255,0.06);
213
+ }
214
+
215
+ .tab-content {
216
+ display: none;
217
+ }
218
+
219
+ .tab-content.active {
220
+ display: block;
116
221
  }
117
222
 
118
223
  /*
@@ -121,14 +226,19 @@ body.dark .progress-bar .step.active {
121
226
  }
122
227
  */
123
228
 
229
+ /*
124
230
  body.dark .radio-group label {
125
231
  background: rgba(0,0,0,0.3);
126
232
  }
233
+ */
234
+ body.dark .radio-group label {
235
+ background: rgba(0,0,0,0.2);
236
+ }
127
237
  .radio-group label {
128
- background: rgba(0,0,0,0.03);
238
+ border-radius: 2px;
239
+ background: white;
129
240
  display: flex;
130
241
  align-items: center;
131
- margin-bottom: 5px;
132
242
  padding: 10px;
133
243
  cursor: pointer;
134
244
  transition: all 0.3s ease;
@@ -145,7 +255,7 @@ body.dark .radio-group label {
145
255
  }
146
256
 
147
257
  .radio-group label span {
148
- font-size: 16px;
258
+ font-size: 14px;
149
259
  /*
150
260
  font-weight: lighter;
151
261
  */
@@ -246,15 +356,10 @@ body.dark .conditional-options {
246
356
  }
247
357
  */
248
358
 
249
- .project-options {
250
- display: none;
251
- }
252
-
253
- .project-options.show {
254
- display: block;
255
- }
256
359
 
257
360
  body.dark textarea, body.dark input[type="url"], body.dark input[type="text"] {
361
+ background: rgba(255, 255, 255, 0.1);
362
+ color: white;
258
363
  }
259
364
  textarea, input[type="url"], input[type="text"] {
260
365
  width: 100%;
@@ -390,6 +495,8 @@ body.dark .m {
390
495
  display: flex;
391
496
  flex-direction: column;
392
497
  flex-grow: 1;
498
+ margin: 0 auto;
499
+ padding: 50px 0;
393
500
  }
394
501
  body aside {
395
502
  /*
@@ -414,6 +521,7 @@ main {
414
521
  flex-grow: 1;
415
522
  min-height: 0;
416
523
  /*
524
+ background: rgba(0,0,100,0.04);
417
525
  height: 100%;
418
526
  */
419
527
  }
@@ -943,7 +1051,6 @@ body.dark .submenu {
943
1051
  font-size: 16px !important;
944
1052
  }
945
1053
 
946
-
947
1054
  .custom-label {
948
1055
  position: absolute;
949
1056
  top: 0;
@@ -967,6 +1074,36 @@ body.dark .submenu {
967
1074
  body.dark .appcanvas {
968
1075
  border-top: 1px solid rgba(255,255,255,0.04);
969
1076
  }
1077
+ .bubble {
1078
+ position: relative;
1079
+ background: rgba(0,0,0,0.1);
1080
+ color: #333;
1081
+ border-radius: 10px;
1082
+ padding: 10px 15px;
1083
+ font-size: 14px;
1084
+ flex-grow: 1;
1085
+ line-height: 1.4;
1086
+ margin: 0 10px;
1087
+ font-weight: bold;
1088
+ }
1089
+ /* Left-side tail */
1090
+ .bubble::before {
1091
+ content: "";
1092
+ position: absolute;
1093
+ top: 10px; /* Vertical alignment of the tail */
1094
+ left: -20px; /* Positioning outside the bubble */
1095
+ border-width: 10px;
1096
+ border-style: solid;
1097
+ border-color: transparent rgba(0,0,0,0.1) transparent transparent;
1098
+ }
1099
+ body.dark .bubble {
1100
+ background: rgba(0,0,0,0.4);
1101
+ color: white;
1102
+ }
1103
+ body.dark .bubble:before {
1104
+ border-color: transparent rgba(0,0,0,0.4) transparent transparent;
1105
+ }
1106
+
970
1107
 
971
1108
  @media only screen and (max-width: 480px) {
972
1109
  nav .btn2 {
@@ -1027,6 +1164,15 @@ body.dark .appcanvas {
1027
1164
  body.dark .command-fields {
1028
1165
  background: rgba(0,0,0,0.3);
1029
1166
  }
1167
+ .header-description {
1168
+ display: flex;
1169
+ align-items: center;
1170
+ /*
1171
+ background: rgba(0,0,0,0.8);
1172
+ color: white;
1173
+ */
1174
+ margin-bottom: 20px;
1175
+ }
1030
1176
 
1031
1177
  .ace-editor {
1032
1178
  width: 100%;
@@ -1090,279 +1236,304 @@ body.dark .ace-editor {
1090
1236
  </header>
1091
1237
  <main>
1092
1238
  <div class="container">
1239
+ <!--
1240
+ <h1>Build a Launcher</h1>
1093
1241
  <h1><img class='logo2' src="/pinokio-black.png"/> Project Setup</h1>
1242
+ -->
1243
+ <div class="tab-container">
1244
+ <div class="tab-nav">
1245
+ <button type="button" class="tab-button active" data-tab="launcher">
1246
+ <i class="fa-solid fa-cloud-arrow-down" style="margin-right: 5px;"></i>
1247
+ Git
1248
+ </button>
1249
+ <button type="button" class="tab-button" data-tab="cli">
1250
+ <i class="fa-solid fa-terminal" style="margin-right: 5px;"></i>
1251
+ CLI
1252
+ </button>
1253
+ <button type="button" class="tab-button" data-tab="project">
1254
+ <i class="fa-regular fa-star" style="margin-right: 5px;"></i>
1255
+ New project
1256
+ </button>
1257
+ </div>
1258
+
1259
+ <form id="bootstrap-form">
1260
+ <!-- Launcher Tab -->
1261
+ <div class="tab-content active" id="launcher-tab">
1262
+ <!--
1263
+ <h2>Create a 1-Click Launcher</h2>
1264
+ -->
1265
+ <div class="header-description">
1266
+ <img class='logo2' src="/pinokio-black.png"/>
1267
+ <div class='bubble'>Create a launcher for any open source project via git.</div>
1268
+ </div>
1269
+ <div class="git-url-input">
1270
+ <blockquote>Name</blockquote>
1271
+ <div class='explain'>Enter a new folder name to create.</div>
1272
+ <input type="text" name="foldername-launcher" id="foldername-launcher" placeholder="folder name">
1273
+ </div>
1274
+
1275
+ <div class="git-url-input">
1276
+ <blockquote>Git URL</blockquote>
1277
+ <div class='explain'>Enter a git repository URL to clone from.</div>
1278
+ <input type="url" name="gitUrl" id="gitUrl" placeholder="example: https://github.com/username/repository.git">
1279
+ </div>
1280
+
1281
+ <div class="project-options">
1282
+ <blockquote>Type</blockquote>
1283
+ <div class='explain'>If you want to decide later, just choose "universal launcher".</div>
1284
+ <div class="radio-group">
1285
+ <label>
1286
+ <input type="radio" name="projectType" value="nodejs">
1287
+ <img class='appicon' src="/asset/prototype/system/nodejs/icon.png"/>
1288
+ <span>Node.js Launcher</span>
1289
+ <p class="description">install and launch a Node.js project.</p>
1290
+ </label>
1291
+ <label>
1292
+ <input type="radio" name="projectType" value="python">
1293
+ <img class='appicon' src="/asset/prototype/system/python/icon.png"/>
1294
+ <span>Python Launcher</span>
1295
+ <p class='description'>install and launch a Python project.</p>
1296
+ </label>
1297
+ <label>
1298
+ <input type="radio" name="projectType" value="empty">
1299
+ <img class='appicon' src="/asset/prototype/system/empty/icon.png"/>
1300
+ <span>Universal Launcher</span>
1301
+ <p class='description'>Build a launcher for any Git repository.</p>
1302
+ </label>
1303
+ </div>
1094
1304
 
1095
- <div class="progress-bar">
1096
- <div class="step active" data-step="1">1</div>
1097
- <div class="step" data-step="2">2</div>
1098
- <div class="step" data-step="3">3</div>
1099
- </div>
1100
-
1101
- <form id="bootstrap-form">
1102
- <!-- Step 1: New vs Clone -->
1103
- <div class="step-content active" id="step-1">
1104
- <h2>What do you want to build?</h2>
1105
- <div class="radio-group">
1106
- <label>
1107
- <input type="radio" name="startType" value="clone" required>
1108
- <i class="fa-solid fa-rocket"></i>
1109
- <div class='col'>
1110
- <span>1-Click Launcher</span>
1111
- <p class="description">Build a 1-click launcher for an existing app (from git)</p>
1305
+ <div class='command-fields conditional-options' id="clone-command-fields">
1306
+ <!-- Additional Fields for Clone Mode -->
1307
+ <div class="git-url-input">
1308
+ <blockquote>Install Command (Leave empty to decide later)</blockquote>
1309
+ <div id="cloneInstallCommand" class="ace-editor" data-name="cloneInstallCommand" data-placeholder="Install commands (one per line)"></div>
1310
+ <div class="checkbox-group">
1311
+ <label>
1312
+ <input type="checkbox" name="allowInstallUserInput" value="true">
1313
+ <span>Allow user input for install commands</span>
1314
+ </label>
1315
+ </div>
1112
1316
  </div>
1113
- </label>
1114
- <label>
1115
- <input type="radio" name="startType" value="new" required>
1116
- <i class="fa-solid fa-code"></i>
1117
- <div class='col'>
1118
- <span> App</span>
1119
- <p class="description">Set up a new project with a built-in 1-click launcher</p>
1317
+
1318
+ <div class="git-url-input">
1319
+ <blockquote>Start Command (Leave empty to decide later)</blockquote>
1320
+ <div id="cloneStartCommand" class="ace-editor" data-name="cloneStartCommand" data-placeholder="Start commands (one per line)"></div>
1321
+ <div class="checkbox-group">
1322
+ <label>
1323
+ <input type="checkbox" name="allowStartUserInput" value="true">
1324
+ <span>Allow user input for start commands</span>
1325
+ </label>
1326
+ </div>
1120
1327
  </div>
1121
- </label>
1122
- </div>
1123
- </div>
1124
-
1125
- <!-- Step 2: Project Type -->
1126
- <div class="step-content" id="step-2">
1127
- <h2>Select Project Type</h2>
1128
-
1129
- <!-- Clone Project Options -->
1130
- <div id="clone-options" class="project-options">
1131
- <div class="radio-group">
1132
- <label>
1133
- <input type="radio" name="projectType" value="nodejs">
1134
- <img class='appicon' src="/asset/prototype/system/nodejs/icon.png"/>
1135
- <span>Node.js Launcher</span>
1136
- <p class="description">install and launch a Node.js project.</p>
1137
- </label>
1138
- <label>
1139
- <input type="radio" name="projectType" value="python">
1140
- <img class='appicon' src="/asset/prototype/system/python/icon.png"/>
1141
- <span>Python Launcher</span>
1142
- <p class='description'>install and launch a Python project.</p>
1143
- </label>
1144
- <label>
1145
- <input type="radio" name="projectType" value="empty">
1146
- <img class='appicon' src="/asset/prototype/system/empty/icon.png"/>
1147
- <span>Universal Launcher</span>
1148
- <p class='description'>Build a launcher for any Git repository.</p>
1149
- </label>
1150
- <label>
1151
- <input type="radio" name="projectType" value="cli">
1152
- <img class='appicon' src="/asset/prototype/system/cli/icon.png"/>
1153
- <span>CLI App Launcher</span>
1154
- <p class="description">Build a 1-click launcher for any terminal app (npx, uvx, etc.).</p>
1155
- </label>
1156
- </div>
1157
-
1158
- <div class='command-fields conditional-options' id="clone-command-fields">
1159
- <div class="git-url-input">
1160
- <label for="gitUrl">Git Repository URL</label>
1161
- <input type="url" name="gitUrl" id="gitUrl" placeholder="https://github.com/username/repository.git">
1162
1328
  </div>
1163
1329
 
1164
- <!-- Additional Fields for Clone Mode -->
1165
- <div class="git-url-input">
1166
- <label for="cloneInstallCommand">Install Command (Leave empty to decide later)</label>
1167
- <div id="cloneInstallCommand" class="ace-editor" data-name="cloneInstallCommand" data-placeholder="Install commands (one per line)"></div>
1330
+ <!-- Python Options for Clone -->
1331
+ <div id="python-options-clone" class="conditional-options">
1332
+ <h3>Python Options</h3>
1168
1333
  <div class="checkbox-group">
1169
1334
  <label>
1170
- <input type="checkbox" name="allowInstallUserInput" value="true">
1171
- <span>Allow user input for install commands</span>
1335
+ <input type="checkbox" name="pythonOptions" value="torch">
1336
+ <span>Torch</span>
1337
+ </label>
1338
+ <label>
1339
+ <input type="checkbox" name="pythonOptions" value="xformers">
1340
+ <span>Xformers</span>
1172
1341
  </label>
1342
+ <label>
1343
+ <input type="checkbox" name="pythonOptions" value="triton">
1344
+ <span>Triton</span>
1345
+ </label>
1346
+ <label>
1347
+ <input type="checkbox" name="pythonOptions" value="sageattention">
1348
+ <span>SageAttention</span>
1349
+ </label>
1350
+ </div>
1351
+ </div>
1352
+
1353
+ </div>
1354
+
1355
+ </div>
1356
+
1357
+ <!-- CLI Tab -->
1358
+ <div class="tab-content" id="cli-tab">
1359
+ <div class="header-description">
1360
+ <img class='logo2' src="/pinokio-black.png"/>
1361
+ <div class='bubble'>Create a launcher for any terminal apps (npx, uvx, etc.)</div>
1362
+ </div>
1363
+ <div class="git-url-input">
1364
+ <blockquote>Name</blockquote>
1365
+ <div class='explain'>Enter a new folder name to create.</div>
1366
+ <input type="text" name="foldername-cli" id="foldername-cli" placeholder="folder name">
1367
+ </div>
1368
+ <blockquote>Type</blockquote>
1369
+ <div class='explain'>Single-command apps vs. Installable apps.</div>
1370
+ <div class="project-options">
1371
+ <div class="radio-group">
1372
+ <label>
1373
+ <input type="radio" name="cliType" value="instant">
1374
+ <img class='appicon' src="/asset/prototype/system/cli/icon.png"/>
1375
+ <span>Instant Command</span>
1376
+ <p class="description">npx, uvx, etc.</p>
1377
+ </label>
1378
+ <label>
1379
+ <input type="radio" name="cliType" value="installable">
1380
+ <img class='appicon' src="/asset/prototype/system/cli/icon.png"/>
1381
+ <span>Installable CLI App</span>
1382
+ <p class="description">CLI apps that require installation</p>
1383
+ </label>
1384
+ </div>
1385
+ </div>
1386
+
1387
+ <!-- Instant CLI Options -->
1388
+ <div id="instant-cli-options" class="conditional-options">
1389
+ <blockquote>Launch Command</blockquote>
1390
+ <input type="text" name="launchCommand" placeholder="e.g., npx create-react-app">
1391
+ </div>
1392
+
1393
+ <!-- Installable CLI Options -->
1394
+ <div id="installable-cli-options" class="conditional-options">
1395
+ <blockquote>Install Command</blockquote>
1396
+ <div id="installCommand" class="ace-editor" data-name="installCommand" data-placeholder="Install commands (one per line)"></div>
1397
+ <blockquote>Launch Command</blockquote>
1398
+ <div id="installableLaunchCommand" class="ace-editor" data-name="installableLaunchCommand" data-placeholder="Launch commands (one per line)"></div>
1399
+ </div>
1400
+
1401
+ <!-- Virtual Environment Option -->
1402
+ <div id="venv-option" class="conditional-options">
1403
+ <div class="checkbox-group">
1404
+ <label>
1405
+ <input type="checkbox" name="useVenv" value="true">
1406
+ <span>Use virtual environment (venv)</span>
1407
+ </label>
1408
+ </div>
1409
+ </div>
1410
+ </div>
1411
+
1412
+ <!-- Project Tab -->
1413
+ <div class="tab-content" id="project-tab">
1414
+ <div class="header-description">
1415
+ <img class='logo2' src="/pinokio-black.png"/>
1416
+ <div class='bubble'>Create a new project with a built-in 1-click launcher</div>
1417
+ </div>
1418
+ <div class="git-url-input">
1419
+ <blockquote>Name</blockquote>
1420
+ <div class='explain'>Enter a new folder name to create.</div>
1421
+ <input type="text" name="foldername-new" id="foldername-new" placeholder="folder name">
1422
+ </div>
1423
+ <blockquote>Type</blockquote>
1424
+ <div class='explain'>Set up a new 1-click launcher project.</div>
1425
+ <div class="project-options">
1426
+ <div class="radio-group">
1427
+ <label>
1428
+ <input type="radio" name="projectType" value="empty">
1429
+ <img class='appicon' src="/asset/prototype/system/empty/icon.png"/>
1430
+ <span>Empty Project</span>
1431
+ </label>
1432
+
1433
+ <label>
1434
+ <input type="radio" name="projectType" value="documentation">
1435
+ <img class='appicon' src="/asset/prototype/system/documentation/icon.png"/>
1436
+ <span>Documentation</span>
1437
+ </label>
1438
+
1439
+ <!-- Documentation Options -->
1440
+ <div id="documentation-options" class="conditional-options">
1441
+ <div class="radio-group">
1442
+ <label>
1443
+ <input type="radio" name="docType" value="local">
1444
+ <span>Documentation from Local Project</span>
1445
+ </label>
1446
+ <div id="local-doc-options" class="conditional-options">
1447
+ <h4>Local Project Path</h4>
1448
+ <input type="text" name="localDocPath" placeholder="e.g., /home/user/my-project" id='local'>
1449
+ </div>
1450
+
1451
+ <label>
1452
+ <input type="radio" name="docType" value="remote">
1453
+ <span>Documentation from Remote Git Repository</span>
1454
+ </label>
1455
+ <div id="remote-doc-options" class="conditional-options">
1456
+ <h4>Remote Git Repository URL</h4>
1457
+ <input type="text" name="remoteDocUrl" placeholder="e.g., https://github.com/user/repo.git">
1458
+ </div>
1459
+ </div>
1173
1460
  </div>
1461
+ <label>
1462
+ <input type="radio" name="projectType" value="nodejs">
1463
+ <img class='appicon' src="/asset/prototype/system/nodejs/icon.png"/>
1464
+ <span>Node.js</span>
1465
+ </label>
1466
+ <label>
1467
+ <input type="radio" name="projectType" value="python">
1468
+ <img class='appicon' src="/asset/prototype/system/python/icon.png"/>
1469
+ <span>Python</span>
1470
+ </label>
1174
1471
  </div>
1175
1472
 
1176
- <div class="git-url-input">
1177
- <label for="cloneStartCommand">Start Command (Leave empty to decide later)</label>
1178
- <div id="cloneStartCommand" class="ace-editor" data-name="cloneStartCommand" data-placeholder="Start commands (one per line)"></div>
1473
+
1474
+ <!-- Python Options -->
1475
+ <div id="python-options" class="conditional-options">
1476
+ <h3>Python Options</h3>
1179
1477
  <div class="checkbox-group">
1180
1478
  <label>
1181
- <input type="checkbox" name="allowStartUserInput" value="true">
1182
- <span>Allow user input for start commands</span>
1479
+ <input type="checkbox" name="pythonOptions" value="torch">
1480
+ <span>Torch</span>
1481
+ </label>
1482
+ <label>
1483
+ <input type="checkbox" name="pythonOptions" value="xformers">
1484
+ <span>Xformers</span>
1485
+ </label>
1486
+ <label>
1487
+ <input type="checkbox" name="pythonOptions" value="triton">
1488
+ <span>Triton</span>
1489
+ </label>
1490
+ <label>
1491
+ <input type="checkbox" name="pythonOptions" value="sageattention">
1492
+ <span>SageAttention</span>
1183
1493
  </label>
1184
1494
  </div>
1185
1495
  </div>
1186
- </div>
1187
-
1188
- <!-- Python Options for Clone -->
1189
- <div id="python-options-clone" class="conditional-options">
1190
- <h3>Python Options</h3>
1191
- <div class="checkbox-group">
1192
- <label>
1193
- <input type="checkbox" name="pythonOptions" value="torch">
1194
- <span>Torch</span>
1195
- </label>
1196
- <label>
1197
- <input type="checkbox" name="pythonOptions" value="xformers">
1198
- <span>Xformers</span>
1199
- </label>
1200
- <label>
1201
- <input type="checkbox" name="pythonOptions" value="triton">
1202
- <span>Triton</span>
1203
- </label>
1204
- <label>
1205
- <input type="checkbox" name="pythonOptions" value="sageattention">
1206
- <span>SageAttention</span>
1207
- </label>
1208
- </div>
1209
- </div>
1210
-
1211
- <!-- CLI App Launcher Options for Clone -->
1212
- <div id="cli-options" class="conditional-options">
1213
- <div class="radio-group">
1214
- <label>
1215
- <input type="radio" name="cliType" value="instant">
1216
- <span>Instant Command Launcher</span>
1217
- <p class="description">npx, uvx, etc.</p>
1218
- </label>
1219
- <label>
1220
- <input type="radio" name="cliType" value="installable">
1221
- <span>Installable CLI App Launcher</span>
1222
- <p class="description">CLI apps that require an installation step</p>
1223
- </label>
1224
- </div>
1225
-
1226
- <!-- Instant CLI Options -->
1227
- <div id="instant-cli-options" class="conditional-options">
1228
- <h4>Launch Command</h4>
1229
- <input type="text" name="launchCommand" placeholder="e.g., npx create-react-app">
1230
- </div>
1231
-
1232
- <!-- Installable CLI Options -->
1233
- <div id="installable-cli-options" class="conditional-options">
1234
- <h4>Install Command</h4>
1235
- <div id="installCommand" class="ace-editor" data-name="installCommand" data-placeholder="Install commands (one per line)"></div>
1236
- <h4>Launch Command</h4>
1237
- <div id="installableLaunchCommand" class="ace-editor" data-name="installableLaunchCommand" data-placeholder="Launch commands (one per line)"></div>
1238
- </div>
1239
-
1240
- <!-- Virtual Environment Option -->
1241
- <div class="checkbox-group">
1242
- <label>
1243
- <input type="checkbox" name="useVenv" value="true">
1244
- <span>Use virtual environment (venv)</span>
1245
- </label>
1246
- </div>
1247
- </div>
1248
- </div>
1249
-
1250
- <!-- New Project Options -->
1251
- <div id="new-options" class="project-options">
1252
- <div class="radio-group">
1253
- <label>
1254
- <input type="radio" name="projectType" value="empty">
1255
- <img class='appicon' src="/asset/prototype/system/empty/icon.png"/>
1256
- <span>Empty Project</span>
1257
- </label>
1258
-
1259
- <label>
1260
- <input type="radio" name="projectType" value="documentation">
1261
- <img class='appicon' src="/asset/prototype/system/documentation/icon.png"/>
1262
- <span>Documentation</span>
1263
- </label>
1264
-
1265
- <!-- Documentation Options -->
1266
- <div id="documentation-options" class="conditional-options">
1267
- <div class="radio-group">
1268
- <label>
1269
- <input type="radio" name="docType" value="local">
1270
- <span>Documentation from Local Project</span>
1271
- </label>
1272
- <div id="local-doc-options" class="conditional-options">
1273
- <h4>Local Project Path</h4>
1274
- <input type="text" name="localDocPath" placeholder="e.g., /home/user/my-project" id='local'>
1275
- </div>
1276
-
1277
- <label>
1278
- <input type="radio" name="docType" value="remote">
1279
- <span>Documentation from Remote Git Repository</span>
1280
- </label>
1281
- <div id="remote-doc-options" class="conditional-options">
1282
- <h4>Remote Git Repository URL</h4>
1283
- <input type="text" name="remoteDocUrl" placeholder="e.g., https://github.com/user/repo.git">
1284
- </div>
1285
- </div>
1286
- </div>
1287
- <label>
1288
- <input type="radio" name="projectType" value="nodejs">
1289
- <img class='appicon' src="/asset/prototype/system/nodejs/icon.png"/>
1290
- <span>Node.js</span>
1291
- </label>
1292
- <label>
1293
- <input type="radio" name="projectType" value="python">
1294
- <img class='appicon' src="/asset/prototype/system/python/icon.png"/>
1295
- <span>Python</span>
1296
- </label>
1297
- </div>
1298
-
1299
-
1300
- <!-- Python Options -->
1301
- <div id="python-options" class="conditional-options">
1302
- <h3>Python Options</h3>
1303
- <div class="checkbox-group">
1304
- <label>
1305
- <input type="checkbox" name="pythonOptions" value="torch">
1306
- <span>Torch</span>
1307
- </label>
1308
- <label>
1309
- <input type="checkbox" name="pythonOptions" value="xformers">
1310
- <span>Xformers</span>
1311
- </label>
1312
- <label>
1313
- <input type="checkbox" name="pythonOptions" value="triton">
1314
- <span>Triton</span>
1315
- </label>
1316
- <label>
1317
- <input type="checkbox" name="pythonOptions" value="sageattention">
1318
- <span>SageAttention</span>
1319
- </label>
1320
- </div>
1321
- </div>
1322
- </div>
1323
-
1324
- <div class="button-group">
1325
- <button type="button" class="btn btn-secondary" onclick="prevStep()"><i class="fa-solid fa-chevron-left"></i> Back</button>
1326
- <button type="button" class="btn btn-primary" onclick="nextStep()">Next <i class="fa-solid fa-chevron-right"></i></button>
1327
- </div>
1328
- </div>
1329
-
1330
- <!-- Step 3: AI Prompt -->
1331
- <div class="step-content" id="step-3">
1332
- <h2>Step 3: AI Prompt (Optional)</h2>
1333
- <p>Enter a prompt to build your app with AI assistance.</p>
1334
- <blockquote>The prompt will be stored in README.md, and ANY AI coding tool will be automatically instructed about the project (Just say "build the app").</blockquote>
1335
- <div id="aiPrompt" class="ace-editor" data-name="aiPrompt" data-placeholder="Describe what you want to build... (optional)" style="height: 150px;"></div>
1336
-
1337
- <div class="button-group">
1338
- <button type="button" class="btn btn-secondary" onclick="prevStep()"><i class="fa-solid fa-chevron-left"></i> Back</button>
1339
- <button type="submit" class="btn btn-success">Create</button>
1340
- </div>
1341
- </div>
1342
- </form>
1496
+ </div>
1497
+
1498
+ </div>
1499
+
1500
+ <!-- AI Prompt Section (shared across both tabs) -->
1501
+ <div class="ai-prompt-section" style="margin-top: 2rem;">
1502
+ <!--
1503
+ <h2>AI Prompt (Optional)</h2>
1504
+ <p>Enter a prompt to build your app with AI assistance.</p>
1505
+ -->
1506
+ <blockquote>What do you want to build?</blockquote>
1507
+ <div class='explain'>(Optional) Explain what the project should do. Will be saved as README.md, and will be automatically used by AI Coding tools to build the app.</div>
1508
+ <!--
1509
+ <blockquote>The prompt will be stored in README.md, and ANY AI coding tool will be automatically instructed about the project (Just say "build the app").</blockquote>
1510
+ -->
1511
+ <div id="aiPrompt" class="ace-editor" data-name="aiPrompt" data-placeholder="Describe what you want to build... (optional)" style="height: 150px;"></div>
1512
+ </div>
1513
+
1514
+ <div class="button-group" style="margin-top: 2rem;">
1515
+ <button type="submit" class="btn btn-success" id="create-button">Create Launcher</button>
1516
+ </div>
1517
+ </form>
1518
+ </div>
1343
1519
  <div id='terminal'></div>
1344
1520
  <div id='end'></div>
1345
1521
  </div>
1346
1522
  </main>
1347
1523
  <script>
1348
- let currentStep = 1;
1349
- const totalSteps = 3;
1350
-
1351
1524
  document.addEventListener('DOMContentLoaded', function() {
1352
- // Initialize form
1353
- showStep(currentStep);
1354
-
1355
- // Add event listeners for conditional logic
1356
- const startTypeRadios = document.querySelectorAll('input[name="startType"]');
1357
- startTypeRadios.forEach(radio => {
1358
- radio.addEventListener('change', handleStartTypeChange);
1359
- radio.addEventListener('change', () => {
1360
- // Automatically move to step 2 when radio button is clicked
1361
- setTimeout(() => {
1362
- if (currentStep === 1) {
1363
- nextStep();
1364
- }
1365
- }, 300); // Small delay for better UX
1525
+ // Initialize tabs
1526
+ initializeTabs();
1527
+
1528
+ // Show launcher tab by default
1529
+ showTab('launcher');
1530
+
1531
+ // Add tab click handlers
1532
+ const tabButtons = document.querySelectorAll('.tab-button');
1533
+ tabButtons.forEach(button => {
1534
+ button.addEventListener('click', () => {
1535
+ const tabName = button.getAttribute('data-tab');
1536
+ showTab(tabName);
1366
1537
  });
1367
1538
  });
1368
1539
 
@@ -1455,178 +1626,81 @@ function initializeAceEditors() {
1455
1626
  });
1456
1627
  }
1457
1628
 
1458
- function showStep(stepNumber) {
1459
- console.log(stepNumber)
1460
- if (stepNumber === 1) {
1461
- document.querySelectorAll("#step-1 input[type=radio]").forEach((el) => {
1462
- el.checked = false
1463
- })
1464
- }
1465
- // Hide all steps
1466
- document.querySelectorAll('.step-content').forEach(step => {
1467
- step.classList.remove('active');
1468
- });
1469
-
1470
- // Show current step
1471
- document.getElementById(`step-${stepNumber}`).classList.add('active');
1472
-
1473
- // Update progress bar
1474
- document.querySelectorAll('.progress-bar .step').forEach((step, index) => {
1475
- step.classList.remove('active', 'completed');
1476
- if (index + 1 < stepNumber) {
1477
- step.classList.add('completed');
1478
- } else if (index + 1 === stepNumber) {
1479
- step.classList.add('active');
1480
- }
1481
- });
1482
- }
1483
-
1484
- function nextStep() {
1485
- if (validateCurrentStep()) {
1486
- if (currentStep < totalSteps) {
1487
- currentStep++;
1488
- showStep(currentStep);
1489
- }
1490
- }
1629
+ function initializeTabs() {
1630
+ // Initialize tab functionality
1491
1631
  }
1492
1632
 
1493
- function prevStep() {
1494
- if (currentStep > 1) {
1495
- currentStep--;
1496
- showStep(currentStep);
1497
- }
1498
- }
1499
-
1500
- function validateCurrentStep() {
1501
- if (currentStep === 1) {
1502
- const startType = document.querySelector('input[name="startType"]:checked');
1503
- if (!startType) {
1504
- alert('Please select whether to start with a new project or clone a repository.');
1505
- return false;
1506
- }
1507
- return true;
1508
- }
1509
-
1510
- if (currentStep === 2) {
1511
- const startType = document.querySelector('input[name="startType"]:checked');
1512
- const projectType = document.querySelector('input[name="projectType"]:checked');
1513
-
1514
- if (!projectType) {
1515
- alert('Please select a project type.');
1516
- return false;
1517
- }
1518
-
1519
- if (startType.value === 'clone' && projectType.value !== 'cli') {
1520
- const gitUrl = document.getElementById('gitUrl').value.trim();
1521
- if (!gitUrl) {
1522
- alert('Please enter a Git repository URL.');
1523
- return false;
1524
- }
1525
-
1526
- // const cloneInstallCommand = document.getElementById('cloneInstallCommand').value.trim();
1527
- // const cloneStartCommand = document.getElementById('cloneStartCommand').value.trim();
1528
- // if (!cloneInstallCommand) {
1529
- // alert('Please enter at least one install command.');
1530
- // return false;
1531
- // }
1532
- // if (!cloneStartCommand) {
1533
- // alert('Please enter at least one start command.');
1534
- // return false;
1535
- // }
1536
- }
1537
-
1538
- // Validate CLI options for the main CLI category
1539
- if (startType && startType.value === 'cli') {
1540
- if (projectType.value === 'instant') {
1541
- const launchCommand = document.querySelector('input[name="launchCommand"]').value.trim();
1542
- if (!launchCommand) {
1543
- alert('Please enter a launch command.');
1544
- return false;
1545
- }
1546
- } else if (projectType.value === 'installable') {
1547
- const installCommand = aceEditors['installCommand'] ? aceEditors['installCommand'].getValue().trim() : '';
1548
- const launchCommand = aceEditors['installableLaunchCommand'] ? aceEditors['installableLaunchCommand'].getValue().trim() : '';
1549
- if (!installCommand) {
1550
- alert('Please enter at least one install command.');
1551
- return false;
1552
- }
1553
- if (!launchCommand) {
1554
- alert('Please enter at least one launch command.');
1555
- return false;
1556
- }
1557
- }
1558
- }
1559
-
1560
- // Validate Documentation options
1561
- if (projectType.value === 'documentation') {
1562
- const docType = document.querySelector('input[name="docType"]:checked');
1563
- if (!docType) {
1564
- alert('Please select a documentation source.');
1565
- return false;
1566
- }
1567
-
1568
- if (docType.value === 'local') {
1569
- const localDocPath = document.querySelector('input[name="localDocPath"]').value.trim();
1570
- if (!localDocPath) {
1571
- alert('Please enter a local project path.');
1572
- return false;
1573
- }
1574
- } else if (docType.value === 'remote') {
1575
- const remoteDocUrl = document.querySelector('input[name="remoteDocUrl"]').value.trim();
1576
- if (!remoteDocUrl) {
1577
- alert('Please enter a remote Git repository URL.');
1578
- return false;
1579
- }
1580
- }
1581
- }
1582
-
1583
- return true;
1633
+ function showTab(tabName) {
1634
+ // Hide all tab contents
1635
+ document.querySelectorAll('.tab-content').forEach(tab => {
1636
+ tab.classList.remove('active');
1637
+ });
1638
+
1639
+ // Remove active class from all tab buttons
1640
+ document.querySelectorAll('.tab-button').forEach(button => {
1641
+ button.classList.remove('active');
1642
+ });
1643
+
1644
+ // Show selected tab
1645
+ document.getElementById(`${tabName}-tab`).classList.add('active');
1646
+ document.querySelector(`[data-tab="${tabName}"]`).classList.add('active');
1647
+
1648
+ // Update create button text
1649
+ const createButton = document.getElementById('create-button');
1650
+ createButton.textContent = 'Create'
1651
+ /*
1652
+ if (tabName === 'launcher') {
1653
+ createButton.textContent = 'Create Launcher';
1654
+ } else if (tabName === 'cli') {
1655
+ createButton.textContent = 'Create CLI Launcher';
1656
+ } else {
1657
+ createButton.textContent = 'Create Project';
1584
1658
  }
1585
-
1586
- return true;
1587
- }
1588
-
1589
- function handleStartTypeChange(event) {
1590
- const startType = event.target.value;
1591
- const newOptions = document.getElementById('new-options');
1592
- const cloneOptions = document.getElementById('clone-options');
1593
-
1594
- // Clear any existing selections
1659
+ */
1660
+
1661
+ // Clear form selections when switching tabs
1595
1662
  document.querySelectorAll('input[name="projectType"]').forEach(radio => {
1596
1663
  radio.checked = false;
1597
1664
  });
1665
+ document.querySelectorAll('input[name="cliType"]').forEach(radio => {
1666
+ radio.checked = false;
1667
+ });
1668
+
1669
+ // Hide all conditional options
1670
+ hideAllConditionalOptions();
1671
+
1672
+ // Clear Git URL when switching away from launcher tab
1673
+ if (tabName !== 'launcher') {
1674
+ document.getElementById('gitUrl').value = '';
1675
+ }
1676
+
1677
+ // Clear CLI inputs
1678
+ if (tabName !== 'cli') {
1679
+ clearCliInputs();
1680
+ }
1681
+ }
1598
1682
 
1599
- // Clear Git URL
1600
- document.getElementById('gitUrl').value = '';
1601
-
1602
- // Hide python options
1683
+ function hideAllConditionalOptions() {
1603
1684
  document.getElementById('python-options').classList.remove('show');
1604
1685
  document.getElementById('python-options-clone').classList.remove('show');
1605
-
1606
- // Hide clone command fields
1686
+ document.getElementById('instant-cli-options').classList.remove('show');
1687
+ document.getElementById('installable-cli-options').classList.remove('show');
1688
+ document.getElementById('venv-option').classList.remove('show');
1607
1689
  document.getElementById('clone-command-fields').classList.remove('show');
1608
-
1609
- if (startType === 'clone') {
1610
- cloneOptions.classList.add('show');
1611
- newOptions.classList.remove('show');
1612
- } else {
1613
- newOptions.classList.add('show');
1614
- cloneOptions.classList.remove('show');
1615
- }
1690
+ document.getElementById('documentation-options').classList.remove('show');
1691
+ document.getElementById('local-doc-options').classList.remove('show');
1692
+ document.getElementById('remote-doc-options').classList.remove('show');
1616
1693
  }
1617
1694
 
1695
+
1618
1696
  function handleProjectTypeChange(event) {
1619
1697
  const projectType = event.target.value;
1620
- const startType = document.querySelector('input[name="startType"]:checked').value;
1698
+ const activeTab = document.querySelector('.tab-content.active').id;
1699
+ const isLauncher = activeTab === 'launcher-tab';
1700
+ const isCli = activeTab === 'cli-tab';
1621
1701
 
1622
1702
  // Hide all conditional options first
1623
- document.getElementById('python-options').classList.remove('show');
1624
- document.getElementById('python-options-clone').classList.remove('show');
1625
- document.getElementById('cli-options').classList.remove('show');
1626
- document.getElementById('instant-cli-options').classList.remove('show');
1627
- document.getElementById('installable-cli-options').classList.remove('show');
1628
- document.getElementById('clone-command-fields').classList.remove('show');
1629
- document.getElementById('documentation-options').classList.remove('show');
1703
+ hideAllConditionalOptions();
1630
1704
 
1631
1705
  // Clear all checkboxes and radio buttons
1632
1706
  document.querySelectorAll('input[name="pythonOptions"]').forEach(checkbox => {
@@ -1642,22 +1716,43 @@ function handleProjectTypeChange(event) {
1642
1716
  // Clear CLI input fields
1643
1717
  clearCliInputs();
1644
1718
 
1645
- // Show clone command fields when a project type is selected in clone mode (but not for CLI)
1646
- if (startType === 'clone' && projectType !== 'cli') {
1719
+ // Show clone command fields when a project type is selected in launcher mode (but not for CLI)
1720
+ if (isLauncher && projectType !== 'cli') {
1647
1721
  document.getElementById('clone-command-fields').classList.add('show');
1648
1722
  updateCloneDefaults(projectType);
1649
1723
  }
1650
1724
 
1651
1725
  // Show appropriate options based on project type
1652
1726
  if (projectType === 'python') {
1653
- if (startType === 'clone') {
1727
+ if (isLauncher) {
1654
1728
  document.getElementById('python-options-clone').classList.add('show');
1655
1729
  } else {
1656
1730
  document.getElementById('python-options').classList.add('show');
1657
1731
  }
1658
- } else if (projectType === 'cli') {
1659
- document.getElementById('cli-options').classList.add('show');
1660
- // Re-initialize CLI editors that just became visible
1732
+ } else if (projectType === 'documentation') {
1733
+ document.getElementById('documentation-options').classList.add('show');
1734
+ }
1735
+ }
1736
+
1737
+ // Add CLI type change handler
1738
+ function handleCliTypeChange(event) {
1739
+ const cliType = event.target.value;
1740
+
1741
+ // Hide all CLI sub-options first
1742
+ document.getElementById('instant-cli-options').classList.remove('show');
1743
+ document.getElementById('installable-cli-options').classList.remove('show');
1744
+ document.getElementById('venv-option').classList.remove('show');
1745
+
1746
+ // Clear CLI input fields
1747
+ clearCliInputs();
1748
+
1749
+ // Show appropriate CLI options
1750
+ if (cliType === 'instant') {
1751
+ document.getElementById('instant-cli-options').classList.add('show');
1752
+ } else if (cliType === 'installable') {
1753
+ document.getElementById('installable-cli-options').classList.add('show');
1754
+ document.getElementById('venv-option').classList.add('show');
1755
+ // Re-initialize editors that just became visible
1661
1756
  setTimeout(() => {
1662
1757
  if (aceEditors['installCommand']) {
1663
1758
  aceEditors['installCommand'].session.insert({ row: aceEditors['installCommand'].session.getLength(), column: 0 }, "\n\n");
@@ -1676,8 +1771,6 @@ function handleProjectTypeChange(event) {
1676
1771
  aceEditors['installableLaunchCommand'].renderer.updateFull();
1677
1772
  }
1678
1773
  }, 50);
1679
- } else if (projectType === 'documentation') {
1680
- document.getElementById('documentation-options').classList.add('show');
1681
1774
  }
1682
1775
  }
1683
1776
 
@@ -1737,19 +1830,26 @@ function handleCliTypeChange(event) {
1737
1830
  }
1738
1831
 
1739
1832
  function updateCloneDefaults(projectType) {
1740
- const installCommandField = document.getElementById('cloneInstallCommand');
1741
- const startCommandField = document.getElementById('cloneStartCommand');
1742
-
1743
- if (projectType === 'nodejs') {
1744
- installCommandField.value = 'npm install';
1745
- startCommandField.value = 'npm start';
1746
- } else if (projectType === 'python') {
1747
- installCommandField.value = 'uv pip install -r requirements.txt';
1748
- startCommandField.value = 'python app.py';
1749
- } else if (projectType === 'empty') {
1750
- // Clear fields for "Use AI" category
1751
- installCommandField.value = '';
1752
- startCommandField.value = '';
1833
+ // Use Ace editor setValue() method instead of .value
1834
+ const installCommandEditor = aceEditors['cloneInstallCommand'];
1835
+ const startCommandEditor = aceEditors['cloneStartCommand'];
1836
+
1837
+ if (installCommandEditor && startCommandEditor) {
1838
+ if (projectType === 'nodejs') {
1839
+ installCommandEditor.setValue('npm install');
1840
+ startCommandEditor.setValue('npm start');
1841
+ } else if (projectType === 'python') {
1842
+ installCommandEditor.setValue('uv pip install -r requirements.txt');
1843
+ startCommandEditor.setValue('python app.py');
1844
+ } else if (projectType === 'empty') {
1845
+ // Clear fields for "Use AI" category
1846
+ installCommandEditor.setValue('');
1847
+ startCommandEditor.setValue('');
1848
+ }
1849
+
1850
+ // Clear selection and move cursor to end for better UX
1851
+ installCommandEditor.clearSelection();
1852
+ startCommandEditor.clearSelection();
1753
1853
  }
1754
1854
  }
1755
1855
 
@@ -1772,10 +1872,131 @@ function handleDocTypeChange(event) {
1772
1872
  }
1773
1873
  }
1774
1874
 
1875
+ function validateForm() {
1876
+ const activeTab = document.querySelector('.tab-content.active').id;
1877
+ const isLauncher = activeTab === 'launcher-tab';
1878
+ const isCli = activeTab === 'cli-tab';
1879
+ const gitUrl = document.getElementById('gitUrl').value.trim();
1880
+
1881
+ // Validate Git URL for launcher tab
1882
+ if (isLauncher) {
1883
+ const gitUrl = document.getElementById('gitUrl').value.trim();
1884
+ if (!gitUrl) {
1885
+ alert('Please enter a Git repository URL.');
1886
+ return false;
1887
+ }
1888
+ const name = document.getElementById('foldername-launcher').value.trim();
1889
+ if (!name) {
1890
+ alert('Please enter a folder name.');
1891
+ return false;
1892
+ }
1893
+ if (name.includes(" ")) {
1894
+ alert('No spaces allowed');
1895
+ return false;
1896
+ }
1897
+
1898
+ const projectType = document.querySelector('input[name="projectType"]:checked');
1899
+ if (!projectType) {
1900
+ alert('Please select a project type.');
1901
+ return false;
1902
+ }
1903
+ }
1904
+
1905
+ // Validate CLI tab
1906
+ if (isCli) {
1907
+ const cliType = document.querySelector('input[name="cliType"]:checked');
1908
+ if (!cliType) {
1909
+ alert('Please select a CLI type.');
1910
+ return false;
1911
+ }
1912
+
1913
+ const name = document.getElementById('foldername-cli').value.trim();
1914
+ if (!name) {
1915
+ alert('Please enter a folder name.');
1916
+ return false;
1917
+ }
1918
+ if (name.includes(" ")) {
1919
+ alert('No spaces allowed');
1920
+ return false;
1921
+ }
1922
+
1923
+ if (cliType.value === 'instant') {
1924
+ const launchCommand = document.querySelector('input[name="launchCommand"]').value.trim();
1925
+ if (!launchCommand) {
1926
+ alert('Please enter a launch command.');
1927
+ return false;
1928
+ }
1929
+ } else if (cliType.value === 'installable') {
1930
+ const installCommand = aceEditors['installCommand'] ? aceEditors['installCommand'].getValue().trim() : '';
1931
+ const launchCommand = aceEditors['installableLaunchCommand'] ? aceEditors['installableLaunchCommand'].getValue().trim() : '';
1932
+ if (!installCommand) {
1933
+ alert('Please enter at least one install command.');
1934
+ return false;
1935
+ }
1936
+ if (!launchCommand) {
1937
+ alert('Please enter at least one launch command.');
1938
+ return false;
1939
+ }
1940
+ }
1941
+ }
1942
+
1943
+ // Validate project tab
1944
+ if (!isLauncher && !isCli) {
1945
+ const projectType = document.querySelector('input[name="projectType"]:checked');
1946
+ if (!projectType) {
1947
+ alert('Please select a project type.');
1948
+ return false;
1949
+ }
1950
+
1951
+ const name = document.getElementById('foldername-new').value.trim();
1952
+ if (!name) {
1953
+ alert('Please enter a folder name.');
1954
+ return false;
1955
+ }
1956
+ if (name.includes(" ")) {
1957
+ alert('No spaces allowed');
1958
+ return false;
1959
+ }
1960
+
1961
+ // Validate Documentation options
1962
+ if (projectType.value === 'documentation') {
1963
+ const docType = document.querySelector('input[name="docType"]:checked');
1964
+ if (!docType) {
1965
+ alert('Please select a documentation source.');
1966
+ return false;
1967
+ }
1968
+
1969
+ if (docType.value === 'local') {
1970
+ const localDocPath = document.querySelector('input[name="localDocPath"]').value.trim();
1971
+ if (!localDocPath) {
1972
+ alert('Please enter a local project path.');
1973
+ return false;
1974
+ }
1975
+ } else if (docType.value === 'remote') {
1976
+ const remoteDocUrl = document.querySelector('input[name="remoteDocUrl"]').value.trim();
1977
+ if (!remoteDocUrl) {
1978
+ alert('Please enter a remote Git repository URL.');
1979
+ return false;
1980
+ }
1981
+ }
1982
+ }
1983
+ }
1984
+
1985
+ return true;
1986
+ }
1987
+
1775
1988
  function handleSubmit(event) {
1776
1989
  event.preventDefault();
1990
+
1991
+ if (!validateForm()) {
1992
+ return;
1993
+ }
1777
1994
 
1778
1995
  const formData = new FormData(event.target);
1996
+ const activeTab = document.querySelector('.tab-content.active').id;
1997
+ const isLauncher = activeTab === 'launcher-tab';
1998
+ const isCli = activeTab === 'cli-tab';
1999
+ const gitUrl = isLauncher ? formData.get('gitUrl').trim() : '';
1779
2000
 
1780
2001
  // Get values from Ace editors and clean them
1781
2002
  const cloneInstallCommandText = aceEditors['cloneInstallCommand'] ? aceEditors['cloneInstallCommand'].getValue().trim() : '';
@@ -1784,23 +2005,36 @@ function handleSubmit(event) {
1784
2005
  const installableLaunchCommandText = aceEditors['installableLaunchCommand'] ? aceEditors['installableLaunchCommand'].getValue().trim() : '';
1785
2006
  const aiPromptText = aceEditors['aiPrompt'] ? aceEditors['aiPrompt'].getValue().trim() : '';
1786
2007
 
1787
- const startType = formData.get('startType');
1788
- const projectType = formData.get('projectType');
2008
+ // Set startType and projectType based on active tab
2009
+ let startType, projectType, name;
2010
+ if (isLauncher) {
2011
+ startType = 'clone';
2012
+ projectType = formData.get('projectType');
2013
+ name = formData.get("foldername-launcher").trim();
2014
+ } else if (isCli) {
2015
+ startType = 'new';
2016
+ projectType = 'cli';
2017
+ name = formData.get("foldername-cli").trim();
2018
+ } else {
2019
+ startType = 'new';
2020
+ projectType = formData.get('projectType');
2021
+ name = formData.get("foldername-new").trim();
2022
+ }
1789
2023
 
1790
2024
  // For CLI category, map the projectType to cliType for backwards compatibility
1791
2025
  let mappedProjectType = projectType;
1792
2026
  let cliType = formData.get('cliType');
1793
2027
 
1794
- if (startType === 'cli') {
1795
- // When CLI is selected as startType, projectType becomes the cliType
1796
- cliType = projectType;
2028
+ if (projectType === 'cli') {
2029
+ // When CLI is selected as projectType, cliType determines the actual type
1797
2030
  mappedProjectType = 'cli';
1798
2031
  }
1799
2032
 
1800
2033
  const config = {
2034
+ name,
1801
2035
  startType: startType,
1802
2036
  projectType: mappedProjectType,
1803
- gitUrl: formData.get('gitUrl'),
2037
+ gitUrl: gitUrl,
1804
2038
  cloneInstallCommand: cloneInstallCommandText ? cloneInstallCommandText.split('\n').filter(line => line.trim() !== '') : [],
1805
2039
  cloneStartCommand: cloneStartCommandText ? cloneStartCommandText.split('\n').filter(line => line.trim() !== '') : [],
1806
2040
  allowInstallUserInput: formData.get('allowInstallUserInput'),
@@ -1910,7 +2144,7 @@ async function displayResults(config) {
1910
2144
  socket.run({
1911
2145
  method: "kernel.proto.create",
1912
2146
  cwd: "<%-JSON.stringify(cwd).slice(1, -1)%>",
1913
- name: "<%=name%>",
2147
+ // name: "<%=name%>",
1914
2148
  params: config
1915
2149
  }, async (packet) => {
1916
2150
  console.log('packet', packet)
@@ -1923,6 +2157,7 @@ async function displayResults(config) {
1923
2157
  location.href = packet.data.success
1924
2158
  } else if (packet.data.error) {
1925
2159
  alert(packet.data.error)
2160
+ location.href = location.href
1926
2161
  }
1927
2162
  } else if (packet.type === "stream") {
1928
2163
  // set the current shell id