diff --git a/README.md b/README.md index 7eb13b4..24f3400 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ The plugin renders a single line in the session prompt right slot: ### Server Discovery -The plugin discovers the llama-server URL by reading the OpenCode configuration file (parsed as JSONC) and extracting `baseURL`/`base_url` fields from provider options that contain "localhost". Falls back to `http://localhost:8080`. +The plugin discovers the llama-server URL by reading the OpenCode configuration via the TUI API and extracting `baseURL`/`base_url` fields from provider options whose name contains "llama" (but excludes providers whose name contains "ollama"). Falls back to `http://localhost:8080` if no matching provider is found. ### Slot Polling diff --git a/package.json b/package.json index 6e2e424..dd5f2a7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/package.json", "name": "@troed/oc-ls-stats", - "version": "1.0.5", + "version": "1.0.17", "type": "module", "exports": { "./tui": { diff --git a/tui.tsx b/tui.tsx index 14cffe9..f74026f 100644 --- a/tui.tsx +++ b/tui.tsx @@ -49,70 +49,6 @@ function estimateStreamTokens(delta: string) { return Math.max(1, Math.ceil(Buffer.byteLength(delta, "utf8") / 5)) } -function parseJSONC(text: string): unknown { - let result = "" - let inString = false - let escape = false - let i = 0 - - while (i < text.length) { - const ch = text[i] - - if (escape) { - result += ch - escape = false - i++ - continue - } - - if (ch === "\\") { - result += ch - escape = true - i++ - continue - } - - if (ch === '"') { - result += ch - inString = !inString - i++ - continue - } - - if (inString) { - result += ch - i++ - continue - } - - if (ch === "/" && text[i + 1] === "/") { - while (i < text.length && text[i] !== "\n") i++ - continue - } - - if (ch === "/" && text[i + 1] === "*") { - i += 2 - while (i < text.length - 1 && !(text[i] === "*" && text[i + 1] === "/")) i++ - i += 2 - result += " " - continue - } - - if (ch === ",") { - const next = text.indexOf(/[\s}\]]/, i + 1) - if (next !== -1 && /[\s}\]]/.test(text[next])) { - i++ - continue - } - } - - result += ch - i++ - } - - return JSON.parse(result) -} - function stripBaseUrlPath(baseURL: string): string { try { const url = new URL(baseURL) @@ -129,12 +65,12 @@ function extractProviderUrls(config: unknown): string[] { if (!provider || typeof provider !== "object") return [] const urls: string[] = [] - for (const [_key, val] of Object.entries(provider as Record)) { + for (const [key, val] of Object.entries(provider as Record)) { if (val && typeof val === "object") { const opts = (val as Record).options if (opts && typeof opts === "object") { const baseURL = (opts as Record).baseURL || (opts as Record).base_url - if (typeof baseURL === "string" && baseURL.includes("localhost")) { + if (typeof baseURL === "string" && key.toLowerCase().includes("llama") && !key.toLowerCase().includes("ollama")) { urls.push(stripBaseUrlPath(baseURL)) } } @@ -145,13 +81,8 @@ function extractProviderUrls(config: unknown): string[] { async function loadConfigUrls(api: Parameters[0]): Promise { try { - const configPath = api.state.path.config - const resp = await fetch(`file://${configPath}`) - if (!resp.ok) return [] - const text = await resp.text() - const config = parseJSONC(text) - return extractProviderUrls(config) - } catch { + return extractProviderUrls(api.state.config as unknown) + } catch (e) { return [] } } @@ -280,7 +211,7 @@ const tui: TuiPlugin = async (api) => { bump() } - let llamaServerUrls: string[] = ["http://localhost:8080"] + let llamaServerUrls: string[] = [] let llamaServerModel: string | undefined const pollMetrics = async () => { @@ -313,8 +244,9 @@ const tui: TuiPlugin = async (api) => { continue } tracker.failure = null + bump() - debug(`poll baseUrl=${baseUrl} slots=${JSON.stringify(slotList)}`) + for (const slot of slotList) { if (slot?.is_processing) { @@ -324,7 +256,13 @@ const tui: TuiPlugin = async (api) => { for (const slotId of prevProcessingSlotIds) { if (!currProcessingSlotIds.has(slotId)) { - delete tracker.prevNdBySlot[slotId] + const prev = tracker.prevNdBySlot[slotId] + if (prev) { + prev.hasIncreased = false + prev.baseline = 0 + } else { + delete tracker.prevNdBySlot[slotId] + } } } @@ -375,7 +313,7 @@ const tui: TuiPlugin = async (api) => { tracker.prefillCapturedTokens = nt tracker.prefillStartAt = now tracker.lastPrefillRate = 0 - debug(`prefill new slot id=${slotId} nt=${nt}`) + } } else { if (tracker.isPrefilling) { @@ -396,7 +334,7 @@ const tui: TuiPlugin = async (api) => { const delta = nd - tracker.generatePrevNd if (dt > 0 && delta > 0) { tracker.lastGeneratedTps = delta / dt - debug(`gen slot=${slotId} nd=${nd} prev=${tracker.generatePrevNd} delta=${delta} dt=${dt.toFixed(2)} tps=${tracker.lastGeneratedTps.toFixed(1)}`) + } tracker.generatePrevNd = nd tracker.generateStartAt = now @@ -405,7 +343,7 @@ const tui: TuiPlugin = async (api) => { tracker.generatePrevNd = nd tracker.generateStartAt = now tracker.lastGeneratedTps = 0 - debug(`gen new slot id=${slotId} nd=${nd}`) + } } else { if (tracker.isGenerating) { @@ -414,7 +352,7 @@ const tui: TuiPlugin = async (api) => { tracker.generateStartAt = 0 tracker.lastGeneratedTps = 0 genEnded = true - debug(`gen no slot found ending`) + } } @@ -501,11 +439,11 @@ const tui: TuiPlugin = async (api) => { }) try { - if (!llamaServerUrls.length) { - llamaServerUrls = await loadConfigUrls(api) - } + const configUrls = await loadConfigUrls(api) + llamaServerUrls = configUrls.length > 0 ? configUrls : ["http://localhost:8080"] } catch (e) { console.error("[oc-ls-stats] loadConfigUrls error:", e) + llamaServerUrls = ["http://localhost:8080"] } api.slots.register({