agentleFS
dewildewil/ai-toolkit/skills/mymeet-snapshot/SKILL.md

mymeet-snapshot

Skill9 starsChanged 2 months agoMITView on GitHub

Настроить/починить зеркало расшифровок встреч mymeet.ai и загрузку записи в облако на транскрибацию: \"тянет чужие встречи\", \"api-ключ mymeet\". Офлайн без облака - `local-transcription`.

Files
SKILL.md

mymeet-snapshot

Скилл для первой настройки или починки локального snapshot расшифровок встреч из mymeet.ai через REST API. Скрипт тянет MD-отчеты проектных встреч и раскладывает по папкам Встречи/ - для чтения, написания .summary.md и работы без захода в web-UI mymeet.

Скрипт-эталон лежит в каноне в scripts/mymeet-snapshot.py (top-level папка scripts/, не внутри папки скилла). .AI bootstrap типа management копирует его в scripts/ в корне проекта - оттуда же, где его ожидает запуск (python3 scripts/mymeet-snapshot.py).

Архитектура повторяет telegram-snapshot / redmine-snapshot: общий секрет на устройстве, проектные указатели - в репозитории проекта.

Когда применять

  • Пользователь впервые настраивает scripts/mymeet-snapshot.py на новом устройстве.
  • Подключается новый проект - нужно создать .mymeet-snapshot.json и проверить, что общая авторизация на устройстве уже есть.
  • Скрипт тянет чужие (непроектные) встречи или кладет встречи не в ту папку - надо настроить правила rules.
  • Первый запуск падает на авторизации (401) или на неизвестных полях ответа.

Когда НЕ применять

  • Обычный регулярный pull новых встреч - это просто Bash-команда (python3 scripts/mymeet-snapshot.py --all), отдельный скилл не нужен. Без флага скрипт только печатает справку и ничего не качает - не принимай это за выполненный pull.
  • Анализ самих расшифровок - они уже лежат .md в Встречи/, читай напрямую.
  • Чтение истории чатов - это telegram-snapshot. Задачи - redmine-snapshot.

Что делает скрипт (модель)

  1. GET /api/workspaces/active/all-meetings (пагинация page/perPage) - список встреч аккаунта.
  2. Аккаунт mymeet общий, встреч много и не только этого проекта. Фильтр - whitelist по правилам: title встречи матчится подстроками из rules[].match; первое подошедшее правило задает папку (rules[].dest).
  3. Подошла под правило + готовый статус (см. ниже) + есть дата -> качает MD (GET /api/storage/download?format=md) в <meetings_root>/<dest>/ГГГГ-ММ-ДД.md (коллизия в один день -> -2, -3).
  4. НЕ подошла ни под одно правило -> в review-файл (<meetings_root>/_mymeet-review.txt) строкой meeting_id | дата | title. Человек глазами решает: проектную - добавить паттерн / дернуть вручную, чужую - игнорировать.
  5. Что уже видел - помнит в <meetings_root>/_mymeet-index.json, повторно не качает.

JSON-отчет по умолчанию НЕ качается (для рутины хватает MD, на объемах JSON - оверхед). По требованию: python3 scripts/mymeet-snapshot.py --json <meeting_id> - положит .json рядом с MD этой встречи. Отдельного -deltas скрипта нет: новые встречи = то, что прогон только что скачал (печатается в конце), а не diff мутирующего файла, как у telegram/redmine.

Режимы (основной - точечный по id; аккаунт mymeet общий на проекты, поэтому балк по умолчанию выключен):

  • --pull <ID|URL> - основной режим: точечно скачать одну встречу по правилам. Принимает и голый meeting_id, и URL встречи целиком (id берется из адреса - его видно в адресной строке mymeet). Рабочий цикл: пользователь правит имена спикеров на mymeet -> дает id/URL -> --pull.
  • --json <ID|URL> - добрать JSON конкретной встречи (тоже принимает URL).
  • --list - dry-run: что нашлось бы и куда легло, без скачивания.
  • --seed - baseline: отметить все текущие встречи аккаунта как виденные, ничего не качая. Нужен на старте, если история уже скачана вручную: иначе балк создаст дубли существующих файлов (-2/-3).
  • --all - балк: забрать ВСЕ новые проектные встречи разом (имена сырые, как распознал mymeet). По умолчанию НЕ запускается - голый прогон без аргументов печатает справку, чтобы на общем мульти-проектном аккаунте случайный запуск не нагреб чужое.

В --pull и --all статус берется из списка встреч сервиса. Только processed и new готовы. Любой другой или отсутствующий статус пропускается без скачивания и без ошибки. В stdout печатается не готова: <id>, статус <статус>; при отсутствии статуса выводится нет статуса.

Итог --all печатается в stdout:

  • OK:, код 0 - все подходящие готовые встречи скачаны, включая прогон без новых встреч.
  • ЧАСТИЧНО: со списком нескачанных id или ошибкой чтения списка, код 1 - есть ошибки скачивания или пагинации; успешные встречи сохраняются в индексе.
  • Код 2 - ошибка конфига или авторизации (HTTP 401/403), если ничего не скачано. Если часть встреч скачана, ошибки авторизации дают ЧАСТИЧНО: и код 1.

Формат ответа API (подтверждено живым прогоном 2026-06-25): список - GET all-meetings -> {followups: [...], total}; у встречи поля id, name (title), status (new/processed/...), date в RFC 2822 ("Thu, 25 Jun 2026 12:02:06 GMT"). Скрипт читает их толерантно (перебор *_KEYS), дату парсит и ISO, и RFC 2822, и epoch.

Алгоритм настройки

Шаг 1. Проверить общую авторизацию устройства

ls ~/.config/mymeet-snapshot/

Должен быть auth.json (api_key, опционально base_url) с правами 600. Если файла нет - шаг 2.

Шаг 2. Получить API-ключ mymeet

  1. Залогиниться в mymeet.ai.
  2. Settings -> API key (https://app.mymeet.ai/ru/settings/api-key).
  3. Скопировать ключ. Доступно на тарифах Lite, Pro, Business.

Шаг 3. Заполнить auth.json

mkdir -p ~/.config/mymeet-snapshot
chmod 700 ~/.config/mymeet-snapshot

Содержимое ~/.config/mymeet-snapshot/auth.json:

{
  "api_key": "<ключ из шага 2>",
  "base_url": "https://backend.mymeet.ai",
  "use_curl": true
}
  • base_url можно опустить - дефолт https://backend.mymeet.ai.
  • use_curl - поднять в true, если Python падает на SSL (CERTIFICATE_VERIFY_FAILED). Сборка python.org на macOS не имеет CA-бандла и не проверяет даже валидный публичный сертификат backend.mymeet.ai; curl берет сертификат из системного хранилища. На практике на macOS нужен true.
chmod 600 ~/.config/mymeet-snapshot/auth.json

Шаг 4. Подключить проект (.mymeet-snapshot.json)

В корне проекта - .mymeet-snapshot.json:

{
  "meetings_root": "Встречи",
  "rules": [
    { "match": ["синк", "заказчик"], "dest": "с заказчиком/{YYYY}/{MM}" },
    { "match": ["дейли", "дейлик", "команд"], "dest": "с командой/{YYYY}/{MM}" },
    { "match": ["1-1", "one-on-one"], "dest": "1-1/_inbox" }
  ],
  "review_file": "Встречи/_mymeet-review.txt"
}
  • meetings_root - корневая папка встреч относительно корня проекта.

    В проекте с несколькими направлениями (клиент-зонтик, rules/client-umbrella.md) единой папки встреч нет: встречи направления живут внутри него (rules/artifacts-structure.md). Тогда meetings_root - корень проекта ("."), а полный путь несет dest каждого правила:

    { "match": ["ShopHack"], "dest": "2026-07 Agent/Встречи/с командой/{YYYY}/{MM}" },
    { "match": ["Харитонов"], "dest": "Встречи/1-1/Харитонов Евгений" }

    Индекс _mymeet-index.json всегда лежит относительно meetings_root, поэтому при смене корня перенеси существующий индекс руками в новое место: на пустом индексе следующий прогон посчитает все старые встречи новыми и скачает их повторно. review_file - отдельный ключ (по умолчанию тоже относительно meetings_root); при "." задай его явно, иначе review осядет в корне.

  • rules - список {match: [подстроки title], dest: путь-шаблон}. Первое правило, чья подстрока нашлась в title (регистронезависимо), задает папку. dest поддерживает {YYYY}/{MM}/{DD} из даты встречи.
  • review_file - куда писать непроектные/нераспознанные встречи.

Файл - не секрет (ключа нет), коммитится.

Важно про title. mymeet галлюцинирует в шапке (путает имена/стороны), поэтому матчинг по title не стопроцентный. Это осознанный компромисс: вместо тихого пропуска все непонятное падает в review-файл, где видно глазами. Не вылизывай правила до идеала - расширяй по мере того, как реальные встречи попадают в review. 1-1 по title в папку конкретного сотрудника не развести - кладем в 1-1/_inbox, дальше руками.

Шаг 5. Dry-run, потом первый pull

Сначала всегда --list - покажет, что API реально отдает и куда ляжет, ничего не качая:

cd <project-root>
python3 scripts/mymeet-snapshot.py --list

Сверь: проектные встречи распознались и нацелены в верные папки, чужое ушло бы в review. Если поля даты/title/id читаются неверно (видно по "дата?" или пустым title) - см. "Типичные ошибки". Когда раскладка верная:

python3 scripts/mymeet-snapshot.py --all

Флаг обязателен: голый запуск печатает справку и ничего не качает. История уже скачана вручную - вместо --all сначала --seed, иначе балк создаст дубли. Дальше рабочий цикл - точечный --pull <ID|URL>. Зависимостей нет - чистый stdlib (urllib).

Шаг 6. Типичные ошибки

ssl.SSLCertVerificationError: CERTIFICATE_VERIFY_FAILED. Python не видит CA-бандл (типично для python.org-сборки на macOS). В ~/.config/mymeet-snapshot/auth.json выставить "use_curl": true - запросы пойдут через curl, который берет сертификат из системного хранилища. Перезапустить.

401 Unauthorized. Неверный/просроченный api_key - перевыпустить (шаг 2). Проверить тариф (нужен Lite/Pro/Business).

В --list у всех "дата?". В ответе списка поле даты названо не так, как перебирает скрипт (DATE_KEYS). Посмотреть сырой ответ: curl -H "X-API-KEY: <ключ>" "https://backend.mymeet.ai/api/workspaces/active/all-meetings?page=0&perPage=5", найти ключ с датой, добавить его первым в DATE_KEYS в скрипте (и оформить как upstream-правку в канон).

Пустые title / не тот id. Аналогично - проверить реальные имена полей в сыром ответе и поправить TITLE_KEYS / ID_KEYS.

Все ушло в review, хотя встречи проектные. Правила rules[].match не совпали с реальными title - расширить подстроки под то, как mymeet называет встречи (видно в review-файле).

Перенес уже забранные встречи в другую папку. Поправь у них в _mymeet-index.json поля dest и file: индекс хранит, куда файл лег, и точечный --pull этой встречи идет по записанному пути. Со старым путем будет одно из двух - если там пусто, приедет второй экземпляр рядом с перенесенным; если место уже занято другим документом, скрипт его перезапишет (прежнее содержимое уедет в <имя>.prev.md, в stderr будет предупреждение с путем и размерами).

В файле шапка mymeet (супер краткое содержание, саммари, задачи). Скрипт режет ее сам по маркеру **Транскрипт:** - если шапка на месте, значит маркера не нашлось (сменился формат) и в stderr было предупреждение. Файл сохранен целиком намеренно: резать по догадке нельзя, потеряется транскрипт. Убрать шапку вручную, а расхождение формата - оформить upstream-правкой в канон. Почему шапку не храним - rules/meeting-transcripts.md.

MD пришел пустой / это JSON. download?format=md мог вернуть не файл, а JSON со ссылкой на storage - скрипт это обрабатывает (следует по url/download_url/link). Если формат ответа иной - глянуть сырой ответ download и поправить download_md.

Загрузка записи на транскрибацию

Обратная половина цикла: не только забрать готовую расшифровку, но и положить запись в сервис. Нужна, когда записи нет в облачном календаре сервиса - телефонный звонок, локальный файл, запись с диктофона.

python3 scripts/mymeet-snapshot.py --upload звонок.mp3 --title "2026-08-04 Клиент - созвон"
python3 scripts/mymeet-snapshot.py --upload запись.m4a --template one-to-one --speakers 2 --wait
python3 scripts/mymeet-snapshot.py --status <meeting_id>
  • --title - имя встречи. Задавать сразу и по проектной конвенции: под правило матчинга попадает имя, и запись с именем "voice_2026.m4a" осядет в review-списке вместо своей папки.
  • --template - шаблон отчета сервиса (default-meeting, one-to-one, hr-interview, lecture-notes, protocol и др.; полный список в скрипте).
  • --speakers N - число участников, если известно.
  • --wait - дождаться обработки (поллинг статуса) и сразу забрать расшифровку по правилам конфига. Без флага скрипт печатает meeting_id и команду проверки статуса; транскрибация занимает минуты.
  • Файл читается и шлется чанками, поэтому длинная запись не съедает память.

Агент не запускает --upload без явного "ок" пользователя на конкретный файл. Отдельного dry-run-гейта у команды нет намеренно (в отличие от telegram-send, где агент сочиняет текст сам): файл называет пользователь, и удваивать рутину подтверждением флага незачем. Но действие необратимо и платно, поэтому подтверждение остается - на уровне поведения, а не флага.

Загрузка расходует минуты аккаунта и создает встречу в общем workspace. Тестовые прогоны оставляют мусорные встречи, которые видны всем проектам, использующим этот аккаунт, - удалять через веб-интерфейс (API удаления скрипт не трогает).

Грабли протокола

  • localTime на финализирующем чанке. В OpenAPI 1.1.0 поле не помечено обязательным. 2026-07-28 без него финализация отдавала голый 500 от nginx (text/html, не JSON; error_format=json на такой ответ не действует) - в проекте-источнике это восемь дней принимали за поломку сервиса и писали в поддержку. На проверке 2026-08-04 сервер принял финализацию и без поля: вендор починил молча. Скрипт шлет поле всегда и сам - полагаться на негарантированное поведение нельзя.
  • Отсюда общий прием: при интеграции сверяйся с эталонной реализацией вендора, а не только со спекой. Расхождение "в спеке поле необязательное, в примере кода оно есть в каждом запросе" - сигнал; проявляется оно не валидационной ошибкой, а 500, который читается как поломка чужой стороны.
  • Поле file обязательно даже у пустого финализирующего маркера - без самого поля приходит 400.
  • Коды ответа говорят по делу: 402 кончились минуты, 422 загрузка битая или вытеснена более новой попыткой (бывает при параллельных заливках одного файла), 426 не хватает минут на файл такой длины, 432 больше 1 ГБ нужен тариф выше, 433 запись короче 30 секунд, 414 больше 3 ГБ, 415 формат.

Жесткие правила

  1. auth.json - НЕ в проектную папку. Проект на Yandex.Disk; утечка api_key в облако недопустима. Только ~/.config/mymeet-snapshot/ (локально на устройство).
  2. api_key - секрет. В .mymeet-snapshot.json, который коммитится, ключа быть не должно.
  3. Whitelist, не pull-all. Аккаунт общий; качать все подряд нельзя. Непроектное - в review, не на диск.
  4. JSON - по требованию. Рутинно держим только MD. JSON (--json) - точечно, когда нужна программная обработка (word_timings/chapters).
  5. Выгруженный JSON - технический артефакт: место ему вне синкаемой папки, а не под ignore после факта (rules/docs-maintenance.md, раздел "Технические артефакты в синкаемой папке"): исключение защищает следующий файл, уже созданный оно не возвращает. Заметки встреч - наоборот, содержимое: они остаются в проекте. Исходных записей это не касается - у них жизненный цикл строже: после проверенной транскрибации запись из проекта убирается совсем (rules/meetings.md, "Записи: в проекте не храним"), а не остается лежать под ignore.

Связанные файлы

  • scripts/mymeet-snapshot.py в корне проекта - pull MD проектных встреч по whitelist, --list (dry-run), --json <id> (добор JSON).
  • ~/.config/mymeet-snapshot/auth.json - локальные credentials на устройство (api_key, base_url). Не в проекте.
  • .mymeet-snapshot.json в корне проекта - проектные указатели {meetings_root, rules, review_file}. Не секрет.
  • <meetings_root>/_mymeet-index.json - реестр уже скачанных встреч (что не качать повторно).
  • <meetings_root>/_mymeet-review.txt - очередь непроектных/нераспознанных встреч на ручное решение.

Модель и текущие назначения

Перед новым заданием и запуском применяй маршрутизацию моделей: свежий MODELS выше канонического дефолта. Границы данных и полномочий этого навыка сохраняются.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.