agentirc-cli 8.5.0__tar.gz → 8.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/CHANGELOG.md +19 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/PKG-INFO +1 -1
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/agent_runner.py +53 -11
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/config.py +24 -0
- agentirc_cli-8.6.0/culture/clients/acp/culture.yaml +32 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/daemon.py +11 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/irc_transport.py +109 -18
- agentirc_cli-8.6.0/culture/clients/acp/telemetry.py +318 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/agent_runner.py +71 -14
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/config.py +24 -0
- agentirc_cli-8.6.0/culture/clients/claude/culture.yaml +29 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/daemon.py +11 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/irc_transport.py +126 -35
- agentirc_cli-8.6.0/culture/clients/claude/telemetry.py +318 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/agent_runner.py +60 -22
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/config.py +26 -0
- agentirc_cli-8.6.0/culture/clients/codex/culture.yaml +29 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/daemon.py +11 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/irc_transport.py +109 -18
- agentirc_cli-8.6.0/culture/clients/codex/telemetry.py +318 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/agent_runner.py +48 -6
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/config.py +24 -0
- agentirc_cli-8.6.0/culture/clients/copilot/culture.yaml +29 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/daemon.py +11 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/irc_transport.py +109 -18
- agentirc_cli-8.6.0/culture/clients/copilot/telemetry.py +318 -0
- agentirc_cli-8.6.0/docs/agentirc/harness-telemetry.md +302 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/agentirc/telemetry.md +40 -4
- agentirc_cli-8.6.0/docs/superpowers/plans/2026-04-28-otel-harness.md +272 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/packages/agent-harness/README.md +11 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/packages/agent-harness/config.py +24 -0
- agentirc_cli-8.6.0/packages/agent-harness/culture.yaml +28 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/packages/agent-harness/daemon.py +13 -1
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/packages/agent-harness/irc_transport.py +108 -18
- agentirc_cli-8.6.0/packages/agent-harness/telemetry.py +315 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/pyproject.toml +1 -1
- agentirc_cli-8.6.0/tests/harness/conftest.py +89 -0
- agentirc_cli-8.6.0/tests/harness/test_agent_runner_acp.py +233 -0
- agentirc_cli-8.6.0/tests/harness/test_agent_runner_claude.py +449 -0
- agentirc_cli-8.6.0/tests/harness/test_agent_runner_codex.py +229 -0
- agentirc_cli-8.6.0/tests/harness/test_agent_runner_copilot.py +256 -0
- agentirc_cli-8.6.0/tests/harness/test_all_backends_parity.py +398 -0
- agentirc_cli-8.6.0/tests/harness/test_daemon_telemetry.py +72 -0
- agentirc_cli-8.6.0/tests/harness/test_irc_transport_propagation.py +447 -0
- agentirc_cli-8.6.0/tests/harness/test_record_llm_call.py +245 -0
- agentirc_cli-8.6.0/tests/harness/test_telemetry_module.py +264 -0
- agentirc_cli-8.6.0/tests/telemetry/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/uv.lock +1 -1
- agentirc_cli-8.5.0/culture/clients/acp/culture.yaml +0 -17
- agentirc_cli-8.5.0/culture/clients/claude/culture.yaml +0 -14
- agentirc_cli-8.5.0/culture/clients/codex/culture.yaml +0 -14
- agentirc_cli-8.5.0/culture/clients/copilot/culture.yaml +0 -14
- agentirc_cli-8.5.0/packages/agent-harness/culture.yaml +0 -13
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.claude/agents/doc-test-alignment.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.flake8 +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.github/workflows/docs-check.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.gitignore +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.pr_agent.toml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/.pylintrc +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/CLAUDE.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/Gemfile +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/Gemfile.lock +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/LICENSE +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/README.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/SECURITY.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/_config.base.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/_config.culture.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/_data/sites.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/_includes/head_custom.html +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/_sass/color_schemes/dark-terminal.scss +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/assets/images/IMG_3183.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/assets/images/apple-touch-icon.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/assets/images/favicon-16x16.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/assets/images/favicon-32x32.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/assets/images/favicon.ico +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/assets/images/og-agentirc.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/assets/images/og-culture.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/__main__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/CLAUDE.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/__main__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/channel.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/docs/agentirc-architecture.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/docs/agentirc-features.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/docs/agentirc-skill.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/docs/agentirc.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/events.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/history_store.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/ircd.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/remote_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/room_store.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/rooms_util.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/server_link.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/skill.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/skills/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/skills/history.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/skills/icon.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/skills/rooms.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/skills/threads.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/agentirc/thread_store.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/aio.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/bot.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/bot_manager.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/filter_dsl.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/system/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/system/welcome/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/system/welcome/bot.yaml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/system/welcome/handler.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/_passthrough.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/afi.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/agent.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/bot.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/channel.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/devex.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/introspect.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/mesh.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/shared/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/shared/constants.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/shared/display.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/shared/formatting.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/shared/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/shared/mesh.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/shared/process.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/cli/skills.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/console/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/console/app.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/console/client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/console/commands.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/console/status.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/constants.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/credentials.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/formatting.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/learn_prompt.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/mesh_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/observer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/overview/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/overview/collector.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/overview/model.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/overview/web/style.css +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/persistence.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/pidfile.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/commands.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/extensions/audit.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/extensions/events.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/extensions/tracing.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/message.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/protocol/replies.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/telemetry/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/telemetry/audit.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/telemetry/context.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/telemetry/metrics.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/culture/telemetry/tracing.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/README.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/agentirc/architecture-overview.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/agentirc/audit.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/agentirc/bots.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/agentirc/events.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/agentirc/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/agentirc/otelcol-template.yaml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/agentirc/why-agentirc.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/agent-lifecycle.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/choose-a-harness.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/features.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/mental-model.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/operate.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/patterns.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/quickstart.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/reflective-development.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/vision-patterns-index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/vision.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/culture/what-is-culture.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/architecture/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/architecture/layers.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/architecture/subsites.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/architecture/threads.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/cli/afi.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/cli/commands.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/cli/devex.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/cli/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/console.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/harnesses/acp.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/harnesses/claude.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/harnesses/codex.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/harnesses/copilot.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/harnesses/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/server/architecture.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/server/config.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/server/deployment.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/server/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/reference/server/security.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/resources/positioning.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/concepts/federation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/concepts/harnesses.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/concepts/humans-and-agents.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/concepts/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/concepts/persistence.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/concepts/rooms.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/demos/magic-demo.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/guides/first-session.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/guides/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/guides/join-as-human.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/guides/local-setup.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/guides/multi-machine.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/shared/use-cases-index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-09-decentralized-agent-config.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-12-console-enhancements.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-15-mesh-events.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-18-culture-dev-positioning.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-22-agex-integration.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-24-otel-foundation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-25-otel-federation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-26-otel-metrics.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/plans/2026-04-27-otel-audit.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-07-reflective-development-reframe-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-08-reflective-development-deepening-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-09-decentralized-agent-config-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-12-console-enhancements-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-15-mesh-events-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-17-sites-repositioning-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-18-culture-dev-positioning-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-22-agex-integration-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/docs/superpowers/specs/2026-04-24-otel-observability-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/favicon.ico +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/robots.txt +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/sitemap-agentirc.html +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/sitemap-main.html +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/sitemap.html +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/sonar-project.properties +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/conftest.py +0 -0
- {agentirc_cli-8.5.0/tests/telemetry → agentirc_cli-8.6.0/tests/harness}/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/_fakes.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/_metrics_helpers.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_audit_emit.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_audit_federation.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_audit_lifecycle.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_audit_module.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_audit_parse_error.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_config_load.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_context.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_dispatch_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_emit_event_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_federation_propagation.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_metrics_clients.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_metrics_events.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_metrics_init.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_metrics_irc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_metrics_s2s.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_metrics_trace_inbound.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_outbound_inject.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_parse_error.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_privmsg_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_s2s_dispatch_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_s2s_relay_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_s2s_session_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_server_init.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_server_link_inject.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_session_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/telemetry/test_tracing.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_archive.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_bot.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_bot_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_bot_config_fires_event_toplevel.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_channel.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_channel_cli.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_cli_afi.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_cli_devex.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_cli_introspect.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_cli_passthrough.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_connection.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_console_chat_markdown.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_console_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_console_commands.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_console_connection.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_console_fixes_224_227.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_console_icons.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_console_integration.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_console_status.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_credentials.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_culture_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_daemon.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_discovery.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_display.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_events_basic.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_events_bot_chain.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_events_bot_trigger.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_events_cap_fallback.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_events_catalog.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_events_federation.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_events_history.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_events_lifecycle.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_events_reserved_nick.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_federation.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_filter_dsl.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_history.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_http_listener.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_irc_transport_tags.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_learn_prompt.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_manifest_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_mention_target_cleanup.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_mention_warning.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_mentions.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_mesh_readiness.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_message.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_message_tags.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_messaging.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_migrate_cli.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_modes.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_overview_model.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_overview_web.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_persistence.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_persistence_timeout.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_pidfile.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_register_cli.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_rooms.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_skill_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_skill_docs.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_skills.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_supervisor.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_template_engine.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_threads.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.6.0}/tests/test_welcome_bot.py +0 -0
|
@@ -4,6 +4,25 @@ 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.6.0] - 2026-04-26
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Harness-side OTEL: 3 spans (harness.irc.connect, harness.irc.message.handle, harness.llm.call) and 4 LLM metrics (culture.harness.llm.tokens.input/output, call.duration, calls).
|
|
12
|
+
- W3C traceparent injection on outbound IRC + extraction on inbound — single trace_id now spans server, federation, and harness in the cross-process tree.
|
|
13
|
+
- Per-backend telemetry citation across claude/codex/copilot/acp with all-backends parity test (24 tests across 6 dimensions) locking down drift.
|
|
14
|
+
- docs/agentirc/harness-telemetry.md — new operator guide for the harness OTEL pillar.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- packages/agent-harness/{telemetry.py,config.py,culture.yaml,irc_transport.py,daemon.py} — reference module for the citation pattern.
|
|
19
|
+
- culture/clients/{claude,codex,copilot,acp}/{telemetry.py,config.py,culture.yaml,irc_transport.py,daemon.py,agent_runner.py} — telemetry citation, harness.llm.call span wrap, record_llm_call invocation.
|
|
20
|
+
- tests/harness/ — 70 new tests (24 parity + 46 module/runner/transport/daemon).
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- Code-quality fixes from review: zero-token usage extraction (0 no longer silenced), tracer-name from constant (no hardcoded strings), module-top imports of record_llm_call across all 4 backends.
|
|
25
|
+
|
|
7
26
|
## [8.5.0] - 2026-04-25
|
|
8
27
|
|
|
9
28
|
### Added
|
|
@@ -12,9 +12,16 @@ import logging
|
|
|
12
12
|
import os
|
|
13
13
|
import shutil
|
|
14
14
|
import tempfile
|
|
15
|
-
|
|
15
|
+
import time
|
|
16
|
+
from typing import TYPE_CHECKING, Any, Awaitable, Callable
|
|
17
|
+
|
|
18
|
+
from opentelemetry import trace as _otel_trace
|
|
16
19
|
|
|
17
20
|
from culture.aio import maybe_await
|
|
21
|
+
from culture.clients.acp.telemetry import _HARNESS_TRACER_NAME, record_llm_call
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from culture.clients.acp.telemetry import HarnessMetricsRegistry
|
|
18
25
|
|
|
19
26
|
logger = logging.getLogger(__name__)
|
|
20
27
|
|
|
@@ -36,6 +43,8 @@ class ACPAgentRunner:
|
|
|
36
43
|
on_exit: Callable[[int], Awaitable[None]] | None = None,
|
|
37
44
|
on_message: Callable[[dict[str, Any]], Awaitable[None]] | None = None,
|
|
38
45
|
on_turn_error: Callable[[], Awaitable[None] | None] | None = None,
|
|
46
|
+
metrics: HarnessMetricsRegistry | None = None,
|
|
47
|
+
nick: str = "",
|
|
39
48
|
) -> None:
|
|
40
49
|
self.model = model
|
|
41
50
|
self.directory = directory
|
|
@@ -44,6 +53,8 @@ class ACPAgentRunner:
|
|
|
44
53
|
self.on_exit = on_exit
|
|
45
54
|
self.on_message = on_message
|
|
46
55
|
self.on_turn_error = on_turn_error
|
|
56
|
+
self._metrics = metrics
|
|
57
|
+
self._nick = nick
|
|
47
58
|
|
|
48
59
|
self._isolated_home: str | None = None
|
|
49
60
|
self._process: asyncio.subprocess.Process | None = None
|
|
@@ -431,16 +442,47 @@ class ACPAgentRunner:
|
|
|
431
442
|
|
|
432
443
|
async def _execute_single_prompt(self, text: str) -> None:
|
|
433
444
|
"""Send one prompt and handle its result, managing the busy flag."""
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
445
|
+
start_perf = time.perf_counter()
|
|
446
|
+
outcome = "success"
|
|
447
|
+
tracer = _otel_trace.get_tracer(_HARNESS_TRACER_NAME)
|
|
448
|
+
with tracer.start_as_current_span(
|
|
449
|
+
"harness.llm.call",
|
|
450
|
+
attributes={
|
|
451
|
+
"harness.backend": "acp",
|
|
452
|
+
"harness.model": self.model,
|
|
453
|
+
"harness.nick": self._nick,
|
|
454
|
+
},
|
|
455
|
+
):
|
|
456
|
+
try:
|
|
457
|
+
self._busy = True
|
|
458
|
+
resp = await self._send_prompt_with_retry(text)
|
|
459
|
+
await self._handle_prompt_result(resp)
|
|
460
|
+
except TimeoutError: # bubbles from _send_prompt_with_retry's retry-then-fail
|
|
461
|
+
outcome = "timeout"
|
|
462
|
+
logger.exception("ACP turn timeout")
|
|
463
|
+
if self.on_turn_error:
|
|
464
|
+
await maybe_await(self.on_turn_error())
|
|
465
|
+
except Exception:
|
|
466
|
+
outcome = "error"
|
|
467
|
+
logger.exception("ACP turn error")
|
|
468
|
+
if self.on_turn_error:
|
|
469
|
+
await maybe_await(self.on_turn_error())
|
|
470
|
+
finally:
|
|
471
|
+
self._busy = False
|
|
472
|
+
duration_ms = (time.perf_counter() - start_perf) * 1000.0
|
|
473
|
+
if self._metrics is not None:
|
|
474
|
+
# ACP token usage MAY arrive in session/update stopReason payload;
|
|
475
|
+
# current implementation does not extract — usage=None for v1.
|
|
476
|
+
# When we add extraction (per backing agent), thread through here.
|
|
477
|
+
record_llm_call(
|
|
478
|
+
self._metrics,
|
|
479
|
+
backend="acp",
|
|
480
|
+
model=self.model,
|
|
481
|
+
nick=self._nick,
|
|
482
|
+
usage=None,
|
|
483
|
+
duration_ms=duration_ms,
|
|
484
|
+
outcome=outcome,
|
|
485
|
+
)
|
|
444
486
|
|
|
445
487
|
async def _prompt_loop(self) -> None:
|
|
446
488
|
"""Process queued prompts one at a time."""
|
|
@@ -62,6 +62,27 @@ class AgentConfig:
|
|
|
62
62
|
icon: str | None = None
|
|
63
63
|
|
|
64
64
|
|
|
65
|
+
@dataclass
|
|
66
|
+
class TelemetryConfig:
|
|
67
|
+
"""OpenTelemetry settings for the agent harness.
|
|
68
|
+
|
|
69
|
+
``enabled: false`` by default so freshly installed harnesses don't
|
|
70
|
+
try to connect to a non-existent OTLP collector. Flip to ``true``
|
|
71
|
+
once your collector is running.
|
|
72
|
+
"""
|
|
73
|
+
|
|
74
|
+
enabled: bool = False
|
|
75
|
+
service_name: str = "culture.harness.acp"
|
|
76
|
+
otlp_endpoint: str = "http://localhost:4317"
|
|
77
|
+
otlp_protocol: str = "grpc" # grpc | http/protobuf (only grpc supported initially)
|
|
78
|
+
otlp_timeout_ms: int = 5000
|
|
79
|
+
otlp_compression: str = "gzip"
|
|
80
|
+
traces_enabled: bool = True
|
|
81
|
+
traces_sampler: str = "parentbased_always_on"
|
|
82
|
+
metrics_enabled: bool = True
|
|
83
|
+
metrics_export_interval_ms: int = 10000
|
|
84
|
+
|
|
85
|
+
|
|
65
86
|
@dataclass
|
|
66
87
|
class DaemonConfig:
|
|
67
88
|
"""Top-level daemon configuration."""
|
|
@@ -69,6 +90,7 @@ class DaemonConfig:
|
|
|
69
90
|
server: ServerConnConfig = field(default_factory=ServerConnConfig)
|
|
70
91
|
supervisor: SupervisorConfig = field(default_factory=SupervisorConfig)
|
|
71
92
|
webhooks: WebhookConfig = field(default_factory=WebhookConfig)
|
|
93
|
+
telemetry: TelemetryConfig = field(default_factory=TelemetryConfig)
|
|
72
94
|
buffer_size: int = 500
|
|
73
95
|
poll_interval: int = 60
|
|
74
96
|
sleep_start: str = "23:00"
|
|
@@ -91,6 +113,7 @@ def load_config(path: str | Path) -> DaemonConfig:
|
|
|
91
113
|
supervisor = SupervisorConfig(**raw.get("supervisor", {}))
|
|
92
114
|
|
|
93
115
|
webhooks = WebhookConfig(**raw.get("webhooks", {}))
|
|
116
|
+
telemetry = TelemetryConfig(**raw.get("telemetry", {}))
|
|
94
117
|
|
|
95
118
|
agents = []
|
|
96
119
|
known_agent_fields = {f.name for f in AgentConfig.__dataclass_fields__.values()}
|
|
@@ -102,6 +125,7 @@ def load_config(path: str | Path) -> DaemonConfig:
|
|
|
102
125
|
server=server,
|
|
103
126
|
supervisor=supervisor,
|
|
104
127
|
webhooks=webhooks,
|
|
128
|
+
telemetry=telemetry,
|
|
105
129
|
buffer_size=raw.get("buffer_size", 500),
|
|
106
130
|
poll_interval=raw.get("poll_interval", 60),
|
|
107
131
|
sleep_start=raw.get("sleep_start", "23:00"),
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
suffix: harness-acp
|
|
2
|
+
backend: claude
|
|
3
|
+
model: claude-opus-4-6
|
|
4
|
+
channels:
|
|
5
|
+
- "#harness"
|
|
6
|
+
acp_command:
|
|
7
|
+
- opencode
|
|
8
|
+
- acp
|
|
9
|
+
system_prompt: |
|
|
10
|
+
You maintain the ACP agent backend in culture/clients/acp/.
|
|
11
|
+
Listen on #harness for propagation instructions from spark-harness.
|
|
12
|
+
Apply changes using the citation pattern (cite, don't import),
|
|
13
|
+
adapting for ACP (Cline, OpenCode, Kiro)
|
|
14
|
+
specifics (agent_runner.py, supervisor.py).
|
|
15
|
+
tags:
|
|
16
|
+
- harness
|
|
17
|
+
- acp
|
|
18
|
+
|
|
19
|
+
# OpenTelemetry configuration for the agent harness.
|
|
20
|
+
# Set enabled: true once your OTLP collector is running.
|
|
21
|
+
# See docs/agentirc/harness-telemetry.md for a setup guide.
|
|
22
|
+
telemetry:
|
|
23
|
+
enabled: false # master switch — flip to true to start exporting
|
|
24
|
+
service_name: culture.harness.acp # overridden per-backend (e.g. culture.harness.acp)
|
|
25
|
+
otlp_endpoint: http://localhost:4317 # OTLP/gRPC receiver endpoint
|
|
26
|
+
otlp_protocol: grpc # grpc or http/protobuf
|
|
27
|
+
otlp_timeout_ms: 5000 # export request timeout in milliseconds
|
|
28
|
+
otlp_compression: gzip # gzip | none
|
|
29
|
+
traces_enabled: true # enable distributed tracing
|
|
30
|
+
traces_sampler: parentbased_always_on # honor the server's sampling decision
|
|
31
|
+
metrics_enabled: true # enable LLM call metrics export
|
|
32
|
+
metrics_export_interval_ms: 10000 # how often to push metric batches (ms)
|
|
@@ -25,6 +25,7 @@ from culture.clients.acp.irc_transport import IRCTransport
|
|
|
25
25
|
from culture.clients.acp.message_buffer import MessageBuffer
|
|
26
26
|
from culture.clients.acp.socket_server import SocketServer
|
|
27
27
|
from culture.clients.acp.supervisor import Supervisor, make_sdk_evaluate_fn
|
|
28
|
+
from culture.clients.acp.telemetry import init_harness_telemetry
|
|
28
29
|
from culture.clients.acp.webhook import AlertEvent, WebhookClient
|
|
29
30
|
from culture.pidfile import remove_pid, write_pid
|
|
30
31
|
|
|
@@ -71,6 +72,8 @@ class ACPDaemon:
|
|
|
71
72
|
self._socket_server: SocketServer | None = None
|
|
72
73
|
self._agent_runner: ACPAgentRunner | None = None
|
|
73
74
|
self._supervisor: Supervisor | None = None
|
|
75
|
+
self._tracer = None
|
|
76
|
+
self._metrics = None
|
|
74
77
|
|
|
75
78
|
# FIFO queue of relay targets — each @mention enqueues a target,
|
|
76
79
|
# each agent response dequeues one, ensuring correct routing even
|
|
@@ -134,6 +137,9 @@ class ACPDaemon:
|
|
|
134
137
|
self._pid_name = f"agent-{self.agent.nick}"
|
|
135
138
|
write_pid(self._pid_name, os.getpid())
|
|
136
139
|
|
|
140
|
+
# 0.5. OTEL telemetry (if telemetry.enabled, installs SDK providers; else no-op).
|
|
141
|
+
self._tracer, self._metrics = init_harness_telemetry(self.config)
|
|
142
|
+
|
|
137
143
|
# 1. Message buffer
|
|
138
144
|
self._buffer = MessageBuffer(max_per_channel=self.config.buffer_size)
|
|
139
145
|
|
|
@@ -148,6 +154,9 @@ class ACPDaemon:
|
|
|
148
154
|
on_mention=self._on_mention,
|
|
149
155
|
tags=list(self.agent.tags),
|
|
150
156
|
on_roominvite=self._on_roominvite,
|
|
157
|
+
tracer=self._tracer,
|
|
158
|
+
metrics=self._metrics,
|
|
159
|
+
backend="acp",
|
|
151
160
|
)
|
|
152
161
|
await self._transport.connect()
|
|
153
162
|
|
|
@@ -389,6 +398,8 @@ class ACPDaemon:
|
|
|
389
398
|
on_exit=self._on_agent_exit,
|
|
390
399
|
on_message=self._on_agent_message,
|
|
391
400
|
on_turn_error=self._on_turn_error,
|
|
401
|
+
metrics=self._metrics,
|
|
402
|
+
nick=self.agent.nick,
|
|
392
403
|
)
|
|
393
404
|
# Absorb the system prompt response without relaying to IRC
|
|
394
405
|
self._mention_targets.append(None)
|
|
@@ -1,20 +1,38 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
|
+
import contextlib
|
|
4
5
|
import logging
|
|
5
6
|
import re
|
|
6
|
-
from
|
|
7
|
+
from contextlib import AbstractContextManager
|
|
8
|
+
from typing import TYPE_CHECKING, Callable
|
|
7
9
|
|
|
8
10
|
from culture.aio import maybe_await
|
|
9
11
|
from culture.clients.acp.message_buffer import MessageBuffer
|
|
10
12
|
from culture.constants import SYSTEM_USER_PREFIX
|
|
11
13
|
from culture.protocol.message import Message
|
|
14
|
+
from culture.telemetry.context import (
|
|
15
|
+
TRACEPARENT_TAG,
|
|
16
|
+
context_from_traceparent,
|
|
17
|
+
current_traceparent,
|
|
18
|
+
extract_traceparent_from_tags,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from opentelemetry.trace import Tracer
|
|
23
|
+
|
|
24
|
+
from culture.clients.acp.telemetry import HarnessMetricsRegistry
|
|
12
25
|
|
|
13
26
|
logger = logging.getLogger(__name__)
|
|
14
27
|
|
|
15
28
|
|
|
16
29
|
class IRCTransport:
|
|
17
|
-
"""Async IRC client for the daemon.
|
|
30
|
+
"""Async IRC client for the daemon.
|
|
31
|
+
|
|
32
|
+
Optional kwargs ``tracer``, ``metrics``, and ``backend`` enable OTEL
|
|
33
|
+
tracing and LLM metrics when an SDK provider is installed. Pass ``None``
|
|
34
|
+
(the default) for all three to run without instrumentation.
|
|
35
|
+
"""
|
|
18
36
|
|
|
19
37
|
def __init__(
|
|
20
38
|
self,
|
|
@@ -28,6 +46,9 @@ class IRCTransport:
|
|
|
28
46
|
tags: list[str] | None = None,
|
|
29
47
|
on_roominvite: Callable[[str, str], None] | None = None,
|
|
30
48
|
icon: str | None = None,
|
|
49
|
+
tracer: Tracer | None = None,
|
|
50
|
+
metrics: HarnessMetricsRegistry | None = None,
|
|
51
|
+
backend: str = "acp",
|
|
31
52
|
):
|
|
32
53
|
self.host = host
|
|
33
54
|
self.port = port
|
|
@@ -39,6 +60,10 @@ class IRCTransport:
|
|
|
39
60
|
self.tags = tags or []
|
|
40
61
|
self.on_roominvite = on_roominvite
|
|
41
62
|
self.icon = icon
|
|
63
|
+
self._tracer = tracer
|
|
64
|
+
# accepted for future per-message metrics (e.g. byte counters); unused in v1
|
|
65
|
+
self._metrics = metrics
|
|
66
|
+
self._backend = backend
|
|
42
67
|
self.connected = False
|
|
43
68
|
self._reader: asyncio.StreamReader | None = None
|
|
44
69
|
self._writer: asyncio.StreamWriter | None = None
|
|
@@ -57,23 +82,46 @@ class IRCTransport:
|
|
|
57
82
|
"332": self._on_numeric_topic,
|
|
58
83
|
}
|
|
59
84
|
|
|
85
|
+
def _span(self, name: str, attrs: dict | None = None) -> AbstractContextManager:
|
|
86
|
+
"""Return a real span context manager when tracing is enabled, else a no-op.
|
|
87
|
+
|
|
88
|
+
Keeps the no-tracer fast path clean — all callers write the same
|
|
89
|
+
``with self._span(...):`` pattern regardless of whether a tracer is
|
|
90
|
+
configured.
|
|
91
|
+
|
|
92
|
+
Does NOT accept a ``context=`` argument; callers that need a span
|
|
93
|
+
parented to a remote trace context (e.g. inbound message handling in
|
|
94
|
+
``_handle``) call ``self._tracer.start_as_current_span`` directly.
|
|
95
|
+
"""
|
|
96
|
+
if self._tracer is not None:
|
|
97
|
+
return self._tracer.start_as_current_span(name, attributes=attrs or {})
|
|
98
|
+
return contextlib.nullcontext()
|
|
99
|
+
|
|
60
100
|
async def connect(self) -> None:
|
|
61
101
|
self._should_run = True
|
|
62
102
|
await self._do_connect()
|
|
63
103
|
|
|
64
104
|
async def _do_connect(self) -> None:
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
105
|
+
with self._span(
|
|
106
|
+
"harness.irc.connect",
|
|
107
|
+
attrs={
|
|
108
|
+
"harness.backend": self._backend,
|
|
109
|
+
"harness.nick": self.nick,
|
|
110
|
+
"harness.server": f"{self.host}:{self.port}",
|
|
111
|
+
},
|
|
112
|
+
):
|
|
113
|
+
try:
|
|
114
|
+
self._reader, self._writer = await asyncio.open_connection(self.host, self.port)
|
|
115
|
+
except OSError as exc:
|
|
116
|
+
raise ConnectionError(
|
|
117
|
+
f"Cannot connect to IRC server at {self.host}:{self.port} "
|
|
118
|
+
f"- is the server running?"
|
|
119
|
+
) from exc
|
|
120
|
+
await self._send_raw("CAP REQ :message-tags")
|
|
121
|
+
await self._send_raw(f"NICK {self.nick}")
|
|
122
|
+
await self._send_raw(f"USER {self.user} 0 * :{self.user}")
|
|
123
|
+
await self._send_raw("CAP END")
|
|
124
|
+
self._read_task = asyncio.create_task(self._read_loop())
|
|
77
125
|
|
|
78
126
|
async def disconnect(self) -> None:
|
|
79
127
|
self._should_run = False
|
|
@@ -145,12 +193,23 @@ class IRCTransport:
|
|
|
145
193
|
await self._send_raw(f"TOPIC {channel}")
|
|
146
194
|
|
|
147
195
|
async def send_raw(self, line: str) -> None:
|
|
148
|
-
"""Send a raw IRC line. Public for commands like HISTORY.
|
|
196
|
+
"""Send a raw IRC line. Public for commands like HISTORY.
|
|
197
|
+
|
|
198
|
+
When a tracer is configured and a span is active, prepends the W3C
|
|
199
|
+
``@culture.dev/traceparent=`` IRCv3 tag so all outbound paths — whether
|
|
200
|
+
called via the internal ``_send_raw`` helper or directly by daemon code
|
|
201
|
+
— carry trace context consistently.
|
|
202
|
+
"""
|
|
203
|
+
if self._tracer is not None and not line.startswith("@"):
|
|
204
|
+
tp = current_traceparent()
|
|
205
|
+
if tp is not None:
|
|
206
|
+
line = f"@{TRACEPARENT_TAG}={tp} {line}"
|
|
149
207
|
if self._writer:
|
|
150
208
|
self._writer.write(f"{line}\r\n".encode())
|
|
151
209
|
await self._writer.drain()
|
|
152
210
|
|
|
153
211
|
async def _send_raw(self, line: str) -> None:
|
|
212
|
+
"""Internal send helper; delegates to send_raw (injection lives there)."""
|
|
154
213
|
await self.send_raw(line)
|
|
155
214
|
|
|
156
215
|
async def _read_loop(self) -> None:
|
|
@@ -193,9 +252,41 @@ class IRCTransport:
|
|
|
193
252
|
delay = min(delay * 2, 60)
|
|
194
253
|
|
|
195
254
|
async def _handle(self, msg: Message) -> None:
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
255
|
+
# Extract inbound traceparent before opening any span so the new span
|
|
256
|
+
# can be correctly parented to the remote trace context.
|
|
257
|
+
result = extract_traceparent_from_tags(msg, peer=None)
|
|
258
|
+
|
|
259
|
+
if self._tracer is not None:
|
|
260
|
+
if result.status == "valid":
|
|
261
|
+
ctx = context_from_traceparent(result.traceparent)
|
|
262
|
+
span_cm = self._tracer.start_as_current_span(
|
|
263
|
+
"harness.irc.message.handle",
|
|
264
|
+
context=ctx,
|
|
265
|
+
attributes={
|
|
266
|
+
"irc.command": msg.command,
|
|
267
|
+
"irc.client.nick": self.nick,
|
|
268
|
+
"culture.trace.origin": "remote",
|
|
269
|
+
},
|
|
270
|
+
)
|
|
271
|
+
else:
|
|
272
|
+
attrs = {
|
|
273
|
+
"irc.command": msg.command,
|
|
274
|
+
"irc.client.nick": self.nick,
|
|
275
|
+
"culture.trace.origin": ("local" if result.status == "missing" else "remote"),
|
|
276
|
+
}
|
|
277
|
+
if result.status in ("malformed", "too_long"):
|
|
278
|
+
attrs["culture.trace.dropped_reason"] = result.status
|
|
279
|
+
span_cm = self._tracer.start_as_current_span(
|
|
280
|
+
"harness.irc.message.handle",
|
|
281
|
+
attributes=attrs,
|
|
282
|
+
)
|
|
283
|
+
else:
|
|
284
|
+
span_cm = contextlib.nullcontext()
|
|
285
|
+
|
|
286
|
+
with span_cm:
|
|
287
|
+
handler = self._cmd_handlers.get(msg.command)
|
|
288
|
+
if handler:
|
|
289
|
+
await maybe_await(handler(msg))
|
|
199
290
|
|
|
200
291
|
async def _on_ping(self, msg: Message) -> None:
|
|
201
292
|
token = msg.params[0] if msg.params else ""
|