@agfpd/iapeer 0.4.0 → 0.4.2

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.
package/README.md CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  **Host-level core for a team of AI agents on one machine.**
4
4
 
5
+ [![CI](https://github.com/agfpd/iapeer/actions/workflows/ci.yml/badge.svg)](https://github.com/agfpd/iapeer/actions/workflows/ci.yml)
5
6
  [![npm](https://img.shields.io/npm/v/@agfpd/iapeer)](https://www.npmjs.com/package/@agfpd/iapeer)
6
- [![license](https://img.shields.io/badge/license-Apache--2.0-blue)](./LICENSE)
7
+ [![license](https://img.shields.io/npm/l/@agfpd/iapeer)](./LICENSE)
7
8
  [![platform](https://img.shields.io/badge/platform-macOS-lightgrey)](#quick-start)
8
9
 
9
10
  iapeer keeps a team of AI agents, humans, and services on one host **always reachable — every one of them a single message away.** Each participant is a **peer**: a Claude Code or Codex CLI agent, a person on Telegram, or a scheduler/watcher service. Any agent reaches any other with one call — `send_to_peer(<name>, <text>)` — and a peer that is asleep is still reachable: the daemon wakes it and delivers. Agents on Claude and on Codex — different AI runtimes from different vendors — talk as equal peers; humans take part over Telegram, or directly in the terminal — attached to a peer's live session with `iapeer attach`.
@@ -95,7 +95,7 @@ Identity has two storage places, and it matters which is authoritative.
95
95
  "intelligence": "artificial",
96
96
  "initial_prompt": "New session. Greet the owner.",
97
97
  "interfaces": {
98
- "telegram": { "bot": "assistant", "bot_username": "assistant_bot" }
98
+ "telegram": { "bot": "assistant" }
99
99
  }
100
100
  }
101
101
  ```
@@ -33,6 +33,9 @@ The same plugin can store data at both levels: shared in `~/.iapeer/`, peer-boun
33
33
  ├── cache/
34
34
  │ ├── iapeer/ core cache
35
35
  │ └── <plugin>/ plugin cache (safe to delete)
36
+ ├── docs/
37
+ │ ├── iapeer/ foundation reference docs (this host's installed version)
38
+ │ └── <package>/ each ecosystem package's docs (copied on its install)
36
39
  ├── plugins/
37
40
  │ ├── iap/ the core IAP plugin's install
38
41
  │ └── <plugin>/ a plugin's install (immutable)
@@ -53,6 +56,15 @@ A few nodes worth highlighting:
53
56
  - **`state/iapeer/`** — where the daemon lives: its local socket `router.sock` and config `router.json`.
54
57
  - **`logs/<name>/`** — an infrastructure peer's logs are placed by peer name at the shared level (not in the peer's folder), because it's the output of a launchd service.
55
58
  - **`runtimes/<runtime>/`** — dual ownership: the root belongs to the runtime itself (Telegram keeps bot tokens and poll state here), while the `plugins/<plugin>/` subfolder is the plugins' space, holding their config under this runtime.
59
+ - **`docs/<package>/`** — on-host reference docs, one folder per ecosystem package (see below).
60
+
61
+ ## On-host ecosystem docs
62
+
63
+ `~/.iapeer/docs/<package>/` holds a copy of each ecosystem package's reference docs, so an agent can read the contract offline at a stable, versioned path. It exists because a compiled binary embeds no docs and the npm tarball's `docs/` is discarded after install — a reference into a transient install or cache directory would go dead on the first update.
64
+
65
+ The convention is **copy-on-install, per package**: every package copies its own public docs (excluding `internals/`) into its own `~/.iapeer/docs/<package>/` on each of its installs and updates, via an atomic swap, best-effort — a copy failure never fails the install. Because the copy happens in the same install that places the artifact, a package's on-host docs always match its installed version. Each package writes only its own subfolder, the same ownership isolation as everywhere else; the folder name is the short unscoped package name (`iapeer`, `iapeer-memory`, `telegram-runtime`, `notifier-runtime`).
66
+
67
+ A peer's system prompt points here — `~/.iapeer/docs/`, one folder per package, starting at `iapeer/README.md` — so a "how does iapeer do X" question is answered from the docs rather than guessed.
56
68
 
57
69
  ## The peer-level layout
58
70
 
@@ -47,25 +47,32 @@ You'll see the core version, the daemon's health, and the memory-slot state. The
47
47
 
48
48
  A breakdown of each onboard step is in [02 — Quick start](02-quickstart.md); runtimes and memory in detail — in [09](09-runtimes.md) and [11](11-extensions-and-memory.md).
49
49
 
50
- ## Updating the core
50
+ ## Updating
51
51
 
52
52
  ```bash
53
- iapeer update # to the latest version
54
- iapeer update 0.2.80 # to a specific version
55
- iapeer update --force # reinstall even if the version is already in place
53
+ iapeer update # cascade-update the WHOLE stack: core + runtimes + memory
54
+ iapeer update --foundation-only # update just the core
55
+ iapeer update 0.2.80 # pin the CORE to a specific version (core only)
56
+ iapeer update --force # reinstall even if the version is already in place
56
57
  ```
57
58
 
58
- An update pulls the core version from npm and restarts the daemon onto it. Step by step:
59
+ A bare `iapeer update` updates the **whole host stack** in one command — the core (foundation), every installed runtime, and the memory provider — so "updated" means the whole machine, not just the core. The core goes first; the runtimes and memory follow only if the core came up healthy.
60
+
61
+ **1. Core (foundation)** — and it ABORTS the cascade on a hard failure (never update runtimes onto a broken core):
59
62
 
60
63
  1. Learns the target version from npm. If the installed one already matches and there's no `--force` — it does nothing.
61
- 2. Downloads and builds the new binary. This is done via `npm pack`, not `npx`: the binary doesn't rebuild itself.
64
+ 2. Downloads and builds the new binary via `npm pack`, not `npx` (the binary doesn't rebuild itself).
62
65
  3. Restarts the daemon onto the new binary.
63
- 4. Restarts the infrastructure launchd jobs the core owns (`com.iapeer.*` — the `timer`, `watcher`, Telegram routers), moving them onto the just-replaced binary. Their plists launch the same core binary as the daemon — without a restart a job would stay on the old code. It's the job that's restarted (booted out and back in); the runtimes' **package code** (telegram-runtime, notifier-runtime) is not updated by this — that's the separate `update-runtime` operation. The memory provider (`iapeer-memory`) and ordinary peers' plists aren't touched at all. If the daemon didn't come up in step 3, this step is skipped — no point moving jobs onto a binary the daemon didn't revive on.
64
- 5. Verifies the daemon actually came up healthy — not by the restart command exiting successfully, but by a probe: it connects to the daemon's socket (the one the daemon opens right before the readiness signal). The daemon counts as healthy only when the socket accepts a connection **twice in a row** — a single probe would also pass for a daemon that bound the socket and immediately crashed. The check is given 15 seconds; if a run of successful probes doesn't accumulate in that time, the command says so directly and advises rolling back.
66
+ 4. Restarts the infrastructure launchd jobs the core owns (`com.iapeer.*` — the `timer`, `watcher`, Telegram routers), moving them onto the just-replaced binary. It's the JOBS that restart, not the runtimes' package code — that's the next step. If the daemon didn't come up in step 3, this is skipped.
67
+ 5. Verifies the daemon came up healthy — by a probe, not by the restart command exiting: it connects to the daemon's socket and counts it healthy only when it accepts a connection **twice in a row** (a single probe would also pass a daemon that bound the socket and immediately crashed). The check is given 15 seconds; on failure the command says so and advises rolling back.
68
+
69
+ **2. Runtimes** — each installed runtime package (telegram-runtime, notifier-runtime) is version-gated, re-installed, re-provisioned, and its peers restarted (via the regular stop/start — the persistent-peer fleet is refused, never forced).
70
+
71
+ **3. Memory provider** — if a provider is claimed, its own update verb runs (the provider owns its update, its slot version, and its memory-daemon restart).
65
72
 
66
- An update touches **only the core**. The daemon plist and third-party packages stay as they are.
73
+ Runtimes and memory are **best-effort**: a component failure is reported and the rest still run; the command exits non-zero if anything failed. Agentic peers (Claude/Codex) pick up new core doctrine lazily on their next wake.
67
74
 
68
- Naming a specific version (`iapeer update <version>`) is useful when you need to roll back deeper than one step, or pin a proven version.
75
+ `iapeer update --foundation-only` does just step 1 (the narrow case). A pinned `iapeer update <version>` is **core-only** by design — a version pin is core-specific (downgrade, or pin a proven version, deeper than one rollback step).
69
76
 
70
77
  ## Rollback
71
78
 
@@ -95,7 +95,7 @@ PEER_IDENTITY = PEER_RUNTIME + "-" + PEER_PERSONALITY
95
95
  "intelligence": "artificial",
96
96
  "initial_prompt": "Новая сессия. Поздоровайся с владельцем.",
97
97
  "interfaces": {
98
- "telegram": { "bot": "assistant", "bot_username": "assistant_bot" }
98
+ "telegram": { "bot": "assistant" }
99
99
  }
100
100
  }
101
101
  ```
@@ -33,6 +33,9 @@
33
33
  ├── cache/
34
34
  │ ├── iapeer/ кеш ядра
35
35
  │ └── <плагин>/ кеш плагина (можно удалять)
36
+ ├── docs/
37
+ │ ├── iapeer/ справочные доки фундамента (версия, установленная на хосте)
38
+ │ └── <пакет>/ доки каждого пакета экосистемы (копируются при его установке)
36
39
  ├── plugins/
37
40
  │ ├── iap/ установка ядрового плагина IAP
38
41
  │ └── <плагин>/ установка плагина (неизменяемая)
@@ -53,6 +56,15 @@
53
56
  - **`state/iapeer/`** — здесь живёт демон: его локальный сокет `router.sock` и конфигурация `router.json`.
54
57
  - **`logs/<имя>/`** — журналы инфраструктурных пиров кладутся по имени пира на общем уровне (а не в папке пира), потому что это вывод службы под launchd.
55
58
  - **`runtimes/<рантайм>/`** — двойное владение: корень принадлежит самому рантайму (Telegram держит здесь токены ботов, состояние опроса), а подпапка `plugins/<плагин>/` — это пространство плагинов, где лежит их конфиг под этим рантаймом.
59
+ - **`docs/<пакет>/`** — справочные доки на хосте, по одной папке на каждый пакет экосистемы (см. ниже).
60
+
61
+ ## Доки экосистемы на хосте
62
+
63
+ `~/.iapeer/docs/<пакет>/` хранит копию справочных доков каждого пакета экосистемы, чтобы агент мог читать контракт офлайн по стабильному версионированному пути. Это нужно потому, что скомпилированный бинарь доков не несёт, а `docs/` из npm-тарбола выбрасывается после установки — ссылка во временный каталог установки или кеша умерла бы на первом же обновлении.
64
+
65
+ Конвенция — **копирование при установке, по пакету**: каждый пакет копирует свои публичные доки (исключая `internals/`) в свою папку `~/.iapeer/docs/<пакет>/` при каждой своей установке и обновлении, атомарной заменой, best-effort — сбой копирования никогда не валит установку. Поскольку копирование происходит в той же установке, что кладёт артефакт, доки пакета на хосте всегда соответствуют его установленной версии. Каждый пакет пишет только свою подпапку — та же изоляция владения, что и везде; имя папки — короткое unscoped-имя пакета (`iapeer`, `iapeer-memory`, `telegram-runtime`, `notifier-runtime`).
66
+
67
+ Системный промпт пира указывает сюда — `~/.iapeer/docs/`, по папке на пакет, начиная с `iapeer/README.md`, — чтобы вопрос «как iapeer делает X» отвечался из доков, а не угадывался.
56
68
 
57
69
  ## Раскладка уровня пира
58
70
 
@@ -47,25 +47,32 @@ iapeer status
47
47
 
48
48
  Разбор каждого шага onboard — в [02 — Быстрый старт](02-быстрый-старт.md); рантаймы и память подробно — в [09](09-рантаймы.md) и [11](11-расширения-и-память.md).
49
49
 
50
- ## Обновление ядра
50
+ ## Обновление
51
51
 
52
52
  ```bash
53
- iapeer update # до последней версии
54
- iapeer update 0.2.80 # до конкретной версии
55
- iapeer update --force # переустановить, даже если версия уже стоит
53
+ iapeer update # каскад: обновить ВЕСЬ стек — ядро + рантаймы + память
54
+ iapeer update --foundation-only # обновить только ядро
55
+ iapeer update 0.2.80 # запинить ЯДРО на конкретную версию (только ядро)
56
+ iapeer update --force # переустановить, даже если версия уже стоит
56
57
  ```
57
58
 
58
- Обновление тянет версию ядра из npm и перезапускает демон на неё. По шагам:
59
+ Голый `iapeer update` обновляет **весь хостовый стек** одной командой — ядро (фундамент), каждый установленный рантайм и провайдер памяти, — чтобы «обновлено» значило всю машину, а не только ядро. Ядро идёт первым; рантаймы и память следуют, только если ядро поднялось здоровым.
60
+
61
+ **1. Ядро (фундамент)** — и оно ПРЕРЫВАЕТ каскад при жёсткой ошибке (не обновлять рантаймы на сломанное ядро):
59
62
 
60
63
  1. Узнаёт нужную версию из npm. Если установленная уже совпадает и нет `--force` — ничего не делает.
61
- 2. Скачивает и собирает новый бинарь. Это делается через `npm pack`, а не `npx`: бинарь не пересобирает себя сам.
64
+ 2. Скачивает и собирает новый бинарь через `npm pack`, а не `npx` (бинарь не пересобирает себя сам).
62
65
  3. Перезапускает демон на новый бинарь.
63
- 4. Перезапускает launchd-джобы инфраструктуры, которыми владеет ядро (`com.iapeer.*` — роутеры `timer`, `watcher`, Telegram), переводя их на только что заменённый бинарь. Их плисты запускают тот же бинарь ядра, что и демон, — без перезапуска джоб остался бы на старом коде. Перезапускается именно джоб (снимается и поднимается заново); **пакетный код** рантаймов (telegram-runtime, notifier-runtime) при этом не обновляется — это отдельная операция `update-runtime`. Провайдер памяти (`iapeer-memory`) и плисты обычных пиров не трогаются вовсе. Если демон на шаге 3 не поднялся, этот шаг пропускается — нет смысла переводить джобы на бинарь, на котором демон не ожил.
64
- 5. Проверяет, что демон действительно поднялся здоровым, — не по тому, что команда перезапуска завершилась успешно, а пробой: подключается к сокету демона (тому самому, что демон открывает прямо перед сигналом готовности). Здоровым демон считается, только когда сокет принимает соединение **дважды подряд** — одиночная проба прошла бы и у демона, который привязал сокет и тут же упал. На проверку отведено 15 секунд; если за это время серия успешных проб не набралась — команда говорит об этом прямо и советует откатиться.
66
+ 4. Перезапускает launchd-джобы инфраструктуры, которыми владеет ядро (`com.iapeer.*` — роутеры `timer`, `watcher`, Telegram), переводя их на заменённый бинарь. Перезапускаются именно ДЖОБЫ, а не пакетный код рантаймов — это следующий шаг. Если демон на шаге 3 не поднялся, шаг пропускается.
67
+ 5. Проверяет, что демон поднялся здоровым, — пробой, а не кодом возврата команды перезапуска: подключается к сокету демона и считает здоровым, только когда тот принимает соединение **дважды подряд** (одиночная проба прошла бы и у демона, который привязал сокет и тут же упал). На проверку 15 секунд; при провале команда говорит и советует откатиться.
68
+
69
+ **2. Рантаймы** — каждый установленный рантайм-пакет (telegram-runtime, notifier-runtime) проходит version-gate, переустановку, ре-провижн, и его пиры перезапускаются (через обычный stop/start — флот persistent-peer отклоняется, не форсится).
70
+
71
+ **3. Провайдер памяти** — если слот занят, запускается его собственный update-verb (провайдер владеет своим обновлением, версией слота и перезапуском memory-демона).
65
72
 
66
- Обновление трогает **только ядро**. Плист демона и сторонние пакеты остаются как есть.
73
+ Рантаймы и память — **best-effort**: ошибка компонента сообщается, остальные всё равно отрабатывают; код возврата ненулевой, если что-то упало. Агентские пиры (Claude/Codex) подхватывают новую доктрину ядра лениво на следующем пробуждении.
67
74
 
68
- Указать конкретную версию (`iapeer update <версия>`) полезно, когда нужно откатиться глубже, чем на один шаг назад, или встать на проверенную версию.
75
+ `iapeer update --foundation-only` делает только шаг 1 (узкий случай). Запиненный `iapeer update <версия>` — **только ядро** by design: пин версии специфичен для ядра (откат глубже одного шага или фиксация проверенной версии).
69
76
 
70
77
  ## Откат
71
78
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agfpd/iapeer",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "Foundation core for the iapeer multi-agent ecosystem: identity, registry, storage, codec.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "agfpd",