agentirc-cli 4.1.3__tar.gz → 4.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/CHANGELOG.md +24 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/Gemfile +1 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/Gemfile.lock +4 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/PKG-INFO +1 -1
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/_config.yml +1 -0
- agentirc_cli-4.2.1/culture/aio.py +12 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/bots/bot_manager.py +3 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/bots/config.py +18 -6
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/cli/_helpers.py +12 -3
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/cli/agent.py +101 -8
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/cli/bot.py +79 -2
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/cli/server.py +173 -1
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/agent_runner.py +4 -2
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/daemon.py +11 -10
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/irc_transport.py +5 -4
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/config.py +102 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/daemon.py +10 -9
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/irc_transport.py +5 -4
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/agent_runner.py +4 -2
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/daemon.py +11 -10
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/irc_transport.py +5 -4
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/agent_runner.py +4 -2
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/daemon.py +11 -10
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/irc_transport.py +5 -4
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/console/app.py +8 -7
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/console/client.py +2 -3
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/mesh_config.py +1 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/client.py +3 -2
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/server_link.py +9 -8
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/skills/rooms.py +2 -1
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/agent-harness-spec.md +5 -1
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/operations/cli.md +61 -0
- agentirc_cli-4.2.1/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +253 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/packages/agent-harness/daemon.py +11 -10
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/packages/agent-harness/irc_transport.py +5 -4
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/pyproject.toml +1 -1
- agentirc_cli-4.2.1/tests/test_archive.py +436 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_daemon_ipc.py +2 -2
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_mention_target_cleanup.py +6 -6
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/uv.lock +1 -1
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.flake8 +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.github/workflows/pages.yml +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.gitignore +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.pr_agent.toml +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/.pylintrc +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/CLAUDE.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/CNAME +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/LICENSE +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/README.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/SECURITY.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/__main__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/bots/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/bots/bot.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/cli/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/cli/channel.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/cli/mesh.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/cli/skills.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/config.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/config.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/config.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/console/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/console/commands.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/credentials.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/learn_prompt.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/observer.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/overview/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/overview/collector.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/overview/model.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/overview/web/style.css +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/persistence.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/pidfile.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/protocol/commands.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/protocol/message.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/protocol/replies.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/__main__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/channel.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/config.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/ircd.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/remote_client.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/room_store.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/rooms_util.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/skill.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/skills/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/skills/history.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/skills/icon.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/skills/threads.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/server/thread_store.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/agent-lifecycle.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/agentic-self-learn.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/agent-client.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/harness-conformance.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/index.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/layer1-core-irc.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/layer2-attention.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/layer3-skills.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/layer4-federation.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/layer5-agent-harness.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/server-architecture.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/architecture/threads.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/channel-polling.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/acp/overview.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/codex/configuration.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/codex/overview.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/codex/setup.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/copilot/configuration.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/copilot/setup.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/culture-cli.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/getting-started.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/index.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/operations/SECURITY.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/operations/bots.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/operations/ci.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/operations/docs-site.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/operations/index.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/operations/ops-tooling.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/operations/overview.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/operations/publishing.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/rooms.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/server-rename.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/use-cases-index.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/docs/what-is-culture.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/sonar-project.properties +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/__init__.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/conftest.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_bot.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_bot_config.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_channel.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_connection.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_console_client.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_console_commands.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_console_connection.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_console_icons.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_console_integration.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_daemon.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_discovery.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_federation.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_history.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_http_listener.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_ipc.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_mentions.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_message.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_messaging.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_modes.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_overview_model.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_overview_web.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_persistence.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_pidfile.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_rooms.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_skill_client.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_skills.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_socket_server.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_supervisor.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_template_engine.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_threads.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-4.1.3 → agentirc_cli-4.2.1}/tests/test_webhook.py +0 -0
|
@@ -4,6 +4,30 @@ 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.2.1] - 2026-04-07
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- Update dispatch patterns to use declarative maybe_await() utility for handling both sync and async handlers
|
|
13
|
+
- Remove unnecessary async keyword from ~40 handler functions that never use await
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Fixed
|
|
17
|
+
|
|
18
|
+
- SonarCloud S7503: async functions that never await (issue #83)
|
|
19
|
+
|
|
20
|
+
## [4.2.0] - 2026-04-07
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- Archive and unarchive commands for servers, agents, and bots
|
|
26
|
+
- Cascade archive: server archive automatically archives all agents and bots
|
|
27
|
+
- Visibility filtering: archived entities hidden from default status/list views
|
|
28
|
+
- --all flag on status/list to reveal archived entities
|
|
29
|
+
- Start guard: archived entities cannot be started until unarchived
|
|
30
|
+
|
|
7
31
|
## [4.1.3] - 2026-04-06
|
|
8
32
|
|
|
9
33
|
|
|
@@ -81,6 +81,8 @@ GEM
|
|
|
81
81
|
sass-embedded (~> 1.75)
|
|
82
82
|
jekyll-seo-tag (2.8.0)
|
|
83
83
|
jekyll (>= 3.8, < 5.0)
|
|
84
|
+
jekyll-sitemap (1.4.0)
|
|
85
|
+
jekyll (>= 3.7, < 5.0)
|
|
84
86
|
jekyll-watch (2.2.1)
|
|
85
87
|
listen (~> 3.0)
|
|
86
88
|
json (2.19.2)
|
|
@@ -171,6 +173,7 @@ DEPENDENCIES
|
|
|
171
173
|
jekyll (~> 4.3)
|
|
172
174
|
jekyll-relative-links
|
|
173
175
|
jekyll-seo-tag
|
|
176
|
+
jekyll-sitemap
|
|
174
177
|
just-the-docs (~> 0.10)
|
|
175
178
|
|
|
176
179
|
CHECKSUMS
|
|
@@ -210,6 +213,7 @@ CHECKSUMS
|
|
|
210
213
|
jekyll-relative-links (0.7.0) sha256=831e54c348eeae751845c0d4ac4b244bd73b664341f0e8c9f1803b16f4570835
|
|
211
214
|
jekyll-sass-converter (3.1.0) sha256=83925d84f1d134410c11d0c6643b0093e82e3a3cf127e90757a85294a3862443
|
|
212
215
|
jekyll-seo-tag (2.8.0) sha256=3f2ed1916d56f14ebfa38e24acde9b7c946df70cb183af2cb5f0598f21ae6818
|
|
216
|
+
jekyll-sitemap (1.4.0) sha256=0de08c5debc185ea5a8f980e1025c7cd3f8e0c35c8b6ef592f15c46235cf4218
|
|
213
217
|
jekyll-watch (2.2.1) sha256=bc44ed43f5e0a552836245a54dbff3ea7421ecc2856707e8a1ee203a8387a7e1
|
|
214
218
|
json (2.19.2) sha256=e7e1bd318b2c37c4ceee2444841c86539bc462e81f40d134cf97826cb14e83cf
|
|
215
219
|
just-the-docs (0.12.0) sha256=15f2839ac9082898d60f33b978aa6f8e46fc50ba8fac20ae7a7f0e1fb295523e
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"""Async utilities for culture."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
async def maybe_await(result):
|
|
9
|
+
"""Await the result only if it's a coroutine, otherwise return directly."""
|
|
10
|
+
if asyncio.iscoroutine(result):
|
|
11
|
+
return await result
|
|
12
|
+
return result
|
|
@@ -26,6 +26,9 @@ class BotConfig:
|
|
|
26
26
|
mention: str | None = None
|
|
27
27
|
template: str | None = None
|
|
28
28
|
fallback: str = "json"
|
|
29
|
+
archived: bool = False
|
|
30
|
+
archived_at: str = ""
|
|
31
|
+
archived_reason: str = ""
|
|
29
32
|
|
|
30
33
|
@property
|
|
31
34
|
def has_handler(self) -> bool:
|
|
@@ -54,6 +57,9 @@ def load_bot_config(path: Path) -> BotConfig:
|
|
|
54
57
|
mention=output_section.get("mention"),
|
|
55
58
|
template=output_section.get("template"),
|
|
56
59
|
fallback=output_section.get("fallback", "json"),
|
|
60
|
+
archived=bot_section.get("archived", False),
|
|
61
|
+
archived_at=bot_section.get("archived_at", ""),
|
|
62
|
+
archived_reason=bot_section.get("archived_reason", ""),
|
|
57
63
|
)
|
|
58
64
|
|
|
59
65
|
|
|
@@ -61,13 +67,19 @@ def save_bot_config(path: Path, config: BotConfig) -> None:
|
|
|
61
67
|
"""Serialize a BotConfig to YAML and write atomically."""
|
|
62
68
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
63
69
|
|
|
70
|
+
bot_section = {
|
|
71
|
+
"name": config.name,
|
|
72
|
+
"owner": config.owner,
|
|
73
|
+
"description": config.description,
|
|
74
|
+
"created": config.created,
|
|
75
|
+
}
|
|
76
|
+
if config.archived:
|
|
77
|
+
bot_section["archived"] = config.archived
|
|
78
|
+
bot_section["archived_at"] = config.archived_at
|
|
79
|
+
bot_section["archived_reason"] = config.archived_reason
|
|
80
|
+
|
|
64
81
|
data = {
|
|
65
|
-
"bot":
|
|
66
|
-
"name": config.name,
|
|
67
|
-
"owner": config.owner,
|
|
68
|
-
"description": config.description,
|
|
69
|
-
"created": config.created,
|
|
70
|
-
},
|
|
82
|
+
"bot": bot_section,
|
|
71
83
|
"trigger": {
|
|
72
84
|
"type": config.trigger_type,
|
|
73
85
|
},
|
|
@@ -381,7 +381,9 @@ 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 print_agents_overview(
|
|
384
|
+
def print_agents_overview(
|
|
385
|
+
agents: list, show_activity: bool, show_archived_marker: bool = False
|
|
386
|
+
) -> None:
|
|
385
387
|
"""Print a table of all agents with status, PID, and optionally activity."""
|
|
386
388
|
if show_activity:
|
|
387
389
|
print(f"{'NICK':<30} {'STATUS':<12} {'PID':<10} {'ACTIVITY'}")
|
|
@@ -391,10 +393,17 @@ def print_agents_overview(agents: list, show_activity: bool) -> None:
|
|
|
391
393
|
print("-" * 52)
|
|
392
394
|
|
|
393
395
|
for agent in agents:
|
|
394
|
-
|
|
396
|
+
archived = getattr(agent, "archived", False)
|
|
397
|
+
base_status, pid = agent_process_status(agent)
|
|
398
|
+
status = base_status
|
|
399
|
+
if archived:
|
|
400
|
+
if show_archived_marker:
|
|
401
|
+
status = f"{base_status} (archived)"
|
|
402
|
+
elif base_status == "stopped":
|
|
403
|
+
status = "archived"
|
|
395
404
|
activity = "-"
|
|
396
405
|
|
|
397
|
-
if show_activity and
|
|
406
|
+
if show_activity and base_status == "running":
|
|
398
407
|
resp = asyncio.run(ipc_request(agent_socket_path(agent.nick), "status"))
|
|
399
408
|
if resp and resp.get("ok"):
|
|
400
409
|
activity = resp.get("data", {}).get("description", "nothing")
|
|
@@ -13,9 +13,11 @@ from culture.clients.claude.config import (
|
|
|
13
13
|
AgentConfig,
|
|
14
14
|
DaemonConfig,
|
|
15
15
|
add_agent_to_config,
|
|
16
|
+
archive_agent,
|
|
16
17
|
load_config,
|
|
17
18
|
load_config_or_default,
|
|
18
19
|
sanitize_agent_name,
|
|
20
|
+
unarchive_agent,
|
|
19
21
|
)
|
|
20
22
|
from culture.pidfile import (
|
|
21
23
|
is_process_alive,
|
|
@@ -99,6 +101,7 @@ def register(subparsers: argparse._SubParsersAction) -> None:
|
|
|
99
101
|
status_parser.add_argument(
|
|
100
102
|
"--full", action="store_true", help="Query agents for activity status"
|
|
101
103
|
)
|
|
104
|
+
status_parser.add_argument("--all", action="store_true", help="Include archived agents")
|
|
102
105
|
status_parser.add_argument("--config", default=DEFAULT_CONFIG, help=_CONFIG_HELP)
|
|
103
106
|
|
|
104
107
|
# -- rename ---------------------------------------------------------------
|
|
@@ -144,11 +147,22 @@ def register(subparsers: argparse._SubParsersAction) -> None:
|
|
|
144
147
|
read_parser.add_argument("--limit", "-n", type=int, default=50, help="Number of messages")
|
|
145
148
|
read_parser.add_argument("--config", default=DEFAULT_CONFIG, help=_CONFIG_HELP)
|
|
146
149
|
|
|
150
|
+
# -- archive --------------------------------------------------------------
|
|
151
|
+
archive_parser = agent_sub.add_parser("archive", help="Archive an agent (stop and retire)")
|
|
152
|
+
archive_parser.add_argument("nick", help="Agent nick to archive")
|
|
153
|
+
archive_parser.add_argument("--reason", default="", help="Reason for archiving")
|
|
154
|
+
archive_parser.add_argument("--config", default=DEFAULT_CONFIG, help=_CONFIG_HELP)
|
|
155
|
+
|
|
156
|
+
# -- unarchive ------------------------------------------------------------
|
|
157
|
+
unarchive_parser = agent_sub.add_parser("unarchive", help="Restore an archived agent")
|
|
158
|
+
unarchive_parser.add_argument("nick", help="Agent nick to unarchive")
|
|
159
|
+
unarchive_parser.add_argument("--config", default=DEFAULT_CONFIG, help=_CONFIG_HELP)
|
|
160
|
+
|
|
147
161
|
|
|
148
162
|
def dispatch(args: argparse.Namespace) -> None:
|
|
149
163
|
if not args.agent_command:
|
|
150
164
|
print(
|
|
151
|
-
"Usage: culture agent {create|join|start|stop|status|rename|assign|sleep|wake|learn|message|read}",
|
|
165
|
+
"Usage: culture agent {create|join|start|stop|status|rename|assign|sleep|wake|learn|message|read|archive|unarchive}",
|
|
152
166
|
file=sys.stderr,
|
|
153
167
|
)
|
|
154
168
|
sys.exit(1)
|
|
@@ -166,6 +180,8 @@ def dispatch(args: argparse.Namespace) -> None:
|
|
|
166
180
|
"learn": _cmd_learn,
|
|
167
181
|
"message": _cmd_message,
|
|
168
182
|
"read": _cmd_read,
|
|
183
|
+
"archive": _cmd_archive,
|
|
184
|
+
"unarchive": _cmd_unarchive,
|
|
169
185
|
}
|
|
170
186
|
handler = handlers.get(args.agent_command)
|
|
171
187
|
if handler:
|
|
@@ -291,25 +307,42 @@ def _cmd_join(args: argparse.Namespace) -> None:
|
|
|
291
307
|
def _resolve_agents_to_start(config, args) -> list:
|
|
292
308
|
"""Return the list of agents to start, or exit with an error message."""
|
|
293
309
|
if args.all:
|
|
294
|
-
agents
|
|
310
|
+
# Skip archived agents when starting --all
|
|
311
|
+
agents = [a for a in config.agents if not a.archived]
|
|
295
312
|
elif args.nick:
|
|
296
313
|
agent = config.get_agent(args.nick)
|
|
297
314
|
if not agent:
|
|
298
315
|
print(f"Agent '{args.nick}' not found in config", file=sys.stderr)
|
|
299
316
|
sys.exit(1)
|
|
317
|
+
if agent.archived:
|
|
318
|
+
print(
|
|
319
|
+
f"Agent '{args.nick}' is archived. Unarchive first:",
|
|
320
|
+
file=sys.stderr,
|
|
321
|
+
)
|
|
322
|
+
print(f" culture agent unarchive {args.nick}", file=sys.stderr)
|
|
323
|
+
sys.exit(1)
|
|
300
324
|
agents = [agent]
|
|
301
325
|
else:
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
326
|
+
active = [a for a in config.agents if not a.archived]
|
|
327
|
+
if len(active) == 1:
|
|
328
|
+
agents = active
|
|
329
|
+
elif len(active) == 0:
|
|
330
|
+
archived_count = sum(1 for a in config.agents if a.archived)
|
|
331
|
+
if archived_count:
|
|
332
|
+
print(
|
|
333
|
+
f"No active agents ({archived_count} archived). "
|
|
334
|
+
"Unarchive an agent or create a new one.",
|
|
335
|
+
file=sys.stderr,
|
|
336
|
+
)
|
|
337
|
+
else:
|
|
338
|
+
print("No agents configured. Run 'culture agent create' first.", file=sys.stderr)
|
|
306
339
|
sys.exit(1)
|
|
307
340
|
else:
|
|
308
341
|
print(
|
|
309
342
|
"Multiple agents configured. Specify a nick or use --all.",
|
|
310
343
|
file=sys.stderr,
|
|
311
344
|
)
|
|
312
|
-
for a in
|
|
345
|
+
for a in active:
|
|
313
346
|
print(f" {a.nick}", file=sys.stderr)
|
|
314
347
|
sys.exit(1)
|
|
315
348
|
|
|
@@ -527,9 +560,27 @@ def _cmd_status(args: argparse.Namespace) -> None:
|
|
|
527
560
|
sys.exit(1)
|
|
528
561
|
|
|
529
562
|
print_agent_detail(agent, args.config, args)
|
|
563
|
+
if agent.archived:
|
|
564
|
+
print(f"\n [archived since {agent.archived_at}]")
|
|
565
|
+
if agent.archived_reason:
|
|
566
|
+
print(f" Reason: {agent.archived_reason}")
|
|
567
|
+
return
|
|
568
|
+
|
|
569
|
+
show_all = getattr(args, "all", False)
|
|
570
|
+
if show_all:
|
|
571
|
+
agents = config.agents
|
|
572
|
+
else:
|
|
573
|
+
agents = [a for a in config.agents if not a.archived]
|
|
574
|
+
|
|
575
|
+
if not agents and not show_all:
|
|
576
|
+
archived_count = sum(1 for a in config.agents if a.archived)
|
|
577
|
+
if archived_count:
|
|
578
|
+
print(f"No active agents ({archived_count} archived, use --all to show)")
|
|
579
|
+
else:
|
|
580
|
+
print("No agents configured")
|
|
530
581
|
return
|
|
531
582
|
|
|
532
|
-
print_agents_overview(
|
|
583
|
+
print_agents_overview(agents, args.full, show_archived_marker=show_all)
|
|
533
584
|
print_bot_listing()
|
|
534
585
|
|
|
535
586
|
|
|
@@ -738,3 +789,45 @@ def _cmd_read(args: argparse.Namespace) -> None:
|
|
|
738
789
|
)
|
|
739
790
|
print("Use 'culture channel read <channel>' for channel history.", file=sys.stderr)
|
|
740
791
|
sys.exit(1)
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
# -----------------------------------------------------------------------
|
|
795
|
+
# Archive / Unarchive
|
|
796
|
+
# -----------------------------------------------------------------------
|
|
797
|
+
|
|
798
|
+
|
|
799
|
+
def _cmd_archive(args: argparse.Namespace) -> None:
|
|
800
|
+
"""Archive an agent: stop if running, set archived flag."""
|
|
801
|
+
config = load_config_or_default(args.config)
|
|
802
|
+
agent = config.get_agent(args.nick)
|
|
803
|
+
if not agent:
|
|
804
|
+
print(f"Agent '{args.nick}' not found in config", file=sys.stderr)
|
|
805
|
+
sys.exit(1)
|
|
806
|
+
|
|
807
|
+
if agent.archived:
|
|
808
|
+
print(f"Agent '{args.nick}' is already archived")
|
|
809
|
+
return
|
|
810
|
+
|
|
811
|
+
# Stop the agent if it's running
|
|
812
|
+
pid = read_pid(f"agent-{args.nick}")
|
|
813
|
+
if pid and is_process_alive(pid):
|
|
814
|
+
stop_agent(args.nick)
|
|
815
|
+
|
|
816
|
+
archive_agent(args.config, args.nick, reason=args.reason)
|
|
817
|
+
|
|
818
|
+
print(f"Agent archived: {args.nick}")
|
|
819
|
+
if args.reason:
|
|
820
|
+
print(f" Reason: {args.reason}")
|
|
821
|
+
print(f"\nTo restore: culture agent unarchive {args.nick}")
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
def _cmd_unarchive(args: argparse.Namespace) -> None:
|
|
825
|
+
"""Restore an archived agent."""
|
|
826
|
+
try:
|
|
827
|
+
unarchive_agent(args.config, args.nick)
|
|
828
|
+
except ValueError as exc:
|
|
829
|
+
print(str(exc), file=sys.stderr)
|
|
830
|
+
sys.exit(1)
|
|
831
|
+
|
|
832
|
+
print(f"Agent unarchived: {args.nick}")
|
|
833
|
+
print(f"\nStart with: culture agent start {args.nick}")
|
|
@@ -40,15 +40,26 @@ def register(subparsers: argparse._SubParsersAction) -> None:
|
|
|
40
40
|
|
|
41
41
|
bot_list = bot_sub.add_parser("list", help="List bots")
|
|
42
42
|
bot_list.add_argument("owner", nargs="?", default=None, help="Filter by owner nick")
|
|
43
|
+
bot_list.add_argument("--all", action="store_true", help="Include archived bots")
|
|
43
44
|
|
|
44
45
|
bot_inspect = bot_sub.add_parser("inspect", help="Show bot details")
|
|
45
46
|
bot_inspect.add_argument("name", help="Bot name")
|
|
46
47
|
bot_inspect.add_argument("--config", default=DEFAULT_CONFIG, help=_CONFIG_HELP)
|
|
47
48
|
|
|
49
|
+
bot_archive = bot_sub.add_parser("archive", help="Archive a bot")
|
|
50
|
+
bot_archive.add_argument("name", help="Bot name to archive")
|
|
51
|
+
bot_archive.add_argument("--reason", default="", help="Reason for archiving")
|
|
52
|
+
|
|
53
|
+
bot_unarchive = bot_sub.add_parser("unarchive", help="Restore an archived bot")
|
|
54
|
+
bot_unarchive.add_argument("name", help="Bot name to unarchive")
|
|
55
|
+
|
|
48
56
|
|
|
49
57
|
def dispatch(args: argparse.Namespace) -> None:
|
|
50
58
|
if not args.bot_command:
|
|
51
|
-
print(
|
|
59
|
+
print(
|
|
60
|
+
"Usage: culture bot {create|start|stop|list|inspect|archive|unarchive}",
|
|
61
|
+
file=sys.stderr,
|
|
62
|
+
)
|
|
52
63
|
sys.exit(1)
|
|
53
64
|
|
|
54
65
|
handlers = {
|
|
@@ -57,6 +68,8 @@ def dispatch(args: argparse.Namespace) -> None:
|
|
|
57
68
|
"stop": _bot_stop,
|
|
58
69
|
"list": _bot_list,
|
|
59
70
|
"inspect": _bot_inspect,
|
|
71
|
+
"archive": _bot_archive,
|
|
72
|
+
"unarchive": _bot_unarchive,
|
|
60
73
|
}
|
|
61
74
|
handler = handlers.get(args.bot_command)
|
|
62
75
|
if handler:
|
|
@@ -146,6 +159,7 @@ def _bot_list(args: argparse.Namespace) -> None:
|
|
|
146
159
|
print("No bots configured.")
|
|
147
160
|
return
|
|
148
161
|
|
|
162
|
+
show_all = getattr(args, "all", False)
|
|
149
163
|
bots = []
|
|
150
164
|
for bot_dir in sorted(BOTS_DIR.iterdir()):
|
|
151
165
|
yaml_path = bot_dir / "bot.yaml"
|
|
@@ -155,6 +169,8 @@ def _bot_list(args: argparse.Namespace) -> None:
|
|
|
155
169
|
config = load_bot_config(yaml_path)
|
|
156
170
|
if args.owner and config.owner != args.owner:
|
|
157
171
|
continue
|
|
172
|
+
if not show_all and config.archived:
|
|
173
|
+
continue
|
|
158
174
|
bots.append(config)
|
|
159
175
|
except Exception:
|
|
160
176
|
continue
|
|
@@ -169,7 +185,10 @@ def _bot_list(args: argparse.Namespace) -> None:
|
|
|
169
185
|
print(f"{'NAME':<35} {'TRIGGER':<10} {'CHANNELS':<20} {'OWNER':<20}")
|
|
170
186
|
for config in bots:
|
|
171
187
|
channels = ", ".join(config.channels) if config.channels else "-"
|
|
172
|
-
|
|
188
|
+
name = config.name
|
|
189
|
+
if show_all and config.archived:
|
|
190
|
+
name = f"{name} [archived]"
|
|
191
|
+
print(f"{name:<35} {config.trigger_type:<10} {channels:<20} {config.owner:<20}")
|
|
173
192
|
|
|
174
193
|
|
|
175
194
|
def _bot_inspect(args: argparse.Namespace) -> None:
|
|
@@ -201,3 +220,61 @@ def _bot_inspect(args: argparse.Namespace) -> None:
|
|
|
201
220
|
first_line = first_line[:57] + "..."
|
|
202
221
|
print(f"Template: {first_line}")
|
|
203
222
|
print(f"Handler: {'custom (handler.py)' if config.has_handler else 'template'}")
|
|
223
|
+
if config.archived:
|
|
224
|
+
print(f"Archived: yes (since {config.archived_at})")
|
|
225
|
+
if config.archived_reason:
|
|
226
|
+
print(f"Reason: {config.archived_reason}")
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
# -----------------------------------------------------------------------
|
|
230
|
+
# Archive / Unarchive
|
|
231
|
+
# -----------------------------------------------------------------------
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _bot_archive(args: argparse.Namespace) -> None:
|
|
235
|
+
import time as _time
|
|
236
|
+
|
|
237
|
+
from culture.bots.config import BOTS_DIR, load_bot_config, save_bot_config
|
|
238
|
+
|
|
239
|
+
bot_dir = BOTS_DIR / args.name
|
|
240
|
+
yaml_path = bot_dir / "bot.yaml"
|
|
241
|
+
if not yaml_path.is_file():
|
|
242
|
+
print(f"Bot '{args.name}' not found at {bot_dir}", file=sys.stderr)
|
|
243
|
+
sys.exit(1)
|
|
244
|
+
|
|
245
|
+
config = load_bot_config(yaml_path)
|
|
246
|
+
if config.archived:
|
|
247
|
+
print(f"Bot '{args.name}' is already archived")
|
|
248
|
+
return
|
|
249
|
+
|
|
250
|
+
config.archived = True
|
|
251
|
+
config.archived_at = _time.strftime("%Y-%m-%d")
|
|
252
|
+
config.archived_reason = args.reason
|
|
253
|
+
save_bot_config(yaml_path, config)
|
|
254
|
+
|
|
255
|
+
print(f"Bot archived: {args.name}")
|
|
256
|
+
if args.reason:
|
|
257
|
+
print(f" Reason: {args.reason}")
|
|
258
|
+
print(f"\nTo restore: culture bot unarchive {args.name}")
|
|
259
|
+
|
|
260
|
+
|
|
261
|
+
def _bot_unarchive(args: argparse.Namespace) -> None:
|
|
262
|
+
from culture.bots.config import BOTS_DIR, load_bot_config, save_bot_config
|
|
263
|
+
|
|
264
|
+
bot_dir = BOTS_DIR / args.name
|
|
265
|
+
yaml_path = bot_dir / "bot.yaml"
|
|
266
|
+
if not yaml_path.is_file():
|
|
267
|
+
print(f"Bot '{args.name}' not found at {bot_dir}", file=sys.stderr)
|
|
268
|
+
sys.exit(1)
|
|
269
|
+
|
|
270
|
+
config = load_bot_config(yaml_path)
|
|
271
|
+
if not config.archived:
|
|
272
|
+
print(f"Bot '{args.name}' is not archived", file=sys.stderr)
|
|
273
|
+
sys.exit(1)
|
|
274
|
+
|
|
275
|
+
config.archived = False
|
|
276
|
+
config.archived_at = ""
|
|
277
|
+
config.archived_reason = ""
|
|
278
|
+
save_bot_config(yaml_path, config)
|
|
279
|
+
|
|
280
|
+
print(f"Bot unarchived: {args.name}")
|
|
@@ -77,10 +77,34 @@ def register(subparsers: argparse._SubParsersAction) -> None:
|
|
|
77
77
|
help="Config file path",
|
|
78
78
|
)
|
|
79
79
|
|
|
80
|
+
srv_archive = server_sub.add_parser(
|
|
81
|
+
"archive", help="Archive the server and all its agents/bots"
|
|
82
|
+
)
|
|
83
|
+
srv_archive.add_argument("--name", default="culture", help="Server name")
|
|
84
|
+
srv_archive.add_argument("--reason", default="", help="Reason for archiving")
|
|
85
|
+
srv_archive.add_argument(
|
|
86
|
+
"--config",
|
|
87
|
+
default=os.path.expanduser("~/.culture/agents.yaml"),
|
|
88
|
+
help="Config file path",
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
srv_unarchive = server_sub.add_parser(
|
|
92
|
+
"unarchive", help="Restore an archived server and all its agents/bots"
|
|
93
|
+
)
|
|
94
|
+
srv_unarchive.add_argument("--name", default="culture", help="Server name")
|
|
95
|
+
srv_unarchive.add_argument(
|
|
96
|
+
"--config",
|
|
97
|
+
default=os.path.expanduser("~/.culture/agents.yaml"),
|
|
98
|
+
help="Config file path",
|
|
99
|
+
)
|
|
100
|
+
|
|
80
101
|
|
|
81
102
|
def dispatch(args: argparse.Namespace) -> None:
|
|
82
103
|
if not args.server_command:
|
|
83
|
-
print(
|
|
104
|
+
print(
|
|
105
|
+
"Usage: culture server {start|stop|status|default|rename|archive|unarchive}",
|
|
106
|
+
file=sys.stderr,
|
|
107
|
+
)
|
|
84
108
|
sys.exit(1)
|
|
85
109
|
|
|
86
110
|
if args.server_command == "start":
|
|
@@ -96,6 +120,10 @@ def dispatch(args: argparse.Namespace) -> None:
|
|
|
96
120
|
print(f"Default server set to '{args.name}'")
|
|
97
121
|
elif args.server_command == "rename":
|
|
98
122
|
_server_rename(args)
|
|
123
|
+
elif args.server_command == "archive":
|
|
124
|
+
_server_archive(args)
|
|
125
|
+
elif args.server_command == "unarchive":
|
|
126
|
+
_server_unarchive(args)
|
|
99
127
|
|
|
100
128
|
|
|
101
129
|
# -----------------------------------------------------------------------
|
|
@@ -182,6 +210,19 @@ def _wait_for_port(
|
|
|
182
210
|
|
|
183
211
|
|
|
184
212
|
def _server_start(args: argparse.Namespace) -> None:
|
|
213
|
+
# Check if server is archived
|
|
214
|
+
from culture.clients.claude.config import load_config_or_default
|
|
215
|
+
|
|
216
|
+
config_path = getattr(args, "config", os.path.expanduser("~/.culture/agents.yaml"))
|
|
217
|
+
config = load_config_or_default(config_path)
|
|
218
|
+
if config.server.name == args.name and config.server.archived:
|
|
219
|
+
print(
|
|
220
|
+
f"Server '{args.name}' is archived. Unarchive first:",
|
|
221
|
+
file=sys.stderr,
|
|
222
|
+
)
|
|
223
|
+
print(f" culture server unarchive --name {args.name}", file=sys.stderr)
|
|
224
|
+
sys.exit(1)
|
|
225
|
+
|
|
185
226
|
pid_name = f"server-{args.name}"
|
|
186
227
|
|
|
187
228
|
existing = read_pid(pid_name)
|
|
@@ -363,3 +404,134 @@ def _server_status(args: argparse.Namespace) -> None:
|
|
|
363
404
|
else:
|
|
364
405
|
print(f"Server '{args.name}': not running (stale PID {pid})")
|
|
365
406
|
remove_pid(pid_name)
|
|
407
|
+
|
|
408
|
+
|
|
409
|
+
# -----------------------------------------------------------------------
|
|
410
|
+
# Archive / Unarchive
|
|
411
|
+
# -----------------------------------------------------------------------
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def _server_archive(args: argparse.Namespace) -> None:
|
|
415
|
+
"""Archive the server and cascade to all agents and bots."""
|
|
416
|
+
from culture.bots.config import BOTS_DIR, load_bot_config, save_bot_config
|
|
417
|
+
from culture.clients.claude.config import (
|
|
418
|
+
archive_server,
|
|
419
|
+
load_config_or_default,
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
config = load_config_or_default(args.config)
|
|
423
|
+
server_name = config.server.name
|
|
424
|
+
|
|
425
|
+
if server_name != args.name:
|
|
426
|
+
print(
|
|
427
|
+
f"Server name mismatch: --name '{args.name}' but config has '{server_name}'",
|
|
428
|
+
file=sys.stderr,
|
|
429
|
+
)
|
|
430
|
+
sys.exit(1)
|
|
431
|
+
|
|
432
|
+
if config.server.archived:
|
|
433
|
+
print(f"Server '{server_name}' is already archived")
|
|
434
|
+
return
|
|
435
|
+
|
|
436
|
+
# Stop server if running
|
|
437
|
+
pid_name = f"server-{server_name}"
|
|
438
|
+
pid = read_pid(pid_name)
|
|
439
|
+
if pid and is_process_alive(pid):
|
|
440
|
+
print(f"Stopping server '{server_name}'...")
|
|
441
|
+
_server_stop(args)
|
|
442
|
+
|
|
443
|
+
# Stop all running agents
|
|
444
|
+
from culture.cli._helpers import stop_agent
|
|
445
|
+
|
|
446
|
+
for agent in config.agents:
|
|
447
|
+
agent_pid = read_pid(f"agent-{agent.nick}")
|
|
448
|
+
if agent_pid and is_process_alive(agent_pid):
|
|
449
|
+
stop_agent(agent.nick)
|
|
450
|
+
|
|
451
|
+
# Archive server + agents in config
|
|
452
|
+
archived_nicks = archive_server(args.config, reason=args.reason)
|
|
453
|
+
|
|
454
|
+
# Archive bots whose owner matches any agent on this server
|
|
455
|
+
import time as _time
|
|
456
|
+
|
|
457
|
+
today = _time.strftime("%Y-%m-%d")
|
|
458
|
+
agent_nicks = {a.nick for a in config.agents}
|
|
459
|
+
archived_bots = []
|
|
460
|
+
if BOTS_DIR.is_dir():
|
|
461
|
+
for bot_dir in BOTS_DIR.iterdir():
|
|
462
|
+
yaml_path = bot_dir / "bot.yaml"
|
|
463
|
+
if not yaml_path.is_file():
|
|
464
|
+
continue
|
|
465
|
+
try:
|
|
466
|
+
bot_config = load_bot_config(yaml_path)
|
|
467
|
+
if bot_config.owner in agent_nicks and not bot_config.archived:
|
|
468
|
+
bot_config.archived = True
|
|
469
|
+
bot_config.archived_at = today
|
|
470
|
+
bot_config.archived_reason = args.reason
|
|
471
|
+
save_bot_config(yaml_path, bot_config)
|
|
472
|
+
archived_bots.append(bot_config.name)
|
|
473
|
+
except (OSError, ValueError) as exc:
|
|
474
|
+
print(f" Warning: skipping bot '{bot_dir.name}': {exc}", file=sys.stderr)
|
|
475
|
+
continue
|
|
476
|
+
|
|
477
|
+
print(f"Server archived: {server_name}")
|
|
478
|
+
if args.reason:
|
|
479
|
+
print(f" Reason: {args.reason}")
|
|
480
|
+
if archived_nicks:
|
|
481
|
+
print(f" Agents: {', '.join(archived_nicks)}")
|
|
482
|
+
if archived_bots:
|
|
483
|
+
print(f" Bots: {', '.join(archived_bots)}")
|
|
484
|
+
print(f"\nTo restore: culture server unarchive --name {server_name}")
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def _server_unarchive(args: argparse.Namespace) -> None:
|
|
488
|
+
"""Restore an archived server and cascade to agents and bots."""
|
|
489
|
+
from culture.bots.config import BOTS_DIR, load_bot_config, save_bot_config
|
|
490
|
+
from culture.clients.claude.config import (
|
|
491
|
+
load_config_or_default,
|
|
492
|
+
unarchive_server,
|
|
493
|
+
)
|
|
494
|
+
|
|
495
|
+
config = load_config_or_default(args.config)
|
|
496
|
+
server_name = config.server.name
|
|
497
|
+
|
|
498
|
+
if server_name != args.name:
|
|
499
|
+
print(
|
|
500
|
+
f"Server name mismatch: --name '{args.name}' but config has '{server_name}'",
|
|
501
|
+
file=sys.stderr,
|
|
502
|
+
)
|
|
503
|
+
sys.exit(1)
|
|
504
|
+
|
|
505
|
+
if not config.server.archived:
|
|
506
|
+
print(f"Server '{server_name}' is not archived", file=sys.stderr)
|
|
507
|
+
sys.exit(1)
|
|
508
|
+
|
|
509
|
+
# Unarchive server + agents
|
|
510
|
+
unarchived_nicks = unarchive_server(args.config)
|
|
511
|
+
|
|
512
|
+
# Unarchive bots whose owner matches any agent on this server
|
|
513
|
+
agent_nicks = {a.nick for a in config.agents}
|
|
514
|
+
unarchived_bots = []
|
|
515
|
+
if BOTS_DIR.is_dir():
|
|
516
|
+
for bot_dir in BOTS_DIR.iterdir():
|
|
517
|
+
yaml_path = bot_dir / "bot.yaml"
|
|
518
|
+
if not yaml_path.is_file():
|
|
519
|
+
continue
|
|
520
|
+
try:
|
|
521
|
+
bot_config = load_bot_config(yaml_path)
|
|
522
|
+
if bot_config.owner in agent_nicks and bot_config.archived:
|
|
523
|
+
bot_config.archived = False
|
|
524
|
+
bot_config.archived_at = ""
|
|
525
|
+
bot_config.archived_reason = ""
|
|
526
|
+
save_bot_config(yaml_path, bot_config)
|
|
527
|
+
unarchived_bots.append(bot_config.name)
|
|
528
|
+
except (OSError, ValueError) as exc:
|
|
529
|
+
print(f" Warning: skipping bot '{bot_dir.name}': {exc}", file=sys.stderr)
|
|
530
|
+
continue
|
|
531
|
+
|
|
532
|
+
print(f"Server unarchived: {server_name}")
|
|
533
|
+
if unarchived_nicks:
|
|
534
|
+
print(f" Agents: {', '.join(unarchived_nicks)}")
|
|
535
|
+
if unarchived_bots:
|
|
536
|
+
print(f" Bots: {', '.join(unarchived_bots)}")
|
|
537
|
+
print(f"\nStart with: culture server start --name {server_name}")
|