agentirc-cli 9.5.0a2__tar.gz → 9.6.1__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.0a2 → agentirc_cli-9.6.1}/CHANGELOG.md +57 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/CLAUDE.md +18 -14
- agentirc_cli-9.6.1/LICENSE +201 -0
- agentirc_cli-9.6.1/PKG-INFO +301 -0
- agentirc_cli-9.6.1/README.md +266 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/bots/http_listener.py +9 -1
- agentirc_cli-9.6.1/agentirc/_internal/event_subscriptions.py +282 -0
- agentirc_cli-9.6.1/agentirc/_internal/virtual_client.py +32 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/channel.py +32 -5
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/client.py +177 -16
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/ircd.py +25 -28
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/server_link.py +1 -1
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skills/rooms.py +1 -1
- {agentirc_cli-9.5.0a2/agentirc/_internal → agentirc_cli-9.6.1/agentirc}/virtual_client.py +36 -17
- agentirc_cli-9.6.1/docs/api-stability.md +417 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/cli.md +1 -1
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/deployment.md +11 -3
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/extension-api.md +5 -5
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/pyproject.toml +17 -7
- agentirc_cli-9.6.1/tests/test_api_stability_embedding.py +138 -0
- agentirc_cli-9.6.1/tests/test_bot_capability.py +204 -0
- agentirc_cli-9.6.1/tests/test_event_subscriptions.py +335 -0
- agentirc_cli-9.6.1/tests/test_eventpub.py +194 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/uv.lock +1 -1
- agentirc_cli-9.5.0a2/LICENSE +0 -21
- agentirc_cli-9.5.0a2/PKG-INFO +0 -57
- agentirc_cli-9.5.0a2/README.md +0 -2
- agentirc_cli-9.5.0a2/docs/api-stability.md +0 -290
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/portability-lint.sh +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/pr-batch.sh +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/pr-comments.sh +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/pr-reply.sh +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/pr-sonar.sh +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/pr-status.sh +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills/pr-review/scripts/workflow.sh +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.claude/skills.local.yaml.example +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/.gitignore +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/__init__.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/__main__.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/__init__.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/aio.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/bots/__init__.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/bots/bot_manager.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/cli_shared/__init__.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/cli_shared/constants.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/cli_shared/mesh.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/constants.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/pidfile.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/protocol/__init__.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/protocol/message.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/protocol/replies.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/telemetry/__init__.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/telemetry/audit.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/telemetry/context.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/telemetry/metrics.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/_internal/telemetry/tracing.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/cli.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/config.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/events.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/history_store.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/protocol.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/remote_client.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/room_store.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/rooms_util.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skill.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skills/__init__.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skills/history.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skills/icon.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/skills/threads.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/agentirc/thread_store.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/steward/onboarding.md +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/superpowers/specs/2026-04-30-bootstrap-design.md +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/superpowers/specs/2026-05-01-bot-extension-api-design.md +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/docs/superpowers/specs/2026-05-01-task14-audit.md +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/__init__.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/_helpers.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/conftest.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/__init__.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/_fakes.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/_metrics_helpers.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_audit_emit.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_audit_lifecycle.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_audit_module.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_audit_parse_error.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_config.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_dispatch_span.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_emit_event_span.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_metrics_init.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_metrics_s2s.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_outbound_inject.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_parse_error.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_s2s_relay_span.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_server_init.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_server_link_inject.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/telemetry/test_tracing.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_channel.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_cli.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_config_loader.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_connection.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_discovery.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_basic.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_catalog.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_federation.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_history.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_lifecycle.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_events_reserved_nick.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_federation.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_history.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_mentions.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_messaging.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_modes.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_protocol_bot_exports.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_skills.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_threads.py +0 -0
- {agentirc_cli-9.5.0a2 → agentirc_cli-9.6.1}/tests/test_wire_format_envelope.py +0 -0
|
@@ -4,6 +4,63 @@ 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.1] - 2026-06-07
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- **License: MIT → Apache 2.0.** Replaced the MIT license text with the
|
|
12
|
+
Apache License 2.0 (`LICENSE`) and aligned the declared license everywhere
|
|
13
|
+
it was still MIT: `pyproject.toml` (`license = "Apache-2.0"` plus the OSI
|
|
14
|
+
classifier) and `README.md`. Copyright holder is Ori Nachum.
|
|
15
|
+
|
|
16
|
+
## [9.6.0] - 2026-05-02
|
|
17
|
+
|
|
18
|
+
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.
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **`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.
|
|
23
|
+
- **`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.
|
|
24
|
+
- **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.
|
|
25
|
+
|
|
26
|
+
### Deprecated
|
|
27
|
+
|
|
28
|
+
- **`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.
|
|
29
|
+
|
|
30
|
+
### Notes
|
|
31
|
+
|
|
32
|
+
- 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.
|
|
33
|
+
- Citation manifest updated: `culture-virtual-client` now targets `agentirc/virtual_client.py`. New entry `agentirc-internal-virtual-client-shim` covers the deprecation re-export.
|
|
34
|
+
|
|
35
|
+
## [9.5.0] - 2026-05-02
|
|
36
|
+
|
|
37
|
+
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).
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- **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`).
|
|
42
|
+
- **`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.
|
|
43
|
+
- **`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.
|
|
44
|
+
- 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.
|
|
45
|
+
- `agentirc.protocol.SEVENT` verb constant (added in 9.5.0a2; reaffirmed here).
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- **`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.
|
|
50
|
+
- `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.
|
|
51
|
+
- `Channel.get_prefix()` returns `+` for bot-CAP members in NAMES output.
|
|
52
|
+
- `Client._build_who_flags()` adds the `B` flag for bot-CAP members in WHO output (composes with `H` and `@`/`+`).
|
|
53
|
+
- `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.
|
|
54
|
+
- `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).
|
|
55
|
+
- `agentirc/_internal/bots/http_listener.py` module docstring notes the no-op stub is scheduled for removal in 9.6.0.
|
|
56
|
+
|
|
57
|
+
### Notes
|
|
58
|
+
|
|
59
|
+
- 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.
|
|
60
|
+
- **Federation interop unchanged from 9.5.0a2.** 9.4→9.5 federation works (sniff tolerance); 9.5→9.4 emit breaks until peers upgrade.
|
|
61
|
+
- 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.
|
|
62
|
+
- 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.
|
|
63
|
+
|
|
7
64
|
## [9.5.0a2] - 2026-05-02
|
|
8
65
|
|
|
9
66
|
### Changed
|
|
@@ -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,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright 2026 Ori Nachum
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentirc-cli
|
|
3
|
+
Version: 9.6.1
|
|
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-Expression: Apache-2.0
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: agents,culture,irc,ircd,mesh
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Communications :: Chat :: Internet Relay Chat
|
|
19
|
+
Requires-Python: >=3.11
|
|
20
|
+
Requires-Dist: opentelemetry-api>=1.22
|
|
21
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.22
|
|
22
|
+
Requires-Dist: opentelemetry-sdk>=1.22
|
|
23
|
+
Requires-Dist: pyyaml>=6.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: bandit; extra == 'dev'
|
|
26
|
+
Requires-Dist: black; extra == 'dev'
|
|
27
|
+
Requires-Dist: citation-cli; extra == 'dev'
|
|
28
|
+
Requires-Dist: flake8; extra == 'dev'
|
|
29
|
+
Requires-Dist: isort; extra == 'dev'
|
|
30
|
+
Requires-Dist: pylint; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-xdist>=3; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# AgentIRC
|
|
37
|
+
|
|
38
|
+
[](https://pypi.org/project/agentirc-cli/)
|
|
39
|
+
[](https://pypi.org/project/agentirc-cli/)
|
|
40
|
+
[](LICENSE)
|
|
41
|
+
|
|
42
|
+
**Agent-friendly IRCd for AI agent meshes.**
|
|
43
|
+
|
|
44
|
+
`agentirc` is a standalone IRC runtime for human-and-agent rooms. It speaks
|
|
45
|
+
classic IRC ([RFC 2812](https://datatracker.ietf.org/doc/html/rfc2812))
|
|
46
|
+
plus IRCv3 message-tags, room/thread/tag skill verbs, server-to-server
|
|
47
|
+
federation with trust levels, and an out-of-process bot extension API
|
|
48
|
+
(`agentirc.io/bot` capability + `EVENTSUB`/`EVENTUNSUB`/`EVENTPUB` verbs).
|
|
49
|
+
It ships with a small, semver-tracked Python API (`agentirc.config`,
|
|
50
|
+
`agentirc.cli`, `agentirc.protocol`) so other tools can drive an IRCd as a
|
|
51
|
+
library, and a CLI (`agentirc serve`, `agentirc start`, …) for operators.
|
|
52
|
+
|
|
53
|
+
It is the runtime/protocol layer extracted from
|
|
54
|
+
[`culture`](https://github.com/agentculture/culture), the AgentCulture
|
|
55
|
+
agent-mesh project. You don't need culture to use it — `pip install
|
|
56
|
+
agentirc-cli` is a complete IRCd.
|
|
57
|
+
|
|
58
|
+
## Relationship to Culture
|
|
59
|
+
|
|
60
|
+
`agentirc` is the standalone server-core; `culture` is the agent-orchestration
|
|
61
|
+
layer that wraps it.
|
|
62
|
+
|
|
63
|
+
| Concern | Lives in |
|
|
64
|
+
|---|---|
|
|
65
|
+
| IRCd, channels, federation, history, telemetry | `agentirc` |
|
|
66
|
+
| Client transport, IRCv3 message-tags | `agentirc` |
|
|
67
|
+
| Public Python API (`agentirc.config`, `agentirc.cli`, `agentirc.protocol`) | `agentirc` |
|
|
68
|
+
| Bot extension API (CAP + `EVENTSUB`/`EVENTPUB`) | `agentirc` |
|
|
69
|
+
| Agent backends (`claude`, `codex`, `copilot`, `acp`) | `culture` |
|
|
70
|
+
| Console, mesh credentials, OS keyring | `culture` |
|
|
71
|
+
| Process supervisor, agent manifest | `culture` |
|
|
72
|
+
|
|
73
|
+
Server-core code is vendored from culture under the **cite-don't-copy**
|
|
74
|
+
pattern — see `[tool.citation]` in [`pyproject.toml`](pyproject.toml) for the
|
|
75
|
+
provenance ledger. Defaults preserve continuity with culture (config path
|
|
76
|
+
`~/.culture/server.yaml`, log path `~/.culture/logs/server-<name>.log`,
|
|
77
|
+
audit path `~/.culture/audit/`) so existing culture deployments don't have
|
|
78
|
+
to migrate; standalone users override via `--config`.
|
|
79
|
+
|
|
80
|
+
## Install
|
|
81
|
+
|
|
82
|
+
From PyPI:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pip install agentirc-cli
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The package is published as **`agentirc-cli`** on real PyPI; on TestPyPI it is
|
|
89
|
+
dual-published as `agentirc-cli` and `agentirc` (both wheels point at the
|
|
90
|
+
same code). Two console scripts are installed — `agentirc` and
|
|
91
|
+
`agentirc-cli` — both routing to the same `agentirc.cli:main` entry point.
|
|
92
|
+
`python -m agentirc <verb>` works equivalently.
|
|
93
|
+
|
|
94
|
+
`agentirc-cli` requires Python 3.11+.
|
|
95
|
+
|
|
96
|
+
## Quickstart
|
|
97
|
+
|
|
98
|
+
Run an IRCd in the foreground (the recommended path under systemd `Type=simple`
|
|
99
|
+
or a container runtime):
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
agentirc serve --host 0.0.0.0 --port 6667
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Or as a managed background daemon:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
agentirc start --name spark --port 6667
|
|
109
|
+
agentirc status --name spark # Server 'spark': running (PID N, port 6667)
|
|
110
|
+
agentirc logs --name spark -f # tail ~/.culture/logs/server-spark.log
|
|
111
|
+
agentirc stop --name spark
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
A YAML config file overrides the built-in defaults; CLI flags override the
|
|
115
|
+
YAML. The default config path is `~/.culture/server.yaml`:
|
|
116
|
+
|
|
117
|
+
```yaml
|
|
118
|
+
server:
|
|
119
|
+
name: spark
|
|
120
|
+
host: 127.0.0.1
|
|
121
|
+
port: 6700
|
|
122
|
+
telemetry:
|
|
123
|
+
enabled: true
|
|
124
|
+
links:
|
|
125
|
+
- {name: alpha, host: 10.0.0.1, port: 6667, password: secret, trust: full}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
agentirc serve --config ~/.culture/server.yaml --port 9999 # CLI > YAML
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
For Python consumers:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from agentirc.config import ServerConfig
|
|
136
|
+
cfg = ServerConfig.from_yaml("~/.culture/server.yaml")
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
See [`docs/cli.md`](docs/cli.md) for the full verb reference and
|
|
140
|
+
[`docs/deployment.md`](docs/deployment.md) for systemd, containers, and
|
|
141
|
+
multi-host federation.
|
|
142
|
+
|
|
143
|
+
## Public API and stability
|
|
144
|
+
|
|
145
|
+
Three modules form the **public, semver-tracked surface**. Everything else
|
|
146
|
+
under `agentirc.*` is internal and may be refactored — including renamed,
|
|
147
|
+
split, or removed — in any minor or patch release.
|
|
148
|
+
|
|
149
|
+
| Module | Members |
|
|
150
|
+
|---|---|
|
|
151
|
+
| [`agentirc.config`](docs/api-stability.md#agentircconfig) | `ServerConfig`, `LinkConfig`, `TelemetryConfig`, `ServerConfig.from_yaml(path)` |
|
|
152
|
+
| [`agentirc.cli`](docs/api-stability.md#agentirccli) | `main()`, `dispatch(argv) -> int` |
|
|
153
|
+
| [`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`) |
|
|
154
|
+
|
|
155
|
+
`agentirc.cli.dispatch(argv)` is the in-process integration surface — it is
|
|
156
|
+
what culture's `culture server` shim calls today. It returns `int` on
|
|
157
|
+
successful dispatch and lets `argparse`'s `SystemExit` propagate for
|
|
158
|
+
`--help` / `--version` / parse errors per Python convention. See
|
|
159
|
+
[`docs/api-stability.md`](docs/api-stability.md) for the full semver
|
|
160
|
+
contract.
|
|
161
|
+
|
|
162
|
+
## Runtime features
|
|
163
|
+
|
|
164
|
+
- **Classic IRC.** `PRIVMSG`, `JOIN`, `PART`, `MODE`, `TOPIC`, `NICK`,
|
|
165
|
+
`USER`, `QUIT`, `WHO`, `WHOIS`, `LIST`, `NAMES`, `INVITE`, `KICK`,
|
|
166
|
+
`PING`/`PONG`, `CAP`, `ERROR` — all the verbs an existing IRC client
|
|
167
|
+
expects.
|
|
168
|
+
- **Skill verbs.** `ROOMCREATE`/`ROOMARCHIVE`/`ROOMMETA` for rooms,
|
|
169
|
+
`THREAD`/`THREADS`/`THREADSEND`/`THREADCLOSE` for threads, `TAGS` for
|
|
170
|
+
user tags. Reference: [`docs/api-stability.md#agentircprotocol`](docs/api-stability.md#agentircprotocol).
|
|
171
|
+
- **S2S federation.** Configure peers via repeatable `--link
|
|
172
|
+
name:host:port:password[:trust]` flags or a `links:` section in YAML.
|
|
173
|
+
Trust levels: `full` (peer can relay messages and replay history) or
|
|
174
|
+
`restricted` (peer's S2S messages aren't forwarded further). See
|
|
175
|
+
[`docs/deployment.md#multi-host-federation`](docs/deployment.md#multi-host-federation).
|
|
176
|
+
- **IRCv3 message-tags + bot CAP.** Standard `message-tags` capability
|
|
177
|
+
for IRCv3 tag-aware clients; the `agentirc.io/bot` capability marks a
|
|
178
|
+
TCP client as an out-of-process bot — see the next section.
|
|
179
|
+
- **Telemetry.** OpenTelemetry traces and metrics over OTLP/gRPC, plus
|
|
180
|
+
per-day audit JSONL at `~/.culture/audit/server-<name>-YYYY-MM-DD.jsonl`
|
|
181
|
+
(rotates at UTC midnight or 256 MiB). Public observability identifiers
|
|
182
|
+
preserve the `culture.` prefix verbatim for continuity. Configure under
|
|
183
|
+
`telemetry:` in YAML.
|
|
184
|
+
- **SQLite-backed history.** Channel history persists to
|
|
185
|
+
`<data-dir>/history.db` in WAL mode; default `<data-dir>` is
|
|
186
|
+
`~/.culture/data/`. Replayable on reconnect via `BACKFILL`/`BACKFILLEND`.
|
|
187
|
+
|
|
188
|
+
## Bot extension API (since 9.5.0)
|
|
189
|
+
|
|
190
|
+
Out-of-process bots are TCP clients that negotiate the `agentirc.io/bot`
|
|
191
|
+
IRCv3 capability. Once negotiated, the client:
|
|
192
|
+
|
|
193
|
+
- Joins channels silently (no JOIN/PART/QUIT broadcasts to other members).
|
|
194
|
+
- Never gets auto-op on a newly created channel.
|
|
195
|
+
- Appears in `NAMES` prefixed with `+` and in `WHO` with a `B` flag.
|
|
196
|
+
- May issue `EVENTSUB` to stream events and `EVENTPUB` to emit custom
|
|
197
|
+
events.
|
|
198
|
+
|
|
199
|
+
The wire shape:
|
|
200
|
+
|
|
201
|
+
```text
|
|
202
|
+
EVENTSUB <sub-id> [type=<glob>] [channel=<name>] [nick=<glob>]
|
|
203
|
+
EVENTUNSUB <sub-id>
|
|
204
|
+
EVENT <sub-id> <type> <channel-or-*> <nick> :<base64-json-envelope>
|
|
205
|
+
EVENTERR <sub-id> :<reason>
|
|
206
|
+
EVENTPUB <type> <channel-or-*> :<base64-json-data>
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Filters are AND-ed; `type` and `nick` accept `fnmatch`-style globs.
|
|
210
|
+
Per-subscription bounded queue (default 1024, configurable via
|
|
211
|
+
`event_subscription_queue_max` in YAML); on overflow the server emits
|
|
212
|
+
`EVENTERR <sub-id> :backpressure-overflow` and drops the subscription
|
|
213
|
+
(the connection itself stays open). The `Event` envelope is canonical
|
|
214
|
+
JSON: `{type, channel, nick, data, timestamp}`.
|
|
215
|
+
|
|
216
|
+
See [`docs/extension-api.md`](docs/extension-api.md) for the full
|
|
217
|
+
bot-author guide (event-type vocabulary, JSON shape, mention/DM
|
|
218
|
+
behavior) and
|
|
219
|
+
[`docs/api-stability.md#bot-extension-surface-shipped-in-950`](docs/api-stability.md#bot-extension-surface-shipped-in-950)
|
|
220
|
+
for the wire contract.
|
|
221
|
+
|
|
222
|
+
**Operational note.** As of 9.5.0, `agentirc` no longer binds `webhook_port`
|
|
223
|
+
even when set in YAML — the field stays in `ServerConfig` for backward
|
|
224
|
+
compatibility with culture's `~/.culture/server.yaml`, but consumers that
|
|
225
|
+
need webhook→bot dispatch host their own HTTP listener (notably culture).
|
|
226
|
+
The field will be removed in 10.0.0.
|
|
227
|
+
|
|
228
|
+
## Current state and roadmap
|
|
229
|
+
|
|
230
|
+
The bootstrap is closed; 9.0.0 through 9.5.0 are released to PyPI. The most
|
|
231
|
+
recent ship is the bot extension API (9.5.0, closes [#15](https://github.com/agentculture/agentirc/issues/15)).
|
|
232
|
+
Outstanding follow-ups are tracked in GitHub issues:
|
|
233
|
+
|
|
234
|
+
- **Track A — coordinated cross-repo wire-format fixes** (require
|
|
235
|
+
culture-side change first, then agentirc bump):
|
|
236
|
+
- [#7](https://github.com/agentculture/agentirc/issues/7) `ROOMETAEND` /
|
|
237
|
+
`ROOMETASET` typo cleanup.
|
|
238
|
+
- [#8](https://github.com/agentculture/agentirc/issues/8)
|
|
239
|
+
`ERR_NOSUCHCHANNEL` (403) semantic misuse.
|
|
240
|
+
- [#9](https://github.com/agentculture/agentirc/issues/9) `STHREAD` verb
|
|
241
|
+
collapse split.
|
|
242
|
+
- [#10](https://github.com/agentculture/agentirc/issues/10) — backport the
|
|
243
|
+
`pr-sonar.sh` + `workflow.sh sonar` wiring upstream to `steward`.
|
|
244
|
+
- [#11](https://github.com/agentculture/agentirc/issues/11) — sweep
|
|
245
|
+
inline IRC verb / numeric-reply string literals to use
|
|
246
|
+
`agentirc.protocol.<NAME>` constants. Pure refactor.
|
|
247
|
+
- [#12](https://github.com/agentculture/agentirc/issues/12) — migrate the
|
|
248
|
+
remaining bot-fixtured tests via subprocess fixture (low-priority;
|
|
249
|
+
currently in culture).
|
|
250
|
+
|
|
251
|
+
## Wire-format compatibility
|
|
252
|
+
|
|
253
|
+
Four known wire-format issues are **preserved verbatim** rather than
|
|
254
|
+
fixed, because correcting them in agentirc alone would silently break
|
|
255
|
+
federation with culture peers running unpatched code: `ROOMETAEND`
|
|
256
|
+
(should be `ROOMMETAEND`), `ROOMETASET` (should be `ROOMMETASET`),
|
|
257
|
+
`ERR_NOSUCHCHANNEL` (403) overloaded for "channel exists already", and
|
|
258
|
+
`STHREAD` collapsing what should be two separate verbs. Each requires a
|
|
259
|
+
coordinated cross-repo bump (Track A above). These constants are
|
|
260
|
+
exported as-is from `agentirc.protocol` so callers don't have to
|
|
261
|
+
hardcode the typos. See
|
|
262
|
+
[`docs/api-stability.md#wire-format-quirks-preserved-verbatim`](docs/api-stability.md#wire-format-quirks-preserved-verbatim).
|
|
263
|
+
|
|
264
|
+
The 9.5 federation seam (`SEVENT` + IRCv3 `event-data` tag) carries the
|
|
265
|
+
canonical 5-field envelope. 9.5 receivers tolerate ≤9.4 legacy peers
|
|
266
|
+
(asymmetric sniff); 9.5→9.4 emit breaks until peers upgrade. Operators
|
|
267
|
+
can roll one peer at a time and accept that 9.5-emitted events drop on
|
|
268
|
+
still-9.4 peers until those peers upgrade.
|
|
269
|
+
|
|
270
|
+
## Documentation
|
|
271
|
+
|
|
272
|
+
- [`docs/api-stability.md`](docs/api-stability.md) — public modules,
|
|
273
|
+
semver contract, `ServerConfig` / `LinkConfig` / `TelemetryConfig`
|
|
274
|
+
field reference, verb constants, wire-format quirks.
|
|
275
|
+
- [`docs/cli.md`](docs/cli.md) — verb table, flag reference, exit codes,
|
|
276
|
+
YAML/CLI precedence, `agentirc`-vs-`culture server` diff table.
|
|
277
|
+
- [`docs/deployment.md`](docs/deployment.md) — on-disk footprint, systemd
|
|
278
|
+
unit, Dockerfile, multi-host federation, log rotation, coexistence
|
|
279
|
+
with culture, backup.
|
|
280
|
+
- [`docs/extension-api.md`](docs/extension-api.md) — bot-author quick
|
|
281
|
+
reference for `agentirc.io/bot` + `EVENTSUB`/`EVENTPUB`.
|
|
282
|
+
- [`docs/superpowers/specs/`](docs/superpowers/specs/) — dated design
|
|
283
|
+
documents: bootstrap design, agentirc extraction design, bot-extension
|
|
284
|
+
API design.
|
|
285
|
+
- [`CHANGELOG.md`](CHANGELOG.md) — release notes for every published
|
|
286
|
+
version.
|
|
287
|
+
|
|
288
|
+
Upstream: [`agentculture/culture`](https://github.com/agentculture/culture).
|
|
289
|
+
Cutover tracking issue:
|
|
290
|
+
[`agentculture/culture#308`](https://github.com/agentculture/culture/issues/308).
|
|
291
|
+
|
|
292
|
+
## Contributing
|
|
293
|
+
|
|
294
|
+
Issues and PRs welcome at
|
|
295
|
+
[`agentculture/agentirc`](https://github.com/agentculture/agentirc).
|
|
296
|
+
Dev setup: `uv venv && uv pip install -e ".[dev]"`, then `pytest -n auto`
|
|
297
|
+
(the suite runs in roughly 30s on default workers).
|
|
298
|
+
|
|
299
|
+
## License
|
|
300
|
+
|
|
301
|
+
Apache 2.0 — see [`LICENSE`](LICENSE).
|