anc
Этап 0: каркас Tauri 2, разбор встречи через OpenRouter, стиль skillok.org
- Ядро на Rust: расшифровка и импорт текста, схема разбора со строгой
проверкой ответа модели, клиент OpenRouter (проверка ключа, разбор),
настройки и ключ в хранилище паролей ОС, встречи папками на диске.
- Интерфейс: экраны «Встречи», «Встреча» (расшифровка, конспект, задачи),
«Настройки»; токены, шрифты и кнопки как на skillok.org.
- Промпт разбора prompts/analysis.md и проверочные расшифровки.
- 30 тестов ядра; клиент OpenRouter проверяется против локальной заглушки.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
d93e31a
30 сентября 2026 г.
main.ts
// Маршрутизация по хешу: #/meetings, #/meeting//<вкладка>[/<реплика>], #/settings.
import { renderMeetings } from "./views/meetings";
import { renderMeeting, type Tab } from "./views/meeting";
import { renderSettings } from "./views/settings";
import { errorText } from "./api";
import { esc } from "./dom";
const app = document.getElementById("app")!;
async function route(): Promise {
const [section, id, tab, target] = location.hash.replace(/^#\/?/, "").split("/");
for (const a of document.querySelectorAll("[data-nav]")) {
const current = a.dataset.nav === (section === "meeting" ? "meetings" : section || "meetings");
if (current) a.setAttribute("aria-current", "page");
else a.removeAttribute("aria-current");
}
try {
if (section === "meeting" && id) {
await renderMeeting(app, decodeURIComponent(id), (tab as Tab) || "transcript", target ? Number(target) : null);
} else if (section === "settings") {
await renderSettings(app);
} else {
await renderMeetings(app);
}
} catch (e) {
app.innerHTML = `${esc(errorText(e))}`;
}
}
window.addEventListener("hashchange", route);
route();