agentirc-cli 9.4.0__tar.gz → 9.5.0a1__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.4.0 → agentirc_cli-9.5.0a1}/CHANGELOG.md +28 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/CLAUDE.md +8 -8
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/PKG-INFO +3 -3
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/cli.py +4 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/config.py +10 -2
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/protocol.py +130 -2
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/skill.py +10 -37
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/docs/api-stability.md +56 -0
- agentirc_cli-9.5.0a1/docs/extension-api.md +243 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/docs/superpowers/specs/2026-04-30-bootstrap-design.md +4 -3
- agentirc_cli-9.5.0a1/docs/superpowers/specs/2026-05-01-bot-extension-api-design.md +458 -0
- agentirc_cli-9.5.0a1/docs/superpowers/specs/2026-05-01-task14-audit.md +65 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/pyproject.toml +18 -18
- agentirc_cli-9.5.0a1/tests/test_protocol_bot_exports.py +214 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/uv.lock +1 -1
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.claude/skills/pr-review/scripts/portability-lint.sh +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.claude/skills/pr-review/scripts/pr-batch.sh +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.claude/skills/pr-review/scripts/pr-comments.sh +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.claude/skills/pr-review/scripts/pr-reply.sh +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.claude/skills/pr-review/scripts/pr-sonar.sh +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.claude/skills/pr-review/scripts/pr-status.sh +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.claude/skills/pr-review/scripts/workflow.sh +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.claude/skills.local.yaml.example +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/.gitignore +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/LICENSE +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/README.md +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/__init__.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/__main__.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/__init__.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/aio.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/bots/__init__.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/bots/bot_manager.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/bots/http_listener.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/cli_shared/__init__.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/cli_shared/constants.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/cli_shared/mesh.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/constants.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/pidfile.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/protocol/__init__.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/protocol/message.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/protocol/replies.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/telemetry/__init__.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/telemetry/audit.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/telemetry/context.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/telemetry/metrics.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/telemetry/tracing.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/_internal/virtual_client.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/channel.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/client.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/events.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/history_store.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/ircd.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/remote_client.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/room_store.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/rooms_util.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/server_link.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/skills/__init__.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/skills/history.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/skills/icon.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/skills/rooms.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/skills/threads.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/agentirc/thread_store.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/docs/cli.md +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/docs/deployment.md +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/docs/steward/onboarding.md +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/__init__.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/_helpers.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/conftest.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/__init__.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/_fakes.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/_metrics_helpers.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_audit_emit.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_audit_lifecycle.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_audit_module.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_audit_parse_error.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_config.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_dispatch_span.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_emit_event_span.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_metrics_init.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_metrics_s2s.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_outbound_inject.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_parse_error.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_s2s_relay_span.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_server_init.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_server_link_inject.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/telemetry/test_tracing.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_channel.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_cli.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_config_loader.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_connection.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_discovery.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_events_basic.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_events_catalog.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_events_federation.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_events_history.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_events_lifecycle.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_events_reserved_nick.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_federation.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_history.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_mentions.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_messaging.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_modes.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_skills.py +0 -0
- {agentirc_cli-9.4.0 → agentirc_cli-9.5.0a1}/tests/test_threads.py +0 -0
|
@@ -4,6 +4,34 @@ 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.5.0a1] - 2026-05-02
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Public `agentirc.protocol` exports for the bot extension API: the `Event` dataclass, the `EventType` enum, 20 per-type `EVENT_TYPE_*` string constants, the `EVENTSUB` / `EVENTUNSUB` / `EVENT` / `EVENTERR` / `EVENTPUB` verb constants, and the `BOT_CAP = "agentirc.io/bot"` capability identifier. `Event.type` is widened to `EventType | str` so federation peers can deliver event types this version doesn't recognise. See `docs/superpowers/specs/2026-05-01-bot-extension-api-design.md` for the full design and `docs/extension-api.md` for the bot-author quick reference.
|
|
12
|
+
- `ServerConfig.event_subscription_queue_max: int = 1024` — per-subscription queue bound. Recognised by `ServerConfig.from_yaml` and `cli._resolve_config()` as a top-level YAML key. Consumed by the subscription registry that lands in 9.5.0a3.
|
|
13
|
+
- `agentirc.skill` keeps re-exporting `Event` and `EventType` for backward compat; the re-export shim is removed in 9.6.0 once Phase A2 confirms no consumer relies on the path.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- `EventType` upgraded from `enum.Enum` to `enum.StrEnum`. Members keep their `.value` strings unchanged, but Python consumers now observe new identity semantics: `isinstance(EventType.JOIN, str)` is `True`, `EventType.JOIN == "user.join"` is `True`, JSON serialization emits the bare string. Internal call sites verified — none compare `EventType.X` against a bare string today, so the truthier equality is pure improvement; downstream consumers that did string-equality round-trips against `EventType` see strictly more matches, never fewer.
|
|
18
|
+
|
|
19
|
+
### Notes
|
|
20
|
+
|
|
21
|
+
- This is the **declarations slice** of the bot extension API. No daemon-level behavior changes: `EVENTSUB` etc. are reserved verb constants but the daemon does not yet handle them; `BOT_CAP` is exported but not yet advertised in `CAP LS` output. The wire-format envelope refactor lands in 9.5.0a2; the bot CAP behavior, subscription verbs, `EVENTPUB`, and `webhook_port` unbinding land in 9.5.0a3 / 9.5.0 final.
|
|
22
|
+
- Tracks [agentculture/agentirc#15](https://github.com/agentculture/agentirc/issues/15).
|
|
23
|
+
|
|
24
|
+
## [9.4.1] - 2026-05-01
|
|
25
|
+
|
|
26
|
+
### Documentation
|
|
27
|
+
|
|
28
|
+
- Marked the bootstrap closed in `docs/superpowers/specs/2026-04-30-bootstrap-design.md` and `CLAUDE.md`. Tasks 16–18 (tag `v9.4.0`, verify PyPI publish, report-back to culture) are done; the spec status note now reads as a closed timeline ("Released ✅"), and `CLAUDE.md`'s "Current state" reads "bootstrap complete (9.4.0 released)" with a non-blocking follow-ups list linking to issues #7–#12 (Track A wire-format fixes, steward backport, callsite sweep, A2 test migration).
|
|
29
|
+
- Fixed 14 stale `OriNachum/*` GitHub URLs in `pyproject.toml` and the bootstrap spec to canonical `agentculture/*` paths. Investigation showed these weren't merely stylistic — `https://github.com/OriNachum/culture` returns 404 and `https://github.com/OriNachum/agentirc` 301-redirects to the wrong path. URL fixes only; sha256s are content-hashed and unaffected. `cite check` still passes.
|
|
30
|
+
|
|
31
|
+
### Notes
|
|
32
|
+
|
|
33
|
+
- Functionally identical to `9.4.0`. Published as a fresh PyPI release because `publish.yml` triggers on push-to-`main` and PyPI rejects re-publishing the same version with different sha256.
|
|
34
|
+
|
|
7
35
|
## [9.4.0] - 2026-05-01
|
|
8
36
|
|
|
9
37
|
### Added
|
|
@@ -2,9 +2,9 @@
|
|
|
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 complete (9.4.0 released)
|
|
6
6
|
|
|
7
|
-
This repo is the agentirc server-core extraction out of the sibling project [`culture`](https://github.com/
|
|
7
|
+
This repo is the agentirc server-core extraction out of the sibling project [`culture`](https://github.com/agentculture/culture). As of 9.4.0 (tagged at `5590256` and live on PyPI):
|
|
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.
|
|
@@ -15,13 +15,13 @@ This repo is the agentirc server-core extraction out of the sibling project [`cu
|
|
|
15
15
|
- **Internal support** (`agentirc/_internal/`) — `aio`, `constants`, `protocol/`, `telemetry/`, `virtual_client`, `pidfile`, `cli_shared/`, `bots/` stubs.
|
|
16
16
|
- **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).
|
|
17
17
|
|
|
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.
|
|
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.4.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 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
19
|
|
|
20
|
-
|
|
21
|
-
- **
|
|
22
|
-
- **
|
|
23
|
-
- **
|
|
24
|
-
- **
|
|
20
|
+
**Outstanding follow-ups (non-blocking; the bootstrap itself is closed):**
|
|
21
|
+
- **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.
|
|
22
|
+
- **Steward backport** — [#10](https://github.com/agentculture/agentirc/issues/10). Port the 9.3.0 `pr-sonar.sh` + `workflow.sh sonar` wiring upstream so other workspace projects pick it up via re-vendoring.
|
|
23
|
+
- **Optional callsite sweep** — [#11](https://github.com/agentculture/agentirc/issues/11). Replace inline IRC verb / numeric-reply string literals in `ircd.py`/`server_link.py`/`skills/*.py` with `agentirc.protocol.<NAME>` imports. Pure refactor.
|
|
24
|
+
- **A2 bot-fixtured tests (low-priority)** — [#12](https://github.com/agentculture/agentirc/issues/12). Currently in culture; could be migrated to agentirc via subprocess-fixture rewrite if culture's coverage drifts.
|
|
25
25
|
|
|
26
26
|
Read the bootstrap spec at `docs/superpowers/specs/2026-04-30-bootstrap-design.md` for the full plan; it is the operative source of truth and is intentionally self-contained. The culture-side counterpart spec is at `../culture/docs/superpowers/specs/2026-04-30-agentirc-extraction-design.md` — not normally needed, but explains *why* if a decision looks arbitrary.
|
|
27
27
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentirc-cli
|
|
3
|
-
Version: 9.
|
|
3
|
+
Version: 9.5.0a1
|
|
4
4
|
Summary: Agent-friendly IRCd: server core for AI agent meshes
|
|
5
|
-
Project-URL: Homepage, https://github.com/
|
|
6
|
-
Project-URL: Issues, https://github.com/
|
|
5
|
+
Project-URL: Homepage, https://github.com/agentculture/agentirc
|
|
6
|
+
Project-URL: Issues, https://github.com/agentculture/agentirc/issues
|
|
7
7
|
Author: Ori Nachum
|
|
8
8
|
License: MIT License
|
|
9
9
|
|
|
@@ -185,6 +185,9 @@ def _resolve_config(args: argparse.Namespace) -> "ServerConfig": # noqa: F821 (
|
|
|
185
185
|
args.data_dir, raw.get("data_dir"), os.path.expanduser("~/.culture/data")
|
|
186
186
|
)
|
|
187
187
|
)
|
|
188
|
+
event_subscription_queue_max = _pick(
|
|
189
|
+
None, raw.get("event_subscription_queue_max"), 1024
|
|
190
|
+
)
|
|
188
191
|
|
|
189
192
|
cfg = ServerConfig(
|
|
190
193
|
name=name or "agentirc",
|
|
@@ -195,6 +198,7 @@ def _resolve_config(args: argparse.Namespace) -> "ServerConfig": # noqa: F821 (
|
|
|
195
198
|
links=_resolve_links(getattr(args, "link", None), raw.get("links") or []),
|
|
196
199
|
system_bots=raw.get("system_bots") or {},
|
|
197
200
|
telemetry=_build_telemetry(raw.get("telemetry") or {}),
|
|
201
|
+
event_subscription_queue_max=event_subscription_queue_max,
|
|
198
202
|
)
|
|
199
203
|
|
|
200
204
|
args.name = name # may be None — handler resolves via default-server file
|
|
@@ -53,13 +53,21 @@ class ServerConfig:
|
|
|
53
53
|
links: list[LinkConfig] = field(default_factory=list)
|
|
54
54
|
system_bots: dict = field(default_factory=dict)
|
|
55
55
|
telemetry: TelemetryConfig = field(default_factory=TelemetryConfig)
|
|
56
|
+
# Bot extension API (9.5.0): per-subscription event-queue bound. When
|
|
57
|
+
# exceeded, the subscription is dropped with EVENTERR :backpressure-overflow
|
|
58
|
+
# and the bot reconciles via re-subscribe + BACKFILL. Behavior wires up in
|
|
59
|
+
# 9.5.0a3; the field is exposed in 9.5.0a1 so consumers can pin against the
|
|
60
|
+
# public surface.
|
|
61
|
+
event_subscription_queue_max: int = 1024
|
|
56
62
|
|
|
57
63
|
@classmethod
|
|
58
64
|
def from_yaml(cls, path: str | Path) -> "ServerConfig":
|
|
59
65
|
"""Load a ServerConfig from a YAML file.
|
|
60
66
|
|
|
61
67
|
Recognises top-level ``server`` (host/port/name), ``telemetry``,
|
|
62
|
-
``links``, ``webhook_port``, ``data_dir``,
|
|
68
|
+
``links``, ``webhook_port``, ``data_dir``, ``system_bots``, and
|
|
69
|
+
``event_subscription_queue_max`` (added in 9.5.0a1; consumed by
|
|
70
|
+
the subscription registry that lands in 9.5.0a3).
|
|
63
71
|
Unknown top-level keys (``supervisor``, ``agents``, ``buffer_size``,
|
|
64
72
|
``poll_interval``, ``sleep_start``, ``sleep_end``) are silently
|
|
65
73
|
ignored — those belong to culture's broader process supervisor,
|
|
@@ -104,7 +112,7 @@ def _yaml_kwargs(raw: dict[str, Any]) -> dict[str, Any]:
|
|
|
104
112
|
for key in ("name", "host", "port"):
|
|
105
113
|
if key in server_section:
|
|
106
114
|
kwargs[key] = server_section[key]
|
|
107
|
-
for key in ("webhook_port", "data_dir"):
|
|
115
|
+
for key in ("webhook_port", "data_dir", "event_subscription_queue_max"):
|
|
108
116
|
if key in raw:
|
|
109
117
|
kwargs[key] = raw[key]
|
|
110
118
|
links_section = raw.get("links") or []
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"""Public protocol surface for agentirc — verbs, numerics, and
|
|
1
|
+
"""Public protocol surface for agentirc — verbs, numerics, tags, and the bot extension API.
|
|
2
2
|
|
|
3
|
-
Semver-tracked module.
|
|
3
|
+
Semver-tracked module. Five categories of public symbols live here:
|
|
4
4
|
|
|
5
5
|
1. **Verb names** — IRC command verbs as bare uppercase tokens. Mostly
|
|
6
6
|
RFC 2812 (PRIVMSG, JOIN, QUIT, ...), plus agentirc skill verbs
|
|
@@ -14,6 +14,16 @@ Semver-tracked module. Three categories of constants live here:
|
|
|
14
14
|
consumers don't reach into the underscore namespace.
|
|
15
15
|
3. **Message tag names** — IRCv3 tag keys for traceparent/tracestate
|
|
16
16
|
and agentirc-specific event tags.
|
|
17
|
+
4. **Event types and the Event dataclass** — :class:`EventType`
|
|
18
|
+
(a :class:`enum.StrEnum` of 20 dotted-lowercase wire strings) and
|
|
19
|
+
:class:`Event` (a frozen-shape dataclass). Plus 20 ``EVENT_TYPE_*``
|
|
20
|
+
per-type string constants for callers that prefer bare strings over
|
|
21
|
+
enum-coercion at JSON boundaries. Added in 9.5.0a1 as part of the
|
|
22
|
+
bot extension API.
|
|
23
|
+
5. **Bot extension verbs and capability** — ``EVENTSUB``, ``EVENTUNSUB``,
|
|
24
|
+
``EVENT``, ``EVENTERR``, ``EVENTPUB`` verb constants and
|
|
25
|
+
``BOT_CAP = "agentirc.io/bot"``. Reserved in 9.5.0a1; daemon
|
|
26
|
+
behavior wires up in 9.5.0a3 / 9.5.0 final.
|
|
17
27
|
|
|
18
28
|
Existing call sites under ``agentirc.ircd``, ``agentirc.server_link``
|
|
19
29
|
and the skills modules still use inline string literals. Migrating them
|
|
@@ -31,6 +41,11 @@ clients and federation. They need a coordinated cross-repo bump.
|
|
|
31
41
|
|
|
32
42
|
from __future__ import annotations
|
|
33
43
|
|
|
44
|
+
import time
|
|
45
|
+
from dataclasses import dataclass, field
|
|
46
|
+
from enum import StrEnum
|
|
47
|
+
from typing import Any
|
|
48
|
+
|
|
34
49
|
# ---------------------------------------------------------------------------
|
|
35
50
|
# Numeric reply codes (re-exported from the internal module)
|
|
36
51
|
# ---------------------------------------------------------------------------
|
|
@@ -164,6 +179,90 @@ ROOMETAEND = "ROOMETAEND" # SIC: typo preserved for wire compat (ROOMMETAEND ta
|
|
|
164
179
|
ROOMETASET = "ROOMETASET" # SIC: typo preserved for wire compat (ROOMMETASET target)
|
|
165
180
|
|
|
166
181
|
|
|
182
|
+
# ---------------------------------------------------------------------------
|
|
183
|
+
# Bot extension API (9.5.0)
|
|
184
|
+
# ---------------------------------------------------------------------------
|
|
185
|
+
# Public Event dataclass + EventType enum, per-type string constants, the
|
|
186
|
+
# EVENTSUB / EVENTUNSUB / EVENT / EVENTERR / EVENTPUB verb names, and the
|
|
187
|
+
# bot-CAP token. See docs/superpowers/specs/2026-05-01-bot-extension-api-design.md
|
|
188
|
+
# for the wire format and verb syntax. Behavior wiring lands in 9.5.0a2/a3;
|
|
189
|
+
# 9.5.0a1 ships these symbols only.
|
|
190
|
+
|
|
191
|
+
# `EventType` is `StrEnum` so `EventType.JOIN == "user.join"` is True at JSON
|
|
192
|
+
# boundaries. Adding a new member is a minor bump; renaming or removing one
|
|
193
|
+
# is a major bump.
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class EventType(StrEnum):
|
|
197
|
+
MESSAGE = "message"
|
|
198
|
+
JOIN = "user.join"
|
|
199
|
+
PART = "user.part"
|
|
200
|
+
QUIT = "user.quit"
|
|
201
|
+
TOPIC = "topic"
|
|
202
|
+
ROOMMETA = "room.meta"
|
|
203
|
+
TAGS = "tags.update"
|
|
204
|
+
ROOMARCHIVE = "room.archive"
|
|
205
|
+
THREAD_CREATE = "thread.create"
|
|
206
|
+
THREAD_MESSAGE = "thread.message"
|
|
207
|
+
THREAD_CLOSE = "thread.close"
|
|
208
|
+
AGENT_CONNECT = "agent.connect"
|
|
209
|
+
AGENT_DISCONNECT = "agent.disconnect"
|
|
210
|
+
CONSOLE_OPEN = "console.open"
|
|
211
|
+
CONSOLE_CLOSE = "console.close"
|
|
212
|
+
SERVER_WAKE = "server.wake"
|
|
213
|
+
SERVER_SLEEP = "server.sleep"
|
|
214
|
+
SERVER_LINK = "server.link"
|
|
215
|
+
SERVER_UNLINK = "server.unlink"
|
|
216
|
+
ROOM_CREATE = "room.create"
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
@dataclass
|
|
220
|
+
class Event:
|
|
221
|
+
# `type` is widened to `EventType | str` so federation peers can deliver
|
|
222
|
+
# event types this version doesn't recognise without raising. Subscribers
|
|
223
|
+
# must tolerate unknown types (forward-compat).
|
|
224
|
+
type: EventType | str
|
|
225
|
+
channel: str | None
|
|
226
|
+
nick: str
|
|
227
|
+
data: dict[str, Any] = field(default_factory=dict)
|
|
228
|
+
timestamp: float = field(default_factory=time.time)
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
# Per-type string constants — parallel to `EventType` for callers that prefer
|
|
232
|
+
# bare strings (e.g. comparing JSON-decoded `type` field without enum-coercing).
|
|
233
|
+
EVENT_TYPE_MESSAGE = "message"
|
|
234
|
+
EVENT_TYPE_USER_JOIN = "user.join"
|
|
235
|
+
EVENT_TYPE_USER_PART = "user.part"
|
|
236
|
+
EVENT_TYPE_USER_QUIT = "user.quit"
|
|
237
|
+
EVENT_TYPE_TOPIC = "topic"
|
|
238
|
+
EVENT_TYPE_ROOM_META = "room.meta"
|
|
239
|
+
EVENT_TYPE_TAGS_UPDATE = "tags.update"
|
|
240
|
+
EVENT_TYPE_ROOM_ARCHIVE = "room.archive"
|
|
241
|
+
EVENT_TYPE_THREAD_CREATE = "thread.create"
|
|
242
|
+
EVENT_TYPE_THREAD_MESSAGE = "thread.message"
|
|
243
|
+
EVENT_TYPE_THREAD_CLOSE = "thread.close"
|
|
244
|
+
EVENT_TYPE_AGENT_CONNECT = "agent.connect"
|
|
245
|
+
EVENT_TYPE_AGENT_DISCONNECT = "agent.disconnect"
|
|
246
|
+
EVENT_TYPE_CONSOLE_OPEN = "console.open"
|
|
247
|
+
EVENT_TYPE_CONSOLE_CLOSE = "console.close"
|
|
248
|
+
EVENT_TYPE_SERVER_WAKE = "server.wake"
|
|
249
|
+
EVENT_TYPE_SERVER_SLEEP = "server.sleep"
|
|
250
|
+
EVENT_TYPE_SERVER_LINK = "server.link"
|
|
251
|
+
EVENT_TYPE_SERVER_UNLINK = "server.unlink"
|
|
252
|
+
EVENT_TYPE_ROOM_CREATE = "room.create"
|
|
253
|
+
|
|
254
|
+
# Bot extension verbs.
|
|
255
|
+
EVENTSUB = "EVENTSUB"
|
|
256
|
+
EVENTUNSUB = "EVENTUNSUB"
|
|
257
|
+
EVENT = "EVENT"
|
|
258
|
+
EVENTERR = "EVENTERR"
|
|
259
|
+
EVENTPUB = "EVENTPUB"
|
|
260
|
+
|
|
261
|
+
# Bot-CAP token. Vendored namespace per IRCv3 conventions, prevents collision
|
|
262
|
+
# with hypothetical bare-`bot` caps from non-agentirc IRC servers.
|
|
263
|
+
BOT_CAP = "agentirc.io/bot"
|
|
264
|
+
|
|
265
|
+
|
|
167
266
|
__all__ = [
|
|
168
267
|
# Numerics
|
|
169
268
|
"ERR_ALREADYREGISTRED",
|
|
@@ -256,4 +355,33 @@ __all__ = [
|
|
|
256
355
|
"STAGS",
|
|
257
356
|
"STHREAD",
|
|
258
357
|
"STOPIC",
|
|
358
|
+
# Bot extension API (9.5.0)
|
|
359
|
+
"BOT_CAP",
|
|
360
|
+
"EVENT",
|
|
361
|
+
"EVENTERR",
|
|
362
|
+
"EVENTPUB",
|
|
363
|
+
"EVENTSUB",
|
|
364
|
+
"EVENTUNSUB",
|
|
365
|
+
"Event",
|
|
366
|
+
"EventType",
|
|
367
|
+
"EVENT_TYPE_AGENT_CONNECT",
|
|
368
|
+
"EVENT_TYPE_AGENT_DISCONNECT",
|
|
369
|
+
"EVENT_TYPE_CONSOLE_CLOSE",
|
|
370
|
+
"EVENT_TYPE_CONSOLE_OPEN",
|
|
371
|
+
"EVENT_TYPE_MESSAGE",
|
|
372
|
+
"EVENT_TYPE_ROOM_ARCHIVE",
|
|
373
|
+
"EVENT_TYPE_ROOM_CREATE",
|
|
374
|
+
"EVENT_TYPE_ROOM_META",
|
|
375
|
+
"EVENT_TYPE_SERVER_LINK",
|
|
376
|
+
"EVENT_TYPE_SERVER_SLEEP",
|
|
377
|
+
"EVENT_TYPE_SERVER_UNLINK",
|
|
378
|
+
"EVENT_TYPE_SERVER_WAKE",
|
|
379
|
+
"EVENT_TYPE_TAGS_UPDATE",
|
|
380
|
+
"EVENT_TYPE_THREAD_CLOSE",
|
|
381
|
+
"EVENT_TYPE_THREAD_CREATE",
|
|
382
|
+
"EVENT_TYPE_THREAD_MESSAGE",
|
|
383
|
+
"EVENT_TYPE_TOPIC",
|
|
384
|
+
"EVENT_TYPE_USER_JOIN",
|
|
385
|
+
"EVENT_TYPE_USER_PART",
|
|
386
|
+
"EVENT_TYPE_USER_QUIT",
|
|
259
387
|
]
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
# Event and EventType moved to agentirc.protocol in 9.5.0a1 as part of the
|
|
6
|
+
# bot extension API public surface. This module keeps re-exporting them so
|
|
7
|
+
# internal call sites and any pre-9.5 vendored consumers keep working; the
|
|
8
|
+
# re-export is removed in 9.6.0 once Phase A2 confirms no consumer relies on
|
|
9
|
+
# this path.
|
|
10
|
+
from agentirc.protocol import Event, EventType
|
|
11
|
+
|
|
12
|
+
__all__ = ["Event", "EventType", "Skill"]
|
|
7
13
|
|
|
8
14
|
if TYPE_CHECKING:
|
|
9
15
|
from agentirc.client import Client
|
|
@@ -11,39 +17,6 @@ if TYPE_CHECKING:
|
|
|
11
17
|
from agentirc._internal.protocol.message import Message
|
|
12
18
|
|
|
13
19
|
|
|
14
|
-
class EventType(Enum):
|
|
15
|
-
MESSAGE = "message"
|
|
16
|
-
JOIN = "user.join"
|
|
17
|
-
PART = "user.part"
|
|
18
|
-
QUIT = "user.quit"
|
|
19
|
-
TOPIC = "topic"
|
|
20
|
-
ROOMMETA = "room.meta"
|
|
21
|
-
TAGS = "tags.update"
|
|
22
|
-
ROOMARCHIVE = "room.archive"
|
|
23
|
-
THREAD_CREATE = "thread.create"
|
|
24
|
-
THREAD_MESSAGE = "thread.message"
|
|
25
|
-
THREAD_CLOSE = "thread.close"
|
|
26
|
-
# Lifecycle + link events introduced by mesh-events feature.
|
|
27
|
-
AGENT_CONNECT = "agent.connect"
|
|
28
|
-
AGENT_DISCONNECT = "agent.disconnect"
|
|
29
|
-
CONSOLE_OPEN = "console.open"
|
|
30
|
-
CONSOLE_CLOSE = "console.close"
|
|
31
|
-
SERVER_WAKE = "server.wake"
|
|
32
|
-
SERVER_SLEEP = "server.sleep"
|
|
33
|
-
SERVER_LINK = "server.link"
|
|
34
|
-
SERVER_UNLINK = "server.unlink"
|
|
35
|
-
ROOM_CREATE = "room.create"
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
@dataclass
|
|
39
|
-
class Event:
|
|
40
|
-
type: EventType
|
|
41
|
-
channel: str | None
|
|
42
|
-
nick: str
|
|
43
|
-
data: dict[str, Any] = field(default_factory=dict)
|
|
44
|
-
timestamp: float = field(default_factory=time.time)
|
|
45
|
-
|
|
46
|
-
|
|
47
20
|
class Skill:
|
|
48
21
|
name: str = ""
|
|
49
22
|
commands: set[str] = set()
|
|
@@ -12,6 +12,33 @@ import only from these three modules.
|
|
|
12
12
|
| [`agentirc.cli`](#agentirccli) | `main()`, `dispatch(argv) -> int` | Public, semver-tracked |
|
|
13
13
|
| [`agentirc.protocol`](#agentircprotocol) | Verb constants, numeric reply codes, IRCv3/extension tag names | Public, semver-tracked |
|
|
14
14
|
|
|
15
|
+
> **Bot extension API — phased rollout:**
|
|
16
|
+
>
|
|
17
|
+
> - **9.5.0a1 (current alpha — declarations slice):** `agentirc.protocol`
|
|
18
|
+
> exports the `Event` dataclass, the `EventType` enum (now `StrEnum`),
|
|
19
|
+
> 20 per-type `EVENT_TYPE_*` string constants, the
|
|
20
|
+
> `EVENTSUB`/`EVENTUNSUB`/`EVENT`/`EVENTERR`/`EVENTPUB` verb constants,
|
|
21
|
+
> and the `BOT_CAP = "agentirc.io/bot"` capability identifier.
|
|
22
|
+
> `ServerConfig` gains the `event_subscription_queue_max: int = 1024`
|
|
23
|
+
> field. **The symbols are importable; the daemon does not yet handle
|
|
24
|
+
> the verbs and does not advertise `BOT_CAP`** — calling them is a
|
|
25
|
+
> no-op until the behavior slices land.
|
|
26
|
+
> - **9.5.0a2 (planned):** wire-format envelope refactor —
|
|
27
|
+
> `_build_event_payload`/`_encode_event_data` emit the 5-field envelope
|
|
28
|
+
> `{type, channel, nick, data, timestamp}`; federated `SEVENT` shifts
|
|
29
|
+
> to the new shape. Internal change; no new public symbols.
|
|
30
|
+
> - **9.5.0a3 (planned):** bot-CAP behavior, `EVENTSUB`/`EVENTUNSUB`
|
|
31
|
+
> handlers, the in-memory `SubscriptionRegistry`, and `EVENTPUB`
|
|
32
|
+
> handler. Daemon starts advertising `BOT_CAP` in `CAP LS` output.
|
|
33
|
+
> - **9.5.0 (final):** `webhook_port` no longer bound; `cli.md` /
|
|
34
|
+
> `deployment.md` updated; this block flips from "phased rollout" to
|
|
35
|
+
> "current," and the version-history table picks up a 9.5.0 row.
|
|
36
|
+
>
|
|
37
|
+
> Wire format and verb syntax are specified in
|
|
38
|
+
> [`docs/superpowers/specs/2026-05-01-bot-extension-api-design.md`](superpowers/specs/2026-05-01-bot-extension-api-design.md);
|
|
39
|
+
> a quick reference for bot authors is at [`docs/extension-api.md`](extension-api.md).
|
|
40
|
+
> Tracking issue: [agentculture/agentirc#15](https://github.com/agentculture/agentirc/issues/15).
|
|
41
|
+
|
|
15
42
|
## Semver contract
|
|
16
43
|
|
|
17
44
|
Following [SemVer 2.0](https://semver.org/):
|
|
@@ -179,6 +206,35 @@ Re-exported from `agentirc._internal.protocol.replies`. About 33 names:
|
|
|
179
206
|
Re-exported from `agentirc._internal.telemetry.context`:
|
|
180
207
|
`TRACEPARENT_TAG`, `TRACESTATE_TAG`, `EVENT_TAG_TYPE`, `EVENT_TAG_DATA`.
|
|
181
208
|
|
|
209
|
+
### Reserved for 9.5.0: bot extension surface
|
|
210
|
+
|
|
211
|
+
These additions are **specified but not yet implemented**. They will land
|
|
212
|
+
together as a single minor bump in 9.5.0 — see the design spec at
|
|
213
|
+
[`docs/superpowers/specs/2026-05-01-bot-extension-api-design.md`](superpowers/specs/2026-05-01-bot-extension-api-design.md)
|
|
214
|
+
for rationale, federation behavior, and acceptance criteria, and
|
|
215
|
+
[`docs/extension-api.md`](extension-api.md) for the bot-author quick
|
|
216
|
+
reference.
|
|
217
|
+
|
|
218
|
+
- **Event verbs:** `EVENTSUB`, `EVENTUNSUB`, `EVENT`, `EVENTERR`, `EVENTPUB`. Subscribers stream events with filter syntax (`type=`/`channel=`/`nick=` AND-ed globs); `EVENTPUB` lets a bot emit its own typed events back into the stream (server-side validation of `type` against `EVENT_TYPE_RE`; `nick` and `timestamp` derived server-side, not trusted from the client).
|
|
219
|
+
- **Bot capability:** `BOT_CAP = "agentirc.io/bot"`. When negotiated via
|
|
220
|
+
the existing CAP REQ/ACK flow, the connection is treated as a bot:
|
|
221
|
+
silent JOIN/PART/QUIT broadcasts, no auto-op on channel creation,
|
|
222
|
+
`+` prefix in NAMES output, `B` flag in WHO output, authorized to
|
|
223
|
+
issue `EVENTSUB`.
|
|
224
|
+
- **Event dataclass and enum:** `Event` and `EventType` (currently
|
|
225
|
+
internal in `agentirc.skill`). Promoted to public for Python consumers.
|
|
226
|
+
Wire format — not the Python class names — is the contract; non-Python
|
|
227
|
+
bots pin against the JSON shape documented in `extension-api.md`.
|
|
228
|
+
- **Per-type string constants:** `EVENT_TYPE_MESSAGE`,
|
|
229
|
+
`EVENT_TYPE_USER_JOIN`, …, one per type-string in the canonical
|
|
230
|
+
vocabulary. Convenience for callers that prefer non-enum-aware
|
|
231
|
+
constants.
|
|
232
|
+
|
|
233
|
+
The `ServerConfig` additions (one new field
|
|
234
|
+
`event_subscription_queue_max: int = 1024`) and the `webhook_port`
|
|
235
|
+
binding-removal are described under
|
|
236
|
+
[`agentirc.config`](#agentircconfig) once 9.5.0 lands.
|
|
237
|
+
|
|
182
238
|
### Wire-format quirks (preserved verbatim)
|
|
183
239
|
|
|
184
240
|
Four known wire-format issues are **preserved** rather than fixed,
|