|
@@ -2,32 +2,38 @@ const messagesEl = document.querySelector("#messages");
|
|
|
const statusEl = document.querySelector("#connection-status");
|
|
const statusEl = document.querySelector("#connection-status");
|
|
|
const chatForm = document.querySelector("#chat-form");
|
|
const chatForm = document.querySelector("#chat-form");
|
|
|
const userMessage = document.querySelector("#user-message");
|
|
const userMessage = document.querySelector("#user-message");
|
|
|
|
|
+const promptSetName = document.querySelector("#prompt-set-name");
|
|
|
|
|
+const savedPromptSets = document.querySelector("#saved-prompt-sets");
|
|
|
const systemPrompts = document.querySelector("#system-prompts");
|
|
const systemPrompts = document.querySelector("#system-prompts");
|
|
|
const preMessages = document.querySelector("#pre-messages");
|
|
const preMessages = document.querySelector("#pre-messages");
|
|
|
const preMessageTemplate = document.querySelector("#pre-message-template");
|
|
const preMessageTemplate = document.querySelector("#pre-message-template");
|
|
|
const toolList = document.querySelector("#tool-list");
|
|
const toolList = document.querySelector("#tool-list");
|
|
|
|
|
+const PROMPT_SETS_STORAGE_KEY = "agent-lab.prompt-sets.v1";
|
|
|
|
|
|
|
|
let socket = null;
|
|
let socket = null;
|
|
|
let activeAssistant = null;
|
|
let activeAssistant = null;
|
|
|
let runStartedAt = 0;
|
|
let runStartedAt = 0;
|
|
|
let firstTokenAt = 0;
|
|
let firstTokenAt = 0;
|
|
|
|
|
+let pendingEnabledTools = null;
|
|
|
|
|
|
|
|
document.querySelector("#add-system-prompt").addEventListener("click", () => {
|
|
document.querySelector("#add-system-prompt").addEventListener("click", () => {
|
|
|
- const textarea = document.createElement("textarea");
|
|
|
|
|
- textarea.className = "system-prompt";
|
|
|
|
|
- textarea.rows = 4;
|
|
|
|
|
- systemPrompts.append(textarea);
|
|
|
|
|
|
|
+ systemPrompts.append(createSystemPrompt(""));
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
document.querySelector("#add-pre-message").addEventListener("click", () => {
|
|
document.querySelector("#add-pre-message").addEventListener("click", () => {
|
|
|
- preMessages.append(preMessageTemplate.content.cloneNode(true));
|
|
|
|
|
|
|
+ preMessages.append(createPreMessage({ role: "user", content: "" }));
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+document.querySelector("#save-prompt-set").addEventListener("click", savePromptSet);
|
|
|
|
|
+document.querySelector("#load-prompt-set").addEventListener("click", loadPromptSet);
|
|
|
|
|
+document.querySelector("#delete-prompt-set").addEventListener("click", deletePromptSet);
|
|
|
|
|
+
|
|
|
chatForm.addEventListener("submit", (event) => {
|
|
chatForm.addEventListener("submit", (event) => {
|
|
|
event.preventDefault();
|
|
event.preventDefault();
|
|
|
runDebugSession();
|
|
runDebugSession();
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
|
|
+refreshPromptSetSelector();
|
|
|
loadTools();
|
|
loadTools();
|
|
|
|
|
|
|
|
async function loadTools() {
|
|
async function loadTools() {
|
|
@@ -63,6 +69,192 @@ function renderTools(tools) {
|
|
|
label.append(checkbox, ` ${tool.name}`);
|
|
label.append(checkbox, ` ${tool.name}`);
|
|
|
toolList.append(label);
|
|
toolList.append(label);
|
|
|
});
|
|
});
|
|
|
|
|
+
|
|
|
|
|
+ if (pendingEnabledTools) {
|
|
|
|
|
+ applySelectedTools(pendingEnabledTools);
|
|
|
|
|
+ pendingEnabledTools = null;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function savePromptSet() {
|
|
|
|
|
+ const name = promptSetName.value.trim();
|
|
|
|
|
+ if (!name) {
|
|
|
|
|
+ statusEl.textContent = "Set name required";
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const store = readPromptSets();
|
|
|
|
|
+ store.sets[name] = buildPromptSet();
|
|
|
|
|
+ writePromptSets(store);
|
|
|
|
|
+ refreshPromptSetSelector(name);
|
|
|
|
|
+ statusEl.textContent = "Prompt set saved";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function loadPromptSet() {
|
|
|
|
|
+ const name = savedPromptSets.value;
|
|
|
|
|
+ if (!name) {
|
|
|
|
|
+ statusEl.textContent = "Select a prompt set";
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const promptSet = readPromptSets().sets[name];
|
|
|
|
|
+ if (!promptSet) {
|
|
|
|
|
+ statusEl.textContent = "Prompt set not found";
|
|
|
|
|
+ refreshPromptSetSelector();
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ promptSetName.value = name;
|
|
|
|
|
+ restorePromptSet(promptSet);
|
|
|
|
|
+ statusEl.textContent = "Prompt set loaded";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function deletePromptSet() {
|
|
|
|
|
+ const name = savedPromptSets.value;
|
|
|
|
|
+ if (!name) {
|
|
|
|
|
+ statusEl.textContent = "Select a prompt set";
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const store = readPromptSets();
|
|
|
|
|
+ delete store.sets[name];
|
|
|
|
|
+ writePromptSets(store);
|
|
|
|
|
+ if (promptSetName.value.trim() === name) {
|
|
|
|
|
+ promptSetName.value = "";
|
|
|
|
|
+ }
|
|
|
|
|
+ refreshPromptSetSelector();
|
|
|
|
|
+ statusEl.textContent = "Prompt set deleted";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function buildPromptSet() {
|
|
|
|
|
+ return {
|
|
|
|
|
+ system_prompts: [...document.querySelectorAll(".system-prompt")]
|
|
|
|
|
+ .map((input) => input.value.trim())
|
|
|
|
|
+ .filter(Boolean),
|
|
|
|
|
+ pre_messages: [...document.querySelectorAll(".pre-message")]
|
|
|
|
|
+ .map((row) => ({
|
|
|
|
|
+ role: row.querySelector(".pre-role").value,
|
|
|
|
|
+ content: row.querySelector(".pre-content").value.trim(),
|
|
|
|
|
+ }))
|
|
|
|
|
+ .filter((message) => message.content),
|
|
|
|
|
+ chat_agent: {
|
|
|
|
|
+ model: document.querySelector("#model").value.trim(),
|
|
|
|
|
+ temperature: Number(document.querySelector("#temperature").value),
|
|
|
|
|
+ max_tokens: Number(document.querySelector("#max-tokens").value),
|
|
|
|
|
+ },
|
|
|
|
|
+ event_agent: {
|
|
|
|
|
+ enabled_tools: selectedTools(),
|
|
|
|
|
+ max_event_loops: Number(document.querySelector("#max-event-loops").value),
|
|
|
|
|
+ },
|
|
|
|
|
+ };
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function restorePromptSet(promptSet) {
|
|
|
|
|
+ restoreSystemPrompts(promptSet.system_prompts || []);
|
|
|
|
|
+ restorePreMessages(promptSet.pre_messages || []);
|
|
|
|
|
+
|
|
|
|
|
+ const chatAgent = promptSet.chat_agent || {};
|
|
|
|
|
+ document.querySelector("#model").value = chatAgent.model || "";
|
|
|
|
|
+ document.querySelector("#temperature").value = chatAgent.temperature ?? 0.2;
|
|
|
|
|
+ document.querySelector("#max-tokens").value = chatAgent.max_tokens ?? 800;
|
|
|
|
|
+
|
|
|
|
|
+ const eventAgent = promptSet.event_agent || {};
|
|
|
|
|
+ document.querySelector("#max-event-loops").value = eventAgent.max_event_loops ?? 3;
|
|
|
|
|
+ const enabledTools = eventAgent.enabled_tools || [];
|
|
|
|
|
+ pendingEnabledTools = applySelectedTools(enabledTools) ? null : enabledTools;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function restoreSystemPrompts(prompts) {
|
|
|
|
|
+ systemPrompts.textContent = "";
|
|
|
|
|
+ const values = prompts.length ? prompts : [""];
|
|
|
|
|
+ values.forEach((prompt) => {
|
|
|
|
|
+ systemPrompts.append(createSystemPrompt(prompt));
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function restorePreMessages(messages) {
|
|
|
|
|
+ preMessages.textContent = "";
|
|
|
|
|
+ messages.forEach((message) => {
|
|
|
|
|
+ preMessages.append(createPreMessage(message));
|
|
|
|
|
+ });
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function createSystemPrompt(value) {
|
|
|
|
|
+ const textarea = document.createElement("textarea");
|
|
|
|
|
+ textarea.className = "system-prompt";
|
|
|
|
|
+ textarea.rows = 4;
|
|
|
|
|
+ textarea.value = value;
|
|
|
|
|
+ return textarea;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function createPreMessage(message) {
|
|
|
|
|
+ const fragment = preMessageTemplate.content.cloneNode(true);
|
|
|
|
|
+ fragment.querySelector(".pre-role").value = message.role || "user";
|
|
|
|
|
+ fragment.querySelector(".pre-content").value = message.content || "";
|
|
|
|
|
+ return fragment;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function applySelectedTools(toolNames) {
|
|
|
|
|
+ const checkboxes = [...toolList.querySelectorAll(".tool-toggle")];
|
|
|
|
|
+ if (!checkboxes.length) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const selected = new Set(toolNames);
|
|
|
|
|
+ checkboxes.forEach((checkbox) => {
|
|
|
|
|
+ checkbox.checked = selected.has(checkbox.value);
|
|
|
|
|
+ });
|
|
|
|
|
+ return true;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function refreshPromptSetSelector(selectedName = "") {
|
|
|
|
|
+ const previousName = selectedName || savedPromptSets.value;
|
|
|
|
|
+ const names = Object.keys(readPromptSets().sets).sort();
|
|
|
|
|
+ savedPromptSets.textContent = "";
|
|
|
|
|
+
|
|
|
|
|
+ const placeholder = document.createElement("option");
|
|
|
|
|
+ placeholder.value = "";
|
|
|
|
|
+ placeholder.textContent = names.length ? "Select a set" : "No saved sets";
|
|
|
|
|
+ savedPromptSets.append(placeholder);
|
|
|
|
|
+
|
|
|
|
|
+ names.forEach((name) => {
|
|
|
|
|
+ const option = document.createElement("option");
|
|
|
|
|
+ option.value = name;
|
|
|
|
|
+ option.textContent = name;
|
|
|
|
|
+ savedPromptSets.append(option);
|
|
|
|
|
+ });
|
|
|
|
|
+
|
|
|
|
|
+ if (names.includes(previousName)) {
|
|
|
|
|
+ savedPromptSets.value = previousName;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function readPromptSets() {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const rawValue = localStorage.getItem(PROMPT_SETS_STORAGE_KEY);
|
|
|
|
|
+ if (!rawValue) {
|
|
|
|
|
+ return { sets: {} };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ const parsed = JSON.parse(rawValue);
|
|
|
|
|
+ if (
|
|
|
|
|
+ !parsed ||
|
|
|
|
|
+ typeof parsed !== "object" ||
|
|
|
|
|
+ !parsed.sets ||
|
|
|
|
|
+ typeof parsed.sets !== "object" ||
|
|
|
|
|
+ Array.isArray(parsed.sets)
|
|
|
|
|
+ ) {
|
|
|
|
|
+ return { sets: {} };
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return parsed;
|
|
|
|
|
+ } catch {
|
|
|
|
|
+ return { sets: {} };
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+function writePromptSets(store) {
|
|
|
|
|
+ localStorage.setItem(PROMPT_SETS_STORAGE_KEY, JSON.stringify(store));
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
function runDebugSession() {
|
|
function runDebugSession() {
|