agentirc-cli 4.3.7__tar.gz → 4.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/CHANGELOG.md +27 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/PKG-INFO +1 -1
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/agent.py +5 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/server.py +23 -4
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/shared/display.py +2 -1
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/shared/ipc.py +1 -1
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/agent_runner.py +23 -3
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/config.py +67 -38
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/irc_transport.py +18 -4
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/config.py +107 -74
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/irc_transport.py +18 -4
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/config.py +64 -37
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/irc_transport.py +18 -4
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/config.py +64 -37
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/irc_transport.py +18 -4
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/protocol/extensions/history.md +6 -1
- agentirc_cli-4.4.1/culture/server/history_store.py +91 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/skills/history.py +48 -1
- agentirc_cli-4.4.1/docs/persistent-history.md +61 -0
- agentirc_cli-4.4.1/packages/agent-harness/irc_transport.py +238 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/pyproject.toml +1 -1
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_acp_daemon.py +61 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_archive.py +167 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_daemon_config.py +90 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_history.py +178 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_irc_transport.py +55 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_mention_alias.py +29 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/uv.lock +1 -1
- agentirc_cli-4.3.7/packages/agent-harness/irc_transport.py +0 -219
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.claude/skills/pr-review/SKILL.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.claude/skills/run-tests/SKILL.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.flake8 +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.github/workflows/pages.yml +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.github/workflows/publish.yml +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.github/workflows/security-checks.yml +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.github/workflows/tests.yml +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.gitignore +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.markdownlint-cli2.yaml +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.pr_agent.toml +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.pre-commit-config.yaml +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/.pylintrc +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/CLAUDE.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/CNAME +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/Gemfile +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/Gemfile.lock +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/LICENSE +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/README.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/SECURITY.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/_config.yml +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/_sass/color_schemes/anthropic.scss +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/_sass/custom/custom.scss +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/__main__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/aio.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/bots/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/bots/bot.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/bots/bot_manager.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/bots/config.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/bots/http_listener.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/bots/template_engine.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/bots/virtual_client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/bot.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/channel.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/mesh.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/shared/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/shared/constants.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/shared/formatting.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/shared/mesh.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/shared/process.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/cli/skills.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/daemon.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/ipc.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/message_buffer.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/skill/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/socket_server.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/supervisor.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/acp/webhook.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/__main__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/agent_runner.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/daemon.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/ipc.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/message_buffer.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/skill/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/socket_server.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/supervisor.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/claude/webhook.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/agent_runner.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/daemon.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/ipc.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/message_buffer.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/skill/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/socket_server.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/supervisor.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/codex/webhook.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/agent_runner.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/daemon.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/ipc.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/message_buffer.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/skill/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/socket_server.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/supervisor.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/clients/copilot/webhook.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/console/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/console/app.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/console/client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/console/commands.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/console/widgets/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/console/widgets/chat.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/console/widgets/info_panel.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/console/widgets/sidebar.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/credentials.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/formatting.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/learn_prompt.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/mesh_config.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/observer.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/overview/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/overview/collector.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/overview/model.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/overview/renderer_text.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/overview/renderer_web.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/overview/web/style.css +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/persistence.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/pidfile.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/protocol/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/protocol/commands.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/protocol/extensions/federation.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/protocol/extensions/icons.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/protocol/extensions/rooms.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/protocol/extensions/tags.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/protocol/extensions/threads.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/protocol/message.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/protocol/protocol-index.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/protocol/replies.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/__main__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/channel.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/config.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/ircd.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/remote_client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/room_store.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/rooms_util.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/server_link.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/skill.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/skills/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/skills/icon.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/skills/rooms.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/skills/threads.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/server/thread_store.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/culture/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/agent-lifecycle.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/agentic-self-learn.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/agent-client.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/agent-harness-spec.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/harness-conformance.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/index.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/layer1-core-irc.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/layer2-attention.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/layer3-skills.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/layer4-federation.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/layer5-agent-harness.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/server-architecture.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/architecture/threads.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/channel-polling.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/acp/overview.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/claude/configuration.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/claude/context-management.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/claude/irc-tools.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/claude/overview.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/claude/setup.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/claude/supervisor.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/claude/webhooks.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/codex/configuration.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/codex/context-management.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/codex/irc-tools.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/codex/overview.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/codex/setup.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/codex/supervisor.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/codex/webhooks.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/copilot/configuration.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/copilot/context-management.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/copilot/irc-tools.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/copilot/overview.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/copilot/setup.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/copilot/supervisor.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/clients/copilot/webhooks.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/culture-cli.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/getting-started.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/index.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/operations/SECURITY.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/operations/bots.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/operations/ci.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/operations/cli.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/operations/docs-site.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/operations/index.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/operations/ops-tooling.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/operations/overview.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/operations/publishing.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/resources/github-copilot-sdk-instructions.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/rooms.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/server-rename.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/use-cases/01-pair-programming.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/use-cases/02-code-review-ensemble.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/use-cases/03-cross-server-delegation.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/use-cases/04-knowledge-propagation.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/use-cases/05-the-observer.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/use-cases/06-cross-server-ops.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/use-cases/07-supervisor-intervention.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/use-cases/08-apps-as-agents.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/use-cases/09-research-swarm.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/use-cases/10-agent-lifecycle.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/use-cases-index.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/docs/what-is-culture.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/packages/agent-harness/README.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/packages/agent-harness/config.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/packages/agent-harness/daemon.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/packages/agent-harness/ipc.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/packages/agent-harness/message_buffer.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/packages/agent-harness/skill/SKILL.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/packages/agent-harness/skill/irc_client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/packages/agent-harness/socket_server.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/packages/agent-harness/webhook.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/plugins/claude-code/skills/culture/SKILL.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/plugins/claude-code/skills/irc/SKILL.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/sonar-project.properties +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/__init__.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/conftest.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_agent_runner.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_bot.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_bot_config.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_bot_manager.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_bots_integration.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_channel.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_codex_daemon.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_connection.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_console_client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_console_commands.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_console_connection.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_console_icons.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_console_integration.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_copilot_daemon.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_daemon.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_daemon_ipc.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_discovery.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_federation.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_http_listener.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_integration_layer5.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_ipc.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_link_reconnect.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_mention_target_cleanup.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_mentions.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_mesh_config.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_message.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_message_buffer.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_messaging.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_modes.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_overview_cli.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_overview_collector.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_overview_model.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_overview_renderer.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_overview_web.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_persistence.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_pidfile.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_poll_loop.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_room_persistence.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_rooms.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_rooms_federation.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_rooms_integration.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_server_icon_skill.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_setup_update_cli.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_skill_client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_skills.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_socket_server.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_supervisor.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_template_engine.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_thread_buffer.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_threads.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_virtual_client.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_wait_for_port.py +0 -0
- {agentirc_cli-4.3.7 → agentirc_cli-4.4.1}/tests/test_webhook.py +0 -0
|
@@ -4,6 +4,33 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/).
|
|
6
6
|
|
|
7
|
+
## [4.4.1] - 2026-04-07
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Config save operations no longer strip backend-specific fields like acp_command (#150)
|
|
13
|
+
- Agent status detail uses cached description by default, --full for live query; IPC deadline increased to 15s (#152)
|
|
14
|
+
- DMs now activate agents — _detect_and_fire_mention handles direct messages in all backends (#153)
|
|
15
|
+
- ACP agent runner preserves HOME/XDG_CONFIG_HOME for auth tokens; warns on authMethods, fails fast on session creation failure (#154)
|
|
16
|
+
- _coerce_to_acp_agent now copies the icon field (#155)
|
|
17
|
+
- _make_backend_config passes supervisor, poll_interval, sleep_start, sleep_end to non-claude backends (#156)
|
|
18
|
+
- ACP load_config strips unknown fields, matching claude/codex/copilot pattern (#157)
|
|
19
|
+
|
|
20
|
+
## [4.4.0] - 2026-04-07
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Added
|
|
24
|
+
|
|
25
|
+
- SQLite-backed persistent channel history (survives server restarts)
|
|
26
|
+
- --data-dir CLI flag for server start (default: ~/.culture/data)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- Multi-line messages truncated to first line in send_privmsg and thread methods
|
|
32
|
+
- data_dir never wired to ServerConfig, silently disabling room/thread persistence
|
|
33
|
+
|
|
7
34
|
## [4.3.7] - 2026-04-07
|
|
8
35
|
|
|
9
36
|
|
|
@@ -455,8 +455,12 @@ def _make_backend_config(config: DaemonConfig, backend_daemon_config_cls):
|
|
|
455
455
|
"""Build a backend-specific DaemonConfig from the base config."""
|
|
456
456
|
return backend_daemon_config_cls(
|
|
457
457
|
server=config.server,
|
|
458
|
+
supervisor=config.supervisor,
|
|
458
459
|
webhooks=config.webhooks,
|
|
459
460
|
buffer_size=config.buffer_size,
|
|
461
|
+
poll_interval=config.poll_interval,
|
|
462
|
+
sleep_start=config.sleep_start,
|
|
463
|
+
sleep_end=config.sleep_end,
|
|
460
464
|
agents=config.agents,
|
|
461
465
|
)
|
|
462
466
|
|
|
@@ -484,6 +488,7 @@ def _coerce_to_acp_agent(agent: AgentConfig):
|
|
|
484
488
|
model=agent.model,
|
|
485
489
|
system_prompt=agent.system_prompt,
|
|
486
490
|
tags=agent.tags,
|
|
491
|
+
icon=agent.icon,
|
|
487
492
|
)
|
|
488
493
|
|
|
489
494
|
|
|
@@ -74,6 +74,11 @@ def register(subparsers: argparse._SubParsersAction) -> None:
|
|
|
74
74
|
action="store_true",
|
|
75
75
|
help="Run in foreground (for service managers)",
|
|
76
76
|
)
|
|
77
|
+
srv_start.add_argument(
|
|
78
|
+
"--data-dir",
|
|
79
|
+
default=os.path.expanduser("~/.culture/data"),
|
|
80
|
+
help="Data directory for persistent storage (default: ~/.culture/data)",
|
|
81
|
+
)
|
|
77
82
|
|
|
78
83
|
srv_stop = server_sub.add_parser("stop", help="Stop the IRC server daemon")
|
|
79
84
|
srv_stop.add_argument("--name", default=None, help=_SERVER_NAME_HELP)
|
|
@@ -279,7 +284,9 @@ def _run_foreground(args: argparse.Namespace, pid_name: str, links: list) -> Non
|
|
|
279
284
|
print(f" Webhook port: {args.webhook_port}")
|
|
280
285
|
_maybe_set_default_server(args.name)
|
|
281
286
|
try:
|
|
282
|
-
asyncio.run(
|
|
287
|
+
asyncio.run(
|
|
288
|
+
_run_server(args.name, args.host, args.port, links, args.webhook_port, args.data_dir)
|
|
289
|
+
)
|
|
283
290
|
finally:
|
|
284
291
|
remove_pid(pid_name)
|
|
285
292
|
|
|
@@ -369,7 +376,9 @@ def _daemonize_server(args: argparse.Namespace, pid_name: str, links: list) -> N
|
|
|
369
376
|
write_pid(pid_name, os.getpid())
|
|
370
377
|
|
|
371
378
|
try:
|
|
372
|
-
asyncio.run(
|
|
379
|
+
asyncio.run(
|
|
380
|
+
_run_server(args.name, args.host, args.port, links, args.webhook_port, args.data_dir)
|
|
381
|
+
)
|
|
373
382
|
finally:
|
|
374
383
|
remove_pid(pid_name)
|
|
375
384
|
os._exit(0)
|
|
@@ -391,14 +400,24 @@ def _server_start(args: argparse.Namespace) -> None:
|
|
|
391
400
|
|
|
392
401
|
|
|
393
402
|
async def _run_server(
|
|
394
|
-
name: str,
|
|
403
|
+
name: str,
|
|
404
|
+
host: str,
|
|
405
|
+
port: int,
|
|
406
|
+
links: list | None = None,
|
|
407
|
+
webhook_port: int = 7680,
|
|
408
|
+
data_dir: str = "",
|
|
395
409
|
) -> None:
|
|
396
410
|
"""Run the IRC server (called in the daemon child process)."""
|
|
397
411
|
from culture.server.config import ServerConfig
|
|
398
412
|
from culture.server.ircd import IRCd
|
|
399
413
|
|
|
400
414
|
config = ServerConfig(
|
|
401
|
-
name=name,
|
|
415
|
+
name=name,
|
|
416
|
+
host=host,
|
|
417
|
+
port=port,
|
|
418
|
+
webhook_port=webhook_port,
|
|
419
|
+
links=links or [],
|
|
420
|
+
data_dir=data_dir,
|
|
402
421
|
)
|
|
403
422
|
ircd = IRCd(config)
|
|
404
423
|
await ircd.start()
|
|
@@ -37,7 +37,8 @@ def print_agent_detail(agent, config_path: str, args: argparse.Namespace) -> Non
|
|
|
37
37
|
print(f" PID: {pid or '-'}")
|
|
38
38
|
|
|
39
39
|
if status == "running":
|
|
40
|
-
|
|
40
|
+
query = getattr(args, "full", False)
|
|
41
|
+
resp = asyncio.run(ipc_request(agent_socket_path(agent.nick), "status", query=query))
|
|
41
42
|
if resp and resp.get("ok"):
|
|
42
43
|
data = resp.get("data", {})
|
|
43
44
|
print(f" Activity: {data.get('description', 'nothing')}")
|
|
@@ -31,7 +31,7 @@ async def ipc_request(socket_path: str, msg_type: str, **kwargs) -> dict | None:
|
|
|
31
31
|
writer.write(encode_message(req))
|
|
32
32
|
await writer.drain()
|
|
33
33
|
loop = asyncio.get_running_loop()
|
|
34
|
-
deadline = loop.time() +
|
|
34
|
+
deadline = loop.time() + 15.0
|
|
35
35
|
while True:
|
|
36
36
|
remaining = deadline - loop.time()
|
|
37
37
|
if remaining <= 0:
|
|
@@ -70,11 +70,12 @@ class ACPAgentRunner:
|
|
|
70
70
|
"""Start the ACP agent as a subprocess and initialize a session."""
|
|
71
71
|
self._stopping = False
|
|
72
72
|
|
|
73
|
-
# Isolate
|
|
73
|
+
# Isolate data/state dirs to prevent session interference, but
|
|
74
|
+
# preserve HOME and XDG_CONFIG_HOME so the agent finds auth tokens.
|
|
74
75
|
self._isolated_home = tempfile.mkdtemp(prefix="culture-acp-")
|
|
75
76
|
isolated_env = dict(os.environ)
|
|
76
|
-
isolated_env["
|
|
77
|
-
isolated_env.
|
|
77
|
+
isolated_env["XDG_DATA_HOME"] = os.path.join(self._isolated_home, ".local", "share")
|
|
78
|
+
isolated_env["XDG_STATE_HOME"] = os.path.join(self._isolated_home, ".local", "state")
|
|
78
79
|
|
|
79
80
|
cmd_label = " ".join(self.acp_command)
|
|
80
81
|
try:
|
|
@@ -108,6 +109,18 @@ class ACPAgentRunner:
|
|
|
108
109
|
)
|
|
109
110
|
logger.info("ACP initialized (%s): %s", cmd_label, resp)
|
|
110
111
|
|
|
112
|
+
# Log available auth methods as a hint
|
|
113
|
+
init_result = resp.get("result", {})
|
|
114
|
+
auth_methods = init_result.get("authMethods", [])
|
|
115
|
+
if auth_methods:
|
|
116
|
+
descriptions = [m.get("description", m.get("id", "unknown")) for m in auth_methods]
|
|
117
|
+
logger.warning(
|
|
118
|
+
"ACP agent (%s) reports auth methods: %s. "
|
|
119
|
+
"If prompts fail, configure auth tokens.",
|
|
120
|
+
cmd_label,
|
|
121
|
+
", ".join(descriptions),
|
|
122
|
+
)
|
|
123
|
+
|
|
111
124
|
# Create a session with model selection
|
|
112
125
|
session_params = {
|
|
113
126
|
"cwd": self.directory,
|
|
@@ -120,6 +133,13 @@ class ACPAgentRunner:
|
|
|
120
133
|
logger.info("ACP session/new raw response: %s", json.dumps(resp)[:500])
|
|
121
134
|
result = resp.get("result", {})
|
|
122
135
|
self._session_id = result.get("sessionId")
|
|
136
|
+
if not self._session_id:
|
|
137
|
+
# Session creation failed — likely auth or model issue
|
|
138
|
+
error = resp.get("error", {})
|
|
139
|
+
error_msg = error.get("message", "unknown error")
|
|
140
|
+
if auth_methods:
|
|
141
|
+
error_msg += f". Auth may be required: {', '.join(descriptions)}"
|
|
142
|
+
raise RuntimeError(f"ACP agent ({cmd_label}) session creation failed: {error_msg}")
|
|
123
143
|
self._running = True
|
|
124
144
|
logger.info("ACP session started (%s): %s", cmd_label, self._session_id)
|
|
125
145
|
|
|
@@ -93,8 +93,10 @@ def load_config(path: str | Path) -> DaemonConfig:
|
|
|
93
93
|
webhooks = WebhookConfig(**raw.get("webhooks", {}))
|
|
94
94
|
|
|
95
95
|
agents = []
|
|
96
|
+
known_agent_fields = {f.name for f in AgentConfig.__dataclass_fields__.values()}
|
|
96
97
|
for agent_raw in raw.get("agents", []):
|
|
97
|
-
|
|
98
|
+
filtered = {k: v for k, v in agent_raw.items() if k in known_agent_fields}
|
|
99
|
+
agents.append(AgentConfig(**filtered))
|
|
98
100
|
|
|
99
101
|
return DaemonConfig(
|
|
100
102
|
server=server,
|
|
@@ -157,6 +159,32 @@ def save_config(path: str | Path, config: DaemonConfig) -> None:
|
|
|
157
159
|
raise
|
|
158
160
|
|
|
159
161
|
|
|
162
|
+
def _load_raw_yaml(path: str | Path) -> dict:
|
|
163
|
+
"""Load raw YAML from a config file, returning empty dict if missing."""
|
|
164
|
+
path = Path(path)
|
|
165
|
+
if not path.exists():
|
|
166
|
+
return {}
|
|
167
|
+
with open(path) as f:
|
|
168
|
+
return yaml.safe_load(f) or {}
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def _save_raw_yaml(path: str | Path, raw: dict) -> None:
|
|
172
|
+
"""Write raw YAML dict atomically."""
|
|
173
|
+
path = Path(path)
|
|
174
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
175
|
+
fd, tmp_path = tempfile.mkstemp(dir=str(path.parent), suffix=".yaml.tmp")
|
|
176
|
+
try:
|
|
177
|
+
with os.fdopen(fd, "w") as f:
|
|
178
|
+
yaml.dump(raw, f, default_flow_style=False, sort_keys=False)
|
|
179
|
+
os.replace(tmp_path, str(path))
|
|
180
|
+
except BaseException:
|
|
181
|
+
try:
|
|
182
|
+
os.unlink(tmp_path)
|
|
183
|
+
except OSError:
|
|
184
|
+
pass
|
|
185
|
+
raise
|
|
186
|
+
|
|
187
|
+
|
|
160
188
|
def add_agent_to_config(
|
|
161
189
|
path: str | Path,
|
|
162
190
|
agent: AgentConfig,
|
|
@@ -166,20 +194,21 @@ def add_agent_to_config(
|
|
|
166
194
|
|
|
167
195
|
If server_name is provided, updates config.server.name.
|
|
168
196
|
Raises ValueError if an agent with the same nick already exists.
|
|
197
|
+
Operates on raw YAML to preserve backend-specific fields.
|
|
169
198
|
"""
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if server_name is not None:
|
|
173
|
-
config.server.name = server_name
|
|
199
|
+
raw = _load_raw_yaml(path)
|
|
200
|
+
agents = raw.setdefault("agents", [])
|
|
174
201
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
if existing.nick == agent.nick:
|
|
202
|
+
for existing in agents:
|
|
203
|
+
if existing.get("nick") == agent.nick:
|
|
178
204
|
raise ValueError(f"Agent with nick {agent.nick!r} already exists in config")
|
|
179
205
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
206
|
+
if server_name is not None:
|
|
207
|
+
raw.setdefault("server", {})["name"] = server_name
|
|
208
|
+
|
|
209
|
+
agents.append(asdict(agent))
|
|
210
|
+
_save_raw_yaml(path, raw)
|
|
211
|
+
return load_config(path)
|
|
183
212
|
|
|
184
213
|
|
|
185
214
|
def rename_server(
|
|
@@ -189,23 +218,26 @@ def rename_server(
|
|
|
189
218
|
"""Rename the server and update all agent nick prefixes.
|
|
190
219
|
|
|
191
220
|
Returns (old_name, [(old_nick, new_nick), ...]).
|
|
221
|
+
Operates on raw YAML to preserve backend-specific fields.
|
|
192
222
|
"""
|
|
193
|
-
|
|
194
|
-
|
|
223
|
+
raw = _load_raw_yaml(path)
|
|
224
|
+
server = raw.get("server", {})
|
|
225
|
+
old_name = server.get("name", ServerConnConfig().name)
|
|
195
226
|
|
|
196
227
|
if old_name == new_name:
|
|
197
228
|
return old_name, []
|
|
198
229
|
|
|
199
|
-
|
|
230
|
+
agents = raw.get("agents", [])
|
|
200
231
|
prefix = f"{old_name}-"
|
|
201
232
|
plan: list[tuple[int, str, str]] = []
|
|
202
|
-
for i,
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
233
|
+
for i, agent_raw in enumerate(agents):
|
|
234
|
+
nick = agent_raw.get("nick", "")
|
|
235
|
+
if nick.startswith(prefix):
|
|
236
|
+
new_nick = f"{new_name}-{nick[len(prefix):]}"
|
|
237
|
+
plan.append((i, nick, new_nick))
|
|
206
238
|
|
|
207
239
|
planned_nicks = {new_nick for _, _, new_nick in plan}
|
|
208
|
-
existing_nicks = {a.nick for a in
|
|
240
|
+
existing_nicks = {a.get("nick", "") for a in agents} - {old for _, old, _ in plan}
|
|
209
241
|
collisions = planned_nicks & existing_nicks
|
|
210
242
|
if collisions:
|
|
211
243
|
raise ValueError(
|
|
@@ -213,14 +245,15 @@ def rename_server(
|
|
|
213
245
|
f"duplicate nick(s): {', '.join(sorted(collisions))}"
|
|
214
246
|
)
|
|
215
247
|
|
|
216
|
-
|
|
248
|
+
server["name"] = new_name
|
|
249
|
+
raw["server"] = server
|
|
217
250
|
|
|
218
251
|
renamed: list[tuple[str, str]] = []
|
|
219
252
|
for i, old_nick, new_nick in plan:
|
|
220
|
-
|
|
253
|
+
agents[i]["nick"] = new_nick
|
|
221
254
|
renamed.append((old_nick, new_nick))
|
|
222
255
|
|
|
223
|
-
|
|
256
|
+
_save_raw_yaml(path, raw)
|
|
224
257
|
return old_name, renamed
|
|
225
258
|
|
|
226
259
|
|
|
@@ -232,19 +265,19 @@ def rename_agent(
|
|
|
232
265
|
"""Rename an agent's nick in the config.
|
|
233
266
|
|
|
234
267
|
Raises ValueError if old_nick is not found or new_nick already exists.
|
|
268
|
+
Operates on raw YAML to preserve backend-specific fields.
|
|
235
269
|
"""
|
|
236
|
-
|
|
270
|
+
raw = _load_raw_yaml(path)
|
|
271
|
+
agents = raw.get("agents", [])
|
|
237
272
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
if agent.nick == new_nick:
|
|
273
|
+
for agent_raw in agents:
|
|
274
|
+
if agent_raw.get("nick") == new_nick:
|
|
241
275
|
raise ValueError(f"Agent with nick {new_nick!r} already exists in config")
|
|
242
276
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
save_config(path, config)
|
|
277
|
+
for agent_raw in agents:
|
|
278
|
+
if agent_raw.get("nick") == old_nick:
|
|
279
|
+
agent_raw["nick"] = new_nick
|
|
280
|
+
_save_raw_yaml(path, raw)
|
|
248
281
|
return
|
|
249
282
|
|
|
250
283
|
raise ValueError(f"Agent {old_nick!r} not found in config")
|
|
@@ -260,18 +293,14 @@ def remove_agent(
|
|
|
260
293
|
agents that the typed schema would strip.
|
|
261
294
|
Raises ValueError if the agent is not found.
|
|
262
295
|
"""
|
|
263
|
-
|
|
264
|
-
if not
|
|
296
|
+
raw = _load_raw_yaml(path)
|
|
297
|
+
if not raw:
|
|
265
298
|
raise ValueError(f"Agent {nick!r} not found in config")
|
|
266
299
|
|
|
267
|
-
with open(path) as f:
|
|
268
|
-
raw = yaml.safe_load(f) or {}
|
|
269
|
-
|
|
270
300
|
agents = raw.get("agents", [])
|
|
271
301
|
for i, agent_raw in enumerate(agents):
|
|
272
302
|
if agent_raw.get("nick") == nick:
|
|
273
303
|
agents.pop(i)
|
|
274
|
-
|
|
275
|
-
yaml.dump(raw, f, default_flow_style=False, sort_keys=False)
|
|
304
|
+
_save_raw_yaml(path, raw)
|
|
276
305
|
return
|
|
277
306
|
raise ValueError(f"Agent {nick!r} not found in config")
|
|
@@ -87,16 +87,26 @@ class IRCTransport:
|
|
|
87
87
|
self.connected = False
|
|
88
88
|
|
|
89
89
|
async def send_privmsg(self, target: str, text: str) -> None:
|
|
90
|
-
|
|
90
|
+
for line in text.splitlines():
|
|
91
|
+
if line:
|
|
92
|
+
await self._send_raw(f"PRIVMSG {target} :{line}")
|
|
91
93
|
|
|
92
94
|
async def send_thread_create(self, channel: str, thread_name: str, text: str) -> None:
|
|
93
|
-
|
|
95
|
+
lines = [l for l in text.splitlines() if l]
|
|
96
|
+
if not lines:
|
|
97
|
+
return
|
|
98
|
+
await self._send_raw(f"THREAD CREATE {channel} {thread_name} :{lines[0]}")
|
|
99
|
+
for line in lines[1:]:
|
|
100
|
+
await self._send_raw(f"THREAD REPLY {channel} {thread_name} :{line}")
|
|
94
101
|
|
|
95
102
|
async def send_thread_reply(self, channel: str, thread_name: str, text: str) -> None:
|
|
96
|
-
|
|
103
|
+
for line in text.splitlines():
|
|
104
|
+
if line:
|
|
105
|
+
await self._send_raw(f"THREAD REPLY {channel} {thread_name} :{line}")
|
|
97
106
|
|
|
98
107
|
async def send_thread_close(self, channel: str, thread_name: str, summary: str) -> None:
|
|
99
|
-
|
|
108
|
+
clean = " ".join(summary.splitlines()).strip()
|
|
109
|
+
await self._send_raw(f"THREADCLOSE {channel} {thread_name} :{clean}")
|
|
100
110
|
|
|
101
111
|
async def send_threads_list(self, channel: str) -> None:
|
|
102
112
|
await self._send_raw(f"THREADS {channel}")
|
|
@@ -203,6 +213,10 @@ class IRCTransport:
|
|
|
203
213
|
"""Check if the message mentions this agent and fire the callback."""
|
|
204
214
|
if not self.on_mention:
|
|
205
215
|
return
|
|
216
|
+
# DMs always activate (target is the agent's own nick)
|
|
217
|
+
if target == self.nick:
|
|
218
|
+
self.on_mention(target, sender, text)
|
|
219
|
+
return
|
|
206
220
|
short = self.nick.split("-", 1)[1] if "-" in self.nick else None
|
|
207
221
|
if re.search(rf"@{re.escape(self.nick)}\b", text) or (
|
|
208
222
|
short and re.search(rf"@{re.escape(short)}\b", text)
|