summaryrefslogtreecommitdiff
path: root/src/ollama_web/static
diff options
context:
space:
mode:
Diffstat (limited to 'src/ollama_web/static')
-rw-r--r--src/ollama_web/static/app.js64
-rw-r--r--src/ollama_web/static/style.css10
2 files changed, 71 insertions, 3 deletions
diff --git a/src/ollama_web/static/app.js b/src/ollama_web/static/app.js
index 3240dcc..b9da89f 100644
--- a/src/ollama_web/static/app.js
+++ b/src/ollama_web/static/app.js
@@ -21,6 +21,34 @@ let currentSessionId = null;
let currentSession = null;
let pendingFiles = [];
let abortController = null;
+let currentCapabilities = new Set();
+
+function updateThinkToggleState() {
+ if (!thinkToggle) return;
+ if (currentCapabilities.has("thinking")) {
+ thinkToggle.disabled = false;
+ thinkToggle.parentElement.classList.remove("disabled");
+ } else {
+ thinkToggle.disabled = true;
+ thinkToggle.checked = false;
+ thinkToggle.parentElement.classList.add("disabled");
+ }
+}
+
+async function loadModelCapabilities() {
+ const model = modelSelect.value;
+ if (!model) return;
+ try {
+ const res = await fetch(`/api/models/${encodeURIComponent(model)}/capabilities`);
+ if (!res.ok) throw new Error(res.statusText);
+ const data = await res.json();
+ currentCapabilities = new Set((data.capabilities || []).map((c) => c.toLowerCase()));
+ } catch (err) {
+ console.error("failed to load model capabilities", err);
+ currentCapabilities = new Set();
+ }
+ updateThinkToggleState();
+}
function getCookie(name) {
const prefix = `${name}=`;
@@ -440,6 +468,8 @@ sessionListEl.addEventListener("click", (e) => {
}
});
+modelSelect.addEventListener("change", loadModelCapabilities);
+
async function send() {
const text = inputEl.value.trim();
if (!text && !pendingFiles.length) return;
@@ -669,9 +699,36 @@ inputEl.addEventListener("keydown", (e) => {
}
});
-clearBtn.addEventListener("click", () => {
- chatEl.innerHTML = "";
-});
+async function clearMessages() {
+ if (!currentSessionId) {
+ chatEl.innerHTML = "";
+ pendingFiles = [];
+ renderAttachments();
+ return;
+ }
+
+ try {
+ const res = await csrfFetch(`/api/sessions/${currentSessionId}/messages`, {
+ method: "DELETE",
+ });
+ if (!res.ok) throw new Error(res.statusText);
+ const data = await res.json();
+ if (!data.cleared) throw new Error("クリアに失敗しました");
+
+ if (currentSession) {
+ currentSession.messages = [];
+ currentSession.files = [];
+ }
+ pendingFiles = [];
+ chatEl.innerHTML = "";
+ renderAttachments();
+ } catch (err) {
+ console.error("failed to clear messages", err);
+ alert("メッセージのクリアに失敗しました");
+ }
+}
+
+clearBtn.addEventListener("click", clearMessages);
cancelBtn.addEventListener("click", () => {
if (abortController) {
@@ -680,3 +737,4 @@ cancelBtn.addEventListener("click", () => {
});
loadSessions();
+loadModelCapabilities();
diff --git a/src/ollama_web/static/style.css b/src/ollama_web/static/style.css
index 14dce76..24623c5 100644
--- a/src/ollama_web/static/style.css
+++ b/src/ollama_web/static/style.css
@@ -333,6 +333,16 @@ button { cursor: pointer; }
button:hover { border-color: var(--accent); }
.think-toggle { display: flex; align-items: center; gap: 4px; color: var(--muted); }
+.think-toggle.disabled,
+.think-toggle:has(input:disabled) {
+ color: var(--muted);
+ opacity: 0.5;
+ cursor: not-allowed;
+}
+.think-toggle.disabled input[type="checkbox"],
+.think-toggle:has(input:disabled) input[type="checkbox"] {
+ cursor: not-allowed;
+}
main#chat {
flex: 1;