1<html><head> 2 <meta charset="UTF-8"> 3 <meta name="viewport" content="width=device-width, initial-scale=1.0"> 4 <title>Cosmic App Forge</title> 5 <meta name="description" content="Cosmic App Forge: A powerful tool for building and customizing your own applications effortlessly. Create, design, and deploy apps with ease using our intuitive interface and robust features. Perfect for developers and non-developers alike."> 6 <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"> 7 <meta http-equiv="Pragma" content="no-cache"> 8 <meta http-equiv="Expires" content="0"> 9 <link rel="icon" href="favicon.png" type="image/png"> 10 <link href="https://cdnjs.cloudflare.com/ajax/libs/daisyui/3.1.0/full.css" rel="stylesheet" type="text/css" /> 11
11<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/2.11.338/pdf.min.js"></script>
11 12
12<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.3.10/purify.min.js"></script>
12 13
13<script src="https://cdn.tailwindcss.com"></script>
13 14
14<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.14/vue.js"></script>
14 15
15<script src="https://cdnjs.cloudflare.com/ajax/libs/marked/12.0.1/marked.min.js"></script>
15 16
16<script src="https://cdnjs.cloudflare.com/ajax/libs/lz-string/1.4.4/lz-string.min.js"></script>
16 17
17<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.33.0/min/vs/loader.min.js"></script>
17 18
18<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
18 19
19<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js"></script>
19 20 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> 21 <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate"> <!-- HTTP 1.1 --> 22 <meta http-equiv="Pragma" content="no-cache"> <!-- HTTP 1.0 --> 23 <meta http-equiv="Expires" content="0"> <!-- Proxies --> 24 25 26 <style> 27 @media (max-width: 1024px) { 28 .fullscreen-button { 29 display: none; 30 } 31 } 32 .loader { 33 border: 4px solid rgba(255, 255, 255, 0.3); 34 border-top: 4px solid #ffffff; 35 border-radius: 50%; 36 width: 24px; 37 height: 24px; 38 animation: spin 1s linear infinite; 39 } 40 @keyframes spin { 41 0% { transform: rotate(0deg); } 42 100% { transform: rotate(360deg); } 43 } 44 45 /* Reasoning/Thinking section styles */ 46 details.reasoning-section { 47 border-left: 3px solid #8b5cf6; 48 } 49 details.reasoning-section summary { 50 transition: all 0.3s ease; 51 } 52 details.reasoning-section[open] summary { 53 margin-bottom: 0.5rem; 54 padding-bottom: 0.5rem; 55 border-bottom: 1px solid rgba(139, 92, 246, 0.3); 56 } 57 details.reasoning-section summary:hover { 58 opacity: 0.8; 59 } 60 61 html, body, #app { 62 height: 100%; 63 64 } 65 .mobile-content { 66 height: calc(100% - 4rem); 67 overflow-y: auto; 68 } 69 #monaco-editor { 70 width: 100%; 71 height: 100%; 72 } 73 .editor-container { 74 display: flex; 75 flex-direction: column; 76 height: 100%; 77 } 78 .tabs-container { 79 flex-shrink: 0; 80 } 81 .monaco-container { 82 flex-grow: 1; 83 overflow: hidden; 84 } 85 86 87 </style> 88 </head> 89 <body> 90 <div id="app" class="flex flex-col h-full bg-base-200"> 91 <!-- Open the modal using ID.showModal() method --> 92 93 <dialog id="settings_modal" class="modal" onclick="if(event.target === this) this.close()"> 94 <div class="modal-box"> 95 <h3 class="text-lg font-bold">Settings</h3> 96 <recursive-settings :settings="settings" ></recursive-settings> 97 <div class="modal-action"> 98 <form method="dialog"> 99 <button class="btn">Close</button> 100 </form> 101 </div> 102 </div> 103 </dialog> 104 <!-- Navbar (hidden on mobile) --> 105 <div class="navbar bg-base-100 shadow-lg flex-wrap hidden lg:flex"> 106 <div class="flex-1"> 107 <a href="https://discord.gg/88fQT5Bgfe" target="_blank" class="btn btn-ghost normal-case text-xl">{{ document.title }}</a> 108 </div> 109 <template id="menu-template-1"> 110 <ul tabindex="0" :style="{ display: 'flex', flexDirection: isFullScreen ? 'row' : 'row' }" :class="['dropdown-content mt-3 z-[1] p-2 bg-base-100 menu-sm menu', { 'w-52 shadow': isFullScreen }]"> 111 112 <li> 113 <a href="./" class="text-lg md:text-base"><i class="fas fa-comments"></i> New Chat </a> 114 </li> 115 116 <li> 117 <details> 118 <summary class="text-lg md:text-base"> 119 <i class="fas fa-comments"></i> <span class="truncate max-w-[111px]">Model</span> 120 </summary> 121 <ul :class="['right-0 p-2 bg-base-100 shadow', { 'absolute': !isFullScreen }]"> 122 <li v-for="model in settings.model.options" :key="model"> 123 <a class="text-lg md:text-base" @click="settings.model.selected=model" :class="{ 'font-bold': settings.model.selected === model }">{{ model }}</a> 124 </li> 125 </ul> 126 </details> 127 </li> 128 <li> 129 <details> 130 <summary title="Select a System Prompt" class="text-lg md:text-base"> 131 <i class="fas fa-user"></i> Preset: {{ params.activeContact }} 132 </summary> 133 <ul :class="['right-0 p-2 bg-base-100 shadow', { 'absolute': !isFullScreen }]"> 134 <li v-for="(contact, index) in settings.contacts" :key="index" v-if="!contact.hidden">
135 <a class="text-lg md:text-base" @click="OnSelectContact(contact)">{{ contact.name }}</a> 136 </li> 137 </ul> 138 </details> 139 </li> 140 <li><a class="text-lg md:text-base" @click="promptInstall()"><i class="fas fa-download"></i> Install...</a></li> 141 <li> 142 <a class="text-lg md:text-base" onclick="settings_modal.showModal()"> 143 <i class="fas fa-cog"></i> Settings 144 </a> 145 </li> 146 <li> 147 <details> 148 <summary class="text-lg md:text-base"> 149 <i class="fas fa-folder-open"></i> File 150 </summary> 151 <ul :class="['right-0 p-2 bg-base-100 shadow', { 'absolute': !isFullScreen }]"> 152 <li><a class="text-lg md:text-base" onclick="OpenFile()">Open File</a></li> 153 <li><a class="text-lg md:text-base" onclick="OpenFromUrl()">Open From Url</a></li> 154 <li><a class="text-lg md:text-base" onclick="window.open('preview/' + chat.params.chatId + '/index.html', '_blank')">Open Preview</a></li> 155 <li v-if="!isMobile"><a class="text-lg md:text-base" onclick="LoadFolder()">Open Folder</a></li> 156 <li v-if="!isMobile"><a class="text-lg md:text-base" onclick="SaveFolder()">Save Folder</a></li> 157 <li><a class="text-lg md:text-base hidden" onclick="OpenFromUrl()">Load from WebSim</a></li> 158 159 <li><a class="text-lg md:text-base" @click="messages=[]"> Clear Chat</a></li> 160 <li> 161 <a class="text-lg md:text-base" @click="ShareChat()"> 162 <i class="fas fa-share"></i> Share Project 163 </a> 164 </li> 165 <li><a class="text-lg md:text-base" href="apps.html">Landing page</a></li> 166 <li v-if="params.activeTab === 'preview' || !isFullScreen"> 167 <a class="text-lg md:text-base" @click="toggleEruda" class="flex items-center"> 168 <span class="font-semibold">Developer Console</span> 169 </a> 170 </li> 171 <li> 172 <a class="text-lg md:text-base" href="https://discord.gg/88fQT5Bgfe" target="_blank"> 173 <i class="fab fa-discord"></i> 174 <span>Bug Report</span> 175 </a> 176 </li> 177 </ul> 178 </details> 179 </li> 180 <li> 181 <details :open="isFullScreen"> 182 <summary class="text-lg md:text-base"> 183 <i class="fas fa-history"></i> Recent Chats 184 </summary> 185 186 <ul :class="['right-0 p-2 bg-base-100 shadow', { 'absolute': !isFullScreen }]"> 187 <li><a class="text-lg md:text-base" @click="bookmarkChat()">Bookmark Current Chat â </a></li> 188 <li v-for="chat in previousChats" :key="chat.id"> 189 <a class="text-lg md:text-base" @click="loadChat(chat.id)"> 190 <span class="font-bold"><span v-if="chat.id.startsWith('f')"> â </span> {{ chat.title || 'Untitled Chat' }}</span> 191 <span class="text-xs opacity-60">{{ new Date(chat.timestamp).toLocaleString() }}</span> 192 </a> 193 </li> 194 </ul> 195 </details> 196 </li> 197 <li> 198 <a class="text-lg md:text-base" @click="toggleTheme(!settings.isDarkTheme)"> 199 <i class="fas" :class="{ 'fa-sun': settings.isDarkTheme, 'fa-moon': !settings.isDarkTheme }"></i> 200 </a> 201 </li> 202 </ul> 203 204 </div> 205 </template> 206 207 </div> 208 209 <!-- Main content area --> 210 <div class="flex-1 flex flex-col lg:flex-row overflow-hidden"> 211 <!-- Chat --> 212 <div :class="['flex', { 'hidden lg:flex': isFullScreen && params.activeTab !== 'chat', 'lg:w-1/2 h-full': !isFullScreen, 'mobile-content': isFullScreen }]"> 213 <div class="fullscreen-button absolute right-0 m-4 z-10"> 214 <button @click="toggleFullScreen('chat')"> 215 <i class="fas fa-expand"></i> 216 </button> 217 </div> 218 <div class="flex flex-grow overflow-y-auto flex-col-reverse" id="chatMessages"> 219 <!-- input field container --> 220 <div class="bottom-0 left-0 right-0 p-4 transition-all duration-300 bg-base-2000" id="inputContainer" style="pointer-events: none;"> 221 <div style="pointer-events: auto;"> 222 <div class="flex overflow-x-auto gap-2 mb-2"> 223 <button v-for="(suggestion, index) in contact.suggestions.filter(s => !newMessage || s.name.toLowerCase().includes(newMessage.toLowerCase()))" :key="index" 224 class="btn btn-sm btn-outline bg-base-300" 225 @click="handleSuggestionClick(suggestion)">
226 <span class="truncate" style="max-width: 150px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;"> {{ suggestion.name }} </span> 227 </button> 228 </div> 229 <div class="join w-full"> 230 <textarea ref="messageInput" v-model="newMessage" :placeholder="lastMessage||'What app you want to create?'" 231 class="textarea textarea-bordered join-item flex-grow placeholder-gray-600" 232 233 @keydown.enter="(event) => { if (!event.shiftKey) { event.preventDefault(); sendMessage(); } }" rows="1"></textarea> 234 <button v-if="!processing" class="btn join-item" @click="sendMessage()"> 235 <i class="fas fa-paper-plane"></i> 236 </button> 237 <button v-else class="btn join-item" @click="stopProcessing()"> 238 <i class="fas fa-stop"></i> 239 </button> 240 <button v-if="!processing && newMessage !== '' " class="btn join-item" @click="newMessage = ''"> 241 <i class="fas fa-eraser"></i> 242 </button> 243 </div> 244 </div> 245 </div> 246 <div v-if="processing" class="flex items-center justify-center"> 247 <div class="loader"></div> 248 <span class="ml-2">Processing...</span> 249 </div> 250 <!-- chat messages --> 251 <div class="p-4 flex flex-col-reverse"> 252 <div v-for="(message, index) in messages.slice().reverse()" :key="index" :class="['chat', message.role === 'assistant' ? 'chat-end' : 'chat-start']" v-if="!message.hidden"> 253 <div class="chat-image avatar"> 254 <div class="w-10 rounded-full"> 255 <img v-if="message.role === 'assistant'" src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcT1DODTLlJPJ2PRmRmfmbWOiWR7uz42fcHQfQ&s" /> 256 <img v-else src="https://randomuser.me/api/portraits/men/32.jpg" /> 257 </div> 258 </div> 259 <div class="chat-header flex justify-between"> 260 {{ message.role }} 261 <time class="text-xs opacity-50">{{ new Date(message.timestamp).toLocaleTimeString() }}</time> 262 </div> 263 <div class="chat-bubble"> 264 <!-- Reasoning/Thinking content (collapsible, expanded by default) --> 265 <details v-if="message.reasoning && message.reasoning.trim()" class="reasoning-section mb-3 bg-base-300 rounded-lg p-3" open> 266 <summary class="cursor-pointer font-semibold text-sm flex items-center gap-2 select-none"> 267 <i class="fas fa-brain text-purple-400"></i> 268 <span>Thinking Process</span> 269 <span class="badge badge-sm badge-primary">{{ message.reasoning.length }} chars</span> 270 </summary> 271 <div v-html="renderMessage(message.reasoning)" class="overflow-hidden mt-2 text-sm opacity-90 max-h-96 overflow-y-auto prose prose-sm"></div> 272 </details> 273 274 <div v-html="renderMessage(message.content)" class="overflow-hidden"></div> 275 <div v-if="message.error" class="text-red-500 mt-2"> 276 {{ message.error }} 277 </div> 278 <div v-if="message.variants?.length" class="tabs tabs-boxed mb-2"> 279 <a v-for="(variant, index) in message.variants" :key="index" :title="variant.model" 280 class="tab" :class="{ 'tab-active': message.activeVariant === index }" 281 @click="setActiveVariant(message, index)"> 282 <div v-if="variant.error" class="fas fa-exclamation-triangle"></div> 283 <div v-else-if="!variant.finished" class="absolute inset-0 bg-green-500" :style="{ width: `${2+(variant.progress||0)*75}%`, top: '98%', marginLeft: '10px' }"></div> 284 Variant {{ index + 1 }} 285 </a> 286 </div> 287 </div> 288 <div class="chat-actions"> 289 <div class="dropdown" :class="message.role === 'assistant' ? 'dropdown-left dropdown-end' : 'dropdown-right dropdown-end'"> 290 <label tabindex="0" class="btn btn-ghost btn-xs"> 291 <i class="fa-solid fa-ellipsis-vertical"></i> 292 </label> 293 <ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52 z-10" onclick="document.activeElement.blur();"> 294 <li><a @click="editMessage(message)">Edit</a></li> 295 <li><a @click="deleteMessage(message)">Delete</a></li> 296 <li v-if="message.role !== 'assistant'"><a @click="resendMessage(message)">Resend</a></li> 297 <li v-else><a @click="continueMessage(message)">Continue</a></li> 298 <li><a @click="copyMessage(message)">Copy</a></li> 299 </ul> 300 </div> 301 </div> 302 </div> 303 <div v-if="!messages.length" class="welcome-message p-4 text-center"> 304 <h2 class="text-lg font-bold">{{ contact.welcomeMessage || 'Hello! What kind of app would you like to create today?' }}</h2> 305 <p class="text-sm">Feel free to ask anything or start a new conversation.</p> 306 </div> 307 </div> 308 309 310 </div> 311 </div> 312 313 <!-- Editor --> 314 <div :class="['lg:w-1/2 lg:flex lg:flex-col h-full', { 'hidden': isFullScreen && params.activeTab !== 'editor' && params.activeTab !== 'preview' }]"> 315 <div class="fullscreen-button absolute right-0 m-4 z-10"> 316 <button @click="toggleFullScreen('editor')"> 317 <i class="fas fa-expand"></i> 318 </button> 319 </div> 320 <div :class="[ 321 'lg:flex-1 ', 322 { 323 'hidden': isFullScreen && params.activeTab !== 'editor', 324 'mobile-content': isFullScreen 325 } 326 ]"> 327 328 <div class="editor-container"> 329 <div class="tabs-container"> 330 <div class="tabs"> 331 <a v-for="(file, index) in editorFiles" :key="index" v-if="!file.hidden" 332 :class="['tab tab-lifted', { 'tab-active': activeEditorTab === index }]" 333 @click="setActiveEditorTab(index)" 334 @dblclick="renameFile(index)"> 335 {{ file.name.replace('example', 'styles') }} 336 <button @click.stop="closeFile(file)" class="close-btn m-1" aria-label="Close file"> 337 <i class="fa-solid fa-xmark"></i> 338 </button> 339 </a> 340 <div class="dropdown"> 341 <label tabindex="0" class="btn btn-ghost btn-xs"> 342 <i class="fa-solid fa-plus"></i> 343 </label> 344 <ul tabindex="0" class="dropdown-content menu p-2 shadow bg-base-100 rounded-box w-52 z-10"> 345 <li><a @click="createNewFile()">New File</a></li> 346 <li><a onclick="OpenFile()">Open File</a></li> 347 <li><a onclick="OpenFromUrl()">Open From Url</a></li> 348 <li v-for="(file, index) in editorFiles" :key="index" v-if="file.hidden"> 349 <a @click="file.hidden=false">{{ file.name }}</a> 350 </li> 351 </ul> 352 </div> 353 </div> 354 355 </div> 356 <div class="monaco-container"> 357 <div id="monaco-editor"></div> 358 </div> 359 </div> 360 361 </div> 362 363 <!-- Preview --> 364 <div :class="[ 'lg:flex-1 ', { 'hidden': contact.noPreview || isFullScreen && params.activeTab !== 'preview', 'mobile-content': isFullScreen } ]"> 365 <div class="fullscreen-button absolute right-0 m-4 z-10"> 366 <button @click="toggleFullScreen('preview')"> 367 <i class="fas fa-expand"></i> 368 </button> 369 </div> 370 <div class="h-full flex flex-col"> 371 <div v-if="isFullScreen" class="p-4 bg-base-100/50"> 372 <div class="flex gap-4 items-center overflow-x-auto"> 373 <input type="text" 374 v-model="newMessage" 375 class="input flex-1 min-w-1 text-base-content placeholder-base-content/50 bg-transparent border-0 hover:border hover:border-base-content/30 focus:border focus:border-base-content/30 focus:outline-none focus:bg-base-100/50 backdrop-blur-[2px]" 376 :placeholder="lastMessage||'What app you want to create?'" 377 @keyup.enter="sendMessage()" 378 list="suggestions22"> 379 <datalist id="suggestions22"> 380 <option v-for="suggestion in contact.suggestions.map(s => s.name)" :value="suggestion"></option> 381 </datalist> 382 <div v-if="activeMessage?.variants?.length" class="tabs tabs-boxed flex-nowrap"> 383 <a v-for="(variant, index) in activeMessage.variants" :key="index" :title="variant.model" 384 class="tab shrink-0" :class="{ 'tab-active': activeMessage.activeVariant === index }" 385 @click="setActiveVariant(activeMessage, index)"> 386 <div v-if="variant.error" class="fas fa-exclamation-triangle"></div> 387 <div v-else-if="!variant.finished" class="absolute inset-0 bg-green-500" :style="{ width: `${2+(variant.progress||0)*75}%`, top: '98%', marginLeft: '10px' }"></div> 388 {{ index + 1 }} 389 </a> 390 </div> 391 </div> 392 </div> 393 <div class="flex-1 overflow-auto"> 394 <iframe id="html-preview" style="width: 100%; height: 100%; border: none;" src="preview/iframe.html"> 395 </iframe> 396 </div> 397 </div> 398 </div> 399 </div> 400 </div> 401 402 <!-- Mobile Navigation --> 403 <div class="btm-nav lg:hidden"> 404 <button :class="{ active: params.activeTab === 'chat' }" @click="setActiveTab('chat')"> 405 <i class="fas fa-comments"></i>
406 <span class="btm-nav-label">Chat</span> 407 </button> 408 <button :class="{ active: params.activeTab === 'editor' }" @click="setActiveTab('editor')"> 409 <i class="fas fa-code"></i> 410 <span class="btm-nav-label">Editor</span> 411 </button> 412 <button :class="{ active: params.activeTab === 'preview' }" @click="setActiveTab('preview')"> 413 <i class="fas fa-eye"></i> 414 <span class="btm-nav-label">Preview</span> 415 </button> 416 <label for="my-drawer" class="drawer-button flex flex-col items-center p-2 rounded-lg"> 417 <i class="fas fa-bars" aria-hidden="true"></i> 418 <span class="btm-nav-label">Menu</span> 419 </label> 420 </div> 421 422 <!-- Drawer --> 423 <div class="drawer"> 424 <input id="my-drawer" type="checkbox" class="drawer-toggle" /> 425 <div class="drawer-side"> 426 <label for="my-drawer" class="drawer-overlay"></label> 427 <ul class="menu p-4 w-80 h-full bg-base-200 text-base-content"> 428 <!-- Close button --> 429 430 <!-- Sidebar content here --> 431 <div data-template="menu-template-1"></div> 432 <label for="my-drawer" class="btn btn-sm absolute top-2">Close</label> 433 </ul> 434 </div> 435 </div> 436 </div> 437
437<script src="classes.js"></script>
437 438
438<script src="huggingFace.js"></script>
438 439
439<script src="utils.js"></script>
439 440
440<script src="syncDirectory.js"></script>
440 441
441<script src="engineer.js"></script>
441 442
442<script src="settings.js"></script>
442 443
443<script src="gptapi.js"></script>
443 444
444<script src="../localSettings.js"></script>
444 445
445<script src="settingsRenderer.js"></script>
445 446
446<script src="publish.js"></script>
446 447
447<script src="chatMore.js"></script>
447 448
448<script src="index.js"></script>
448 449 450
450<script> 451 document.addEventListener('click', function(event) { 452 if(chat.isMobile)return; 453 document.querySelectorAll('details').forEach(detail => { detail.removeAttribute('open');}); 454 }); 455 </script>
455 456 </body> 457 </html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.