import "pettyui/button"; import "pettyui/badge"; import "pettyui/text-field"; import "pettyui/select"; import { invoke } from "@tauri-apps/api/core"; type ProviderId = "anthropic" | "openai" | "google" | "groq" | "mistral" | "local"; type Strategy = { id: string; name: string; description: string; rationale: string; selected: boolean; }; type MutationRequest = { prompt: string; task?: string | null; provider: ProviderId; model?: string | null; enabled_strategy_ids?: string[] | null; }; type MutationVariant = { id: string; title: string; strategy_id: string; strategy_label: string; provider: string; mutated_prompt: string; why_it_may_help: string; score: number; }; type MutationResponse = { provider: string; model: string | null; provider_guidance: string; evaluation_rubric: string[]; variants: MutationVariant[]; }; const samplePrompt = `You are helping me write a launch announcement for a developer tool. Write something good about it.`; const sampleTask = `Write a launch announcement that sounds credible, sharp, and useful to developers.`; const strategyList = document.querySelector("#strategy-list")!; const promptInput = document.querySelector("#prompt-input")!; const taskInput = document.querySelector("#task-input")!; const modelInput = document.querySelector("#model-input")!; const providerInput = document.querySelector("input[name='provider']")!; const providerSelect = document.querySelector("#provider-select")!; const generateBtn = document.querySelector("#generate-btn")!; const sampleBtn = document.querySelector("#sample-btn")!; const copyBestBtn = document.querySelector("#copy-best-btn")!; const resultsGrid = document.querySelector("#results-grid")!; const resultCount = document.querySelector("#result-count")!; const selectedStrategyCount = document.querySelector("#selected-strategy-count")!; const strategyCount = document.querySelector("#strategy-count")!; const summaryStrip = document.querySelector("#summary-strip")!; let strategies: Strategy[] = []; let latestResponse: MutationResponse | null = null; function escapeHtml(value: string): string { return value .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """) .replaceAll("'", "'"); } function selectedIds(): string[] { return strategies.filter((strategy) => strategy.selected).map((strategy) => strategy.id); } function renderStrategies(): void { strategyList.innerHTML = strategies.map((strategy) => ` `).join(""); selectedStrategyCount.textContent = `${selectedIds().length} selected`; strategyCount.textContent = String(strategies.length); } function renderSummary(response: MutationResponse): void { summaryStrip.innerHTML = `
Provider guidance

${escapeHtml(response.provider_guidance)}

Evaluation rubric
    ${response.evaluation_rubric.map((item) => `
  • ${escapeHtml(item)}
  • `).join("")}
`; } function renderResults(response: MutationResponse): void { const sorted = [...response.variants].sort((a, b) => b.score - a.score); resultsGrid.innerHTML = sorted.map((variant, index) => `

${index === 0 ? "Best candidate" : `Rank ${index + 1}`}

${escapeHtml(variant.title)}

${variant.score}/100
${escapeHtml(variant.strategy_label)} ${escapeHtml(variant.provider)}

${escapeHtml(variant.why_it_may_help)}

${escapeHtml(variant.mutated_prompt)}
`).join(""); resultCount.textContent = `${response.variants.length} variants`; } async function loadStrategies(): Promise { strategies = await invoke("list_strategies"); renderStrategies(); } async function generateMutations(): Promise { const prompt = promptInput.value.trim(); if (!prompt) return; generateBtn.setAttribute("loading", ""); try { const response = await invoke("mutate_prompt", { request: { prompt, task: taskInput.value.trim() || null, provider: providerInput.value as ProviderId, model: modelInput.value.trim() || null, enabled_strategy_ids: selectedIds(), } satisfies MutationRequest, }); latestResponse = response; renderSummary(response); renderResults(response); } finally { generateBtn.removeAttribute("loading"); } } function loadSample(): void { promptInput.value = samplePrompt; taskInput.value = sampleTask; } async function copyBest(): Promise { const best = latestResponse?.variants.slice().sort((a, b) => b.score - a.score)[0]; if (!best) return; await navigator.clipboard.writeText(best.mutated_prompt); const button = copyBestBtn.querySelector("button"); if (!button) return; const old = button.textContent; button.textContent = "Copied"; window.setTimeout(() => { button.textContent = old ?? "Copy best"; }, 1500); } strategyList.addEventListener("change", (event) => { const target = event.target as HTMLInputElement | null; if (!target?.matches("input[data-strategy-id]")) return; strategies = strategies.map((strategy) => strategy.id === target.dataset.strategyId ? { ...strategy, selected: target.checked } : strategy); renderStrategies(); }); generateBtn.addEventListener("click", () => { void generateMutations(); }); sampleBtn.addEventListener("click", loadSample); copyBestBtn.addEventListener("click", () => { void copyBest(); }); providerSelect.addEventListener("petty-change", () => { const provider = providerInput.value as ProviderId; const defaults: Record = { anthropic: "claude-3-7-sonnet", openai: "gpt-4.1", google: "gemini-2.5-pro", groq: "llama-3.3-70b-versatile", mistral: "mistral-large", local: "llama3.2", }; modelInput.value = defaults[provider]; }); loadSample(); void loadStrategies().then(() => generateMutations());