Google Workspace

Gmail, Calendar, Drive, Docs, Sheets через gws CLI или Python.

Метаданные навыка

ИсточникВстроенный (установлен по умолчанию)
Путьskills/productivity/google-workspace
Версия1.1.0
АвторNous Research
ЛицензияMIT
Платформыlinux, macos, windows
ТегиGoogle, Gmail, Calendar, Drive, Sheets, Docs, Contacts, Email, OAuth
Связанные навыкиhimalaya

Справочник: полный SKILL.md

инфо

Ниже приведено полное определение навыка, которое Hermes загружает при срабатывании этого навыка. Именно его агент видит как инструкции, пока навык активен.

Google Workspace

Gmail, Calendar, Drive, Contacts, Sheets и Docs — через управляемый Hermes OAuth и тонкую обёртку CLI. Если установлен gws, навык использует его для более широкого охвата Google Workspace; иначе переходит к встроенному Python-клиенту.

References

  • references/gmail-search-syntax.md — операторы поиска Gmail (is:unread, from:, newer_than: и т.д.)

Scripts

  • scripts/setup.py — настройка OAuth2 (запускается один раз для авторизации)
  • scripts/google_api.py — CLI-обёртка для совместимости. Для операций предпочитает gws, когда тот доступен, при этом сохраняет контракт JSON-вывода Hermes без изменений.

Первичная настройка

Настройка полностью неинтерактивная — вы ведёте её шаг за шагом, чтобы она работала в CLI, Telegram, Discord или на любой другой платформе.

Сначала задайте сокращение:

GSETUP="python ${HERMES_HOME:-$HOME/.hermes}/skills/productivity/google-workspace/scripts/setup.py"

Шаг 0: Проверьте, не настроено ли уже

$GSETUP --check

Если вывелось AUTHENTICATED, переходите к разделу «Использование» — настройка уже выполнена.

Шаг 1: Уточнение — спросите пользователя, что ему нужно

Перед началом настройки OAuth задайте пользователю ДВА вопроса:

Вопрос 1: «Какие сервисы Google вам нужны? Только почта или ещё и Calendar/Drive/Sheets/Docs?»

  • Только почта → Этот навык им вообще не нужен. Используйте навык himalaya — он работает с паролем приложения Gmail (Настройки → Безопасность → Пароли приложений) и настраивается за 2 минуты. Проект Google Cloud не требуется. Загрузите навык himalaya и следуйте его инструкциям по настройке.

  • Почта + Calendar → Продолжайте с этим навыком, но при авторизации укажите --services email,calendar, чтобы экран согласия запрашивал только нужные им разрешения.

  • Только Calendar/Drive/Sheets/Docs → Продолжайте с этим навыком и задайте более узкий набор --services, например calendar,drive,sheets,docs.

  • Полный доступ к Workspace → Продолжайте с этим навыком и используйте набор сервисов all по умолчанию.

Вопрос 2: «Использует ли ваш аккаунт Google усиленную защиту (Advanced Protection, для входа обязательны аппаратные ключи безопасности)? Если не уверены — скорее всего, нет: её подключают только осознанно и вручную.»

  • Нет / Не уверен → Обычная настройка. Продолжайте ниже.
  • Да → Администратор их Workspace должен добавить идентификатор клиента OAuth в список разрешённых приложений организации, иначе Шаг 4 не сработает. Предупредите их заранее.

Шаг 2: Создайте учётные данные OAuth (разово, ~5 минут)

Скажите пользователю:

Вам нужен OAuth-клиент Google Cloud. Это разовая настройка:

  1. Создайте или выберите проект: https://console.cloud.google.com/projectselector2/home/dashboard
  2. Включите нужные API в библиотеке API: https://console.cloud.google.com/apis/library Включите: Gmail API, Google Calendar API, Google Drive API, Google Sheets API, Google Docs API, People API
  3. Создайте OAuth-клиент здесь: https://console.cloud.google.com/apis/credentials Credentials → Create Credentials → OAuth 2.0 Client ID
  4. Тип приложения: «Desktop app» → Create
  5. Если приложение ещё в режиме Testing, добавьте аккаунт Google пользователя как тестового пользователя здесь: https://console.cloud.google.com/auth/audience Audience → Test users → Add users
  6. Скачайте файл JSON и сообщите мне путь к нему

Важное замечание по Hermes CLI: если путь к файлу начинается с /, НЕ отправляйте голый путь отдельным сообщением в CLI — его могут принять за слэш-команду. Пошлите его в составе предложения, например: The JSON file path is: /home/user/Downloads/client_secret_....json

Как только они укажут путь:

$GSETUP --client-secret /path/to/client_secret.json

Если вместо пути к файлу они вставляют сырые значения client ID / client secret, сами сформируйте корректный JSON-файл Desktop OAuth, сохраните его в явное место (например, ~/Downloads/hermes-google-client-secret.json), а затем запустите --client-secret для этого файла.

Шаг 3: Получите URL авторизации

Используйте набор сервисов, выбранный на Шаге 1. Примеры:

$GSETUP --auth-url --services email,calendar --format json
$GSETUP --auth-url --services calendar,drive,sheets,docs --format json
$GSETUP --auth-url --services all --format json

Команда возвращает JSON с полем auth_url и заодно сохраняет точный URL в ~/.hermes/google_oauth_last_url.txt.

Правила для агента на этом шаге:

  • Извлеките поле auth_url и отправьте этот точный URL пользователю одной строкой.
  • Предупредите пользователя, что после подтверждения браузер, скорее всего, выдаст ошибку на http://localhost:1 — это ожидаемо.
  • Скажите им скопировать ЦЕЛИКОМ перенаправленный URL из адресной строки браузера.
  • Если у пользователя возникает Error 403: access_denied, отправьте его прямо на https://console.cloud.google.com/auth/audience, чтобы он добавил себя как тестового пользователя.

Шаг 4: Обменяйте код

Пользователь вставит обратно либо URL вида http://localhost:1/?code=4/0A...&scope=..., либо просто строку с кодом. Подойдёт и то, и другое. Шаг --auth-url сохраняет временную ожидающую OAuth-сессию локально, чтобы --auth-code мог завершить обмен PKCE позже, даже на серверах без графического интерфейса:

$GSETUP --auth-code "THE_URL_OR_CODE_THE_USER_PASTED" --format json

Если --auth-code завершается ошибкой из-за истёкшего, уже использованного кода или кода из старой вкладки браузера, команда вернёт свежий fresh_auth_url. В этом случае сразу отправьте новый URL пользователю и попросите повторить попытку, используя только самое свежее перенаправление браузера.

Шаг 5: Проверьте

$GSETUP --check

Должно вывестись AUTHENTICATED. Настройка завершена — токен с этого момента обновляется автоматически.

Примечания

  • Токен хранится в ~/.hermes/google_token.json и обновляется автоматически.
  • Состояние ожидающей OAuth-сессии и верификатор временно хранятся в ~/.hermes/google_oauth_pending.json до завершения обмена.
  • Если установлен gws, google_api.py направляет его на тот же файл учётных данных ~/.hermes/google_token.json. Отдельный поток gws auth login запускать не нужно.
  • Чтобы отозвать доступ: $GSETUP --revoke

Использование

Все команды идут через API-скрипт. Задайте сокращение GAPI:

GAPI="python ${HERMES_HOME:-$HOME/.hermes}/skills/productivity/google-workspace/scripts/google_api.py"

Gmail

# Поиск (возвращает JSON-массив с id, from, subject, date, snippet)
$GAPI gmail search "is:unread" --max 10
$GAPI gmail search "from:boss@company.com newer_than:1d"
$GAPI gmail search "has:attachment filename:pdf newer_than:7d"

# Прочитать сообщение целиком (возвращает JSON с текстом тела)
$GAPI gmail get MESSAGE_ID

# Отправить
$GAPI gmail send --to user@example.com --subject "Hello" --body "Message text"
$GAPI gmail send --to user@example.com --subject "Report" --body "<h1>Q4</h1><p>Details...</p>" --html
$GAPI gmail send --to user@example.com --subject "Hello" --from '"Research Agent" <user@example.com>' --body "Message text"

# Ответить (автоматически выстраивает цепочку и проставляет In-Reply-To)
$GAPI gmail reply MESSAGE_ID --body "Thanks, that works for me."
$GAPI gmail reply MESSAGE_ID --from '"Support Bot" <user@example.com>' --body "Thanks"

# Ярлыки
$GAPI gmail labels
$GAPI gmail modify MESSAGE_ID --add-labels LABEL_ID
$GAPI gmail modify MESSAGE_ID --remove-labels UNREAD

Calendar

# Список событий (по умолчанию на ближайшие 7 дней)
$GAPI calendar list
$GAPI calendar list --start 2026-03-01T00:00:00Z --end 2026-03-07T23:59:59Z

# Создать событие (нужен ISO 8601 с часовым поясом)
$GAPI calendar create --summary "Team Standup" --start 2026-03-01T10:00:00-06:00 --end 2026-03-01T10:30:00-06:00
$GAPI calendar create --summary "Lunch" --start 2026-03-01T12:00:00Z --end 2026-03-01T13:00:00Z --location "Cafe"
$GAPI calendar create --summary "Review" --start 2026-03-01T14:00:00Z --end 2026-03-01T15:00:00Z --attendees "alice@co.com,bob@co.com"

# Удалить событие
$GAPI calendar delete EVENT_ID

Drive

# Поиск существующих файлов
$GAPI drive search "quarterly report" --max 10
$GAPI drive search "mimeType='application/pdf'" --raw-query --max 5

# Получить метаданные одного файла
$GAPI drive get FILE_ID

# Загрузить локальный файл (MIME-тип определяется автоматически)
$GAPI drive upload /path/to/report.pdf
$GAPI drive upload /path/to/image.png --name "Logo.png" --parent FOLDER_ID

# Скачать (бинарные файлы скачиваются как есть; нативные файлы Google
# экспортируются в разумный формат по умолчанию — Docs→pdf, Sheets→csv, Slides→pdf, Drawings→png)
$GAPI drive download FILE_ID
$GAPI drive download DOC_ID --output ~/doc.pdf
$GAPI drive download DOC_ID --export-mime text/plain --output ~/doc.txt

# Создать папку
$GAPI drive create-folder "Reports"
$GAPI drive create-folder "Q4" --parent FOLDER_ID

# Поделиться
$GAPI drive share FILE_ID --email alice@example.com --role reader
$GAPI drive share FILE_ID --email alice@example.com --role writer --notify
$GAPI drive share FILE_ID --type anyone --role reader        # любой по ссылке
$GAPI drive share FILE_ID --type domain --domain example.com --role reader

# Удалить — по умолчанию в корзину (обратимо). Используйте --permanent, чтобы минуть корзину.
$GAPI drive delete FILE_ID
$GAPI drive delete FILE_ID --permanent

Contacts

$GAPI contacts list --max 20

Sheets

# Создать новую таблицу
$GAPI sheets create --title "Q4 Budget"
$GAPI sheets create --title "Inventory" --sheet-name "Stock"

# Прочитать
$GAPI sheets get SHEET_ID "Sheet1!A1:D10"

# Записать
$GAPI sheets update SHEET_ID "Sheet1!A1:B2" --values '[["Name","Score"],["Alice","95"]]'

# Добавить строки
$GAPI sheets append SHEET_ID "Sheet1!A:C" --values '[["new","row","data"]]'

Docs

# Прочитать
$GAPI docs get DOC_ID

# Создать новый документ (по желанию с начальным текстом тела)
$GAPI docs create --title "Meeting Notes"
$GAPI docs create --title "Draft" --body "First paragraph..."

# Добавить текст в конец существующего документа
$GAPI docs append DOC_ID --text "Additional content to append"

Формат вывода

Все команды возвращают JSON. Разбирайте его через jq или читайте напрямую. Ключевые поля:

  • Gmail search: [{id, threadId, from, to, subject, date, snippet, labels}]
  • Gmail get: {id, threadId, from, to, subject, date, labels, body}
  • Gmail send/reply: {status: "sent", id, threadId}
  • Calendar list: [{id, summary, start, end, location, description, htmlLink}]
  • Calendar create: {status: "created", id, summary, htmlLink}
  • Drive search: [{id, name, mimeType, modifiedTime, webViewLink}]
  • Drive get: {id, name, mimeType, modifiedTime, size, webViewLink, parents, owners}
  • Drive upload: {status: "uploaded", id, name, mimeType, webViewLink}
  • Drive download: {status: "downloaded", id, name, path, mimeType}
  • Drive create-folder: {status: "created", id, name, webViewLink}
  • Drive share: {status: "shared", permissionId, fileId, role, type}
  • Drive delete: {status: "trashed" | "deleted", fileId, permanent}
  • Contacts list: [{name, emails: [...], phones: [...]}]
  • Sheets get: [[cell, cell, ...], ...]
  • Sheets create: {status: "created", spreadsheetId, title, spreadsheetUrl}
  • Docs create: {status: "created", documentId, title, url}
  • Docs append: {status: "appended", documentId, inserted_at, characters}

Правила

  1. Никогда не отправляйте письма, не создавайте и не удаляйте события Calendar, не удаляйте файлы Drive, не делитесь файлами и не меняйте Docs/Sheets без предварительного подтверждения от пользователя. Покажите, что будет сделано (получатели, ID файлов, содержимое, роль доступа), и спросите согласия. Для drive delete предпочитайте корзину по умолчанию (обратимо), а не --permanent.
  2. Проверяйте авторизацию перед первым использованием — запустите setup.py --check. Если она не проходит, проведите пользователя через настройку.
  3. Для сложных запросов используйте справочник по синтаксису поиска Gmail — загрузите его командой skill_view("google-workspace", file_path="references/gmail-search-syntax.md").
  4. Время в календаре должно включать часовой пояс — всегда используйте ISO 8601 со смещением (например, 2026-03-01T10:00:00-06:00) или UTC (Z).
  5. Соблюдайте лимиты запросов — избегайте быстрых подряд идущих вызовов API. По возможности группируйте чтения в пакеты.

Устранение неполадок

ПроблемаРешение
NOT_AUTHENTICATEDВыполните Шаги настройки 2–5 выше
REFRESH_FAILEDТокен отозван или истёк — повторите Шаги 3–5
HttpError 403: Insufficient PermissionНе хватает разрешения API — $GSETUP --revoke, затем повторите Шаги 3–5
AUTHENTICATED (partial) или «Token missing scopes»Новые возможности записи (Drive write/delete, Docs create/edit) требуют повторной авторизации. $GSETUP --revoke, затем повторите Шаги 3–5, чтобы выдать расширенные разрешения.
HttpError 403: Access Not ConfiguredAPI не включён — пользователю нужно включить его в Google Cloud Console
ModuleNotFoundErrorЗапустите $GSETUP --install-deps
Усиленная защита блокирует авторизациюАдминистратор Workspace должен добавить идентификатор клиента OAuth в список разрешений

Отзыв доступа

$GSETUP --revoke
ESC