skillok meeting
d93e31a829c96025e18e4ceed0cf1552df5934c8
Перейти к файлу
Код
meeting srcmain.ts
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/<id>/<вкладка>[/<реплика>], #/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<void> {
  const [section, id, tab, target] = location.hash.replace(/^#\/?/, "").split("/");
  for (const a of document.querySelectorAll<HTMLAnchorElement>("[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 = `<p class="error">${esc(errorText(e))}</p>`;
  }
}

window.addEventListener("hashchange", route);
route();