@agfpd/iapeer 0.2.98 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/README.md +21 -7
  2. package/docs/01-overview.md +86 -0
  3. package/docs/02-quickstart.md +110 -0
  4. package/docs/03-peers-runtimes-identity.md +117 -0
  5. package/docs/04-lifecycle-and-daemon.md +101 -0
  6. package/docs/05-system-prompt.md +82 -0
  7. package/docs/06-storage.md +115 -0
  8. package/docs/07-install-and-update.md +87 -0
  9. package/docs/08-peer-management.md +119 -0
  10. package/docs/09-runtimes.md +103 -0
  11. package/docs/10-messaging.md +69 -0
  12. package/docs/11-extensions-and-memory.md +60 -0
  13. package/docs/12-cli-reference.md +96 -0
  14. package/docs/13-architecture-and-contract.md +190 -0
  15. package/docs/14-configuration-and-logs.md +91 -0
  16. package/docs/README.md +97 -0
  17. package/docs/ru/01-/320/276/320/261/320/267/320/276/321/200.md +86 -0
  18. package/docs/ru/02-/320/261/321/213/321/201/321/202/321/200/321/213/320/271-/321/201/321/202/320/260/321/200/321/202.md +110 -0
  19. package/docs/ru/03-/320/277/320/270/321/200/321/213-/321/200/320/260/320/275/321/202/320/260/320/271/320/274/321/213-/320/270/320/264/320/265/320/275/321/202/320/270/321/207/320/275/320/276/321/201/321/202/321/214.md +117 -0
  20. package/docs/ru/04-/320/266/320/270/320/267/320/275/320/265/320/275/320/275/321/213/320/271-/321/206/320/270/320/272/320/273-/320/270-/320/264/320/265/320/274/320/276/320/275.md +101 -0
  21. package/docs/ru/05-/321/201/320/270/321/201/321/202/320/265/320/274/320/275/321/213/320/271-/320/277/321/200/320/276/320/274/320/277/321/202.md +82 -0
  22. package/docs/ru/06-/321/205/321/200/320/260/320/275/320/265/320/275/320/270/320/265.md +115 -0
  23. package/docs/ru/07-/321/203/321/201/321/202/320/260/320/275/320/276/320/262/320/272/320/260-/320/270-/320/276/320/261/320/275/320/276/320/262/320/273/320/265/320/275/320/270/320/265.md +87 -0
  24. package/docs/ru/08-/321/203/320/277/321/200/320/260/320/262/320/273/320/265/320/275/320/270/320/265-/320/277/320/270/321/200/320/260/320/274/320/270.md +119 -0
  25. package/docs/ru/09-/321/200/320/260/320/275/321/202/320/260/320/271/320/274/321/213.md +103 -0
  26. package/docs/ru/10-/320/276/320/261/320/274/320/265/320/275-/321/201/320/276/320/276/320/261/321/211/320/265/320/275/320/270/321/217/320/274/320/270.md +69 -0
  27. package/docs/ru/11-/321/200/320/260/321/201/321/210/320/270/321/200/320/265/320/275/320/270/321/217-/320/270-/320/277/320/260/320/274/321/217/321/202/321/214.md +60 -0
  28. package/docs/ru/12-cli-reference.md +96 -0
  29. package/docs/ru/13-/320/260/321/200/321/205/320/270/321/202/320/265/320/272/321/202/321/203/321/200/320/260-/320/270-/320/272/320/276/320/275/321/202/321/200/320/260/320/272/321/202.md +190 -0
  30. package/docs/ru/14-/320/272/320/276/320/275/321/204/320/270/320/263/321/203/321/200/320/260/321/206/320/270/321/217-/320/270-/320/266/321/203/321/200/320/275/320/260/320/273/321/213.md +91 -0
  31. package/docs/ru/README.md +97 -0
  32. package/package.json +8 -2
  33. package/src/cli/index.ts +20 -0
  34. package/src/tui/onboard/app.tsx +260 -0
  35. package/src/tui/onboard/run.tsx +72 -0
  36. package/tsconfig.json +3 -1
@@ -0,0 +1,110 @@
1
+ # 02 — Быстрый старт
2
+
3
+ **Русский** · [English](../02-quickstart.md)
4
+
5
+ Четыре шага — от пустого хоста до агента, которому можно написать. Каждый шаг это одна команда; под ней разобрано, что она делает.
6
+
7
+ ## Требования
8
+
9
+ - **macOS.** Присутствием процессов управляет launchd, поэтому пока поддерживается только macOS.
10
+ - **[bun](https://bun.sh)** на `PATH`. Нужен для установки и обновлений: пакет ставится из исходников (готового скомпилированного JS в нём нет), а бинарь `iapeer` собирается через `bun build --compile`. Сам установленный `~/.local/bin/iapeer` — самостоятельный бинарь и при работе bun уже не требует.
11
+ - **`~/.local/bin` на `PATH`.** Сюда ставится бинарь `iapeer`. Если каталога нет в `PATH`, после установки команда `iapeer` не найдётся — добавьте его: `export PATH="$HOME/.local/bin:$PATH"` в профиль оболочки.
12
+ - **Хотя бы один агентский рантайм** — Claude Code или Codex CLI. Каждый AI-пир это живая сессия одного из них; если не установлен ни один, `iapeer create` и `iapeer init` скажут об этом ошибкой, а не упадут молча позже.
13
+
14
+ ## Шаг 1. Установите ядро
15
+
16
+ ```bash
17
+ npx @agfpd/iapeer
18
+ ```
19
+
20
+ Вызов без аргументов — это установка. Она делает три вещи и ничего не запускает:
21
+
22
+ 1. Собирает бинарь `iapeer` и кладёт в `~/.local/bin/iapeer` (предыдущая версия остаётся рядом как `iapeer.prev` — на случай отката).
23
+ 2. Создаёт раскладку `~/.iapeer/` — каталоги реестра, состояния, логов, кеша и рантаймов.
24
+ 3. Пишет плист демона в `~/Library/LaunchAgents/com.agfpd.iapeer.plist`, но **не загружает** его — это сделает `iapeer onboard` на шаге 2.
25
+
26
+ Установка идемпотентна: повторный запуск обновит бинарь и пересоберёт раскладку, ничего не сломав.
27
+
28
+ ## Шаг 2. Подготовьте хост
29
+
30
+ ```bash
31
+ iapeer onboard
32
+ ```
33
+
34
+ `onboard` готовит хост к появлению агентов и обязателен: первым делом он поднимает демон-роутер, без которого сообщения не доставляются. Что он делает по порядку:
35
+
36
+ - **Демон.** Загружает плист в launchd (идемпотентно) и проверяет, что роутер отвечает. Дальше launchd поднимает демон сам — после падения и после перезагрузки машины. Это запуск постоянного фонового сервиса, поэтому macOS покажет уведомление «iapeer added a background item» — так и должно быть.
37
+ - **Marketplace.** Регистрирует marketplace расширений agfpd в Claude и Codex, чтобы агенты потом ставили capability-плагины.
38
+ - **notifier.** Разворачивает инфраструктурный рантайм планировщика: появляются служебные пиры `timer` (срабатывает по расписанию) и `watcher` (следит за событиями).
39
+ - **Telegram.** Заводит пир-человека — это вы, владелец, — присутствующего через Telegram. Шаг интерактивный: понадобится ваш Telegram user-id.
40
+ - **Память.** Ставит провайдера памяти по умолчанию, если слот свободен.
41
+
42
+ Старт демона идёт всегда; остальные шаги включены по умолчанию, но любой выключается флагом — `--no-notifier`, `--no-telegram`, `--no-memory`. Чтобы увидеть, что команда сделает, ничего не меняя:
43
+
44
+ ```bash
45
+ iapeer onboard --dry-run
46
+ ```
47
+
48
+ Проверьте, что демон жив и хост готов:
49
+
50
+ ```bash
51
+ iapeer status
52
+ ```
53
+
54
+ Вы увидите снимок хоста: версию ядра, здоровье демона, состояние слота памяти.
55
+
56
+ ## Шаг 3. Создайте первого агента
57
+
58
+ ```bash
59
+ iapeer create assistant --runtime claude
60
+ ```
61
+
62
+ Так появляется пир `assistant` на рантайме Claude. Что заводит команда:
63
+
64
+ - рабочую папку — по умолчанию `~/.iapeer/peers/assistant`;
65
+ - профиль пира `peer-profile.json` — имя, рантаймы, описание, природа;
66
+ - запись в реестре, чтобы демон знал о пире;
67
+ - подключение к демону по MCP — через него агент получит инструмент `send_to_peer`;
68
+ - файл доктрины `IAPEER.md` — роль и характер агента (аналог `CLAUDE.md` для пира), который вы потом наполните;
69
+ - общую память, если слот памяти занят.
70
+
71
+ Агент создан, но сессия ещё не запущена — она поднимется на первом сообщении.
72
+
73
+ `IAPEER.md` для пира — то же, что `CLAUDE.md` для проекта: его инструкции и характер. Тот, что в `~/.iapeer/`, действует на всех пиров хоста; тот, что в папке пира, — только на этого пира. А любой другой `.md`, который вы положите в корень папки `.iapeer/` пира (или хоста, `~/.iapeer/`), тоже едет в системный промпт — так что выдать агенту дополнительный контекст можно просто добавив файл. Подробности — в [05 — Идентичность и системный промпт](05-системный-промпт.md).
74
+
75
+ Создать агента можно и из его рабочей папки, без указания пути, командой `iapeer init`. Разницу между `create` и `init` разбирает [08 — Управление пирами](08-управление-пирами.md).
76
+
77
+ **Хотите, чтобы агент отвечал в Telegram?** Подключите к нему бота — и пишите агенту прямо из мессенджера; см. [быстрый старт telegram-runtime](https://github.com/agfpd/telegram-runtime/blob/main/docs/ru/02-быстрый-старт.md).
78
+
79
+ ## Шаг 4. Отправьте первое сообщение
80
+
81
+ ```bash
82
+ iapeer send assistant --message "привет, ты на связи?"
83
+ ```
84
+
85
+ Живой сессии ещё нет, поэтому демон поднимает её и доставляет сообщение. В ответ вы увидите `delivered to assistant (claude)` — или `queued …`, если агент оказался занят.
86
+
87
+ Посмотреть, какие есть пиры и кто сейчас жив:
88
+
89
+ ```bash
90
+ iapeer list
91
+ ```
92
+
93
+ Каждая строка — пир, его рантаймы и состояние: `●` живой, `○` спит, `✕` остановлен.
94
+
95
+ Подключиться к сессии агента вживую, как к обычному терминалу:
96
+
97
+ ```bash
98
+ iapeer attach assistant
99
+ ```
100
+
101
+ Сессия откроется под супервизором; отсоединиться — `Ctrl-]` или просто закрыть терминал. В любом случае сессия продолжает работать в фоне, а переподключиться можно командой `iapeer attach`, когда понадобится.
102
+
103
+ ## Что дальше
104
+
105
+ Базовый круг замкнут: хост готов, агент создан, сообщение доставлено. Дальше по задаче:
106
+
107
+ - Что происходит при пробуждении и усыплении — [04 — Жизненный цикл и демон](04-жизненный-цикл-и-демон.md).
108
+ - Наполнить роль агента и разобраться с системным промптом — [05 — Идентичность и системный промпт](05-системный-промпт.md).
109
+ - Подключить агента к Telegram, добавить второй рантайм, переключить всех пиров на другой рантайм — [09 — Рантаймы](09-рантаймы.md).
110
+ - Поставить агенту расширение или память — [11 — Расширения и память](11-расширения-и-память.md).
@@ -0,0 +1,117 @@
1
+ # 03 — Пиры, рантаймы, идентичность
2
+
3
+ **Русский** · [English](../03-peers-runtimes-identity.md)
4
+
5
+ Углублённая версия трёх базовых понятий из [обзора](01-обзор.md) — с уровнем детализации, нужным, чтобы создавать пиров, переключать их между рантаймами и читать профили.
6
+
7
+ ## Пир
8
+
9
+ Пир — участник системы. У него есть рабочая папка, имя, набор рантаймов и природа.
10
+
11
+ ### Имя (personality)
12
+
13
+ Имя — короткое логическое имя в нижнем регистре: `assistant`, `code-reviewer`, `timer`. Формат по шаблону `^[a-z][a-z0-9-]{0,31}$`: буква, дальше буквы, цифры, дефисы, до 32 символов.
14
+
15
+ Имя не хранится отдельной величиной — оно **выводится из имени рабочей папки**. Папка `~/.iapeer/peers/assistant` даёт имя `assistant`; не-латиница и прочие символы нормализуются к допустимому виду.
16
+
17
+ Отсюда жёсткое правило: **имя и рабочая папка связаны один к одному**. Занятое другим пиром имя — отказ, без молчаливого суффикса для развода коллизии. Имя — это адрес, и он обязан быть однозначным.
18
+
19
+ ### Природа (intelligence)
20
+
21
+ Каждый пир несёт атрибут природы. Он едет вместе с сообщением, поэтому получатель знает, с кем говорит, не полагаясь на догадки.
22
+
23
+ | Значение | Кто это |
24
+ |---|---|
25
+ | `artificial` | AI-агент (Claude, Codex) |
26
+ | `natural` | человек (через Telegram и подобные каналы) |
27
+ | `absent` | программа без интеллекта (планировщик, наблюдатель, веб-хук) |
28
+
29
+ Природа по умолчанию выводится из рантайма: агентские рантаймы дают `artificial`, Telegram — `natural`, notifier — `absent`. При создании пира её можно задать явно.
30
+
31
+ Раньше использовались значения `human` и `scripted` — они и сейчас читаются (понимаются как `natural` и `absent` соответственно), но при записи система сохраняет то значение, что уже стоит в профиле, и не переписывает уже заведённых пиров.
32
+
33
+ ## Рантайм
34
+
35
+ Рантайм — способ присутствия пира. Имя рантайма короче имени пира: формат `^[a-z][a-z0-9]{0,31}$`, без дефисов. Это важно для разбора идентичности (ниже).
36
+
37
+ ### Два класса рантаймов
38
+
39
+ **claude, codex** — AI-агенты. Сессию не держат запущенной постоянно: демон поднимает агента на входящее сообщение и закрывает сессию после часа простоя. Этим рантаймом демон управляет полностью — поднимает и усыпляет.
40
+
41
+ **telegram, notifier** — рантаймы-роутеры, не AI. Telegram-мост принимает входящие в любой момент, notifier срабатывает по расписанию — поэтому работают постоянно под launchd с автоперезапуском. Такой рантайм демон **не трогает**: пробуждение и усыпление к нему неприменимы, его жизненным циклом распоряжается launchd. Это инфраструктурные рантаймы.
42
+
43
+ Деление — граница ответственности: демон отвечает за claude/codex, launchd — за инфраструктурные. Команды `stop`/`start`/`new` работают по-разному в зависимости от класса (см. [08 — Управление пирами](08-управление-пирами.md)).
44
+
45
+ ### Несколько рантаймов у одного пира
46
+
47
+ Пир может объявлять несколько рантаймов. В профиле это два поля:
48
+
49
+ - **`runtimes`** — список всех рантаймов, на которых пир может присутствовать, например `["claude", "codex"]`.
50
+ - **`default_runtime`** — основной рантайм: куда по умолчанию маршрутизируются сообщения и какой рантайм поднимается первым.
51
+
52
+ Добавить пиру рантайм и сделать его основным — разные операции. Первая (`add-runtime`) расширяет возможности, не меняя маршрутизацию; вторая (`default-runtime`) переключает основной рантайм. Массовое переключение `default_runtime` по всем пирам — это и есть момент «пересадки» команды с одного агентского рантайма на другой. См. [09 — Рантаймы](09-рантаймы.md).
53
+
54
+ Список рантаймов пополняется и сам: при инициализации пира система сканирует его папку на признаки рантаймов (каталоги `.claude`, `.codex` и подпапки в `runtimes/`) и добавляет найденное в `runtimes`. Так список остаётся актуальным, даже когда рантайм появился у пира органически, а не был объявлен явно.
55
+
56
+ ## Идентичность
57
+
58
+ Идентичность — адрес конкретного живого присутствия пира. Складывается из рантайма и имени через дефис:
59
+
60
+ ```text
61
+ PEER_IDENTITY = PEER_RUNTIME + "-" + PEER_PERSONALITY
62
+ ```
63
+
64
+ Пир `assistant` в Claude — это `claude-assistant`; он же в Codex — `codex-assistant`. Имя одно, идентичности две.
65
+
66
+ Разбор идентичности идёт **по первому дефису**: всё слева — рантайм, всё справа — имя. Поскольку в имени рантайма дефисов нет, а в имени пира они допустимы, разбор однозначен: `claude-code-reviewer` — это рантайм `claude` и пир `code-reviewer`.
67
+
68
+ ### ABI идентичности
69
+
70
+ Три значения образуют ABI — набор переменных окружения, по которым любой компонент системы понимает, кто он:
71
+
72
+ | Переменная | Значение | Пример |
73
+ |---|---|---|
74
+ | `PEER_PERSONALITY` | имя пира | `assistant` |
75
+ | `PEER_RUNTIME` | рантайм текущей сессии | `claude` |
76
+ | `PEER_IDENTITY` | полный адрес | `claude-assistant` |
77
+
78
+ Когда демон поднимает сессию агента, он передаёт эти переменные в окружение. Агент по ним знает своё имя и от чьего лица отправляет сообщения. Рантайм текущей сессии определяется в таком порядке: из заголовка идентичности (`PEER_IDENTITY`), затем из профиля, затем из `PEER_RUNTIME`, и в последнюю очередь — автоопределением по признакам рантайма в окружении: Codex выставляет `CODEX_THREAD_ID`, Claude — `CLAUDECODE=1`. Если не сработал ни один источник, подъём отклоняется с требованием задать `PEER_RUNTIME` или завести профиль.
79
+
80
+ ## Профиль и реестр
81
+
82
+ У идентичности два места хранения, и важно понимать, какое из них главное.
83
+
84
+ ### Профиль пира — источник истины
85
+
86
+ `<папка-пира>/.iapeer/peer-profile.json` — это карточка пира, единственный источник истины о нём. Вот реальный профиль:
87
+
88
+ ```json
89
+ {
90
+ "personality": "assistant",
91
+ "runtimes": ["codex", "claude"],
92
+ "default_runtime": "claude",
93
+ "runtime": "claude",
94
+ "description": "Помощник общего профиля. Принимает задачи через IAP.",
95
+ "intelligence": "artificial",
96
+ "initial_prompt": "Новая сессия. Поздоровайся с владельцем.",
97
+ "interfaces": {
98
+ "telegram": { "bot": "assistant", "bot_username": "assistant_bot" }
99
+ }
100
+ }
101
+ ```
102
+
103
+ Поля профиля делятся на три класса по тому, кто ими владеет:
104
+
105
+ - **Ядро идентичности** — `personality`, `default_runtime`, `runtimes`, `description`, `intelligence`, `initial_prompt`. Этим владеет ядро и жизненный цикл. Поле `initial_prompt` — затравка первого хода свежей сессии. Поле `runtime` рядом с `default_runtime` — это синхронная копия для совместимости со старыми читателями; оба пишутся согласованно.
106
+ - **Приватная конфигурация плагина** — секции вроде `expansion` (шорткаты-алиасы), `notifier` (настройка пира-планировщика) и прочие, по одной на плагин. Читаются только из локального профиля, в реестр не попадают.
107
+ - **Публичный паспорт** — секция `interfaces` (например `interfaces.telegram.bot`). Это атрибуты маршрутизации, и они проецируются в реестр.
108
+
109
+ Описание `description` ограничено по длине (сейчас 450 символов) — оно само-документирующее, его видят другие пиры в реестре.
110
+
111
+ ### Реестр — производная
112
+
113
+ `~/.iapeer/peers-profiles.json` — общий реестр всех пиров. Демон читает его, чтобы понять, кому доставлять сообщение и какие у пира рантаймы. Запись реестра содержит проекцию профиля: имя, основной рантайм, список рантаймов, описание, природа, рабочая папка, публичные интерфейсы.
114
+
115
+ Реестр — не источник истины, а **проекция** локальных профилей. Его можно пересобрать из профилей в любой момент (`iapeer verify --fix`). Если реестр и профиль разошлись, прав профиль — реестр чинится по нему.
116
+
117
+ Реестр пишется только через единственного писателя под файловой блокировкой — прямое редактирование `peers-profiles.json` запрещено на уровне ядра. Это исключает гонки, когда несколько процессов одновременно меняют состав пиров. Подробнее о раскладке и владении — [06 — Хранение](06-хранение.md).
@@ -0,0 +1,101 @@
1
+ # 04 — Жизненный цикл и демон
2
+
3
+ **Русский** · [English](../04-lifecycle-and-daemon.md)
4
+
5
+ ## Демон-роутер
6
+
7
+ Демон — единственный постоянно работающий процесс ядра. У него три роли:
8
+
9
+ 1. **Маршрутизация** — принимает `send_to_peer`, находит получателя в реестре, доставляет.
10
+ 2. **Пробуждение** — поднимает сессию спящего получателя и доставляет после подъёма.
11
+ 3. **Надзор** — раз в минуту обходит пиров: усыпляет простаивающих, замечает упавших, перезапускает помеченных на свежий старт.
12
+
13
+ Демон держит launchd по плисту `com.agfpd.iapeer` — отдельному от плистов пиров. launchd поднимает демон при загрузке системы и перезапускает при падении, поэтому роутер переживает и перезагрузку машины, и собственные сбои.
14
+
15
+ Слушает демон на двух входах одновременно:
16
+
17
+ - **локальный сокет** `~/.iapeer/state/iapeer/router.sock` (доступ только владельцу) — для CLI и рантаймов-роутеров;
18
+ - **TCP на петле** `127.0.0.1:8765` — для агентов Claude и Codex, подключённых к `send_to_peer` по HTTP.
19
+
20
+ ### Надзорный тик
21
+
22
+ Раз в минуту демон выполняет надзорный обход. За один тик он усыпляет агентов, простоявших дольше часа; замечает умершие сессии и решает их судьбу; поднимает свежими помеченных на немедленный перезапуск; докармливает очереди эфемерных воркеров. Минута — это потолок задержки для отложенной работы: очередь, накопившаяся за окно перезапуска демона, разгребётся на ближайшем тике.
23
+
24
+ ## Состояния пира
25
+
26
+ Агент claude/codex в каждый момент в одном из трёх состояний:
27
+
28
+ | Состояние | Что значит | Метка в `iapeer list` |
29
+ |---|---|---|
30
+ | **живой** | сессия запущена и отвечает | `●` |
31
+ | **спит** | сессии нет, пир готов проснуться по сообщению | `○` |
32
+ | **остановлен** | оператор поставил стоп-флаг; демон не будит | `✕` |
33
+
34
+ ```text
35
+ сообщение
36
+ спит ──────────────▶ живой
37
+ ▲ │
38
+ │ снят стоп-флаг │ час простоя / падение
39
+ │ ▼
40
+ остановлен ◀────────── живой
41
+ стоп (оператор)
42
+ ```
43
+
44
+ ## Доставка и пробуждение
45
+
46
+ На входящее сообщение демон смотрит на состояние получателя:
47
+
48
+ - **живой** — вставляет в сессию, подтверждает приём, отвечает `доставлено`;
49
+ - **спит** — поднимает сессию, перепроверяет получателя, доставляет, отвечает `доставлено, разбудил`;
50
+ - **остановлен** — отказывает и сообщает отправителю прямо.
51
+
52
+ Гарантию «`доставлено` значит легло в живую сессию» разбирает [10 — Обмен сообщениями](10-обмен-сообщениями.md).
53
+
54
+ ### Свежий старт или продолжение диалога
55
+
56
+ Поднимая спящего, демон выбирает: начать **свежую** сессию или **продолжить** прежний диалог. Зависит от того, чем будят, от типа пира и — для агентов — от **топика** входящего сообщения.
57
+
58
+ Три типа пира — три базовых поведения: **эфемерный воркер** всегда стартует свежим, **человек** (Telegram) всегда продолжает, **агент** продолжает только по совпавшему топику. Полная развёртка:
59
+
60
+ | Чем разбудили | Условие | Результат |
61
+ |---|---|---|
62
+ | `iapeer <runtime>` (из папки) | — | 🆕 свежий |
63
+ | `iapeer attach` | — | ▶️ продолжение (ошибка, если продолжать нечего) |
64
+ | сообщение | упал / закрылся сам / никогда не запускался | 🆕 свежий |
65
+ | сообщение | усыплён за простой, пир-**человек** (Telegram) | ▶️ продолжение (всегда) |
66
+ | сообщение | усыплён за простой, **агент** · топик совпал с нитью сессии | ▶️ продолжение |
67
+ | сообщение | усыплён за простой, **агент** · топик новый или его нет | 🆕 свежий |
68
+ | сообщение | пир остановлен (`stop`) | 🚫 не будится — явный отказ |
69
+
70
+ Ключевое для агентов: **продолжение включается явно — через топик**. Сообщение без топика после простоя поднимает свежую сессию, а не воскрешает старый контекст (иначе оживёт сессия многодневной давности и продолжит не ту работу). Чтобы продолжить нужную нить — отправитель указывает её топик. Топики **копятся**: в одной сессии может идти несколько нитей, и пинг по любой из них (не только последней) продолжит её. Для пиров-людей продолжение всегда — топик их не сбрасывает.
71
+
72
+ Ленивый сброс на свежесть — **`iapeer refresh`** (см. «Команды жизненного цикла» ниже): помечает пира, и на его ближайшем естественном пробуждении он стартует свежим вместо продолжения — для любого типа, включая людей-в-Telegram. Так после обновления доктрины команда перечитывает её сама собой, без ручного `/new` и без массового пробуждения.
73
+
74
+ ## Усыпление при простое
75
+
76
+ Агент, не проявлявший активности дольше часа, усыпляется на ближайшем надзорном тике: демон закрывает сессию и ставит метку усыпления. Память освобождается, диалог сохраняется на диске — следующее сообщение **с топиком той работы** поднимет агента ровно там, где он остановился (без топика или с новым — свежим, см. выше). Час простоя — единственная временна́я граница: «слепого» TTL по времени жизни нет. Порог простоя по умолчанию — 3600 секунд; он и другие пороги жизненного цикла (загрузка, готовность, защита от цикла перезапусков) настраиваются переменными окружения — [14 — Конфигурация и журналы](14-конфигурация-и-журналы.md).
77
+
78
+ ## Надзор и устойчивость
79
+
80
+ **Защита от цикла перезапусков.** Демон ведёт кольцо последних смертей каждого пира. Если за 5 минут пир умирает 3 раза, демон перестаёт его поднимать и оставляет спящим — это сигнал неисправности, а не сотая попытка вслепую.
81
+
82
+ **Сериализация пробуждений.** На спящего агента может прилететь несколько сообщений сразу; поднять его должна одна попытка, иначе родятся две конкурирующие сессии. Демон берёт блокировку на пробуждение конкретного пира — остальные ждут готовности первой.
83
+
84
+ **Посмертная диагностика.** Супервизор в момент смерти сессии фиксирует её причину (код выхода / сигнал) — это то, что обычная проверка «жив ли процесс» не ловит. На этот случай отдельный сторож (canary) держит блокирующее соединение с супервизором и при смерти сессии записывает обстоятельства — память, swap, список процессов, отчёты диагностики — в журнал.
85
+
86
+ ## Граница: claude/codex против инфраструктурных
87
+
88
+ Демон управляет только агентами claude/codex и только теми, чей плист принадлежит ядру. Инфраструктурные пиры (Telegram, notifier) и любые пиры под чужим launchd-плистом для демона неприкосновенны: он их не будит, не усыпляет, не перезапускает. Их жизненным циклом распоряжается launchd.
89
+
90
+ Поэтому `stop`, `start`, `new` отказываются трогать чужие launchd-пиры — для них ядро только читатель. Это защита от драки ядра с launchd за управление процессом.
91
+
92
+ ## Команды жизненного цикла
93
+
94
+ - **`iapeer stop` / `start`** — остановить (стоп-флаг + закрыть сессию) и снять остановку. Для инфраструктурных — через launchd.
95
+ - **`iapeer new`** — безусловный свежий перезапуск, аварийный рычаг для зависшей или мёртвой сессии; действует механически, в обход агента.
96
+ - **`iapeer refresh <пир> \| --all`** — ленивый «мягкий перезапуск»: пометить пира на свежий старт при его СЛЕДУЮЩЕМ естественном пробуждении (перечитать доктрину/фрагменты с диска), не убивая живую сессию и не будя остальных. В отличие от `new` (немедленный жёсткий перезапуск) — это отложенный, ненавязчивый рычаг: применяют после релиза доктрины, чтобы команда освежилась сама собой. Маркер перекрывает «продолжение» для всех типов пиров, включая людей-в-Telegram (которые иначе продолжают старую сессию до явного `/new`).
97
+ - **`iapeer compact`** — сжать диалог; спящего после усыпления демон сначала продолжит, потом сожмёт.
98
+ - **`iapeer interrupt`** — прервать текущий ход (Escape), не теряя контекст.
99
+ - **`iapeer self-fresh` / `self-done`** — самовызовы агента: пометить себя на свежий перезапуск или тихо завершиться (для эфемерных воркеров).
100
+
101
+ Поведение по классам рантаймов — [08 — Управление пирами](08-управление-пирами.md); эфемерные воркеры — [10 — Обмен сообщениями](10-обмен-сообщениями.md).
@@ -0,0 +1,82 @@
1
+ # 05 — Идентичность и системный промпт
2
+
3
+ **Русский** · [English](../05-system-prompt.md)
4
+
5
+ Чтобы агент знал своё имя, роль и соседей по команде, iapeer собирает ему системный промпт — текст, который рантайм получает до начала диалога. Промпт складывается из слоёв: часть пишет человек, часть собирает система.
6
+
7
+ ## Зачем подменять системный промпт
8
+
9
+ У Claude и Codex есть собственный встроенный системный промпт — тот, что делает их «ассистентом по коду». iapeer заменяет его целиком: вместо родного промпта рантайм получает собранный iapeer текст, где агент описан как пир команды — со своим именем, ролью, знанием о соседях и общими правилами.
10
+
11
+ Замена идёт штатным механизмом каждого рантайма:
12
+
13
+ - **Claude** — флагом `--system-prompt-file <файл>`;
14
+ - **Codex** — настройкой `model_instructions_file` (`codex -c model_instructions_file=<файл>`), которая подменяет компилированные базовые инструкции.
15
+
16
+ Инфраструктурные рантаймы (Telegram, notifier) системный промпт не получают — это не языковые модели, им нечего им наполнять.
17
+
18
+ ## Слои промпта
19
+
20
+ Промпт собирается из слоёв, от общего к частному. Каждый слой при пустом содержимом просто выпадает — лишних разделов не появляется.
21
+
22
+ ```text
23
+ 1. Блок идентичности (YAML) ← система, всегда свежий
24
+ 2. Доктрина IAPEER.md ← человек: общая + персональная
25
+ 3. Реестр пиров ← система: кто ещё в команде
26
+ 4. Доменные файлы (любой .md по имени)← человек/плагин
27
+ 5. Доктринальные фрагменты ← плагины-примитивы, машинно
28
+ ```
29
+
30
+ ### Слой 1 — блок идентичности
31
+
32
+ Динамический YAML-блок в начале промпта. Система синтезирует его при каждом запуске из профиля пира и фактов о хосте: имя, описание, рабочая папка, платформа, версия ОС, пользователь, имя машины, сегодняшняя дата. Значения экранируются, поэтому двоеточия, кавычки и переводы строк в описании не ломают разметку.
33
+
34
+ Этот слой всегда свежий — дата и факты о хосте подставляются заново на каждый запуск.
35
+
36
+ ### Слой 2 — доктрина IAPEER.md
37
+
38
+ Главный слой, который наполняет человек, — для пира то же, что `CLAUDE.md` для проекта: постоянные инструкции и характер агента. Это два файла:
39
+
40
+ - **Общая доктрина** `~/.iapeer/IAPEER.md` — правила, действующие для всех пиров хоста: как отвечать на обращения, как обращаться с памятью, общие договорённости команды.
41
+ - **Персональная доктрина** `<папка-пира>/.iapeer/IAPEER.md` — роль и характер конкретного пира: кто он, чем занимается, какие у него зоны ответственности.
42
+
43
+ Порядок — от общего к частному: сначала общая доктрина, затем персональная. Частное идёт после общего и уточняет его. Каждый файл вставляется как отдельная помеченная секция со своей меткой-путём (HTML-комментарий с путём файла, видимый модели), чтобы агент понимал, откуда взялось каждое правило.
44
+
45
+ Оба файла редактирует оператор обычным markdown. Это и есть то место, где задаётся, кем будет агент.
46
+
47
+ ### Слой 3 — реестр пиров
48
+
49
+ Система вставляет краткую сводку по всем пирам команды: имя, основной рантайм, список рантаймов, описание, природа. Так агент знает, к кому он может обратиться через `send_to_peer` и кто чем занимается. Сводка отсортирована по именам; если пиров нет — слой выпадает.
50
+
51
+ Здесь и работает само-документирующее `description` из профиля: оно ограничено по длине именно потому, что попадает в промпт каждого пира — раздутые описания стоили бы контекста всей команде.
52
+
53
+ Для сервис-пира — скажем, `timer` и `watcher` нотифаера — это описание несёт сам формат вызова: JSON-поля и пример. Так агент умеет управлять сервисом из одного своего промпта, а когда нужно больше — просто спрашивает сервис (на `help` тот отвечает полным форматом). Реестр учит вызову; остальное пир документирует сам.
54
+
55
+ ### Слой 4 — доменные файлы по имени
56
+
57
+ Любой markdown-файл в корне `.iapeer/`, кроме `IAPEER.md`, едет в промпт своей секцией. Этот канал открыт и вам, не только плагинам: положите `SOUL.md` (или любое имя) в `~/.iapeer/` — его увидит каждый пир хоста; положите в папку `.iapeer/` одного пира — увидит только он. Выдать агенту дополнительный контекст — это просто добавить файл.
58
+
59
+ Как и доктрина, каждый файл бывает общим (`~/.iapeer/<ДОМЕН>.md`) и персональным (`<папка-пира>/.iapeer/<ДОМЕН>.md`), вставляется от общего к частному. Сканируется только корень `.iapeer/` — не подпапки. Файлы идут в детерминированном порядке (по алфавиту имени), каждый — отдельной помеченной секцией, пустые выпадают. Плагины пользуются этим же каналом для своих настроек (`<ДОМЕН>.md` на плагин); ваши файлы вручную и файлы плагина стоят бок о бок.
60
+
61
+ ### Слой 5 — доктринальные фрагменты
62
+
63
+ Последний слой — фрагменты, которые генерируют машинно плагины-примитивы. Они лежат в подпапке `fragments/` обоих корней (`~/.iapeer/fragments/` и `<папка-пира>/.iapeer/fragments/`). Например, провайдер памяти кладёт сюда актуальную карту памяти агента.
64
+
65
+ Этот слой — самый изменчивый, поэтому он идёт последним и **перечитывается на каждом свежем подъёме сессии**. Когда у агента меняется память или другой машинный контекст, обновлённый фрагмент попадёт в промпт при следующем запуске.
66
+
67
+ ## Сборка и неизменность в сессии
68
+
69
+ Слои склеиваются в один файл с пустой строкой между секциями. Этот файл и передаётся рантайму флагом подмены промпта.
70
+
71
+ Системный промпт фиксируется в момент подъёма сессии и не меняется, пока сессия живёт. Когда демон поднимает агента заново — свежим или продолжая прежний диалог, — он пересобирает файл, поэтому свежие фрагменты слоя 5 и актуальная дата подтягиваются на каждом подъёме. Это проверено: продолжение диалога переприменяет новый файл промпта, а не тянет старый.
72
+
73
+ Подмена доставляет системный промпт iapeer — личность пира. Она не отключает собственные нативные файлы инструкций рантайма: `CLAUDE.md` (Claude) или `AGENTS.md` (Codex) работают ровно так же, как вне iapeer, — читаются как постоянные инструкции, которым модель следует. Это два независимых канала — личность iapeer через подмену и нативные `CLAUDE.md`/`AGENTS.md` рантайма — и действуют они вместе. Так что если вы приносите готовый проект, где уже есть `CLAUDE.md`, он продолжит работать рядом с промптом iapeer; а сами эти файлы работают и без iapeer вообще.
74
+
75
+ ## Что наполнять вам
76
+
77
+ Из всех слоёв руками наполняют два файла:
78
+
79
+ - `~/.iapeer/IAPEER.md` — общие правила команды (один раз на хост);
80
+ - `<папка-пира>/.iapeer/IAPEER.md` — роль каждого пира.
81
+
82
+ Остальное — блок идентичности, реестр, фрагменты — система и плагины собирают сами. Раскладку каталогов, где лежат эти файлы, разбирает [06 — Хранение](06-хранение.md).
@@ -0,0 +1,115 @@
1
+ # 06 — Хранение
2
+
3
+ **Русский** · [English](../06-storage.md)
4
+
5
+ Состояние iapeer лежит в двух местах: общий каталог хоста `~/.iapeer/` и каталог `.iapeer/` внутри рабочей папки каждого пира.
6
+
7
+ ## Два уровня хранения
8
+
9
+ **Общий уровень** `~/.iapeer/` — всё, что касается хоста целиком: реестр пиров, состояние демона, общие настройки, установленные пакеты рантаймов.
10
+
11
+ **Уровень пира** `<папка-пира>/.iapeer/` — всё, что касается одного пира: его профиль, доктрина, состояние его плагинов, журналы его сессий.
12
+
13
+ Один и тот же плагин может хранить данные на обоих уровнях: общие — в `~/.iapeer/`, привязанные к конкретному пиру — в его папке.
14
+
15
+ ## Раскладка общего уровня
16
+
17
+ ```text
18
+ ~/.iapeer/
19
+ ├── IAPEER.md доктрина хоста (общая для всех пиров; слой 2 промпта)
20
+ ├── peers-profiles.json реестр всех пиров (пишется под блокировкой)
21
+ ├── peers-profiles.lock файл блокировки реестра
22
+ ├── memory-provider.json слот памяти: кто провайдер (если занят)
23
+ ├── fragments/ общие доктринальные фрагменты (слой 5 промпта)
24
+ ├── peers/
25
+ │ └── <имя>/ рабочая папка пира по умолчанию
26
+ │ └── .iapeer/ (раскладка уровня пира — см. ниже)
27
+ ├── state/
28
+ │ ├── iapeer/ состояние демона (router.sock, router.json …)
29
+ │ └── <плагин>/ изменяемое состояние плагина
30
+ ├── logs/
31
+ │ ├── iapeer/ журналы демона: lifecycle.log, delivery.log, exits.log
32
+ │ └── <имя>/ журналы инфраструктурного пира (по имени)
33
+ ├── cache/
34
+ │ ├── iapeer/ кеш ядра
35
+ │ └── <плагин>/ кеш плагина (можно удалять)
36
+ ├── plugins/
37
+ │ ├── iap/ установка ядрового плагина IAP
38
+ │ └── <плагин>/ установка плагина (неизменяемая)
39
+ └── runtimes/
40
+ ├── claude/
41
+ │ └── plugins/<плагин>/ конфиг плагина под рантаймом claude
42
+ ├── codex/
43
+ │ └── plugins/<плагин>/
44
+ ├── telegram/
45
+ │ └── runtime.json манифест рантайм-пакета
46
+ └── notifier/
47
+ └── runtime.json
48
+ ```
49
+
50
+ Несколько узлов стоит выделить:
51
+
52
+ - **`peers-profiles.json`** — реестр. Пишется только через единственного писателя под файловой блокировкой `peers-profiles.lock`; прямое редактирование запрещено на уровне ядра.
53
+ - **`state/iapeer/`** — здесь живёт демон: его локальный сокет `router.sock` и конфигурация `router.json`.
54
+ - **`logs/<имя>/`** — журналы инфраструктурных пиров кладутся по имени пира на общем уровне (а не в папке пира), потому что это вывод службы под launchd.
55
+ - **`runtimes/<рантайм>/`** — двойное владение: корень принадлежит самому рантайму (Telegram держит здесь токены ботов, состояние опроса), а подпапка `plugins/<плагин>/` — это пространство плагинов, где лежит их конфиг под этим рантаймом.
56
+
57
+ ## Раскладка уровня пира
58
+
59
+ ```text
60
+ <папка-пира>/.iapeer/
61
+ ├── peer-profile.json профиль пира — источник истины о нём
62
+ ├── IAPEER.md персональная доктрина (слой 2 промпта)
63
+ ├── fragments/ персональные доктринальные фрагменты (слой 5)
64
+ ├── plugins/
65
+ │ ├── iap/
66
+ │ └── <плагин>/ данные плагина для этого пира
67
+ ├── state/
68
+ │ ├── iap/
69
+ │ └── <плагин>/
70
+ ├── logs/
71
+ │ ├── iap/
72
+ │ └── <плагин>/
73
+ ├── cache/
74
+ │ ├── iap/
75
+ │ └── <плагин>/
76
+ └── runtimes/
77
+ ├── claude/
78
+ │ ├── launch.env аргументы и переменные запуска для этого рантайма
79
+ │ └── plugins/<плагин>/
80
+ └── codex/
81
+ ├── launch.env
82
+ └── plugins/<плагин>/
83
+ ```
84
+
85
+ - **`peer-profile.json`** — карточка пира и единственный источник истины о нём (поля разобраны в [03 — Пиры, рантаймы, идентичность](03-пиры-рантаймы-идентичность.md)).
86
+ - **`launch.env`** — файл вида `KEY=VALUE` для конкретной пары пир+рантайм: дополнительные аргументы запуска (`PEER_START_ARGS`) и переменные окружения. Так одному пиру можно задать особые флаги запуска, не трогая остальных.
87
+
88
+ Рабочая папка пира не обязана лежать в `~/.iapeer/peers/`. По умолчанию `iapeer create` кладёт её туда, но пиром можно сделать любую папку командой `iapeer init` — тогда `.iapeer/` появится прямо в ней.
89
+
90
+ ## Кто чем владеет
91
+
92
+ Граница владения проста: каждый владеет содержимым своей папки и не лезет в чужие.
93
+
94
+ | Владелец | Что принадлежит |
95
+ |---|---|
96
+ | **Ядро (`iapeer`)** | `peers-profiles.json`, `state/iapeer/`, `logs/iapeer/`, `cache/iapeer/` |
97
+ | **Рантайм** | корень `runtimes/<рантайм>/` — кроме подпапки `plugins/` |
98
+ | **Плагин** | своя папка `<плагин>/` во всех категориях (`state`, `logs`, `cache`, `plugins`) на обоих уровнях |
99
+
100
+ Имя `iapeer` в категориях зарезервировано за ядром. Рантайм никогда не трогает `plugins/<плагин>/` внутри своего пространства, а плагин — корень рантайма.
101
+
102
+ ## Классы данных по сроку жизни
103
+
104
+ Установка отделена от изменяемых данных — это важно для обновлений и для уборки:
105
+
106
+ - **Установка** (`plugins/<плагин>/`) — неизменяемая. Это разложенный код плагина; обновление заменяет его целиком.
107
+ - **Состояние** (`state/`) — изменяемые данные, которые нужно беречь: их потеря — потеря работы.
108
+ - **Журналы** (`logs/`) — вывод процессов; полезны для разбора, но не критичны. Что пишется в `lifecycle.log`, `delivery.log`, `exits.log` и как настроить их ротацию — [14 — Конфигурация и журналы](14-конфигурация-и-журналы.md).
109
+ - **Кеш** (`cache/`) — восстановимые данные; их можно удалить без последствий, система пересоздаст.
110
+
111
+ Такое разделение означает, что обновить плагин — значит заменить его папку установки, не задев его состояние; а почистить место — значит удалить кеш, не рискуя данными.
112
+
113
+ ## Реестр как производная
114
+
115
+ Стоит повторить ключевой принцип хранения: **реестр `peers-profiles.json` — это проекция локальных профилей, а не отдельный источник истины.** Источник истины о пире — его `peer-profile.json`. Реестр можно пересобрать из профилей в любой момент командой `iapeer verify --fix`. При расхождении между реестром и профилем прав профиль. Поэтому потеря или порча реестра не фатальна — он восстанавливается обходом рабочих папок пиров.