agentirc-cli 4.3.3__tar.gz → 4.3.5__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.3.3 → agentirc_cli-4.3.5}/CHANGELOG.md +15 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/PKG-INFO +1 -1
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/bots/bot_manager.py +5 -3
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/cli/agent.py +198 -147
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/cli/bot.py +23 -17
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/cli/channel.py +2 -1
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/cli/mesh.py +90 -75
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/cli/server.py +102 -55
- agentirc_cli-4.3.5/culture/cli/shared/constants.py +16 -0
- agentirc_cli-4.3.5/culture/cli/shared/display.py +131 -0
- agentirc_cli-4.3.5/culture/cli/shared/ipc.py +68 -0
- agentirc_cli-4.3.5/culture/cli/shared/mesh.py +102 -0
- agentirc_cli-4.3.5/culture/cli/shared/process.py +144 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/cli/skills.py +18 -10
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/acp/agent_runner.py +79 -67
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/acp/daemon.py +52 -42
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/acp/irc_transport.py +15 -6
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/acp/skill/irc_client.py +8 -5
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/daemon.py +50 -40
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/irc_transport.py +15 -6
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/codex/agent_runner.py +83 -70
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/codex/daemon.py +52 -42
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/codex/irc_transport.py +15 -6
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/codex/supervisor.py +13 -11
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/copilot/agent_runner.py +14 -8
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/copilot/daemon.py +52 -42
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/copilot/irc_transport.py +15 -6
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/copilot/skill/irc_client.py +8 -5
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/observer.py +22 -9
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/overview/collector.py +27 -8
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/overview/renderer_web.py +100 -40
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/persistence.py +130 -97
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/protocol/replies.py +8 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/client.py +20 -14
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/server_link.py +92 -57
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/skills/history.py +3 -3
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/skills/rooms.py +116 -74
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/skills/threads.py +129 -110
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/packages/agent-harness/daemon.py +35 -21
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/pyproject.toml +1 -1
- agentirc_cli-4.3.5/tests/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/uv.lock +1 -1
- agentirc_cli-4.3.3/culture/cli/_helpers.py +0 -456
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.flake8 +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.github/workflows/pages.yml +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.gitignore +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.pr_agent.toml +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/.pylintrc +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/CLAUDE.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/CNAME +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/Gemfile +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/Gemfile.lock +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/LICENSE +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/README.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/SECURITY.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/_config.yml +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/__main__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/aio.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/bots/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/bots/bot.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/bots/config.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/cli/__init__.py +0 -0
- {agentirc_cli-4.3.3/culture/clients → agentirc_cli-4.3.5/culture/cli/shared}/__init__.py +0 -0
- {agentirc_cli-4.3.3/culture/clients/acp → agentirc_cli-4.3.5/culture/clients}/__init__.py +0 -0
- {agentirc_cli-4.3.3/culture/clients/acp/skill → agentirc_cli-4.3.5/culture/clients/acp}/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/acp/config.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.3/culture/clients/claude → agentirc_cli-4.3.5/culture/clients/acp/skill}/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-4.3.3/culture/clients/claude/skill → agentirc_cli-4.3.5/culture/clients/claude}/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/config.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.3/culture/clients/codex → agentirc_cli-4.3.5/culture/clients/claude/skill}/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-4.3.3/culture/clients/codex/skill → agentirc_cli-4.3.5/culture/clients/codex}/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/codex/config.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.3/culture/clients/copilot → agentirc_cli-4.3.5/culture/clients/codex/skill}/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-4.3.3/culture/clients/copilot/skill → agentirc_cli-4.3.5/culture/clients/copilot}/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/copilot/config.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.3/culture/protocol → agentirc_cli-4.3.5/culture/clients/copilot/skill}/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/console/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/console/app.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/console/client.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/console/commands.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/credentials.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/learn_prompt.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/mesh_config.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/overview/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/overview/model.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/overview/web/style.css +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/pidfile.py +0 -0
- {agentirc_cli-4.3.3/culture/server → agentirc_cli-4.3.5/culture/protocol}/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/protocol/commands.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/protocol/message.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-4.3.3/culture/server/skills → agentirc_cli-4.3.5/culture/server}/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/__main__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/channel.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/config.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/ircd.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/remote_client.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/room_store.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/rooms_util.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/skill.py +0 -0
- {agentirc_cli-4.3.3/tests → agentirc_cli-4.3.5/culture/server/skills}/__init__.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/skills/icon.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/server/thread_store.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/agent-lifecycle.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/agentic-self-learn.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/agent-client.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/harness-conformance.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/index.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/layer1-core-irc.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/layer2-attention.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/layer3-skills.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/layer4-federation.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/layer5-agent-harness.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/server-architecture.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/architecture/threads.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/channel-polling.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/acp/overview.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/codex/configuration.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/codex/overview.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/codex/setup.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/copilot/configuration.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/copilot/setup.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/culture-cli.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/getting-started.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/index.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/operations/SECURITY.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/operations/bots.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/operations/ci.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/operations/cli.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/operations/docs-site.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/operations/index.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/operations/ops-tooling.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/operations/overview.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/operations/publishing.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/rooms.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/server-rename.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/use-cases-index.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/docs/what-is-culture.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/packages/agent-harness/irc_transport.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/sonar-project.properties +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/conftest.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_archive.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_bot.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_bot_config.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_channel.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_connection.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_console_client.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_console_commands.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_console_connection.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_console_icons.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_console_integration.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_daemon.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_discovery.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_federation.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_history.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_http_listener.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_ipc.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_mention_target_cleanup.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_mentions.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_message.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_messaging.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_modes.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_overview_model.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_overview_web.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_persistence.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_pidfile.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_rooms.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_skill_client.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_skills.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_socket_server.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_supervisor.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_template_engine.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_threads.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-4.3.3 → agentirc_cli-4.3.5}/tests/test_webhook.py +0 -0
|
@@ -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
|
+
## [4.3.5] - 2026-04-07
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Reduce cognitive complexity in 30+ functions across backend clients, server code, CLI submodules, and standalone files to meet SonarCloud threshold (≤15)
|
|
13
|
+
|
|
14
|
+
## [4.3.4] - 2026-04-07
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Changed
|
|
18
|
+
|
|
19
|
+
- Extract duplicated string literals into named constants (SonarCloud S1192)
|
|
20
|
+
- Refactor cli/_helpers.py into modular cli/shared/ package (constants, ipc, process, mesh, display)
|
|
21
|
+
|
|
7
22
|
## [4.3.3] - 2026-04-07
|
|
8
23
|
|
|
9
24
|
|
|
@@ -13,6 +13,8 @@ if TYPE_CHECKING:
|
|
|
13
13
|
|
|
14
14
|
logger = logging.getLogger(__name__)
|
|
15
15
|
|
|
16
|
+
BOT_CONFIG_FILE = "bot.yaml"
|
|
17
|
+
|
|
16
18
|
|
|
17
19
|
class BotManager:
|
|
18
20
|
"""Loads, starts, stops, and dispatches webhooks to bots."""
|
|
@@ -27,7 +29,7 @@ class BotManager:
|
|
|
27
29
|
return
|
|
28
30
|
|
|
29
31
|
for bot_dir in sorted(BOTS_DIR.iterdir()):
|
|
30
|
-
yaml_path = bot_dir /
|
|
32
|
+
yaml_path = bot_dir / BOT_CONFIG_FILE
|
|
31
33
|
if not yaml_path.is_file():
|
|
32
34
|
continue
|
|
33
35
|
try:
|
|
@@ -45,7 +47,7 @@ class BotManager:
|
|
|
45
47
|
async def create_bot(self, config: BotConfig) -> Bot:
|
|
46
48
|
"""Create a new bot: write config to disk and start it."""
|
|
47
49
|
bot_dir = BOTS_DIR / config.name
|
|
48
|
-
save_bot_config(bot_dir /
|
|
50
|
+
save_bot_config(bot_dir / BOT_CONFIG_FILE, config)
|
|
49
51
|
|
|
50
52
|
bot = Bot(config, self.server)
|
|
51
53
|
self.bots[config.name] = bot
|
|
@@ -57,7 +59,7 @@ class BotManager:
|
|
|
57
59
|
bot = self.bots.get(name)
|
|
58
60
|
if not bot:
|
|
59
61
|
# Try loading from disk
|
|
60
|
-
yaml_path = BOTS_DIR / name /
|
|
62
|
+
yaml_path = BOTS_DIR / name / BOT_CONFIG_FILE
|
|
61
63
|
if not yaml_path.is_file():
|
|
62
64
|
raise ValueError(f"Bot {name!r} not found")
|
|
63
65
|
config = load_bot_config(yaml_path)
|
|
@@ -27,18 +27,16 @@ from culture.pidfile import (
|
|
|
27
27
|
write_pid,
|
|
28
28
|
)
|
|
29
29
|
|
|
30
|
-
from .
|
|
30
|
+
from .shared.constants import (
|
|
31
31
|
_CONFIG_HELP,
|
|
32
|
+
DEFAULT_CHANNEL,
|
|
32
33
|
DEFAULT_CONFIG,
|
|
33
34
|
LOG_DIR,
|
|
34
|
-
|
|
35
|
-
get_observer,
|
|
36
|
-
ipc_request,
|
|
37
|
-
print_agent_detail,
|
|
38
|
-
print_agents_overview,
|
|
39
|
-
print_bot_listing,
|
|
40
|
-
stop_agent,
|
|
35
|
+
NO_AGENTS_MSG,
|
|
41
36
|
)
|
|
37
|
+
from .shared.display import print_agent_detail, print_agents_overview, print_bot_listing
|
|
38
|
+
from .shared.ipc import agent_socket_path, get_observer, ipc_request
|
|
39
|
+
from .shared.process import stop_agent
|
|
42
40
|
|
|
43
41
|
logger = logging.getLogger("culture")
|
|
44
42
|
|
|
@@ -203,59 +201,83 @@ def dispatch(args: argparse.Namespace) -> None:
|
|
|
203
201
|
# -----------------------------------------------------------------------
|
|
204
202
|
|
|
205
203
|
|
|
206
|
-
def
|
|
207
|
-
"""Build a
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
)
|
|
217
|
-
if args.agent == "copilot":
|
|
218
|
-
from culture.clients.copilot.config import AgentConfig as CopilotAgentConfig
|
|
219
|
-
|
|
220
|
-
return CopilotAgentConfig(
|
|
221
|
-
nick=full_nick,
|
|
222
|
-
agent="copilot",
|
|
223
|
-
directory=os.getcwd(),
|
|
224
|
-
channels=["#general"],
|
|
225
|
-
)
|
|
226
|
-
if args.agent == "acp":
|
|
227
|
-
import json as _json
|
|
204
|
+
def _create_codex_config(full_nick: str) -> AgentConfig:
|
|
205
|
+
"""Build a CodexAgentConfig."""
|
|
206
|
+
from culture.clients.codex.config import AgentConfig as CodexAgentConfig
|
|
207
|
+
|
|
208
|
+
return CodexAgentConfig(
|
|
209
|
+
nick=full_nick,
|
|
210
|
+
agent="codex",
|
|
211
|
+
directory=os.getcwd(),
|
|
212
|
+
channels=[DEFAULT_CHANNEL],
|
|
213
|
+
)
|
|
228
214
|
|
|
229
|
-
from culture.clients.acp.config import AgentConfig as ACPAgentConfig
|
|
230
215
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
216
|
+
def _create_copilot_config(full_nick: str) -> AgentConfig:
|
|
217
|
+
"""Build a CopilotAgentConfig."""
|
|
218
|
+
from culture.clients.copilot.config import AgentConfig as CopilotAgentConfig
|
|
219
|
+
|
|
220
|
+
return CopilotAgentConfig(
|
|
221
|
+
nick=full_nick,
|
|
222
|
+
agent="copilot",
|
|
223
|
+
directory=os.getcwd(),
|
|
224
|
+
channels=[DEFAULT_CHANNEL],
|
|
225
|
+
)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def _parse_acp_command(raw_command: str | None) -> list[str]:
|
|
229
|
+
"""Parse and validate the ACP command from CLI args."""
|
|
230
|
+
import json as _json
|
|
231
|
+
|
|
232
|
+
acp_cmd = ["opencode", "acp"]
|
|
233
|
+
if raw_command:
|
|
234
|
+
try:
|
|
235
|
+
acp_cmd = _json.loads(raw_command)
|
|
236
|
+
except _json.JSONDecodeError:
|
|
237
|
+
acp_cmd = raw_command.split()
|
|
238
|
+
if not isinstance(acp_cmd, list) or not acp_cmd or not all(isinstance(s, str) for s in acp_cmd):
|
|
239
|
+
print("Error: --acp-command must be a non-empty list of strings", file=sys.stderr)
|
|
240
|
+
sys.exit(1)
|
|
241
|
+
return acp_cmd
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _create_acp_config(full_nick: str, args: argparse.Namespace) -> AgentConfig:
|
|
245
|
+
"""Build an ACPAgentConfig."""
|
|
246
|
+
from culture.clients.acp.config import AgentConfig as ACPAgentConfig
|
|
247
|
+
|
|
248
|
+
acp_cmd = _parse_acp_command(args.acp_command)
|
|
249
|
+
return ACPAgentConfig(
|
|
250
|
+
nick=full_nick,
|
|
251
|
+
agent="acp",
|
|
252
|
+
acp_command=acp_cmd,
|
|
253
|
+
directory=os.getcwd(),
|
|
254
|
+
channels=[DEFAULT_CHANNEL],
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
def _create_default_config(full_nick: str, backend: str) -> AgentConfig:
|
|
259
|
+
"""Build a default (claude) AgentConfig."""
|
|
251
260
|
return AgentConfig(
|
|
252
261
|
nick=full_nick,
|
|
253
|
-
agent=
|
|
262
|
+
agent=backend,
|
|
254
263
|
directory=os.getcwd(),
|
|
255
|
-
channels=[
|
|
264
|
+
channels=[DEFAULT_CHANNEL],
|
|
256
265
|
)
|
|
257
266
|
|
|
258
267
|
|
|
268
|
+
def _create_agent_config(args: argparse.Namespace, full_nick: str) -> AgentConfig:
|
|
269
|
+
"""Build a backend-specific AgentConfig from CLI args."""
|
|
270
|
+
factories = {
|
|
271
|
+
"codex": lambda: _create_codex_config(full_nick),
|
|
272
|
+
"copilot": lambda: _create_copilot_config(full_nick),
|
|
273
|
+
"acp": lambda: _create_acp_config(full_nick, args),
|
|
274
|
+
}
|
|
275
|
+
factory = factories.get(args.agent)
|
|
276
|
+
if factory:
|
|
277
|
+
return factory()
|
|
278
|
+
return _create_default_config(full_nick, args.agent)
|
|
279
|
+
|
|
280
|
+
|
|
259
281
|
def _cmd_create(args: argparse.Namespace) -> None:
|
|
260
282
|
config = load_config_or_default(args.config)
|
|
261
283
|
|
|
@@ -365,7 +387,7 @@ def _resolve_agents_to_start(config, args) -> list:
|
|
|
365
387
|
agents = _resolve_auto(config)
|
|
366
388
|
|
|
367
389
|
if not agents:
|
|
368
|
-
print(
|
|
390
|
+
print(NO_AGENTS_MSG, file=sys.stderr)
|
|
369
391
|
sys.exit(1)
|
|
370
392
|
return agents
|
|
371
393
|
|
|
@@ -389,6 +411,32 @@ def _probe_server_connection(host: str, port: int, server_name: str) -> None:
|
|
|
389
411
|
sys.exit(1)
|
|
390
412
|
|
|
391
413
|
|
|
414
|
+
def _start_foreground(config: DaemonConfig, agents: list[AgentConfig]) -> None:
|
|
415
|
+
"""Start a single agent in the foreground."""
|
|
416
|
+
if len(agents) != 1:
|
|
417
|
+
print("--foreground requires a single agent nick, not --all", file=sys.stderr)
|
|
418
|
+
sys.exit(1)
|
|
419
|
+
agent = agents[0]
|
|
420
|
+
print(f"Starting agent {agent.nick} in foreground...")
|
|
421
|
+
asyncio.run(_run_single_agent(config, agent))
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def _start_background(config: DaemonConfig, agents: list[AgentConfig]) -> None:
|
|
425
|
+
"""Start agents in background mode (fork on Unix, single on Windows)."""
|
|
426
|
+
if sys.platform == "win32":
|
|
427
|
+
if len(agents) != 1:
|
|
428
|
+
print(
|
|
429
|
+
"Multi-agent daemon mode not supported on Windows. Start agents individually.",
|
|
430
|
+
file=sys.stderr,
|
|
431
|
+
)
|
|
432
|
+
sys.exit(1)
|
|
433
|
+
agent = agents[0]
|
|
434
|
+
print(f"Starting agent {agent.nick}...")
|
|
435
|
+
asyncio.run(_run_single_agent(config, agent))
|
|
436
|
+
else:
|
|
437
|
+
_run_multi_agents(config, agents)
|
|
438
|
+
|
|
439
|
+
|
|
392
440
|
def _cmd_start(args: argparse.Namespace) -> None:
|
|
393
441
|
config = load_config(args.config)
|
|
394
442
|
|
|
@@ -397,86 +445,88 @@ def _cmd_start(args: argparse.Namespace) -> None:
|
|
|
397
445
|
server_name = config.server.name
|
|
398
446
|
_probe_server_connection(config.server.host, config.server.port, server_name)
|
|
399
447
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
if foreground:
|
|
403
|
-
if len(agents) != 1:
|
|
404
|
-
print("--foreground requires a single agent nick, not --all", file=sys.stderr)
|
|
405
|
-
sys.exit(1)
|
|
406
|
-
agent = agents[0]
|
|
407
|
-
print(f"Starting agent {agent.nick} in foreground...")
|
|
408
|
-
asyncio.run(_run_single_agent(config, agent))
|
|
448
|
+
if getattr(args, "foreground", False):
|
|
449
|
+
_start_foreground(config, agents)
|
|
409
450
|
else:
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
451
|
+
_start_background(config, agents)
|
|
452
|
+
|
|
453
|
+
|
|
454
|
+
def _make_backend_config(config: DaemonConfig, backend_daemon_config_cls):
|
|
455
|
+
"""Build a backend-specific DaemonConfig from the base config."""
|
|
456
|
+
return backend_daemon_config_cls(
|
|
457
|
+
server=config.server,
|
|
458
|
+
webhooks=config.webhooks,
|
|
459
|
+
buffer_size=config.buffer_size,
|
|
460
|
+
agents=config.agents,
|
|
461
|
+
)
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
def _create_codex_daemon(config: DaemonConfig, agent: AgentConfig):
|
|
465
|
+
"""Create a Codex backend daemon."""
|
|
466
|
+
from culture.clients.codex.config import DaemonConfig as CodexDaemonConfig
|
|
467
|
+
from culture.clients.codex.daemon import CodexDaemon
|
|
468
|
+
|
|
469
|
+
return CodexDaemon(_make_backend_config(config, CodexDaemonConfig), agent)
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def _coerce_to_acp_agent(agent: AgentConfig):
|
|
473
|
+
"""Ensure agent is an ACPAgentConfig, converting if necessary."""
|
|
474
|
+
from culture.clients.acp.config import AgentConfig as ACPAgentConfig
|
|
475
|
+
|
|
476
|
+
if isinstance(agent, ACPAgentConfig):
|
|
477
|
+
return agent
|
|
478
|
+
return ACPAgentConfig(
|
|
479
|
+
nick=agent.nick,
|
|
480
|
+
agent="acp",
|
|
481
|
+
acp_command=getattr(agent, "acp_command", None) or ["opencode", "acp"],
|
|
482
|
+
directory=agent.directory,
|
|
483
|
+
channels=agent.channels,
|
|
484
|
+
model=agent.model,
|
|
485
|
+
system_prompt=agent.system_prompt,
|
|
486
|
+
tags=agent.tags,
|
|
487
|
+
)
|
|
488
|
+
|
|
489
|
+
|
|
490
|
+
def _create_acp_daemon(config: DaemonConfig, agent: AgentConfig):
|
|
491
|
+
"""Create an ACP backend daemon."""
|
|
492
|
+
from culture.clients.acp.config import DaemonConfig as ACPDaemonConfig
|
|
493
|
+
from culture.clients.acp.daemon import ACPDaemon
|
|
494
|
+
|
|
495
|
+
return ACPDaemon(
|
|
496
|
+
_make_backend_config(config, ACPDaemonConfig),
|
|
497
|
+
_coerce_to_acp_agent(agent),
|
|
498
|
+
)
|
|
499
|
+
|
|
500
|
+
|
|
501
|
+
def _create_copilot_daemon(config: DaemonConfig, agent: AgentConfig):
|
|
502
|
+
"""Create a Copilot backend daemon."""
|
|
503
|
+
from culture.clients.copilot.config import DaemonConfig as CopilotDaemonConfig
|
|
504
|
+
from culture.clients.copilot.daemon import CopilotDaemon
|
|
505
|
+
|
|
506
|
+
return CopilotDaemon(_make_backend_config(config, CopilotDaemonConfig), agent)
|
|
507
|
+
|
|
508
|
+
|
|
509
|
+
def _create_claude_daemon(config: DaemonConfig, agent: AgentConfig):
|
|
510
|
+
"""Create the default Claude backend daemon."""
|
|
511
|
+
from culture.clients.claude.daemon import AgentDaemon
|
|
512
|
+
|
|
513
|
+
return AgentDaemon(config, agent)
|
|
514
|
+
|
|
515
|
+
|
|
516
|
+
_BACKEND_DAEMON_FACTORIES = {
|
|
517
|
+
"codex": _create_codex_daemon,
|
|
518
|
+
"acp": _create_acp_daemon,
|
|
519
|
+
"opencode": _create_acp_daemon,
|
|
520
|
+
"copilot": _create_copilot_daemon,
|
|
521
|
+
}
|
|
423
522
|
|
|
424
523
|
|
|
425
524
|
async def _run_single_agent(config: DaemonConfig, agent: AgentConfig) -> None:
|
|
426
525
|
"""Run a single agent daemon in the foreground."""
|
|
427
526
|
backend = getattr(agent, "agent", "claude")
|
|
428
527
|
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
from culture.clients.codex.daemon import CodexDaemon
|
|
432
|
-
|
|
433
|
-
codex_config = CodexDaemonConfig(
|
|
434
|
-
server=config.server,
|
|
435
|
-
webhooks=config.webhooks,
|
|
436
|
-
buffer_size=config.buffer_size,
|
|
437
|
-
agents=config.agents,
|
|
438
|
-
)
|
|
439
|
-
daemon = CodexDaemon(codex_config, agent)
|
|
440
|
-
elif backend in ("acp", "opencode"):
|
|
441
|
-
from culture.clients.acp.config import AgentConfig as ACPAgentConfig
|
|
442
|
-
from culture.clients.acp.config import DaemonConfig as ACPDaemonConfig
|
|
443
|
-
from culture.clients.acp.daemon import ACPDaemon
|
|
444
|
-
|
|
445
|
-
acp_config = ACPDaemonConfig(
|
|
446
|
-
server=config.server,
|
|
447
|
-
webhooks=config.webhooks,
|
|
448
|
-
buffer_size=config.buffer_size,
|
|
449
|
-
agents=config.agents,
|
|
450
|
-
)
|
|
451
|
-
if not isinstance(agent, ACPAgentConfig):
|
|
452
|
-
acp_agent = ACPAgentConfig(
|
|
453
|
-
nick=agent.nick,
|
|
454
|
-
agent="acp",
|
|
455
|
-
acp_command=getattr(agent, "acp_command", None) or ["opencode", "acp"],
|
|
456
|
-
directory=agent.directory,
|
|
457
|
-
channels=agent.channels,
|
|
458
|
-
model=agent.model,
|
|
459
|
-
system_prompt=agent.system_prompt,
|
|
460
|
-
tags=agent.tags,
|
|
461
|
-
)
|
|
462
|
-
else:
|
|
463
|
-
acp_agent = agent
|
|
464
|
-
daemon = ACPDaemon(acp_config, acp_agent)
|
|
465
|
-
elif backend == "copilot":
|
|
466
|
-
from culture.clients.copilot.config import DaemonConfig as CopilotDaemonConfig
|
|
467
|
-
from culture.clients.copilot.daemon import CopilotDaemon
|
|
468
|
-
|
|
469
|
-
copilot_config = CopilotDaemonConfig(
|
|
470
|
-
server=config.server,
|
|
471
|
-
webhooks=config.webhooks,
|
|
472
|
-
buffer_size=config.buffer_size,
|
|
473
|
-
agents=config.agents,
|
|
474
|
-
)
|
|
475
|
-
daemon = CopilotDaemon(copilot_config, agent)
|
|
476
|
-
else:
|
|
477
|
-
from culture.clients.claude.daemon import AgentDaemon
|
|
478
|
-
|
|
479
|
-
daemon = AgentDaemon(config, agent)
|
|
528
|
+
factory = _BACKEND_DAEMON_FACTORIES.get(backend, _create_claude_daemon)
|
|
529
|
+
daemon = factory(config, agent)
|
|
480
530
|
|
|
481
531
|
stop_event = asyncio.Event()
|
|
482
532
|
daemon.set_stop_event(stop_event)
|
|
@@ -526,30 +576,31 @@ def _run_multi_agents(config: DaemonConfig, agents: list[AgentConfig]) -> None:
|
|
|
526
576
|
print(f"Started {agent.nick} (PID {pid})")
|
|
527
577
|
|
|
528
578
|
|
|
529
|
-
def
|
|
530
|
-
|
|
531
|
-
|
|
579
|
+
def _resolve_agents_to_stop(config, args) -> list:
|
|
580
|
+
"""Resolve which agents should be stopped, or exit with an error."""
|
|
532
581
|
if args.all:
|
|
533
|
-
|
|
534
|
-
|
|
582
|
+
return config.agents
|
|
583
|
+
if args.nick:
|
|
535
584
|
agent = config.get_agent(args.nick)
|
|
536
585
|
if not agent:
|
|
537
586
|
print(f"Agent '{args.nick}' not found in config", file=sys.stderr)
|
|
538
587
|
sys.exit(1)
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
)
|
|
551
|
-
sys.exit(1)
|
|
588
|
+
return [agent]
|
|
589
|
+
if len(config.agents) == 1:
|
|
590
|
+
return config.agents
|
|
591
|
+
if len(config.agents) == 0:
|
|
592
|
+
print(NO_AGENTS_MSG, file=sys.stderr)
|
|
593
|
+
sys.exit(1)
|
|
594
|
+
print(
|
|
595
|
+
"Multiple agents configured. Specify a nick or use --all.",
|
|
596
|
+
file=sys.stderr,
|
|
597
|
+
)
|
|
598
|
+
sys.exit(1)
|
|
552
599
|
|
|
600
|
+
|
|
601
|
+
def _cmd_stop(args: argparse.Namespace) -> None:
|
|
602
|
+
config = load_config_or_default(args.config)
|
|
603
|
+
agents = _resolve_agents_to_stop(config, args)
|
|
553
604
|
for agent in agents:
|
|
554
605
|
stop_agent(agent.nick)
|
|
555
606
|
|
|
@@ -574,14 +625,14 @@ def _no_agents_message(config, show_all: bool) -> str:
|
|
|
574
625
|
archived_count = sum(1 for a in config.agents if a.archived)
|
|
575
626
|
if archived_count:
|
|
576
627
|
return f"No active agents ({archived_count} archived, use --all to show)"
|
|
577
|
-
return
|
|
628
|
+
return NO_AGENTS_MSG
|
|
578
629
|
|
|
579
630
|
|
|
580
631
|
def _cmd_status(args: argparse.Namespace) -> None:
|
|
581
632
|
config = load_config_or_default(args.config)
|
|
582
633
|
|
|
583
634
|
if not config.agents:
|
|
584
|
-
print(
|
|
635
|
+
print(NO_AGENTS_MSG)
|
|
585
636
|
return
|
|
586
637
|
|
|
587
638
|
if args.nick:
|
|
@@ -8,7 +8,7 @@ import time
|
|
|
8
8
|
|
|
9
9
|
from culture.clients.claude.config import load_config_or_default
|
|
10
10
|
|
|
11
|
-
from .
|
|
11
|
+
from .shared.constants import _BOT_NAME_HELP, _CONFIG_HELP, BOT_CONFIG_FILE, DEFAULT_CONFIG
|
|
12
12
|
|
|
13
13
|
NAME = "bot"
|
|
14
14
|
|
|
@@ -31,11 +31,11 @@ def register(subparsers: argparse._SubParsersAction) -> None:
|
|
|
31
31
|
bot_create.add_argument("--config", default=DEFAULT_CONFIG, help=_CONFIG_HELP)
|
|
32
32
|
|
|
33
33
|
bot_start = bot_sub.add_parser("start", help="Start a bot")
|
|
34
|
-
bot_start.add_argument("name", help=
|
|
34
|
+
bot_start.add_argument("name", help=_BOT_NAME_HELP)
|
|
35
35
|
bot_start.add_argument("--config", default=DEFAULT_CONFIG, help=_CONFIG_HELP)
|
|
36
36
|
|
|
37
37
|
bot_stop = bot_sub.add_parser("stop", help="Stop a bot")
|
|
38
|
-
bot_stop.add_argument("name", help=
|
|
38
|
+
bot_stop.add_argument("name", help=_BOT_NAME_HELP)
|
|
39
39
|
bot_stop.add_argument("--config", default=DEFAULT_CONFIG, help=_CONFIG_HELP)
|
|
40
40
|
|
|
41
41
|
bot_list = bot_sub.add_parser("list", help="List bots")
|
|
@@ -43,7 +43,7 @@ def register(subparsers: argparse._SubParsersAction) -> None:
|
|
|
43
43
|
bot_list.add_argument("--all", action="store_true", help="Include archived bots")
|
|
44
44
|
|
|
45
45
|
bot_inspect = bot_sub.add_parser("inspect", help="Show bot details")
|
|
46
|
-
bot_inspect.add_argument("name", help=
|
|
46
|
+
bot_inspect.add_argument("name", help=_BOT_NAME_HELP)
|
|
47
47
|
bot_inspect.add_argument("--config", default=DEFAULT_CONFIG, help=_CONFIG_HELP)
|
|
48
48
|
|
|
49
49
|
bot_archive = bot_sub.add_parser("archive", help="Archive a bot")
|
|
@@ -113,11 +113,11 @@ def _bot_create(args: argparse.Namespace) -> None:
|
|
|
113
113
|
)
|
|
114
114
|
|
|
115
115
|
bot_dir = BOTS_DIR / name
|
|
116
|
-
if (bot_dir /
|
|
116
|
+
if (bot_dir / BOT_CONFIG_FILE).exists():
|
|
117
117
|
print(f"Bot '{name}' already exists at {bot_dir}", file=sys.stderr)
|
|
118
118
|
sys.exit(1)
|
|
119
119
|
|
|
120
|
-
save_bot_config(bot_dir /
|
|
120
|
+
save_bot_config(bot_dir / BOT_CONFIG_FILE, bot_config)
|
|
121
121
|
print(f"Bot '{name}' created at {bot_dir}")
|
|
122
122
|
print(f" Owner: {args.owner}")
|
|
123
123
|
print(f" Trigger: {args.trigger}")
|
|
@@ -132,7 +132,7 @@ def _bot_start(args: argparse.Namespace) -> None:
|
|
|
132
132
|
from culture.bots.config import BOTS_DIR
|
|
133
133
|
|
|
134
134
|
bot_dir = BOTS_DIR / args.name
|
|
135
|
-
if not (bot_dir /
|
|
135
|
+
if not (bot_dir / BOT_CONFIG_FILE).exists():
|
|
136
136
|
print(f"Bot '{args.name}' not found at {bot_dir}", file=sys.stderr)
|
|
137
137
|
sys.exit(1)
|
|
138
138
|
|
|
@@ -144,7 +144,7 @@ def _bot_stop(args: argparse.Namespace) -> None:
|
|
|
144
144
|
from culture.bots.config import BOTS_DIR
|
|
145
145
|
|
|
146
146
|
bot_dir = BOTS_DIR / args.name
|
|
147
|
-
if not (bot_dir /
|
|
147
|
+
if not (bot_dir / BOT_CONFIG_FILE).exists():
|
|
148
148
|
print(f"Bot '{args.name}' not found at {bot_dir}", file=sys.stderr)
|
|
149
149
|
sys.exit(1)
|
|
150
150
|
|
|
@@ -152,6 +152,15 @@ def _bot_stop(args: argparse.Namespace) -> None:
|
|
|
152
152
|
print("(Live reload via IPC will be available in a future release.)")
|
|
153
153
|
|
|
154
154
|
|
|
155
|
+
def _should_include_bot(bot_config, owner: str | None, show_archived: bool) -> bool:
|
|
156
|
+
"""Return True if the bot should be included in the listing."""
|
|
157
|
+
if owner and bot_config.owner != owner:
|
|
158
|
+
return False
|
|
159
|
+
if not show_archived and bot_config.archived:
|
|
160
|
+
return False
|
|
161
|
+
return True
|
|
162
|
+
|
|
163
|
+
|
|
155
164
|
def _load_and_filter_bots(args) -> list:
|
|
156
165
|
"""Load bot configs, filtering by owner and archived status."""
|
|
157
166
|
from culture.bots.config import BOTS_DIR, load_bot_config
|
|
@@ -161,18 +170,15 @@ def _load_and_filter_bots(args) -> list:
|
|
|
161
170
|
show_all = getattr(args, "all", False)
|
|
162
171
|
bots = []
|
|
163
172
|
for bot_dir in sorted(BOTS_DIR.iterdir()):
|
|
164
|
-
yaml_path = bot_dir /
|
|
173
|
+
yaml_path = bot_dir / BOT_CONFIG_FILE
|
|
165
174
|
if not yaml_path.is_file():
|
|
166
175
|
continue
|
|
167
176
|
try:
|
|
168
177
|
config = load_bot_config(yaml_path)
|
|
169
178
|
except Exception:
|
|
170
179
|
continue
|
|
171
|
-
if
|
|
172
|
-
|
|
173
|
-
if not show_all and config.archived:
|
|
174
|
-
continue
|
|
175
|
-
bots.append(config)
|
|
180
|
+
if _should_include_bot(config, args.owner, show_all):
|
|
181
|
+
bots.append(config)
|
|
176
182
|
return bots
|
|
177
183
|
|
|
178
184
|
|
|
@@ -203,7 +209,7 @@ def _bot_inspect(args: argparse.Namespace) -> None:
|
|
|
203
209
|
from culture.bots.config import BOTS_DIR, load_bot_config
|
|
204
210
|
|
|
205
211
|
bot_dir = BOTS_DIR / args.name
|
|
206
|
-
yaml_path = bot_dir /
|
|
212
|
+
yaml_path = bot_dir / BOT_CONFIG_FILE
|
|
207
213
|
if not yaml_path.is_file():
|
|
208
214
|
print(f"Bot '{args.name}' not found at {bot_dir}", file=sys.stderr)
|
|
209
215
|
sys.exit(1)
|
|
@@ -245,7 +251,7 @@ def _bot_archive(args: argparse.Namespace) -> None:
|
|
|
245
251
|
from culture.bots.config import BOTS_DIR, load_bot_config, save_bot_config
|
|
246
252
|
|
|
247
253
|
bot_dir = BOTS_DIR / args.name
|
|
248
|
-
yaml_path = bot_dir /
|
|
254
|
+
yaml_path = bot_dir / BOT_CONFIG_FILE
|
|
249
255
|
if not yaml_path.is_file():
|
|
250
256
|
print(f"Bot '{args.name}' not found at {bot_dir}", file=sys.stderr)
|
|
251
257
|
sys.exit(1)
|
|
@@ -270,7 +276,7 @@ def _bot_unarchive(args: argparse.Namespace) -> None:
|
|
|
270
276
|
from culture.bots.config import BOTS_DIR, load_bot_config, save_bot_config
|
|
271
277
|
|
|
272
278
|
bot_dir = BOTS_DIR / args.name
|
|
273
|
-
yaml_path = bot_dir /
|
|
279
|
+
yaml_path = bot_dir / BOT_CONFIG_FILE
|
|
274
280
|
if not yaml_path.is_file():
|
|
275
281
|
print(f"Bot '{args.name}' not found at {bot_dir}", file=sys.stderr)
|
|
276
282
|
sys.exit(1)
|