agentirc-cli 8.0.0__tar.gz → 8.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/CHANGELOG.md +24 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/PKG-INFO +6 -1
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/_config.culture.yml +3 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/_data/sites.yml +1 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/_includes/head_custom.html +1 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/client.py +200 -74
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/config.py +15 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/ircd.py +49 -20
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/__init__.py +3 -2
- agentirc_cli-8.2.0/culture/cli/_passthrough.py +116 -0
- agentirc_cli-8.2.0/culture/cli/afi.py +71 -0
- agentirc_cli-8.2.0/culture/cli/devex.py +71 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/config.py +10 -0
- agentirc_cli-8.2.0/culture/protocol/extensions/tracing.md +31 -0
- agentirc_cli-8.2.0/culture/telemetry/__init__.py +22 -0
- agentirc_cli-8.2.0/culture/telemetry/context.py +84 -0
- agentirc_cli-8.2.0/culture/telemetry/tracing.py +114 -0
- agentirc_cli-8.2.0/docs/agentirc/otelcol-template.yaml +25 -0
- agentirc_cli-8.2.0/docs/agentirc/telemetry.md +81 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/features.md +1 -1
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/vision.md +8 -8
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/what-is-culture.md +5 -4
- agentirc_cli-8.2.0/docs/reference/architecture/index.md +27 -0
- agentirc_cli-8.2.0/docs/reference/architecture/subsites.md +111 -0
- agentirc_cli-8.2.0/docs/reference/cli/afi.md +95 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/cli/devex.md +5 -6
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/cli/index.md +10 -6
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/server/config.md +26 -0
- agentirc_cli-8.2.0/docs/superpowers/plans/2026-04-24-otel-foundation.md +2159 -0
- agentirc_cli-8.2.0/docs/superpowers/specs/2026-04-24-otel-observability-design.md +334 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/pyproject.toml +6 -1
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/sitemap.html +1 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/conftest.py +26 -0
- agentirc_cli-8.2.0/tests/telemetry/__init__.py +0 -0
- agentirc_cli-8.2.0/tests/telemetry/_fakes.py +26 -0
- agentirc_cli-8.2.0/tests/telemetry/test_config.py +26 -0
- agentirc_cli-8.2.0/tests/telemetry/test_config_load.py +36 -0
- agentirc_cli-8.2.0/tests/telemetry/test_context.py +105 -0
- agentirc_cli-8.2.0/tests/telemetry/test_dispatch_span.py +45 -0
- agentirc_cli-8.2.0/tests/telemetry/test_emit_event_span.py +42 -0
- agentirc_cli-8.2.0/tests/telemetry/test_outbound_inject.py +70 -0
- agentirc_cli-8.2.0/tests/telemetry/test_parse_error.py +33 -0
- agentirc_cli-8.2.0/tests/telemetry/test_privmsg_span.py +45 -0
- agentirc_cli-8.2.0/tests/telemetry/test_server_init.py +29 -0
- agentirc_cli-8.2.0/tests/telemetry/test_tracing.py +49 -0
- agentirc_cli-8.2.0/tests/test_cli_afi.py +111 -0
- agentirc_cli-8.2.0/tests/test_cli_passthrough.py +146 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/uv.lock +196 -1
- agentirc_cli-8.0.0/culture/cli/devex.py +0 -111
- agentirc_cli-8.0.0/docs/reference/architecture/index.md +0 -13
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.claude/agents/doc-test-alignment.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.flake8 +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.github/workflows/docs-check.yml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.gitignore +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.pr_agent.toml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/.pylintrc +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/CLAUDE.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/Gemfile +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/Gemfile.lock +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/LICENSE +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/README.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/SECURITY.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/_config.base.yml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/_sass/color_schemes/dark-terminal.scss +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/assets/images/IMG_3183.png +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/assets/images/apple-touch-icon.png +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/assets/images/favicon-16x16.png +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/assets/images/favicon-32x32.png +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/assets/images/favicon.ico +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/assets/images/og-agentirc.png +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/assets/images/og-culture.png +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/__main__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/CLAUDE.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/__main__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/channel.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/docs/agentirc-architecture.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/docs/agentirc-features.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/docs/agentirc-skill.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/docs/agentirc.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/events.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/history_store.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/remote_client.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/room_store.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/rooms_util.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/server_link.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/skill.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/skills/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/skills/history.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/skills/icon.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/skills/rooms.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/skills/threads.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/agentirc/thread_store.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/aio.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/bot.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/bot_manager.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/filter_dsl.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/system/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/system/welcome/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/system/welcome/bot.yaml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/system/welcome/handler.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/agent.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/bot.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/channel.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/introspect.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/mesh.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/server.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/shared/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/shared/constants.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/shared/display.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/shared/formatting.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/shared/ipc.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/shared/mesh.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/shared/process.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/cli/skills.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/agent_runner.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/culture.yaml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/daemon.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/irc_transport.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/culture.yaml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/daemon.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/irc_transport.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/agent_runner.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/culture.yaml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/daemon.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/irc_transport.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/agent_runner.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/culture.yaml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/daemon.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/irc_transport.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/console/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/console/app.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/console/client.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/console/commands.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/console/status.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/constants.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/credentials.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/formatting.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/learn_prompt.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/mesh_config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/observer.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/overview/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/overview/collector.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/overview/model.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/overview/web/style.css +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/persistence.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/pidfile.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/commands.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/extensions/events.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/message.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/protocol/replies.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/README.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/agentirc/architecture-overview.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/agentirc/bots.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/agentirc/events.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/agentirc/index.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/agentirc/why-agentirc.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/agent-lifecycle.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/choose-a-harness.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/index.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/mental-model.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/operate.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/patterns.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/quickstart.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/reflective-development.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/culture/vision-patterns-index.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/architecture/layers.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/architecture/threads.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/cli/commands.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/console.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/harnesses/acp.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/harnesses/claude.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/harnesses/codex.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/harnesses/copilot.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/harnesses/index.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/index.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/server/architecture.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/server/deployment.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/server/index.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/reference/server/security.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/resources/positioning.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/concepts/federation.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/concepts/harnesses.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/concepts/humans-and-agents.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/concepts/index.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/concepts/persistence.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/concepts/rooms.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/demos/magic-demo.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/guides/first-session.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/guides/index.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/guides/join-as-human.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/guides/local-setup.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/guides/multi-machine.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/shared/use-cases-index.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-04-09-decentralized-agent-config.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-04-12-console-enhancements.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-04-15-mesh-events.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-04-18-culture-dev-positioning.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/plans/2026-04-22-agex-integration.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-07-reflective-development-reframe-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-08-reflective-development-deepening-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-09-decentralized-agent-config-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-12-console-enhancements-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-15-mesh-events-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-17-sites-repositioning-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-18-culture-dev-positioning-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/docs/superpowers/specs/2026-04-22-agex-integration-design.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/favicon.ico +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/packages/agent-harness/culture.yaml +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/packages/agent-harness/daemon.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/packages/agent-harness/irc_transport.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/robots.txt +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/sitemap-agentirc.html +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/sitemap-main.html +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/sonar-project.properties +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/__init__.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_archive.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_bot.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_bot_config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_bot_config_fires_event_toplevel.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_channel.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_channel_cli.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_cli_devex.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_cli_introspect.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_connection.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_console_chat_markdown.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_console_client.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_console_commands.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_console_connection.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_console_fixes_224_227.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_console_icons.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_console_integration.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_console_status.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_credentials.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_culture_config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_daemon.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_discovery.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_display.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_events_basic.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_events_bot_chain.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_events_bot_trigger.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_events_cap_fallback.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_events_catalog.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_events_federation.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_events_history.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_events_lifecycle.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_events_reserved_nick.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_federation.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_filter_dsl.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_history.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_http_listener.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_ipc.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_irc_transport_tags.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_learn_prompt.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_manifest_config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_mention_target_cleanup.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_mention_warning.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_mentions.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_mesh_readiness.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_message.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_message_tags.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_messaging.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_migrate_cli.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_modes.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_overview_model.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_overview_web.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_persistence.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_persistence_timeout.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_pidfile.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_register_cli.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_rooms.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_skill_client.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_skill_docs.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_skills.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_socket_server.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_supervisor.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_template_engine.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_threads.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_webhook.py +0 -0
- {agentirc_cli-8.0.0 → agentirc_cli-8.2.0}/tests/test_welcome_bot.py +0 -0
|
@@ -4,6 +4,30 @@ 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
|
+
## [8.2.0] - 2026-04-24
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- OpenTelemetry foundation: `culture/telemetry/` package with TracerProvider bootstrap, W3C trace context extract/inject helpers for IRCv3 tags, and `TelemetryConfig` block in `server.yaml`.
|
|
12
|
+
- Protocol extension: `culture.dev/traceparent` and `culture.dev/tracestate` IRCv3 tags (`culture/protocol/extensions/tracing.md`).
|
|
13
|
+
- Server-side tracing: `IRCd.emit_event`, `Client._dispatch`, `Client._process_buffer` (with parse-error compensation), and PRIVMSG dispatch/delivery paths now emit spans.
|
|
14
|
+
- Outbound traceparent injection on `Client.send` and `Client.send_raw` when a span is active.
|
|
15
|
+
- Operator docs at `docs/agentirc/telemetry.md` and starter collector config at `docs/agentirc/otelcol-template.yaml`; `docs/reference/server/config.md` documents the new `telemetry` block.
|
|
16
|
+
- Dependencies: `opentelemetry-api`, `opentelemetry-sdk`, `opentelemetry-exporter-otlp-proto-grpc`, `opentelemetry-semantic-conventions`.
|
|
17
|
+
|
|
18
|
+
## [8.1.0] - 2026-04-23
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- `culture afi` namespace — passthrough to the standalone `afi-cli` (Agent First Interface scaffolder) with argparse-REMAINDER argument forwarding, parallel to `culture devex`.
|
|
23
|
+
- Universal verbs register the `afi` topic; `culture explain afi` / `culture overview afi` / `culture learn afi` all route through `afi-cli` 0.3+ and `culture explain` no longer marks `culture afi` as coming-soon.
|
|
24
|
+
- `afi-cli>=0.3,<1.0` as a library dependency (0.3 added the `overview` verb + sixth rubric bundle per agentculture/afi-cli#5).
|
|
25
|
+
- `culture/cli/_passthrough.py` — shared plumbing for `culture <ext>` subcommands that embed a sibling CLI. Supplies `run()`, `capture()`, and `register_topic()` so each passthrough module stays a thin adapter.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- `culture/cli/devex.py` refactored onto the new shared passthrough helper. Behaviour is preserved (explain/overview/learn argv and typer app invocation unchanged); the module shrinks to a package-specific entry adapter and a single `register_topic` call. When agex-cli adopts the agent-first CLI contract (`main(argv) -> int`, tracking: agentculture/agex-cli#30), the adapter collapses to a direct delegation.
|
|
30
|
+
|
|
7
31
|
## [8.0.0] - 2026-04-22
|
|
8
32
|
|
|
9
33
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentirc-cli
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.2.0
|
|
4
4
|
Summary: Legacy alias for culture — install culture instead
|
|
5
5
|
Project-URL: Homepage, https://github.com/OriNachum/culture
|
|
6
6
|
Author: Ori Nachum
|
|
@@ -12,11 +12,16 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
12
12
|
Classifier: Programming Language :: Python :: 3.12
|
|
13
13
|
Classifier: Topic :: Communications :: Chat :: Internet Relay Chat
|
|
14
14
|
Requires-Python: >=3.12
|
|
15
|
+
Requires-Dist: afi-cli<1.0,>=0.3
|
|
15
16
|
Requires-Dist: agex-cli<1.0,>=0.13
|
|
16
17
|
Requires-Dist: aiohttp>=3.9
|
|
17
18
|
Requires-Dist: anthropic>=0.40
|
|
18
19
|
Requires-Dist: claude-agent-sdk>=0.1
|
|
19
20
|
Requires-Dist: mistune>=3.0
|
|
21
|
+
Requires-Dist: opentelemetry-api>=1.25
|
|
22
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.25
|
|
23
|
+
Requires-Dist: opentelemetry-sdk>=1.25
|
|
24
|
+
Requires-Dist: opentelemetry-semantic-conventions>=0.46b0
|
|
20
25
|
Requires-Dist: pyyaml>=6.0
|
|
21
26
|
Requires-Dist: textual>=1.0
|
|
22
27
|
Provides-Extra: copilot
|
|
@@ -36,6 +36,8 @@ aux_links:
|
|
|
36
36
|
- "/agentirc/"
|
|
37
37
|
"Agent Experience":
|
|
38
38
|
- "https://culture.dev/agex/"
|
|
39
|
+
"Agent First Interop":
|
|
40
|
+
- "https://culture.dev/afi/"
|
|
39
41
|
"Citation CLI":
|
|
40
42
|
- "/citation-cli/"
|
|
41
43
|
"GitHub":
|
|
@@ -49,5 +51,6 @@ footer_content: >-
|
|
|
49
51
|
Inspectable CLI via <a href="/reference/cli/devex/">culture devex</a>
|
|
50
52
|
(explain / overview / learn at every level).
|
|
51
53
|
Agent Experience via <a href="https://culture.dev/agex/">agex-cli</a>.
|
|
54
|
+
Agent First Interop via <a href="https://culture.dev/afi/">afi-cli</a>.
|
|
52
55
|
Code distribution via <a href="/citation-cli/">Citation CLI</a>.
|
|
53
56
|
Source on <a href="https://github.com/agentculture/culture">GitHub</a>.
|
|
@@ -4,4 +4,5 @@
|
|
|
4
4
|
<link rel="icon" type="image/png" sizes="16x16" href="{{ '/assets/images/favicon-16x16.png' | relative_url }}">
|
|
5
5
|
<link rel="apple-touch-icon" sizes="180x180" href="{{ '/assets/images/apple-touch-icon.png' | relative_url }}">
|
|
6
6
|
<link rel="related" href="{{ site.data.sites.agex }}" title="Agent Experience">
|
|
7
|
+
<link rel="related" href="{{ site.data.sites.afi }}" title="Agent First Interop">
|
|
7
8
|
<link rel="related" href="{{ site.data.sites.citation_cli }}" title="Citation CLI">
|
|
@@ -6,12 +6,59 @@ import logging
|
|
|
6
6
|
import re
|
|
7
7
|
from typing import TYPE_CHECKING
|
|
8
8
|
|
|
9
|
+
from opentelemetry import trace as _otel_trace
|
|
10
|
+
from opentelemetry.trace import NonRecordingSpan, SpanContext, TraceFlags
|
|
11
|
+
from opentelemetry.trace.propagation import set_span_in_context
|
|
12
|
+
|
|
9
13
|
from culture.agentirc.channel import Channel
|
|
10
14
|
from culture.agentirc.skill import Event, EventType
|
|
11
15
|
from culture.aio import maybe_await
|
|
12
16
|
from culture.constants import SYSTEM_USER_PREFIX
|
|
13
17
|
from culture.protocol import replies
|
|
14
18
|
from culture.protocol.message import Message
|
|
19
|
+
from culture.telemetry.context import TRACEPARENT_TAG as _TP_TAG_NAME
|
|
20
|
+
from culture.telemetry.context import (
|
|
21
|
+
extract_traceparent_from_tags,
|
|
22
|
+
)
|
|
23
|
+
from culture.telemetry.context import inject_traceparent as _inject_traceparent
|
|
24
|
+
|
|
25
|
+
# OTEL instrumentation name (must match `_CULTURE_TRACER_NAME` in
|
|
26
|
+
# culture/telemetry/tracing.py so trace consumers see one consistent value).
|
|
27
|
+
_TRACER_NAME = "culture.agentirc"
|
|
28
|
+
# Span attribute keys for PRIVMSG body capture, defined once so a future
|
|
29
|
+
# rename / sanitization layer has one edit point.
|
|
30
|
+
_ATTR_BODY = "irc.message.body"
|
|
31
|
+
_ATTR_SIZE = "irc.message.size"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _context_from_traceparent(tp: str):
|
|
35
|
+
"""Build an OTEL context whose current span is a NonRecordingSpan
|
|
36
|
+
synthesized from a W3C traceparent string. The `_dispatch` span we
|
|
37
|
+
start next will be a child of this context."""
|
|
38
|
+
# Format: 00-<trace-id>-<parent-id>-<flags>
|
|
39
|
+
_, trace_hex, parent_hex, flags_hex = tp.split("-")
|
|
40
|
+
span_ctx = SpanContext(
|
|
41
|
+
trace_id=int(trace_hex, 16),
|
|
42
|
+
span_id=int(parent_hex, 16),
|
|
43
|
+
is_remote=True,
|
|
44
|
+
trace_flags=TraceFlags(int(flags_hex, 16)),
|
|
45
|
+
)
|
|
46
|
+
return set_span_in_context(NonRecordingSpan(span_ctx))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _current_traceparent() -> str | None:
|
|
50
|
+
"""Return the W3C traceparent for the currently-active span, or None
|
|
51
|
+
if no span is recording (no-op tracer / sampler dropped).
|
|
52
|
+
"""
|
|
53
|
+
span = _otel_trace.get_current_span()
|
|
54
|
+
ctx = span.get_span_context()
|
|
55
|
+
if not ctx.is_valid:
|
|
56
|
+
return None
|
|
57
|
+
return (
|
|
58
|
+
f"00-{format(ctx.trace_id, '032x')}-{format(ctx.span_id, '016x')}"
|
|
59
|
+
f"-{format(int(ctx.trace_flags), '02x')}"
|
|
60
|
+
)
|
|
61
|
+
|
|
15
62
|
|
|
16
63
|
if TYPE_CHECKING:
|
|
17
64
|
from culture.agentirc.ircd import IRCd
|
|
@@ -45,6 +92,14 @@ class Client:
|
|
|
45
92
|
return f"{self.nick}!{self.user}@{self.host}"
|
|
46
93
|
|
|
47
94
|
async def send(self, message: Message) -> None:
|
|
95
|
+
# Only inject trace context for clients that negotiated IRCv3
|
|
96
|
+
# message-tags; otherwise older clients would see an unexpected @-tag
|
|
97
|
+
# block and `send_tagged`'s tag-stripping for non-capable clients
|
|
98
|
+
# would be undone here.
|
|
99
|
+
if "message-tags" in self.caps:
|
|
100
|
+
tp = _current_traceparent()
|
|
101
|
+
if tp is not None:
|
|
102
|
+
_inject_traceparent(message, traceparent=tp, tracestate=None)
|
|
48
103
|
try:
|
|
49
104
|
self.writer.write(message.format().encode("utf-8"))
|
|
50
105
|
await self.writer.drain()
|
|
@@ -55,7 +110,15 @@ class Client:
|
|
|
55
110
|
"""Write a pre-formatted IRC line to the client socket.
|
|
56
111
|
|
|
57
112
|
Appends CRLF internally, matching ServerLink.send_raw convention.
|
|
113
|
+
Injects `culture.dev/traceparent` as an IRCv3 tag when a span is active
|
|
114
|
+
AND the client negotiated the `message-tags` capability.
|
|
58
115
|
"""
|
|
116
|
+
if "message-tags" in self.caps:
|
|
117
|
+
tp = _current_traceparent()
|
|
118
|
+
if tp is not None:
|
|
119
|
+
# send_raw takes a pre-formatted line without an existing tag
|
|
120
|
+
# block; prefix a fresh @tag.
|
|
121
|
+
line = f"@{_TP_TAG_NAME}={tp} {line}"
|
|
59
122
|
try:
|
|
60
123
|
self.writer.write(f"{line}\r\n".encode("utf-8"))
|
|
61
124
|
await self.writer.drain()
|
|
@@ -84,13 +147,28 @@ class Client:
|
|
|
84
147
|
|
|
85
148
|
async def _process_buffer(self, buffer: str) -> str:
|
|
86
149
|
"""Parse and dispatch all complete lines from buffer, return remainder."""
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
150
|
+
# Per-call get_tracer: test fixture swaps provider between tests.
|
|
151
|
+
with _otel_trace.get_tracer(_TRACER_NAME).start_as_current_span(
|
|
152
|
+
"irc.client.process_buffer"
|
|
153
|
+
) as span:
|
|
154
|
+
while "\n" in buffer:
|
|
155
|
+
line, buffer = buffer.split("\n", 1)
|
|
156
|
+
if not line.strip():
|
|
157
|
+
continue
|
|
158
|
+
try:
|
|
159
|
+
msg = Message.parse(line)
|
|
160
|
+
except Exception as exc: # noqa: BLE001 -- widen for any parser failure
|
|
161
|
+
span.add_event(
|
|
162
|
+
"irc.parse_error",
|
|
163
|
+
attributes={
|
|
164
|
+
"line_preview": line[:64],
|
|
165
|
+
"error": type(exc).__name__,
|
|
166
|
+
},
|
|
167
|
+
)
|
|
168
|
+
continue
|
|
91
169
|
if msg.command:
|
|
92
170
|
await self._dispatch(msg)
|
|
93
|
-
|
|
171
|
+
return buffer
|
|
94
172
|
|
|
95
173
|
async def handle(self, initial_msg: str | None = None) -> None:
|
|
96
174
|
buffer = ""
|
|
@@ -110,20 +188,41 @@ class Client:
|
|
|
110
188
|
buffer = await self._process_buffer(buffer)
|
|
111
189
|
|
|
112
190
|
async def _dispatch(self, msg: Message) -> None:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
191
|
+
extract = extract_traceparent_from_tags(msg, peer=None)
|
|
192
|
+
parent_ctx = None
|
|
193
|
+
if extract.status == "valid":
|
|
194
|
+
parent_ctx = _context_from_traceparent(extract.traceparent)
|
|
195
|
+
|
|
196
|
+
attrs = {
|
|
197
|
+
"irc.command": msg.command,
|
|
198
|
+
"irc.prefix_nick": (msg.prefix.split("!")[0] if msg.prefix else ""),
|
|
199
|
+
"culture.trace.origin": "local" if extract.status == "missing" else "remote",
|
|
200
|
+
}
|
|
201
|
+
if extract.status in ("malformed", "too_long"):
|
|
202
|
+
attrs["culture.trace.dropped_reason"] = extract.status
|
|
203
|
+
|
|
204
|
+
# Per-call get_tracer: test fixture swaps provider between tests.
|
|
205
|
+
with _otel_trace.get_tracer(_TRACER_NAME).start_as_current_span(
|
|
206
|
+
f"irc.command.{msg.command}",
|
|
207
|
+
context=parent_ctx,
|
|
208
|
+
attributes=attrs,
|
|
209
|
+
):
|
|
210
|
+
handler = getattr(self, f"_handle_{msg.command.lower()}", None)
|
|
211
|
+
if handler:
|
|
212
|
+
await maybe_await(handler(msg))
|
|
125
213
|
else:
|
|
126
|
-
|
|
214
|
+
skill = self.server.get_skill_for_command(msg.command)
|
|
215
|
+
if skill and self._registered:
|
|
216
|
+
try:
|
|
217
|
+
await skill.on_command(self, msg)
|
|
218
|
+
except Exception:
|
|
219
|
+
logging.getLogger(__name__).exception(
|
|
220
|
+
"Skill %s failed on command %s", skill.name, msg.command
|
|
221
|
+
)
|
|
222
|
+
else:
|
|
223
|
+
await self.send_numeric(
|
|
224
|
+
replies.ERR_UNKNOWNCOMMAND, msg.command, "Unknown command"
|
|
225
|
+
)
|
|
127
226
|
|
|
128
227
|
async def _handle_ping(self, msg: Message) -> None:
|
|
129
228
|
token = msg.params[0] if msg.params else ""
|
|
@@ -615,46 +714,64 @@ class Client:
|
|
|
615
714
|
await self.send_numeric(replies.RPL_UMODEIS, mode_str)
|
|
616
715
|
|
|
617
716
|
async def _send_to_channel(self, channel, target, relay, text, is_notice):
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
717
|
+
with _otel_trace.get_tracer(_TRACER_NAME).start_as_current_span(
|
|
718
|
+
"irc.privmsg.deliver.channel",
|
|
719
|
+
attributes={
|
|
720
|
+
"irc.channel": target,
|
|
721
|
+
_ATTR_BODY: text,
|
|
722
|
+
_ATTR_SIZE: len(text),
|
|
723
|
+
"irc.notice": is_notice,
|
|
724
|
+
},
|
|
725
|
+
):
|
|
726
|
+
for member in list(channel.members):
|
|
727
|
+
if member is not self:
|
|
728
|
+
await member.send(relay)
|
|
729
|
+
event_data = {"text": text}
|
|
730
|
+
if is_notice:
|
|
731
|
+
event_data["notice"] = True
|
|
732
|
+
await self.server.emit_event(
|
|
733
|
+
Event(
|
|
734
|
+
type=EventType.MESSAGE,
|
|
735
|
+
channel=target,
|
|
736
|
+
nick=self.nick,
|
|
737
|
+
data=event_data,
|
|
738
|
+
)
|
|
630
739
|
)
|
|
631
|
-
)
|
|
632
740
|
|
|
633
741
|
async def _send_to_client(self, target, relay, text, is_notice):
|
|
634
742
|
from culture.agentirc.remote_client import RemoteClient
|
|
635
743
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
744
|
+
with _otel_trace.get_tracer(_TRACER_NAME).start_as_current_span(
|
|
745
|
+
"irc.privmsg.deliver.dm",
|
|
746
|
+
attributes={
|
|
747
|
+
"irc.target.nick": target,
|
|
748
|
+
_ATTR_BODY: text,
|
|
749
|
+
_ATTR_SIZE: len(text),
|
|
750
|
+
"irc.notice": is_notice,
|
|
751
|
+
},
|
|
752
|
+
):
|
|
753
|
+
recipient = self.server.get_client(target)
|
|
754
|
+
if not recipient:
|
|
755
|
+
return False
|
|
756
|
+
if isinstance(recipient, RemoteClient):
|
|
757
|
+
s2s_cmd = "SNOTICE" if is_notice else "SMSG"
|
|
758
|
+
await recipient.link.send_raw(
|
|
759
|
+
f":{self.server.config.name} {s2s_cmd} {target} {self.nick} :{text}"
|
|
760
|
+
)
|
|
761
|
+
else:
|
|
762
|
+
await recipient.send(relay)
|
|
763
|
+
event_data = {"text": text, "target": target}
|
|
764
|
+
if is_notice:
|
|
765
|
+
event_data["notice"] = True
|
|
766
|
+
await self.server.emit_event(
|
|
767
|
+
Event(
|
|
768
|
+
type=EventType.MESSAGE,
|
|
769
|
+
channel=None,
|
|
770
|
+
nick=self.nick,
|
|
771
|
+
data=event_data,
|
|
772
|
+
)
|
|
655
773
|
)
|
|
656
|
-
|
|
657
|
-
return True
|
|
774
|
+
return True
|
|
658
775
|
|
|
659
776
|
async def _handle_privmsg(self, msg: Message) -> None:
|
|
660
777
|
if len(msg.params) < 2:
|
|
@@ -665,28 +782,37 @@ class Client:
|
|
|
665
782
|
|
|
666
783
|
target = msg.params[0]
|
|
667
784
|
text = msg.params[1]
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
)
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
785
|
+
# Per-call get_tracer: test fixture swaps provider between tests.
|
|
786
|
+
with _otel_trace.get_tracer(_TRACER_NAME).start_as_current_span(
|
|
787
|
+
"irc.privmsg.dispatch",
|
|
788
|
+
attributes={
|
|
789
|
+
"irc.target": target,
|
|
790
|
+
_ATTR_BODY: text,
|
|
791
|
+
_ATTR_SIZE: len(text),
|
|
792
|
+
},
|
|
793
|
+
):
|
|
794
|
+
relay = Message(prefix=self.prefix, command="PRIVMSG", params=[target, text])
|
|
795
|
+
|
|
796
|
+
if target.startswith("#"):
|
|
797
|
+
channel = self.server.channels.get(target)
|
|
798
|
+
if not channel:
|
|
799
|
+
await self.send_numeric(
|
|
800
|
+
replies.ERR_NOSUCHCHANNEL, target, replies.MSG_NOSUCHCHANNEL
|
|
801
|
+
)
|
|
802
|
+
return
|
|
803
|
+
if self not in channel.members:
|
|
804
|
+
await self.send_numeric(
|
|
805
|
+
replies.ERR_CANNOTSENDTOCHAN, target, "Cannot send to channel"
|
|
806
|
+
)
|
|
807
|
+
return
|
|
808
|
+
await self._send_to_channel(channel, target, relay, text, False)
|
|
809
|
+
await self._notify_mentions(target, text)
|
|
810
|
+
else:
|
|
811
|
+
found = await self._send_to_client(target, relay, text, False)
|
|
812
|
+
if not found:
|
|
813
|
+
await self.send_numeric(replies.ERR_NOSUCHNICK, target, replies.MSG_NOSUCHNICK)
|
|
814
|
+
return
|
|
815
|
+
await self._notify_mentions(None, text)
|
|
690
816
|
|
|
691
817
|
async def _notify_mentions(self, channel_name: str | None, text: str) -> None:
|
|
692
818
|
from culture.agentirc.remote_client import RemoteClient
|
|
@@ -12,6 +12,20 @@ class LinkConfig:
|
|
|
12
12
|
trust: str = "full" # "full" or "restricted"
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
@dataclass
|
|
16
|
+
class TelemetryConfig:
|
|
17
|
+
"""OpenTelemetry settings. Mirrors server.yaml `telemetry:` block."""
|
|
18
|
+
|
|
19
|
+
enabled: bool = False
|
|
20
|
+
service_name: str = "culture.agentirc"
|
|
21
|
+
otlp_endpoint: str = "http://localhost:4317"
|
|
22
|
+
otlp_protocol: str = "grpc" # grpc | http/protobuf (only grpc supported initially)
|
|
23
|
+
otlp_timeout_ms: int = 5000
|
|
24
|
+
otlp_compression: str = "gzip" # gzip | none
|
|
25
|
+
traces_enabled: bool = True
|
|
26
|
+
traces_sampler: str = "parentbased_always_on"
|
|
27
|
+
|
|
28
|
+
|
|
15
29
|
@dataclass
|
|
16
30
|
class ServerConfig:
|
|
17
31
|
"""Configuration for a culture server instance."""
|
|
@@ -23,3 +37,4 @@ class ServerConfig:
|
|
|
23
37
|
data_dir: str = ""
|
|
24
38
|
links: list[LinkConfig] = field(default_factory=list)
|
|
25
39
|
system_bots: dict = field(default_factory=dict)
|
|
40
|
+
telemetry: TelemetryConfig = field(default_factory=TelemetryConfig)
|
|
@@ -8,6 +8,8 @@ import logging
|
|
|
8
8
|
from collections import deque
|
|
9
9
|
from typing import TYPE_CHECKING
|
|
10
10
|
|
|
11
|
+
from opentelemetry import trace as _otel_trace
|
|
12
|
+
|
|
11
13
|
from culture.agentirc.channel import Channel
|
|
12
14
|
from culture.agentirc.config import ServerConfig
|
|
13
15
|
from culture.agentirc.events import NO_SURFACE_EVENT_TYPES, render_event
|
|
@@ -33,7 +35,10 @@ class IRCd:
|
|
|
33
35
|
"""The culture IRC server."""
|
|
34
36
|
|
|
35
37
|
def __init__(self, config: ServerConfig):
|
|
38
|
+
from culture.telemetry import init_telemetry
|
|
39
|
+
|
|
36
40
|
self.config = config
|
|
41
|
+
self.tracer = init_telemetry(config)
|
|
37
42
|
self.clients: dict[str, Client | VirtualClient] = {} # nick -> Client
|
|
38
43
|
self.channels: dict[str, Channel] = {} # name -> Channel
|
|
39
44
|
self.skills: list[Skill] = []
|
|
@@ -166,36 +171,60 @@ class IRCd:
|
|
|
166
171
|
self._seq += 1
|
|
167
172
|
return self._seq
|
|
168
173
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
174
|
+
@staticmethod
|
|
175
|
+
def _build_event_span_attrs(event: Event, origin_tag: str | None) -> dict[str, str]:
|
|
176
|
+
# event.type may be an EventType enum OR a plain string — federated
|
|
177
|
+
# events forward unknown types verbatim (see _parse_event_type in
|
|
178
|
+
# server_link.py).
|
|
179
|
+
event_type_str = event.type.value if hasattr(event.type, "value") else str(event.type)
|
|
180
|
+
attrs: dict[str, str] = {
|
|
181
|
+
"event.type": event_type_str,
|
|
182
|
+
"event.origin": "federated" if origin_tag else "local",
|
|
183
|
+
}
|
|
184
|
+
if event.channel:
|
|
185
|
+
attrs["event.channel"] = event.channel
|
|
186
|
+
if origin_tag:
|
|
187
|
+
attrs["culture.federation.peer"] = origin_tag
|
|
188
|
+
return attrs
|
|
173
189
|
|
|
174
|
-
|
|
190
|
+
async def _run_skill_hooks(self, event: Event) -> None:
|
|
175
191
|
for skill in self.skills:
|
|
176
192
|
try:
|
|
177
193
|
await skill.on_event(event)
|
|
178
194
|
except Exception:
|
|
179
195
|
logger.exception("Skill %s failed on event %s", skill.name, event.type)
|
|
180
196
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if not event.data.get("_origin"):
|
|
184
|
-
for peer_name, link in list(self.links.items()):
|
|
185
|
-
try:
|
|
186
|
-
await link.relay_event(event)
|
|
187
|
-
except Exception:
|
|
188
|
-
logger.exception("Failed to relay event to %s", peer_name)
|
|
189
|
-
|
|
190
|
-
# 4) Dispatch to event-triggered bots.
|
|
191
|
-
if self.bot_manager is not None:
|
|
197
|
+
async def _relay_to_peers(self, event: Event) -> None:
|
|
198
|
+
for peer_name, link in list(self.links.items()):
|
|
192
199
|
try:
|
|
193
|
-
await
|
|
200
|
+
await link.relay_event(event)
|
|
194
201
|
except Exception:
|
|
195
|
-
logger.exception("
|
|
202
|
+
logger.exception("Failed to relay event to %s", peer_name)
|
|
203
|
+
|
|
204
|
+
async def _dispatch_to_bots(self, event: Event) -> None:
|
|
205
|
+
if self.bot_manager is None:
|
|
206
|
+
return
|
|
207
|
+
try:
|
|
208
|
+
await self.bot_manager.on_event(event)
|
|
209
|
+
except Exception:
|
|
210
|
+
logger.exception("bot_manager.on_event failed")
|
|
196
211
|
|
|
197
|
-
|
|
198
|
-
|
|
212
|
+
async def emit_event(self, event: Event) -> None:
|
|
213
|
+
origin_tag = event.data.get("_origin")
|
|
214
|
+
attrs = self._build_event_span_attrs(event, origin_tag)
|
|
215
|
+
# Per-call get_tracer: the `tracing_exporter` test fixture swaps the
|
|
216
|
+
# global provider between tests; a cached Tracer would bind to the
|
|
217
|
+
# first test's provider and stop delivering to later ones.
|
|
218
|
+
with _otel_trace.get_tracer("culture.agentirc").start_as_current_span(
|
|
219
|
+
"irc.event.emit", attributes=attrs
|
|
220
|
+
):
|
|
221
|
+
seq = self.next_seq()
|
|
222
|
+
self._event_log.append((seq, event))
|
|
223
|
+
await self._run_skill_hooks(event)
|
|
224
|
+
if not origin_tag:
|
|
225
|
+
await self._relay_to_peers(event)
|
|
226
|
+
await self._dispatch_to_bots(event)
|
|
227
|
+
await self._surface_event_privmsg(event)
|
|
199
228
|
|
|
200
229
|
_NO_SURFACE_TYPES = NO_SURFACE_EVENT_TYPES
|
|
201
230
|
|
|
@@ -8,6 +8,7 @@ Commands are organized into noun-based groups:
|
|
|
8
8
|
culture bot {create,start,stop,list,inspect,archive,unarchive}
|
|
9
9
|
culture skills {install}
|
|
10
10
|
culture devex {...developer-experience passthrough (powered by agex-cli)...}
|
|
11
|
+
culture afi {...agent-first interface passthrough (powered by afi-cli)...}
|
|
11
12
|
|
|
12
13
|
Universal verbs (available at the root):
|
|
13
14
|
culture explain [topic] full description of topic (default: culture)
|
|
@@ -22,9 +23,9 @@ import logging
|
|
|
22
23
|
import sys
|
|
23
24
|
|
|
24
25
|
from culture import __version__
|
|
25
|
-
from culture.cli import agent, bot, channel, devex, introspect, mesh, server, skills
|
|
26
|
+
from culture.cli import afi, agent, bot, channel, devex, introspect, mesh, server, skills
|
|
26
27
|
|
|
27
|
-
GROUPS = [agent, server, mesh, channel, bot, skills, devex, introspect]
|
|
28
|
+
GROUPS = [agent, server, mesh, channel, bot, skills, devex, afi, introspect]
|
|
28
29
|
|
|
29
30
|
|
|
30
31
|
def _names_of(group) -> set[str]:
|