godqhr1421's picture
Upload app.js
45e12ae verified
Raw
History Blame Contribute Delete
5.17 kB
const tools = [
{
type: "function",
function: {
name: "terminal",
description: "Run a shell command. This demo displays the request but does not execute it.",
parameters: {
type: "object",
properties: { command: { type: "string", description: "The command to run." } },
required: ["command"],
},
},
},
{
type: "function",
function: {
name: "read_file",
description: "Read a UTF-8 text file. This demo only displays the requested path.",
parameters: {
type: "object",
properties: { path: { type: "string", description: "Path of the file to read." } },
required: ["path"],
},
},
},
{
type: "function",
function: {
name: "web_search",
description: "Search the web. This demo displays the query but does not send it.",
parameters: {
type: "object",
properties: { query: { type: "string", description: "The search query." } },
required: ["query"],
},
},
},
];
const $ = (selector) => document.querySelector(selector);
const runButton = $("#run");
const status = $("#status");
const answer = $("#answer");
const calls = $("#calls");
const latency = $("#latency");
function parseValue(value) {
const trimmed = value.trim();
try { return JSON.parse(trimmed); } catch { return trimmed; }
}
function parseAtem(text) {
const parsed = [];
const invokes = text.matchAll(/<atem:invoke\s+name="([^"]+)">([\s\S]*?)<\/atem:invoke>/g);
for (const match of invokes) {
const argumentsObject = {};
for (const parameter of match[2].matchAll(/<atem:parameter\s+name="([^"]+)">([\s\S]*?)<\/atem:parameter>/g)) {
argumentsObject[parameter[1]] = parseValue(parameter[2]);
}
parsed.push({ name: match[1], arguments: argumentsObject });
}
return parsed;
}
function normalizeCalls(message) {
if (Array.isArray(message.tool_calls) && message.tool_calls.length) {
return message.tool_calls.map((call) => {
let argumentsObject = call.function?.arguments ?? {};
if (typeof argumentsObject === "string") {
try { argumentsObject = JSON.parse(argumentsObject); } catch { argumentsObject = { raw: argumentsObject }; }
}
return { name: call.function?.name ?? "unknown", arguments: argumentsObject };
});
}
return parseAtem(message.content ?? "");
}
function visibleContent(content) {
if (!content) return "No user-facing answer was produced. See the proposed tool call below.";
const withoutCalls = content.replace(/<atem:function_calls>[\s\S]*?<\/atem:function_calls>/g, "");
const withoutProtocol = withoutCalls.replace(/<\|[^>]+\|>/g, "").replace(/^\s*to=[^<\n]+/, "").trim();
return withoutProtocol || "No user-facing answer was produced. See the proposed tool call below.";
}
async function generate() {
const endpoint = $("#endpoint").value.trim().replace(/\/+$/, "");
const prompt = $("#prompt").value.trim();
if (!endpoint || !prompt) {
status.textContent = "Enter both a public endpoint and a request.";
return;
}
runButton.disabled = true;
status.textContent = "";
latency.textContent = "Generating…";
const started = performance.now();
try {
const response = await fetch(`${endpoint}/v1/chat/completions`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
model: "muse-glimmer-30b",
messages: [
{
role: "system",
content: `You are a helpful AI assistant. Reasoning strength: ${$("#reasoning").value}. Use a tool only when necessary. Never claim a tool succeeded because this demo does not execute tools. Confirm destructive actions.`,
},
{ role: "user", content: prompt },
],
tools,
temperature: Number($("#temperature").value),
top_p: 0.95,
max_tokens: Number($("#maxTokens").value),
}),
});
const payload = await response.json().catch(() => ({}));
if (!response.ok) throw new Error(payload.error?.message || `Endpoint returned HTTP ${response.status}.`);
const message = payload.choices?.[0]?.message;
if (!message) throw new Error("The endpoint response did not contain choices[0].message.");
const proposed = normalizeCalls(message);
answer.textContent = visibleContent(message.content);
answer.classList.remove("empty");
calls.textContent = JSON.stringify(proposed, null, 2);
latency.textContent = `${((performance.now() - started) / 1000).toFixed(1)} s · ${payload.usage?.completion_tokens ?? "?"} tokens`;
} catch (error) {
status.textContent = `${error.message} Check endpoint reachability, HTTPS, and CORS.`;
latency.textContent = "Request failed";
} finally {
runButton.disabled = false;
}
}
runButton.addEventListener("click", generate);
$("#prompt").addEventListener("keydown", (event) => {
if ((event.ctrlKey || event.metaKey) && event.key === "Enter") generate();
});
document.querySelectorAll("[data-prompt]").forEach((button) => {
button.addEventListener("click", () => { $("#prompt").value = button.dataset.prompt; });
});