agentirc-cli 4.1.1__tar.gz → 4.1.2__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-4.1.1 → agentirc_cli-4.1.2}/CHANGELOG.md +7 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/PKG-INFO +1 -1
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/agent_runner.py +4 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/daemon.py +6 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/agent_runner.py +4 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/daemon.py +6 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/agent_runner.py +4 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/daemon.py +6 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/packages/agent-harness/daemon.py +9 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/pyproject.toml +1 -1
- agentirc_cli-4.1.2/tests/test_mention_target_cleanup.py +135 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/uv.lock +1 -1
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.flake8 +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.github/workflows/pages.yml +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.gitignore +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.pr_agent.toml +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/.pylintrc +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/CLAUDE.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/CNAME +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/Gemfile +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/Gemfile.lock +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/LICENSE +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/README.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/SECURITY.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/_config.yml +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/__main__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/bots/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/bots/bot.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/bots/bot_manager.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/bots/config.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/cli/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/cli/_helpers.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/cli/agent.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/cli/bot.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/cli/channel.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/cli/mesh.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/cli/server.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/cli/skills.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/config.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/irc_transport.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/config.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/daemon.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/irc_transport.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/config.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/irc_transport.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/config.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/irc_transport.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/console/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/console/app.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/console/client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/console/commands.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/credentials.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/learn_prompt.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/mesh_config.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/observer.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/overview/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/overview/collector.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/overview/model.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/overview/web/style.css +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/persistence.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/pidfile.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/protocol/commands.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/protocol/message.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/protocol/replies.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/__main__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/channel.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/config.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/ircd.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/remote_client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/room_store.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/rooms_util.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/server_link.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/skill.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/skills/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/skills/history.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/skills/icon.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/skills/rooms.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/skills/threads.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/server/thread_store.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/agent-lifecycle.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/agentic-self-learn.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/agent-client.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/harness-conformance.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/index.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/layer1-core-irc.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/layer2-attention.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/layer3-skills.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/layer4-federation.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/layer5-agent-harness.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/server-architecture.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/architecture/threads.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/channel-polling.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/acp/overview.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/codex/configuration.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/codex/overview.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/codex/setup.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/copilot/configuration.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/copilot/setup.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/culture-cli.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/getting-started.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/index.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/operations/SECURITY.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/operations/bots.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/operations/ci.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/operations/cli.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/operations/docs-site.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/operations/index.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/operations/ops-tooling.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/operations/overview.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/operations/publishing.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/rooms.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/server-rename.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/use-cases-index.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/docs/what-is-culture.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/packages/agent-harness/irc_transport.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/sonar-project.properties +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/__init__.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/conftest.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_bot.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_bot_config.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_channel.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_connection.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_console_client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_console_commands.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_console_connection.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_console_icons.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_console_integration.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_daemon.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_discovery.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_federation.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_history.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_http_listener.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_ipc.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_mentions.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_message.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_messaging.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_modes.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_overview_model.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_overview_web.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_persistence.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_pidfile.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_rooms.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_skill_client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_skills.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_socket_server.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_supervisor.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_template_engine.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_threads.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-4.1.1 → agentirc_cli-4.1.2}/tests/test_webhook.py +0 -0
|
@@ -4,6 +4,13 @@ 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
|
+
## [4.1.2] - 2026-04-06
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Clean up _mention_targets deque on prompt failure to prevent misrouted responses
|
|
13
|
+
|
|
7
14
|
## [4.1.1] - 2026-04-06
|
|
8
15
|
|
|
9
16
|
|
|
@@ -33,6 +33,7 @@ class ACPAgentRunner:
|
|
|
33
33
|
system_prompt: str = "",
|
|
34
34
|
on_exit: Callable[[int], Awaitable[None]] | None = None,
|
|
35
35
|
on_message: Callable[[dict[str, Any]], Awaitable[None]] | None = None,
|
|
36
|
+
on_turn_error: Callable[[], Awaitable[None]] | None = None,
|
|
36
37
|
) -> None:
|
|
37
38
|
self.model = model
|
|
38
39
|
self.directory = directory
|
|
@@ -40,6 +41,7 @@ class ACPAgentRunner:
|
|
|
40
41
|
self.system_prompt = system_prompt
|
|
41
42
|
self.on_exit = on_exit
|
|
42
43
|
self.on_message = on_message
|
|
44
|
+
self.on_turn_error = on_turn_error
|
|
43
45
|
|
|
44
46
|
self._isolated_home: str | None = None
|
|
45
47
|
self._process: asyncio.subprocess.Process | None = None
|
|
@@ -384,6 +386,8 @@ class ACPAgentRunner:
|
|
|
384
386
|
|
|
385
387
|
except Exception:
|
|
386
388
|
logger.exception("ACP turn error")
|
|
389
|
+
if self.on_turn_error:
|
|
390
|
+
await self.on_turn_error()
|
|
387
391
|
finally:
|
|
388
392
|
self._busy = False
|
|
389
393
|
|
|
@@ -318,6 +318,11 @@ class ACPDaemon:
|
|
|
318
318
|
# Agent runner helpers
|
|
319
319
|
# ------------------------------------------------------------------
|
|
320
320
|
|
|
321
|
+
async def _on_turn_error(self) -> None:
|
|
322
|
+
"""Clean up stale relay target when a prompt fails."""
|
|
323
|
+
if self._mention_targets:
|
|
324
|
+
self._mention_targets.popleft()
|
|
325
|
+
|
|
321
326
|
async def _start_agent_runner(self) -> None:
|
|
322
327
|
self._agent_runner = ACPAgentRunner(
|
|
323
328
|
model=self.agent.model,
|
|
@@ -326,6 +331,7 @@ class ACPDaemon:
|
|
|
326
331
|
system_prompt=self._build_system_prompt(),
|
|
327
332
|
on_exit=self._on_agent_exit,
|
|
328
333
|
on_message=self._on_agent_message,
|
|
334
|
+
on_turn_error=self._on_turn_error,
|
|
329
335
|
)
|
|
330
336
|
# Absorb the system prompt response without relaying to IRC
|
|
331
337
|
self._mention_targets.append(None)
|
|
@@ -23,12 +23,14 @@ class CodexAgentRunner:
|
|
|
23
23
|
system_prompt: str = "",
|
|
24
24
|
on_exit: Callable[[int], Awaitable[None]] | None = None,
|
|
25
25
|
on_message: Callable[[dict[str, Any]], Awaitable[None]] | None = None,
|
|
26
|
+
on_turn_error: Callable[[], Awaitable[None]] | None = None,
|
|
26
27
|
) -> None:
|
|
27
28
|
self.model = model
|
|
28
29
|
self.directory = directory
|
|
29
30
|
self.system_prompt = system_prompt
|
|
30
31
|
self.on_exit = on_exit
|
|
31
32
|
self.on_message = on_message
|
|
33
|
+
self.on_turn_error = on_turn_error
|
|
32
34
|
|
|
33
35
|
self._isolated_home: str | None = None
|
|
34
36
|
self._process: asyncio.subprocess.Process | None = None
|
|
@@ -318,6 +320,8 @@ class CodexAgentRunner:
|
|
|
318
320
|
|
|
319
321
|
except Exception:
|
|
320
322
|
logger.exception("Codex turn error")
|
|
323
|
+
if self.on_turn_error:
|
|
324
|
+
await self.on_turn_error()
|
|
321
325
|
|
|
322
326
|
except asyncio.CancelledError:
|
|
323
327
|
raise
|
|
@@ -293,6 +293,11 @@ class CodexDaemon:
|
|
|
293
293
|
# Agent runner helpers
|
|
294
294
|
# ------------------------------------------------------------------
|
|
295
295
|
|
|
296
|
+
async def _on_turn_error(self) -> None:
|
|
297
|
+
"""Clean up stale relay target when a prompt fails."""
|
|
298
|
+
if self._mention_targets:
|
|
299
|
+
self._mention_targets.popleft()
|
|
300
|
+
|
|
296
301
|
async def _start_agent_runner(self) -> None:
|
|
297
302
|
self._agent_runner = CodexAgentRunner(
|
|
298
303
|
model=self.agent.model,
|
|
@@ -300,6 +305,7 @@ class CodexDaemon:
|
|
|
300
305
|
system_prompt=self._build_system_prompt(),
|
|
301
306
|
on_exit=self._on_agent_exit,
|
|
302
307
|
on_message=self._on_agent_message,
|
|
308
|
+
on_turn_error=self._on_turn_error,
|
|
303
309
|
)
|
|
304
310
|
await self._agent_runner.start()
|
|
305
311
|
logger.info("CodexAgentRunner started for %s", self.agent.nick)
|
|
@@ -23,6 +23,7 @@ class CopilotAgentRunner:
|
|
|
23
23
|
skill_directories: list[str] | None = None,
|
|
24
24
|
on_exit: Callable[[int], Awaitable[None]] | None = None,
|
|
25
25
|
on_message: Callable[[dict[str, Any]], Awaitable[None]] | None = None,
|
|
26
|
+
on_turn_error: Callable[[], Awaitable[None]] | None = None,
|
|
26
27
|
) -> None:
|
|
27
28
|
self.model = model
|
|
28
29
|
self.directory = directory
|
|
@@ -30,6 +31,7 @@ class CopilotAgentRunner:
|
|
|
30
31
|
self.skill_directories = skill_directories or []
|
|
31
32
|
self.on_exit = on_exit
|
|
32
33
|
self.on_message = on_message
|
|
34
|
+
self.on_turn_error = on_turn_error
|
|
33
35
|
|
|
34
36
|
self._isolated_home: str | None = None
|
|
35
37
|
self._client: Any = None
|
|
@@ -158,6 +160,8 @@ class CopilotAgentRunner:
|
|
|
158
160
|
|
|
159
161
|
except Exception:
|
|
160
162
|
logger.exception("Copilot session turn error")
|
|
163
|
+
if self.on_turn_error:
|
|
164
|
+
await self.on_turn_error()
|
|
161
165
|
if not self._stopping:
|
|
162
166
|
self._running = False
|
|
163
167
|
if self.on_exit:
|
|
@@ -293,6 +293,11 @@ class CopilotDaemon:
|
|
|
293
293
|
# Agent runner helpers
|
|
294
294
|
# ------------------------------------------------------------------
|
|
295
295
|
|
|
296
|
+
async def _on_turn_error(self) -> None:
|
|
297
|
+
"""Clean up stale relay target when a prompt fails."""
|
|
298
|
+
if self._mention_targets:
|
|
299
|
+
self._mention_targets.popleft()
|
|
300
|
+
|
|
296
301
|
async def _start_agent_runner(self) -> None:
|
|
297
302
|
# Resolve installed skill path for the Copilot session
|
|
298
303
|
skill_dirs: list[str] = []
|
|
@@ -307,6 +312,7 @@ class CopilotDaemon:
|
|
|
307
312
|
skill_directories=skill_dirs,
|
|
308
313
|
on_exit=self._on_agent_exit,
|
|
309
314
|
on_message=self._on_agent_message,
|
|
315
|
+
on_turn_error=self._on_turn_error,
|
|
310
316
|
)
|
|
311
317
|
await self._agent_runner.start()
|
|
312
318
|
logger.info("CopilotAgentRunner started for %s", self.agent.nick)
|
|
@@ -258,6 +258,15 @@ class AgentDaemon:
|
|
|
258
258
|
except Exception:
|
|
259
259
|
logger.exception("Poll loop error")
|
|
260
260
|
|
|
261
|
+
async def _on_turn_error(self) -> None:
|
|
262
|
+
"""Clean up stale relay target when a prompt fails.
|
|
263
|
+
|
|
264
|
+
Wire this as the ``on_turn_error`` callback on your agent runner so
|
|
265
|
+
the ``_mention_targets`` deque stays in sync with the prompt queue.
|
|
266
|
+
"""
|
|
267
|
+
if self._mention_targets:
|
|
268
|
+
self._mention_targets.popleft()
|
|
269
|
+
|
|
261
270
|
def _on_mention(self, target: str, sender: str, text: str) -> None:
|
|
262
271
|
"""Called when the agent is @mentioned. Sends prompt to runner.
|
|
263
272
|
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Tests for _mention_targets deque cleanup on prompt failure.
|
|
2
|
+
|
|
3
|
+
When a prompt fails (timeout, error), the corresponding _mention_targets
|
|
4
|
+
entry must be cleaned up so that future responses route correctly.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import asyncio
|
|
8
|
+
import tempfile
|
|
9
|
+
from unittest.mock import AsyncMock, MagicMock
|
|
10
|
+
|
|
11
|
+
import pytest
|
|
12
|
+
|
|
13
|
+
from culture.clients.acp.config import (
|
|
14
|
+
AgentConfig,
|
|
15
|
+
DaemonConfig,
|
|
16
|
+
ServerConnConfig,
|
|
17
|
+
)
|
|
18
|
+
from culture.clients.acp.daemon import ACPDaemon
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _make_daemon(server_port: int) -> ACPDaemon:
|
|
22
|
+
config = DaemonConfig(
|
|
23
|
+
server=ServerConnConfig(host="127.0.0.1", port=server_port),
|
|
24
|
+
poll_interval=0,
|
|
25
|
+
)
|
|
26
|
+
agent = AgentConfig(
|
|
27
|
+
nick="testserv-bot",
|
|
28
|
+
directory="/tmp",
|
|
29
|
+
channels=["#general"],
|
|
30
|
+
acp_command=["echo"],
|
|
31
|
+
)
|
|
32
|
+
sock_dir = tempfile.mkdtemp()
|
|
33
|
+
return ACPDaemon(config, agent, socket_dir=sock_dir, skip_agent=True)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _inject_fake_runner(daemon):
|
|
37
|
+
"""Inject a fake agent runner that records prompts."""
|
|
38
|
+
runner = MagicMock()
|
|
39
|
+
runner.is_running.return_value = True
|
|
40
|
+
runner.send_prompt = AsyncMock()
|
|
41
|
+
runner.stop = AsyncMock()
|
|
42
|
+
daemon._agent_runner = runner
|
|
43
|
+
return runner
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@pytest.mark.asyncio
|
|
47
|
+
async def test_on_turn_error_pops_stale_target(server):
|
|
48
|
+
"""_on_turn_error should pop the front entry from _mention_targets."""
|
|
49
|
+
daemon = _make_daemon(server.config.port)
|
|
50
|
+
await daemon.start()
|
|
51
|
+
|
|
52
|
+
# Simulate: poll enqueued a target, then the prompt failed
|
|
53
|
+
daemon._mention_targets.append("#general")
|
|
54
|
+
daemon._mention_targets.append("#code-review")
|
|
55
|
+
assert len(daemon._mention_targets) == 2
|
|
56
|
+
|
|
57
|
+
await daemon._on_turn_error()
|
|
58
|
+
assert len(daemon._mention_targets) == 1
|
|
59
|
+
assert daemon._mention_targets[0] == "#code-review"
|
|
60
|
+
|
|
61
|
+
await daemon.stop()
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@pytest.mark.asyncio
|
|
65
|
+
async def test_on_turn_error_empty_deque_is_safe(server):
|
|
66
|
+
"""_on_turn_error should be a no-op on an empty deque."""
|
|
67
|
+
daemon = _make_daemon(server.config.port)
|
|
68
|
+
await daemon.start()
|
|
69
|
+
|
|
70
|
+
assert len(daemon._mention_targets) == 0
|
|
71
|
+
await daemon._on_turn_error() # should not raise
|
|
72
|
+
assert len(daemon._mention_targets) == 0
|
|
73
|
+
|
|
74
|
+
await daemon.stop()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@pytest.mark.asyncio
|
|
78
|
+
async def test_relay_routes_correctly_after_error_cleanup(server, make_client):
|
|
79
|
+
"""After a failed prompt is cleaned up, the next response should route correctly."""
|
|
80
|
+
daemon = _make_daemon(server.config.port)
|
|
81
|
+
await daemon.start()
|
|
82
|
+
_inject_fake_runner(daemon)
|
|
83
|
+
await asyncio.sleep(0.5)
|
|
84
|
+
|
|
85
|
+
# Simulate: system prompt enqueued None, then timed out and was cleaned up
|
|
86
|
+
daemon._mention_targets.append(None)
|
|
87
|
+
await daemon._on_turn_error() # cleans up None
|
|
88
|
+
|
|
89
|
+
# Now simulate a real mention that succeeds
|
|
90
|
+
daemon._mention_targets.append("#general")
|
|
91
|
+
|
|
92
|
+
# Simulate agent response
|
|
93
|
+
sent_messages = []
|
|
94
|
+
original_send = daemon._transport.send_privmsg
|
|
95
|
+
|
|
96
|
+
async def capture_send(target, text):
|
|
97
|
+
sent_messages.append((target, text))
|
|
98
|
+
await original_send(target, text)
|
|
99
|
+
|
|
100
|
+
daemon._transport.send_privmsg = capture_send
|
|
101
|
+
|
|
102
|
+
msg = {
|
|
103
|
+
"type": "assistant",
|
|
104
|
+
"content": [{"type": "text", "text": "Hello from bot!"}],
|
|
105
|
+
}
|
|
106
|
+
await daemon._relay_response_to_irc(msg)
|
|
107
|
+
|
|
108
|
+
assert len(sent_messages) == 1
|
|
109
|
+
assert sent_messages[0][0] == "#general"
|
|
110
|
+
assert "Hello from bot!" in sent_messages[0][1]
|
|
111
|
+
assert len(daemon._mention_targets) == 0
|
|
112
|
+
|
|
113
|
+
await daemon.stop()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
@pytest.mark.asyncio
|
|
117
|
+
async def test_multiple_errors_drain_deque_correctly(server):
|
|
118
|
+
"""Multiple consecutive errors should each pop one entry."""
|
|
119
|
+
daemon = _make_daemon(server.config.port)
|
|
120
|
+
await daemon.start()
|
|
121
|
+
|
|
122
|
+
# Simulate 3 failed prompts
|
|
123
|
+
daemon._mention_targets.append(None) # system prompt
|
|
124
|
+
daemon._mention_targets.append("#general") # poll 1
|
|
125
|
+
daemon._mention_targets.append("#general") # poll 2
|
|
126
|
+
|
|
127
|
+
await daemon._on_turn_error() # pops None
|
|
128
|
+
await daemon._on_turn_error() # pops #general
|
|
129
|
+
assert len(daemon._mention_targets) == 1
|
|
130
|
+
assert daemon._mention_targets[0] == "#general"
|
|
131
|
+
|
|
132
|
+
await daemon._on_turn_error() # pops last #general
|
|
133
|
+
assert len(daemon._mention_targets) == 0
|
|
134
|
+
|
|
135
|
+
await daemon.stop()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|