Metadata-Version: 2.4
Name: hermes-yandex-calendar
Version: 0.1.0
Summary: Yandex Calendar plugin for Hermes Agent (list/create/delete events over CalDAV).
Project-URL: Homepage, https://github.com/akinfold/hermes-yandex-calendar
Project-URL: Repository, https://github.com/akinfold/hermes-yandex-calendar
Author: Roman Akinfeev
License-Expression: MIT
License-File: LICENSE
Keywords: caldav,calendar,hermes,hermes-agent,plugin,yandex
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Office/Business :: Scheduling
Requires-Python: <3.14,>=3.11
Requires-Dist: defusedxml>=0.7
Requires-Dist: httpx>=0.24
Provides-Extra: dev
Requires-Dist: pytest-cov>=4.1; extra == 'dev'
Requires-Dist: pytest>=7.4; extra == 'dev'
Requires-Dist: ruff>=0.6; extra == 'dev'
Description-Content-Type: text/markdown

# hermes-yandex-calendar

[![CI](https://github.com/akinfold/hermes-yandex-calendar/actions/workflows/ci.yml/badge.svg)](https://github.com/akinfold/hermes-yandex-calendar/actions/workflows/ci.yml)
[![coverage](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/akinfold/hermes-yandex-calendar/badges/coverage.json)](https://github.com/akinfold/hermes-yandex-calendar/actions/workflows/ci.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)

**Give [Hermes Agent](https://github.com/NousResearch/hermes-agent) read/write access to your Yandex Calendar** — list, create, update, respond to, move, and delete events over CalDAV, across multiple calendars, with attendee and busy/free management.

Tested against Hermes **0.19.x**, Python **3.11–3.13**.

## What it does

Registers seven standalone tools:

| Tool | Purpose |
|---|---|
| `yandex_calendar_list_calendars` | List the calendars the plugin can use (name + `href`). |
| `yandex_calendar_list_events` | List events in a time range from a calendar (returns summary, start/end, location, description, attendees, busy status, and an `href`). |
| `yandex_calendar_create_event` | Create an event (summary, start, optional end/location/description/all-day, attendees, busy status, target calendar). |
| `yandex_calendar_update_event` | Edit an existing event by `href`: change fields, add/remove attendees, toggle busy/free. Recurrence rules and alarms are preserved. |
| `yandex_calendar_respond_event` | Respond to a meeting invitation — accept, decline, or tentatively accept. |
| `yandex_calendar_move_event` | Move an event to another calendar (details, attendees, recurrence, and alarms are kept). |
| `yandex_calendar_delete_event` | Delete an event by the `href` returned from a list. |

Yandex Calendar has no public REST API, so this plugin speaks **CalDAV**
(`https://caldav.yandex.ru`) directly — the same protocol Yandex's own docs point
third-party clients at.

### Multiple calendars

Every tool that reads or writes events takes an optional `calendar` argument — a
calendar **name** (as returned by `yandex_calendar_list_calendars`) or its `href`.
Omit it to use the default (first) calendar. `update` and `delete` identify the
event by its `href`, which already encodes the calendar it lives in.

You can restrict which calendars the plugin touches with `YANDEX_CALENDAR_CALENDARS`
(see below); the first one in that list becomes the default.

## Quick start

1. **Create a Yandex app password** (a normal account password will not work for
   CalDAV): https://id.yandex.ru/security/app-passwords → add a password scoped to
   *"Calendar (CalDAV)"*.

2. **Install the plugin into Hermes:**

   ```bash
   hermes plugins install akinfold/hermes-yandex-calendar --enable
   ```

3. **Provide credentials** — either answer the install prompts, or add them to
   `~/.hermes/.env`:

   ```dotenv
   YANDEX_CALENDAR_LOGIN=you@yandex.ru
   YANDEX_CALENDAR_APP_PASSWORD=xxxxxxxxxxxxxxxx
   ```

4. **Enable it** in `~/.hermes/config.yaml` (third-party plugins are off by default):

   ```yaml
   plugins:
     enabled: [yandex_calendar]
   ```

That's it — ask the agent things like *"what's on my calendar next week?"* or
*"add a 30-minute call tomorrow at 3pm"*.

## Configuration

| Env var | Required | Default | Meaning |
|---|---|---|---|
| `YANDEX_CALENDAR_LOGIN` | yes | — | Yandex login / email. |
| `YANDEX_CALENDAR_APP_PASSWORD` | yes | — | App password for CalDAV (see step 1). |
| `YANDEX_CALENDAR_BASE_URL` | no | `https://caldav.yandex.ru` | Override for self-hosted / testing. |
| `YANDEX_CALENDAR_CALENDARS` | no | *(all)* | Comma-separated allow-list of calendar names the plugin may use, e.g. `Work,Personal`. The first is the default calendar. |

Credentials are read from the environment first, then from `~/.hermes/.env`, so they
work in gateway and subprocess runs. Secret values are never logged.

Dates and times are ISO 8601 (`2026-07-25` or `2026-07-25T14:00:00+03:00`); a datetime
without an offset is treated as UTC.

## Install alternatives

- **pip** (discovered via the `hermes_agent.plugins` entry point):
  ```bash
  pip install hermes-yandex-calendar
  ```
  then add `yandex_calendar` to `plugins.enabled`.
- **Drop-in**: unzip the release archive into `~/.hermes/plugins/` so you get
  `~/.hermes/plugins/yandex_calendar/plugin.yaml`, then enable it.

## Development

```bash
python -m venv .venv && source .venv/bin/activate
pip install -e '.[dev]'
ruff check . && ruff format --check .
pytest                       # unit tests (no network)
```

Live end-to-end tests hit a real account and are deselected by default. They create
then delete a throwaway event far in the future, so a successful run leaves no residue:

```bash
YANDEX_CALENDAR_LOGIN=you@yandex.ru \
YANDEX_CALENDAR_APP_PASSWORD=xxxx \
pytest -m e2e
```

## License

MIT — see [LICENSE](LICENSE).
