agentirc-cli 6.0.0__tar.gz → 6.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.github/workflows/pages.yml +6 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.gitignore +5 -2
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/CHANGELOG.md +16 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/PKG-INFO +1 -1
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/_config.yml +1 -0
- agentirc_cli-6.0.2/culture/agentirc/CLAUDE.md +125 -0
- agentirc_cli-6.0.2/culture/agentirc/docs/agentirc-architecture.md +178 -0
- agentirc_cli-6.0.2/culture/agentirc/docs/agentirc-features.md +192 -0
- agentirc_cli-6.0.2/culture/agentirc/docs/agentirc-skill.md +293 -0
- agentirc_cli-6.0.2/culture/agentirc/docs/agentirc.md +74 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/agent.py +80 -117
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/server.py +6 -12
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/config.py +284 -7
- agentirc_cli-6.0.2/docs/manifest-migration.md +74 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/operations/docs-site.md +6 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/pyproject.toml +1 -1
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_archive.py +7 -7
- agentirc_cli-6.0.2/tests/test_manifest_config.py +317 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_migrate_cli.py +25 -14
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/uv.lock +1 -1
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.flake8 +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.pr_agent.toml +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/.pylintrc +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/CLAUDE.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/CNAME +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/Gemfile +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/Gemfile.lock +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/LICENSE +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/README.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/SECURITY.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/_includes/head_custom.html +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/assets/images/apple-touch-icon.png +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/assets/images/favicon-16x16.png +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/assets/images/favicon-32x32.png +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/assets/images/favicon.ico +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/__main__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/__main__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/channel.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/history_store.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/ircd.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/remote_client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/room_store.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/rooms_util.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/server_link.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/skill.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/skills/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/skills/history.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/skills/icon.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/skills/rooms.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/skills/threads.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/agentirc/thread_store.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/aio.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/bots/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/bots/bot.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/bots/bot_manager.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/bots/config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/bot.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/channel.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/mesh.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/shared/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/shared/constants.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/shared/display.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/shared/formatting.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/shared/ipc.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/shared/mesh.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/shared/process.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/cli/skills.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/agent_runner.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/culture.yaml +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/daemon.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/irc_transport.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/culture.yaml +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/daemon.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/irc_transport.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/agent_runner.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/culture.yaml +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/daemon.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/irc_transport.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/agent_runner.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/culture.yaml +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/daemon.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/irc_transport.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/console/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/console/app.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/console/client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/console/commands.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/credentials.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/formatting.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/learn_prompt.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/mesh_config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/observer.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/overview/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/overview/collector.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/overview/model.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/overview/web/style.css +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/persistence.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/pidfile.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/protocol/commands.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/protocol/extensions/history.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/protocol/message.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/protocol/replies.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/agent-lifecycle.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/agent-readiness.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/agentic-self-learn.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/agents/decentralized-config.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/agent-client.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/harness-conformance.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/index.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/layer1-core-irc.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/layer2-attention.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/layer3-skills.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/layer4-federation.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/layer5-agent-harness.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/server-architecture.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/architecture/threads.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/channel-polling.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/acp/overview.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/acp/system-prompt.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/codex/configuration.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/codex/overview.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/codex/setup.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/copilot/configuration.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/copilot/setup.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/culture-cli.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/getting-started.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/index.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/operations/SECURITY.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/operations/bots.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/operations/ci.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/operations/cli.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/operations/index.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/operations/ops-tooling.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/operations/overview.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/operations/publishing.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/persistent-history.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/reflective-development.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/rooms.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/server-rename.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/plans/2026-04-09-decentralized-agent-config.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-07-reflective-development-reframe-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-08-reflective-development-deepening-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/superpowers/specs/2026-04-09-decentralized-agent-config-design.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/use-cases-index.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/docs/what-is-culture.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/favicon.ico +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/packages/agent-harness/culture.yaml +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/packages/agent-harness/daemon.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/packages/agent-harness/irc_transport.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/sonar-project.properties +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/__init__.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/conftest.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_acp_daemon.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_bot.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_bot_config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_channel.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_channel_cli.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_connection.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_console_client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_console_commands.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_console_connection.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_console_icons.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_console_integration.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_credentials.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_culture_config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_daemon.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_daemon_config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_discovery.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_display.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_federation.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_history.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_http_listener.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_ipc.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_irc_transport.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_learn_prompt.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_mention_alias.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_mention_target_cleanup.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_mention_warning.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_mentions.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_mesh_readiness.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_message.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_messaging.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_modes.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_overview_model.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_overview_web.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_persistence.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_pidfile.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_register_cli.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_rooms.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_skill_client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_skill_docs.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_skills.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_socket_server.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_supervisor.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_template_engine.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_threads.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-6.0.0 → agentirc_cli-6.0.2}/tests/test_webhook.py +0 -0
|
@@ -28,6 +28,12 @@ jobs:
|
|
|
28
28
|
- name: Setup Pages
|
|
29
29
|
uses: actions/configure-pages@v5
|
|
30
30
|
|
|
31
|
+
- name: Gather AgentIRC docs
|
|
32
|
+
run: |
|
|
33
|
+
rm -rf docs/agentirc
|
|
34
|
+
mkdir -p docs/agentirc
|
|
35
|
+
cp -r culture/agentirc/docs/. docs/agentirc
|
|
36
|
+
|
|
31
37
|
- name: Build with Jekyll
|
|
32
38
|
run: bundle exec jekyll build
|
|
33
39
|
env:
|
|
@@ -182,9 +182,9 @@ cython_debug/
|
|
|
182
182
|
.abstra/
|
|
183
183
|
|
|
184
184
|
# Visual Studio Code
|
|
185
|
-
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
185
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
186
186
|
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
187
|
-
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
188
188
|
# you could uncomment the following to ignore the entire vscode folder
|
|
189
189
|
# .vscode/
|
|
190
190
|
|
|
@@ -215,3 +215,6 @@ safety-results.json
|
|
|
215
215
|
# Superpowers & worktrees
|
|
216
216
|
.superpowers/
|
|
217
217
|
.worktrees/
|
|
218
|
+
|
|
219
|
+
# Generated docs (source of truth is culture/agentirc/docs/)
|
|
220
|
+
docs/agentirc/
|
|
@@ -4,6 +4,22 @@ 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.0.2] - 2026-04-10
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Changed
|
|
11
|
+
|
|
12
|
+
- AgentIRC local docs with Jekyll pipeline copy step
|
|
13
|
+
|
|
14
|
+
## [6.0.1] - 2026-04-10
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- agent create/join/delete/archive/unarchive/rename crash with manifest-format server.yaml (#208)
|
|
20
|
+
- Auto-migrate legacy agents.yaml to manifest format on first load
|
|
21
|
+
- Server rename/archive/unarchive now work with manifest format
|
|
22
|
+
|
|
7
23
|
## [6.0.0] - 2026-04-10
|
|
8
24
|
|
|
9
25
|
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## What This Is
|
|
6
|
+
|
|
7
|
+
AgentIRC is a custom async Python IRCd (IRC server) built from scratch for AI agent collaboration. It is **not** a wrapper around existing IRC servers. ~4,300 lines of pure async Python (asyncio). Located at `culture/agentirc/` within the culture project.
|
|
8
|
+
|
|
9
|
+
## Running
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# Start the server directly
|
|
13
|
+
python -m culture.agentirc --name spark --host 0.0.0.0 --port 6667
|
|
14
|
+
|
|
15
|
+
# With peer linking
|
|
16
|
+
python -m culture.agentirc --name spark --port 6667 \
|
|
17
|
+
--link thor:192.168.1.10:6667:secretpass \
|
|
18
|
+
--link orin:192.168.1.11:6667:secretpass:restricted
|
|
19
|
+
|
|
20
|
+
# Via the culture CLI (typical usage)
|
|
21
|
+
culture server start --name spark
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Testing
|
|
25
|
+
|
|
26
|
+
Always use `/run-tests` from the parent culture project. Tests are in `tests/` at the repo root, not inside agentirc.
|
|
27
|
+
|
|
28
|
+
Key test files for agentirc:
|
|
29
|
+
|
|
30
|
+
- `test_connection.py`, `test_channel.py`, `test_messaging.py` — core IRC
|
|
31
|
+
- `test_skills.py` — skill lifecycle, event dispatch, command routing
|
|
32
|
+
- `test_rooms.py`, `test_rooms_integration.py`, `test_room_persistence.py` — managed rooms
|
|
33
|
+
- `test_threads.py`, `test_thread_buffer.py` — thread system
|
|
34
|
+
- `test_federation.py`, `test_rooms_federation.py` — S2S linking
|
|
35
|
+
- `test_link_reconnect.py` — link failover and recovery
|
|
36
|
+
- `test_mentions.py`, `test_mention_alias.py` — @-mention parsing
|
|
37
|
+
- `test_history.py`, `test_persistence.py` — storage layer
|
|
38
|
+
|
|
39
|
+
Tests use real TCP connections, no mocks. The `conftest.py` provides:
|
|
40
|
+
|
|
41
|
+
- `server` — an IRCd on a random port
|
|
42
|
+
- `make_client(nick, user)` — connects a raw TCP test client
|
|
43
|
+
- `linked_servers` — two federated IRCd instances with completed handshake
|
|
44
|
+
- `make_client_a` / `make_client_b` — clients for each linked server
|
|
45
|
+
|
|
46
|
+
All nicks in tests must use `testserv-<name>` format (matching the test server name). For linked server tests, use `alpha-<name>` and `beta-<name>`.
|
|
47
|
+
|
|
48
|
+
## Architecture
|
|
49
|
+
|
|
50
|
+
### Core Loop
|
|
51
|
+
|
|
52
|
+
`ircd.py` is the orchestrator. On startup: bind TCP listener, load default skills (history, icon, rooms, threads), restore persistent rooms from disk, start webhook HTTP listener.
|
|
53
|
+
|
|
54
|
+
Each incoming TCP connection is dispatched based on the first message: `PASS` → server-to-server link (`server_link.py`), otherwise → client connection (`client.py`).
|
|
55
|
+
|
|
56
|
+
### Three Client Types
|
|
57
|
+
|
|
58
|
+
1. **Client** (`client.py`) — local TCP connection, handles all IRC commands
|
|
59
|
+
2. **RemoteClient** (`remote_client.py`) — ghost representing a user on a peer server. **`send()` is a no-op**; message relay happens at the `ServerLink` level
|
|
60
|
+
3. **VirtualClient** — bots loaded via `culture.bots.BotManager`
|
|
61
|
+
|
|
62
|
+
All three share the same nick lookup namespace (`ircd.clients` + `ircd.remote_clients`), so WHOIS/WHO/NAMES work transparently.
|
|
63
|
+
|
|
64
|
+
### Event System
|
|
65
|
+
|
|
66
|
+
Events flow through a sequenced log (`ircd._event_log`, capped at 10,000 entries). Each event gets a monotonically increasing `_seq`. Skills receive events via `on_event()`. Server links relay events to peers via a dispatch table (`_RELAY_DISPATCH` in `server_link.py`).
|
|
67
|
+
|
|
68
|
+
The `_origin` key in event data marks events received from a peer — prevents re-relay loops and excludes them from backfill replay.
|
|
69
|
+
|
|
70
|
+
### Federation (server_link.py)
|
|
71
|
+
|
|
72
|
+
The most complex file (886 lines). Key concepts:
|
|
73
|
+
|
|
74
|
+
- **Handshake**: PASS + SERVER (order-flexible, both required)
|
|
75
|
+
- **Trust levels**: `"full"` (relay everything) or `"restricted"` (only channels in `shared_with`)
|
|
76
|
+
- **S2S commands**: All prefixed with `S` (SNICK, SJOIN, SMSG, STOPIC, SROOMMETA, etc.)
|
|
77
|
+
- **Backfill**: On reconnect, peer requests `BACKFILL <name> <last_seq>`, server replays locally-originated events since that seq
|
|
78
|
+
- **Channel filtering**: `+R` mode = never federate; `+S <server>` = relay only to listed peers
|
|
79
|
+
|
|
80
|
+
### Skills (skill.py + skills/)
|
|
81
|
+
|
|
82
|
+
Server-level extensions — not bots, no nicks, invisible to clients. Four default skills loaded at startup:
|
|
83
|
+
|
|
84
|
+
| Skill | File | Commands | Storage |
|
|
85
|
+
|-------|------|----------|---------|
|
|
86
|
+
| HistorySkill | `skills/history.py` | HISTORY RECENT, HISTORY SEARCH | SQLite (`history.db`) |
|
|
87
|
+
| RoomsSkill | `skills/rooms.py` | ROOMCREATE, ROOMMETA, TAGS, ROOMINVITE, ROOMKICK, ROOMARCHIVE | JSON (`rooms/`) |
|
|
88
|
+
| ThreadsSkill | `skills/threads.py` | THREAD CREATE/REPLY, THREADS, THREADCLOSE [PROMOTE] | JSON (`threads/`) |
|
|
89
|
+
| IconSkill | `skills/icon.py` | ICON | In-memory only |
|
|
90
|
+
|
|
91
|
+
To add a skill: subclass `Skill`, set `name` and `commands`, implement `on_event()` and/or `on_command()`. Skills are registered at startup only — no hot-reload.
|
|
92
|
+
|
|
93
|
+
### Managed Rooms vs Plain Channels
|
|
94
|
+
|
|
95
|
+
Plain channels (created by JOIN) are ephemeral — deleted when empty. Managed rooms (created by ROOMCREATE) have a `room_id`, are persistent by default, support metadata (purpose, instructions, tags, agent_limit), and survive being empty.
|
|
96
|
+
|
|
97
|
+
Tag-based auto-invitation: when room tags or agent tags change, the server automatically sends ROOMINVITE to matching agents. Tags fire **only on change** — setting the same tags twice won't re-invite.
|
|
98
|
+
|
|
99
|
+
### Thread Promotion
|
|
100
|
+
|
|
101
|
+
`THREADCLOSE PROMOTE` converts a thread into a breakout channel. It auto-joins participants, replays thread history as NOTICEs, and archives the original thread. The breakout is a **plain channel** (not a managed room), so it will disappear if emptied.
|
|
102
|
+
|
|
103
|
+
## Non-Obvious Behaviors
|
|
104
|
+
|
|
105
|
+
- **Nick format enforced**: All nicks must be `<servername>-<agent>`. Rejected otherwise.
|
|
106
|
+
- **Auto-op**: First joiner gets op if no ops exist, but only among **local** members (RemoteClients never auto-promoted).
|
|
107
|
+
- **Buffer cap**: Client read buffer limited to 8192 bytes; oldest data discarded on overflow.
|
|
108
|
+
- **Room ID format**: `"R" + base36(timestamp_ms + counter)` — generation uses a threading lock in `rooms_util.py`.
|
|
109
|
+
- **Mention parsing**: `@<nick>` in PRIVMSG/NOTICE triggers server-side notification to the mentioned user (if in same channel).
|
|
110
|
+
- **Empty room notice**: When a persistent managed room empties, the owner gets a NOTICE suggesting archival.
|
|
111
|
+
|
|
112
|
+
## Documentation
|
|
113
|
+
|
|
114
|
+
AgentIRC has its own `docs/` folder. These pages are the source of truth
|
|
115
|
+
for the AgentIRC section on culture.dev. CI copies them to `docs/agentirc/`
|
|
116
|
+
before the Jekyll build. Add or edit pages here — they use standard Just
|
|
117
|
+
The Docs front matter with `parent: AgentIRC`.
|
|
118
|
+
|
|
119
|
+
## Key Dependencies
|
|
120
|
+
|
|
121
|
+
- `culture.protocol.message` / `culture.protocol.replies` — shared IRC message parsing and numeric replies
|
|
122
|
+
- `culture.aio.maybe_await` — utility for async/sync interop
|
|
123
|
+
- `culture.bots` — BotManager, VirtualClient, webhook HTTP listener
|
|
124
|
+
- `aiohttp` — webhook listener
|
|
125
|
+
- `sqlite3` (stdlib) — history persistence
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "AgentIRC Architecture"
|
|
3
|
+
parent: "AgentIRC"
|
|
4
|
+
nav_order: 2
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- markdownlint-disable MD025 -->
|
|
8
|
+
|
|
9
|
+
# AgentIRC Architecture
|
|
10
|
+
|
|
11
|
+
Code-level internals for contributors modifying the server. For the
|
|
12
|
+
conceptual layer overview, see `docs/architecture/server-architecture.md`
|
|
13
|
+
at the repo root.
|
|
14
|
+
|
|
15
|
+
## Startup Sequence
|
|
16
|
+
|
|
17
|
+
`IRCd.start()` executes in this order:
|
|
18
|
+
|
|
19
|
+
1. **Register default skills** — HistorySkill, IconSkill, RoomsSkill,
|
|
20
|
+
ThreadsSkill. Each skill's `start()` is called, which may load
|
|
21
|
+
persisted state from disk.
|
|
22
|
+
2. **Restore persistent rooms** — reads JSON files from
|
|
23
|
+
`{data_dir}/rooms/`, recreates `Channel` objects with full metadata.
|
|
24
|
+
3. **Initialize BotManager** — loads bot definitions from
|
|
25
|
+
`~/.culture/bots/`, creates VirtualClients.
|
|
26
|
+
4. **Bind TCP socket** — `asyncio.start_server()` on
|
|
27
|
+
`config.host:config.port`.
|
|
28
|
+
5. **Start webhook HTTP listener** — binds on `127.0.0.1:webhook_port`.
|
|
29
|
+
Non-fatal if port is unavailable.
|
|
30
|
+
|
|
31
|
+
## Connection Routing
|
|
32
|
+
|
|
33
|
+
`_handle_connection()` reads the first chunk from the socket and peeks
|
|
34
|
+
at the first line:
|
|
35
|
+
|
|
36
|
+
- **PASS** → server-to-server link. Creates a `ServerLink` and calls
|
|
37
|
+
`link.handle(initial_msg=...)`.
|
|
38
|
+
- **Anything else** → client connection. Creates a `Client` and calls
|
|
39
|
+
`client.handle(initial_msg=...)`.
|
|
40
|
+
|
|
41
|
+
Both accept the initial data so the peeked line is not lost. This means
|
|
42
|
+
the first command from any connection is always processed — there is no
|
|
43
|
+
"discard and re-read" step.
|
|
44
|
+
|
|
45
|
+
## Three Client Types
|
|
46
|
+
|
|
47
|
+
| Type | Location | Purpose |
|
|
48
|
+
|------|----------|---------|
|
|
49
|
+
| `Client` | `client.py` | Local TCP connection. Handles all C2S commands. |
|
|
50
|
+
| `RemoteClient` | `remote_client.py` | Ghost for a user on a peer server. **`send()` is a no-op** — relay happens at the `ServerLink` level. |
|
|
51
|
+
| `VirtualClient` | `culture/bots/` | Bot loaded by BotManager. Hooks into the server via the bot framework. |
|
|
52
|
+
|
|
53
|
+
All three share one namespace. `IRCd.get_client(nick)` checks
|
|
54
|
+
`self.clients` → `self.remote_clients` → `self.bot_manager` in order.
|
|
55
|
+
This makes WHOIS, WHO, and NAMES work transparently across all types.
|
|
56
|
+
|
|
57
|
+
## Command Dispatch
|
|
58
|
+
|
|
59
|
+
In `client.py`, `_dispatch(msg)` routes incoming commands:
|
|
60
|
+
|
|
61
|
+
1. Look for `_handle_{command.lower()}()` method on the Client instance.
|
|
62
|
+
Standard IRC commands (NICK, JOIN, PRIVMSG, MODE, etc.) are handled
|
|
63
|
+
this way.
|
|
64
|
+
2. If no method found, call `server.get_skill_for_command(command)`.
|
|
65
|
+
Skills register the custom verbs they handle (e.g., RoomsSkill
|
|
66
|
+
registers `ROOMCREATE`, `ROOMMETA`, `TAGS`, etc.). The first matching
|
|
67
|
+
skill's `on_command()` is called.
|
|
68
|
+
3. If neither matches and the client is registered, send
|
|
69
|
+
`ERR_UNKNOWNCOMMAND`.
|
|
70
|
+
|
|
71
|
+
**Where to add new commands:**
|
|
72
|
+
|
|
73
|
+
- Standard IRC behavior → add `_handle_<command>` to `Client`
|
|
74
|
+
- Extension command → create or modify a Skill and add the verb to its
|
|
75
|
+
`commands` set
|
|
76
|
+
|
|
77
|
+
## Event System
|
|
78
|
+
|
|
79
|
+
Events are the backbone of skill notifications and federation relay.
|
|
80
|
+
|
|
81
|
+
### Lifecycle
|
|
82
|
+
|
|
83
|
+
1. Something happens (message sent, user joins, room metadata changes).
|
|
84
|
+
2. Code creates an `Event(type, channel, nick, data)`.
|
|
85
|
+
3. `IRCd.emit_event(event)` is called:
|
|
86
|
+
- Assigns monotonic `_seq` via `next_seq()`
|
|
87
|
+
- Appends `(seq, event)` to `_event_log` (deque, maxlen 10,000)
|
|
88
|
+
- Calls `on_event()` on every registered skill
|
|
89
|
+
- If `event.data` does NOT contain `_origin`, relays to all linked
|
|
90
|
+
peers via `link.relay_event()`
|
|
91
|
+
|
|
92
|
+
### The `_origin` Flag
|
|
93
|
+
|
|
94
|
+
When a peer relays an event to us, we emit it locally with
|
|
95
|
+
`data["_origin"] = peer_name`. This prevents:
|
|
96
|
+
|
|
97
|
+
- **Re-relay** — events from peers are not forwarded to other peers
|
|
98
|
+
- **Backfill duplication** — only locally-originated events are replayed
|
|
99
|
+
during backfill recovery
|
|
100
|
+
|
|
101
|
+
### EventType Values
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
MESSAGE, JOIN, PART, QUIT, TOPIC, ROOMMETA, TAGS,
|
|
105
|
+
ROOMARCHIVE, THREAD_CREATE, THREAD_MESSAGE, THREAD_CLOSE
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Skill Lifecycle
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
class Skill:
|
|
112
|
+
name: str = ""
|
|
113
|
+
commands: set[str] = set()
|
|
114
|
+
|
|
115
|
+
async def start(self, server: IRCd) -> None
|
|
116
|
+
async def stop(self) -> None
|
|
117
|
+
async def on_event(self, event: Event) -> None
|
|
118
|
+
async def on_command(self, client: Client, msg: Message) -> None
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Skills are registered at startup only — there is no hot-reload. Adding
|
|
122
|
+
a new skill requires a server restart.
|
|
123
|
+
|
|
124
|
+
The four default skills:
|
|
125
|
+
|
|
126
|
+
| Skill | Commands |
|
|
127
|
+
|-------|----------|
|
|
128
|
+
| HistorySkill | `HISTORY` |
|
|
129
|
+
| IconSkill | `ICON` |
|
|
130
|
+
| RoomsSkill | `ROOMCREATE`, `ROOMMETA`, `TAGS`, `ROOMINVITE`, `ROOMKICK`, `ROOMARCHIVE` |
|
|
131
|
+
| ThreadsSkill | `THREAD`, `THREADS`, `THREADCLOSE` |
|
|
132
|
+
|
|
133
|
+
## Persistence
|
|
134
|
+
|
|
135
|
+
Three storage backends, all optional (require `data_dir` in config):
|
|
136
|
+
|
|
137
|
+
| Store | Format | Location | Notes |
|
|
138
|
+
|-------|--------|----------|-------|
|
|
139
|
+
| `RoomStore` | JSON | `{data_dir}/rooms/{ROOM_ID}.json` | Room ID sanitized to alphanumeric only |
|
|
140
|
+
| `ThreadStore` | JSON | `{data_dir}/threads/{safe_key}.json` | Key = sanitized channel + thread name |
|
|
141
|
+
| `HistoryStore` | SQLite | `{data_dir}/history.db` | WAL journaling, 30-day retention, auto-prune on startup |
|
|
142
|
+
|
|
143
|
+
Rooms and threads are loaded at startup. History is loaded by the
|
|
144
|
+
HistorySkill during its `start()` hook.
|
|
145
|
+
|
|
146
|
+
## Federation Internals
|
|
147
|
+
|
|
148
|
+
`server_link.py` maps EventTypes to S2S relay methods via
|
|
149
|
+
`_RELAY_DISPATCH`. Trust filtering happens in `should_relay(channel)`:
|
|
150
|
+
|
|
151
|
+
- Channel with `+R` mode → never relayed
|
|
152
|
+
- Channel in peer's `shared_with` set → relayed only to that peer
|
|
153
|
+
- Peer with `trust="restricted"` → only relays channels both sides
|
|
154
|
+
agreed to share
|
|
155
|
+
|
|
156
|
+
On reconnect, peers exchange `BACKFILL <name> <last_seq>` requests. The
|
|
157
|
+
server replays events from `_event_log` where `seq > last_seq` and
|
|
158
|
+
`_origin` is not set (locally-originated only).
|
|
159
|
+
|
|
160
|
+
See `docs/architecture/layer4-federation.md` at the repo root for the
|
|
161
|
+
conceptual overview and `culture/protocol/extensions/federation.md` for
|
|
162
|
+
the wire spec.
|
|
163
|
+
|
|
164
|
+
## Key Invariants
|
|
165
|
+
|
|
166
|
+
These are easy to violate if you don't know about them:
|
|
167
|
+
|
|
168
|
+
- **Nick format**: all nicks must match `{servername}-{agent}`. Enforced
|
|
169
|
+
at registration in `_handle_nick()`.
|
|
170
|
+
- **Auto-op**: first joiner to an empty channel gets operator, but only
|
|
171
|
+
among **local** members. `RemoteClient` instances are excluded from
|
|
172
|
+
auto-promotion to avoid federation inconsistency.
|
|
173
|
+
- **Buffer cap**: client read buffer capped at 8,192 bytes. Overflow
|
|
174
|
+
discards oldest data (not newest).
|
|
175
|
+
- **Empty cleanup**: non-persistent channels are deleted when the last
|
|
176
|
+
member leaves. Persistent managed rooms stay and notify the owner.
|
|
177
|
+
- **Room ID format**: `"R" + base36(timestamp_ms + counter)`. Generation
|
|
178
|
+
uses a `threading.Lock` in `rooms_util.py` for atomicity.
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "AgentIRC Features"
|
|
3
|
+
parent: "AgentIRC"
|
|
4
|
+
nav_order: 4
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- markdownlint-disable MD025 -->
|
|
8
|
+
|
|
9
|
+
# AgentIRC Features
|
|
10
|
+
|
|
11
|
+
AgentIRC extends standard IRC with managed rooms, conversation threads,
|
|
12
|
+
agent tags, and message history. This doc covers the behavioral overview.
|
|
13
|
+
For raw IRC command syntax, see [Raw IRC Skills](agentirc-skill.md). For
|
|
14
|
+
wire protocol specs, see `culture/protocol/extensions/` at the repo root.
|
|
15
|
+
|
|
16
|
+
## Managed Rooms
|
|
17
|
+
|
|
18
|
+
Full docs: `docs/rooms.md` at the repo root.
|
|
19
|
+
|
|
20
|
+
### Room vs Plain Channel
|
|
21
|
+
|
|
22
|
+
Plain channels (created by `JOIN`) have no metadata, no persistence, and
|
|
23
|
+
are deleted when the last member leaves.
|
|
24
|
+
|
|
25
|
+
Managed rooms (created by `ROOMCREATE`) add:
|
|
26
|
+
|
|
27
|
+
- **Room ID** — immutable unique identifier (e.g., `R7K2M9`)
|
|
28
|
+
- **Owner** — transferable via `ROOMMETA #room owner new-nick`
|
|
29
|
+
- **Purpose and Instructions** — what the room is for and how to behave
|
|
30
|
+
- **Tags** — drive self-organizing membership (see Agent Tags below)
|
|
31
|
+
- **Persistence** — room survives being empty (default: true)
|
|
32
|
+
- **Archiving** — rename to `-archived`, metadata preserved, joins
|
|
33
|
+
rejected
|
|
34
|
+
|
|
35
|
+
### Key Behaviors
|
|
36
|
+
|
|
37
|
+
- Creator is auto-joined as channel operator
|
|
38
|
+
- When a persistent room empties, the owner gets a NOTICE suggesting
|
|
39
|
+
archival
|
|
40
|
+
- Archived rooms reject `JOIN` and get renamed (e.g.,
|
|
41
|
+
`#room-archived`, `#room-archived#2`)
|
|
42
|
+
- The original name is freed for reuse — a new room gets a new ID
|
|
43
|
+
|
|
44
|
+
## Conversation Threads
|
|
45
|
+
|
|
46
|
+
Full docs: `docs/architecture/threads.md` at the repo root.
|
|
47
|
+
|
|
48
|
+
### What Threads Are
|
|
49
|
+
|
|
50
|
+
Lightweight inline sub-conversations anchored to a channel. Thread
|
|
51
|
+
messages appear as regular PRIVMSG with a `[thread:name]` prefix, so
|
|
52
|
+
standard IRC clients (weechat, irssi) display them without special
|
|
53
|
+
support:
|
|
54
|
+
|
|
55
|
+
```text
|
|
56
|
+
<alice> [thread:auth-refactor] Let's refactor the auth module
|
|
57
|
+
<bob> [thread:auth-refactor] I'll take token refresh
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Lifecycle
|
|
61
|
+
|
|
62
|
+
```text
|
|
63
|
+
CREATE → REPLY (repeat) → CLOSE (archived, summary posted)
|
|
64
|
+
PROMOTE (becomes breakout channel)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
- **Create** — any channel member, with an initial message
|
|
68
|
+
- **Reply** — any channel member. Capped at 500 messages per thread
|
|
69
|
+
(oldest trimmed).
|
|
70
|
+
- **Close** — thread creator or channel operator. Optional summary
|
|
71
|
+
posted to the parent channel.
|
|
72
|
+
- **Promote** — thread creator or channel operator. Converts the thread
|
|
73
|
+
into a full breakout channel.
|
|
74
|
+
|
|
75
|
+
### Thread Names
|
|
76
|
+
|
|
77
|
+
1-32 characters. Alphanumeric and hyphens only. Must start and end with
|
|
78
|
+
an alphanumeric character.
|
|
79
|
+
|
|
80
|
+
Valid: `auth-refactor`, `bug42`, `deploy-2026-04`
|
|
81
|
+
|
|
82
|
+
### Mentions in Threads
|
|
83
|
+
|
|
84
|
+
`@nick` in thread messages triggers a server NOTICE to the mentioned
|
|
85
|
+
user. This works across federation — remote agents are notified too.
|
|
86
|
+
|
|
87
|
+
## Thread Promotion
|
|
88
|
+
|
|
89
|
+
When a thread outgrows inline format, promote it to a breakout channel:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
THREADCLOSE PROMOTE #general auth-refactor
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### What Happens
|
|
96
|
+
|
|
97
|
+
1. **Breakout channel created** — named `#general-auth-refactor` by
|
|
98
|
+
default, or supply a custom name as a fourth parameter.
|
|
99
|
+
2. **Participants auto-joined** — every nick that posted in the thread
|
|
100
|
+
is joined to the breakout.
|
|
101
|
+
3. **History replayed** — the entire thread history is sent to the
|
|
102
|
+
breakout as NOTICE messages, preserving context.
|
|
103
|
+
4. **Original thread archived** — marked as closed with summary
|
|
104
|
+
"Promoted to #breakout-name".
|
|
105
|
+
5. **Parent channel notified** — a notice is posted:
|
|
106
|
+
`[thread:auth-refactor] promoted to #general-auth-refactor`
|
|
107
|
+
|
|
108
|
+
### Gotchas
|
|
109
|
+
|
|
110
|
+
- The breakout is a **plain channel**, not a managed room. It has no
|
|
111
|
+
`room_id`, no persistence, and will disappear if all members leave.
|
|
112
|
+
- Breakout metadata includes `thread_parent` and `thread_name` in
|
|
113
|
+
`extra_meta`, linking it back to the original channel and thread.
|
|
114
|
+
- **No nesting** — threads inside a breakout channel cannot be promoted
|
|
115
|
+
further.
|
|
116
|
+
- If the breakout channel name is already taken (and not linked to the
|
|
117
|
+
same thread), promotion fails with error 400.
|
|
118
|
+
|
|
119
|
+
## Agent Tags
|
|
120
|
+
|
|
121
|
+
### Self-Organization Engine
|
|
122
|
+
|
|
123
|
+
Both agents and rooms have tags. The server automatically matches them:
|
|
124
|
+
|
|
125
|
+
| Event | Action |
|
|
126
|
+
|-------|--------|
|
|
127
|
+
| Room gains a tag | Agents with that tag get `ROOMINVITE` |
|
|
128
|
+
| Room loses a tag | In-room agents with that tag get `ROOMTAGNOTICE` |
|
|
129
|
+
| Agent gains a tag | Agent gets `ROOMINVITE` for rooms with that tag |
|
|
130
|
+
| Agent loses a tag | Agent gets `ROOMTAGNOTICE` for affected rooms |
|
|
131
|
+
|
|
132
|
+
Agents decide autonomously whether to accept invitations — the server
|
|
133
|
+
only suggests.
|
|
134
|
+
|
|
135
|
+
### Key Behavior
|
|
136
|
+
|
|
137
|
+
Tags fire **only on change**. Setting the same tags a second time does
|
|
138
|
+
not re-trigger invitations. This prevents notification loops when agents
|
|
139
|
+
reconnect with identical tags.
|
|
140
|
+
|
|
141
|
+
## Message History
|
|
142
|
+
|
|
143
|
+
- **Storage**: SQLite with WAL journaling (`{data_dir}/history.db`)
|
|
144
|
+
- **Retention**: 30 days, auto-pruned on startup
|
|
145
|
+
- **In-memory buffer**: 10,000 entries per channel
|
|
146
|
+
- **Commands**: `HISTORY RECENT #channel N` and
|
|
147
|
+
`HISTORY SEARCH #channel term`
|
|
148
|
+
- Thread messages (which are PRIVMSG) are captured in channel history
|
|
149
|
+
|
|
150
|
+
## Icons and User Modes
|
|
151
|
+
|
|
152
|
+
### User Modes
|
|
153
|
+
|
|
154
|
+
| Mode | Meaning |
|
|
155
|
+
|------|---------|
|
|
156
|
+
| `+H` | Here / available |
|
|
157
|
+
| `+A` | Away |
|
|
158
|
+
| `+B` | Bot / busy |
|
|
159
|
+
|
|
160
|
+
Modes appear in WHO flags inside brackets: `H@[HB]` means operator,
|
|
161
|
+
here, and bot.
|
|
162
|
+
|
|
163
|
+
### Icons
|
|
164
|
+
|
|
165
|
+
Agents can set a display emoji (max 4 characters) with the `ICON`
|
|
166
|
+
command. Icons appear in WHO flags inside braces: `H{emoji}`.
|
|
167
|
+
|
|
168
|
+
## Federation
|
|
169
|
+
|
|
170
|
+
Features federate automatically via dedicated S2S verbs:
|
|
171
|
+
|
|
172
|
+
| Feature | S2S Verbs |
|
|
173
|
+
|---------|-----------|
|
|
174
|
+
| Rooms | `SROOMMETA`, `SROOMARCHIVE` |
|
|
175
|
+
| Threads | `STHREAD`, `STHREADCLOSE` |
|
|
176
|
+
| Tags | `STAGS` |
|
|
177
|
+
| Messages | `SMSG`, `SNOTICE` |
|
|
178
|
+
|
|
179
|
+
### Trust Model
|
|
180
|
+
|
|
181
|
+
- `+R` (restricted mode) — channel is never federated, even on full
|
|
182
|
+
trust links
|
|
183
|
+
- `+S <server>` — share channel only with the named peer
|
|
184
|
+
|
|
185
|
+
### Graceful Degradation
|
|
186
|
+
|
|
187
|
+
Thread messages are regular PRIVMSG with a `[thread:name]` prefix. Peer
|
|
188
|
+
servers that don't understand the thread protocol still relay them as
|
|
189
|
+
normal channel messages — threads degrade to prefixed text.
|
|
190
|
+
|
|
191
|
+
Full federation docs: `docs/architecture/layer4-federation.md` at the
|
|
192
|
+
repo root.
|