agentirc-cli 4.3.1__tar.gz → 4.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/CHANGELOG.md +7 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/PKG-INFO +1 -1
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/cli/_helpers.py +52 -32
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/cli/agent.py +100 -101
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/cli/bot.py +20 -12
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/cli/mesh.py +44 -38
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/cli/server.py +95 -93
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/agent_runner.py +35 -29
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/pyproject.toml +1 -1
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/uv.lock +1 -1
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.flake8 +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.github/workflows/pages.yml +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.gitignore +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.pr_agent.toml +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/.pylintrc +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/CLAUDE.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/CNAME +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/Gemfile +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/Gemfile.lock +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/LICENSE +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/README.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/SECURITY.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/_config.yml +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/__main__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/aio.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/bots/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/bots/bot.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/bots/bot_manager.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/bots/config.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/cli/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/cli/channel.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/cli/skills.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/config.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/daemon.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/irc_transport.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/config.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/daemon.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/irc_transport.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/agent_runner.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/config.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/daemon.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/irc_transport.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/agent_runner.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/config.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/daemon.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/irc_transport.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/console/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/console/app.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/console/client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/console/commands.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/credentials.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/learn_prompt.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/mesh_config.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/observer.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/overview/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/overview/collector.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/overview/model.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/overview/web/style.css +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/persistence.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/pidfile.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/protocol/commands.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/protocol/message.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/protocol/replies.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/__main__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/channel.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/config.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/ircd.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/remote_client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/room_store.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/rooms_util.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/server_link.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/skill.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/skills/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/skills/history.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/skills/icon.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/skills/rooms.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/skills/threads.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/server/thread_store.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/agent-lifecycle.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/agentic-self-learn.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/agent-client.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/harness-conformance.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/index.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/layer1-core-irc.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/layer2-attention.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/layer3-skills.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/layer4-federation.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/layer5-agent-harness.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/server-architecture.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/architecture/threads.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/channel-polling.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/acp/overview.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/codex/configuration.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/codex/overview.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/codex/setup.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/copilot/configuration.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/copilot/setup.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/culture-cli.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/getting-started.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/index.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/operations/SECURITY.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/operations/bots.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/operations/ci.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/operations/cli.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/operations/docs-site.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/operations/index.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/operations/ops-tooling.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/operations/overview.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/operations/publishing.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/rooms.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/server-rename.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/use-cases-index.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/docs/what-is-culture.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/packages/agent-harness/daemon.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/packages/agent-harness/irc_transport.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/sonar-project.properties +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/__init__.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/conftest.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_archive.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_bot.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_bot_config.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_channel.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_connection.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_console_client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_console_commands.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_console_connection.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_console_icons.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_console_integration.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_daemon.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_discovery.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_federation.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_history.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_http_listener.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_ipc.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_mention_target_cleanup.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_mentions.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_message.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_messaging.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_modes.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_overview_model.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_overview_web.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_persistence.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_pidfile.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_rooms.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_skill_client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_skills.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_socket_server.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_supervisor.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_template_engine.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_threads.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-4.3.1 → agentirc_cli-4.3.2}/tests/test_webhook.py +0 -0
|
@@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/).
|
|
6
6
|
|
|
7
|
+
## [4.3.2] - 2026-04-07
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Reduced cognitive complexity in 13 functions across 6 files by extracting helpers and flattening control flow (SonarCloud S3776)
|
|
13
|
+
|
|
7
14
|
## [4.3.1] - 2026-04-07
|
|
8
15
|
|
|
9
16
|
|
|
@@ -381,6 +381,25 @@ def print_agent_detail(agent, config_path: str, args: argparse.Namespace) -> Non
|
|
|
381
381
|
print(f" Config: {config_path}")
|
|
382
382
|
|
|
383
383
|
|
|
384
|
+
def _format_agent_status(base_status: str, archived: bool, show_archived_marker: bool) -> str:
|
|
385
|
+
"""Format the display status string for an agent."""
|
|
386
|
+
if not archived:
|
|
387
|
+
return base_status
|
|
388
|
+
if show_archived_marker:
|
|
389
|
+
return f"{base_status} (archived)"
|
|
390
|
+
if base_status == "stopped":
|
|
391
|
+
return "archived"
|
|
392
|
+
return base_status
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def _fetch_agent_activity(agent) -> str:
|
|
396
|
+
"""Fetch activity description from a running agent via IPC."""
|
|
397
|
+
resp = asyncio.run(ipc_request(agent_socket_path(agent.nick), "status"))
|
|
398
|
+
if resp and resp.get("ok"):
|
|
399
|
+
return resp.get("data", {}).get("description", "nothing")
|
|
400
|
+
return "-"
|
|
401
|
+
|
|
402
|
+
|
|
384
403
|
def print_agents_overview(
|
|
385
404
|
agents: list, show_activity: bool, show_archived_marker: bool = False
|
|
386
405
|
) -> None:
|
|
@@ -393,44 +412,45 @@ def print_agents_overview(
|
|
|
393
412
|
print("-" * 52)
|
|
394
413
|
|
|
395
414
|
for agent in agents:
|
|
396
|
-
archived = getattr(agent, "archived", False)
|
|
397
415
|
base_status, pid = agent_process_status(agent)
|
|
398
|
-
status =
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
activity = "-"
|
|
405
|
-
|
|
406
|
-
if show_activity and base_status == "running":
|
|
407
|
-
resp = asyncio.run(ipc_request(agent_socket_path(agent.nick), "status"))
|
|
408
|
-
if resp and resp.get("ok"):
|
|
409
|
-
activity = resp.get("data", {}).get("description", "nothing")
|
|
410
|
-
|
|
416
|
+
status = _format_agent_status(
|
|
417
|
+
base_status, getattr(agent, "archived", False), show_archived_marker
|
|
418
|
+
)
|
|
419
|
+
activity = (
|
|
420
|
+
_fetch_agent_activity(agent) if show_activity and base_status == "running" else "-"
|
|
421
|
+
)
|
|
411
422
|
if show_activity:
|
|
412
423
|
print(f"{agent.nick:<30} {status:<12} {str(pid or '-'):<10} {activity}")
|
|
413
424
|
else:
|
|
414
425
|
print(f"{agent.nick:<30} {status:<12} {str(pid or '-'):<10}")
|
|
415
426
|
|
|
416
427
|
|
|
417
|
-
def
|
|
418
|
-
"""
|
|
428
|
+
def _load_bot_configs() -> list:
|
|
429
|
+
"""Load all valid bot configs from the bots directory."""
|
|
419
430
|
from culture.bots.config import BOTS_DIR, load_bot_config
|
|
420
431
|
|
|
421
|
-
if BOTS_DIR.is_dir():
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
432
|
+
if not BOTS_DIR.is_dir():
|
|
433
|
+
return []
|
|
434
|
+
configs = []
|
|
435
|
+
for bot_dir in sorted(BOTS_DIR.iterdir()):
|
|
436
|
+
yaml_path = bot_dir / "bot.yaml"
|
|
437
|
+
if not yaml_path.is_file():
|
|
438
|
+
continue
|
|
439
|
+
try:
|
|
440
|
+
configs.append(load_bot_config(yaml_path))
|
|
441
|
+
except Exception:
|
|
442
|
+
pass
|
|
443
|
+
return configs
|
|
444
|
+
|
|
445
|
+
|
|
446
|
+
def print_bot_listing() -> None:
|
|
447
|
+
"""Print a table of configured bots (if any exist)."""
|
|
448
|
+
bot_configs = _load_bot_configs()
|
|
449
|
+
if not bot_configs:
|
|
450
|
+
return
|
|
451
|
+
print()
|
|
452
|
+
print(f"{'BOT':<30} {'TRIGGER':<12} {'CHANNELS'}")
|
|
453
|
+
print("-" * 60)
|
|
454
|
+
for bc in bot_configs:
|
|
455
|
+
channels = ", ".join(bc.channels) if bc.channels else "-"
|
|
456
|
+
print(f"{bc.name:<30} {bc.trigger_type:<12} {channels}")
|
|
@@ -315,52 +315,58 @@ def _cmd_join(args: argparse.Namespace) -> None:
|
|
|
315
315
|
# -----------------------------------------------------------------------
|
|
316
316
|
|
|
317
317
|
|
|
318
|
+
def _get_active_agents(config) -> list:
|
|
319
|
+
"""Return non-archived agents."""
|
|
320
|
+
return [a for a in config.agents if not a.archived]
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def _resolve_by_nick(config, nick: str):
|
|
324
|
+
"""Look up a single agent by nick, exit on error."""
|
|
325
|
+
agent = config.get_agent(nick)
|
|
326
|
+
if not agent:
|
|
327
|
+
print(f"Agent '{nick}' not found in config", file=sys.stderr)
|
|
328
|
+
sys.exit(1)
|
|
329
|
+
if agent.archived:
|
|
330
|
+
print(f"Agent '{nick}' is archived. Unarchive first:", file=sys.stderr)
|
|
331
|
+
print(f" culture agent unarchive {nick}", file=sys.stderr)
|
|
332
|
+
sys.exit(1)
|
|
333
|
+
return agent
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
def _resolve_auto(config) -> list:
|
|
337
|
+
"""Auto-resolve agents when no nick or --all given, exit if ambiguous."""
|
|
338
|
+
active = _get_active_agents(config)
|
|
339
|
+
if len(active) == 1:
|
|
340
|
+
return active
|
|
341
|
+
if len(active) == 0:
|
|
342
|
+
archived_count = sum(1 for a in config.agents if a.archived)
|
|
343
|
+
if archived_count:
|
|
344
|
+
print(
|
|
345
|
+
f"No active agents ({archived_count} archived). "
|
|
346
|
+
"Unarchive an agent or create a new one.",
|
|
347
|
+
file=sys.stderr,
|
|
348
|
+
)
|
|
349
|
+
else:
|
|
350
|
+
print("No agents configured. Run 'culture agent create' first.", file=sys.stderr)
|
|
351
|
+
sys.exit(1)
|
|
352
|
+
print("Multiple agents configured. Specify a nick or use --all.", file=sys.stderr)
|
|
353
|
+
for a in active:
|
|
354
|
+
print(f" {a.nick}", file=sys.stderr)
|
|
355
|
+
sys.exit(1)
|
|
356
|
+
|
|
357
|
+
|
|
318
358
|
def _resolve_agents_to_start(config, args) -> list:
|
|
319
359
|
"""Return the list of agents to start, or exit with an error message."""
|
|
320
360
|
if args.all:
|
|
321
|
-
|
|
322
|
-
agents = [a for a in config.agents if not a.archived]
|
|
361
|
+
agents = _get_active_agents(config)
|
|
323
362
|
elif args.nick:
|
|
324
|
-
|
|
325
|
-
if not agent:
|
|
326
|
-
print(f"Agent '{args.nick}' not found in config", file=sys.stderr)
|
|
327
|
-
sys.exit(1)
|
|
328
|
-
if agent.archived:
|
|
329
|
-
print(
|
|
330
|
-
f"Agent '{args.nick}' is archived. Unarchive first:",
|
|
331
|
-
file=sys.stderr,
|
|
332
|
-
)
|
|
333
|
-
print(f" culture agent unarchive {args.nick}", file=sys.stderr)
|
|
334
|
-
sys.exit(1)
|
|
335
|
-
agents = [agent]
|
|
363
|
+
agents = [_resolve_by_nick(config, args.nick)]
|
|
336
364
|
else:
|
|
337
|
-
|
|
338
|
-
if len(active) == 1:
|
|
339
|
-
agents = active
|
|
340
|
-
elif len(active) == 0:
|
|
341
|
-
archived_count = sum(1 for a in config.agents if a.archived)
|
|
342
|
-
if archived_count:
|
|
343
|
-
print(
|
|
344
|
-
f"No active agents ({archived_count} archived). "
|
|
345
|
-
"Unarchive an agent or create a new one.",
|
|
346
|
-
file=sys.stderr,
|
|
347
|
-
)
|
|
348
|
-
else:
|
|
349
|
-
print("No agents configured. Run 'culture agent create' first.", file=sys.stderr)
|
|
350
|
-
sys.exit(1)
|
|
351
|
-
else:
|
|
352
|
-
print(
|
|
353
|
-
"Multiple agents configured. Specify a nick or use --all.",
|
|
354
|
-
file=sys.stderr,
|
|
355
|
-
)
|
|
356
|
-
for a in active:
|
|
357
|
-
print(f" {a.nick}", file=sys.stderr)
|
|
358
|
-
sys.exit(1)
|
|
365
|
+
agents = _resolve_auto(config)
|
|
359
366
|
|
|
360
367
|
if not agents:
|
|
361
368
|
print("No agents configured", file=sys.stderr)
|
|
362
369
|
sys.exit(1)
|
|
363
|
-
|
|
364
370
|
return agents
|
|
365
371
|
|
|
366
372
|
|
|
@@ -553,6 +559,24 @@ def _cmd_stop(args: argparse.Namespace) -> None:
|
|
|
553
559
|
# -----------------------------------------------------------------------
|
|
554
560
|
|
|
555
561
|
|
|
562
|
+
def _print_archived_info(agent) -> None:
|
|
563
|
+
"""Print archive details for an agent."""
|
|
564
|
+
if not agent.archived:
|
|
565
|
+
return
|
|
566
|
+
print(f"\n [archived since {agent.archived_at}]")
|
|
567
|
+
if agent.archived_reason:
|
|
568
|
+
print(f" Reason: {agent.archived_reason}")
|
|
569
|
+
|
|
570
|
+
|
|
571
|
+
def _no_agents_message(config, show_all: bool) -> str:
|
|
572
|
+
"""Return appropriate message when no agents to display."""
|
|
573
|
+
if not show_all:
|
|
574
|
+
archived_count = sum(1 for a in config.agents if a.archived)
|
|
575
|
+
if archived_count:
|
|
576
|
+
return f"No active agents ({archived_count} archived, use --all to show)"
|
|
577
|
+
return "No agents configured"
|
|
578
|
+
|
|
579
|
+
|
|
556
580
|
def _cmd_status(args: argparse.Namespace) -> None:
|
|
557
581
|
config = load_config_or_default(args.config)
|
|
558
582
|
|
|
@@ -561,34 +585,19 @@ def _cmd_status(args: argparse.Namespace) -> None:
|
|
|
561
585
|
return
|
|
562
586
|
|
|
563
587
|
if args.nick:
|
|
564
|
-
agent =
|
|
565
|
-
for a in config.agents:
|
|
566
|
-
if a.nick == args.nick:
|
|
567
|
-
agent = a
|
|
568
|
-
break
|
|
588
|
+
agent = config.get_agent(args.nick)
|
|
569
589
|
if not agent:
|
|
570
590
|
print(f"Agent '{args.nick}' not found in config", file=sys.stderr)
|
|
571
591
|
sys.exit(1)
|
|
572
|
-
|
|
573
592
|
print_agent_detail(agent, args.config, args)
|
|
574
|
-
|
|
575
|
-
print(f"\n [archived since {agent.archived_at}]")
|
|
576
|
-
if agent.archived_reason:
|
|
577
|
-
print(f" Reason: {agent.archived_reason}")
|
|
593
|
+
_print_archived_info(agent)
|
|
578
594
|
return
|
|
579
595
|
|
|
580
596
|
show_all = getattr(args, "all", False)
|
|
581
|
-
if show_all
|
|
582
|
-
agents = config.agents
|
|
583
|
-
else:
|
|
584
|
-
agents = [a for a in config.agents if not a.archived]
|
|
597
|
+
agents = config.agents if show_all else _get_active_agents(config)
|
|
585
598
|
|
|
586
|
-
if not agents
|
|
587
|
-
|
|
588
|
-
if archived_count:
|
|
589
|
-
print(f"No active agents ({archived_count} archived, use --all to show)")
|
|
590
|
-
else:
|
|
591
|
-
print("No agents configured")
|
|
599
|
+
if not agents:
|
|
600
|
+
print(_no_agents_message(config, show_all))
|
|
592
601
|
return
|
|
593
602
|
|
|
594
603
|
print_agents_overview(agents, args.full, show_archived_marker=show_all)
|
|
@@ -703,35 +712,39 @@ def _cmd_assign(args: argparse.Namespace) -> None:
|
|
|
703
712
|
# -----------------------------------------------------------------------
|
|
704
713
|
|
|
705
714
|
|
|
706
|
-
def
|
|
707
|
-
"""
|
|
708
|
-
config = load_config_or_default(args.config)
|
|
709
|
-
|
|
715
|
+
def _resolve_ipc_targets(config, args, action_verb: str) -> list:
|
|
716
|
+
"""Resolve which agents to send IPC messages to."""
|
|
710
717
|
if args.nick and args.all:
|
|
711
718
|
print("Cannot specify both nick and --all", file=sys.stderr)
|
|
712
719
|
sys.exit(1)
|
|
713
|
-
|
|
714
720
|
if not args.nick and not args.all:
|
|
715
721
|
print(f"Usage: culture agent {action_verb} <nick> or --all", file=sys.stderr)
|
|
716
722
|
sys.exit(1)
|
|
723
|
+
if args.all:
|
|
724
|
+
return config.agents
|
|
725
|
+
for a in config.agents:
|
|
726
|
+
if a.nick == args.nick:
|
|
727
|
+
return [a]
|
|
728
|
+
print(f"Agent '{args.nick}' not found in config", file=sys.stderr)
|
|
729
|
+
sys.exit(1)
|
|
717
730
|
|
|
718
|
-
targets = config.agents if args.all else []
|
|
719
|
-
if args.nick:
|
|
720
|
-
for a in config.agents:
|
|
721
|
-
if a.nick == args.nick:
|
|
722
|
-
targets = [a]
|
|
723
|
-
break
|
|
724
|
-
else:
|
|
725
|
-
print(f"Agent '{args.nick}' not found in config", file=sys.stderr)
|
|
726
|
-
sys.exit(1)
|
|
727
731
|
|
|
732
|
+
def _send_ipc(agent, msg_type: str, action_verb: str) -> None:
|
|
733
|
+
"""Send a single IPC message to an agent and print result."""
|
|
734
|
+
socket_path = agent_socket_path(agent.nick)
|
|
735
|
+
resp = asyncio.run(ipc_request(socket_path, msg_type))
|
|
736
|
+
if resp and resp.get("ok"):
|
|
737
|
+
print(f"{agent.nick}: {action_verb}")
|
|
738
|
+
else:
|
|
739
|
+
print(f"{agent.nick}: failed (not running?)", file=sys.stderr)
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
def _ipc_to_agents(args: argparse.Namespace, msg_type: str, action_verb: str) -> None:
|
|
743
|
+
"""Send an IPC message (pause/resume) to one or all agents."""
|
|
744
|
+
config = load_config_or_default(args.config)
|
|
745
|
+
targets = _resolve_ipc_targets(config, args, action_verb)
|
|
728
746
|
for agent in targets:
|
|
729
|
-
|
|
730
|
-
resp = asyncio.run(ipc_request(socket_path, msg_type))
|
|
731
|
-
if resp and resp.get("ok"):
|
|
732
|
-
print(f"{agent.nick}: {action_verb}")
|
|
733
|
-
else:
|
|
734
|
-
print(f"{agent.nick}: failed (not running?)", file=sys.stderr)
|
|
747
|
+
_send_ipc(agent, msg_type, action_verb)
|
|
735
748
|
|
|
736
749
|
|
|
737
750
|
def _cmd_sleep(args: argparse.Namespace) -> None:
|
|
@@ -748,38 +761,24 @@ def _cmd_learn(args: argparse.Namespace) -> None:
|
|
|
748
761
|
config = load_config_or_default(args.config)
|
|
749
762
|
cwd = os.getcwd()
|
|
750
763
|
|
|
751
|
-
agent = None
|
|
752
764
|
if args.nick:
|
|
753
|
-
|
|
754
|
-
if a.nick == args.nick:
|
|
755
|
-
agent = a
|
|
756
|
-
break
|
|
765
|
+
agent = config.get_agent(args.nick)
|
|
757
766
|
if not agent:
|
|
758
767
|
print(f"Agent '{args.nick}' not found in config", file=sys.stderr)
|
|
759
768
|
sys.exit(1)
|
|
760
769
|
else:
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
770
|
+
cwd_real = os.path.realpath(cwd)
|
|
771
|
+
agent = next(
|
|
772
|
+
(a for a in config.agents if os.path.realpath(a.directory) == cwd_real),
|
|
773
|
+
None,
|
|
774
|
+
)
|
|
765
775
|
|
|
776
|
+
kwargs = {"server": config.server.name, "directory": cwd}
|
|
766
777
|
if agent:
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
nick=agent.nick,
|
|
770
|
-
server=config.server.name,
|
|
771
|
-
directory=agent.directory,
|
|
772
|
-
backend=agent.agent,
|
|
773
|
-
channels=agent.channels,
|
|
774
|
-
)
|
|
775
|
-
)
|
|
776
|
-
else:
|
|
777
|
-
print(
|
|
778
|
-
generate_learn_prompt(
|
|
779
|
-
server=config.server.name,
|
|
780
|
-
directory=cwd,
|
|
781
|
-
)
|
|
778
|
+
kwargs.update(
|
|
779
|
+
nick=agent.nick, directory=agent.directory, backend=agent.agent, channels=agent.channels
|
|
782
780
|
)
|
|
781
|
+
print(generate_learn_prompt(**kwargs))
|
|
783
782
|
|
|
784
783
|
|
|
785
784
|
# -----------------------------------------------------------------------
|
|
@@ -152,13 +152,12 @@ 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
|
|
155
|
+
def _load_and_filter_bots(args) -> list:
|
|
156
|
+
"""Load bot configs, filtering by owner and archived status."""
|
|
156
157
|
from culture.bots.config import BOTS_DIR, load_bot_config
|
|
157
158
|
|
|
158
159
|
if not BOTS_DIR.is_dir():
|
|
159
|
-
|
|
160
|
-
return
|
|
161
|
-
|
|
160
|
+
return []
|
|
162
161
|
show_all = getattr(args, "all", False)
|
|
163
162
|
bots = []
|
|
164
163
|
for bot_dir in sorted(BOTS_DIR.iterdir()):
|
|
@@ -167,14 +166,24 @@ def _bot_list(args: argparse.Namespace) -> None:
|
|
|
167
166
|
continue
|
|
168
167
|
try:
|
|
169
168
|
config = load_bot_config(yaml_path)
|
|
170
|
-
if args.owner and config.owner != args.owner:
|
|
171
|
-
continue
|
|
172
|
-
if not show_all and config.archived:
|
|
173
|
-
continue
|
|
174
|
-
bots.append(config)
|
|
175
169
|
except Exception:
|
|
176
170
|
continue
|
|
171
|
+
if args.owner and config.owner != args.owner:
|
|
172
|
+
continue
|
|
173
|
+
if not show_all and config.archived:
|
|
174
|
+
continue
|
|
175
|
+
bots.append(config)
|
|
176
|
+
return bots
|
|
177
177
|
|
|
178
|
+
|
|
179
|
+
def _bot_list(args: argparse.Namespace) -> None:
|
|
180
|
+
from culture.bots.config import BOTS_DIR
|
|
181
|
+
|
|
182
|
+
if not BOTS_DIR.is_dir():
|
|
183
|
+
print("No bots configured.")
|
|
184
|
+
return
|
|
185
|
+
|
|
186
|
+
bots = _load_and_filter_bots(args)
|
|
178
187
|
if not bots:
|
|
179
188
|
if args.owner:
|
|
180
189
|
print(f"No bots found for owner '{args.owner}'.")
|
|
@@ -182,12 +191,11 @@ def _bot_list(args: argparse.Namespace) -> None:
|
|
|
182
191
|
print("No bots configured.")
|
|
183
192
|
return
|
|
184
193
|
|
|
194
|
+
show_all = getattr(args, "all", False)
|
|
185
195
|
print(f"{'NAME':<35} {'TRIGGER':<10} {'CHANNELS':<20} {'OWNER':<20}")
|
|
186
196
|
for config in bots:
|
|
187
197
|
channels = ", ".join(config.channels) if config.channels else "-"
|
|
188
|
-
name = config.name
|
|
189
|
-
if show_all and config.archived:
|
|
190
|
-
name = f"{name} [archived]"
|
|
198
|
+
name = f"{config.name} [archived]" if show_all and config.archived else config.name
|
|
191
199
|
print(f"{name:<35} {config.trigger_type:<10} {channels:<20} {config.owner:<20}")
|
|
192
200
|
|
|
193
201
|
|
|
@@ -408,6 +408,30 @@ def _cmd_setup(args: argparse.Namespace) -> None:
|
|
|
408
408
|
# -----------------------------------------------------------------------
|
|
409
409
|
|
|
410
410
|
|
|
411
|
+
def _find_upgrade_tool() -> tuple[str, list[str]] | None:
|
|
412
|
+
"""Return (tool_name, command_args) for the first available upgrade tool, or None."""
|
|
413
|
+
uv = shutil.which("uv")
|
|
414
|
+
if uv:
|
|
415
|
+
return "uv", [uv, "tool", "upgrade", "culture"]
|
|
416
|
+
|
|
417
|
+
pip = shutil.which("pip") or shutil.which("pip3")
|
|
418
|
+
if pip:
|
|
419
|
+
return "pip", [pip, "install", "--upgrade", "culture"]
|
|
420
|
+
|
|
421
|
+
return None
|
|
422
|
+
|
|
423
|
+
|
|
424
|
+
def _run_upgrade(tool_name: str, cmd: list[str]) -> None:
|
|
425
|
+
"""Run the upgrade subprocess and exit on failure."""
|
|
426
|
+
print(f"Upgrading via {tool_name}...")
|
|
427
|
+
result = subprocess.run(cmd, capture_output=True, text=True)
|
|
428
|
+
if tool_name == "uv":
|
|
429
|
+
print(result.stdout.strip() if result.stdout else "")
|
|
430
|
+
if result.returncode != 0:
|
|
431
|
+
print(f"{tool_name} upgrade failed: {result.stderr}", file=sys.stderr)
|
|
432
|
+
sys.exit(1)
|
|
433
|
+
|
|
434
|
+
|
|
411
435
|
def _upgrade_culture_package(args: argparse.Namespace) -> bool:
|
|
412
436
|
"""Upgrade the culture package via uv or pip, then re-exec with --skip-upgrade."""
|
|
413
437
|
if args.skip_upgrade:
|
|
@@ -418,33 +442,12 @@ def _upgrade_culture_package(args: argparse.Namespace) -> bool:
|
|
|
418
442
|
print("[dry-run] Would re-exec with --skip-upgrade")
|
|
419
443
|
return False
|
|
420
444
|
|
|
421
|
-
|
|
422
|
-
if
|
|
423
|
-
print("
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
text=True,
|
|
428
|
-
)
|
|
429
|
-
print(result.stdout.strip() if result.stdout else "")
|
|
430
|
-
if result.returncode != 0:
|
|
431
|
-
print(f"uv upgrade failed: {result.stderr}", file=sys.stderr)
|
|
432
|
-
sys.exit(1)
|
|
433
|
-
else:
|
|
434
|
-
pip = shutil.which("pip") or shutil.which("pip3")
|
|
435
|
-
if pip:
|
|
436
|
-
print("Upgrading via pip...")
|
|
437
|
-
result = subprocess.run(
|
|
438
|
-
[pip, "install", "--upgrade", "culture"],
|
|
439
|
-
capture_output=True,
|
|
440
|
-
text=True,
|
|
441
|
-
)
|
|
442
|
-
if result.returncode != 0:
|
|
443
|
-
print(f"pip upgrade failed: {result.stderr}", file=sys.stderr)
|
|
444
|
-
sys.exit(1)
|
|
445
|
-
else:
|
|
446
|
-
print("Neither uv nor pip found", file=sys.stderr)
|
|
447
|
-
sys.exit(1)
|
|
445
|
+
tool = _find_upgrade_tool()
|
|
446
|
+
if tool is None:
|
|
447
|
+
print("Neither uv nor pip found", file=sys.stderr)
|
|
448
|
+
sys.exit(1)
|
|
449
|
+
|
|
450
|
+
_run_upgrade(*tool)
|
|
448
451
|
|
|
449
452
|
culture_bin = shutil.which("culture") or "culture"
|
|
450
453
|
reexec_args = [culture_bin, "mesh", "update", "--skip-upgrade", "--config", args.config]
|
|
@@ -455,6 +458,18 @@ def _upgrade_culture_package(args: argparse.Namespace) -> bool:
|
|
|
455
458
|
os.execvp(culture_bin, reexec_args)
|
|
456
459
|
|
|
457
460
|
|
|
461
|
+
def _wait_for_server_port(port: int, retries: int = 50, interval: float = 0.1) -> None:
|
|
462
|
+
"""Poll until *port* accepts a TCP connection."""
|
|
463
|
+
import socket as _socket
|
|
464
|
+
|
|
465
|
+
for _ in range(retries):
|
|
466
|
+
try:
|
|
467
|
+
with _socket.create_connection(("localhost", port), timeout=1):
|
|
468
|
+
return
|
|
469
|
+
except (ConnectionRefusedError, OSError):
|
|
470
|
+
time.sleep(interval)
|
|
471
|
+
|
|
472
|
+
|
|
458
473
|
def _restart_mesh_services(
|
|
459
474
|
mesh, server_name: str, culture_bin: str, config_path: str, dry_run: bool
|
|
460
475
|
) -> None:
|
|
@@ -479,7 +494,7 @@ def _restart_mesh_services(
|
|
|
479
494
|
print(f" Stopping server {server_name}...")
|
|
480
495
|
server_stop_by_name(server_name)
|
|
481
496
|
|
|
482
|
-
from culture.persistence import install_service
|
|
497
|
+
from culture.persistence import install_service, restart_service
|
|
483
498
|
|
|
484
499
|
server_cmd = build_server_start_cmd(mesh, culture_bin, config_path)
|
|
485
500
|
install_service(f"culture-server-{server_name}", server_cmd, f"culture server {server_name}")
|
|
@@ -499,8 +514,6 @@ def _restart_mesh_services(
|
|
|
499
514
|
]
|
|
500
515
|
install_service(f"culture-agent-{full_nick}", agent_cmd, f"culture agent {full_nick}")
|
|
501
516
|
|
|
502
|
-
from culture.persistence import restart_service
|
|
503
|
-
|
|
504
517
|
server_svc = f"culture-server-{server_name}"
|
|
505
518
|
print(f" Restarting {server_svc}...")
|
|
506
519
|
if not restart_service(server_svc):
|
|
@@ -528,14 +541,7 @@ def _restart_mesh_services(
|
|
|
528
541
|
check=False,
|
|
529
542
|
)
|
|
530
543
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
for _ in range(50):
|
|
534
|
-
try:
|
|
535
|
-
with _socket.create_connection(("localhost", mesh.server.port), timeout=1):
|
|
536
|
-
break
|
|
537
|
-
except (ConnectionRefusedError, OSError):
|
|
538
|
-
time.sleep(0.1)
|
|
544
|
+
_wait_for_server_port(mesh.server.port)
|
|
539
545
|
|
|
540
546
|
for agent in mesh.agents:
|
|
541
547
|
full_nick = f"{server_name}-{agent.nick}"
|