# Понятия

> Интеграция, slug, токен, поля, островок, карточка, приоритет и срок жизни значений.

## Интеграция

Интеграция — то, что вы собрали в Настройках: название, адрес (slug), набор
типизированных полей и то, как они показываются на островке (индикатор, строка
плашки, карточка). Структура интеграции статична: скрипт присылает значения, но не
может добавить поле, кнопку или элемент сверх того, что вы настроили. Одна интеграция
даёт ровно один индикатор и одну строку плашки на островке — если нужно две строки,
это две отдельные интеграции.

Выключенная интеграция отвечает на запись `409 integration_disabled` и ничего не
показывает; конфигурация и токен при этом сохраняются.

## Slug (адрес)

Slug — то, как скрипт находит интеграцию: `/v1/integrations/{slug}/…`,
`sparku push {slug} …`. Правила:

- строчные латинские буквы, цифры и дефис;
- начинается с буквы или цифры, не заканчивается дефисом;
- не длиннее 32 символов.

Примеры годных slug: `deploy`, `build`, `server`, `home-server`. При импорте `.sparku`
и совпадении адреса SparkU сам подбирает свободный: `deploy` → `deploy-2`.

## Токен

У каждой интеграции свой токен, выпущенный при её создании. Он хранится в Keychain и
не защищает от других процессов вашей учётной записи — они и так имеют доступ к
сокету. Его задача — адресация, защита от опечаток и чужих скриптов, а также
выборочный отзыв доступа перевыпуском токена.

**Где взять.** Настройки SparkU → Свои интеграции → нужная интеграция → раздел
«Подключение»: строка `export SPARKU_TOKEN_<АДРЕС>=…` и готовые примеры кода.

**Как передавать.** Заголовком `Authorization: Bearer <токен>` в каждом запросе.

**Порядок поиска в CLI** (`sparku` пробует по очереди, пока не найдёт непустое
значение):

1. `--token <токен>`
2. `--token-file <путь>`
3. переменная окружения `SPARKU_TOKEN_<АДРЕС>` (адрес — заглавными буквами, дефисы →
   `_`; например для `home-server` — `SPARKU_TOKEN_HOME_SERVER`)
4. переменная `SPARKU_TOKEN`
5. переменная `SPARKU_TOKEN_FILE` (путь к файлу с токеном)

`SPARKU_TOKEN` без суффикса адреса удобен, когда скрипт пишет в одну интеграцию;
`SPARKU_TOKEN_<АДРЕС>` — когда в несколько сразу.

## Поля

Поле — именованный типизированный слот: ключ (`progress`, `cpu`), тип
([типы полей](/docs/api/ru/fields.md)) и подпись. Ключ поля — строчные латинские буквы, цифры и
`_`, начинается с буквы, не длиннее 32 символов (это же имя переменной окружения
`SPARKU_FIELD_<КЛЮЧ>` для shell-действий кнопок, поэтому дефис в ключе не допускается).
У интеграции не больше 32 полей.

Запись полей — **всё или ничего**: если хоть одно значение не проходит проверку,
`POST …/fields` отклоняет весь запрос, и на островке не оказывается наполовину
обновлённого состояния.

## Островок: индикатор, строка, карточка

### Индикатор (свёрнутый островок, слот 28 pt)

По одному на интеграцию. Стили:

| Стиль | Что показывает | Источник |
|---|---|---|
| Значок | статичный SF Symbol | — |
| Кольцо | прогресс-кольцо со значком или числом внутри | поле `progress` или `number` с `min`/`max` |
| Значение | короткая строка до 4 символов | `text`, `number`, `progress`, `state`, `bool` |
| Эквалайзер | анимация как у «Медиа» | поле `bool` включает движение |
| Крутилка | вращающийся индикатор | поле `bool` включает вращение |

Поле `state` можно назначить дополнительно (`stateField`) — его значение подменяет
значок, цвет и анимацию индикатора, не меняя его тип.

### Строка плашки (одна на интеграцию)

| Стиль | Что показывает | Источник |
|---|---|---|
| Текст | шаблон `{title} · {progress}` | любые поля через `{ключ}` |
| Таймер | живой отсчёт | поле `time` |
| Шкала | подпись и мини-полоса | поле `progress` или `number` с `min`/`max` |
| Аватары | стек кружков с инициалами, «+N» сверх трёх | поле `list` |

**Шаблон строки** (`{ключ}`): подставляет значение в виде по умолчанию для типа
поля. `{{` и `}}` — литеральные скобки, форматных спецификаторов нет. Вид по
умолчанию: число — до двух знаков после точки плюс единица (`21°C`, `120 ms`),
прогресс — `43%`, состояние — его подпись, время — отсчёт до момента или время с
момента (`4:59`, `1:02:03`), список — число строк, булево — «да»/«нет». Нет
значения — прочерк (`—`).

### Карточка (раскрытый островок)

Собирается из шаблона со слотами — свободной сетки нет, чтобы визуальный ряд
оставался единым со встроенными интеграциями.

| Шаблон | Прообраз | Слоты / поля |
|---|---|---|
| Значение | Валюта | главное (`number`/`progress`/`text`), подпись |
| Статус | агенты | главное (`state`), подпись, «с какого момента» (`time`) |
| Прогресс | Pomodoro | главное (`progress`/`number`), подпись, отсчёт (`time`) |
| Таймер | Pomodoro | главное (`time`), подпись, кольцо (`progress`) |
| Шкалы | Монитор ресурсов | 2–4 поля `progress`/`number` (с `min`/`max`) рядом |
| Лимит | Claude Code | быстрое окно (`progress`), медленное окно (`progress`), подпись |
| Метрики | агенты | 2–4 поля `text`/`number`/`progress`/`state`/`bool`/`time` колонками |
| Список | Календарь, Todo | одно поле `list` |
| Сейчас | Медиа | заголовок (`text`, обязательно), подпись, обложка (`image`), шкала (`progress`) |
| График | — | одно поле `number` — рисуется по накопленной истории |

У карточки есть общая шапка и ряд из 0–3 элементов управления. Карточка может
запрашивать обычную или широкую ширину (как встроенные интеграции), и подходящий
компактный вариант.

## Элементы управления и их действия

Элемент — кнопка, кнопка-капсула, тумблер (управляет полем `bool`) или меню (выбирает
значение поля `state`). До трёх на карточку. Что делает нажатие — решает человек в
редакторе, а не скрипт:

| Действие | Что происходит |
|---|---|
| `event` | посылает событие слушателям `GET …/events` / `sparku listen`; без слушателя элемент неактивен |
| `url` | открывает ссылку, файл или приложение (адрес — статический или `{поле}`) |
| `shell` | выполняет команду; значения полей передаются **только** через переменные окружения `SPARKU_FIELD_<КЛЮЧ>`, никогда не подставляются в текст команды |
| `shortcut` | запускает команду приложения «Команды» по имени |

Слушатель получает событие о любом нажатии независимо от того, какое действие
настроено сверх этого.

## Приоритет

Островок — общий ресурс: окантовка выреза, маячок внимания и очередь диалогов
устроены как стек заявок, а не «первый занял — все ждут». У пользовательской
интеграции три уровня приоритета:

- **Низкий**
- **Обычный** — наравне со встроенными интеграциями SparkU (по умолчанию)
- **Высокий** — выше встроенных

При равном приоритете побеждает заявка, поданная **последней**. Обновление уже
поданной заявки не выдвигает её вперёд: модуль, который раз в секунду сообщает
прогресс, не отбирает дорожку у того, кто заявился после него.

## Срок жизни значений (TTL)

Значения полей живут **только в памяти** и не переживают перезапуск SparkU —
конфигурация интеграции при этом сохраняется всегда. По умолчанию значения живут до
перезапуска SparkU или до явного `sparku end`; интеграция может задать свой срок, а
конкретный запрос — переопределить его параметром `?ttl=`:

```
POST /v1/integrations/deploy/fields?ttl=5m
POST /v1/integrations/deploy/fields?ttl=90
```

`ttl` — число секунд или `5m` / `1h30m` (те же единицы, что у времени полей),
не больше 7 дней. Пустой или отсутствующий параметр — срок из настроек интеграции.
Каждая новая запись отсчитывает срок заново.

`sparku push` поддерживает тот же параметр флагом `--ttl` (см.
[CLI](/docs/api/ru/cli.md#push)).

## Привязка к процессу

Срок не спасает от упавшего скрипта: он успел написать «Деплой 40 %» и умер, а
островок показывает это до конца срока. Привязка решает это иначе — значения живут,
пока жив процесс:

```
POST /v1/integrations/deploy/fields?bind=process   # процесс, который прислал запрос
POST /v1/integrations/deploy/fields?bind=4211      # процесс с этим PID
POST /v1/integrations/deploy/fields?bind=none      # снять привязку
```

Процесс завершился — значения снимаются сразу, как от `sparku end`. Привязка
остаётся и у следующих записей без `bind`; новая `bind` её заменяет. Срок жизни
при этом тоже действует: что наступит раньше.

`bind=process` — для программ, которые сами держат соединение (скрипт на Python,
сервис на Node). `curl` и `sparku` завершаются сразу после запроса, поэтому им нужен
PID скрипта: в shell это `?bind=$$`, а `sparku push --bind` подставляет его сам.

## Notify-ограничение

`POST …/notify` (вспышка + строка на несколько секунд) можно вызывать не чаще
**раза в 2 секунды на интеграцию**. Более частый вызов получает `429
too_many_notices` с заголовком `Retry-After`. Ограничение не связано с записью
значений через `fields` — она принимается без ограничений, на экран просто попадает
не чаще кадра.

## История чисел

Для графика (шаблон карточки «График») и тренда SparkU копит историю каждого
числового поля: не больше одной точки в секунду (запись внутри той же секунды
заменяет последнюю точку), 120 точек на поле, только в памяти — история пропадает
вместе со значениями при перезапуске SparkU.
