agentirc-cli 0.15.2__tar.gz → 0.16.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/.pr_agent.toml +1 -1
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/CHANGELOG.md +15 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/CLAUDE.md +1 -1
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/PKG-INFO +5 -2
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/README.md +4 -1
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/cli.py +66 -38
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/acp}/agent_runner.py +31 -18
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/acp}/config.py +4 -2
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/acp}/daemon.py +43 -30
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/acp}/irc_transport.py +1 -1
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/acp}/skill/SKILL.md +9 -9
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/acp}/skill/irc_client.py +5 -5
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/acp}/socket_server.py +1 -1
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/acp}/webhook.py +1 -1
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/claude/config.py +5 -1
- agentirc_cli-0.16.0/agentirc/clients/claude/supervisor.py +141 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/codex/config.py +3 -1
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/copilot/config.py +3 -1
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/learn_prompt.py +5 -2
- agentirc_cli-0.16.0/docs/agent-client.md +28 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/agent-harness-spec.md +7 -6
- agentirc_cli-0.16.0/docs/clients/acp/overview.md +140 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/harness-conformance.md +1 -1
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/layer5-agent-harness.md +1 -1
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/pyproject.toml +2 -2
- agentirc_cli-0.15.2/tests/test_opencode_daemon.py → agentirc_cli-0.16.0/tests/test_acp_daemon.py +26 -24
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/uv.lock +1 -1
- agentirc_cli-0.15.2/agentirc/clients/opencode/supervisor.py +0 -163
- agentirc_cli-0.15.2/docs/agent-client.md +0 -11
- agentirc_cli-0.15.2/docs/clients/opencode/configuration.md +0 -187
- agentirc_cli-0.15.2/docs/clients/opencode/context-management.md +0 -73
- agentirc_cli-0.15.2/docs/clients/opencode/irc-tools.md +0 -186
- agentirc_cli-0.15.2/docs/clients/opencode/overview.md +0 -125
- agentirc_cli-0.15.2/docs/clients/opencode/setup.md +0 -214
- agentirc_cli-0.15.2/docs/clients/opencode/supervisor.md +0 -126
- agentirc_cli-0.15.2/docs/clients/opencode/webhooks.md +0 -91
- agentirc_cli-0.15.2/docs/opencode-backend.md +0 -6
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/.github/workflows/pages.yml +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/.gitignore +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/CNAME +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/Gemfile +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/Gemfile.lock +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/LICENSE +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/_config.yml +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/__main__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/__init__.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/claude → agentirc_cli-0.16.0/agentirc/clients/acp}/__init__.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/claude → agentirc_cli-0.16.0/agentirc/clients/acp}/ipc.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/claude → agentirc_cli-0.16.0/agentirc/clients/acp}/message_buffer.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/claude → agentirc_cli-0.16.0/agentirc/clients/acp}/skill/__init__.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/claude → agentirc_cli-0.16.0/agentirc/clients/acp}/supervisor.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/codex → agentirc_cli-0.16.0/agentirc/clients/claude}/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/claude/__main__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/claude/daemon.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/codex → agentirc_cli-0.16.0/agentirc/clients/claude}/ipc.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/claude/irc_transport.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/codex → agentirc_cli-0.16.0/agentirc/clients/claude}/message_buffer.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/codex → agentirc_cli-0.16.0/agentirc/clients/claude}/skill/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/claude/socket_server.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/claude/webhook.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/copilot → agentirc_cli-0.16.0/agentirc/clients/codex}/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/codex/agent_runner.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/codex/daemon.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/copilot → agentirc_cli-0.16.0/agentirc/clients/codex}/ipc.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/codex/irc_transport.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/copilot → agentirc_cli-0.16.0/agentirc/clients/codex}/message_buffer.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/copilot → agentirc_cli-0.16.0/agentirc/clients/codex}/skill/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/codex/socket_server.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/codex/supervisor.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/codex/webhook.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/copilot}/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/copilot/agent_runner.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/copilot/daemon.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/copilot}/ipc.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/copilot/irc_transport.py +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/copilot}/message_buffer.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/copilot}/skill/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/clients/copilot/webhook.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/observer.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/overview/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/overview/collector.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/overview/model.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/overview/renderer_text.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/overview/renderer_web.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/overview/web/style.css +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/pidfile.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/protocol/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/protocol/commands.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/protocol/extensions/federation.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/protocol/extensions/history.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/protocol/extensions/tags.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/protocol/message.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/protocol/protocol-index.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/protocol/replies.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/__main__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/channel.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/client.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/config.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/ircd.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/remote_client.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/room_store.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/rooms_util.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/server_link.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/skill.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/skills/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/skills/history.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/agentirc/server/skills/rooms.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/ci.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/cli.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/codex/configuration.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/codex/overview.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/codex/setup.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/copilot/configuration.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/copilot/setup.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/codex-backend.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/copilot-backend.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/design.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/docs-site.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/getting-started.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/grow-your-agent.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/layer1-core-irc.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/layer2-attention.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/layer3-skills.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/layer4-federation.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/overview.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/publishing.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/rooms.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/server-architecture.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/use-cases/10-grow-your-agent.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/docs/use-cases-index.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/index.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/packages/agent-harness/daemon.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/packages/agent-harness/irc_transport.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/plugins/codex/skills/agentirc-irc/SKILL.md +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/__init__.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/conftest.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_channel.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_connection.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_daemon.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_discovery.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_federation.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_history.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_ipc.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_mentions.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_message.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_messaging.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_modes.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_overview_model.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_overview_web.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_rooms.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_skill_client.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_skills.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_socket_server.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_supervisor.py +0 -0
- {agentirc_cli-0.15.2 → agentirc_cli-0.16.0}/tests/test_webhook.py +0 -0
|
@@ -10,7 +10,7 @@ extra_instructions = """
|
|
|
10
10
|
|
|
11
11
|
## Harness Conformance (CRITICAL)
|
|
12
12
|
|
|
13
|
-
The authoritative spec is `docs/agent-harness-spec.md`. There are 4 agent backends under `agentirc/clients/` — claude, codex, copilot,
|
|
13
|
+
The authoritative spec is `docs/agent-harness-spec.md`. There are 4 agent backends under `agentirc/clients/` — claude, codex, copilot, acp — plus a reference implementation in `packages/agent-harness/`. The ACP backend supports any agent implementing the Agent Client Protocol (Cline, OpenCode, Kiro, etc.) via a configurable `acp_command`. The all-backends rule: a feature that exists in only one backend is a bug.
|
|
14
14
|
|
|
15
15
|
When reviewing changes to any file under `agentirc/clients/` or `packages/agent-harness/`, apply these checks:
|
|
16
16
|
|
|
@@ -4,6 +4,21 @@ 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
|
+
## [0.16.0] - 2026-03-31
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Generic ACP backend — supports Cline, OpenCode, Kiro, Gemini, and any ACP-compatible agent via configurable spawn command
|
|
13
|
+
- CLI --agent acp with --acp-command flag for registering ACP agents
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Replaced OpenCode-specific backend with generic ACP backend (clients/acp/)
|
|
19
|
+
- ACP supervisor uses SDK-based evaluation (vendor-agnostic) instead of opencode --non-interactive
|
|
20
|
+
- Backward compat: existing agent: opencode configs map to ACP backend automatically
|
|
21
|
+
|
|
7
22
|
## [0.15.2] - 2026-03-31
|
|
8
23
|
|
|
9
24
|
|
|
@@ -25,7 +25,7 @@ For agent backends (`clients/claude/`, `clients/codex/`, etc.):
|
|
|
25
25
|
|
|
26
26
|
If you improve a generic component (e.g., `irc_transport.py`), update the reference in `packages/` too so the next backend starts from the latest version.
|
|
27
27
|
|
|
28
|
-
**All-backends rule:** When adding or changing a feature in any agent harness (config fields, transport capabilities, daemon handlers), propagate the change to **all** backends (`claude`, `codex`, `copilot`, `
|
|
28
|
+
**All-backends rule:** When adding or changing a feature in any agent harness (config fields, transport capabilities, daemon handlers), propagate the change to **all** backends (`claude`, `codex`, `copilot`, `acp`) and update `docs/` accordingly. A feature that only exists in one backend is a bug.
|
|
29
29
|
|
|
30
30
|
## Documentation
|
|
31
31
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentirc-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.16.0
|
|
4
4
|
Summary: IRC protocol chatrooms for AI agents (and humans allowed)
|
|
5
5
|
Project-URL: Homepage, https://github.com/OriNachum/agentirc
|
|
6
6
|
Author: Ori Nachum
|
|
@@ -27,6 +27,8 @@ Description-Content-Type: text/markdown
|
|
|
27
27
|
|
|
28
28
|
IRC Protocol ChatRooms for Agents (And humans allowed)
|
|
29
29
|
|
|
30
|
+
Supports Claude Code, Codex, Copilot, and any ACP agent (Cline, OpenCode, Kiro, Gemini)
|
|
31
|
+
|
|
30
32
|
<br>
|
|
31
33
|
|
|
32
34
|
<a href="https://agentirc.dev"><img src="https://img.shields.io/badge/docs-agentirc.dev-D97706?style=flat&labelColor=2D2B27" alt="Docs"></a>
|
|
@@ -162,7 +164,7 @@ Full docs at **[agentirc.dev](https://agentirc.dev)** -- or browse below.
|
|
|
162
164
|
</details>
|
|
163
165
|
|
|
164
166
|
<details>
|
|
165
|
-
<summary><b>Agent Client</b> <sub>
|
|
167
|
+
<summary><b>Agent Client</b> <sub>8 docs</sub></summary>
|
|
166
168
|
|
|
167
169
|
| Doc | Description |
|
|
168
170
|
|-----|-------------|
|
|
@@ -173,6 +175,7 @@ Full docs at **[agentirc.dev](https://agentirc.dev)** -- or browse below.
|
|
|
173
175
|
| [Context Management](docs/clients/claude/context-management.md) | Compact, clear, set directory |
|
|
174
176
|
| [Supervisor](docs/clients/claude/supervisor.md) | Human oversight and intervention |
|
|
175
177
|
| [Webhooks](docs/clients/claude/webhooks.md) | Alerting and event notifications |
|
|
178
|
+
| [ACP Backend](docs/clients/acp/overview.md) | Cline, OpenCode, Kiro, Gemini, and any ACP agent |
|
|
176
179
|
|
|
177
180
|
</details>
|
|
178
181
|
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
IRC Protocol ChatRooms for Agents (And humans allowed)
|
|
7
7
|
|
|
8
|
+
Supports Claude Code, Codex, Copilot, and any ACP agent (Cline, OpenCode, Kiro, Gemini)
|
|
9
|
+
|
|
8
10
|
<br>
|
|
9
11
|
|
|
10
12
|
<a href="https://agentirc.dev"><img src="https://img.shields.io/badge/docs-agentirc.dev-D97706?style=flat&labelColor=2D2B27" alt="Docs"></a>
|
|
@@ -140,7 +142,7 @@ Full docs at **[agentirc.dev](https://agentirc.dev)** -- or browse below.
|
|
|
140
142
|
</details>
|
|
141
143
|
|
|
142
144
|
<details>
|
|
143
|
-
<summary><b>Agent Client</b> <sub>
|
|
145
|
+
<summary><b>Agent Client</b> <sub>8 docs</sub></summary>
|
|
144
146
|
|
|
145
147
|
| Doc | Description |
|
|
146
148
|
|-----|-------------|
|
|
@@ -151,6 +153,7 @@ Full docs at **[agentirc.dev](https://agentirc.dev)** -- or browse below.
|
|
|
151
153
|
| [Context Management](docs/clients/claude/context-management.md) | Compact, clear, set directory |
|
|
152
154
|
| [Supervisor](docs/clients/claude/supervisor.md) | Human oversight and intervention |
|
|
153
155
|
| [Webhooks](docs/clients/claude/webhooks.md) | Alerting and event notifications |
|
|
156
|
+
| [ACP Backend](docs/clients/acp/overview.md) | Cline, OpenCode, Kiro, Gemini, and any ACP agent |
|
|
154
157
|
|
|
155
158
|
</details>
|
|
156
159
|
|
|
@@ -103,7 +103,8 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
103
103
|
init_parser = sub.add_parser("init", help="Register an agent for the current directory")
|
|
104
104
|
init_parser.add_argument("--server", default=None, help="Server name prefix")
|
|
105
105
|
init_parser.add_argument("--nick", default=None, help="Agent suffix (after server-)")
|
|
106
|
-
init_parser.add_argument("--agent", default="claude", choices=["claude", "codex", "
|
|
106
|
+
init_parser.add_argument("--agent", default="claude", choices=["claude", "codex", "copilot", "acp"], help="Agent backend")
|
|
107
|
+
init_parser.add_argument("--acp-command", default=None, help="ACP spawn command as JSON list (e.g. '[\"cline\",\"--acp\"]')")
|
|
107
108
|
init_parser.add_argument("--config", default=DEFAULT_CONFIG, help="Config file path")
|
|
108
109
|
|
|
109
110
|
# -- start subcommand --------------------------------------------------
|
|
@@ -167,8 +168,8 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
167
168
|
skills_sub = skills_parser.add_subparsers(dest="skills_command")
|
|
168
169
|
skills_install = skills_sub.add_parser("install", help="Install IRC skill for an agent")
|
|
169
170
|
skills_install.add_argument(
|
|
170
|
-
"target", choices=["claude", "codex", "
|
|
171
|
-
help="Target agent: claude, codex,
|
|
171
|
+
"target", choices=["claude", "codex", "copilot", "acp", "opencode", "all"],
|
|
172
|
+
help="Target agent: claude, codex, copilot, acp, opencode (alias of acp), or all",
|
|
172
173
|
)
|
|
173
174
|
|
|
174
175
|
# -- overview subcommand -----------------------------------------------
|
|
@@ -413,14 +414,6 @@ def _cmd_init(args: argparse.Namespace) -> None:
|
|
|
413
414
|
directory=os.getcwd(),
|
|
414
415
|
channels=["#general"],
|
|
415
416
|
)
|
|
416
|
-
elif args.agent == "opencode":
|
|
417
|
-
from agentirc.clients.opencode.config import AgentConfig as OpenCodeAgentConfig
|
|
418
|
-
agent = OpenCodeAgentConfig(
|
|
419
|
-
nick=full_nick,
|
|
420
|
-
agent="opencode",
|
|
421
|
-
directory=os.getcwd(),
|
|
422
|
-
channels=["#general"],
|
|
423
|
-
)
|
|
424
417
|
elif args.agent == "copilot":
|
|
425
418
|
from agentirc.clients.copilot.config import AgentConfig as CopilotAgentConfig
|
|
426
419
|
agent = CopilotAgentConfig(
|
|
@@ -429,6 +422,26 @@ def _cmd_init(args: argparse.Namespace) -> None:
|
|
|
429
422
|
directory=os.getcwd(),
|
|
430
423
|
channels=["#general"],
|
|
431
424
|
)
|
|
425
|
+
elif args.agent == "acp":
|
|
426
|
+
import json as _json
|
|
427
|
+
from agentirc.clients.acp.config import AgentConfig as ACPAgentConfig
|
|
428
|
+
acp_cmd = ["opencode", "acp"]
|
|
429
|
+
if args.acp_command:
|
|
430
|
+
try:
|
|
431
|
+
acp_cmd = _json.loads(args.acp_command)
|
|
432
|
+
except _json.JSONDecodeError:
|
|
433
|
+
# Treat as a simple command name (e.g. "cline --acp")
|
|
434
|
+
acp_cmd = args.acp_command.split()
|
|
435
|
+
if not isinstance(acp_cmd, list) or not acp_cmd or not all(isinstance(s, str) for s in acp_cmd):
|
|
436
|
+
print("Error: --acp-command must be a non-empty list of strings", file=sys.stderr)
|
|
437
|
+
sys.exit(1)
|
|
438
|
+
agent = ACPAgentConfig(
|
|
439
|
+
nick=full_nick,
|
|
440
|
+
agent="acp",
|
|
441
|
+
acp_command=acp_cmd,
|
|
442
|
+
directory=os.getcwd(),
|
|
443
|
+
channels=["#general"],
|
|
444
|
+
)
|
|
432
445
|
else:
|
|
433
446
|
agent = AgentConfig(
|
|
434
447
|
nick=full_nick,
|
|
@@ -529,19 +542,34 @@ async def _run_single_agent(config: DaemonConfig, agent: AgentConfig) -> None:
|
|
|
529
542
|
agents=config.agents,
|
|
530
543
|
)
|
|
531
544
|
daemon = CodexDaemon(codex_config, agent)
|
|
532
|
-
elif backend
|
|
533
|
-
from agentirc.clients.
|
|
534
|
-
from agentirc.clients.
|
|
535
|
-
DaemonConfig as
|
|
545
|
+
elif backend in ("acp", "opencode"):
|
|
546
|
+
from agentirc.clients.acp.daemon import ACPDaemon
|
|
547
|
+
from agentirc.clients.acp.config import (
|
|
548
|
+
DaemonConfig as ACPDaemonConfig,
|
|
549
|
+
AgentConfig as ACPAgentConfig,
|
|
536
550
|
)
|
|
537
|
-
# Re-load config through
|
|
538
|
-
|
|
551
|
+
# Re-load config through ACP module for correct supervisor defaults
|
|
552
|
+
acp_config = ACPDaemonConfig(
|
|
539
553
|
server=config.server,
|
|
540
554
|
webhooks=config.webhooks,
|
|
541
555
|
buffer_size=config.buffer_size,
|
|
542
556
|
agents=config.agents,
|
|
543
557
|
)
|
|
544
|
-
|
|
558
|
+
# Backward compat: opencode -> acp with default command
|
|
559
|
+
if not isinstance(agent, ACPAgentConfig):
|
|
560
|
+
acp_agent = ACPAgentConfig(
|
|
561
|
+
nick=agent.nick,
|
|
562
|
+
agent="acp",
|
|
563
|
+
acp_command=getattr(agent, "acp_command", None) or ["opencode", "acp"],
|
|
564
|
+
directory=agent.directory,
|
|
565
|
+
channels=list(agent.channels),
|
|
566
|
+
model=agent.model,
|
|
567
|
+
system_prompt=agent.system_prompt,
|
|
568
|
+
tags=list(agent.tags),
|
|
569
|
+
)
|
|
570
|
+
else:
|
|
571
|
+
acp_agent = agent
|
|
572
|
+
daemon = ACPDaemon(acp_config, acp_agent)
|
|
545
573
|
elif backend == "copilot":
|
|
546
574
|
from agentirc.clients.copilot.daemon import CopilotDaemon
|
|
547
575
|
from agentirc.clients.copilot.config import (
|
|
@@ -1018,45 +1046,45 @@ def _install_skill_codex() -> None:
|
|
|
1018
1046
|
print(f"Installed Codex skill: {dest}")
|
|
1019
1047
|
|
|
1020
1048
|
|
|
1021
|
-
def
|
|
1022
|
-
"""Return the path to the bundled
|
|
1049
|
+
def _get_bundled_copilot_skill_path() -> str:
|
|
1050
|
+
"""Return the path to the bundled Copilot SKILL.md in the installed package."""
|
|
1023
1051
|
import agentirc
|
|
1024
|
-
return os.path.join(os.path.dirname(agentirc.__file__), "clients", "
|
|
1052
|
+
return os.path.join(os.path.dirname(agentirc.__file__), "clients", "copilot", "skill", "SKILL.md")
|
|
1025
1053
|
|
|
1026
1054
|
|
|
1027
|
-
def
|
|
1028
|
-
"""Install IRC skill for
|
|
1029
|
-
src =
|
|
1030
|
-
dest_dir = os.path.expanduser("~/.
|
|
1055
|
+
def _install_skill_copilot() -> None:
|
|
1056
|
+
"""Install IRC skill for GitHub Copilot."""
|
|
1057
|
+
src = _get_bundled_copilot_skill_path()
|
|
1058
|
+
dest_dir = os.path.expanduser("~/.copilot_skills/agentirc-irc")
|
|
1031
1059
|
dest = os.path.join(dest_dir, "SKILL.md")
|
|
1032
1060
|
|
|
1033
1061
|
os.makedirs(dest_dir, exist_ok=True)
|
|
1034
1062
|
import shutil
|
|
1035
1063
|
shutil.copy2(src, dest)
|
|
1036
|
-
print(f"Installed
|
|
1064
|
+
print(f"Installed Copilot skill: {dest}")
|
|
1037
1065
|
|
|
1038
1066
|
|
|
1039
|
-
def
|
|
1040
|
-
"""Return the path to the bundled
|
|
1067
|
+
def _get_bundled_acp_skill_path() -> str:
|
|
1068
|
+
"""Return the path to the bundled ACP SKILL.md in the installed package."""
|
|
1041
1069
|
import agentirc
|
|
1042
|
-
return os.path.join(os.path.dirname(agentirc.__file__), "clients", "
|
|
1070
|
+
return os.path.join(os.path.dirname(agentirc.__file__), "clients", "acp", "skill", "SKILL.md")
|
|
1043
1071
|
|
|
1044
1072
|
|
|
1045
|
-
def
|
|
1046
|
-
"""Install IRC skill for
|
|
1047
|
-
src =
|
|
1048
|
-
dest_dir = os.path.expanduser("~/.
|
|
1073
|
+
def _install_skill_acp() -> None:
|
|
1074
|
+
"""Install IRC skill for ACP agents (Cline, OpenCode, etc.)."""
|
|
1075
|
+
src = _get_bundled_acp_skill_path()
|
|
1076
|
+
dest_dir = os.path.expanduser("~/.acp/skills/agentirc-irc")
|
|
1049
1077
|
dest = os.path.join(dest_dir, "SKILL.md")
|
|
1050
1078
|
|
|
1051
1079
|
os.makedirs(dest_dir, exist_ok=True)
|
|
1052
1080
|
import shutil
|
|
1053
1081
|
shutil.copy2(src, dest)
|
|
1054
|
-
print(f"Installed
|
|
1082
|
+
print(f"Installed ACP skill: {dest}")
|
|
1055
1083
|
|
|
1056
1084
|
|
|
1057
1085
|
def _cmd_skills(args: argparse.Namespace) -> None:
|
|
1058
1086
|
if not hasattr(args, "skills_command") or args.skills_command != "install":
|
|
1059
|
-
print("Usage: agentirc skills install <claude|codex|
|
|
1087
|
+
print("Usage: agentirc skills install <claude|codex|copilot|acp|all>", file=sys.stderr)
|
|
1060
1088
|
sys.exit(1)
|
|
1061
1089
|
|
|
1062
1090
|
target = args.target
|
|
@@ -1065,13 +1093,13 @@ def _cmd_skills(args: argparse.Namespace) -> None:
|
|
|
1065
1093
|
_install_skill_claude()
|
|
1066
1094
|
if target in ("codex", "all"):
|
|
1067
1095
|
_install_skill_codex()
|
|
1068
|
-
if target in ("opencode", "all"):
|
|
1069
|
-
_install_skill_opencode()
|
|
1070
1096
|
if target in ("copilot", "all"):
|
|
1071
1097
|
_install_skill_copilot()
|
|
1098
|
+
if target in ("acp", "opencode", "all"):
|
|
1099
|
+
_install_skill_acp()
|
|
1072
1100
|
|
|
1073
1101
|
if target == "all":
|
|
1074
|
-
print("\nSkills installed for Claude Code, Codex,
|
|
1102
|
+
print("\nSkills installed for Claude Code, Codex, Copilot, and ACP.")
|
|
1075
1103
|
print(f"\nSet AGENTIRC_NICK in your shell profile to enable the skill.")
|
|
1076
1104
|
|
|
1077
1105
|
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""ACP agent runner — manages any ACP-compatible agent via JSON-RPC over stdio.
|
|
2
|
+
|
|
3
|
+
Supports any agent that implements the Agent Client Protocol (ACP), such as
|
|
4
|
+
Cline (cline --acp), OpenCode (opencode acp), and others.
|
|
5
|
+
"""
|
|
2
6
|
|
|
3
7
|
from __future__ import annotations
|
|
4
8
|
|
|
@@ -13,19 +17,26 @@ from typing import Any, Awaitable, Callable
|
|
|
13
17
|
logger = logging.getLogger(__name__)
|
|
14
18
|
|
|
15
19
|
|
|
16
|
-
class
|
|
17
|
-
"""Manages an
|
|
20
|
+
class ACPAgentRunner:
|
|
21
|
+
"""Manages an ACP session for the agentirc daemon.
|
|
22
|
+
|
|
23
|
+
Works with any ACP-compatible agent by configuring the spawn command
|
|
24
|
+
via the ``acp_command`` parameter (e.g. ``["cline", "--acp"]`` or
|
|
25
|
+
``["opencode", "acp"]``).
|
|
26
|
+
"""
|
|
18
27
|
|
|
19
28
|
def __init__(
|
|
20
29
|
self,
|
|
21
30
|
model: str,
|
|
22
31
|
directory: str,
|
|
32
|
+
acp_command: list[str] | None = None,
|
|
23
33
|
system_prompt: str = "",
|
|
24
34
|
on_exit: Callable[[int], Awaitable[None]] | None = None,
|
|
25
35
|
on_message: Callable[[dict[str, Any]], Awaitable[None]] | None = None,
|
|
26
36
|
) -> None:
|
|
27
37
|
self.model = model
|
|
28
38
|
self.directory = directory
|
|
39
|
+
self.acp_command = acp_command or ["opencode", "acp"]
|
|
29
40
|
self.system_prompt = system_prompt
|
|
30
41
|
self.on_exit = on_exit
|
|
31
42
|
self.on_message = on_message
|
|
@@ -52,21 +63,22 @@ class OpenCodeAgentRunner:
|
|
|
52
63
|
return self._session_id
|
|
53
64
|
|
|
54
65
|
async def start(self, initial_prompt: str = "") -> None:
|
|
55
|
-
"""Start
|
|
66
|
+
"""Start the ACP agent as a subprocess and initialize a session."""
|
|
56
67
|
self._stopping = False
|
|
57
68
|
|
|
58
|
-
# Isolate from host config (
|
|
59
|
-
self._isolated_home = tempfile.mkdtemp(prefix="agentirc-
|
|
69
|
+
# Isolate from host config (XDG, etc.)
|
|
70
|
+
self._isolated_home = tempfile.mkdtemp(prefix="agentirc-acp-")
|
|
60
71
|
isolated_env = dict(os.environ)
|
|
61
72
|
isolated_env["HOME"] = self._isolated_home
|
|
62
73
|
isolated_env.pop("XDG_CONFIG_HOME", None)
|
|
63
74
|
|
|
75
|
+
cmd_label = " ".join(self.acp_command)
|
|
64
76
|
try:
|
|
65
|
-
# Spawn
|
|
77
|
+
# Spawn ACP agent in stdio mode
|
|
66
78
|
# Use a large stdout buffer — ACP messages (especially session/new with
|
|
67
79
|
# all available models) can exceed asyncio's default 64KB line limit.
|
|
68
80
|
self._process = await asyncio.create_subprocess_exec(
|
|
69
|
-
|
|
81
|
+
*self.acp_command,
|
|
70
82
|
stdin=asyncio.subprocess.PIPE,
|
|
71
83
|
stdout=asyncio.subprocess.PIPE,
|
|
72
84
|
stderr=asyncio.subprocess.PIPE,
|
|
@@ -85,9 +97,9 @@ class OpenCodeAgentRunner:
|
|
|
85
97
|
"fs": {"readTextFile": True, "writeTextFile": True},
|
|
86
98
|
"terminal": True,
|
|
87
99
|
},
|
|
88
|
-
"clientInfo": {"name": "agentirc-
|
|
100
|
+
"clientInfo": {"name": "agentirc-acp", "version": "0.1.0"},
|
|
89
101
|
})
|
|
90
|
-
logger.info("
|
|
102
|
+
logger.info("ACP initialized (%s): %s", cmd_label, resp)
|
|
91
103
|
|
|
92
104
|
# Create a session with model selection
|
|
93
105
|
session_params = {
|
|
@@ -98,11 +110,11 @@ class OpenCodeAgentRunner:
|
|
|
98
110
|
session_params["model"] = self.model
|
|
99
111
|
resp = await self._send_request("session/new", session_params)
|
|
100
112
|
|
|
101
|
-
logger.info("
|
|
113
|
+
logger.info("ACP session/new raw response: %s", json.dumps(resp)[:500])
|
|
102
114
|
result = resp.get("result", {})
|
|
103
115
|
self._session_id = result.get("sessionId")
|
|
104
116
|
self._running = True
|
|
105
|
-
logger.info("
|
|
117
|
+
logger.info("ACP session started (%s): %s", cmd_label, self._session_id)
|
|
106
118
|
|
|
107
119
|
# Start the prompt processing loop
|
|
108
120
|
self._task = asyncio.create_task(self._prompt_loop())
|
|
@@ -120,7 +132,7 @@ class OpenCodeAgentRunner:
|
|
|
120
132
|
raise
|
|
121
133
|
|
|
122
134
|
async def stop(self) -> None:
|
|
123
|
-
"""Stop the
|
|
135
|
+
"""Stop the ACP agent process."""
|
|
124
136
|
self._stopping = True
|
|
125
137
|
self._running = False
|
|
126
138
|
|
|
@@ -238,7 +250,7 @@ class OpenCodeAgentRunner:
|
|
|
238
250
|
except (asyncio.CancelledError, ConnectionError):
|
|
239
251
|
pass
|
|
240
252
|
except Exception:
|
|
241
|
-
logger.exception("
|
|
253
|
+
logger.exception("ACP read loop error")
|
|
242
254
|
finally:
|
|
243
255
|
# Wait for process to fully exit and notify daemon for crash recovery
|
|
244
256
|
returncode = -1
|
|
@@ -270,9 +282,10 @@ class OpenCodeAgentRunner:
|
|
|
270
282
|
await self.on_exit(returncode)
|
|
271
283
|
|
|
272
284
|
async def _stderr_loop(self) -> None:
|
|
273
|
-
"""Log stderr output from the
|
|
285
|
+
"""Log stderr output from the ACP agent process."""
|
|
274
286
|
if not self._process or not self._process.stderr:
|
|
275
287
|
return
|
|
288
|
+
cmd_name = self.acp_command[0]
|
|
276
289
|
try:
|
|
277
290
|
while True:
|
|
278
291
|
line = await self._process.stderr.readline()
|
|
@@ -280,7 +293,7 @@ class OpenCodeAgentRunner:
|
|
|
280
293
|
break
|
|
281
294
|
text = line.decode("utf-8", errors="replace").rstrip()
|
|
282
295
|
if text:
|
|
283
|
-
logger.warning("
|
|
296
|
+
logger.warning("acp[%s] stderr: %s", cmd_name, text)
|
|
284
297
|
except (asyncio.CancelledError, ConnectionError):
|
|
285
298
|
pass
|
|
286
299
|
|
|
@@ -324,7 +337,7 @@ class OpenCodeAgentRunner:
|
|
|
324
337
|
await self._process.stdin.drain()
|
|
325
338
|
|
|
326
339
|
elif method == "error":
|
|
327
|
-
logger.error("
|
|
340
|
+
logger.error("ACP error (%s): %s", self.acp_command[0], params)
|
|
328
341
|
|
|
329
342
|
async def _prompt_loop(self) -> None:
|
|
330
343
|
"""Process queued prompts one at a time."""
|
|
@@ -360,7 +373,7 @@ class OpenCodeAgentRunner:
|
|
|
360
373
|
await asyncio.sleep(0.1)
|
|
361
374
|
|
|
362
375
|
except Exception:
|
|
363
|
-
logger.exception("
|
|
376
|
+
logger.exception("ACP turn error")
|
|
364
377
|
|
|
365
378
|
except asyncio.CancelledError:
|
|
366
379
|
pass
|
{agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/acp}/config.py
RENAMED
|
@@ -20,7 +20,8 @@ class ServerConnConfig:
|
|
|
20
20
|
@dataclass
|
|
21
21
|
class SupervisorConfig:
|
|
22
22
|
"""Supervisor sub-agent settings."""
|
|
23
|
-
model: str = "
|
|
23
|
+
model: str = "claude-sonnet-4-6"
|
|
24
|
+
thinking: str = ""
|
|
24
25
|
window_size: int = 20
|
|
25
26
|
eval_interval: int = 5
|
|
26
27
|
escalation_threshold: int = 3
|
|
@@ -42,7 +43,8 @@ class WebhookConfig:
|
|
|
42
43
|
class AgentConfig:
|
|
43
44
|
"""Per-agent settings."""
|
|
44
45
|
nick: str = ""
|
|
45
|
-
agent: str = "
|
|
46
|
+
agent: str = "acp"
|
|
47
|
+
acp_command: list[str] = field(default_factory=lambda: ["opencode", "acp"])
|
|
46
48
|
directory: str = "."
|
|
47
49
|
channels: list[str] = field(default_factory=lambda: ["#general"])
|
|
48
50
|
model: str = "anthropic/claude-sonnet-4-6"
|
{agentirc_cli-0.15.2/agentirc/clients/opencode → agentirc_cli-0.16.0/agentirc/clients/acp}/daemon.py
RENAMED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""ACP agent daemon — bridges any ACP-compatible agent to the IRC network.
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Supports Cline (cline --acp), OpenCode (opencode acp), and any other agent
|
|
4
|
+
that implements the Agent Client Protocol over stdio.
|
|
5
|
+
|
|
6
|
+
Uses ACPAgentRunner (JSON-RPC/stdio) and an SDK-based Supervisor
|
|
7
|
+
(Claude Agent SDK for periodic evaluation).
|
|
5
8
|
"""
|
|
6
9
|
|
|
7
10
|
from __future__ import annotations
|
|
@@ -14,14 +17,14 @@ import time
|
|
|
14
17
|
from collections import deque
|
|
15
18
|
from typing import Any
|
|
16
19
|
|
|
17
|
-
from agentirc.clients.
|
|
18
|
-
from agentirc.clients.
|
|
19
|
-
from agentirc.clients.
|
|
20
|
-
from agentirc.clients.
|
|
21
|
-
from agentirc.clients.
|
|
22
|
-
from agentirc.clients.
|
|
23
|
-
from agentirc.clients.
|
|
24
|
-
from agentirc.clients.
|
|
20
|
+
from agentirc.clients.acp.config import DaemonConfig, AgentConfig
|
|
21
|
+
from agentirc.clients.acp.ipc import make_response
|
|
22
|
+
from agentirc.clients.acp.irc_transport import IRCTransport
|
|
23
|
+
from agentirc.clients.acp.message_buffer import MessageBuffer
|
|
24
|
+
from agentirc.clients.acp.socket_server import SocketServer
|
|
25
|
+
from agentirc.clients.acp.webhook import WebhookClient, AlertEvent
|
|
26
|
+
from agentirc.clients.acp.agent_runner import ACPAgentRunner
|
|
27
|
+
from agentirc.clients.acp.supervisor import Supervisor, make_sdk_evaluate_fn
|
|
25
28
|
from agentirc.pidfile import write_pid, remove_pid
|
|
26
29
|
|
|
27
30
|
logger = logging.getLogger(__name__)
|
|
@@ -31,20 +34,20 @@ CRASH_WINDOW_SECONDS = 300
|
|
|
31
34
|
CRASH_RESTART_DELAY = 5
|
|
32
35
|
|
|
33
36
|
|
|
34
|
-
class
|
|
37
|
+
class ACPDaemon:
|
|
35
38
|
"""Central orchestrator that ties together the IRC transport, socket server,
|
|
36
|
-
|
|
39
|
+
ACP agent runner, supervisor, and webhook client for a single agent nick."""
|
|
37
40
|
|
|
38
41
|
def __init__(
|
|
39
42
|
self,
|
|
40
43
|
config: DaemonConfig,
|
|
41
44
|
agent: AgentConfig,
|
|
42
45
|
socket_dir: str | None = None,
|
|
43
|
-
|
|
46
|
+
skip_agent: bool = False,
|
|
44
47
|
) -> None:
|
|
45
48
|
self.config = config
|
|
46
49
|
self.agent = agent
|
|
47
|
-
self.
|
|
50
|
+
self.skip_agent = skip_agent
|
|
48
51
|
|
|
49
52
|
self._socket_path = os.path.join(
|
|
50
53
|
socket_dir or os.environ.get("XDG_RUNTIME_DIR", "/tmp"),
|
|
@@ -55,8 +58,8 @@ class OpenCodeDaemon:
|
|
|
55
58
|
self._transport: IRCTransport | None = None
|
|
56
59
|
self._webhook: WebhookClient | None = None
|
|
57
60
|
self._socket_server: SocketServer | None = None
|
|
58
|
-
self._agent_runner:
|
|
59
|
-
self._supervisor:
|
|
61
|
+
self._agent_runner: ACPAgentRunner | None = None
|
|
62
|
+
self._supervisor: Supervisor | None = None
|
|
60
63
|
|
|
61
64
|
# FIFO queue of relay targets — each @mention enqueues a target,
|
|
62
65
|
# each agent response dequeues one, ensuring correct routing even
|
|
@@ -86,6 +89,8 @@ class OpenCodeDaemon:
|
|
|
86
89
|
|
|
87
90
|
async def start(self) -> None:
|
|
88
91
|
"""Start all components in dependency order."""
|
|
92
|
+
cmd_label = " ".join(self.agent.acp_command)
|
|
93
|
+
|
|
89
94
|
# 0. Write PID file for this agent
|
|
90
95
|
self._pid_name = f"agent-{self.agent.nick}"
|
|
91
96
|
write_pid(self._pid_name, os.getpid())
|
|
@@ -120,25 +125,28 @@ class OpenCodeDaemon:
|
|
|
120
125
|
)
|
|
121
126
|
await self._socket_server.start()
|
|
122
127
|
|
|
123
|
-
# 5.
|
|
124
|
-
self._supervisor =
|
|
125
|
-
model=self.config.supervisor.model,
|
|
128
|
+
# 5. SDK-based supervisor (vendor-agnostic)
|
|
129
|
+
self._supervisor = Supervisor(
|
|
126
130
|
window_size=self.config.supervisor.window_size,
|
|
127
131
|
eval_interval=self.config.supervisor.eval_interval,
|
|
128
132
|
escalation_threshold=self.config.supervisor.escalation_threshold,
|
|
133
|
+
evaluate_fn=make_sdk_evaluate_fn(
|
|
134
|
+
model=self.config.supervisor.model,
|
|
135
|
+
thinking=self.config.supervisor.thinking or None,
|
|
136
|
+
prompt_override=self.config.supervisor.prompt_override,
|
|
137
|
+
),
|
|
129
138
|
on_whisper=self._on_supervisor_whisper,
|
|
130
139
|
on_escalation=self._on_supervisor_escalation,
|
|
131
|
-
prompt_override=self.config.supervisor.prompt_override,
|
|
132
140
|
)
|
|
133
141
|
|
|
134
|
-
# 6. Optionally start the
|
|
135
|
-
if not self.
|
|
142
|
+
# 6. Optionally start the ACP agent runner
|
|
143
|
+
if not self.skip_agent:
|
|
136
144
|
try:
|
|
137
145
|
await self._start_agent_runner()
|
|
138
146
|
except Exception:
|
|
139
147
|
logger.exception(
|
|
140
|
-
"Failed to start agent runner for %s, scheduling retry",
|
|
141
|
-
self.agent.nick,
|
|
148
|
+
"Failed to start agent runner for %s (%s), scheduling retry",
|
|
149
|
+
self.agent.nick, cmd_label,
|
|
142
150
|
)
|
|
143
151
|
self._agent_runner = None
|
|
144
152
|
self._crash_times.append(time.time())
|
|
@@ -148,7 +156,8 @@ class OpenCodeDaemon:
|
|
|
148
156
|
self._sleep_task = asyncio.create_task(self._sleep_scheduler())
|
|
149
157
|
|
|
150
158
|
logger.info(
|
|
151
|
-
"
|
|
159
|
+
"ACPDaemon started for %s (cmd=%s, socket=%s)",
|
|
160
|
+
self.agent.nick, cmd_label, self._socket_path,
|
|
152
161
|
)
|
|
153
162
|
|
|
154
163
|
async def stop(self) -> None:
|
|
@@ -177,7 +186,7 @@ class OpenCodeDaemon:
|
|
|
177
186
|
if self._pid_name:
|
|
178
187
|
remove_pid(self._pid_name)
|
|
179
188
|
|
|
180
|
-
logger.info("
|
|
189
|
+
logger.info("ACPDaemon stopped for %s", self.agent.nick)
|
|
181
190
|
|
|
182
191
|
def _parse_sleep_schedule(self) -> tuple[int, int] | None:
|
|
183
192
|
"""Parse sleep_start/sleep_end into minutes. Returns None if invalid."""
|
|
@@ -245,9 +254,10 @@ class OpenCodeDaemon:
|
|
|
245
254
|
# ------------------------------------------------------------------
|
|
246
255
|
|
|
247
256
|
async def _start_agent_runner(self) -> None:
|
|
248
|
-
self._agent_runner =
|
|
257
|
+
self._agent_runner = ACPAgentRunner(
|
|
249
258
|
model=self.agent.model,
|
|
250
259
|
directory=self.agent.directory,
|
|
260
|
+
acp_command=self.agent.acp_command,
|
|
251
261
|
system_prompt=self._build_system_prompt(),
|
|
252
262
|
on_exit=self._on_agent_exit,
|
|
253
263
|
on_message=self._on_agent_message,
|
|
@@ -255,12 +265,15 @@ class OpenCodeDaemon:
|
|
|
255
265
|
# Absorb the system prompt response without relaying to IRC
|
|
256
266
|
self._mention_targets.append(None)
|
|
257
267
|
await self._agent_runner.start()
|
|
258
|
-
logger.info(
|
|
268
|
+
logger.info(
|
|
269
|
+
"ACPAgentRunner started for %s (cmd=%s)",
|
|
270
|
+
self.agent.nick, " ".join(self.agent.acp_command),
|
|
271
|
+
)
|
|
259
272
|
|
|
260
273
|
def _on_mention(self, target: str, sender: str, text: str) -> None:
|
|
261
274
|
"""Called by IRCTransport when the agent is @mentioned or DM'd.
|
|
262
275
|
|
|
263
|
-
Formats a prompt and enqueues it so the
|
|
276
|
+
Formats a prompt and enqueues it so the ACP session picks it up.
|
|
264
277
|
"""
|
|
265
278
|
if self._paused:
|
|
266
279
|
return
|
|
@@ -5,7 +5,7 @@ import logging
|
|
|
5
5
|
from typing import Callable
|
|
6
6
|
|
|
7
7
|
from agentirc.protocol.message import Message
|
|
8
|
-
from agentirc.clients.
|
|
8
|
+
from agentirc.clients.acp.message_buffer import MessageBuffer
|
|
9
9
|
|
|
10
10
|
logger = logging.getLogger(__name__)
|
|
11
11
|
|