mirror of
https://git.sync.wtf/troed/oc-ls-stats.git
synced 2026-08-31 09:43:38 +03:00
chore: v1.0.17 — detect llama-server from api.state.config.provider
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
+1
-1
@@ -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": {
|
||||
|
||||
@@ -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<string, unknown>)) {
|
||||
for (const [key, val] of Object.entries(provider as Record<string, unknown>)) {
|
||||
if (val && typeof val === "object") {
|
||||
const opts = (val as Record<string, unknown>).options
|
||||
if (opts && typeof opts === "object") {
|
||||
const baseURL = (opts as Record<string, unknown>).baseURL || (opts as Record<string, unknown>).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<TuiPlugin>[0]): Promise<string[]> {
|
||||
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({
|
||||
|
||||
Reference in New Issue
Block a user