agentirc-cli 4.1.2__tar.gz → 4.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/CHANGELOG.md +18 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/Gemfile +1 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/Gemfile.lock +4 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/PKG-INFO +1 -1
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/_config.yml +1 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/bots/bot_manager.py +3 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/bots/config.py +18 -6
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/cli/_helpers.py +12 -3
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/cli/agent.py +101 -8
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/cli/bot.py +79 -2
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/cli/mesh.py +64 -11
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/cli/server.py +173 -1
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/config.py +102 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/mesh_config.py +10 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/operations/cli.md +66 -2
- agentirc_cli-4.2.0/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +253 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/pyproject.toml +1 -1
- agentirc_cli-4.2.0/tests/test_archive.py +436 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_mesh_config.py +37 -0
- agentirc_cli-4.2.0/tests/test_setup_update_cli.py +185 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/uv.lock +1 -1
- agentirc_cli-4.1.2/tests/test_setup_update_cli.py +0 -45
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.flake8 +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.github/workflows/pages.yml +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.gitignore +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.pr_agent.toml +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/.pylintrc +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/CLAUDE.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/CNAME +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/LICENSE +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/README.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/SECURITY.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/__main__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/bots/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/bots/bot.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/cli/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/cli/channel.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/cli/skills.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/agent_runner.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/config.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/daemon.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/irc_transport.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/daemon.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/irc_transport.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/agent_runner.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/config.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/daemon.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/irc_transport.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/agent_runner.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/config.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/daemon.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/irc_transport.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/console/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/console/app.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/console/client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/console/commands.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/credentials.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/learn_prompt.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/observer.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/overview/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/overview/collector.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/overview/model.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/overview/web/style.css +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/persistence.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/pidfile.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/protocol/commands.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/protocol/message.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/protocol/replies.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/__main__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/channel.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/config.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/ircd.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/remote_client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/room_store.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/rooms_util.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/server_link.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/skill.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/skills/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/skills/history.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/skills/icon.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/skills/rooms.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/skills/threads.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/server/thread_store.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/agent-lifecycle.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/agentic-self-learn.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/agent-client.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/harness-conformance.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/index.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/layer1-core-irc.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/layer2-attention.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/layer3-skills.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/layer4-federation.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/layer5-agent-harness.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/server-architecture.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/architecture/threads.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/channel-polling.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/acp/overview.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/codex/configuration.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/codex/overview.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/codex/setup.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/copilot/configuration.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/copilot/setup.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/culture-cli.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/getting-started.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/index.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/operations/SECURITY.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/operations/bots.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/operations/ci.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/operations/docs-site.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/operations/index.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/operations/ops-tooling.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/operations/overview.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/operations/publishing.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/rooms.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/server-rename.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/use-cases-index.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/docs/what-is-culture.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/packages/agent-harness/daemon.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/packages/agent-harness/irc_transport.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/sonar-project.properties +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/__init__.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/conftest.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_bot.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_bot_config.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_channel.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_connection.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_console_client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_console_commands.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_console_connection.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_console_icons.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_console_integration.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_daemon.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_discovery.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_federation.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_history.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_http_listener.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_ipc.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_mention_target_cleanup.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_mentions.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_message.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_messaging.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_modes.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_overview_model.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_overview_web.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_persistence.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_pidfile.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_rooms.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_skill_client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_skills.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_socket_server.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_supervisor.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_template_engine.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_threads.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-4.1.2 → agentirc_cli-4.2.0}/tests/test_webhook.py +0 -0
|
@@ -4,6 +4,24 @@ 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.0] - 2026-04-07
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Archive and unarchive commands for servers, agents, and bots
|
|
13
|
+
- Cascade archive: server archive automatically archives all agents and bots
|
|
14
|
+
- Visibility filtering: archived entities hidden from default status/list views
|
|
15
|
+
- --all flag on status/list to reveal archived entities
|
|
16
|
+
- Start guard: archived entities cannot be started until unarchived
|
|
17
|
+
|
|
18
|
+
## [4.1.3] - 2026-04-06
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- mesh update now discovers and restarts all running servers instead of only the one in mesh.yaml
|
|
24
|
+
|
|
7
25
|
## [4.1.2] - 2026-04-06
|
|
8
26
|
|
|
9
27
|
|
|
@@ -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
|
|
@@ -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}")
|
|
@@ -549,23 +549,76 @@ def _restart_mesh_services(
|
|
|
549
549
|
check=False,
|
|
550
550
|
)
|
|
551
551
|
|
|
552
|
-
print(
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
def
|
|
556
|
-
|
|
552
|
+
print()
|
|
553
|
+
|
|
554
|
+
|
|
555
|
+
def _resolve_mesh_for_server(server_name: str, config_path: str):
|
|
556
|
+
"""Find or build a MeshConfig for *server_name*.
|
|
557
|
+
|
|
558
|
+
Resolution order:
|
|
559
|
+
1. mesh.yaml — use directly if its server.name matches.
|
|
560
|
+
2. agents.yaml — build via from_daemon_config(), preserving host, port,
|
|
561
|
+
and links from the old mesh.yaml. Saves the updated mesh.yaml so
|
|
562
|
+
future runs are consistent.
|
|
563
|
+
"""
|
|
564
|
+
from culture.mesh_config import (
|
|
565
|
+
from_daemon_config,
|
|
566
|
+
load_mesh_config,
|
|
567
|
+
merge_links,
|
|
568
|
+
save_mesh_config,
|
|
569
|
+
)
|
|
557
570
|
|
|
571
|
+
old_server = None
|
|
558
572
|
try:
|
|
559
|
-
|
|
573
|
+
old_mesh = load_mesh_config(config_path)
|
|
574
|
+
if old_mesh.server.name == server_name:
|
|
575
|
+
return old_mesh
|
|
576
|
+
old_server = old_mesh.server
|
|
560
577
|
except FileNotFoundError:
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
578
|
+
pass
|
|
579
|
+
|
|
580
|
+
if os.path.isfile(DEFAULT_CONFIG):
|
|
581
|
+
daemon_config = load_config(DEFAULT_CONFIG)
|
|
582
|
+
if daemon_config.server.name == server_name:
|
|
583
|
+
mesh = from_daemon_config(daemon_config)
|
|
584
|
+
if old_server is not None:
|
|
585
|
+
mesh.server.host = old_server.host
|
|
586
|
+
mesh.server.port = old_server.port
|
|
587
|
+
merge_links(mesh, old_server.links)
|
|
588
|
+
save_mesh_config(mesh, config_path)
|
|
589
|
+
return mesh
|
|
590
|
+
|
|
591
|
+
return None
|
|
564
592
|
|
|
565
|
-
|
|
593
|
+
|
|
594
|
+
def _cmd_update(args: argparse.Namespace) -> None:
|
|
595
|
+
from culture.mesh_config import load_mesh_config
|
|
596
|
+
from culture.pidfile import list_servers
|
|
566
597
|
|
|
567
598
|
if not _upgrade_culture_package(args):
|
|
568
599
|
return
|
|
569
600
|
|
|
570
601
|
culture_bin = shutil.which("culture") or "culture"
|
|
571
|
-
|
|
602
|
+
|
|
603
|
+
running = list_servers()
|
|
604
|
+
|
|
605
|
+
if running:
|
|
606
|
+
for srv in running:
|
|
607
|
+
mesh = _resolve_mesh_for_server(srv["name"], args.config)
|
|
608
|
+
if mesh is None:
|
|
609
|
+
print(
|
|
610
|
+
f" Warning: no config found for server '{srv['name']}', skipping",
|
|
611
|
+
file=sys.stderr,
|
|
612
|
+
)
|
|
613
|
+
continue
|
|
614
|
+
_restart_mesh_services(mesh, srv["name"], culture_bin, args.config, args.dry_run)
|
|
615
|
+
else:
|
|
616
|
+
try:
|
|
617
|
+
mesh = load_mesh_config(args.config)
|
|
618
|
+
except FileNotFoundError:
|
|
619
|
+
mesh = generate_mesh_from_agents(args.config)
|
|
620
|
+
if mesh is None:
|
|
621
|
+
sys.exit(1)
|
|
622
|
+
_restart_mesh_services(mesh, mesh.server.name, culture_bin, args.config, args.dry_run)
|
|
623
|
+
|
|
624
|
+
print("Update complete. All services restarted.")
|