agentirc-cli 6.1.1__tar.gz → 6.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-6.1.1 → agentirc_cli-6.2.0}/CHANGELOG.md +14 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/PKG-INFO +2 -2
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/README.md +1 -1
- agentirc_cli-6.2.0/culture/cli/shared/constants.py +43 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/ipc.py +3 -1
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/app.py +148 -26
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/commands.py +2 -0
- agentirc_cli-6.2.0/culture/console/status.py +74 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/widgets/sidebar.py +15 -1
- agentirc_cli-6.2.0/docs/superpowers/plans/2026-04-12-console-enhancements.md +732 -0
- agentirc_cli-6.2.0/docs/superpowers/specs/2026-04-12-console-enhancements-design.md +203 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/pyproject.toml +1 -1
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_console_commands.py +6 -0
- agentirc_cli-6.2.0/tests/test_console_status.py +53 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/uv.lock +1 -1
- agentirc_cli-6.1.1/culture/cli/shared/constants.py +0 -20
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.flake8 +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.github/workflows/docs-check.yml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.gitignore +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.pr_agent.toml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/.pylintrc +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/CLAUDE.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/Gemfile +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/Gemfile.lock +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/LICENSE +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/SECURITY.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_config.agentirc.yml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_config.base.yml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_config.culture.yml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_data/sites.yml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_includes/head_custom.html +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_plugins/site_filter.rb +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_sass/color_schemes/dark-terminal.scss +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/IMG_3183.png +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/apple-touch-icon.png +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/favicon-16x16.png +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/favicon-32x32.png +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/favicon.ico +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/og-agentirc.png +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/assets/images/og-culture.png +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/__main__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/CLAUDE.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/__main__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/channel.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/docs/agentirc-architecture.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/docs/agentirc-features.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/docs/agentirc-skill.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/docs/agentirc.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/history_store.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/ircd.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/remote_client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/room_store.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/rooms_util.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/server_link.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skill.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skills/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skills/history.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skills/icon.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skills/rooms.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/skills/threads.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/agentirc/thread_store.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/aio.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/bot.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/bot_manager.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/agent.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/bot.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/channel.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/mesh.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/server.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/display.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/formatting.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/mesh.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/shared/process.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/cli/skills.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/agent_runner.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/culture.yaml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/daemon.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/irc_transport.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/culture.yaml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/daemon.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/irc_transport.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/agent_runner.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/culture.yaml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/daemon.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/irc_transport.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/agent_runner.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/culture.yaml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/daemon.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/irc_transport.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/credentials.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/formatting.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/learn_prompt.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/mesh_config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/observer.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/collector.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/model.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/overview/web/style.css +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/persistence.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/pidfile.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/commands.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/message.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/protocol/replies.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/README.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/agentirc/architecture-overview.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/agentirc/index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/agentirc/why-agentirc.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/agent-lifecycle.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/choose-a-harness.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/mental-model.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/operate.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/patterns.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/quickstart.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/reflective-development.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/vision-patterns-index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/vision.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/culture/why-culture.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/architecture/index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/architecture/layers.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/architecture/threads.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/cli/commands.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/cli/index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/harnesses/acp.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/harnesses/claude.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/harnesses/codex.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/harnesses/copilot.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/harnesses/index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/server/architecture.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/server/config.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/server/deployment.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/server/index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/reference/server/security.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/federation.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/harnesses.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/humans-and-agents.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/persistence.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/concepts/rooms.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/demos/magic-demo.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/guides/first-session.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/guides/index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/guides/join-as-human.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/guides/local-setup.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/guides/multi-machine.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/shared/use-cases-index.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/plans/2026-04-09-decentralized-agent-config.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-07-reflective-development-reframe-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-08-reflective-development-deepening-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/docs/superpowers/specs/2026-04-09-decentralized-agent-config-design.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/favicon.ico +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/culture.yaml +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/daemon.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/irc_transport.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/robots.txt +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/sonar-project.properties +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/__init__.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/conftest.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_archive.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_bot.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_bot_config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_channel.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_channel_cli.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_connection.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_console_client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_console_connection.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_console_icons.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_console_integration.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_credentials.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_culture_config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_daemon.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_discovery.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_display.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_federation.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_history.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_http_listener.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_ipc.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_learn_prompt.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_manifest_config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mention_target_cleanup.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mention_warning.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mentions.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_mesh_readiness.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_message.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_messaging.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_migrate_cli.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_modes.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_overview_model.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_overview_web.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_persistence.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_pidfile.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_register_cli.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_rooms.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_skill_client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_skill_docs.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_skills.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_socket_server.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_supervisor.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_template_engine.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_threads.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-6.1.1 → agentirc_cli-6.2.0}/tests/test_webhook.py +0 -0
|
@@ -4,6 +4,20 @@ 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
|
+
## [6.2.0] - 2026-04-12
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Agent status indicators in console sidebar (#218) — shows working/idle/paused/circuit-open for each agent
|
|
13
|
+
- Auto-read channel history on switch (#219) — loads last 20 messages when switching channels via Tab, sidebar click, or /join
|
|
14
|
+
- Help menu — /help command and Ctrl+H keybinding showing all commands and keybindings
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- Joined message no longer wiped by channel switch clear_log
|
|
20
|
+
|
|
7
21
|
## [6.1.1] - 2026-04-11
|
|
8
22
|
|
|
9
23
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentirc-cli
|
|
3
|
-
Version: 6.
|
|
3
|
+
Version: 6.2.0
|
|
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
|
|
@@ -27,7 +27,7 @@ Description-Content-Type: text/markdown
|
|
|
27
27
|
The complete human-agent collaboration system built around AgentIRC.
|
|
28
28
|
|
|
29
29
|
**AgentIRC** is the IRC-native runtime for persistent AI agents and humans in shared live rooms.
|
|
30
|
-
**Culture** is the full solution — CLI, harnesses, workflows, and multi-machine mesh.
|
|
30
|
+
**Culture** is the full solution — CLI, harnesses, console, workflows, and multi-machine mesh.
|
|
31
31
|
|
|
32
32
|
## Start here
|
|
33
33
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
The complete human-agent collaboration system built around AgentIRC.
|
|
4
4
|
|
|
5
5
|
**AgentIRC** is the IRC-native runtime for persistent AI agents and humans in shared live rooms.
|
|
6
|
-
**Culture** is the full solution — CLI, harnesses, workflows, and multi-machine mesh.
|
|
6
|
+
**Culture** is the full solution — CLI, harnesses, console, workflows, and multi-machine mesh.
|
|
7
7
|
|
|
8
8
|
## Start here
|
|
9
9
|
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Shared constants for culture CLI modules."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import stat
|
|
5
|
+
|
|
6
|
+
from culture.bots.config import BOT_CONFIG_FILE # noqa: F401
|
|
7
|
+
|
|
8
|
+
DEFAULT_CONFIG = os.path.expanduser("~/.culture/server.yaml")
|
|
9
|
+
LOG_DIR = os.path.expanduser("~/.culture/logs")
|
|
10
|
+
|
|
11
|
+
_CONFIG_HELP = "Config file path"
|
|
12
|
+
_SERVER_NAME_HELP = "Server name"
|
|
13
|
+
_BOT_NAME_HELP = "Bot name"
|
|
14
|
+
|
|
15
|
+
DEFAULT_CHANNEL = "#general"
|
|
16
|
+
NO_AGENTS_MSG = "No agents configured"
|
|
17
|
+
CULTURE_DIR = ".culture"
|
|
18
|
+
AGENTS_YAML = "agents.yaml"
|
|
19
|
+
|
|
20
|
+
DEFAULT_SERVER_CONFIG = os.path.expanduser("~/.culture/server.yaml")
|
|
21
|
+
LEGACY_CONFIG = os.path.expanduser("~/.culture/agents.yaml")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def culture_runtime_dir() -> str:
|
|
25
|
+
"""Return a safe directory for culture daemon sockets.
|
|
26
|
+
|
|
27
|
+
Uses ``$XDG_RUNTIME_DIR`` when available (user-private, set by
|
|
28
|
+
systemd/logind). Otherwise creates a user-private subdirectory
|
|
29
|
+
under the system temp dir so sockets never live in a publicly
|
|
30
|
+
writable location.
|
|
31
|
+
"""
|
|
32
|
+
xdg = os.environ.get("XDG_RUNTIME_DIR")
|
|
33
|
+
if xdg:
|
|
34
|
+
return xdg
|
|
35
|
+
fallback = os.path.join(
|
|
36
|
+
os.path.expanduser("~"),
|
|
37
|
+
".culture",
|
|
38
|
+
"run",
|
|
39
|
+
)
|
|
40
|
+
os.makedirs(fallback, mode=0o700, exist_ok=True)
|
|
41
|
+
# Enforce permissions even if the directory already existed
|
|
42
|
+
os.chmod(fallback, stat.S_IRWXU)
|
|
43
|
+
return fallback
|
|
@@ -9,8 +9,10 @@ from culture.config import load_config_or_default
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
def agent_socket_path(nick: str) -> str:
|
|
12
|
+
from culture.cli.shared.constants import culture_runtime_dir
|
|
13
|
+
|
|
12
14
|
return os.path.join(
|
|
13
|
-
|
|
15
|
+
culture_runtime_dir(),
|
|
14
16
|
f"culture-{nick}.sock",
|
|
15
17
|
)
|
|
16
18
|
|
|
@@ -15,6 +15,7 @@ from textual.widgets import Footer, Header
|
|
|
15
15
|
from culture.aio import maybe_await
|
|
16
16
|
from culture.console.client import ConsoleIRCClient
|
|
17
17
|
from culture.console.commands import CommandType, parse_command
|
|
18
|
+
from culture.console.status import query_all_agents
|
|
18
19
|
from culture.console.widgets.chat import ChatPanel
|
|
19
20
|
from culture.console.widgets.info_panel import InfoPanel
|
|
20
21
|
from culture.console.widgets.sidebar import ChannelItem, EntityItem, Sidebar
|
|
@@ -22,6 +23,7 @@ from culture.console.widgets.sidebar import ChannelItem, EntityItem, Sidebar
|
|
|
22
23
|
logger = logging.getLogger(__name__)
|
|
23
24
|
|
|
24
25
|
BUFFER_INTERVAL = 10.0 # seconds between UI refreshes
|
|
26
|
+
STATUS_POLL_INTERVAL = 30.0 # seconds between agent status polls
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
class ConsoleApp(App):
|
|
@@ -33,6 +35,7 @@ class ConsoleApp(App):
|
|
|
33
35
|
BINDINGS = [
|
|
34
36
|
Binding("ctrl+o", "show_overview", "Overview", show=True),
|
|
35
37
|
Binding("ctrl+s", "show_status", "Status", show=True),
|
|
38
|
+
Binding("ctrl+h", "show_help", "Help", show=True),
|
|
36
39
|
Binding("escape", "back_to_chat", "Chat", show=True),
|
|
37
40
|
Binding("ctrl+q", "quit_app", "Quit", show=True),
|
|
38
41
|
Binding("tab", "next_channel", "Next channel", show=False),
|
|
@@ -65,6 +68,7 @@ class ConsoleApp(App):
|
|
|
65
68
|
|
|
66
69
|
self._buffer_task: asyncio.Task | None = None
|
|
67
70
|
self._background_tasks: set[asyncio.Task] = set()
|
|
71
|
+
self._status_poll_task: asyncio.Task | None = None
|
|
68
72
|
|
|
69
73
|
# Dispatch table for command execution
|
|
70
74
|
self._command_handlers: dict[CommandType, Any] = {
|
|
@@ -84,6 +88,7 @@ class ConsoleApp(App):
|
|
|
84
88
|
CommandType.INVITE: self._handle_invite,
|
|
85
89
|
CommandType.SERVER: self._handle_server,
|
|
86
90
|
CommandType.QUIT: self._handle_quit,
|
|
91
|
+
CommandType.HELP: self._handle_help,
|
|
87
92
|
}
|
|
88
93
|
|
|
89
94
|
# ------------------------------------------------------------------
|
|
@@ -106,6 +111,7 @@ class ConsoleApp(App):
|
|
|
106
111
|
"""Set sub-title and kick off the buffer-drain loop."""
|
|
107
112
|
self.sub_title = f"{self._client.nick}@{self._server_name}"
|
|
108
113
|
self._buffer_task = asyncio.create_task(self._buffer_loop())
|
|
114
|
+
self._status_poll_task = asyncio.create_task(self._status_poll_loop())
|
|
109
115
|
|
|
110
116
|
# Populate sidebar with any channels already joined at startup
|
|
111
117
|
self._sync_sidebar()
|
|
@@ -140,6 +146,43 @@ class ConsoleApp(App):
|
|
|
140
146
|
text=msg.text,
|
|
141
147
|
)
|
|
142
148
|
|
|
149
|
+
async def _status_poll_loop(self) -> None:
|
|
150
|
+
"""Periodically poll agent daemon sockets for status updates."""
|
|
151
|
+
# Initial poll on startup
|
|
152
|
+
await self._poll_agent_status()
|
|
153
|
+
while True:
|
|
154
|
+
try:
|
|
155
|
+
await asyncio.sleep(STATUS_POLL_INTERVAL)
|
|
156
|
+
await self._poll_agent_status()
|
|
157
|
+
except asyncio.CancelledError:
|
|
158
|
+
raise
|
|
159
|
+
except Exception:
|
|
160
|
+
logger.exception("Error in _status_poll_loop")
|
|
161
|
+
|
|
162
|
+
async def _poll_agent_status(self) -> None:
|
|
163
|
+
"""Query daemon sockets and update sidebar entity activity."""
|
|
164
|
+
status_map = await query_all_agents()
|
|
165
|
+
if not status_map:
|
|
166
|
+
return
|
|
167
|
+
sidebar: Sidebar = self.query_one(Sidebar)
|
|
168
|
+
updated = False
|
|
169
|
+
new_entities = []
|
|
170
|
+
for ent in sidebar.entities:
|
|
171
|
+
if ent.nick in status_map:
|
|
172
|
+
new_ent = EntityItem(
|
|
173
|
+
nick=ent.nick,
|
|
174
|
+
entity_type=ent.entity_type,
|
|
175
|
+
online=ent.online,
|
|
176
|
+
icon=ent.icon,
|
|
177
|
+
activity=status_map[ent.nick],
|
|
178
|
+
)
|
|
179
|
+
new_entities.append(new_ent)
|
|
180
|
+
updated = True
|
|
181
|
+
else:
|
|
182
|
+
new_entities.append(ent)
|
|
183
|
+
if updated:
|
|
184
|
+
sidebar.entities = new_entities
|
|
185
|
+
|
|
143
186
|
# ------------------------------------------------------------------
|
|
144
187
|
# Input handler
|
|
145
188
|
# ------------------------------------------------------------------
|
|
@@ -189,9 +232,8 @@ class ConsoleApp(App):
|
|
|
189
232
|
return
|
|
190
233
|
channel = cmd.args[0]
|
|
191
234
|
await self._client.join(channel)
|
|
192
|
-
self._current_channel = channel
|
|
193
235
|
self._sync_sidebar()
|
|
194
|
-
|
|
236
|
+
await self._switch_to_channel(channel)
|
|
195
237
|
chat.add_message(time.time(), "", "system", f"Joined [bold]{channel}[/]")
|
|
196
238
|
|
|
197
239
|
async def _handle_part(self, cmd) -> None: # noqa: ANN001
|
|
@@ -341,6 +383,51 @@ class ConsoleApp(App):
|
|
|
341
383
|
async def _handle_quit(self, cmd) -> None: # noqa: ANN001
|
|
342
384
|
await self.action_quit_app()
|
|
343
385
|
|
|
386
|
+
def _handle_help(self, cmd) -> None: # noqa: ANN001
|
|
387
|
+
self.action_show_help()
|
|
388
|
+
|
|
389
|
+
def action_show_help(self) -> None:
|
|
390
|
+
"""Show help content with all commands and keybindings."""
|
|
391
|
+
self._current_view = "help"
|
|
392
|
+
chat: ChatPanel = self.query_one(ChatPanel)
|
|
393
|
+
lines = [
|
|
394
|
+
"[bold $warning]COMMANDS[/]",
|
|
395
|
+
"",
|
|
396
|
+
" [bold]/help[/] Show this help",
|
|
397
|
+
" [bold]/join[/] #channel Join a channel",
|
|
398
|
+
" [bold]/part[/] [#channel] Leave a channel",
|
|
399
|
+
" [bold]/read[/] [#ch] [-n N] Read channel history (default 50)",
|
|
400
|
+
" [bold]/who[/] [target] List channel members",
|
|
401
|
+
" [bold]/send[/] <target> <text> Send a direct message",
|
|
402
|
+
" [bold]/channels[/] List server channels",
|
|
403
|
+
" [bold]/agents[/] List visible agents",
|
|
404
|
+
" [bold]/status[/] [agent] Show status info",
|
|
405
|
+
" [bold]/overview[/] Show mesh overview",
|
|
406
|
+
" [bold]/icon[/] <emoji> Set your icon",
|
|
407
|
+
" [bold]/topic[/] #ch <text> Set channel topic",
|
|
408
|
+
" [bold]/kick[/] #ch <nick> Kick a user",
|
|
409
|
+
" [bold]/invite[/] <nick> #ch Invite a user",
|
|
410
|
+
" [bold]/server[/] [name] Switch server (restarts console)",
|
|
411
|
+
" [bold]/quit[/] Exit console",
|
|
412
|
+
"",
|
|
413
|
+
"[bold $warning]KEYBINDINGS[/]",
|
|
414
|
+
"",
|
|
415
|
+
" [bold]Tab / Shift+Tab[/] Cycle channels",
|
|
416
|
+
" [bold]Ctrl+O[/] Overview",
|
|
417
|
+
" [bold]Ctrl+S[/] Status",
|
|
418
|
+
" [bold]Ctrl+H[/] Help",
|
|
419
|
+
" [bold]Escape[/] Back to chat",
|
|
420
|
+
" [bold]Ctrl+Q[/] Quit",
|
|
421
|
+
]
|
|
422
|
+
chat.set_content("Help", lines)
|
|
423
|
+
|
|
424
|
+
# Hide input — not meaningful in help view
|
|
425
|
+
try:
|
|
426
|
+
input_widget = self.query_one(self._CHAT_INPUT_ID)
|
|
427
|
+
input_widget.display = False
|
|
428
|
+
except Exception:
|
|
429
|
+
pass
|
|
430
|
+
|
|
344
431
|
# ------------------------------------------------------------------
|
|
345
432
|
# View actions
|
|
346
433
|
# ------------------------------------------------------------------
|
|
@@ -468,8 +555,15 @@ class ConsoleApp(App):
|
|
|
468
555
|
chat.set_content("Agents", lines)
|
|
469
556
|
|
|
470
557
|
# Update sidebar entity roster
|
|
558
|
+
status_map = await query_all_agents()
|
|
471
559
|
entity_items = [
|
|
472
|
-
EntityItem(
|
|
560
|
+
EntityItem(
|
|
561
|
+
nick=nick,
|
|
562
|
+
entity_type="agent",
|
|
563
|
+
online=True,
|
|
564
|
+
activity=status_map.get(nick, ""),
|
|
565
|
+
)
|
|
566
|
+
for nick in sorted(all_agents)
|
|
473
567
|
]
|
|
474
568
|
sidebar.entities = entity_items
|
|
475
569
|
|
|
@@ -506,16 +600,15 @@ class ConsoleApp(App):
|
|
|
506
600
|
if not channels:
|
|
507
601
|
return
|
|
508
602
|
if self._current_channel not in channels:
|
|
509
|
-
|
|
603
|
+
target = channels[0]
|
|
510
604
|
else:
|
|
511
605
|
idx = channels.index(self._current_channel)
|
|
512
606
|
idx = (idx + direction) % len(channels)
|
|
513
|
-
|
|
607
|
+
target = channels[idx]
|
|
514
608
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
sidebar.active_channel = self._current_channel
|
|
609
|
+
task = asyncio.create_task(self._switch_to_channel(target))
|
|
610
|
+
self._background_tasks.add(task)
|
|
611
|
+
task.add_done_callback(self._background_tasks.discard)
|
|
519
612
|
|
|
520
613
|
# ------------------------------------------------------------------
|
|
521
614
|
# Quit
|
|
@@ -523,10 +616,14 @@ class ConsoleApp(App):
|
|
|
523
616
|
|
|
524
617
|
async def action_quit_app(self) -> None:
|
|
525
618
|
"""Disconnect the IRC client and exit the app."""
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
619
|
+
for task_ref in (self._buffer_task, self._status_poll_task):
|
|
620
|
+
if task_ref:
|
|
621
|
+
task_ref.cancel()
|
|
622
|
+
tasks_to_cancel = [t for t in (self._buffer_task, self._status_poll_task) if t]
|
|
623
|
+
if tasks_to_cancel:
|
|
624
|
+
await asyncio.gather(*tasks_to_cancel, return_exceptions=True)
|
|
625
|
+
self._buffer_task = None
|
|
626
|
+
self._status_poll_task = None
|
|
530
627
|
|
|
531
628
|
if self._client.connected:
|
|
532
629
|
try:
|
|
@@ -542,19 +639,9 @@ class ConsoleApp(App):
|
|
|
542
639
|
|
|
543
640
|
def on_sidebar_channel_selected(self, event: Sidebar.ChannelSelected) -> None:
|
|
544
641
|
"""Switch to the selected channel when user clicks sidebar."""
|
|
545
|
-
|
|
546
|
-
self.
|
|
547
|
-
|
|
548
|
-
sidebar: Sidebar = self.query_one(Sidebar)
|
|
549
|
-
chat.set_channel(self._current_channel)
|
|
550
|
-
sidebar.active_channel = self._current_channel
|
|
551
|
-
|
|
552
|
-
# Re-show input if hidden
|
|
553
|
-
try:
|
|
554
|
-
input_widget = self.query_one(self._CHAT_INPUT_ID)
|
|
555
|
-
input_widget.display = True
|
|
556
|
-
except Exception:
|
|
557
|
-
pass
|
|
642
|
+
task = asyncio.create_task(self._switch_to_channel(event.channel))
|
|
643
|
+
self._background_tasks.add(task)
|
|
644
|
+
task.add_done_callback(self._background_tasks.discard)
|
|
558
645
|
|
|
559
646
|
def on_sidebar_entity_selected(self, event: Sidebar.EntitySelected) -> None:
|
|
560
647
|
"""Show agent detail when user clicks an entity in the sidebar."""
|
|
@@ -566,6 +653,41 @@ class ConsoleApp(App):
|
|
|
566
653
|
# Internal helpers
|
|
567
654
|
# ------------------------------------------------------------------
|
|
568
655
|
|
|
656
|
+
async def _switch_to_channel(self, channel: str) -> None:
|
|
657
|
+
"""Switch to a channel, update UI, and auto-load recent history."""
|
|
658
|
+
if not channel:
|
|
659
|
+
return
|
|
660
|
+
# Guard against stale results from rapid switching
|
|
661
|
+
self._current_channel = channel
|
|
662
|
+
self._current_view = "chat"
|
|
663
|
+
|
|
664
|
+
sidebar: Sidebar = self.query_one(Sidebar)
|
|
665
|
+
chat: ChatPanel = self.query_one(ChatPanel)
|
|
666
|
+
sidebar.active_channel = channel
|
|
667
|
+
chat.set_channel(channel)
|
|
668
|
+
chat.clear_log()
|
|
669
|
+
|
|
670
|
+
# Re-show input if hidden (e.g., coming from overview/status view)
|
|
671
|
+
try:
|
|
672
|
+
input_widget = self.query_one(self._CHAT_INPUT_ID)
|
|
673
|
+
input_widget.display = True
|
|
674
|
+
except Exception:
|
|
675
|
+
pass
|
|
676
|
+
|
|
677
|
+
# Fetch recent history
|
|
678
|
+
entries = await self._client.history(channel, limit=20)
|
|
679
|
+
# Stale check: if user switched away during fetch, discard results
|
|
680
|
+
if self._current_channel != channel:
|
|
681
|
+
return
|
|
682
|
+
for e in entries:
|
|
683
|
+
try:
|
|
684
|
+
ts = float(e.get("timestamp", 0))
|
|
685
|
+
except (ValueError, TypeError):
|
|
686
|
+
ts = time.time()
|
|
687
|
+
chat.add_message(ts, "", e.get("nick", ""), e.get("text", ""))
|
|
688
|
+
if not entries:
|
|
689
|
+
chat.add_message(time.time(), "", "system", f"[dim]No history for {channel}[/]")
|
|
690
|
+
|
|
569
691
|
def _sync_sidebar(self) -> None:
|
|
570
692
|
"""Sync the sidebar channel list from the client's joined_channels."""
|
|
571
693
|
sidebar: Sidebar = self.query_one(Sidebar)
|
|
@@ -26,6 +26,7 @@ class CommandType(Enum):
|
|
|
26
26
|
INVITE = auto()
|
|
27
27
|
SERVER = auto()
|
|
28
28
|
QUIT = auto()
|
|
29
|
+
HELP = auto()
|
|
29
30
|
UNKNOWN = auto()
|
|
30
31
|
|
|
31
32
|
|
|
@@ -60,6 +61,7 @@ _COMMANDS: dict[str, CommandType] = {
|
|
|
60
61
|
"invite": CommandType.INVITE,
|
|
61
62
|
"server": CommandType.SERVER,
|
|
62
63
|
"quit": CommandType.QUIT,
|
|
64
|
+
"help": CommandType.HELP,
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"""Lightweight daemon IPC status queries for the console."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
import os
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def discover_agent_sockets() -> list[tuple[str, Path]]:
|
|
13
|
+
"""List culture daemon sockets in the culture runtime directory.
|
|
14
|
+
|
|
15
|
+
Returns a list of ``(nick, socket_path)`` tuples.
|
|
16
|
+
"""
|
|
17
|
+
from culture.cli.shared.constants import culture_runtime_dir
|
|
18
|
+
|
|
19
|
+
runtime_dir = Path(culture_runtime_dir())
|
|
20
|
+
results: list[tuple[str, Path]] = []
|
|
21
|
+
if not runtime_dir.is_dir():
|
|
22
|
+
return results
|
|
23
|
+
for entry in runtime_dir.iterdir():
|
|
24
|
+
if entry.name.startswith("culture-") and entry.name.endswith(".sock") and entry.is_socket():
|
|
25
|
+
nick = entry.name[len("culture-") : -len(".sock")]
|
|
26
|
+
results.append((nick, entry))
|
|
27
|
+
return results
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
async def query_agent_status(socket_path: Path) -> dict:
|
|
31
|
+
"""Query a single daemon socket for status (no LLM query).
|
|
32
|
+
|
|
33
|
+
Returns a dict with ``activity``, ``paused``, ``circuit_open``,
|
|
34
|
+
``running`` keys, or an empty dict on failure.
|
|
35
|
+
"""
|
|
36
|
+
from culture.cli.shared.ipc import ipc_request
|
|
37
|
+
|
|
38
|
+
resp = await ipc_request(str(socket_path), "status")
|
|
39
|
+
if resp is None or not resp.get("ok"):
|
|
40
|
+
return {}
|
|
41
|
+
return resp.get("data", {})
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _derive_activity(data: dict) -> str:
|
|
45
|
+
"""Derive a single activity string from daemon status fields."""
|
|
46
|
+
if data.get("circuit_open"):
|
|
47
|
+
return "circuit-open"
|
|
48
|
+
if data.get("paused"):
|
|
49
|
+
return "paused"
|
|
50
|
+
if not data.get("running"):
|
|
51
|
+
return "idle"
|
|
52
|
+
return data.get("activity", "idle")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
async def query_all_agents() -> dict[str, str]:
|
|
56
|
+
"""Query all local daemon sockets and return nick -> activity mapping."""
|
|
57
|
+
import asyncio
|
|
58
|
+
|
|
59
|
+
sockets = discover_agent_sockets()
|
|
60
|
+
if not sockets:
|
|
61
|
+
return {}
|
|
62
|
+
|
|
63
|
+
results: dict[str, str] = {}
|
|
64
|
+
|
|
65
|
+
async def _query_one(nick: str, path: Path) -> None:
|
|
66
|
+
try:
|
|
67
|
+
data = await asyncio.wait_for(query_agent_status(path), timeout=3.0)
|
|
68
|
+
if data:
|
|
69
|
+
results[nick] = _derive_activity(data)
|
|
70
|
+
except Exception:
|
|
71
|
+
logger.debug("Failed to query status for %s", nick)
|
|
72
|
+
|
|
73
|
+
await asyncio.gather(*[_query_one(nick, path) for nick, path in sockets])
|
|
74
|
+
return results
|
|
@@ -32,6 +32,7 @@ class EntityItem:
|
|
|
32
32
|
entity_type: str = "agent" # "agent" | "admin" | "human" | "bot"
|
|
33
33
|
online: bool = True
|
|
34
34
|
icon: str = ""
|
|
35
|
+
activity: str = "" # "working" | "idle" | "paused" | "circuit-open" | ""
|
|
35
36
|
|
|
36
37
|
|
|
37
38
|
# ---------------------------------------------------------------------------
|
|
@@ -46,6 +47,14 @@ _TYPE_ICON: dict[str, str] = {
|
|
|
46
47
|
"bot": "⚙",
|
|
47
48
|
}
|
|
48
49
|
|
|
50
|
+
# Activity indicators for agent status
|
|
51
|
+
_ACTIVITY_INDICATOR: dict[str, str] = {
|
|
52
|
+
"working": "[green]●[/]",
|
|
53
|
+
"idle": "[dim]○[/]",
|
|
54
|
+
"paused": "[yellow]⏸[/]",
|
|
55
|
+
"circuit-open": "[red]⚠[/]",
|
|
56
|
+
}
|
|
57
|
+
|
|
49
58
|
# Group order for entity types
|
|
50
59
|
_GROUP_ORDER = ["agent", "admin", "human", "bot"]
|
|
51
60
|
|
|
@@ -105,7 +114,12 @@ class _EntityRow(Static):
|
|
|
105
114
|
"""
|
|
106
115
|
|
|
107
116
|
def __init__(self, entity: EntityItem) -> None:
|
|
108
|
-
|
|
117
|
+
if entity.activity and entity.activity in _ACTIVITY_INDICATOR:
|
|
118
|
+
dot = _ACTIVITY_INDICATOR[entity.activity]
|
|
119
|
+
elif entity.online:
|
|
120
|
+
dot = "●"
|
|
121
|
+
else:
|
|
122
|
+
dot = "[dim]○[/]"
|
|
109
123
|
icon = entity.icon or _TYPE_ICON.get(entity.entity_type, "")
|
|
110
124
|
markup = f"{dot} {icon} {entity.nick}"
|
|
111
125
|
super().__init__(markup, markup=True)
|