Skip to content

Instantly share code, notes, and snippets.

@nickjuntilla
Created April 24, 2026 17:58
Show Gist options
  • Select an option

  • Save nickjuntilla/90ed74bc19b64a90a030078fe309c7c5 to your computer and use it in GitHub Desktop.

Select an option

Save nickjuntilla/90ed74bc19b64a90a030078fe309c7c5 to your computer and use it in GitHub Desktop.
In chrome console class for hooking up LM studio
let LLM = class {
constructor(config = {}) {
this.endpoint = 'http://localhost:1234/v1/chat/completions';
this.maxContextChars = config.maxContextChars || 30000;
this.history = [];
this.defaults = {
html: config.html !== undefined ? config.html : true,
js: config.js !== undefined ? config.js : false,
runJS: config.runJS !== undefined ? config.runJS : true
};
}
estimate(text) { return Math.ceil(text.length / 4); }
async m(userMessage, options = {}) {
const settings = { ...this.defaults, ...options };
let htmlPart = "";
let budget = this.maxContextChars;
// 1. GATHER CONTEXT (Priority: HTML)
if (settings.html) {
const pageText = document.body.innerText.substring(0, 8000);
const elements = Array.from(document.querySelectorAll('article, .article, h1, h2, h3, button, a'))
.map(el => `${el.tagName}: ${el.innerText.trim()}`)
.filter(t => t.length > 10).join('\n');
htmlPart = `[VISIBLE TEXT]\n${pageText}\n\n[PAGE STRUCTURE]\n${elements}`;
htmlPart = htmlPart.substring(0, budget);
budget -= htmlPart.length;
}
// 2. AGENT SYSTEM PROMPT
const systemPrompt = `You are a Browser Automation Agent. You are embedded in the user's browser console.
CONTEXT: You have access to the DOM.
GOAL: When the user asks for a change or data, provide a \`\`\`javascript code block to perform the action.
RULES:
- Use document.querySelectorAll() and loops for multiple replacements.
- For text changes, use: element.innerText = element.innerText.replace(/Old/g, 'New').
- If a specific action is requested (click, scroll, style change), write the JS for it.
- Always explain briefly what the code does before the block.`;
const messages = [
{ role: "system", content: systemPrompt },
...this.history,
{ role: "user", content: `CURRENT PAGE CONTEXT:\n${htmlPart}\n\nUSER REQUEST: ${userMessage}` }
];
// Log Context Stats
console.log(`%c[Context] Sending ~${this.estimate(htmlPart)} tokens to AI.`, "color: #999;");
try {
const response = await fetch(this.endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
messages,
model: "local-model",
temperature: 0.1 // Keep it precise for code generation
})
});
const data = await response.json();
const reply = data.choices[0].message.content;
console.log(`%cAI: ${reply}`, "color: #00ffcc; font-weight: bold;");
// 3. AUTO-EXECUTION LOGIC
if (settings.runJS) {
const codeMatch = reply.match(/```(?:javascript|js)\n([\s\S]*?)```/);
if (codeMatch && codeMatch[1]) {
const code = codeMatch[1].trim();
console.log(`%c[Executing JS]:`, "color: #ffff00; font-weight: bold;");
console.log(code);
try {
eval(code); // Runs the code in the context of the current page
console.log("%c[Success] Page updated.", "color: #00ff00;");
} catch (e) {
console.error("[JS Error] AI generated invalid code:", e);
}
}
}
// Update history (Clean version to save memory)
this.history.push({ role: "user", content: userMessage });
this.history.push({ role: "assistant", content: reply });
return reply;
} catch (err) {
console.error("Connection failed. Check LM Studio CORS settings.", err);
}
}
clear() { this.history = []; console.log("Memory cleared."); }
};
// Initialize
let chat = new LLM({ maxContextChars: 25000 });
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment