agentirc-cli 9.5.0a1__tar.gz → 9.6.0__tar.gz
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.
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/CHANGELOG.md +78 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/CLAUDE.md +18 -14
- agentirc_cli-9.6.0/PKG-INFO +321 -0
- agentirc_cli-9.6.0/README.md +266 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/bots/http_listener.py +9 -1
- agentirc_cli-9.6.0/agentirc/_internal/event_subscriptions.py +282 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/telemetry/audit.py +7 -0
- agentirc_cli-9.6.0/agentirc/_internal/virtual_client.py +32 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/channel.py +32 -5
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/client.py +177 -16
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/ircd.py +83 -46
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/protocol.py +2 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/server_link.py +60 -10
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/skills/rooms.py +1 -1
- {agentirc_cli-9.5.0a1/agentirc/_internal → agentirc_cli-9.6.0/agentirc}/virtual_client.py +36 -17
- agentirc_cli-9.6.0/docs/api-stability.md +417 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/docs/cli.md +1 -1
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/docs/deployment.md +11 -3
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/docs/extension-api.md +6 -6
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/pyproject.toml +15 -3
- agentirc_cli-9.6.0/tests/test_api_stability_embedding.py +138 -0
- agentirc_cli-9.6.0/tests/test_bot_capability.py +204 -0
- agentirc_cli-9.6.0/tests/test_event_subscriptions.py +335 -0
- agentirc_cli-9.6.0/tests/test_eventpub.py +194 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_events_basic.py +9 -2
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_events_lifecycle.py +16 -9
- agentirc_cli-9.6.0/tests/test_wire_format_envelope.py +325 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/uv.lock +1 -1
- agentirc_cli-9.5.0a1/PKG-INFO +0 -57
- agentirc_cli-9.5.0a1/README.md +0 -2
- agentirc_cli-9.5.0a1/docs/api-stability.md +0 -288
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.claude/skills/pr-review/scripts/portability-lint.sh +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.claude/skills/pr-review/scripts/pr-batch.sh +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.claude/skills/pr-review/scripts/pr-comments.sh +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.claude/skills/pr-review/scripts/pr-reply.sh +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.claude/skills/pr-review/scripts/pr-sonar.sh +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.claude/skills/pr-review/scripts/pr-status.sh +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.claude/skills/pr-review/scripts/workflow.sh +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.claude/skills.local.yaml.example +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/.gitignore +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/LICENSE +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/__init__.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/__main__.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/__init__.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/aio.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/bots/__init__.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/bots/bot_manager.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/cli_shared/__init__.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/cli_shared/constants.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/cli_shared/mesh.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/constants.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/pidfile.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/protocol/__init__.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/protocol/message.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/protocol/replies.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/telemetry/__init__.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/telemetry/context.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/telemetry/metrics.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/_internal/telemetry/tracing.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/cli.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/config.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/events.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/history_store.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/remote_client.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/room_store.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/rooms_util.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/skill.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/skills/__init__.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/skills/history.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/skills/icon.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/skills/threads.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/agentirc/thread_store.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/docs/steward/onboarding.md +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/docs/superpowers/specs/2026-04-30-bootstrap-design.md +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/docs/superpowers/specs/2026-05-01-bot-extension-api-design.md +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/docs/superpowers/specs/2026-05-01-task14-audit.md +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/__init__.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/_helpers.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/conftest.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/__init__.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/_fakes.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/_metrics_helpers.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_audit_emit.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_audit_lifecycle.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_audit_module.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_audit_parse_error.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_config.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_dispatch_span.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_emit_event_span.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_metrics_init.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_metrics_s2s.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_outbound_inject.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_parse_error.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_s2s_relay_span.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_server_init.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_server_link_inject.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/telemetry/test_tracing.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_channel.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_cli.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_config_loader.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_connection.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_discovery.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_events_catalog.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_events_federation.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_events_history.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_events_reserved_nick.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_federation.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_history.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_mentions.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_messaging.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_modes.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_protocol_bot_exports.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_skills.py +0 -0
- {agentirc_cli-9.5.0a1 → agentirc_cli-9.6.0}/tests/test_threads.py +0 -0
|
@@ -4,6 +4,84 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/).
|
|
6
6
|
|
|
7
|
+
## [9.6.0] - 2026-05-02
|
|
8
|
+
|
|
9
|
+
Closes [agentculture/agentirc#22](https://github.com/agentculture/agentirc/issues/22) — promote the in-process embedding API. Unblocks [agentculture/culture#308](https://github.com/agentculture/culture/issues/308) Phase A2-Bridge: culture's `culture/bots/virtual_client.py` (231 LOC, near-line-for-line copy of agentirc's internal `VirtualClient`) collapses to a thin wrapper around the public class, and `culture/cli/server.py:_run_server` can construct an `agentirc.ircd.IRCd` directly instead of going through the `agentirc serve` subprocess.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **`agentirc.virtual_client.VirtualClient`** is now public, semver-tracked. `from agentirc.virtual_client import VirtualClient` is the canonical import. Class behaviour is unchanged — the file moved from `agentirc/_internal/virtual_client.py` to `agentirc/virtual_client.py` with no edits to the class body.
|
|
14
|
+
- **`agentirc.ircd.IRCd`** is now public, semver-tracked. The locked-in surface is the constructor (`IRCd(config: ServerConfig)`), the lifecycle methods (`await ircd.start()`, `await ircd.stop()`), `await ircd.emit_event(event)`, and the `subscription_registry`, `clients`, `channels`, `config`, and `system_client` attributes. Other attributes on `IRCd` remain implementation detail and may change without a major bump.
|
|
15
|
+
- **Embedding worked example** in `docs/api-stability.md` showing how to construct an `IRCd` in-process, register a `VirtualClient`, and run until shutdown. Includes a member-by-member breakdown of the public `IRCd` surface and the `VirtualClient` constructor / method signatures.
|
|
16
|
+
|
|
17
|
+
### Deprecated
|
|
18
|
+
|
|
19
|
+
- **`agentirc._internal.virtual_client.VirtualClient`** still resolves via a transitional re-export module that emits `DeprecationWarning` on import. Removal is scheduled for 10.0.0. All in-tree call sites (`ircd.py`, `server_link.py`, `channel.py`, `skills/rooms.py`) have been retargeted at the public path so the shim never fires under our own tests.
|
|
20
|
+
|
|
21
|
+
### Notes
|
|
22
|
+
|
|
23
|
+
- This release is purely additive at the Python level. No protocol changes, no CLI changes, no behaviour changes. The wire surface (the `agentirc.io/bot` CAP, `EVENTSUB`/`EVENTUNSUB`/`EVENT`/`EVENTERR`/`EVENTPUB` verbs, the canonical 5-field envelope) is identical to 9.5.0 and stays byte-locked.
|
|
24
|
+
- Citation manifest updated: `culture-virtual-client` now targets `agentirc/virtual_client.py`. New entry `agentirc-internal-virtual-client-shim` covers the deprecation re-export.
|
|
25
|
+
|
|
26
|
+
## [9.5.0] - 2026-05-02
|
|
27
|
+
|
|
28
|
+
Closes [agentculture/agentirc#15](https://github.com/agentculture/agentirc/issues/15) — out-of-process bot extension API. Unblocks [agentculture/culture#308](https://github.com/agentculture/culture/issues/308) Phase A2 (bot rewrite against the public API).
|
|
29
|
+
|
|
30
|
+
### Added
|
|
31
|
+
|
|
32
|
+
- **IRCv3 `agentirc.io/bot` capability.** Advertised in `CAP LS` output. When negotiated via `CAP REQ`, gates four behaviours: silent JOIN/PART/QUIT broadcasts (other channel members see nothing), no auto-op on a fresh-channel first-joiner, `+` prefix in NAMES output, `B` flag in WHO output. Channel membership is added normally; events still fire (subscribers see them via `EVENTSUB`).
|
|
33
|
+
- **`EVENTSUB` / `EVENTUNSUB` / `EVENT` / `EVENTERR` IRC verbs** for streaming events to bots out-of-process. `EVENTSUB <sub-id> [type=<glob>] [channel=<name>] [nick=<glob>]`: filters AND-ed; `type` and `nick` accept `fnmatch`-style globs; `channel` accepts an exact name, `*`, or empty (nick-scoped only). Multiple concurrent subscriptions per client are allowed. Wire format: `:server EVENT <sub-id> <type> <channel-or-*> <nick> :<base64-json-envelope>` carrying the canonical 5-field envelope. Per-subscription bounded queue (default 1024); on overflow the server emits `EVENTERR <sub-id> :backpressure-overflow` and drops the subscription (connection stays open). Subscriptions die on client disconnect.
|
|
34
|
+
- **`EVENTPUB` IRC verb** for bots to emit custom-typed events back into the stream. `EVENTPUB <type> <channel-or-*> :<base64-json-data>`. Type validated against `EVENT_TYPE_RE` (dotted lowercase, ≥1 dot — single-segment names like `message` and `topic` are reserved for built-in vocabulary). Server fills `nick` from the bot's connection nick (not spoofable) and `timestamp` from `time.time()` so federation peers see consistent clocks. `_`-prefixed keys are stripped from the payload before emit.
|
|
35
|
+
- New internal module `agentirc._internal.event_subscriptions` with the `Subscription` dataclass and `SubscriptionRegistry`. `IRCd.subscription_registry` exposes the registry; `IRCd.emit_event` dispatches every event through it.
|
|
36
|
+
- `agentirc.protocol.SEVENT` verb constant (added in 9.5.0a2; reaffirmed here).
|
|
37
|
+
|
|
38
|
+
### Changed
|
|
39
|
+
|
|
40
|
+
- **`webhook_port` is no longer bound by `IRCd.start()`.** The field stays in `ServerConfig` so culture's `~/.culture/server.yaml` keeps loading unchanged, but `agentirc` no longer instantiates the HTTP listener. Consumers that need webhook→bot dispatch host their own listener (see `docs/deployment.md`). No deprecation warning at runtime — the docs change is sufficient.
|
|
41
|
+
- `Channel.add()` no longer auto-ops bot-CAP clients (real or `VirtualClient`). A bot joining an empty channel stays unprivileged; the next human becomes op.
|
|
42
|
+
- `Channel.get_prefix()` returns `+` for bot-CAP members in NAMES output.
|
|
43
|
+
- `Client._build_who_flags()` adds the `B` flag for bot-CAP members in WHO output (composes with `H` and `@`/`+`).
|
|
44
|
+
- `VirtualClient` gains a class-level `caps = frozenset({"agentirc.io/bot", "message-tags"})` so the in-process system bot is treated identically to a real CAP-bot.
|
|
45
|
+
- `Client._handle_cap` `CAP LS` reply now lists supported caps from a class-level `_SUPPORTED_CAPS` frozenset (centralised; removing a cap is a major bump).
|
|
46
|
+
- `agentirc/_internal/bots/http_listener.py` module docstring notes the no-op stub is scheduled for removal in 9.6.0.
|
|
47
|
+
|
|
48
|
+
### Notes
|
|
49
|
+
|
|
50
|
+
- This is the **final slice** of the bot extension API. `9.5.0a1` shipped the public `agentirc.protocol` declarations; `9.5.0a2` switched the federation wire format to the 5-field envelope; this release wires the actual behaviour.
|
|
51
|
+
- **Federation interop unchanged from 9.5.0a2.** 9.4→9.5 federation works (sniff tolerance); 9.5→9.4 emit breaks until peers upgrade.
|
|
52
|
+
- The `agentirc.skill.{Event, EventType}` re-export shim from 9.5.0a1 stays through the 9.x line; removal is scheduled for 10.0.0.
|
|
53
|
+
- The `agentirc/_internal/bots/` synthesize stubs (`bot_manager.py`, `http_listener.py`) stay through the 9.5.x cycle; removal is scheduled for 9.6.0 once Phase A2 confirms no consumer imports them.
|
|
54
|
+
|
|
55
|
+
## [9.5.0a2] - 2026-05-02
|
|
56
|
+
|
|
57
|
+
### Changed
|
|
58
|
+
|
|
59
|
+
- **Wire format: SEVENT payload and IRCv3 `event-data` tag now carry the 5-field envelope** `{type, channel, nick, data, timestamp}`. Both the federation seam (`SEVENT` between linked servers) and the human-visible `#system` PRIVMSG `event-data` tag emit the new shape via `IRCd._build_event_envelope` + `IRCd._encode_event_data`. Type-specific keys (e.g. `text`, `room_id`, `purpose`) now nest under `data`; `nick` and `channel` remain at the top level. See `docs/superpowers/specs/2026-05-01-bot-extension-api-design.md` § Decision A for the rationale.
|
|
60
|
+
- `IRCd._build_event_payload` is replaced by `IRCd._build_event_envelope` (internal — no public API impact). Old name removed; the only two callsites (`_surface_event_privmsg` and `ServerLink.relay_event`'s SEVENT fallback) updated in the same commit.
|
|
61
|
+
|
|
62
|
+
### Added
|
|
63
|
+
|
|
64
|
+
- `ServerLink._is_envelope(decoded)` — sniff helper that recognises the new envelope shape vs. the legacy data-only dict at decode time. `_handle_sevent` uses it for asymmetric tolerance (see Notes).
|
|
65
|
+
- `agentirc.protocol.SEVENT` — verb-name constant for the federation event-relay verb. Used by the new test suite and the outbound relay path. Other agentirc-side string-literal callsites are tracked separately in [#11](https://github.com/agentculture/agentirc/issues/11).
|
|
66
|
+
- `tests/test_wire_format_envelope.py` — 12 tests including a golden-file byte-equality lock-in for the canonical JSON encoding (any future change to the encoder that breaks this is a wire-format break and requires a major bump), plus regression guards for the trust-bypass and underscore-injection fixes below.
|
|
67
|
+
|
|
68
|
+
### Security
|
|
69
|
+
|
|
70
|
+
- **`ServerLink._handle_sevent` now treats the SEVENT verb-arg channel as authoritative.** The previous draft of this PR (pre-review) used the envelope's `channel` field on the receive side, which would have allowed a malformed/malicious peer to bypass `_check_incoming_trust` by sending `target="*"` (no trust check) while putting a restricted channel name in the envelope. The verb-arg channel is what the trust gate already protects, so the receiver now ignores any envelope channel claim and uses `verb_channel` for both the trust check and the resulting `Event.channel`.
|
|
71
|
+
- **Peer-supplied `_`-prefixed keys are stripped from incoming SEVENT data before emit.** `_render` and similar server-internal hints would otherwise let a peer dictate human-readable surfacing on this server. The receiver strips every key starting with `_` from the decoded data before adding its own `_origin` marker.
|
|
72
|
+
|
|
73
|
+
### Fixed
|
|
74
|
+
|
|
75
|
+
- **`IRCd._encode_event_data` fallback now produces a valid 5-field envelope instead of `b"{}"`.** A serialization failure used to emit a bare empty dict, which fails the receiver's envelope sniff and is misclassified as legacy data-only — worse than emitting an event with no type-specific payload. The fallback now emits `{type, channel, nick, data: {}, timestamp: time.time()}` so consumers can still parse the shape.
|
|
76
|
+
|
|
77
|
+
### Notes
|
|
78
|
+
|
|
79
|
+
- **Federation interop story.** A 9.5 daemon's `_handle_sevent` sniffs the decoded payload: if it has a top-level `type` (string) and `data` (dict), treat as 9.5+ envelope; otherwise treat as ≤9.4 legacy data-only and reconstruct an `Event` from the SEVENT verb args + the bare data dict. This gives 9.5 receivers asymmetric tolerance — they read traffic from both upgraded and pre-9.5 peers — so federations can roll forward one peer at a time. The reverse direction (9.5 emit → 9.4 receive) does **not** work; 9.4 daemons have no sniff and will fail to find expected `data` fields. Operators must either upgrade all peers in lockstep, or roll one at a time and accept that 9.5-emitted events drop on still-9.4 peers until those peers also upgrade. This matches the migration cost the spec calls out.
|
|
80
|
+
- **Audit JSONL is unchanged.** `agentirc/_internal/telemetry/audit.py:build_audit_record` continues to record the legacy data-only payload (data dict with `nick`/`channel` merged in via `setdefault`, `_`-prefixed keys stripped). Ops dashboards and downstream log processors that read the audit JSONL keep their existing field shape; the 5-field envelope is reserved for the public network surface (SEVENT payload + IRCv3 `event-data` tag).
|
|
81
|
+
- **Audit timestamp on legacy peers.** When `_handle_sevent` decodes a legacy payload from a ≤9.4 peer, no originating timestamp is available; the receiver assigns `time.time()` to the reconstructed `Event.timestamp`. 9.5+ peers preserve the originating timestamp.
|
|
82
|
+
- This is the **wire-format slice** of the bot extension API. The next slice (9.5.0a3) wires the bot CAP behavior (`agentirc.io/bot`), the `EVENTSUB`/`EVENTUNSUB`/`EVENTPUB` handlers, and the `SubscriptionRegistry`. 9.5.0 final adds `webhook_port` unbinding and flips `docs/api-stability.md` to "current".
|
|
83
|
+
- Tracks [agentculture/agentirc#15](https://github.com/agentculture/agentirc/issues/15).
|
|
84
|
+
|
|
7
85
|
## [9.5.0a1] - 2026-05-02
|
|
8
86
|
|
|
9
87
|
### Added
|
|
@@ -2,20 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
4
|
|
|
5
|
-
## Current state: bootstrap
|
|
5
|
+
## Current state: bootstrap closed; bot extension API + in-process embedding API shipped (9.6.0 released)
|
|
6
6
|
|
|
7
|
-
This repo is the agentirc server-core extraction out of the sibling project [`culture`](https://github.com/agentculture/culture).
|
|
7
|
+
This repo is the agentirc server-core extraction out of the sibling project [`culture`](https://github.com/agentculture/culture). The bootstrap is closed; 9.0.0 through 9.6.0 are live on PyPI. The most recent ship is the in-process embedding API (9.6.0, closed [#22](https://github.com/agentculture/agentirc/issues/22)) — promoting `agentirc.ircd.IRCd` and `agentirc.virtual_client.VirtualClient` to public, semver-tracked status so culture's Phase A2-Bridge can construct an IRCd in-process and host bots inside it without going through the `agentirc serve` subprocess. The previous ship was the out-of-process bot extension API (9.5.0, closed [#15](https://github.com/agentculture/agentirc/issues/15)). The repo currently contains:
|
|
8
8
|
|
|
9
9
|
- **Server-core** (`agentirc/{ircd,server_link,channel,events,skill,remote_client,…}.py`, `agentirc/skills/{rooms,threads,history,icon}.py`) — vendored from `culture@df50942` via the `cite-don't-copy` pattern (see `[tool.citation]` in `pyproject.toml`).
|
|
10
10
|
- **Client transport** (`agentirc/client.py`) — vendored from `culture/agentirc/client.py` in PR-B2.
|
|
11
11
|
- **Public CLI** (`agentirc/cli.py`) — real verb dispatch extracted from `culture/cli/server.py`. Verbs: `serve` (foreground, no PID; for systemd `Type=simple` and containers), `start`/`stop`/`status` (lifecycle), `restart`, `link` (peer-spec validator), `logs` (cat / tail of `~/.culture/logs/server-<name>.log`), `version`. Since 9.4.0, `serve`/`start`/`restart` overlay CLI flags on `--config` YAML (precedence: CLI > YAML > built-in default).
|
|
12
|
-
- **Public config** (`agentirc/config.py`) — `ServerConfig`, `LinkConfig`, `TelemetryConfig` dataclasses plus the `ServerConfig.from_yaml(path)` classmethod (added 9.4.0). Recognises `server`/`telemetry`/`links`/`webhook_port`/`data_dir`/`system_bots` keys; silently ignores culture-only keys (`supervisor`, `agents`, `buffer_size`, etc.) so the same `~/.culture/server.yaml` can drive both daemons.
|
|
13
|
-
- **Public protocol** (`agentirc/protocol.py`) — verb name constants, numerics, IRCv3 tag names. Wire-format quirks (`ROOMETAEND`, `ROOMETASET` typos, `ERR_NOSUCHCHANNEL` semantic misuse, `STHREAD` verb collapse) preserved verbatim — they need coordinated cross-repo bumps to fix.
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
12
|
+
- **Public config** (`agentirc/config.py`) — `ServerConfig`, `LinkConfig`, `TelemetryConfig` dataclasses plus the `ServerConfig.from_yaml(path)` classmethod (added 9.4.0). Recognises `server`/`telemetry`/`links`/`webhook_port`/`data_dir`/`system_bots`/`event_subscription_queue_max` keys; silently ignores culture-only keys (`supervisor`, `agents`, `buffer_size`, etc.) so the same `~/.culture/server.yaml` can drive both daemons. Since 9.5.0, `webhook_port` is accepted but no longer bound by `IRCd.start()` — the field stays in `ServerConfig` for backward compat with culture's YAML, but consumers needing webhook→bot dispatch host their own listener.
|
|
13
|
+
- **Public protocol** (`agentirc/protocol.py`) — verb name constants, numerics, IRCv3 tag names. Since 9.5.0 also exports the bot extension surface: `Event` dataclass, `EventType` (`StrEnum`), 20 `EVENT_TYPE_*` constants, `EVENTSUB`/`EVENTUNSUB`/`EVENT`/`EVENTERR`/`EVENTPUB` verb constants, `SEVENT` federation verb, and `BOT_CAP = "agentirc.io/bot"`. Wire-format quirks (`ROOMETAEND`, `ROOMETASET` typos, `ERR_NOSUCHCHANNEL` semantic misuse, `STHREAD` verb collapse) preserved verbatim — they need coordinated cross-repo bumps to fix.
|
|
14
|
+
- **Bot extension API (9.5.0)** — IRCv3 `agentirc.io/bot` capability gates four behaviours when negotiated via `CAP REQ`: silent JOIN/PART/QUIT broadcasts, no auto-op on a fresh-channel first-joiner, `+` prefix in NAMES output, `B` flag in WHO output. `EVENTSUB <sub-id> [type=<glob>] [channel=<name>] [nick=<glob>]` opens a streaming subscription; `EVENTPUB <type> <channel-or-*> :<base64-json-data>` emits a custom-typed event back into the stream (server fills `nick` and `timestamp` so federation peers see consistent values). Per-subscription bounded queue (default 1024); on overflow the server emits `EVENTERR <sub-id> :backpressure-overflow` and drops the subscription. Quick reference at [`docs/extension-api.md`](docs/extension-api.md); design spec at [`docs/superpowers/specs/2026-05-01-bot-extension-api-design.md`](docs/superpowers/specs/2026-05-01-bot-extension-api-design.md).
|
|
15
|
+
- **Test suite** — 36 tests vendored from `culture@df50942` (~6.5kloc) plus agentirc-native tests in `tests/test_config_loader.py` and `tests/test_wire_format_envelope.py` (the 9.5.0a2 golden-file lock-in). `pytest -n auto` in ~30s on default workers. Three telemetry tests (`test_bot_event_dispatch_span`, `test_bot_run_span`, `test_metrics_bots`) and `test_welcome_bot` stay in culture because they depend on the real `BotManager`.
|
|
16
|
+
- **In-process embedding API (9.6.0)** — `agentirc.ircd.IRCd` and `agentirc.virtual_client.VirtualClient` promoted to the public surface. The `IRCd` public contract is the constructor (`IRCd(config: ServerConfig)`), `await ircd.start()`/`stop()`, `await ircd.emit_event(event)`, plus the `subscription_registry`/`clients`/`channels`/`config`/`system_client` attributes; everything else on `IRCd` remains implementation detail. `VirtualClient` moved from `agentirc/_internal/virtual_client.py` to `agentirc/virtual_client.py` with no body edits; the legacy import path resolves via a deprecation re-export (removal in 10.0.0). Worked example + member breakdown live in [`docs/api-stability.md`](docs/api-stability.md#embedding-agentirc-in-process). Same wire surface as 9.5.0; no protocol changes.
|
|
17
|
+
- **Internal support** (`agentirc/_internal/`) — `aio`, `constants`, `protocol/`, `telemetry/`, `pidfile`, `cli_shared/`, `bots/` stubs, `event_subscriptions/` (added 9.5.0). The `_internal/virtual_client.py` module remains as a deprecation re-export of the now-public `agentirc.virtual_client.VirtualClient`; emits `DeprecationWarning` on import; scheduled for removal in 10.0.0.
|
|
18
|
+
- **Bootstrap docs** (PR-B4, 9.4.0) — `docs/api-stability.md` (3 public modules + semver contract), `docs/cli.md` (verb table, flag reference, exit codes, YAML/CLI precedence, agentirc-vs-culture diff table), `docs/deployment.md` (on-disk footprint, systemd `Type=simple` example, container deployment, multi-host federation, log rotation, coexistence with culture, backup), and `docs/extension-api.md` (bot-author quick reference, added 9.5.0). Public-facing `README.md` rewritten for issue [#19](https://github.com/agentculture/agentirc/issues/19).
|
|
17
19
|
|
|
18
|
-
End-to-end verified: `agentirc start --port <p>` boots a real IRCd, TCP NICK/USER handshake returns `001 RPL_WELCOME`, `agentirc stop` shuts cleanly. `agentirc serve --config server.yaml --port 9999` correctly overlays CLI flag on YAML. `pip install agentirc-cli==9.
|
|
20
|
+
End-to-end verified: `agentirc start --port <p>` boots a real IRCd, TCP NICK/USER handshake returns `001 RPL_WELCOME`, `agentirc stop` shuts cleanly. `agentirc serve --config server.yaml --port 9999` correctly overlays CLI flag on YAML. `pip install agentirc-cli==9.5.0` from real PyPI in a clean venv produces both `agentirc` and `agentirc-cli` binaries; both reach the same `agentirc.cli:main` entry point. Acceptance audit for the bootstrap recorded at [`docs/superpowers/specs/2026-05-01-task14-audit.md`](docs/superpowers/specs/2026-05-01-task14-audit.md). Culture-side cutover unblocked via [agentculture/culture#308](https://github.com/agentculture/culture/issues/308).
|
|
19
21
|
|
|
20
22
|
**Outstanding follow-ups (non-blocking; the bootstrap itself is closed):**
|
|
21
23
|
- **Cross-repo wire-format fixes (Track A)** — [#7](https://github.com/agentculture/agentirc/issues/7) (`ROOMETAEND`/`ROOMETASET` typos), [#8](https://github.com/agentculture/agentirc/issues/8) (`ERR_NOSUCHCHANNEL` overload), [#9](https://github.com/agentculture/agentirc/issues/9) (`STHREAD` verb collapse). Each requires culture-side change first then agentirc bump.
|
|
@@ -59,13 +61,15 @@ When migrating tests, the rule is: pure server tests come here, transport tests
|
|
|
59
61
|
|
|
60
62
|
## Public API contract (semver-tracked)
|
|
61
63
|
|
|
62
|
-
|
|
64
|
+
Five modules are public. Everything else is internal and may be refactored without a major bump.
|
|
63
65
|
|
|
64
|
-
| Module | Members |
|
|
65
|
-
|
|
66
|
-
| `agentirc.config` | `ServerConfig`, `LinkConfig`, `TelemetryConfig` |
|
|
67
|
-
| `agentirc.cli` | `main()`, `dispatch(argv) -> int` |
|
|
68
|
-
| `agentirc.protocol` | verb name constants, numeric reply codes, extension tag names |
|
|
66
|
+
| Module | Members | Since |
|
|
67
|
+
|---|---|---|
|
|
68
|
+
| `agentirc.config` | `ServerConfig`, `LinkConfig`, `TelemetryConfig` | 9.0.0 |
|
|
69
|
+
| `agentirc.cli` | `main()`, `dispatch(argv) -> int` | 9.2.0 |
|
|
70
|
+
| `agentirc.protocol` | verb name constants, numeric reply codes, extension tag names; bot extension surface (`Event`, `EventType`, `EVENT_TYPE_*`, `EVENTSUB`/`EVENTUNSUB`/`EVENT`/`EVENTERR`/`EVENTPUB`/`SEVENT` verbs, `BOT_CAP`) | 9.2.0 (extended 9.5.0) |
|
|
71
|
+
| `agentirc.ircd` | `IRCd` (constructor + `start`/`stop`/`emit_event`/`subscription_registry`/`clients`/`channels`/`config`/`system_client`) | 9.6.0 |
|
|
72
|
+
| `agentirc.virtual_client` | `VirtualClient` | 9.6.0 |
|
|
69
73
|
|
|
70
74
|
`agentirc.cli.dispatch(argv)` is the function `culture`'s `culture server` shim calls — it must accept the exact same flag set, exit codes, and stderr formatting that `culture server` produces today. Do not "improve" CLI ergonomics during the bootstrap; that breaks the transparency contract culture relies on. `dispatch()` returns `int` on successful command dispatch and lets argparse's `SystemExit` propagate on `--help`/`--version`/parse-errors per Python convention; in-process callers (i.e. culture's shim) must catch `SystemExit` themselves or use `subprocess`.
|
|
71
75
|
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentirc-cli
|
|
3
|
+
Version: 9.6.0
|
|
4
|
+
Summary: Agent-friendly IRCd: server core for AI agent meshes
|
|
5
|
+
Project-URL: Homepage, https://github.com/agentculture/agentirc
|
|
6
|
+
Project-URL: Issues, https://github.com/agentculture/agentirc/issues
|
|
7
|
+
Author: Ori Nachum
|
|
8
|
+
License: MIT License
|
|
9
|
+
|
|
10
|
+
Copyright (c) 2026 agentculture
|
|
11
|
+
|
|
12
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
13
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
14
|
+
in the Software without restriction, including without limitation the rights
|
|
15
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
16
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
17
|
+
furnished to do so, subject to the following conditions:
|
|
18
|
+
|
|
19
|
+
The above copyright notice and this permission notice shall be included in all
|
|
20
|
+
copies or substantial portions of the Software.
|
|
21
|
+
|
|
22
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
23
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
24
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
25
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
26
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
27
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
28
|
+
SOFTWARE.
|
|
29
|
+
License-File: LICENSE
|
|
30
|
+
Keywords: agents,culture,irc,ircd,mesh
|
|
31
|
+
Classifier: Development Status :: 3 - Alpha
|
|
32
|
+
Classifier: Intended Audience :: Developers
|
|
33
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
34
|
+
Classifier: Programming Language :: Python :: 3
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
38
|
+
Classifier: Topic :: Communications :: Chat :: Internet Relay Chat
|
|
39
|
+
Requires-Python: >=3.11
|
|
40
|
+
Requires-Dist: opentelemetry-api>=1.22
|
|
41
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.22
|
|
42
|
+
Requires-Dist: opentelemetry-sdk>=1.22
|
|
43
|
+
Requires-Dist: pyyaml>=6.0
|
|
44
|
+
Provides-Extra: dev
|
|
45
|
+
Requires-Dist: bandit; extra == 'dev'
|
|
46
|
+
Requires-Dist: black; extra == 'dev'
|
|
47
|
+
Requires-Dist: citation-cli; extra == 'dev'
|
|
48
|
+
Requires-Dist: flake8; extra == 'dev'
|
|
49
|
+
Requires-Dist: isort; extra == 'dev'
|
|
50
|
+
Requires-Dist: pylint; extra == 'dev'
|
|
51
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
52
|
+
Requires-Dist: pytest-xdist>=3; extra == 'dev'
|
|
53
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
54
|
+
Description-Content-Type: text/markdown
|
|
55
|
+
|
|
56
|
+
# AgentIRC
|
|
57
|
+
|
|
58
|
+
[](https://pypi.org/project/agentirc-cli/)
|
|
59
|
+
[](https://pypi.org/project/agentirc-cli/)
|
|
60
|
+
[](LICENSE)
|
|
61
|
+
|
|
62
|
+
**Agent-friendly IRCd for AI agent meshes.**
|
|
63
|
+
|
|
64
|
+
`agentirc` is a standalone IRC runtime for human-and-agent rooms. It speaks
|
|
65
|
+
classic IRC ([RFC 2812](https://datatracker.ietf.org/doc/html/rfc2812))
|
|
66
|
+
plus IRCv3 message-tags, room/thread/tag skill verbs, server-to-server
|
|
67
|
+
federation with trust levels, and an out-of-process bot extension API
|
|
68
|
+
(`agentirc.io/bot` capability + `EVENTSUB`/`EVENTUNSUB`/`EVENTPUB` verbs).
|
|
69
|
+
It ships with a small, semver-tracked Python API (`agentirc.config`,
|
|
70
|
+
`agentirc.cli`, `agentirc.protocol`) so other tools can drive an IRCd as a
|
|
71
|
+
library, and a CLI (`agentirc serve`, `agentirc start`, …) for operators.
|
|
72
|
+
|
|
73
|
+
It is the runtime/protocol layer extracted from
|
|
74
|
+
[`culture`](https://github.com/agentculture/culture), the AgentCulture
|
|
75
|
+
agent-mesh project. You don't need culture to use it — `pip install
|
|
76
|
+
agentirc-cli` is a complete IRCd.
|
|
77
|
+
|
|
78
|
+
## Relationship to Culture
|
|
79
|
+
|
|
80
|
+
`agentirc` is the standalone server-core; `culture` is the agent-orchestration
|
|
81
|
+
layer that wraps it.
|
|
82
|
+
|
|
83
|
+
| Concern | Lives in |
|
|
84
|
+
|---|---|
|
|
85
|
+
| IRCd, channels, federation, history, telemetry | `agentirc` |
|
|
86
|
+
| Client transport, IRCv3 message-tags | `agentirc` |
|
|
87
|
+
| Public Python API (`agentirc.config`, `agentirc.cli`, `agentirc.protocol`) | `agentirc` |
|
|
88
|
+
| Bot extension API (CAP + `EVENTSUB`/`EVENTPUB`) | `agentirc` |
|
|
89
|
+
| Agent backends (`claude`, `codex`, `copilot`, `acp`) | `culture` |
|
|
90
|
+
| Console, mesh credentials, OS keyring | `culture` |
|
|
91
|
+
| Process supervisor, agent manifest | `culture` |
|
|
92
|
+
|
|
93
|
+
Server-core code is vendored from culture under the **cite-don't-copy**
|
|
94
|
+
pattern — see `[tool.citation]` in [`pyproject.toml`](pyproject.toml) for the
|
|
95
|
+
provenance ledger. Defaults preserve continuity with culture (config path
|
|
96
|
+
`~/.culture/server.yaml`, log path `~/.culture/logs/server-<name>.log`,
|
|
97
|
+
audit path `~/.culture/audit/`) so existing culture deployments don't have
|
|
98
|
+
to migrate; standalone users override via `--config`.
|
|
99
|
+
|
|
100
|
+
## Install
|
|
101
|
+
|
|
102
|
+
From PyPI:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pip install agentirc-cli
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The package is published as **`agentirc-cli`** on real PyPI; on TestPyPI it is
|
|
109
|
+
dual-published as `agentirc-cli` and `agentirc` (both wheels point at the
|
|
110
|
+
same code). Two console scripts are installed — `agentirc` and
|
|
111
|
+
`agentirc-cli` — both routing to the same `agentirc.cli:main` entry point.
|
|
112
|
+
`python -m agentirc <verb>` works equivalently.
|
|
113
|
+
|
|
114
|
+
`agentirc-cli` requires Python 3.11+.
|
|
115
|
+
|
|
116
|
+
## Quickstart
|
|
117
|
+
|
|
118
|
+
Run an IRCd in the foreground (the recommended path under systemd `Type=simple`
|
|
119
|
+
or a container runtime):
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
agentirc serve --host 0.0.0.0 --port 6667
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Or as a managed background daemon:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
agentirc start --name spark --port 6667
|
|
129
|
+
agentirc status --name spark # Server 'spark': running (PID N, port 6667)
|
|
130
|
+
agentirc logs --name spark -f # tail ~/.culture/logs/server-spark.log
|
|
131
|
+
agentirc stop --name spark
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
A YAML config file overrides the built-in defaults; CLI flags override the
|
|
135
|
+
YAML. The default config path is `~/.culture/server.yaml`:
|
|
136
|
+
|
|
137
|
+
```yaml
|
|
138
|
+
server:
|
|
139
|
+
name: spark
|
|
140
|
+
host: 127.0.0.1
|
|
141
|
+
port: 6700
|
|
142
|
+
telemetry:
|
|
143
|
+
enabled: true
|
|
144
|
+
links:
|
|
145
|
+
- {name: alpha, host: 10.0.0.1, port: 6667, password: secret, trust: full}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
agentirc serve --config ~/.culture/server.yaml --port 9999 # CLI > YAML
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
For Python consumers:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from agentirc.config import ServerConfig
|
|
156
|
+
cfg = ServerConfig.from_yaml("~/.culture/server.yaml")
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
See [`docs/cli.md`](docs/cli.md) for the full verb reference and
|
|
160
|
+
[`docs/deployment.md`](docs/deployment.md) for systemd, containers, and
|
|
161
|
+
multi-host federation.
|
|
162
|
+
|
|
163
|
+
## Public API and stability
|
|
164
|
+
|
|
165
|
+
Three modules form the **public, semver-tracked surface**. Everything else
|
|
166
|
+
under `agentirc.*` is internal and may be refactored — including renamed,
|
|
167
|
+
split, or removed — in any minor or patch release.
|
|
168
|
+
|
|
169
|
+
| Module | Members |
|
|
170
|
+
|---|---|
|
|
171
|
+
| [`agentirc.config`](docs/api-stability.md#agentircconfig) | `ServerConfig`, `LinkConfig`, `TelemetryConfig`, `ServerConfig.from_yaml(path)` |
|
|
172
|
+
| [`agentirc.cli`](docs/api-stability.md#agentirccli) | `main()`, `dispatch(argv) -> int` |
|
|
173
|
+
| [`agentirc.protocol`](docs/api-stability.md#agentircprotocol) | Verb constants, numeric reply codes, IRCv3/extension tag names, the bot extension surface (`Event`, `EventType`, `EVENT_TYPE_*`, `EVENTSUB`/`EVENTUNSUB`/`EVENT`/`EVENTERR`/`EVENTPUB`/`SEVENT`, `BOT_CAP`) |
|
|
174
|
+
|
|
175
|
+
`agentirc.cli.dispatch(argv)` is the in-process integration surface — it is
|
|
176
|
+
what culture's `culture server` shim calls today. It returns `int` on
|
|
177
|
+
successful dispatch and lets `argparse`'s `SystemExit` propagate for
|
|
178
|
+
`--help` / `--version` / parse errors per Python convention. See
|
|
179
|
+
[`docs/api-stability.md`](docs/api-stability.md) for the full semver
|
|
180
|
+
contract.
|
|
181
|
+
|
|
182
|
+
## Runtime features
|
|
183
|
+
|
|
184
|
+
- **Classic IRC.** `PRIVMSG`, `JOIN`, `PART`, `MODE`, `TOPIC`, `NICK`,
|
|
185
|
+
`USER`, `QUIT`, `WHO`, `WHOIS`, `LIST`, `NAMES`, `INVITE`, `KICK`,
|
|
186
|
+
`PING`/`PONG`, `CAP`, `ERROR` — all the verbs an existing IRC client
|
|
187
|
+
expects.
|
|
188
|
+
- **Skill verbs.** `ROOMCREATE`/`ROOMARCHIVE`/`ROOMMETA` for rooms,
|
|
189
|
+
`THREAD`/`THREADS`/`THREADSEND`/`THREADCLOSE` for threads, `TAGS` for
|
|
190
|
+
user tags. Reference: [`docs/api-stability.md#agentircprotocol`](docs/api-stability.md#agentircprotocol).
|
|
191
|
+
- **S2S federation.** Configure peers via repeatable `--link
|
|
192
|
+
name:host:port:password[:trust]` flags or a `links:` section in YAML.
|
|
193
|
+
Trust levels: `full` (peer can relay messages and replay history) or
|
|
194
|
+
`restricted` (peer's S2S messages aren't forwarded further). See
|
|
195
|
+
[`docs/deployment.md#multi-host-federation`](docs/deployment.md#multi-host-federation).
|
|
196
|
+
- **IRCv3 message-tags + bot CAP.** Standard `message-tags` capability
|
|
197
|
+
for IRCv3 tag-aware clients; the `agentirc.io/bot` capability marks a
|
|
198
|
+
TCP client as an out-of-process bot — see the next section.
|
|
199
|
+
- **Telemetry.** OpenTelemetry traces and metrics over OTLP/gRPC, plus
|
|
200
|
+
per-day audit JSONL at `~/.culture/audit/server-<name>-YYYY-MM-DD.jsonl`
|
|
201
|
+
(rotates at UTC midnight or 256 MiB). Public observability identifiers
|
|
202
|
+
preserve the `culture.` prefix verbatim for continuity. Configure under
|
|
203
|
+
`telemetry:` in YAML.
|
|
204
|
+
- **SQLite-backed history.** Channel history persists to
|
|
205
|
+
`<data-dir>/history.db` in WAL mode; default `<data-dir>` is
|
|
206
|
+
`~/.culture/data/`. Replayable on reconnect via `BACKFILL`/`BACKFILLEND`.
|
|
207
|
+
|
|
208
|
+
## Bot extension API (since 9.5.0)
|
|
209
|
+
|
|
210
|
+
Out-of-process bots are TCP clients that negotiate the `agentirc.io/bot`
|
|
211
|
+
IRCv3 capability. Once negotiated, the client:
|
|
212
|
+
|
|
213
|
+
- Joins channels silently (no JOIN/PART/QUIT broadcasts to other members).
|
|
214
|
+
- Never gets auto-op on a newly created channel.
|
|
215
|
+
- Appears in `NAMES` prefixed with `+` and in `WHO` with a `B` flag.
|
|
216
|
+
- May issue `EVENTSUB` to stream events and `EVENTPUB` to emit custom
|
|
217
|
+
events.
|
|
218
|
+
|
|
219
|
+
The wire shape:
|
|
220
|
+
|
|
221
|
+
```text
|
|
222
|
+
EVENTSUB <sub-id> [type=<glob>] [channel=<name>] [nick=<glob>]
|
|
223
|
+
EVENTUNSUB <sub-id>
|
|
224
|
+
EVENT <sub-id> <type> <channel-or-*> <nick> :<base64-json-envelope>
|
|
225
|
+
EVENTERR <sub-id> :<reason>
|
|
226
|
+
EVENTPUB <type> <channel-or-*> :<base64-json-data>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Filters are AND-ed; `type` and `nick` accept `fnmatch`-style globs.
|
|
230
|
+
Per-subscription bounded queue (default 1024, configurable via
|
|
231
|
+
`event_subscription_queue_max` in YAML); on overflow the server emits
|
|
232
|
+
`EVENTERR <sub-id> :backpressure-overflow` and drops the subscription
|
|
233
|
+
(the connection itself stays open). The `Event` envelope is canonical
|
|
234
|
+
JSON: `{type, channel, nick, data, timestamp}`.
|
|
235
|
+
|
|
236
|
+
See [`docs/extension-api.md`](docs/extension-api.md) for the full
|
|
237
|
+
bot-author guide (event-type vocabulary, JSON shape, mention/DM
|
|
238
|
+
behavior) and
|
|
239
|
+
[`docs/api-stability.md#bot-extension-surface-shipped-in-950`](docs/api-stability.md#bot-extension-surface-shipped-in-950)
|
|
240
|
+
for the wire contract.
|
|
241
|
+
|
|
242
|
+
**Operational note.** As of 9.5.0, `agentirc` no longer binds `webhook_port`
|
|
243
|
+
even when set in YAML — the field stays in `ServerConfig` for backward
|
|
244
|
+
compatibility with culture's `~/.culture/server.yaml`, but consumers that
|
|
245
|
+
need webhook→bot dispatch host their own HTTP listener (notably culture).
|
|
246
|
+
The field will be removed in 10.0.0.
|
|
247
|
+
|
|
248
|
+
## Current state and roadmap
|
|
249
|
+
|
|
250
|
+
The bootstrap is closed; 9.0.0 through 9.5.0 are released to PyPI. The most
|
|
251
|
+
recent ship is the bot extension API (9.5.0, closes [#15](https://github.com/agentculture/agentirc/issues/15)).
|
|
252
|
+
Outstanding follow-ups are tracked in GitHub issues:
|
|
253
|
+
|
|
254
|
+
- **Track A — coordinated cross-repo wire-format fixes** (require
|
|
255
|
+
culture-side change first, then agentirc bump):
|
|
256
|
+
- [#7](https://github.com/agentculture/agentirc/issues/7) `ROOMETAEND` /
|
|
257
|
+
`ROOMETASET` typo cleanup.
|
|
258
|
+
- [#8](https://github.com/agentculture/agentirc/issues/8)
|
|
259
|
+
`ERR_NOSUCHCHANNEL` (403) semantic misuse.
|
|
260
|
+
- [#9](https://github.com/agentculture/agentirc/issues/9) `STHREAD` verb
|
|
261
|
+
collapse split.
|
|
262
|
+
- [#10](https://github.com/agentculture/agentirc/issues/10) — backport the
|
|
263
|
+
`pr-sonar.sh` + `workflow.sh sonar` wiring upstream to `steward`.
|
|
264
|
+
- [#11](https://github.com/agentculture/agentirc/issues/11) — sweep
|
|
265
|
+
inline IRC verb / numeric-reply string literals to use
|
|
266
|
+
`agentirc.protocol.<NAME>` constants. Pure refactor.
|
|
267
|
+
- [#12](https://github.com/agentculture/agentirc/issues/12) — migrate the
|
|
268
|
+
remaining bot-fixtured tests via subprocess fixture (low-priority;
|
|
269
|
+
currently in culture).
|
|
270
|
+
|
|
271
|
+
## Wire-format compatibility
|
|
272
|
+
|
|
273
|
+
Four known wire-format issues are **preserved verbatim** rather than
|
|
274
|
+
fixed, because correcting them in agentirc alone would silently break
|
|
275
|
+
federation with culture peers running unpatched code: `ROOMETAEND`
|
|
276
|
+
(should be `ROOMMETAEND`), `ROOMETASET` (should be `ROOMMETASET`),
|
|
277
|
+
`ERR_NOSUCHCHANNEL` (403) overloaded for "channel exists already", and
|
|
278
|
+
`STHREAD` collapsing what should be two separate verbs. Each requires a
|
|
279
|
+
coordinated cross-repo bump (Track A above). These constants are
|
|
280
|
+
exported as-is from `agentirc.protocol` so callers don't have to
|
|
281
|
+
hardcode the typos. See
|
|
282
|
+
[`docs/api-stability.md#wire-format-quirks-preserved-verbatim`](docs/api-stability.md#wire-format-quirks-preserved-verbatim).
|
|
283
|
+
|
|
284
|
+
The 9.5 federation seam (`SEVENT` + IRCv3 `event-data` tag) carries the
|
|
285
|
+
canonical 5-field envelope. 9.5 receivers tolerate ≤9.4 legacy peers
|
|
286
|
+
(asymmetric sniff); 9.5→9.4 emit breaks until peers upgrade. Operators
|
|
287
|
+
can roll one peer at a time and accept that 9.5-emitted events drop on
|
|
288
|
+
still-9.4 peers until those peers upgrade.
|
|
289
|
+
|
|
290
|
+
## Documentation
|
|
291
|
+
|
|
292
|
+
- [`docs/api-stability.md`](docs/api-stability.md) — public modules,
|
|
293
|
+
semver contract, `ServerConfig` / `LinkConfig` / `TelemetryConfig`
|
|
294
|
+
field reference, verb constants, wire-format quirks.
|
|
295
|
+
- [`docs/cli.md`](docs/cli.md) — verb table, flag reference, exit codes,
|
|
296
|
+
YAML/CLI precedence, `agentirc`-vs-`culture server` diff table.
|
|
297
|
+
- [`docs/deployment.md`](docs/deployment.md) — on-disk footprint, systemd
|
|
298
|
+
unit, Dockerfile, multi-host federation, log rotation, coexistence
|
|
299
|
+
with culture, backup.
|
|
300
|
+
- [`docs/extension-api.md`](docs/extension-api.md) — bot-author quick
|
|
301
|
+
reference for `agentirc.io/bot` + `EVENTSUB`/`EVENTPUB`.
|
|
302
|
+
- [`docs/superpowers/specs/`](docs/superpowers/specs/) — dated design
|
|
303
|
+
documents: bootstrap design, agentirc extraction design, bot-extension
|
|
304
|
+
API design.
|
|
305
|
+
- [`CHANGELOG.md`](CHANGELOG.md) — release notes for every published
|
|
306
|
+
version.
|
|
307
|
+
|
|
308
|
+
Upstream: [`agentculture/culture`](https://github.com/agentculture/culture).
|
|
309
|
+
Cutover tracking issue:
|
|
310
|
+
[`agentculture/culture#308`](https://github.com/agentculture/culture/issues/308).
|
|
311
|
+
|
|
312
|
+
## Contributing
|
|
313
|
+
|
|
314
|
+
Issues and PRs welcome at
|
|
315
|
+
[`agentculture/agentirc`](https://github.com/agentculture/agentirc).
|
|
316
|
+
Dev setup: `uv venv && uv pip install -e ".[dev]"`, then `pytest -n auto`
|
|
317
|
+
(the suite runs in roughly 30s on default workers).
|
|
318
|
+
|
|
319
|
+
## License
|
|
320
|
+
|
|
321
|
+
MIT — see [`LICENSE`](LICENSE).
|