From e771a0d9bb9508fdbbab8b3c19e93a0cc3da0d2d Mon Sep 17 00:00:00 2001 From: elainefan331 Date: Fri, 9 Oct 2026 15:21:43 -0400 Subject: [PATCH 1/2] feat(ollama): move AI panel to shui with server and model set in .env; --- backend/src/controllers/ollama.controller.js | 9 +++++++-- .../User/Dashboard/DatasetOrganizer/LLMPanel.tsx | 4 ++-- src/services/ollama.service.ts | 13 ++++++++++--- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/backend/src/controllers/ollama.controller.js b/backend/src/controllers/ollama.controller.js index fe0c4e8..2253de1 100644 --- a/backend/src/controllers/ollama.controller.js +++ b/backend/src/controllers/ollama.controller.js @@ -1,5 +1,10 @@ -const OLLAMA_BASE_URL = "http://jin.neu.edu:11434"; -const OLLAMA_MODEL = "qwen3.6:27b"; +// Ollama server + model come from .env, so switching needs no code change: +// OLLAMA_BASE_URL=http://shui.neu.edu:11434 +// OLLAMA_MODEL=qwen3.8-careful:latest +const OLLAMA_BASE_URL = ( + process.env.OLLAMA_BASE_URL || "http://shui.neu.edu:11434" +).replace(/\/+$/, ""); +const OLLAMA_MODEL = process.env.OLLAMA_MODEL || "qwen3.8-careful:latest"; const proxyChat = async (req, res) => { console.log("🟣 [Ollama] proxyChat hit — model:", OLLAMA_MODEL); diff --git a/src/components/User/Dashboard/DatasetOrganizer/LLMPanel.tsx b/src/components/User/Dashboard/DatasetOrganizer/LLMPanel.tsx index 63cc92f..ffdb7ee 100644 --- a/src/components/User/Dashboard/DatasetOrganizer/LLMPanel.tsx +++ b/src/components/User/Dashboard/DatasetOrganizer/LLMPanel.tsx @@ -66,7 +66,7 @@ const llmProviders: Record = { name: "Ollama (NeuroJSON Server)", baseUrl: "", models: [ - { id: "qwen3.6:27b", name: "Qwen 3.6 27B" }, + { id: "qwen3.8-careful:latest", name: "Qwen 3.8 Careful" }, // { id: "qwen3-coder-next:latest", name: "Qwen 3 Coder Next" }, // { id: "qwen3-coder-careful:latest", name: "Qwen 3 Coder Careful" }, // { id: "qwen3.5:9b", name: "Qwen 3.5 9B" }, @@ -1461,7 +1461,7 @@ const LLMPanel: React.FC = ({ {provider === "ollama" && ( - Using qwen3.6:27b on NeuroJSON server + Using Qwen 3.8 Careful on NeuroJSON server )} diff --git a/src/services/ollama.service.ts b/src/services/ollama.service.ts index f725687..7a23b01 100644 --- a/src/services/ollama.service.ts +++ b/src/services/ollama.service.ts @@ -15,6 +15,9 @@ export const OllamaService = { // const temperature = getQwenTemperature(model); const response = await fetch(`${API_URL}/ollama/bidsify`, { method: "POST", + // Send the login cookie: /ollama/bidsify requires login, and locally the + // API (localhost:5000) is a different origin from the page. + credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ model, @@ -29,19 +32,23 @@ export const OllamaService = { const data = await response.json(); if (!response.ok) { - throw new Error(data.error || "Failed to call Ollama"); + throw new Error(data.error || data.message || "Failed to call Ollama"); } return data; }, getTags: async (): Promise => { - const response = await fetch(`${API_URL}/ollama/tags`); + const response = await fetch(`${API_URL}/ollama/tags`, { + credentials: "include", + }); const data = await response.json(); if (!response.ok) { - throw new Error(data.error || "Failed to fetch Ollama models"); + throw new Error( + data.error || data.message || "Failed to fetch Ollama models" + ); } return data; From d04a79635afc06f0cbabfc148e0f547062c606dd Mon Sep 17 00:00:00 2001 From: elainefan331 Date: Mon, 12 Oct 2026 11:15:28 -0400 Subject: [PATCH 2/2] fix(download): make the dataset download scripts runnable and safe --- src/pages/UpdatedDatasetDetailPage.tsx | 47 +++++++++++++++++++++----- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src/pages/UpdatedDatasetDetailPage.tsx b/src/pages/UpdatedDatasetDetailPage.tsx index 835a6b5..d986818 100644 --- a/src/pages/UpdatedDatasetDetailPage.tsx +++ b/src/pages/UpdatedDatasetDetailPage.tsx @@ -619,16 +619,39 @@ const UpdatedDatasetDetailPage: React.FC = () => { }), ]; - // Bash script (Mac/Linux) + // Shell-safe single quoting: ' → '\'' (nothing inside '…' is expanded). + const shq = (s?: string) => `'${(s ?? "").replace(/'/g, `'\\''`)}'`; + // Batch: % must be doubled (else %20 etc. are read as variables); + // a " can't be quoted safely, so such items are skipped below. + const batq = (s?: string) => `"${(s ?? "").replace(/%/g, "%%")}"`; + // Only plain relative paths inside the download folder: no leading /, + // no "..", no backslash, no control characters. Others → file-. + const safeName = (name: string) => + !!name && + !name.startsWith("/") && + !name.includes("\\") && + !/[\x00-\x1f\x7f]/.test(name) && + !name.split("/").some((part) => part === ".." || part === ""); + const safeItems = items.map((it, i) => ({ + ...it, + filename: safeName(it.filename) ? it.filename : `file-${i}`, + })); + + // Bash script (Mac/Linux). --create-dirs makes the sub-01/anat/… folders. const sh = `#!/bin/bash\n` + `# Downloads ${docId} from ${dbName}\n` + `# Usage: bash ${docId}.sh\n` + `set -e\n` + - `mkdir -p "${docId}"\n` + - `cd "${docId}" || exit 1\n` + - items - .map((it) => `curl -L -C - -o "${it.filename}" "${it.url}"`) + `mkdir -p ${shq(docId)}\n` + + `cd ${shq(docId)} || exit 1\n` + + safeItems + .map( + (it) => + `curl -L -C - --create-dirs -o ${shq(it.filename)} ${shq( + it.url + )}` + ) .join("\n") + `\necho "Done. Files saved to $(pwd)"\n`; @@ -637,10 +660,16 @@ const UpdatedDatasetDetailPage: React.FC = () => { `@echo off\r\n` + `REM Downloads ${docId} from ${dbName}\r\n` + `REM Usage: double-click or run ${docId}.bat\r\n` + - `if not exist "${docId}" mkdir "${docId}"\r\n` + - `cd /d "${docId}"\r\n` + - items - .map((it) => `curl -L -C - -o "${it.filename}" "${it.url}"`) + `if not exist ${batq(docId)} mkdir ${batq(docId)}\r\n` + + `cd /d ${batq(docId)}\r\n` + + safeItems + .filter((it) => !it.filename.includes('"') && !it.url.includes('"')) + .map( + (it) => + `curl -L -C - --create-dirs -o ${batq(it.filename)} ${batq( + it.url + )}` + ) .join("\r\n") + `\r\necho Done. Files saved to %cd%\r\n` + `pause\r\n`;