agentirc-cli 4.4.1__tar.gz → 4.4.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.4.1 → agentirc_cli-4.4.2}/CHANGELOG.md +13 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/CLAUDE.md +1 -1
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/PKG-INFO +5 -5
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/README.md +4 -4
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/daemon.py +48 -5
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/daemon.py +17 -2
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/agent_runner.py +21 -7
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/daemon.py +48 -5
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/agent_runner.py +5 -3
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/daemon.py +48 -5
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/channel-polling.md +1 -1
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/acp/overview.md +2 -1
- agentirc_cli-4.4.2/docs/clients/acp/system-prompt.md +183 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/codex/configuration.md +4 -4
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/codex/overview.md +3 -2
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/codex/setup.md +2 -2
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/copilot/configuration.md +9 -8
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/copilot/setup.md +1 -1
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/index.md +3 -3
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +5 -5
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +1 -1
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +3 -3
- agentirc_cli-4.4.2/docs/superpowers/specs/2026-04-07-reflective-development-reframe-design.md +165 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/packages/agent-harness/daemon.py +39 -5
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/pyproject.toml +1 -1
- agentirc_cli-4.4.2/tests/test_codex_daemon.py +252 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_copilot_daemon.py +106 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_mention_target_cleanup.py +6 -6
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/uv.lock +1 -1
- agentirc_cli-4.4.1/tests/test_codex_daemon.py +0 -96
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.flake8 +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.github/workflows/pages.yml +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.gitignore +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.pr_agent.toml +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/.pylintrc +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/CNAME +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/Gemfile +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/Gemfile.lock +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/LICENSE +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/SECURITY.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/_config.yml +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/__main__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/aio.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/bots/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/bots/bot.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/bots/bot_manager.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/bots/config.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/agent.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/bot.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/channel.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/mesh.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/server.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/shared/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/shared/constants.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/shared/display.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/shared/formatting.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/shared/ipc.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/shared/mesh.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/shared/process.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/cli/skills.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/agent_runner.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/config.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/irc_transport.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/config.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/irc_transport.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/config.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/irc_transport.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/config.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/irc_transport.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/console/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/console/app.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/console/client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/console/commands.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/credentials.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/formatting.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/learn_prompt.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/mesh_config.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/observer.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/overview/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/overview/collector.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/overview/model.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/overview/web/style.css +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/persistence.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/pidfile.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/protocol/commands.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/protocol/message.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/protocol/replies.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/__main__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/channel.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/config.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/history_store.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/ircd.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/remote_client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/room_store.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/rooms_util.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/server_link.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/skill.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/skills/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/skills/history.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/skills/icon.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/skills/rooms.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/skills/threads.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/server/thread_store.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/agent-lifecycle.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/agentic-self-learn.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/agent-client.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/harness-conformance.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/index.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/layer1-core-irc.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/layer2-attention.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/layer3-skills.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/layer4-federation.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/layer5-agent-harness.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/server-architecture.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/architecture/threads.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/culture-cli.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/getting-started.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/operations/SECURITY.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/operations/bots.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/operations/ci.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/operations/cli.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/operations/docs-site.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/operations/index.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/operations/ops-tooling.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/operations/overview.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/operations/publishing.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/persistent-history.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/rooms.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/server-rename.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/use-cases-index.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/docs/what-is-culture.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/packages/agent-harness/irc_transport.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/sonar-project.properties +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/__init__.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/conftest.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_archive.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_bot.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_bot_config.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_channel.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_connection.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_console_client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_console_commands.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_console_connection.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_console_icons.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_console_integration.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_daemon.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_discovery.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_federation.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_history.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_http_listener.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_ipc.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_mentions.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_message.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_messaging.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_modes.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_overview_model.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_overview_web.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_persistence.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_pidfile.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_rooms.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_skill_client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_skills.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_socket_server.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_supervisor.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_template_engine.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_threads.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-4.4.1 → agentirc_cli-4.4.2}/tests/test_webhook.py +0 -0
|
@@ -4,6 +4,19 @@ 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.4.2] - 2026-04-08
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Codex/copilot: preserve HOME for auth tokens instead of isolating (#159)
|
|
13
|
+
- Codex: fix turn sync race condition causing concatenated rapid-mention responses (#165)
|
|
14
|
+
- All backends: sleep scheduler no longer overrides manual pause (#162)
|
|
15
|
+
- All backends: poll loop filters @mention messages to prevent duplicate responses (#160)
|
|
16
|
+
- All backends: turn errors now send feedback to IRC channel (#163)
|
|
17
|
+
- All backends: consecutive turn failure circuit breaker pauses agent after 3 failures (#164)
|
|
18
|
+
- Status query response verified not leaking to IRC channel (#161)
|
|
19
|
+
|
|
7
20
|
## [4.4.1] - 2026-04-07
|
|
8
21
|
|
|
9
22
|
|
|
@@ -11,7 +11,7 @@ Design spec: `docs/superpowers/specs/2026-03-19-agentirc-design.md`
|
|
|
11
11
|
## Package Management
|
|
12
12
|
|
|
13
13
|
- **External packages:** Managed in `pyproject.toml`, installed with `uv`
|
|
14
|
-
- **Internal packages:** Written in `packages/` folder. Internal packages are NOT installed as dependencies — they are
|
|
14
|
+
- **Internal packages:** Written in `packages/` folder. Internal packages are NOT installed as dependencies — they are reflected into target projects as native code, placed in the correct folder and location as if written directly in the target project.
|
|
15
15
|
|
|
16
16
|
## Assimilai Pattern
|
|
17
17
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentirc-cli
|
|
3
|
-
Version: 4.4.
|
|
3
|
+
Version: 4.4.2
|
|
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
|
|
@@ -60,7 +60,7 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
60
60
|
|
|
61
61
|
| | |
|
|
62
62
|
|---|---|
|
|
63
|
-
| 🎓 **
|
|
63
|
+
| 🎓 **Reflective Lifecycle** | Introduce → Educate → Join → Mentor → Promote. Members develop through real work, not configuration. |
|
|
64
64
|
| 🌐 **Connected Worlds** | Link cultures across machines. Members see each other without a central controller. |
|
|
65
65
|
| 🧭 **Mentorship** | A guide watches for drift, spiraling, and stalling — whispers corrections when needed. |
|
|
66
66
|
| 🤝 **Open Membership** | Claude, Codex, Copilot, or any ACP agent. All are welcome. |
|
|
@@ -84,7 +84,7 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
84
84
|
| **Spiraling detection** | AI supervisor reads conversation meaning | Retry limits + escalation timeouts | Retry limits + fallback agents |
|
|
85
85
|
| **Observability** | Live web dashboard + any IRC client | Web dashboard + Slack/Discord/webhook alerts | CLI commands (metrics partially mocked) |
|
|
86
86
|
| **Self-organization** | Tag-driven room membership | Orchestrator assigns issues to workers | ML-based routing with learning pipeline |
|
|
87
|
-
| **Philosophy** | Simple,
|
|
87
|
+
| **Philosophy** | Simple, reflective, transparent | Parallel coding coordinator — isolation via worktrees | Enterprise-complex (130+ skills, vector DB, Q-learning) |
|
|
88
88
|
|
|
89
89
|
---
|
|
90
90
|
|
|
@@ -138,9 +138,9 @@ Members on any machine see each other in `#general`. @mentions cross boundaries.
|
|
|
138
138
|
|
|
139
139
|
---
|
|
140
140
|
|
|
141
|
-
##
|
|
141
|
+
## Reflective Development
|
|
142
142
|
|
|
143
|
-
Culture follows the **
|
|
143
|
+
Culture follows the **Reflective Development** paradigm — agents develop by reflecting on real work, not by configuration. Documentation flows back as context. Code reflects from reference to implementation. The lifecycle is continuous, not graduated:
|
|
144
144
|
|
|
145
145
|
👋 **Introduce** → 🎓 **Educate** → 🤝 **Join** → 🧭 **Mentor** → ⭐ **Promote**
|
|
146
146
|
|
|
@@ -36,7 +36,7 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
36
36
|
|
|
37
37
|
| | |
|
|
38
38
|
|---|---|
|
|
39
|
-
| 🎓 **
|
|
39
|
+
| 🎓 **Reflective Lifecycle** | Introduce → Educate → Join → Mentor → Promote. Members develop through real work, not configuration. |
|
|
40
40
|
| 🌐 **Connected Worlds** | Link cultures across machines. Members see each other without a central controller. |
|
|
41
41
|
| 🧭 **Mentorship** | A guide watches for drift, spiraling, and stalling — whispers corrections when needed. |
|
|
42
42
|
| 🤝 **Open Membership** | Claude, Codex, Copilot, or any ACP agent. All are welcome. |
|
|
@@ -60,7 +60,7 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
60
60
|
| **Spiraling detection** | AI supervisor reads conversation meaning | Retry limits + escalation timeouts | Retry limits + fallback agents |
|
|
61
61
|
| **Observability** | Live web dashboard + any IRC client | Web dashboard + Slack/Discord/webhook alerts | CLI commands (metrics partially mocked) |
|
|
62
62
|
| **Self-organization** | Tag-driven room membership | Orchestrator assigns issues to workers | ML-based routing with learning pipeline |
|
|
63
|
-
| **Philosophy** | Simple,
|
|
63
|
+
| **Philosophy** | Simple, reflective, transparent | Parallel coding coordinator — isolation via worktrees | Enterprise-complex (130+ skills, vector DB, Q-learning) |
|
|
64
64
|
|
|
65
65
|
---
|
|
66
66
|
|
|
@@ -114,9 +114,9 @@ Members on any machine see each other in `#general`. @mentions cross boundaries.
|
|
|
114
114
|
|
|
115
115
|
---
|
|
116
116
|
|
|
117
|
-
##
|
|
117
|
+
## Reflective Development
|
|
118
118
|
|
|
119
|
-
Culture follows the **
|
|
119
|
+
Culture follows the **Reflective Development** paradigm — agents develop by reflecting on real work, not by configuration. Documentation flows back as context. Code reflects from reference to implementation. The lifecycle is continuous, not graduated:
|
|
120
120
|
|
|
121
121
|
👋 **Introduce** → 🎓 **Educate** → 🤝 **Join** → 🧭 **Mentor** → ⭐ **Promote**
|
|
122
122
|
|
|
@@ -13,6 +13,7 @@ import asyncio
|
|
|
13
13
|
import datetime
|
|
14
14
|
import logging
|
|
15
15
|
import os
|
|
16
|
+
import re
|
|
16
17
|
import time
|
|
17
18
|
from collections import deque
|
|
18
19
|
|
|
@@ -37,6 +38,7 @@ _ERR_MISSING_CHANNEL_THREAD_MSG = "Missing 'channel', 'thread', or 'message'"
|
|
|
37
38
|
MAX_CRASH_COUNT = 3
|
|
38
39
|
CRASH_WINDOW_SECONDS = 300
|
|
39
40
|
CRASH_RESTART_DELAY = 5
|
|
41
|
+
MAX_CONSECUTIVE_TURN_FAILURES = 3
|
|
40
42
|
|
|
41
43
|
|
|
42
44
|
class ACPDaemon:
|
|
@@ -74,9 +76,11 @@ class ACPDaemon:
|
|
|
74
76
|
# Crash-recovery state
|
|
75
77
|
self._crash_times: list[float] = []
|
|
76
78
|
self._circuit_open = False
|
|
79
|
+
self._consecutive_turn_failures: int = 0
|
|
77
80
|
|
|
78
81
|
# Pause/sleep state
|
|
79
82
|
self._paused: bool = False
|
|
83
|
+
self._manually_paused: bool = False
|
|
80
84
|
self._last_activation: float | None = None
|
|
81
85
|
|
|
82
86
|
# Status query state — for asking the agent what it's doing
|
|
@@ -270,7 +274,7 @@ class ACPDaemon:
|
|
|
270
274
|
if should_sleep and not self._paused:
|
|
271
275
|
self._paused = True
|
|
272
276
|
logger.info("Sleep schedule: pausing %s", self.agent.nick)
|
|
273
|
-
elif not should_sleep and self._paused:
|
|
277
|
+
elif not should_sleep and self._paused and not self._manually_paused:
|
|
274
278
|
self._paused = False
|
|
275
279
|
logger.info("Sleep schedule: resuming %s", self.agent.nick)
|
|
276
280
|
except asyncio.CancelledError:
|
|
@@ -300,6 +304,17 @@ class ACPDaemon:
|
|
|
300
304
|
|
|
301
305
|
def _send_channel_poll(self, channel) -> None:
|
|
302
306
|
msgs = self._buffer.read(channel)
|
|
307
|
+
if not msgs:
|
|
308
|
+
return
|
|
309
|
+
# Filter out messages that @mention this agent (already handled by _on_mention)
|
|
310
|
+
nick = self.agent.nick
|
|
311
|
+
short = nick.split("-", 1)[1] if "-" in nick else None
|
|
312
|
+
msgs = [
|
|
313
|
+
m
|
|
314
|
+
for m in msgs
|
|
315
|
+
if not re.search(rf"@{re.escape(nick)}\b", m.text)
|
|
316
|
+
and not (short and re.search(rf"@{re.escape(short)}\b", m.text))
|
|
317
|
+
]
|
|
303
318
|
if not msgs:
|
|
304
319
|
return
|
|
305
320
|
lines = "\n".join(f" <{m.nick}> {m.text}" for m in msgs)
|
|
@@ -330,10 +345,35 @@ class ACPDaemon:
|
|
|
330
345
|
# Agent runner helpers
|
|
331
346
|
# ------------------------------------------------------------------
|
|
332
347
|
|
|
333
|
-
def _on_turn_error(self) -> None:
|
|
334
|
-
"""
|
|
348
|
+
async def _on_turn_error(self) -> None:
|
|
349
|
+
"""Send error feedback to IRC and clean up stale relay target."""
|
|
335
350
|
if self._mention_targets:
|
|
336
|
-
self._mention_targets.popleft()
|
|
351
|
+
relay_target = self._mention_targets.popleft()
|
|
352
|
+
if self._transport and relay_target:
|
|
353
|
+
await self._transport.send_privmsg(
|
|
354
|
+
relay_target,
|
|
355
|
+
"Sorry, I encountered an error processing your request.",
|
|
356
|
+
)
|
|
357
|
+
self._consecutive_turn_failures += 1
|
|
358
|
+
if self._consecutive_turn_failures >= MAX_CONSECUTIVE_TURN_FAILURES:
|
|
359
|
+
self._paused = True
|
|
360
|
+
self._manually_paused = True
|
|
361
|
+
logger.error(
|
|
362
|
+
"Agent %s paused after %d consecutive turn failures",
|
|
363
|
+
self.agent.nick,
|
|
364
|
+
self._consecutive_turn_failures,
|
|
365
|
+
)
|
|
366
|
+
if self._webhook:
|
|
367
|
+
await self._webhook.fire(
|
|
368
|
+
AlertEvent(
|
|
369
|
+
event_type="agent_spiraling",
|
|
370
|
+
nick=self.agent.nick,
|
|
371
|
+
message=(
|
|
372
|
+
f"Agent {self.agent.nick} paused after "
|
|
373
|
+
f"{self._consecutive_turn_failures} consecutive turn failures."
|
|
374
|
+
),
|
|
375
|
+
)
|
|
376
|
+
)
|
|
337
377
|
|
|
338
378
|
async def _start_agent_runner(self) -> None:
|
|
339
379
|
self._agent_runner = ACPAgentRunner(
|
|
@@ -475,6 +515,7 @@ class ACPDaemon:
|
|
|
475
515
|
|
|
476
516
|
async def _on_agent_message(self, msg: dict) -> None:
|
|
477
517
|
"""Relay agent text to IRC and feed to supervisor."""
|
|
518
|
+
self._consecutive_turn_failures = 0
|
|
478
519
|
await self._relay_response_to_irc(msg)
|
|
479
520
|
|
|
480
521
|
if self._supervisor:
|
|
@@ -621,11 +662,13 @@ class ACPDaemon:
|
|
|
621
662
|
|
|
622
663
|
def _ipc_pause(self, req_id: str, msg: dict) -> dict:
|
|
623
664
|
self._paused = True
|
|
624
|
-
|
|
665
|
+
self._manually_paused = True
|
|
666
|
+
logger.info("Agent %s paused (manual)", self.agent.nick)
|
|
625
667
|
return make_response(req_id, ok=True)
|
|
626
668
|
|
|
627
669
|
def _ipc_resume(self, req_id: str, msg: dict) -> dict:
|
|
628
670
|
self._paused = False
|
|
671
|
+
self._manually_paused = False
|
|
629
672
|
logger.info("Agent %s resumed", self.agent.nick)
|
|
630
673
|
# NOTE: Catch-up on missed messages is not yet implemented.
|
|
631
674
|
# IRCTransport does not process HISTORY responses into the buffer.
|
|
@@ -4,6 +4,7 @@ import asyncio
|
|
|
4
4
|
import datetime
|
|
5
5
|
import logging
|
|
6
6
|
import os
|
|
7
|
+
import re
|
|
7
8
|
import time
|
|
8
9
|
|
|
9
10
|
from culture.aio import maybe_await
|
|
@@ -62,6 +63,7 @@ class AgentDaemon:
|
|
|
62
63
|
|
|
63
64
|
# Pause/sleep state
|
|
64
65
|
self._paused: bool = False
|
|
66
|
+
self._manually_paused: bool = False
|
|
65
67
|
self._last_activation: float | None = None
|
|
66
68
|
|
|
67
69
|
# Status query state — for asking the agent what it's doing
|
|
@@ -236,7 +238,7 @@ class AgentDaemon:
|
|
|
236
238
|
if should_sleep and not self._paused:
|
|
237
239
|
self._paused = True
|
|
238
240
|
logger.info("Sleep schedule: pausing %s", self.agent.nick)
|
|
239
|
-
elif not should_sleep and self._paused:
|
|
241
|
+
elif not should_sleep and self._paused and not self._manually_paused:
|
|
240
242
|
self._paused = False
|
|
241
243
|
logger.info("Sleep schedule: resuming %s", self.agent.nick)
|
|
242
244
|
except asyncio.CancelledError:
|
|
@@ -256,6 +258,17 @@ class AgentDaemon:
|
|
|
256
258
|
continue
|
|
257
259
|
for channel in self.agent.channels:
|
|
258
260
|
msgs = self._buffer.read(channel)
|
|
261
|
+
if not msgs:
|
|
262
|
+
continue
|
|
263
|
+
# Filter out messages that @mention this agent (already handled)
|
|
264
|
+
nick = self.agent.nick
|
|
265
|
+
short = nick.split("-", 1)[1] if "-" in nick else None
|
|
266
|
+
msgs = [
|
|
267
|
+
m
|
|
268
|
+
for m in msgs
|
|
269
|
+
if not re.search(rf"@{re.escape(nick)}\b", m.text)
|
|
270
|
+
and not (short and re.search(rf"@{re.escape(short)}\b", m.text))
|
|
271
|
+
]
|
|
259
272
|
if not msgs:
|
|
260
273
|
continue
|
|
261
274
|
lines = "\n".join(f" <{m.nick}> {m.text}" for m in msgs)
|
|
@@ -542,11 +555,13 @@ class AgentDaemon:
|
|
|
542
555
|
|
|
543
556
|
def _ipc_pause(self, req_id: str, msg: dict) -> dict:
|
|
544
557
|
self._paused = True
|
|
545
|
-
|
|
558
|
+
self._manually_paused = True
|
|
559
|
+
logger.info("Agent %s paused (manual)", self.agent.nick)
|
|
546
560
|
return make_response(req_id, ok=True)
|
|
547
561
|
|
|
548
562
|
def _ipc_resume(self, req_id: str, msg: dict) -> dict:
|
|
549
563
|
self._paused = False
|
|
564
|
+
self._manually_paused = False
|
|
550
565
|
logger.info("Agent %s resumed", self.agent.nick)
|
|
551
566
|
# NOTE: Catch-up on missed messages is not yet implemented.
|
|
552
567
|
# IRCTransport does not process HISTORY responses into the buffer.
|
|
@@ -46,6 +46,8 @@ class CodexAgentRunner:
|
|
|
46
46
|
self._request_id = 0
|
|
47
47
|
self._pending: dict[int, asyncio.Future] = {}
|
|
48
48
|
self._accumulated_text = ""
|
|
49
|
+
self._turn_done: asyncio.Event = asyncio.Event()
|
|
50
|
+
self._turn_done.set() # Initially not busy
|
|
49
51
|
|
|
50
52
|
def is_running(self) -> bool:
|
|
51
53
|
return self._running
|
|
@@ -58,12 +60,12 @@ class CodexAgentRunner:
|
|
|
58
60
|
"""Start codex app-server as a subprocess and initialize a thread."""
|
|
59
61
|
self._stopping = False
|
|
60
62
|
|
|
61
|
-
# Isolate
|
|
63
|
+
# Isolate data/state dirs to prevent session interference, but
|
|
64
|
+
# preserve HOME and XDG_CONFIG_HOME so codex finds auth tokens.
|
|
62
65
|
self._isolated_home = tempfile.mkdtemp(prefix="culture-codex-")
|
|
63
66
|
isolated_env = dict(os.environ)
|
|
64
|
-
isolated_env["
|
|
65
|
-
isolated_env.
|
|
66
|
-
isolated_env.pop("XDG_CONFIG_HOME", None)
|
|
67
|
+
isolated_env["XDG_DATA_HOME"] = os.path.join(self._isolated_home, ".local", "share")
|
|
68
|
+
isolated_env["XDG_STATE_HOME"] = os.path.join(self._isolated_home, ".local", "state")
|
|
67
69
|
|
|
68
70
|
try:
|
|
69
71
|
# Spawn codex app-server in stdio mode
|
|
@@ -298,12 +300,17 @@ class CodexAgentRunner:
|
|
|
298
300
|
elif method == "turn/completed":
|
|
299
301
|
self._busy = False
|
|
300
302
|
await self._flush_accumulated_text()
|
|
303
|
+
self._turn_done.set()
|
|
301
304
|
|
|
302
305
|
elif method in self._APPROVAL_METHODS:
|
|
303
306
|
await self._auto_approve(msg)
|
|
304
307
|
|
|
305
308
|
elif method == "error":
|
|
306
309
|
logger.error("Codex error: %s", params)
|
|
310
|
+
self._busy = False
|
|
311
|
+
self._turn_done.set()
|
|
312
|
+
if self.on_turn_error:
|
|
313
|
+
await maybe_await(self.on_turn_error())
|
|
307
314
|
|
|
308
315
|
async def _flush_accumulated_text(self) -> None:
|
|
309
316
|
"""Fire on_message with any accumulated text and reset the buffer."""
|
|
@@ -328,6 +335,7 @@ class CodexAgentRunner:
|
|
|
328
335
|
|
|
329
336
|
async def _execute_single_turn(self, text: str) -> None:
|
|
330
337
|
"""Send one turn request and wait for completion."""
|
|
338
|
+
self._turn_done.clear()
|
|
331
339
|
try:
|
|
332
340
|
await self._send_request(
|
|
333
341
|
"turn/start",
|
|
@@ -336,11 +344,17 @@ class CodexAgentRunner:
|
|
|
336
344
|
"input": [{"type": "text", "text": text}],
|
|
337
345
|
},
|
|
338
346
|
)
|
|
339
|
-
# Wait for turn
|
|
340
|
-
|
|
341
|
-
await
|
|
347
|
+
# Wait for turn/completed notification via the event
|
|
348
|
+
async with asyncio.timeout(300):
|
|
349
|
+
await self._turn_done.wait()
|
|
350
|
+
except asyncio.TimeoutError:
|
|
351
|
+
logger.warning("Codex turn timed out after 300s")
|
|
352
|
+
self._turn_done.set()
|
|
353
|
+
if self.on_turn_error:
|
|
354
|
+
await maybe_await(self.on_turn_error())
|
|
342
355
|
except Exception:
|
|
343
356
|
logger.exception("Codex turn error")
|
|
357
|
+
self._turn_done.set()
|
|
344
358
|
if self.on_turn_error:
|
|
345
359
|
await maybe_await(self.on_turn_error())
|
|
346
360
|
|
|
@@ -10,6 +10,7 @@ import asyncio
|
|
|
10
10
|
import datetime
|
|
11
11
|
import logging
|
|
12
12
|
import os
|
|
13
|
+
import re
|
|
13
14
|
import time
|
|
14
15
|
from collections import deque
|
|
15
16
|
|
|
@@ -34,6 +35,7 @@ _ERR_MISSING_CHANNEL_THREAD_MSG = "Missing 'channel', 'thread', or 'message'"
|
|
|
34
35
|
MAX_CRASH_COUNT = 3
|
|
35
36
|
CRASH_WINDOW_SECONDS = 300
|
|
36
37
|
CRASH_RESTART_DELAY = 5
|
|
38
|
+
MAX_CONSECUTIVE_TURN_FAILURES = 3
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
class CodexDaemon:
|
|
@@ -71,9 +73,11 @@ class CodexDaemon:
|
|
|
71
73
|
# Crash-recovery state
|
|
72
74
|
self._crash_times: list[float] = []
|
|
73
75
|
self._circuit_open = False
|
|
76
|
+
self._consecutive_turn_failures: int = 0
|
|
74
77
|
|
|
75
78
|
# Pause/sleep state
|
|
76
79
|
self._paused: bool = False
|
|
80
|
+
self._manually_paused: bool = False
|
|
77
81
|
self._last_activation: float | None = None
|
|
78
82
|
|
|
79
83
|
# Status query state — for asking the agent what it's doing
|
|
@@ -245,7 +249,7 @@ class CodexDaemon:
|
|
|
245
249
|
if should_sleep and not self._paused:
|
|
246
250
|
self._paused = True
|
|
247
251
|
logger.info("Sleep schedule: pausing %s", self.agent.nick)
|
|
248
|
-
elif not should_sleep and self._paused:
|
|
252
|
+
elif not should_sleep and self._paused and not self._manually_paused:
|
|
249
253
|
self._paused = False
|
|
250
254
|
logger.info("Sleep schedule: resuming %s", self.agent.nick)
|
|
251
255
|
except asyncio.CancelledError:
|
|
@@ -275,6 +279,17 @@ class CodexDaemon:
|
|
|
275
279
|
|
|
276
280
|
def _send_channel_poll(self, channel) -> None:
|
|
277
281
|
msgs = self._buffer.read(channel)
|
|
282
|
+
if not msgs:
|
|
283
|
+
return
|
|
284
|
+
# Filter out messages that @mention this agent (already handled by _on_mention)
|
|
285
|
+
nick = self.agent.nick
|
|
286
|
+
short = nick.split("-", 1)[1] if "-" in nick else None
|
|
287
|
+
msgs = [
|
|
288
|
+
m
|
|
289
|
+
for m in msgs
|
|
290
|
+
if not re.search(rf"@{re.escape(nick)}\b", m.text)
|
|
291
|
+
and not (short and re.search(rf"@{re.escape(short)}\b", m.text))
|
|
292
|
+
]
|
|
278
293
|
if not msgs:
|
|
279
294
|
return
|
|
280
295
|
lines = "\n".join(f" <{m.nick}> {m.text}" for m in msgs)
|
|
@@ -305,10 +320,35 @@ class CodexDaemon:
|
|
|
305
320
|
# Agent runner helpers
|
|
306
321
|
# ------------------------------------------------------------------
|
|
307
322
|
|
|
308
|
-
def _on_turn_error(self) -> None:
|
|
309
|
-
"""
|
|
323
|
+
async def _on_turn_error(self) -> None:
|
|
324
|
+
"""Send error feedback to IRC and clean up stale relay target."""
|
|
310
325
|
if self._mention_targets:
|
|
311
|
-
self._mention_targets.popleft()
|
|
326
|
+
relay_target = self._mention_targets.popleft()
|
|
327
|
+
if self._transport and relay_target:
|
|
328
|
+
await self._transport.send_privmsg(
|
|
329
|
+
relay_target,
|
|
330
|
+
"Sorry, I encountered an error processing your request.",
|
|
331
|
+
)
|
|
332
|
+
self._consecutive_turn_failures += 1
|
|
333
|
+
if self._consecutive_turn_failures >= MAX_CONSECUTIVE_TURN_FAILURES:
|
|
334
|
+
self._paused = True
|
|
335
|
+
self._manually_paused = True
|
|
336
|
+
logger.error(
|
|
337
|
+
"Agent %s paused after %d consecutive turn failures",
|
|
338
|
+
self.agent.nick,
|
|
339
|
+
self._consecutive_turn_failures,
|
|
340
|
+
)
|
|
341
|
+
if self._webhook:
|
|
342
|
+
await self._webhook.fire(
|
|
343
|
+
AlertEvent(
|
|
344
|
+
event_type="agent_spiraling",
|
|
345
|
+
nick=self.agent.nick,
|
|
346
|
+
message=(
|
|
347
|
+
f"Agent {self.agent.nick} paused after "
|
|
348
|
+
f"{self._consecutive_turn_failures} consecutive turn failures."
|
|
349
|
+
),
|
|
350
|
+
)
|
|
351
|
+
)
|
|
312
352
|
|
|
313
353
|
async def _start_agent_runner(self) -> None:
|
|
314
354
|
self._agent_runner = CodexAgentRunner(
|
|
@@ -443,6 +483,7 @@ class CodexDaemon:
|
|
|
443
483
|
|
|
444
484
|
async def _on_agent_message(self, msg: dict) -> None:
|
|
445
485
|
"""Relay agent text to IRC and feed to supervisor."""
|
|
486
|
+
self._consecutive_turn_failures = 0
|
|
446
487
|
await self._relay_response_to_irc(msg)
|
|
447
488
|
|
|
448
489
|
if self._supervisor:
|
|
@@ -581,11 +622,13 @@ class CodexDaemon:
|
|
|
581
622
|
|
|
582
623
|
def _ipc_pause(self, req_id: str, msg: dict) -> dict:
|
|
583
624
|
self._paused = True
|
|
584
|
-
|
|
625
|
+
self._manually_paused = True
|
|
626
|
+
logger.info("Agent %s paused (manual)", self.agent.nick)
|
|
585
627
|
return make_response(req_id, ok=True)
|
|
586
628
|
|
|
587
629
|
def _ipc_resume(self, req_id: str, msg: dict) -> dict:
|
|
588
630
|
self._paused = False
|
|
631
|
+
self._manually_paused = False
|
|
589
632
|
logger.info("Agent %s resumed", self.agent.nick)
|
|
590
633
|
# NOTE: Catch-up on missed messages is not yet implemented.
|
|
591
634
|
# IRCTransport does not process HISTORY responses into the buffer.
|
|
@@ -58,10 +58,12 @@ class CopilotAgentRunner:
|
|
|
58
58
|
# Lazy import — github-copilot-sdk is only needed at runtime
|
|
59
59
|
from copilot import CopilotClient, PermissionHandler, SubprocessConfig
|
|
60
60
|
|
|
61
|
-
# Isolate
|
|
61
|
+
# Isolate data/state dirs to prevent session interference, but
|
|
62
|
+
# preserve HOME and XDG_CONFIG_HOME so copilot finds auth tokens.
|
|
62
63
|
self._isolated_home = tempfile.mkdtemp(prefix="culture-copilot-")
|
|
63
|
-
isolated_env =
|
|
64
|
-
isolated_env.
|
|
64
|
+
isolated_env = dict(os.environ)
|
|
65
|
+
isolated_env["XDG_DATA_HOME"] = os.path.join(self._isolated_home, ".local", "share")
|
|
66
|
+
isolated_env["XDG_STATE_HOME"] = os.path.join(self._isolated_home, ".local", "state")
|
|
65
67
|
|
|
66
68
|
try:
|
|
67
69
|
# Create and start the CopilotClient (spawns copilot CLI process)
|
|
@@ -10,6 +10,7 @@ import asyncio
|
|
|
10
10
|
import datetime
|
|
11
11
|
import logging
|
|
12
12
|
import os
|
|
13
|
+
import re
|
|
13
14
|
import time
|
|
14
15
|
from collections import deque
|
|
15
16
|
|
|
@@ -34,6 +35,7 @@ _ERR_MISSING_CHANNEL_THREAD_MSG = "Missing 'channel', 'thread', or 'message'"
|
|
|
34
35
|
MAX_CRASH_COUNT = 3
|
|
35
36
|
CRASH_WINDOW_SECONDS = 300
|
|
36
37
|
CRASH_RESTART_DELAY = 5
|
|
38
|
+
MAX_CONSECUTIVE_TURN_FAILURES = 3
|
|
37
39
|
|
|
38
40
|
|
|
39
41
|
class CopilotDaemon:
|
|
@@ -71,9 +73,11 @@ class CopilotDaemon:
|
|
|
71
73
|
# Crash-recovery state
|
|
72
74
|
self._crash_times: list[float] = []
|
|
73
75
|
self._circuit_open = False
|
|
76
|
+
self._consecutive_turn_failures: int = 0
|
|
74
77
|
|
|
75
78
|
# Pause/sleep state
|
|
76
79
|
self._paused: bool = False
|
|
80
|
+
self._manually_paused: bool = False
|
|
77
81
|
self._last_activation: float | None = None
|
|
78
82
|
|
|
79
83
|
# Status query state — for asking the agent what it's doing
|
|
@@ -245,7 +249,7 @@ class CopilotDaemon:
|
|
|
245
249
|
if should_sleep and not self._paused:
|
|
246
250
|
self._paused = True
|
|
247
251
|
logger.info("Sleep schedule: pausing %s", self.agent.nick)
|
|
248
|
-
elif not should_sleep and self._paused:
|
|
252
|
+
elif not should_sleep and self._paused and not self._manually_paused:
|
|
249
253
|
self._paused = False
|
|
250
254
|
logger.info("Sleep schedule: resuming %s", self.agent.nick)
|
|
251
255
|
except asyncio.CancelledError:
|
|
@@ -275,6 +279,17 @@ class CopilotDaemon:
|
|
|
275
279
|
|
|
276
280
|
def _send_channel_poll(self, channel) -> None:
|
|
277
281
|
msgs = self._buffer.read(channel)
|
|
282
|
+
if not msgs:
|
|
283
|
+
return
|
|
284
|
+
# Filter out messages that @mention this agent (already handled by _on_mention)
|
|
285
|
+
nick = self.agent.nick
|
|
286
|
+
short = nick.split("-", 1)[1] if "-" in nick else None
|
|
287
|
+
msgs = [
|
|
288
|
+
m
|
|
289
|
+
for m in msgs
|
|
290
|
+
if not re.search(rf"@{re.escape(nick)}\b", m.text)
|
|
291
|
+
and not (short and re.search(rf"@{re.escape(short)}\b", m.text))
|
|
292
|
+
]
|
|
278
293
|
if not msgs:
|
|
279
294
|
return
|
|
280
295
|
lines = "\n".join(f" <{m.nick}> {m.text}" for m in msgs)
|
|
@@ -305,10 +320,35 @@ class CopilotDaemon:
|
|
|
305
320
|
# Agent runner helpers
|
|
306
321
|
# ------------------------------------------------------------------
|
|
307
322
|
|
|
308
|
-
def _on_turn_error(self) -> None:
|
|
309
|
-
"""
|
|
323
|
+
async def _on_turn_error(self) -> None:
|
|
324
|
+
"""Send error feedback to IRC and clean up stale relay target."""
|
|
310
325
|
if self._mention_targets:
|
|
311
|
-
self._mention_targets.popleft()
|
|
326
|
+
relay_target = self._mention_targets.popleft()
|
|
327
|
+
if self._transport and relay_target:
|
|
328
|
+
await self._transport.send_privmsg(
|
|
329
|
+
relay_target,
|
|
330
|
+
"Sorry, I encountered an error processing your request.",
|
|
331
|
+
)
|
|
332
|
+
self._consecutive_turn_failures += 1
|
|
333
|
+
if self._consecutive_turn_failures >= MAX_CONSECUTIVE_TURN_FAILURES:
|
|
334
|
+
self._paused = True
|
|
335
|
+
self._manually_paused = True
|
|
336
|
+
logger.error(
|
|
337
|
+
"Agent %s paused after %d consecutive turn failures",
|
|
338
|
+
self.agent.nick,
|
|
339
|
+
self._consecutive_turn_failures,
|
|
340
|
+
)
|
|
341
|
+
if self._webhook:
|
|
342
|
+
await self._webhook.fire(
|
|
343
|
+
AlertEvent(
|
|
344
|
+
event_type="agent_spiraling",
|
|
345
|
+
nick=self.agent.nick,
|
|
346
|
+
message=(
|
|
347
|
+
f"Agent {self.agent.nick} paused after "
|
|
348
|
+
f"{self._consecutive_turn_failures} consecutive turn failures."
|
|
349
|
+
),
|
|
350
|
+
)
|
|
351
|
+
)
|
|
312
352
|
|
|
313
353
|
async def _start_agent_runner(self) -> None:
|
|
314
354
|
# Resolve installed skill path for the Copilot session
|
|
@@ -450,6 +490,7 @@ class CopilotDaemon:
|
|
|
450
490
|
|
|
451
491
|
async def _on_agent_message(self, msg: dict) -> None:
|
|
452
492
|
"""Relay agent text to IRC and feed to supervisor."""
|
|
493
|
+
self._consecutive_turn_failures = 0
|
|
453
494
|
await self._relay_response_to_irc(msg)
|
|
454
495
|
|
|
455
496
|
if self._supervisor:
|
|
@@ -588,11 +629,13 @@ class CopilotDaemon:
|
|
|
588
629
|
|
|
589
630
|
def _ipc_pause(self, req_id: str, msg: dict) -> dict:
|
|
590
631
|
self._paused = True
|
|
591
|
-
|
|
632
|
+
self._manually_paused = True
|
|
633
|
+
logger.info("Agent %s paused (manual)", self.agent.nick)
|
|
592
634
|
return make_response(req_id, ok=True)
|
|
593
635
|
|
|
594
636
|
def _ipc_resume(self, req_id: str, msg: dict) -> dict:
|
|
595
637
|
self._paused = False
|
|
638
|
+
self._manually_paused = False
|
|
596
639
|
logger.info("Agent %s resumed", self.agent.nick)
|
|
597
640
|
# NOTE: Catch-up on missed messages is not yet implemented.
|
|
598
641
|
# IRCTransport does not process HISTORY responses into the buffer.
|
|
@@ -48,4 +48,4 @@ Polling respects the sleep schedule. When an agent is paused (during sleep hours
|
|
|
48
48
|
|
|
49
49
|
## Interaction with @mentions
|
|
50
50
|
|
|
51
|
-
If an @mention arrives between polls, it triggers immediately. The
|
|
51
|
+
If an @mention arrives between polls, it triggers immediately. The poll loop filters out messages that @mention the agent, so mentions are never processed twice.
|
|
@@ -106,7 +106,7 @@ compatibility.
|
|
|
106
106
|
| `directory` | Working directory for the agent | required |
|
|
107
107
|
| `channels` | List of IRC channels to join on startup | required |
|
|
108
108
|
| `model` | Model identifier (provider-prefixed, e.g. `anthropic/claude-sonnet-4-6`) | `anthropic/claude-sonnet-4-6` |
|
|
109
|
-
| `system_prompt` | Custom system prompt (replaces the default) | -- (uses built-in) |
|
|
109
|
+
| `system_prompt` | Custom system prompt (replaces the default). See [System Prompt Configuration](system-prompt.md) | -- (uses built-in) |
|
|
110
110
|
| `tags` | List of capability/interest tags for self-organizing rooms | `[]` |
|
|
111
111
|
|
|
112
112
|
## CLI Usage
|
|
@@ -159,6 +159,7 @@ evaluation mode.
|
|
|
159
159
|
|
|
160
160
|
## Further Reading
|
|
161
161
|
|
|
162
|
+
- [System Prompt Configuration](system-prompt.md) -- prompt layers and composition
|
|
162
163
|
- [IRC Tools](../claude/irc-tools.md) -- skill tools (same across backends)
|
|
163
164
|
- [Configuration](../claude/configuration.md) -- YAML format details
|
|
164
165
|
- [Webhooks](../claude/webhooks.md) -- event types and alerting
|