|
107 | 107 | border: 1px solid var(--vscode-inputValidation-errorBorder); |
108 | 108 | } |
109 | 109 |
|
| 110 | + #welcome[hidden] { |
| 111 | + display: none; |
| 112 | + } |
| 113 | + |
| 114 | + .welcome-card { |
| 115 | + padding: 14px 16px; |
| 116 | + border: 1px solid var(--vscode-input-border, var(--vscode-widget-border)); |
| 117 | + border-radius: 12px; |
| 118 | + background: var(--vscode-editor-inactiveSelectionBackground); |
| 119 | + } |
| 120 | + |
| 121 | + .welcome-card h2 { |
| 122 | + margin: 0 0 6px; |
| 123 | + font-size: 16px; |
| 124 | + line-height: 1.25; |
| 125 | + } |
| 126 | + |
| 127 | + .welcome-card h3 { |
| 128 | + margin: 14px 0 6px; |
| 129 | + font-size: 11px; |
| 130 | + font-weight: 600; |
| 131 | + letter-spacing: 0.6px; |
| 132 | + text-transform: uppercase; |
| 133 | + color: var(--vscode-descriptionForeground); |
| 134 | + } |
| 135 | + |
| 136 | + .welcome-card p { |
| 137 | + margin: 0 0 10px; |
| 138 | + color: var(--vscode-descriptionForeground); |
| 139 | + } |
| 140 | + |
| 141 | + .welcome-steps, |
| 142 | + .welcome-bullets { |
| 143 | + margin: 0 0 8px 18px; |
| 144 | + padding: 0; |
| 145 | + } |
| 146 | + |
| 147 | + .welcome-steps li, |
| 148 | + .welcome-bullets li { |
| 149 | + margin: 4px 0; |
| 150 | + } |
| 151 | + |
| 152 | + .welcome-bullets b { |
| 153 | + color: var(--vscode-foreground); |
| 154 | + } |
| 155 | + |
| 156 | + .welcome-bullets code { |
| 157 | + font-family: var(--vscode-editor-font-family, monospace); |
| 158 | + font-size: 0.92em; |
| 159 | + padding: 1px 4px; |
| 160 | + border-radius: 4px; |
| 161 | + background: var(--vscode-textCodeBlock-background, rgba(127, 127, 127, 0.12)); |
| 162 | + } |
| 163 | + |
| 164 | + .welcome-tip { |
| 165 | + margin: 12px 0 0; |
| 166 | + padding: 8px 10px; |
| 167 | + border-radius: 6px; |
| 168 | + background: var(--vscode-textCodeBlock-background, rgba(127, 127, 127, 0.08)); |
| 169 | + color: var(--vscode-foreground); |
| 170 | + font-size: 0.95em; |
| 171 | + } |
| 172 | + |
| 173 | + .welcome-actions { |
| 174 | + display: flex; |
| 175 | + gap: 10px; |
| 176 | + align-items: center; |
| 177 | + flex-wrap: wrap; |
| 178 | + } |
| 179 | + |
| 180 | + .welcome-actions .primary { |
| 181 | + padding: 6px 12px; |
| 182 | + border: 0; |
| 183 | + border-radius: 7px; |
| 184 | + cursor: pointer; |
| 185 | + font: inherit; |
| 186 | + color: var(--vscode-button-foreground); |
| 187 | + background: var(--vscode-button-background); |
| 188 | + } |
| 189 | + |
| 190 | + .welcome-actions .primary:hover { |
| 191 | + background: var(--vscode-button-hoverBackground); |
| 192 | + } |
| 193 | + |
| 194 | + .welcome-actions .link { |
| 195 | + padding: 6px 4px; |
| 196 | + border: 0; |
| 197 | + background: transparent; |
| 198 | + cursor: pointer; |
| 199 | + font: inherit; |
| 200 | + color: var(--vscode-descriptionForeground); |
| 201 | + text-decoration: underline; |
| 202 | + } |
| 203 | + |
| 204 | + .welcome-actions .link:hover { |
| 205 | + color: var(--vscode-foreground); |
| 206 | + } |
| 207 | + |
110 | 208 | .composer-wrap { |
111 | 209 | position: relative; |
112 | 210 | display: grid; |
|
392 | 490 | <body> |
393 | 491 | <main> |
394 | 492 | <section id="transcript" aria-live="polite"></section> |
| 493 | + <section id="welcome" hidden> |
| 494 | + <div class="welcome-card"> |
| 495 | + <h2>Welcome to CodeSetu</h2> |
| 496 | + <p> |
| 497 | + A privacy-aware, open-source AI coding assistant. |
| 498 | + <b>Bring your own model</b> — Sarvam, Hugging Face, or any OpenAI-compatible API |
| 499 | + (Ollama, vLLM, local). Your key is stored in the OS keychain; your prompts go only to |
| 500 | + the provider you configure. |
| 501 | + </p> |
| 502 | + |
| 503 | + <h3>Get started in 30 seconds</h3> |
| 504 | + <ol class="welcome-steps"> |
| 505 | + <li>Click <b>Configure provider</b> below.</li> |
| 506 | + <li>Pick a provider, paste your API key (stored in the OS keychain).</li> |
| 507 | + <li>Type a question and hit send.</li> |
| 508 | + </ol> |
| 509 | + |
| 510 | + <div class="welcome-actions"> |
| 511 | + <button id="welcome-configure" type="button" class="primary">Configure provider</button> |
| 512 | + <button id="welcome-docs" type="button" class="link">Learn more</button> |
| 513 | + </div> |
| 514 | + |
| 515 | + <h3>What you can do</h3> |
| 516 | + <ul class="welcome-bullets"> |
| 517 | + <li> |
| 518 | + <b>Repo-aware chat</b> — your active file and selection are attached automatically. |
| 519 | + Toggle this off any time from the <b>+</b> menu in the composer. |
| 520 | + </li> |
| 521 | + <li> |
| 522 | + <b>Selected-code actions</b> — select code, right-click, then pick |
| 523 | + <i>Explain / Refactor / Write Tests / Fix Bug / Add Docs with CodeSetu</i>. |
| 524 | + </li> |
| 525 | + <li> |
| 526 | + <b>Switch on the fly</b> — click the <b>provider · model</b> chip in the composer to |
| 527 | + change models or providers without leaving the chat. |
| 528 | + </li> |
| 529 | + <li> |
| 530 | + <b>Workspace skills</b> — drop <code>.codesetu/skills/*.md</code> files at the project |
| 531 | + root; they're folded into the system prompt for every message. |
| 532 | + </li> |
| 533 | + </ul> |
| 534 | + |
| 535 | + <h3>Try these prompts</h3> |
| 536 | + <ul class="welcome-bullets"> |
| 537 | + <li> |
| 538 | + <b>Understand:</b> “Explain what this file does and how the main function fits |
| 539 | + in.” |
| 540 | + </li> |
| 541 | + <li> |
| 542 | + <b>Refactor:</b> “Refactor the selected function for readability without |
| 543 | + changing behavior. List the changes.” |
| 544 | + </li> |
| 545 | + <li> |
| 546 | + <b>Test:</b> “Write unit tests for the selected function — happy path plus edge |
| 547 | + cases.” |
| 548 | + </li> |
| 549 | + <li> |
| 550 | + <b>Debug:</b> “Why might this function throw a null-pointer exception? Give the |
| 551 | + smallest safe fix.” |
| 552 | + </li> |
| 553 | + <li> |
| 554 | + <b>Document:</b> “Add JSDoc comments to the selected function — describe each |
| 555 | + parameter and the return value.” |
| 556 | + </li> |
| 557 | + <li> |
| 558 | + <b>Translate:</b> “Translate the selected Python snippet to TypeScript with |
| 559 | + equivalent types.” |
| 560 | + </li> |
| 561 | + <li> |
| 562 | + <b>Generate:</b> “Generate a regex that matches Indian phone numbers (+91, 10 |
| 563 | + digits, optional spaces).” |
| 564 | + </li> |
| 565 | + </ul> |
| 566 | + |
| 567 | + <p class="welcome-tip"> |
| 568 | + <b>Tip:</b> Open the <b>+</b> menu in the composer to toggle |
| 569 | + <b>Include IDE context</b> off when asking a general question — keeps prompts small and |
| 570 | + your code out of the request. |
| 571 | + </p> |
| 572 | + </div> |
| 573 | + </section> |
395 | 574 | <form id="chat-form" class="composer-wrap"> |
396 | 575 | <div class="composer-shell"> |
397 | 576 | <textarea id="message" aria-label="Message" placeholder="Ask CodeSetu"></textarea> |
|
471 | 650 | const includeContext = document.getElementById("include-context"); |
472 | 651 | const modelChip = document.getElementById("model-chip"); |
473 | 652 | const modelLabel = document.getElementById("model-label"); |
| 653 | + const welcome = document.getElementById("welcome"); |
| 654 | + const welcomeConfigure = document.getElementById("welcome-configure"); |
| 655 | + const welcomeDocs = document.getElementById("welcome-docs"); |
474 | 656 | let activeAssistantMessage; |
475 | 657 | let activeAssistantRaw = ""; |
476 | 658 |
|
|
589 | 771 | message.textContent = text; |
590 | 772 | } |
591 | 773 | transcript.appendChild(message); |
| 774 | + // First real message hides the welcome panel for the rest of the session. |
| 775 | + welcome.hidden = true; |
592 | 776 | message.scrollIntoView({ block: "end", behavior: "smooth" }); |
593 | 777 | return message; |
594 | 778 | } |
|
623 | 807 | post({ type: "selectModel" }); |
624 | 808 | }); |
625 | 809 |
|
| 810 | + welcomeConfigure.addEventListener("click", () => { |
| 811 | + post({ type: "configureProvider" }); |
| 812 | + }); |
| 813 | + |
| 814 | + welcomeDocs.addEventListener("click", () => { |
| 815 | + post({ type: "openUrl", url: "https://github.com/getcodesetu/codesetu" }); |
| 816 | + }); |
| 817 | + |
626 | 818 | document.addEventListener("click", (event) => { |
627 | 819 | const target = event.target; |
628 | 820 | if (!(target instanceof Element)) { |
|
681 | 873 | modelLabel.textContent = message.text; |
682 | 874 | } |
683 | 875 |
|
| 876 | + if (message.type === "welcome") { |
| 877 | + welcome.hidden = !message.show; |
| 878 | + } |
| 879 | + |
684 | 880 | if (message.type === "busy") { |
685 | 881 | const isBusy = Boolean(message.value); |
686 | 882 | send.disabled = isBusy; |
|
0 commit comments