Skip to content

Instantly share code, notes, and snippets.

@ZavierChambers
Created March 29, 2026 03:15
Show Gist options
  • Select an option

  • Save ZavierChambers/593b89bde72efbb1e43ccad3be9ec921 to your computer and use it in GitHub Desktop.

Select an option

Save ZavierChambers/593b89bde72efbb1e43ccad3be9ec921 to your computer and use it in GitHub Desktop.
Simple, reusable LM Studio client (OpenAI-compatible local API)
// lmstudio.js
// Simple, reusable LM Studio client (OpenAI-compatible local API)
const LMSTUDIO_BASE_URL = "http://localhost:1234/v1";
/**
* Non-streaming completion
*/
export async function lmChat({
messages,
temperature = 0.7,
model = "local-model"
}) {
const res = await fetch(`${LMSTUDIO_BASE_URL}/chat/completions`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
model,
messages,
temperature,
stream: false
})
});
if (!res.ok) {
throw new Error(`LM Studio error: ${res.status}`);
}
const data = await res.json();
return data.choices?.[0]?.message?.content || "";
}
/**
* Streaming completion (token-by-token)
*/
export async function lmStream({
messages,
onToken,
onDone,
onError,
model = "local-model"
}) {
try {
const res = await fetch(`${LMSTUDIO_BASE_URL}/chat/completions`, {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
model,
messages,
stream: true
})
});
if (!res.body) throw new Error("No response body");
const reader = res.body.getReader();
const decoder = new TextDecoder("utf-8");
let buffer = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop(); // keep incomplete line
for (const line of lines) {
if (!line.startsWith("data: ")) continue;
const json = line.replace("data: ", "").trim();
if (json === "[DONE]") {
onDone && onDone();
return;
}
try {
const parsed = JSON.parse(json);
const token = parsed.choices?.[0]?.delta?.content;
if (token) {
onToken && onToken(token);
}
} catch (err) {
// ignore partial JSON
}
}
}
onDone && onDone();
} catch (err) {
onError && onError(err);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment