agentirc-cli 8.5.0__tar.gz → 8.7.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.7.0}/CHANGELOG.md +29 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/PKG-INFO +2 -1
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/bot.py +24 -13
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/bot_manager.py +53 -24
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/http_listener.py +35 -1
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/agent_runner.py +53 -11
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/config.py +24 -0
- agentirc_cli-8.7.0/culture/clients/acp/culture.yaml +32 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/daemon.py +11 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/irc_transport.py +109 -18
- agentirc_cli-8.7.0/culture/clients/acp/telemetry.py +318 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/agent_runner.py +71 -14
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/config.py +24 -0
- agentirc_cli-8.7.0/culture/clients/claude/culture.yaml +29 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/daemon.py +11 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/irc_transport.py +126 -35
- agentirc_cli-8.7.0/culture/clients/claude/telemetry.py +318 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/agent_runner.py +60 -22
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/config.py +26 -0
- agentirc_cli-8.7.0/culture/clients/codex/culture.yaml +29 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/daemon.py +11 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/irc_transport.py +109 -18
- agentirc_cli-8.7.0/culture/clients/codex/telemetry.py +318 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/agent_runner.py +48 -6
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/config.py +24 -0
- agentirc_cli-8.7.0/culture/clients/copilot/culture.yaml +29 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/daemon.py +11 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/irc_transport.py +109 -18
- agentirc_cli-8.7.0/culture/clients/copilot/telemetry.py +318 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/telemetry/metrics.py +13 -0
- agentirc_cli-8.7.0/docs/agentirc/harness-telemetry.md +302 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/telemetry.md +77 -5
- agentirc_cli-8.7.0/docs/superpowers/plans/2026-04-28-otel-harness.md +272 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-24-otel-observability-design.md +1 -1
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/README.md +11 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/config.py +24 -0
- agentirc_cli-8.7.0/packages/agent-harness/culture.yaml +28 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/daemon.py +13 -1
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/irc_transport.py +108 -18
- agentirc_cli-8.7.0/packages/agent-harness/telemetry.py +315 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/pyproject.toml +2 -1
- agentirc_cli-8.7.0/tests/harness/conftest.py +89 -0
- agentirc_cli-8.7.0/tests/harness/test_agent_runner_acp.py +233 -0
- agentirc_cli-8.7.0/tests/harness/test_agent_runner_claude.py +449 -0
- agentirc_cli-8.7.0/tests/harness/test_agent_runner_codex.py +229 -0
- agentirc_cli-8.7.0/tests/harness/test_agent_runner_copilot.py +256 -0
- agentirc_cli-8.7.0/tests/harness/test_all_backends_parity.py +398 -0
- agentirc_cli-8.7.0/tests/harness/test_daemon_telemetry.py +72 -0
- agentirc_cli-8.7.0/tests/harness/test_irc_transport_propagation.py +447 -0
- agentirc_cli-8.7.0/tests/harness/test_record_llm_call.py +245 -0
- agentirc_cli-8.7.0/tests/harness/test_telemetry_module.py +264 -0
- agentirc_cli-8.7.0/tests/telemetry/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/_metrics_helpers.py +9 -0
- agentirc_cli-8.7.0/tests/telemetry/conftest.py +33 -0
- agentirc_cli-8.7.0/tests/telemetry/test_bot_event_dispatch_span.py +138 -0
- agentirc_cli-8.7.0/tests/telemetry/test_bot_run_span.py +91 -0
- agentirc_cli-8.7.0/tests/telemetry/test_metrics_bots.py +127 -0
- agentirc_cli-8.7.0/tests/telemetry/test_metrics_webhook.py +148 -0
- agentirc_cli-8.7.0/tests/telemetry/test_webhook_http_span.py +45 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/uv.lock +107 -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.7.0}/.claude/agents/doc-test-alignment.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.flake8 +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.github/workflows/docs-check.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.gitignore +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.pr_agent.toml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/.pylintrc +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/CLAUDE.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/Gemfile +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/Gemfile.lock +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/LICENSE +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/README.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/SECURITY.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_config.base.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_config.culture.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_data/sites.yml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_includes/head_custom.html +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_sass/color_schemes/dark-terminal.scss +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/IMG_3183.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/apple-touch-icon.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/favicon-16x16.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/favicon-32x32.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/favicon.ico +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/og-agentirc.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/assets/images/og-culture.png +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/__main__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/CLAUDE.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/__main__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/channel.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/docs/agentirc-architecture.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/docs/agentirc-features.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/docs/agentirc-skill.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/docs/agentirc.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/events.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/history_store.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/ircd.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/remote_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/room_store.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/rooms_util.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/server_link.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skill.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skills/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skills/history.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skills/icon.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skills/rooms.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/skills/threads.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/agentirc/thread_store.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/aio.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/filter_dsl.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/system/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/system/welcome/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/system/welcome/bot.yaml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/system/welcome/handler.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/_passthrough.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/afi.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/agent.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/bot.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/channel.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/devex.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/introspect.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/mesh.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/constants.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/display.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/formatting.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/mesh.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/shared/process.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/cli/skills.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/app.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/commands.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/status.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/constants.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/credentials.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/formatting.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/learn_prompt.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/mesh_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/observer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/collector.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/model.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/overview/web/style.css +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/persistence.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/pidfile.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/commands.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/audit.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/events.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/extensions/tracing.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/message.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/protocol/replies.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/telemetry/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/telemetry/audit.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/telemetry/context.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/culture/telemetry/tracing.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/README.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/architecture-overview.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/audit.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/bots.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/events.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/otelcol-template.yaml +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/agentirc/why-agentirc.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/agent-lifecycle.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/choose-a-harness.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/features.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/mental-model.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/operate.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/patterns.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/quickstart.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/reflective-development.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/vision-patterns-index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/vision.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/culture/what-is-culture.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/architecture/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/architecture/layers.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/architecture/subsites.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/architecture/threads.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/cli/afi.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/cli/commands.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/cli/devex.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/cli/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/console.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/harnesses/acp.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/harnesses/claude.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/harnesses/codex.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/harnesses/copilot.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/harnesses/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/server/architecture.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/server/config.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/server/deployment.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/server/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/reference/server/security.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/resources/positioning.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/federation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/harnesses.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/humans-and-agents.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/persistence.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/concepts/rooms.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/demos/magic-demo.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/guides/first-session.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/guides/index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/guides/join-as-human.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/guides/local-setup.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/guides/multi-machine.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/shared/use-cases-index.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-09-decentralized-agent-config.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-12-console-enhancements.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-15-mesh-events.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-18-culture-dev-positioning.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-22-agex-integration.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-24-otel-foundation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-25-otel-federation.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-26-otel-metrics.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/plans/2026-04-27-otel-audit.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-07-reflective-development-reframe-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-08-reflective-development-deepening-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-09-decentralized-agent-config-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-12-console-enhancements-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-15-mesh-events-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-17-sites-repositioning-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-18-culture-dev-positioning-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/docs/superpowers/specs/2026-04-22-agex-integration-design.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/favicon.ico +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/robots.txt +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/sitemap-agentirc.html +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/sitemap-main.html +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/sitemap.html +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/sonar-project.properties +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/conftest.py +0 -0
- {agentirc_cli-8.5.0/tests/telemetry → agentirc_cli-8.7.0/tests/harness}/__init__.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/_fakes.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_audit_emit.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_audit_federation.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_audit_lifecycle.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_audit_module.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_audit_parse_error.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_config_load.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_context.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_dispatch_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_emit_event_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_federation_propagation.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_clients.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_events.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_init.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_irc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_s2s.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_metrics_trace_inbound.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_outbound_inject.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_parse_error.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_privmsg_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_s2s_dispatch_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_s2s_relay_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_s2s_session_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_server_init.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_server_link_inject.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_session_span.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/telemetry/test_tracing.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_archive.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_bot.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_bot_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_bot_config_fires_event_toplevel.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_channel.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_channel_cli.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_cli_afi.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_cli_devex.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_cli_introspect.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_cli_passthrough.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_connection.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_chat_markdown.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_commands.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_connection.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_fixes_224_227.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_icons.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_integration.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_console_status.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_credentials.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_culture_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_daemon.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_discovery.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_display.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_basic.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_bot_chain.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_bot_trigger.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_cap_fallback.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_catalog.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_federation.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_history.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_lifecycle.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_events_reserved_nick.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_federation.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_filter_dsl.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_history.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_http_listener.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_ipc.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_irc_transport_tags.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_learn_prompt.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_manifest_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mention_target_cleanup.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mention_warning.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mentions.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_mesh_readiness.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_message.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_message_tags.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_messaging.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_migrate_cli.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_modes.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_overview_model.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_overview_web.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_persistence.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_persistence_timeout.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_pidfile.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_register_cli.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_rooms.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_skill_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_skill_docs.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_skills.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_socket_server.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_supervisor.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_template_engine.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_threads.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_webhook.py +0 -0
- {agentirc_cli-8.5.0 → agentirc_cli-8.7.0}/tests/test_welcome_bot.py +0 -0
|
@@ -4,6 +4,35 @@ 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.7.0] - 2026-04-26
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- OTEL bot instrumentation (Plan 7): bot.event.dispatch and bot.run spans, culture.bot.invocations counter, culture.bot.webhook.duration histogram, aiohttp-server auto-instrumentation on the webhook listener.
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- docs/agentirc/telemetry.md updated with the 8.7.0 section; harness-telemetry.md cross-link updated.
|
|
16
|
+
|
|
17
|
+
## [8.6.0] - 2026-04-26
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- 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).
|
|
22
|
+
- W3C traceparent injection on outbound IRC + extraction on inbound — single trace_id now spans server, federation, and harness in the cross-process tree.
|
|
23
|
+
- Per-backend telemetry citation across claude/codex/copilot/acp with all-backends parity test (24 tests across 6 dimensions) locking down drift.
|
|
24
|
+
- docs/agentirc/harness-telemetry.md — new operator guide for the harness OTEL pillar.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- packages/agent-harness/{telemetry.py,config.py,culture.yaml,irc_transport.py,daemon.py} — reference module for the citation pattern.
|
|
29
|
+
- 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.
|
|
30
|
+
- tests/harness/ — 70 new tests (24 parity + 46 module/runner/transport/daemon).
|
|
31
|
+
|
|
32
|
+
### Fixed
|
|
33
|
+
|
|
34
|
+
- 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.
|
|
35
|
+
|
|
7
36
|
## [8.5.0] - 2026-04-25
|
|
8
37
|
|
|
9
38
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentirc-cli
|
|
3
|
-
Version: 8.
|
|
3
|
+
Version: 8.7.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
|
|
@@ -20,6 +20,7 @@ Requires-Dist: claude-agent-sdk>=0.1
|
|
|
20
20
|
Requires-Dist: mistune>=3.0
|
|
21
21
|
Requires-Dist: opentelemetry-api>=1.25
|
|
22
22
|
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.25
|
|
23
|
+
Requires-Dist: opentelemetry-instrumentation-aiohttp-server>=0.46b0
|
|
23
24
|
Requires-Dist: opentelemetry-sdk>=1.25
|
|
24
25
|
Requires-Dist: opentelemetry-semantic-conventions>=0.46b0
|
|
25
26
|
Requires-Dist: pyyaml>=6.0
|
|
@@ -8,6 +8,8 @@ import time
|
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
from typing import TYPE_CHECKING, Any
|
|
10
10
|
|
|
11
|
+
from opentelemetry import trace as _otel_trace
|
|
12
|
+
|
|
11
13
|
from culture.agentirc.skill import Event, EventType
|
|
12
14
|
from culture.bots.config import BOTS_DIR, BotConfig
|
|
13
15
|
from culture.bots.template_engine import render_fallback, render_template
|
|
@@ -125,19 +127,28 @@ class Bot:
|
|
|
125
127
|
|
|
126
128
|
Returns the rendered message text.
|
|
127
129
|
"""
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
130
|
+
# Span opens before the active-check so, if handle() is invoked for an
|
|
131
|
+
# inactive bot, the failure still surfaces in tracing with ERROR
|
|
132
|
+
# status and bot.name set instead of only raising.
|
|
133
|
+
with _otel_trace.get_tracer("culture.agentirc").start_as_current_span(
|
|
134
|
+
"bot.run",
|
|
135
|
+
attributes={"bot.name": self.config.name},
|
|
136
|
+
) as span:
|
|
137
|
+
if not self.active or not self.virtual_client:
|
|
138
|
+
span.set_status(_otel_trace.StatusCode.ERROR, "bot not active")
|
|
139
|
+
raise RuntimeError(f"Bot {self.config.name} is not active")
|
|
140
|
+
|
|
141
|
+
message = await self._resolve_message(payload)
|
|
142
|
+
if not message:
|
|
143
|
+
span.set_attribute("bot.run.empty_message", True)
|
|
144
|
+
return ""
|
|
145
|
+
|
|
146
|
+
if self.config.mention:
|
|
147
|
+
message = f"@{self.config.mention} {message}"
|
|
148
|
+
|
|
149
|
+
await self._deliver(message, payload)
|
|
150
|
+
await self._maybe_fire_event(payload)
|
|
151
|
+
return message
|
|
141
152
|
|
|
142
153
|
async def _resolve_message(self, payload: dict) -> str:
|
|
143
154
|
"""Render the message from custom handler or template."""
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import asyncio
|
|
5
6
|
import logging
|
|
6
7
|
from typing import TYPE_CHECKING
|
|
7
8
|
|
|
9
|
+
from opentelemetry import trace as _otel_trace
|
|
10
|
+
|
|
8
11
|
from culture.bots.bot import Bot
|
|
9
12
|
from culture.bots.config import (
|
|
10
13
|
BOT_CONFIG_FILE,
|
|
@@ -88,32 +91,58 @@ class BotManager:
|
|
|
88
91
|
async def on_event(self, event) -> None:
|
|
89
92
|
"""Evaluate event-triggered bots against an event and dispatch matches."""
|
|
90
93
|
# Snapshot: handle() may call emit_event() which re-enters on_event().
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
94
|
+
ctx = {
|
|
95
|
+
"type": event.type.value if hasattr(event.type, "value") else str(event.type),
|
|
96
|
+
"channel": event.channel,
|
|
97
|
+
"nick": event.nick,
|
|
98
|
+
"data": dict(event.data),
|
|
99
|
+
}
|
|
100
|
+
for bot in list(self.bots.values()):
|
|
101
|
+
if self._matches_event(bot, ctx):
|
|
102
|
+
await self._dispatch_to_bot(bot, ctx)
|
|
103
|
+
|
|
104
|
+
def _matches_event(self, bot: Bot, ctx: dict) -> bool:
|
|
105
|
+
"""True iff `bot` is event-triggered and its filter accepts `ctx`."""
|
|
106
|
+
cfg = bot.config
|
|
107
|
+
if cfg.trigger_type != "event":
|
|
108
|
+
return False
|
|
109
|
+
compiled = getattr(cfg, "_compiled_filter", None)
|
|
110
|
+
if compiled is None:
|
|
111
|
+
return False
|
|
112
|
+
try:
|
|
113
|
+
return bool(evaluate(compiled, ctx))
|
|
114
|
+
except Exception:
|
|
115
|
+
logger.exception("Filter evaluation failed for bot %s", cfg.name)
|
|
116
|
+
return False
|
|
117
|
+
|
|
118
|
+
async def _dispatch_to_bot(self, bot: Bot, ctx: dict) -> None:
|
|
119
|
+
"""Lazily start the bot and run handle() inside a bot.event.dispatch span."""
|
|
120
|
+
if not await self._try_start_bot(bot):
|
|
121
|
+
return
|
|
122
|
+
cfg = bot.config
|
|
123
|
+
event_type_str = ctx["type"]
|
|
124
|
+
with _otel_trace.get_tracer("culture.agentirc").start_as_current_span(
|
|
125
|
+
"bot.event.dispatch",
|
|
126
|
+
attributes={"bot.name": cfg.name, "event.type": event_type_str},
|
|
127
|
+
) as span:
|
|
128
|
+
outcome = "success"
|
|
113
129
|
try:
|
|
114
130
|
await bot.handle({"event": ctx})
|
|
115
|
-
except
|
|
116
|
-
|
|
131
|
+
except asyncio.CancelledError:
|
|
132
|
+
raise
|
|
133
|
+
except Exception as exc:
|
|
134
|
+
outcome = "error"
|
|
135
|
+
span.set_status(_otel_trace.StatusCode.ERROR, str(exc))
|
|
136
|
+
logger.exception("Bot %s handle() failed for event %s", cfg.name, ctx["type"])
|
|
137
|
+
finally:
|
|
138
|
+
self.server.metrics.bot_invocations.add(
|
|
139
|
+
1,
|
|
140
|
+
{
|
|
141
|
+
"bot": cfg.name,
|
|
142
|
+
"event.type": event_type_str,
|
|
143
|
+
"outcome": outcome,
|
|
144
|
+
},
|
|
145
|
+
)
|
|
117
146
|
|
|
118
147
|
def load_system_bots(self) -> None:
|
|
119
148
|
"""Discover and register system bots from the package."""
|
|
@@ -4,9 +4,11 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
|
+
import time
|
|
7
8
|
from typing import TYPE_CHECKING
|
|
8
9
|
|
|
9
10
|
from aiohttp import web
|
|
11
|
+
from opentelemetry.instrumentation.aiohttp_server import AioHttpServerInstrumentor
|
|
10
12
|
|
|
11
13
|
if TYPE_CHECKING:
|
|
12
14
|
from culture.bots.bot_manager import BotManager
|
|
@@ -25,7 +27,16 @@ class HttpListener:
|
|
|
25
27
|
self._runner: web.AppRunner | None = None
|
|
26
28
|
|
|
27
29
|
async def start(self) -> None:
|
|
28
|
-
|
|
30
|
+
# Patch aiohttp.web.Application to auto-inject the OTEL server
|
|
31
|
+
# middleware. Deferred from import time so just importing this module
|
|
32
|
+
# has no side effect. Re-instrument each start() so the captured
|
|
33
|
+
# tracer/meter rebinds to the *current* TracerProvider — important for
|
|
34
|
+
# tests that swap providers between runs, harmless in production.
|
|
35
|
+
instrumentor = AioHttpServerInstrumentor()
|
|
36
|
+
if instrumentor.is_instrumented_by_opentelemetry:
|
|
37
|
+
instrumentor.uninstrument()
|
|
38
|
+
instrumentor.instrument()
|
|
39
|
+
self._app = web.Application(middlewares=[self._record_webhook_duration])
|
|
29
40
|
self._app.router.add_get("/health", self._handle_health)
|
|
30
41
|
self._app.router.add_post("/{bot_name}", self._handle_webhook)
|
|
31
42
|
|
|
@@ -41,6 +52,29 @@ class HttpListener:
|
|
|
41
52
|
self._runner = None
|
|
42
53
|
self._app = None
|
|
43
54
|
|
|
55
|
+
@web.middleware
|
|
56
|
+
async def _record_webhook_duration(self, request, handler):
|
|
57
|
+
"""Record per-request duration into culture.bot.webhook.duration."""
|
|
58
|
+
bot_name = request.match_info.get("bot_name") or "_unrouted"
|
|
59
|
+
start = time.perf_counter()
|
|
60
|
+
# Default for the "handler raised a non-HTTPException" path: aiohttp
|
|
61
|
+
# converts unhandled exceptions to 500 responses outside this
|
|
62
|
+
# middleware, so the histogram should report 5xx for them.
|
|
63
|
+
status_class = "5xx"
|
|
64
|
+
try:
|
|
65
|
+
response = await handler(request)
|
|
66
|
+
status_class = f"{response.status // 100}xx"
|
|
67
|
+
return response
|
|
68
|
+
except web.HTTPException as exc:
|
|
69
|
+
status_class = f"{exc.status // 100}xx"
|
|
70
|
+
raise
|
|
71
|
+
finally:
|
|
72
|
+
duration = time.perf_counter() - start
|
|
73
|
+
self.bot_manager.server.metrics.bot_webhook_duration.record(
|
|
74
|
+
duration,
|
|
75
|
+
{"bot": bot_name, "status_class": status_class},
|
|
76
|
+
)
|
|
77
|
+
|
|
44
78
|
async def _handle_health(self, request: web.Request) -> web.Response:
|
|
45
79
|
return web.json_response({"status": "ok"})
|
|
46
80
|
|
|
@@ -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)
|