Первый коммит
This commit is contained in:
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>
|
||||
|
After Width: | Height: | Size: 261 B |
+415
@@ -0,0 +1,415 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
font-family: var(--vscode-font-family);
|
||||
font-size: var(--vscode-font-size);
|
||||
color: var(--vscode-foreground);
|
||||
background: var(--vscode-sideBar-background);
|
||||
}
|
||||
|
||||
.chat-root {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
min-height: 200px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.chat-header {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
min-height: 44px;
|
||||
padding: 8px;
|
||||
border-bottom: 1px solid var(--vscode-widget-border, rgba(128, 128, 128, 0.35));
|
||||
background: var(--vscode-sideBar-background);
|
||||
}
|
||||
|
||||
.header-controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 6px;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.process-select-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.process-select-label {
|
||||
font-size: 0.78em;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.process-select-wrap select {
|
||||
min-width: 120px;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid var(--vscode-dropdown-border, var(--vscode-widget-border, rgba(128, 128, 128, 0.35)));
|
||||
background: var(--vscode-dropdown-background, var(--vscode-input-background));
|
||||
color: var(--vscode-dropdown-foreground, var(--vscode-input-foreground));
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.process-select-wrap select:focus {
|
||||
outline: 1px solid var(--vscode-focusBorder);
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
.header-session {
|
||||
flex: 1 1 320px;
|
||||
min-width: 220px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 6px;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid var(--vscode-widget-border, rgba(128, 128, 128, 0.35));
|
||||
border-radius: 4px;
|
||||
background: var(--vscode-sideBar-background);
|
||||
color: var(--vscode-descriptionForeground, var(--vscode-disabledForeground));
|
||||
font-size: 0.88em;
|
||||
line-height: 1.25;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.header-session:hover {
|
||||
border-color: var(--vscode-focusBorder, rgba(128, 128, 128, 0.6));
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.header-session:focus {
|
||||
outline: 1px solid var(--vscode-focusBorder, rgba(128, 128, 128, 0.6));
|
||||
outline-offset: 1px;
|
||||
}
|
||||
|
||||
.header-session.copied {
|
||||
border-color: var(--vscode-testing-iconPassed, #73c991);
|
||||
color: var(--vscode-testing-iconPassed, #73c991);
|
||||
}
|
||||
|
||||
.header-session-label {
|
||||
flex-shrink: 0;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.header-session-value {
|
||||
min-width: 0;
|
||||
white-space: normal;
|
||||
overflow-wrap: anywhere;
|
||||
word-break: break-word;
|
||||
font-family: var(--vscode-editor-font-family, var(--vscode-font-family));
|
||||
}
|
||||
|
||||
.header-spacer {
|
||||
flex: 999 1 auto;
|
||||
}
|
||||
|
||||
.btn {
|
||||
font-family: inherit;
|
||||
font-size: var(--vscode-font-size);
|
||||
padding: 4px 10px;
|
||||
cursor: pointer;
|
||||
border: 1px solid var(--vscode-button-border, transparent);
|
||||
background: var(--vscode-button-secondaryBackground);
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.btn:hover {
|
||||
background: var(--vscode-button-secondaryHoverBackground);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
background: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
min-width: 32px;
|
||||
padding: 4px 8px;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.menu-wrap {
|
||||
position: relative;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.menu-dropdown {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
right: 0;
|
||||
margin-top: 4px;
|
||||
min-width: 200px;
|
||||
padding: 4px 0;
|
||||
background: var(--vscode-menu-background);
|
||||
color: var(--vscode-menu-foreground);
|
||||
border: 1px solid var(--vscode-menu-border);
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
padding: 6px 12px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menu-item:hover {
|
||||
background: var(--vscode-menu-selectionBackground);
|
||||
color: var(--vscode-menu-selectionForeground);
|
||||
}
|
||||
|
||||
.chat-body {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.messages-pane {
|
||||
height: 100%;
|
||||
min-height: 0;
|
||||
padding: 8px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.status-blocks {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.status-block {
|
||||
border: 1px solid var(--vscode-widget-border, transparent);
|
||||
border-radius: 6px;
|
||||
background: color-mix(in srgb, var(--vscode-sideBar-background) 88%, var(--vscode-editor-inactiveSelectionBackground) 12%);
|
||||
color: color-mix(in srgb, var(--vscode-foreground) 62%, transparent);
|
||||
}
|
||||
|
||||
.status-block-title {
|
||||
padding: 6px 8px 4px;
|
||||
font-size: 0.86em;
|
||||
font-weight: 600;
|
||||
opacity: 0.85;
|
||||
border-bottom: 1px solid color-mix(in srgb, var(--vscode-widget-border, rgba(128, 128, 128, 0.35)) 70%, transparent);
|
||||
}
|
||||
|
||||
.status-block-body {
|
||||
max-height: 12.5em;
|
||||
overflow-y: auto;
|
||||
padding: 4px 8px 6px;
|
||||
font-size: 0.84em;
|
||||
line-height: 1.25;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.status-block-line + .status-block-line {
|
||||
margin-top: 2px;
|
||||
}
|
||||
|
||||
.messages {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.chat-footer {
|
||||
flex-shrink: 0;
|
||||
border-top: 1px solid var(--vscode-widget-border, rgba(128, 128, 128, 0.35));
|
||||
background: var(--vscode-sideBar-background);
|
||||
}
|
||||
|
||||
.input-pane {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 8px;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.input-pane textarea {
|
||||
min-height: 72px;
|
||||
max-height: 140px;
|
||||
resize: vertical;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
padding: 8px;
|
||||
border: 1px solid var(--vscode-input-border, var(--vscode-widget-border));
|
||||
background: var(--vscode-input-background);
|
||||
color: var(--vscode-input-foreground);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
.input-pane textarea:focus {
|
||||
outline: 1px solid var(--vscode-focusBorder);
|
||||
outline-offset: -1px;
|
||||
}
|
||||
|
||||
.input-actions {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.task-status {
|
||||
padding: 8px 10px;
|
||||
border: 1px solid var(--vscode-widget-border, transparent);
|
||||
border-radius: 6px;
|
||||
background: var(--vscode-editor-inactiveSelectionBackground, rgba(128, 128, 128, 0.12));
|
||||
}
|
||||
|
||||
.task-status-label,
|
||||
.rag-label {
|
||||
font-weight: 600;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.task-status-detail,
|
||||
.rag-detail,
|
||||
.rag-metrics {
|
||||
font-size: 0.92em;
|
||||
opacity: 0.88;
|
||||
}
|
||||
|
||||
.task-progress {
|
||||
margin-top: 8px;
|
||||
height: 6px;
|
||||
border-radius: 999px;
|
||||
overflow: hidden;
|
||||
background: var(--vscode-editorGroup-border, rgba(128, 128, 128, 0.15));
|
||||
}
|
||||
|
||||
.task-progress-bar {
|
||||
height: 100%;
|
||||
width: 0%;
|
||||
background: var(--vscode-progressBar-background, var(--vscode-button-background));
|
||||
}
|
||||
|
||||
.rag-status {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
padding: 8px 10px;
|
||||
border: 1px solid var(--vscode-widget-border, transparent);
|
||||
border-radius: 6px;
|
||||
background: color-mix(in srgb, var(--vscode-sideBar-background) 82%, var(--vscode-editor-inactiveSelectionBackground) 18%);
|
||||
}
|
||||
|
||||
.rag-status-main {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.rag-dot {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border-radius: 999px;
|
||||
margin-top: 4px;
|
||||
background: var(--vscode-disabledForeground);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.rag-dot.state-idle {
|
||||
background: var(--vscode-disabledForeground);
|
||||
}
|
||||
|
||||
.rag-dot.state-indexing {
|
||||
background: var(--vscode-charts-yellow, #d7ba7d);
|
||||
}
|
||||
|
||||
.rag-dot.state-ready {
|
||||
background: var(--vscode-testing-iconPassed, #73c991);
|
||||
}
|
||||
|
||||
.rag-dot.state-error {
|
||||
background: var(--vscode-testing-iconFailed, #f14c4c);
|
||||
}
|
||||
|
||||
.rag-text {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.msg {
|
||||
max-width: 95%;
|
||||
padding: 8px 10px;
|
||||
border-radius: 6px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.msg-user {
|
||||
align-self: flex-end;
|
||||
background: var(--vscode-textBlockQuote-background);
|
||||
border: 1px solid var(--vscode-widget-border, transparent);
|
||||
}
|
||||
|
||||
.msg-assistant {
|
||||
align-self: flex-start;
|
||||
background: var(--vscode-editor-inactiveSelectionBackground, rgba(128, 128, 128, 0.15));
|
||||
border: 1px solid var(--vscode-widget-border, transparent);
|
||||
}
|
||||
|
||||
.msg-error {
|
||||
align-self: stretch;
|
||||
background: color-mix(in srgb, var(--vscode-inputValidation-errorBackground, rgba(241, 76, 76, 0.18)) 90%, transparent);
|
||||
border: 1px solid var(--vscode-inputValidation-errorBorder, rgba(241, 76, 76, 0.7));
|
||||
}
|
||||
|
||||
.msg-status {
|
||||
align-self: stretch;
|
||||
padding: 0;
|
||||
border: none;
|
||||
background: transparent;
|
||||
color: var(--vscode-descriptionForeground, var(--vscode-disabledForeground));
|
||||
font-size: 0.9em;
|
||||
opacity: 0.9;
|
||||
line-height: 1.12;
|
||||
}
|
||||
|
||||
.msg-role {
|
||||
font-size: 0.75em;
|
||||
opacity: 0.8;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.msg-text,
|
||||
.msg-markdown {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
.msg-markdown {
|
||||
font-family: var(--vscode-editor-font-family, var(--vscode-font-family));
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src {{CSP}}; script-src {{CSP}};" />
|
||||
<link href="{{CSS_URI}}" rel="stylesheet" />
|
||||
</head>
|
||||
<body>
|
||||
<div class="chat-root">
|
||||
<header class="chat-header">
|
||||
<div class="header-controls">
|
||||
<button type="button" class="btn" id="btn-clear" title="Новая сессия">Новая сессия</button>
|
||||
<label class="process-select-wrap" for="process-version">
|
||||
<span class="process-select-label">Процесс</span>
|
||||
<select id="process-version" aria-label="Версия процесса агента">
|
||||
<option value="v1">v1</option>
|
||||
<option value="v2" selected>v2</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="header-session"
|
||||
id="header-rag-session"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
title="Кликните, чтобы скопировать RAG session id"
|
||||
aria-label="RAG session id"
|
||||
>
|
||||
<span class="header-session-label">RAG:</span>
|
||||
<span class="header-session-value" id="header-rag-session-value">—</span>
|
||||
</div>
|
||||
<div class="header-spacer"></div>
|
||||
<div class="menu-wrap">
|
||||
<button type="button" class="btn btn-icon" id="btn-menu" title="Меню" aria-haspopup="true" aria-expanded="false">⋯</button>
|
||||
<div class="menu-dropdown" id="menu-dropdown" hidden>
|
||||
<button type="button" class="menu-item" data-action="settings">Настройки (заглушка)</button>
|
||||
<button type="button" class="menu-item" data-action="about">О плагине (заглушка)</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="chat-body">
|
||||
<div class="messages-pane" id="feed-scroll">
|
||||
<div class="status-blocks" id="status-blocks"></div>
|
||||
<div class="messages" id="messages"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="chat-footer">
|
||||
<div class="input-pane">
|
||||
<div class="task-status" id="task-status" hidden>
|
||||
<div class="task-status-label" id="task-status-label"></div>
|
||||
<div class="task-status-detail" id="task-status-detail"></div>
|
||||
<div class="task-progress" id="task-progress" hidden>
|
||||
<div class="task-progress-bar" id="task-progress-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
<textarea id="input" rows="3" placeholder="Сообщение…" aria-label="Текст сообщения"></textarea>
|
||||
<div class="input-actions">
|
||||
<button type="button" class="btn btn-primary" id="btn-send">Отправить</button>
|
||||
</div>
|
||||
<div class="rag-status" id="rag-status">
|
||||
<div class="rag-status-main">
|
||||
<span class="rag-dot" id="rag-dot"></span>
|
||||
<div class="rag-text">
|
||||
<div class="rag-label" id="rag-label">RAG не готов</div>
|
||||
<div class="rag-detail" id="rag-detail">Ожидается индексация проекта.</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rag-metrics" id="rag-metrics"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{{JS_URI}}"></script>
|
||||
</body>
|
||||
</html>
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
(function () {
|
||||
const vscode = acquireVsCodeApi();
|
||||
|
||||
const feedScrollEl = document.getElementById("feed-scroll");
|
||||
const headerRagSessionEl = document.getElementById("header-rag-session");
|
||||
const headerRagSessionValueEl = document.getElementById("header-rag-session-value");
|
||||
const processVersionEl = document.getElementById("process-version");
|
||||
const statusBlocksEl = document.getElementById("status-blocks");
|
||||
const messagesEl = document.getElementById("messages");
|
||||
const inputEl = document.getElementById("input");
|
||||
const btnSend = document.getElementById("btn-send");
|
||||
const btnClear = document.getElementById("btn-clear");
|
||||
const btnMenu = document.getElementById("btn-menu");
|
||||
const menuDropdown = document.getElementById("menu-dropdown");
|
||||
const taskStatusEl = document.getElementById("task-status");
|
||||
const taskStatusLabelEl = document.getElementById("task-status-label");
|
||||
const taskStatusDetailEl = document.getElementById("task-status-detail");
|
||||
const taskProgressEl = document.getElementById("task-progress");
|
||||
const taskProgressBarEl = document.getElementById("task-progress-bar");
|
||||
const ragDotEl = document.getElementById("rag-dot");
|
||||
const ragLabelEl = document.getElementById("rag-label");
|
||||
const ragDetailEl = document.getElementById("rag-detail");
|
||||
const ragMetricsEl = document.getElementById("rag-metrics");
|
||||
let currentRagSessionId = "";
|
||||
|
||||
function renderStatusBlocks(items) {
|
||||
statusBlocksEl.innerHTML = "";
|
||||
(items || []).forEach(function (block) {
|
||||
const wrap = document.createElement("div");
|
||||
wrap.className = "status-block";
|
||||
|
||||
const title = document.createElement("div");
|
||||
title.className = "status-block-title";
|
||||
title.textContent = block.title || block.id || "Status";
|
||||
wrap.appendChild(title);
|
||||
|
||||
const body = document.createElement("div");
|
||||
body.className = "status-block-body";
|
||||
(block.lines || []).forEach(function (line) {
|
||||
const item = document.createElement("div");
|
||||
item.className = "status-block-line";
|
||||
item.textContent = line || "";
|
||||
body.appendChild(item);
|
||||
});
|
||||
wrap.appendChild(body);
|
||||
statusBlocksEl.appendChild(wrap);
|
||||
});
|
||||
}
|
||||
|
||||
function renderMessages(items) {
|
||||
messagesEl.innerHTML = "";
|
||||
(items || []).forEach(function (m) {
|
||||
const div = document.createElement("div");
|
||||
var roleClass = "msg-assistant";
|
||||
if (m.role === "user") {
|
||||
roleClass = "msg-user";
|
||||
} else if (m.role === "status") {
|
||||
roleClass = "msg-status";
|
||||
} else if (m.role === "error") {
|
||||
roleClass = "msg-error";
|
||||
}
|
||||
div.className = "msg " + roleClass;
|
||||
const text = document.createElement("div");
|
||||
text.className = m.kind === "markdown" ? "msg-markdown" : "msg-text";
|
||||
text.textContent = m.text || "";
|
||||
if (m.role !== "status") {
|
||||
const role = document.createElement("div");
|
||||
role.className = "msg-role";
|
||||
role.textContent =
|
||||
m.role === "user" ? "Вы" : m.role === "error" ? "Ошибка" : "Ответ";
|
||||
div.appendChild(role);
|
||||
}
|
||||
div.appendChild(text);
|
||||
messagesEl.appendChild(div);
|
||||
});
|
||||
}
|
||||
|
||||
function renderTaskStatus(status) {
|
||||
var visible = Boolean(status && status.visible);
|
||||
taskStatusEl.hidden = !visible;
|
||||
if (!visible) {
|
||||
taskProgressEl.hidden = true;
|
||||
taskProgressBarEl.style.width = "0%";
|
||||
return;
|
||||
}
|
||||
taskStatusLabelEl.textContent = status.label || "Статус";
|
||||
taskStatusDetailEl.textContent = status.detail || "";
|
||||
if (typeof status.progress === "number" && isFinite(status.progress)) {
|
||||
taskProgressEl.hidden = false;
|
||||
taskProgressBarEl.style.width = Math.max(0, Math.min(100, status.progress)) + "%";
|
||||
} else {
|
||||
taskProgressEl.hidden = true;
|
||||
taskProgressBarEl.style.width = "0%";
|
||||
}
|
||||
}
|
||||
|
||||
function renderRagStatus(status) {
|
||||
var state = (status && status.state) || "idle";
|
||||
var sessionId = (status && status.ragSessionId) || "";
|
||||
currentRagSessionId = sessionId;
|
||||
ragDotEl.className = "rag-dot state-" + state;
|
||||
ragLabelEl.textContent = (status && status.label) || "RAG не готов";
|
||||
ragDetailEl.textContent =
|
||||
(status && status.detail) || "Ожидается индексация проекта.";
|
||||
if (headerRagSessionEl && headerRagSessionValueEl) {
|
||||
headerRagSessionValueEl.textContent = sessionId || "—";
|
||||
headerRagSessionEl.title = sessionId
|
||||
? "Кликните, чтобы скопировать RAG session id"
|
||||
: "RAG session is not created yet.";
|
||||
}
|
||||
var metrics = [];
|
||||
if (status) {
|
||||
metrics.push("indexed: " + (status.indexedFiles || 0));
|
||||
metrics.push("failed: " + (status.failedFiles || 0));
|
||||
metrics.push("cache hit: " + (status.cacheHitFiles || 0));
|
||||
metrics.push("cache miss: " + (status.cacheMissFiles || 0));
|
||||
}
|
||||
ragMetricsEl.textContent = metrics.join(" | ");
|
||||
}
|
||||
|
||||
function renderState(state) {
|
||||
renderStatusBlocks(state.statusBlocks);
|
||||
renderMessages(state.messages);
|
||||
renderTaskStatus(state.taskStatus);
|
||||
renderRagStatus(state.ragStatus);
|
||||
if (processVersionEl && state && state.processVersion) {
|
||||
processVersionEl.value = state.processVersion;
|
||||
}
|
||||
btnSend.disabled = false;
|
||||
inputEl.disabled = false;
|
||||
btnClear.disabled = Boolean(state.busy);
|
||||
if (feedScrollEl) {
|
||||
feedScrollEl.scrollTop = feedScrollEl.scrollHeight;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener("message", function (event) {
|
||||
const msg = event.data;
|
||||
if (msg && msg.type === "state") {
|
||||
renderState(msg.payload || {});
|
||||
}
|
||||
});
|
||||
|
||||
function send() {
|
||||
const text = (inputEl.value || "").trim();
|
||||
if (!text) {
|
||||
return;
|
||||
}
|
||||
vscode.postMessage({ type: "send", text: text });
|
||||
inputEl.value = "";
|
||||
}
|
||||
|
||||
btnSend.addEventListener("click", send);
|
||||
inputEl.addEventListener("keydown", function (e) {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
send();
|
||||
}
|
||||
});
|
||||
|
||||
btnClear.addEventListener("click", function () {
|
||||
vscode.postMessage({ type: "clear" });
|
||||
});
|
||||
|
||||
processVersionEl.addEventListener("change", function () {
|
||||
vscode.postMessage({
|
||||
type: "set-process-version",
|
||||
value: processVersionEl.value || "v2",
|
||||
});
|
||||
});
|
||||
|
||||
async function copyRagSessionId() {
|
||||
if (!currentRagSessionId) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
if (navigator.clipboard && typeof navigator.clipboard.writeText === "function") {
|
||||
await navigator.clipboard.writeText(currentRagSessionId);
|
||||
} else {
|
||||
const helper = document.createElement("textarea");
|
||||
helper.value = currentRagSessionId;
|
||||
helper.style.position = "fixed";
|
||||
helper.style.opacity = "0";
|
||||
document.body.appendChild(helper);
|
||||
helper.focus();
|
||||
helper.select();
|
||||
document.execCommand("copy");
|
||||
document.body.removeChild(helper);
|
||||
}
|
||||
if (headerRagSessionEl) {
|
||||
headerRagSessionEl.classList.add("copied");
|
||||
window.setTimeout(function () {
|
||||
headerRagSessionEl.classList.remove("copied");
|
||||
}, 1200);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Failed to copy RAG session id", error);
|
||||
}
|
||||
}
|
||||
|
||||
headerRagSessionEl.addEventListener("click", function () {
|
||||
void copyRagSessionId();
|
||||
});
|
||||
|
||||
headerRagSessionEl.addEventListener("keydown", function (event) {
|
||||
if (event.key === "Enter" || event.key === " ") {
|
||||
event.preventDefault();
|
||||
void copyRagSessionId();
|
||||
}
|
||||
});
|
||||
|
||||
btnMenu.addEventListener("click", function (e) {
|
||||
e.stopPropagation();
|
||||
const open = menuDropdown.hidden;
|
||||
menuDropdown.hidden = !open;
|
||||
btnMenu.setAttribute("aria-expanded", open ? "true" : "false");
|
||||
});
|
||||
|
||||
document.addEventListener("click", function () {
|
||||
if (!menuDropdown.hidden) {
|
||||
menuDropdown.hidden = true;
|
||||
btnMenu.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
});
|
||||
|
||||
menuDropdown.addEventListener("click", function (e) {
|
||||
e.stopPropagation();
|
||||
const t = e.target;
|
||||
if (t && t.classList && t.classList.contains("menu-item")) {
|
||||
const action = t.getAttribute("data-action") || "";
|
||||
vscode.postMessage({ type: "menu", action: action });
|
||||
menuDropdown.hidden = true;
|
||||
btnMenu.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
});
|
||||
|
||||
vscode.postMessage({ type: "ready" });
|
||||
})();
|
||||
Reference in New Issue
Block a user