agentirc-cli 2.0.1__tar.gz → 3.0.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-2.0.1 → agentirc_cli-3.0.1}/CHANGELOG.md +20 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/PKG-INFO +14 -13
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/README.md +12 -12
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/cli.py +143 -8
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/config.py +1 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/irc_transport.py +4 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/config.py +1 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/irc_transport.py +4 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/config.py +1 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/irc_transport.py +4 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/config.py +1 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/irc_transport.py +4 -0
- agentirc_cli-3.0.1/culture/console/__init__.py +1 -0
- agentirc_cli-3.0.1/culture/console/app.py +576 -0
- agentirc_cli-3.0.1/culture/console/client.py +381 -0
- agentirc_cli-3.0.1/culture/console/commands.py +93 -0
- agentirc_cli-3.0.1/culture/console/widgets/__init__.py +1 -0
- agentirc_cli-3.0.1/culture/console/widgets/chat.py +147 -0
- agentirc_cli-3.0.1/culture/console/widgets/info_panel.py +172 -0
- agentirc_cli-3.0.1/culture/console/widgets/sidebar.py +191 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/overview/collector.py +28 -21
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/pidfile.py +39 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/protocol/commands.py +1 -0
- agentirc_cli-3.0.1/culture/protocol/extensions/icons.md +89 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/client.py +21 -1
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/ircd.py +2 -0
- agentirc_cli-3.0.1/culture/server/skills/icon.py +52 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/index.md +17 -0
- agentirc_cli-3.0.1/docs/superpowers/plans/2026-04-06-console-chat.md +2246 -0
- agentirc_cli-3.0.1/docs/superpowers/specs/2026-04-06-console-chat-design.md +298 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/packages/agent-harness/config.py +1 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/packages/agent-harness/irc_transport.py +4 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/pyproject.toml +2 -1
- agentirc_cli-3.0.1/tests/test_console_client.py +298 -0
- agentirc_cli-3.0.1/tests/test_console_commands.py +129 -0
- agentirc_cli-3.0.1/tests/test_console_connection.py +70 -0
- agentirc_cli-3.0.1/tests/test_console_icons.py +228 -0
- agentirc_cli-3.0.1/tests/test_console_integration.py +65 -0
- agentirc_cli-3.0.1/tests/test_overview_cli.py +133 -0
- agentirc_cli-3.0.1/tests/test_server_icon_skill.py +214 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/uv.lock +58 -1
- agentirc_cli-2.0.1/tests/test_overview_cli.py +0 -42
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.flake8 +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.github/workflows/pages.yml +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.gitignore +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.pr_agent.toml +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/.pylintrc +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/CLAUDE.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/CNAME +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/Gemfile +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/Gemfile.lock +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/LICENSE +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/SECURITY.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/_config.yml +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/__main__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/bots/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/bots/bot.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/bots/bot_manager.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/bots/config.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/agent_runner.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/daemon.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/daemon.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/agent_runner.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/daemon.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/agent_runner.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/daemon.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/credentials.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/learn_prompt.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/mesh_config.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/observer.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/overview/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/overview/model.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/overview/web/style.css +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/persistence.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/protocol/message.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/protocol/replies.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/__main__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/channel.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/config.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/remote_client.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/room_store.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/rooms_util.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/server_link.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/skill.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/skills/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/skills/history.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/skills/rooms.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/skills/threads.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/server/thread_store.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/agent-lifecycle.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/agentic-self-learn.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/agent-client.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/design.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/harness-conformance.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/index.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/layer1-core-irc.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/layer2-attention.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/layer3-skills.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/layer4-federation.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/layer5-agent-harness.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/server-architecture.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/architecture/threads.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/acp/overview.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/codex/configuration.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/codex/overview.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/codex/setup.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/copilot/configuration.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/copilot/setup.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/culture-cli.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/getting-started.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/operations/SECURITY.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/operations/bots.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/operations/ci.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/operations/cli.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/operations/docs-site.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/operations/index.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/operations/ops-tooling.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/operations/overview.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/operations/publishing.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/rooms.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/use-cases-index.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/docs/what-is-culture.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/packages/agent-harness/daemon.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/sonar-project.properties +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/__init__.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/conftest.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_bot.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_bot_config.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_channel.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_connection.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_daemon.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_discovery.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_federation.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_history.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_http_listener.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_ipc.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_mentions.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_message.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_messaging.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_modes.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_overview_model.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_overview_web.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_persistence.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_pidfile.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_rooms.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_skill_client.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_skills.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_socket_server.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_supervisor.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_template_engine.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_threads.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-2.0.1 → agentirc_cli-3.0.1}/tests/test_webhook.py +0 -0
|
@@ -4,6 +4,26 @@ 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
|
+
## [3.0.1] - 2026-04-06
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Fix empty error message when running `culture overview` against a starting or unreachable server
|
|
13
|
+
|
|
14
|
+
## [3.0.0] - 2026-04-06
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
|
|
19
|
+
- Console chat TUI for human participation in the IRC mesh (culture console)
|
|
20
|
+
- ICON IRC protocol extension for custom entity icons
|
|
21
|
+
- User modes (+H/+A/+B) for entity type identification
|
|
22
|
+
- Server discovery and default server management
|
|
23
|
+
- Three-column TUI layout with sidebar, chat, and info panel
|
|
24
|
+
- View switching: overview, status, agent detail
|
|
25
|
+
- Command parser with full CLI command parity
|
|
26
|
+
|
|
7
27
|
## [2.0.1] - 2026-04-05
|
|
8
28
|
|
|
9
29
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentirc-cli
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.1
|
|
4
4
|
Summary: Legacy alias for culture — install culture instead
|
|
5
5
|
Project-URL: Homepage, https://github.com/OriNachum/culture
|
|
6
6
|
Author: Ori Nachum
|
|
@@ -17,6 +17,7 @@ Requires-Dist: anthropic>=0.40
|
|
|
17
17
|
Requires-Dist: claude-agent-sdk>=0.1
|
|
18
18
|
Requires-Dist: mistune>=3.0
|
|
19
19
|
Requires-Dist: pyyaml>=6.0
|
|
20
|
+
Requires-Dist: textual>=1.0
|
|
20
21
|
Provides-Extra: copilot
|
|
21
22
|
Requires-Dist: github-copilot-sdk; extra == 'copilot'
|
|
22
23
|
Description-Content-Type: text/markdown
|
|
@@ -72,18 +73,18 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
72
73
|
|
|
73
74
|
## Why Culture
|
|
74
75
|
|
|
75
|
-
| | Culture | Ruflo |
|
|
76
|
-
|
|
77
|
-
| **Architecture** | Peer mesh — no hierarchy, servers link as equals | Queen-led swarm hierarchies with centralized ledger |
|
|
78
|
-
| **Protocol** | IRC (simple, text-native, LLM-familiar) — any client connects | Proprietary CLI/MCP with custom messaging |
|
|
79
|
-
| **Federation** | Real server-to-server across machines | Within single orchestration instance |
|
|
80
|
-
| **Agent backends** | Claude, Codex, Copilot, ACP (any) — each runs natively | Multi-LLM routing, primarily Claude-focused |
|
|
81
|
-
| **Human participation** | First-class — same protocol, any IRC client | Pair programming modes with verification gates |
|
|
82
|
-
| **Lifecycle** | Persistent daemons with sleep/wake cycles | Lifecycle hooks, no explicit sleep/wake |
|
|
83
|
-
| **Spiraling detection** | AI supervisor reads conversation meaning | Retry limits + fallback agents |
|
|
84
|
-
| **Observability** | Live web dashboard + any IRC client | CLI commands (metrics partially mocked) |
|
|
85
|
-
| **Self-organization** | Tag-driven room membership | ML-based routing with learning pipeline |
|
|
86
|
-
| **Philosophy** | Simple, organic, transparent | Enterprise-complex (130+ skills, vector DB, Q-learning) |
|
|
76
|
+
| | Culture | Agent Orchestrator | Ruflo |
|
|
77
|
+
|---|---|---|---|
|
|
78
|
+
| **Architecture** | Peer mesh — no hierarchy, servers link as equals | Plugin-based orchestrator — spawns workers per issue | Queen-led swarm hierarchies with centralized ledger |
|
|
79
|
+
| **Protocol** | IRC (simple, text-native, LLM-familiar) — any client connects | Git worktrees + GitHub/GitLab APIs | Proprietary CLI/MCP with custom messaging |
|
|
80
|
+
| **Federation** | Real server-to-server across machines | Single-machine orchestration | Within single orchestration instance |
|
|
81
|
+
| **Agent backends** | Claude, Codex, Copilot, ACP (any) — each runs natively | Claude Code, Codex, Aider, OpenCode — plugin-swappable | Multi-LLM routing, primarily Claude-focused |
|
|
82
|
+
| **Human participation** | First-class — same protocol, any IRC client | Dashboard supervisor — pulled in for approvals | Pair programming modes with verification gates |
|
|
83
|
+
| **Lifecycle** | Persistent daemons with sleep/wake cycles | Spawns per-issue, cleans up after merge | Lifecycle hooks, no explicit sleep/wake |
|
|
84
|
+
| **Spiraling detection** | AI supervisor reads conversation meaning | Retry limits + escalation timeouts | Retry limits + fallback agents |
|
|
85
|
+
| **Observability** | Live web dashboard + any IRC client | Web dashboard + Slack/Discord/webhook alerts | CLI commands (metrics partially mocked) |
|
|
86
|
+
| **Self-organization** | Tag-driven room membership | Orchestrator assigns issues to workers | ML-based routing with learning pipeline |
|
|
87
|
+
| **Philosophy** | Simple, organic, transparent | Parallel coding coordinator — isolation via worktrees | Enterprise-complex (130+ skills, vector DB, Q-learning) |
|
|
87
88
|
|
|
88
89
|
---
|
|
89
90
|
|
|
@@ -49,18 +49,18 @@ Claude Code · Codex · Copilot · ACP (Cline, Kiro, OpenCode, Gemini, ...)
|
|
|
49
49
|
|
|
50
50
|
## Why Culture
|
|
51
51
|
|
|
52
|
-
| | Culture | Ruflo |
|
|
53
|
-
|
|
54
|
-
| **Architecture** | Peer mesh — no hierarchy, servers link as equals | Queen-led swarm hierarchies with centralized ledger |
|
|
55
|
-
| **Protocol** | IRC (simple, text-native, LLM-familiar) — any client connects | Proprietary CLI/MCP with custom messaging |
|
|
56
|
-
| **Federation** | Real server-to-server across machines | Within single orchestration instance |
|
|
57
|
-
| **Agent backends** | Claude, Codex, Copilot, ACP (any) — each runs natively | Multi-LLM routing, primarily Claude-focused |
|
|
58
|
-
| **Human participation** | First-class — same protocol, any IRC client | Pair programming modes with verification gates |
|
|
59
|
-
| **Lifecycle** | Persistent daemons with sleep/wake cycles | Lifecycle hooks, no explicit sleep/wake |
|
|
60
|
-
| **Spiraling detection** | AI supervisor reads conversation meaning | Retry limits + fallback agents |
|
|
61
|
-
| **Observability** | Live web dashboard + any IRC client | CLI commands (metrics partially mocked) |
|
|
62
|
-
| **Self-organization** | Tag-driven room membership | ML-based routing with learning pipeline |
|
|
63
|
-
| **Philosophy** | Simple, organic, transparent | Enterprise-complex (130+ skills, vector DB, Q-learning) |
|
|
52
|
+
| | Culture | Agent Orchestrator | Ruflo |
|
|
53
|
+
|---|---|---|---|
|
|
54
|
+
| **Architecture** | Peer mesh — no hierarchy, servers link as equals | Plugin-based orchestrator — spawns workers per issue | Queen-led swarm hierarchies with centralized ledger |
|
|
55
|
+
| **Protocol** | IRC (simple, text-native, LLM-familiar) — any client connects | Git worktrees + GitHub/GitLab APIs | Proprietary CLI/MCP with custom messaging |
|
|
56
|
+
| **Federation** | Real server-to-server across machines | Single-machine orchestration | Within single orchestration instance |
|
|
57
|
+
| **Agent backends** | Claude, Codex, Copilot, ACP (any) — each runs natively | Claude Code, Codex, Aider, OpenCode — plugin-swappable | Multi-LLM routing, primarily Claude-focused |
|
|
58
|
+
| **Human participation** | First-class — same protocol, any IRC client | Dashboard supervisor — pulled in for approvals | Pair programming modes with verification gates |
|
|
59
|
+
| **Lifecycle** | Persistent daemons with sleep/wake cycles | Spawns per-issue, cleans up after merge | Lifecycle hooks, no explicit sleep/wake |
|
|
60
|
+
| **Spiraling detection** | AI supervisor reads conversation meaning | Retry limits + escalation timeouts | Retry limits + fallback agents |
|
|
61
|
+
| **Observability** | Live web dashboard + any IRC client | Web dashboard + Slack/Discord/webhook alerts | CLI commands (metrics partially mocked) |
|
|
62
|
+
| **Self-organization** | Tag-driven room membership | Orchestrator assigns issues to workers | ML-based routing with learning pipeline |
|
|
63
|
+
| **Philosophy** | Simple, organic, transparent | Parallel coding coordinator — isolation via worktrees | Enterprise-complex (130+ skills, vector DB, Q-learning) |
|
|
64
64
|
|
|
65
65
|
---
|
|
66
66
|
|
|
@@ -18,6 +18,7 @@ Subcommands:
|
|
|
18
18
|
culture overview [--room X] [--agent X] Show mesh overview
|
|
19
19
|
culture setup [--config X] [--uninstall] Set up mesh from mesh.yaml
|
|
20
20
|
culture update [--dry-run] [--skip-upgrade] Upgrade and restart mesh
|
|
21
|
+
culture console [server_name] Interactive admin console TUI
|
|
21
22
|
"""
|
|
22
23
|
|
|
23
24
|
from __future__ import annotations
|
|
@@ -131,6 +132,9 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
131
132
|
srv_status = server_sub.add_parser("status", help="Check server daemon status")
|
|
132
133
|
srv_status.add_argument("--name", default="culture", help="Server name")
|
|
133
134
|
|
|
135
|
+
srv_default = server_sub.add_parser("default", help="Set default server")
|
|
136
|
+
srv_default.add_argument("name", help="Server name to set as default")
|
|
137
|
+
|
|
134
138
|
# -- create / join subcommands -----------------------------------------
|
|
135
139
|
# 'create' registers an agent definition; 'join' adds it to the mesh.
|
|
136
140
|
# 'init' is a deprecated alias for 'create'.
|
|
@@ -316,6 +320,20 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
316
320
|
bot_inspect.add_argument("name", help="Bot name")
|
|
317
321
|
bot_inspect.add_argument("--config", default=DEFAULT_CONFIG, help="Config file path")
|
|
318
322
|
|
|
323
|
+
# -- console subcommand ------------------------------------------------
|
|
324
|
+
console_parser = sub.add_parser("console", help="Interactive admin console")
|
|
325
|
+
console_parser.add_argument(
|
|
326
|
+
"server_name",
|
|
327
|
+
nargs="?",
|
|
328
|
+
default=None,
|
|
329
|
+
help="Server to connect to (auto-detects if omitted)",
|
|
330
|
+
)
|
|
331
|
+
console_parser.add_argument(
|
|
332
|
+
"--config",
|
|
333
|
+
default=DEFAULT_CONFIG,
|
|
334
|
+
help="Config file path",
|
|
335
|
+
)
|
|
336
|
+
|
|
319
337
|
return parser
|
|
320
338
|
|
|
321
339
|
|
|
@@ -353,6 +371,7 @@ def main() -> None:
|
|
|
353
371
|
"setup": _cmd_setup,
|
|
354
372
|
"update": _cmd_update,
|
|
355
373
|
"bot": _cmd_bot,
|
|
374
|
+
"console": _cmd_console,
|
|
356
375
|
}
|
|
357
376
|
handler = dispatch.get(args.command)
|
|
358
377
|
if handler:
|
|
@@ -367,6 +386,90 @@ def main() -> None:
|
|
|
367
386
|
sys.exit(1)
|
|
368
387
|
|
|
369
388
|
|
|
389
|
+
# -----------------------------------------------------------------------
|
|
390
|
+
# Console subcommand
|
|
391
|
+
# -----------------------------------------------------------------------
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def _resolve_server(server_name: str | None) -> tuple[str, int] | None:
|
|
395
|
+
"""Resolve server name and port from running servers.
|
|
396
|
+
|
|
397
|
+
Returns (server_name, port) or None if no servers are running.
|
|
398
|
+
"""
|
|
399
|
+
from culture.pidfile import list_servers, read_default_server, read_port
|
|
400
|
+
|
|
401
|
+
if server_name:
|
|
402
|
+
p = read_port(server_name)
|
|
403
|
+
port = p if p else 6667
|
|
404
|
+
return server_name, port
|
|
405
|
+
|
|
406
|
+
servers = list_servers()
|
|
407
|
+
if not servers:
|
|
408
|
+
return None
|
|
409
|
+
|
|
410
|
+
if len(servers) == 1:
|
|
411
|
+
return servers[0]["name"], servers[0]["port"]
|
|
412
|
+
|
|
413
|
+
default = read_default_server()
|
|
414
|
+
if default:
|
|
415
|
+
match = [s for s in servers if s["name"] == default]
|
|
416
|
+
if match:
|
|
417
|
+
return match[0]["name"], match[0]["port"]
|
|
418
|
+
|
|
419
|
+
return servers[0]["name"], servers[0]["port"]
|
|
420
|
+
|
|
421
|
+
|
|
422
|
+
def _cmd_console(args: argparse.Namespace) -> None:
|
|
423
|
+
"""Launch the interactive console TUI."""
|
|
424
|
+
result = _resolve_server(args.server_name)
|
|
425
|
+
if result is None:
|
|
426
|
+
print("No culture servers running. Start one with: culture server start")
|
|
427
|
+
return
|
|
428
|
+
|
|
429
|
+
server_name, port = result
|
|
430
|
+
host = "127.0.0.1"
|
|
431
|
+
|
|
432
|
+
nick_suffix = _resolve_console_nick()
|
|
433
|
+
nick = f"{server_name}-{nick_suffix}"
|
|
434
|
+
|
|
435
|
+
from culture.console.app import ConsoleApp
|
|
436
|
+
from culture.console.client import ConsoleIRCClient
|
|
437
|
+
|
|
438
|
+
client = ConsoleIRCClient(host=host, port=port, nick=nick, mode="H")
|
|
439
|
+
|
|
440
|
+
async def run():
|
|
441
|
+
await client.connect()
|
|
442
|
+
app = ConsoleApp(irc_client=client, server_name=server_name)
|
|
443
|
+
await app.run_async()
|
|
444
|
+
|
|
445
|
+
asyncio.run(run())
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def _resolve_console_nick() -> str:
|
|
449
|
+
"""Resolve the human nick: git username -> OS user -> config override."""
|
|
450
|
+
import re
|
|
451
|
+
import subprocess
|
|
452
|
+
|
|
453
|
+
try:
|
|
454
|
+
result = subprocess.run(
|
|
455
|
+
["git", "config", "user.name"],
|
|
456
|
+
capture_output=True,
|
|
457
|
+
text=True,
|
|
458
|
+
timeout=2,
|
|
459
|
+
)
|
|
460
|
+
if result.returncode == 0 and result.stdout.strip():
|
|
461
|
+
name = result.stdout.strip().lower()
|
|
462
|
+
name = re.sub(r"[^a-z0-9-]", "", name.replace(" ", "-"))
|
|
463
|
+
if name:
|
|
464
|
+
return name
|
|
465
|
+
except (subprocess.SubprocessError, FileNotFoundError):
|
|
466
|
+
pass
|
|
467
|
+
|
|
468
|
+
import os
|
|
469
|
+
|
|
470
|
+
return os.environ.get("USER", "human")
|
|
471
|
+
|
|
472
|
+
|
|
370
473
|
# -----------------------------------------------------------------------
|
|
371
474
|
# Server subcommands
|
|
372
475
|
# -----------------------------------------------------------------------
|
|
@@ -374,7 +477,7 @@ def main() -> None:
|
|
|
374
477
|
|
|
375
478
|
def _cmd_server(args: argparse.Namespace) -> None:
|
|
376
479
|
if not args.server_command:
|
|
377
|
-
print("Usage: culture server {start|stop|status}", file=sys.stderr)
|
|
480
|
+
print("Usage: culture server {start|stop|status|default}", file=sys.stderr)
|
|
378
481
|
sys.exit(1)
|
|
379
482
|
|
|
380
483
|
if args.server_command == "start":
|
|
@@ -383,6 +486,11 @@ def _cmd_server(args: argparse.Namespace) -> None:
|
|
|
383
486
|
_server_stop(args)
|
|
384
487
|
elif args.server_command == "status":
|
|
385
488
|
_server_status(args)
|
|
489
|
+
elif args.server_command == "default":
|
|
490
|
+
from culture.pidfile import write_default_server
|
|
491
|
+
|
|
492
|
+
write_default_server(args.name)
|
|
493
|
+
print(f"Default server set to '{args.name}'")
|
|
386
494
|
|
|
387
495
|
|
|
388
496
|
def _server_start(args: argparse.Namespace) -> None:
|
|
@@ -406,6 +514,11 @@ def _server_start(args: argparse.Namespace) -> None:
|
|
|
406
514
|
print(f"Server '{args.name}' starting in foreground (PID {os.getpid()})")
|
|
407
515
|
print(f" Listening on {args.host}:{args.port}")
|
|
408
516
|
print(f" Webhook port: {args.webhook_port}")
|
|
517
|
+
# Auto-set default server if none is set
|
|
518
|
+
from culture.pidfile import read_default_server, write_default_server
|
|
519
|
+
|
|
520
|
+
if read_default_server() is None:
|
|
521
|
+
write_default_server(args.name)
|
|
409
522
|
try:
|
|
410
523
|
asyncio.run(_run_server(args.name, args.host, args.port, links, args.webhook_port))
|
|
411
524
|
finally:
|
|
@@ -424,6 +537,11 @@ def _server_start(args: argparse.Namespace) -> None:
|
|
|
424
537
|
print(f"Server '{args.name}' started (PID {pid})")
|
|
425
538
|
print(f" Listening on {args.host}:{args.port}")
|
|
426
539
|
print(f" Logs: {LOG_DIR}/server-{args.name}.log")
|
|
540
|
+
# Auto-set default server if none is set
|
|
541
|
+
from culture.pidfile import read_default_server, write_default_server
|
|
542
|
+
|
|
543
|
+
if read_default_server() is None:
|
|
544
|
+
write_default_server(args.name)
|
|
427
545
|
else:
|
|
428
546
|
print(f"Server '{args.name}' failed to start", file=sys.stderr)
|
|
429
547
|
sys.exit(1)
|
|
@@ -1475,14 +1593,31 @@ def _cmd_overview(args: argparse.Namespace) -> None:
|
|
|
1475
1593
|
)
|
|
1476
1594
|
return
|
|
1477
1595
|
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1596
|
+
host, port = config.server.host, config.server.port
|
|
1597
|
+
try:
|
|
1598
|
+
mesh = asyncio.run(
|
|
1599
|
+
collect_mesh_state(
|
|
1600
|
+
host=host,
|
|
1601
|
+
port=port,
|
|
1602
|
+
server_name=config.server.name,
|
|
1603
|
+
message_limit=message_limit,
|
|
1604
|
+
)
|
|
1484
1605
|
)
|
|
1485
|
-
|
|
1606
|
+
except ConnectionRefusedError:
|
|
1607
|
+
print(
|
|
1608
|
+
f"Error: could not connect to {host}:{port} — is the server running?",
|
|
1609
|
+
file=sys.stderr,
|
|
1610
|
+
)
|
|
1611
|
+
sys.exit(1)
|
|
1612
|
+
except TimeoutError:
|
|
1613
|
+
print(
|
|
1614
|
+
f"Error: server at {host}:{port} not responding" " — it may still be starting up",
|
|
1615
|
+
file=sys.stderr,
|
|
1616
|
+
)
|
|
1617
|
+
sys.exit(1)
|
|
1618
|
+
except OSError as exc:
|
|
1619
|
+
print(f"Error: {exc}", file=sys.stderr)
|
|
1620
|
+
sys.exit(1)
|
|
1486
1621
|
output = render_text(
|
|
1487
1622
|
mesh,
|
|
1488
1623
|
room_filter=args.room,
|
|
@@ -24,6 +24,7 @@ class IRCTransport:
|
|
|
24
24
|
on_mention: Callable[[str, str, str], None] | None = None,
|
|
25
25
|
tags: list[str] | None = None,
|
|
26
26
|
on_roominvite: Callable[[str, str], None] | None = None,
|
|
27
|
+
icon: str | None = None,
|
|
27
28
|
):
|
|
28
29
|
self.host = host
|
|
29
30
|
self.port = port
|
|
@@ -34,6 +35,7 @@ class IRCTransport:
|
|
|
34
35
|
self.on_mention = on_mention
|
|
35
36
|
self.tags = tags or []
|
|
36
37
|
self.on_roominvite = on_roominvite
|
|
38
|
+
self.icon = icon
|
|
37
39
|
self.connected = False
|
|
38
40
|
self._reader: asyncio.StreamReader | None = None
|
|
39
41
|
self._writer: asyncio.StreamWriter | None = None
|
|
@@ -174,6 +176,8 @@ class IRCTransport:
|
|
|
174
176
|
if self.tags:
|
|
175
177
|
tags_str = ",".join(self.tags)
|
|
176
178
|
await self._send_raw(f"TAGS {self.nick} {tags_str}")
|
|
179
|
+
if self.icon:
|
|
180
|
+
await self._send_raw(f"ICON {self.icon}")
|
|
177
181
|
|
|
178
182
|
async def _on_privmsg(self, msg: Message) -> None:
|
|
179
183
|
if len(msg.params) < 2:
|
|
@@ -24,6 +24,7 @@ class IRCTransport:
|
|
|
24
24
|
on_mention: Callable[[str, str, str], None] | None = None,
|
|
25
25
|
tags: list[str] | None = None,
|
|
26
26
|
on_roominvite: Callable[[str, str], None] | None = None,
|
|
27
|
+
icon: str | None = None,
|
|
27
28
|
):
|
|
28
29
|
self.host = host
|
|
29
30
|
self.port = port
|
|
@@ -34,6 +35,7 @@ class IRCTransport:
|
|
|
34
35
|
self.on_mention = on_mention
|
|
35
36
|
self.tags = tags or []
|
|
36
37
|
self.on_roominvite = on_roominvite
|
|
38
|
+
self.icon = icon
|
|
37
39
|
self.connected = False
|
|
38
40
|
self._reader: asyncio.StreamReader | None = None
|
|
39
41
|
self._writer: asyncio.StreamWriter | None = None
|
|
@@ -174,6 +176,8 @@ class IRCTransport:
|
|
|
174
176
|
if self.tags:
|
|
175
177
|
tags_str = ",".join(self.tags)
|
|
176
178
|
await self._send_raw(f"TAGS {self.nick} {tags_str}")
|
|
179
|
+
if self.icon:
|
|
180
|
+
await self._send_raw(f"ICON {self.icon}")
|
|
177
181
|
|
|
178
182
|
async def _on_privmsg(self, msg: Message) -> None:
|
|
179
183
|
if len(msg.params) < 2:
|
|
@@ -24,6 +24,7 @@ class IRCTransport:
|
|
|
24
24
|
on_mention: Callable[[str, str, str], None] | None = None,
|
|
25
25
|
tags: list[str] | None = None,
|
|
26
26
|
on_roominvite: Callable[[str, str], None] | None = None,
|
|
27
|
+
icon: str | None = None,
|
|
27
28
|
):
|
|
28
29
|
self.host = host
|
|
29
30
|
self.port = port
|
|
@@ -34,6 +35,7 @@ class IRCTransport:
|
|
|
34
35
|
self.on_mention = on_mention
|
|
35
36
|
self.tags = tags or []
|
|
36
37
|
self.on_roominvite = on_roominvite
|
|
38
|
+
self.icon = icon
|
|
37
39
|
self.connected = False
|
|
38
40
|
self._reader: asyncio.StreamReader | None = None
|
|
39
41
|
self._writer: asyncio.StreamWriter | None = None
|
|
@@ -174,6 +176,8 @@ class IRCTransport:
|
|
|
174
176
|
if self.tags:
|
|
175
177
|
tags_str = ",".join(self.tags)
|
|
176
178
|
await self._send_raw(f"TAGS {self.nick} {tags_str}")
|
|
179
|
+
if self.icon:
|
|
180
|
+
await self._send_raw(f"ICON {self.icon}")
|
|
177
181
|
|
|
178
182
|
async def _on_privmsg(self, msg: Message) -> None:
|
|
179
183
|
if len(msg.params) < 2:
|
|
@@ -24,6 +24,7 @@ class IRCTransport:
|
|
|
24
24
|
on_mention: Callable[[str, str, str], None] | None = None,
|
|
25
25
|
tags: list[str] | None = None,
|
|
26
26
|
on_roominvite: Callable[[str, str], None] | None = None,
|
|
27
|
+
icon: str | None = None,
|
|
27
28
|
):
|
|
28
29
|
self.host = host
|
|
29
30
|
self.port = port
|
|
@@ -34,6 +35,7 @@ class IRCTransport:
|
|
|
34
35
|
self.on_mention = on_mention
|
|
35
36
|
self.tags = tags or []
|
|
36
37
|
self.on_roominvite = on_roominvite
|
|
38
|
+
self.icon = icon
|
|
37
39
|
self.connected = False
|
|
38
40
|
self._reader: asyncio.StreamReader | None = None
|
|
39
41
|
self._writer: asyncio.StreamWriter | None = None
|
|
@@ -174,6 +176,8 @@ class IRCTransport:
|
|
|
174
176
|
if self.tags:
|
|
175
177
|
tags_str = ",".join(self.tags)
|
|
176
178
|
await self._send_raw(f"TAGS {self.nick} {tags_str}")
|
|
179
|
+
if self.icon:
|
|
180
|
+
await self._send_raw(f"ICON {self.icon}")
|
|
177
181
|
|
|
178
182
|
async def _on_privmsg(self, msg: Message) -> None:
|
|
179
183
|
if len(msg.params) < 2:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Console TUI for culture mesh administration."""
|