agent: foundation — sync incremental changes from legacy codebase

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
jake
2026-03-21 10:50:32 +00:00
parent 387e7d7acc
commit 4c0fd0aeda
10 changed files with 22 additions and 15 deletions

View File

@@ -71,7 +71,7 @@ static ALL_MODELS: LazyLock<Vec<ModelEntry>> = LazyLock::new(|| {
languages: LanguageSupport::EnglishOnly,
files: vec![
ModelFile {
filename: "model_int8.onnx",
filename: "encoder-model.onnx",
url: "https://huggingface.co/onnx-community/parakeet-ctc-0.6b-ONNX/resolve/main/onnx/model_int8.onnx",
size: Megabytes(1),
},

View File

@@ -91,7 +91,7 @@ async fn download_file(
);
let client = reqwest::Client::builder()
.timeout(std::time::Duration::from_secs(30))
.connect_timeout(std::time::Duration::from_secs(30))
.build()
.map_err(|e| KonError::DownloadFailed(e.to_string()))?;

View File

@@ -123,6 +123,7 @@ pub async fn transcribe_pcm_parakeet(
remove_fillers: bool,
british_english: bool,
anti_hallucination: bool,
format_mode: String,
) -> Result<(), String> {
let engine = state.parakeet_engine.clone();
let audio = kon_core::AudioSamples::mono_16khz(samples);
@@ -141,7 +142,7 @@ pub async fn transcribe_pcm_parakeet(
remove_fillers,
british_english,
anti_hallucination,
format_mode: FormatMode::parse("Clean"),
format_mode: FormatMode::parse(&format_mode),
},
);

View File

@@ -322,6 +322,7 @@
removeFillers: settings.removeFillers,
britishEnglish: settings.britishEnglish,
antiHallucination: settings.antiHallucination,
formatMode: settings.formatMode,
});
} else {
await invoke("transcribe_pcm", {

View File

@@ -124,7 +124,8 @@
if (!fileTranscript) return;
showExportMenu = false;
const content = exportTranscript(fileTranscript, segments, format);
const ext = format === "vtt" ? "vtt" : format === "srt" ? "srt" : format === "md" ? "md" : "txt";
const extMap = { vtt: "vtt", srt: "srt", md: "md", csv: "csv", html: "html" };
const ext = extMap[format] || "txt";
const blob = new Blob([content], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
@@ -230,7 +231,7 @@
>Export</button>
{#if showExportMenu}
<div class="absolute left-0 bottom-full mb-1 bg-bg-card border border-border rounded-lg shadow-lg py-1 z-10 animate-fade-in min-w-[120px]">
{#each [["txt", "Plain Text"], ["md", "Markdown"], ["srt", "SRT Subtitles"], ["vtt", "WebVTT"]] as [fmt, label]}
{#each [["txt", "Plain Text"], ["md", "Markdown"], ["csv", "CSV"], ["html", "HTML"], ["srt", "SRT Subtitles"], ["vtt", "WebVTT"]] as [fmt, label]}
<button
class="w-full text-left btn-md text-text-secondary hover:bg-hover hover:text-text"
onclick={() => handleExport(fmt)}

View File

@@ -35,6 +35,7 @@
);
function clearAll() {
if (!confirm("Delete all history? This can't be undone.")) return;
history.splice(0);
saveHistory();
expandedId = null;

View File

@@ -100,8 +100,9 @@
await invoke("download_model", { size });
downloadedModels = await invoke("list_models");
downloadingModel = "";
} catch {
} catch (err) {
downloadingModel = "";
engineStatus = typeof err === "string" ? err : "Download failed";
}
}
@@ -138,9 +139,9 @@
parakeetDownloaded = true;
parakeetDownloading = false;
parakeetStatus = "Downloaded (not loaded)";
} catch {
} catch (err) {
parakeetDownloading = false;
parakeetStatus = "Download failed";
parakeetStatus = typeof err === "string" ? err : "Download failed";
}
}

View File

@@ -454,7 +454,7 @@
<!-- Delete -->
<button
aria-label="Delete task"
class="mt-0.5 text-text-tertiary hover:text-danger opacity-0 group-hover:opacity-100 transition-opacity"
class="mt-0.5 text-text-tertiary hover:text-danger opacity-0 group-hover:opacity-100 focus:opacity-100 transition-opacity"
onclick={() => deleteTask(task.id)}
>
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
@@ -499,7 +499,7 @@
</div>
<button
aria-label="Delete completed task"
class="mt-0.5 text-text-tertiary hover:text-danger opacity-0 group-hover:opacity-100 transition-opacity"
class="mt-0.5 text-text-tertiary hover:text-danger opacity-0 group-hover:opacity-100 focus:opacity-100 transition-opacity"
onclick={() => deleteTask(task.id)}
>
<svg class="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">

View File

@@ -260,7 +260,7 @@ export function moveTaskListToProfile(listId, profileId) {
const list = taskLists.find((l) => l.id === listId);
if (list && !list.builtIn) {
list.profileId = profileId || null;
if (profileId) list.name = profileId;
if (profileId && !list.name) list.name = profileId;
saveTaskLists();
}
}

View File

@@ -54,6 +54,10 @@ function toCSV(segments) {
return csv;
}
function escapeHtml(str) {
return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
}
function toHTML(text, segments) {
let html = `<!DOCTYPE html>
<html lang="en">
@@ -67,7 +71,6 @@ function toHTML(text, segments) {
.segment { display: flex; gap: 1rem; padding: 0.4rem 0; }
.timestamp { color: #9a9486; font-size: 0.8rem; min-width: 3rem; font-variant-numeric: tabular-nums; padding-top: 0.15rem; }
.text { flex: 1; }
.starred { border-left: 3px solid #e8a87c; padding-left: 0.5rem; }
</style>
</head>
<body>
@@ -83,11 +86,10 @@ function toHTML(text, segments) {
for (const seg of segments) {
const mins = Math.floor(seg.start / 60);
const secs = Math.floor(seg.start % 60);
const starClass = seg.starred ? ' starred' : '';
html += `<div class="segment${starClass}"><span class="timestamp">${pad(mins)}:${pad(secs)}</span><span class="text">${seg.text.trim()}</span></div>\n`;
html += `<div class="segment"><span class="timestamp">${pad(mins)}:${pad(secs)}</span><span class="text">${escapeHtml(seg.text.trim())}</span></div>\n`;
}
} else {
html += `<p>${text.replace(/\n/g, "<br>")}</p>`;
html += `<p>${escapeHtml(text).replace(/\n/g, "<br>")}</p>`;
}
html += `</body></html>`;
return html;