agentirc-cli 4.3.4__tar.gz → 4.3.5__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.
Files changed (315) hide show
  1. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/CHANGELOG.md +7 -0
  2. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/PKG-INFO +1 -1
  3. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/agent.py +188 -135
  4. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/bot.py +11 -5
  5. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/mesh.py +84 -65
  6. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/server.py +80 -40
  7. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/agent_runner.py +79 -67
  8. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/daemon.py +43 -36
  9. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/irc_transport.py +15 -6
  10. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/skill/irc_client.py +8 -5
  11. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/daemon.py +41 -34
  12. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/irc_transport.py +15 -6
  13. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/agent_runner.py +83 -70
  14. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/daemon.py +43 -36
  15. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/irc_transport.py +15 -6
  16. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/supervisor.py +13 -11
  17. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/agent_runner.py +14 -8
  18. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/daemon.py +43 -36
  19. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/irc_transport.py +15 -6
  20. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/skill/irc_client.py +8 -5
  21. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/observer.py +22 -9
  22. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/overview/collector.py +27 -8
  23. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/overview/renderer_web.py +100 -40
  24. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/persistence.py +130 -97
  25. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/server_link.py +92 -57
  26. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/skills/rooms.py +93 -61
  27. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/skills/threads.py +114 -97
  28. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/packages/agent-harness/daemon.py +35 -21
  29. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/pyproject.toml +1 -1
  30. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/uv.lock +1 -1
  31. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.claude/skills/pr-review/SKILL.md +0 -0
  32. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.claude/skills/run-tests/SKILL.md +0 -0
  33. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.claude/skills/run-tests/scripts/test.sh +0 -0
  34. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.flake8 +0 -0
  35. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.github/workflows/pages.yml +0 -0
  36. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.github/workflows/publish.yml +0 -0
  37. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.github/workflows/security-checks.yml +0 -0
  38. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.github/workflows/tests.yml +0 -0
  39. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.gitignore +0 -0
  40. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.markdownlint-cli2.yaml +0 -0
  41. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.pr_agent.toml +0 -0
  42. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.pre-commit-config.yaml +0 -0
  43. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/.pylintrc +0 -0
  44. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/CLAUDE.md +0 -0
  45. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/CNAME +0 -0
  46. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/Gemfile +0 -0
  47. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/Gemfile.lock +0 -0
  48. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/LICENSE +0 -0
  49. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/README.md +0 -0
  50. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/SECURITY.md +0 -0
  51. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/_config.yml +0 -0
  52. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/_sass/color_schemes/anthropic.scss +0 -0
  53. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/_sass/custom/custom.scss +0 -0
  54. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/__init__.py +0 -0
  55. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/__main__.py +0 -0
  56. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/aio.py +0 -0
  57. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/bots/__init__.py +0 -0
  58. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/bots/bot.py +0 -0
  59. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/bots/bot_manager.py +0 -0
  60. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/bots/config.py +0 -0
  61. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/bots/http_listener.py +0 -0
  62. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/bots/template_engine.py +0 -0
  63. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/bots/virtual_client.py +0 -0
  64. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/__init__.py +0 -0
  65. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/channel.py +0 -0
  66. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/shared/__init__.py +0 -0
  67. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/shared/constants.py +0 -0
  68. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/shared/display.py +0 -0
  69. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/shared/ipc.py +0 -0
  70. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/shared/mesh.py +0 -0
  71. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/shared/process.py +0 -0
  72. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/cli/skills.py +0 -0
  73. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/__init__.py +0 -0
  74. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/__init__.py +0 -0
  75. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/config.py +0 -0
  76. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/ipc.py +0 -0
  77. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/message_buffer.py +0 -0
  78. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/skill/SKILL.md +0 -0
  79. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/skill/__init__.py +0 -0
  80. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/socket_server.py +0 -0
  81. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/supervisor.py +0 -0
  82. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/acp/webhook.py +0 -0
  83. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/__init__.py +0 -0
  84. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/__main__.py +0 -0
  85. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/agent_runner.py +0 -0
  86. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/config.py +0 -0
  87. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/ipc.py +0 -0
  88. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/message_buffer.py +0 -0
  89. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/skill/SKILL.md +0 -0
  90. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/skill/__init__.py +0 -0
  91. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/skill/irc_client.py +0 -0
  92. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/socket_server.py +0 -0
  93. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/supervisor.py +0 -0
  94. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/claude/webhook.py +0 -0
  95. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/__init__.py +0 -0
  96. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/config.py +0 -0
  97. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/ipc.py +0 -0
  98. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/message_buffer.py +0 -0
  99. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/skill/SKILL.md +0 -0
  100. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/skill/__init__.py +0 -0
  101. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/skill/irc_client.py +0 -0
  102. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/socket_server.py +0 -0
  103. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/codex/webhook.py +0 -0
  104. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/__init__.py +0 -0
  105. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/config.py +0 -0
  106. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/ipc.py +0 -0
  107. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/message_buffer.py +0 -0
  108. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/skill/SKILL.md +0 -0
  109. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/skill/__init__.py +0 -0
  110. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/socket_server.py +0 -0
  111. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/supervisor.py +0 -0
  112. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/clients/copilot/webhook.py +0 -0
  113. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/console/__init__.py +0 -0
  114. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/console/app.py +0 -0
  115. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/console/client.py +0 -0
  116. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/console/commands.py +0 -0
  117. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/console/widgets/__init__.py +0 -0
  118. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/console/widgets/chat.py +0 -0
  119. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/console/widgets/info_panel.py +0 -0
  120. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/console/widgets/sidebar.py +0 -0
  121. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/credentials.py +0 -0
  122. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/learn_prompt.py +0 -0
  123. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/mesh_config.py +0 -0
  124. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/overview/__init__.py +0 -0
  125. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/overview/model.py +0 -0
  126. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/overview/renderer_text.py +0 -0
  127. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/overview/web/style.css +0 -0
  128. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/pidfile.py +0 -0
  129. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/protocol/__init__.py +0 -0
  130. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/protocol/commands.py +0 -0
  131. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/protocol/extensions/federation.md +0 -0
  132. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/protocol/extensions/history.md +0 -0
  133. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/protocol/extensions/icons.md +0 -0
  134. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/protocol/extensions/rooms.md +0 -0
  135. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/protocol/extensions/tags.md +0 -0
  136. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/protocol/extensions/threads.md +0 -0
  137. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/protocol/message.py +0 -0
  138. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/protocol/protocol-index.md +0 -0
  139. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/protocol/replies.py +0 -0
  140. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/__init__.py +0 -0
  141. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/__main__.py +0 -0
  142. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/channel.py +0 -0
  143. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/client.py +0 -0
  144. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/config.py +0 -0
  145. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/ircd.py +0 -0
  146. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/remote_client.py +0 -0
  147. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/room_store.py +0 -0
  148. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/rooms_util.py +0 -0
  149. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/skill.py +0 -0
  150. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/skills/__init__.py +0 -0
  151. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/skills/history.py +0 -0
  152. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/skills/icon.py +0 -0
  153. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/server/thread_store.py +0 -0
  154. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/culture/skills/culture/SKILL.md +0 -0
  155. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/agent-lifecycle.md +0 -0
  156. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/agentic-self-learn.md +0 -0
  157. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/agent-client.md +0 -0
  158. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/agent-harness-spec.md +0 -0
  159. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/design.md +0 -0
  160. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/harness-conformance.md +0 -0
  161. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/index.md +0 -0
  162. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/layer1-core-irc.md +0 -0
  163. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/layer2-attention.md +0 -0
  164. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/layer3-skills.md +0 -0
  165. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/layer4-federation.md +0 -0
  166. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/layer5-agent-harness.md +0 -0
  167. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/server-architecture.md +0 -0
  168. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/architecture/threads.md +0 -0
  169. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/channel-polling.md +0 -0
  170. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/acp/overview.md +0 -0
  171. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/claude/configuration.md +0 -0
  172. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/claude/context-management.md +0 -0
  173. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/claude/irc-tools.md +0 -0
  174. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/claude/overview.md +0 -0
  175. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/claude/setup.md +0 -0
  176. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/claude/supervisor.md +0 -0
  177. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/claude/webhooks.md +0 -0
  178. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/codex/configuration.md +0 -0
  179. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/codex/context-management.md +0 -0
  180. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/codex/irc-tools.md +0 -0
  181. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/codex/overview.md +0 -0
  182. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/codex/setup.md +0 -0
  183. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/codex/supervisor.md +0 -0
  184. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/codex/webhooks.md +0 -0
  185. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/copilot/configuration.md +0 -0
  186. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/copilot/context-management.md +0 -0
  187. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/copilot/irc-tools.md +0 -0
  188. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/copilot/overview.md +0 -0
  189. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/copilot/setup.md +0 -0
  190. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/copilot/supervisor.md +0 -0
  191. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/clients/copilot/webhooks.md +0 -0
  192. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/culture-cli.md +0 -0
  193. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/getting-started.md +0 -0
  194. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/index.md +0 -0
  195. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/operations/SECURITY.md +0 -0
  196. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/operations/bots.md +0 -0
  197. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/operations/ci.md +0 -0
  198. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/operations/cli.md +0 -0
  199. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/operations/docs-site.md +0 -0
  200. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/operations/index.md +0 -0
  201. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/operations/ops-tooling.md +0 -0
  202. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/operations/overview.md +0 -0
  203. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/operations/publishing.md +0 -0
  204. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/resources/github-copilot-sdk-instructions.md +0 -0
  205. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/rooms.md +0 -0
  206. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/server-rename.md +0 -0
  207. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
  208. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
  209. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
  210. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
  211. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
  212. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
  213. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
  214. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
  215. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
  216. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
  217. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
  218. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
  219. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
  220. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
  221. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
  222. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
  223. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
  224. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
  225. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
  226. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
  227. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
  228. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
  229. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/use-cases/01-pair-programming.md +0 -0
  230. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/use-cases/02-code-review-ensemble.md +0 -0
  231. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/use-cases/03-cross-server-delegation.md +0 -0
  232. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/use-cases/04-knowledge-propagation.md +0 -0
  233. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/use-cases/05-the-observer.md +0 -0
  234. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/use-cases/06-cross-server-ops.md +0 -0
  235. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/use-cases/07-supervisor-intervention.md +0 -0
  236. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/use-cases/08-apps-as-agents.md +0 -0
  237. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/use-cases/09-research-swarm.md +0 -0
  238. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/use-cases/10-agent-lifecycle.md +0 -0
  239. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/use-cases-index.md +0 -0
  240. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/docs/what-is-culture.md +0 -0
  241. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/packages/agent-harness/README.md +0 -0
  242. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/packages/agent-harness/config.py +0 -0
  243. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/packages/agent-harness/ipc.py +0 -0
  244. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/packages/agent-harness/irc_transport.py +0 -0
  245. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/packages/agent-harness/message_buffer.py +0 -0
  246. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/packages/agent-harness/skill/SKILL.md +0 -0
  247. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/packages/agent-harness/skill/irc_client.py +0 -0
  248. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/packages/agent-harness/socket_server.py +0 -0
  249. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/packages/agent-harness/webhook.py +0 -0
  250. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
  251. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/plugins/claude-code/skills/culture/SKILL.md +0 -0
  252. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/plugins/claude-code/skills/irc/SKILL.md +0 -0
  253. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
  254. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/sonar-project.properties +0 -0
  255. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/__init__.py +0 -0
  256. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/conftest.py +0 -0
  257. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_acp_daemon.py +0 -0
  258. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_agent_runner.py +0 -0
  259. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_archive.py +0 -0
  260. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_bot.py +0 -0
  261. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_bot_config.py +0 -0
  262. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_bot_manager.py +0 -0
  263. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_bots_integration.py +0 -0
  264. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_channel.py +0 -0
  265. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_codex_daemon.py +0 -0
  266. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_connection.py +0 -0
  267. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_console_client.py +0 -0
  268. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_console_commands.py +0 -0
  269. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_console_connection.py +0 -0
  270. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_console_icons.py +0 -0
  271. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_console_integration.py +0 -0
  272. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_copilot_daemon.py +0 -0
  273. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_daemon.py +0 -0
  274. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_daemon_config.py +0 -0
  275. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_daemon_ipc.py +0 -0
  276. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_discovery.py +0 -0
  277. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_federation.py +0 -0
  278. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_history.py +0 -0
  279. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_http_listener.py +0 -0
  280. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_integration_layer5.py +0 -0
  281. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_ipc.py +0 -0
  282. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_irc_transport.py +0 -0
  283. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_link_reconnect.py +0 -0
  284. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_mention_alias.py +0 -0
  285. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_mention_target_cleanup.py +0 -0
  286. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_mentions.py +0 -0
  287. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_mesh_config.py +0 -0
  288. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_message.py +0 -0
  289. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_message_buffer.py +0 -0
  290. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_messaging.py +0 -0
  291. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_modes.py +0 -0
  292. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_overview_cli.py +0 -0
  293. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_overview_collector.py +0 -0
  294. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_overview_model.py +0 -0
  295. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_overview_renderer.py +0 -0
  296. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_overview_web.py +0 -0
  297. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_persistence.py +0 -0
  298. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_pidfile.py +0 -0
  299. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_poll_loop.py +0 -0
  300. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_room_persistence.py +0 -0
  301. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_rooms.py +0 -0
  302. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_rooms_federation.py +0 -0
  303. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_rooms_integration.py +0 -0
  304. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_server_icon_skill.py +0 -0
  305. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_setup_update_cli.py +0 -0
  306. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_skill_client.py +0 -0
  307. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_skills.py +0 -0
  308. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_socket_server.py +0 -0
  309. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_supervisor.py +0 -0
  310. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_template_engine.py +0 -0
  311. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_thread_buffer.py +0 -0
  312. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_threads.py +0 -0
  313. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_virtual_client.py +0 -0
  314. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_wait_for_port.py +0 -0
  315. {agentirc_cli-4.3.4 → agentirc_cli-4.3.5}/tests/test_webhook.py +0 -0
@@ -4,6 +4,13 @@ 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.3.5] - 2026-04-07
8
+
9
+
10
+ ### Changed
11
+
12
+ - Reduce cognitive complexity in 30+ functions across backend clients, server code, CLI submodules, and standalone files to meet SonarCloud threshold (≤15)
13
+
7
14
  ## [4.3.4] - 2026-04-07
8
15
 
9
16
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentirc-cli
3
- Version: 4.3.4
3
+ Version: 4.3.5
4
4
  Summary: Legacy alias for culture — install culture instead
5
5
  Project-URL: Homepage, https://github.com/OriNachum/culture
6
6
  Author: Ori Nachum
@@ -201,59 +201,83 @@ def dispatch(args: argparse.Namespace) -> None:
201
201
  # -----------------------------------------------------------------------
202
202
 
203
203
 
204
- def _create_agent_config(args: argparse.Namespace, full_nick: str) -> AgentConfig:
205
- """Build a backend-specific AgentConfig from CLI args."""
206
- if args.agent == "codex":
207
- from culture.clients.codex.config import AgentConfig as CodexAgentConfig
208
-
209
- return CodexAgentConfig(
210
- nick=full_nick,
211
- agent="codex",
212
- directory=os.getcwd(),
213
- channels=[DEFAULT_CHANNEL],
214
- )
215
- if args.agent == "copilot":
216
- from culture.clients.copilot.config import AgentConfig as CopilotAgentConfig
217
-
218
- return CopilotAgentConfig(
219
- nick=full_nick,
220
- agent="copilot",
221
- directory=os.getcwd(),
222
- channels=[DEFAULT_CHANNEL],
223
- )
224
- if args.agent == "acp":
225
- import json as _json
204
+ def _create_codex_config(full_nick: str) -> AgentConfig:
205
+ """Build a CodexAgentConfig."""
206
+ from culture.clients.codex.config import AgentConfig as CodexAgentConfig
207
+
208
+ return CodexAgentConfig(
209
+ nick=full_nick,
210
+ agent="codex",
211
+ directory=os.getcwd(),
212
+ channels=[DEFAULT_CHANNEL],
213
+ )
226
214
 
227
- from culture.clients.acp.config import AgentConfig as ACPAgentConfig
228
215
 
229
- acp_cmd = ["opencode", "acp"]
230
- if args.acp_command:
231
- try:
232
- acp_cmd = _json.loads(args.acp_command)
233
- except _json.JSONDecodeError:
234
- acp_cmd = args.acp_command.split()
235
- if (
236
- not isinstance(acp_cmd, list)
237
- or not acp_cmd
238
- or not all(isinstance(s, str) for s in acp_cmd)
239
- ):
240
- print("Error: --acp-command must be a non-empty list of strings", file=sys.stderr)
241
- sys.exit(1)
242
- return ACPAgentConfig(
243
- nick=full_nick,
244
- agent="acp",
245
- acp_command=acp_cmd,
246
- directory=os.getcwd(),
247
- channels=[DEFAULT_CHANNEL],
248
- )
216
+ def _create_copilot_config(full_nick: str) -> AgentConfig:
217
+ """Build a CopilotAgentConfig."""
218
+ from culture.clients.copilot.config import AgentConfig as CopilotAgentConfig
219
+
220
+ return CopilotAgentConfig(
221
+ nick=full_nick,
222
+ agent="copilot",
223
+ directory=os.getcwd(),
224
+ channels=[DEFAULT_CHANNEL],
225
+ )
226
+
227
+
228
+ def _parse_acp_command(raw_command: str | None) -> list[str]:
229
+ """Parse and validate the ACP command from CLI args."""
230
+ import json as _json
231
+
232
+ acp_cmd = ["opencode", "acp"]
233
+ if raw_command:
234
+ try:
235
+ acp_cmd = _json.loads(raw_command)
236
+ except _json.JSONDecodeError:
237
+ acp_cmd = raw_command.split()
238
+ if not isinstance(acp_cmd, list) or not acp_cmd or not all(isinstance(s, str) for s in acp_cmd):
239
+ print("Error: --acp-command must be a non-empty list of strings", file=sys.stderr)
240
+ sys.exit(1)
241
+ return acp_cmd
242
+
243
+
244
+ def _create_acp_config(full_nick: str, args: argparse.Namespace) -> AgentConfig:
245
+ """Build an ACPAgentConfig."""
246
+ from culture.clients.acp.config import AgentConfig as ACPAgentConfig
247
+
248
+ acp_cmd = _parse_acp_command(args.acp_command)
249
+ return ACPAgentConfig(
250
+ nick=full_nick,
251
+ agent="acp",
252
+ acp_command=acp_cmd,
253
+ directory=os.getcwd(),
254
+ channels=[DEFAULT_CHANNEL],
255
+ )
256
+
257
+
258
+ def _create_default_config(full_nick: str, backend: str) -> AgentConfig:
259
+ """Build a default (claude) AgentConfig."""
249
260
  return AgentConfig(
250
261
  nick=full_nick,
251
- agent=args.agent,
262
+ agent=backend,
252
263
  directory=os.getcwd(),
253
264
  channels=[DEFAULT_CHANNEL],
254
265
  )
255
266
 
256
267
 
268
+ def _create_agent_config(args: argparse.Namespace, full_nick: str) -> AgentConfig:
269
+ """Build a backend-specific AgentConfig from CLI args."""
270
+ factories = {
271
+ "codex": lambda: _create_codex_config(full_nick),
272
+ "copilot": lambda: _create_copilot_config(full_nick),
273
+ "acp": lambda: _create_acp_config(full_nick, args),
274
+ }
275
+ factory = factories.get(args.agent)
276
+ if factory:
277
+ return factory()
278
+ return _create_default_config(full_nick, args.agent)
279
+
280
+
257
281
  def _cmd_create(args: argparse.Namespace) -> None:
258
282
  config = load_config_or_default(args.config)
259
283
 
@@ -387,6 +411,32 @@ def _probe_server_connection(host: str, port: int, server_name: str) -> None:
387
411
  sys.exit(1)
388
412
 
389
413
 
414
+ def _start_foreground(config: DaemonConfig, agents: list[AgentConfig]) -> None:
415
+ """Start a single agent in the foreground."""
416
+ if len(agents) != 1:
417
+ print("--foreground requires a single agent nick, not --all", file=sys.stderr)
418
+ sys.exit(1)
419
+ agent = agents[0]
420
+ print(f"Starting agent {agent.nick} in foreground...")
421
+ asyncio.run(_run_single_agent(config, agent))
422
+
423
+
424
+ def _start_background(config: DaemonConfig, agents: list[AgentConfig]) -> None:
425
+ """Start agents in background mode (fork on Unix, single on Windows)."""
426
+ if sys.platform == "win32":
427
+ if len(agents) != 1:
428
+ print(
429
+ "Multi-agent daemon mode not supported on Windows. Start agents individually.",
430
+ file=sys.stderr,
431
+ )
432
+ sys.exit(1)
433
+ agent = agents[0]
434
+ print(f"Starting agent {agent.nick}...")
435
+ asyncio.run(_run_single_agent(config, agent))
436
+ else:
437
+ _run_multi_agents(config, agents)
438
+
439
+
390
440
  def _cmd_start(args: argparse.Namespace) -> None:
391
441
  config = load_config(args.config)
392
442
 
@@ -395,86 +445,88 @@ def _cmd_start(args: argparse.Namespace) -> None:
395
445
  server_name = config.server.name
396
446
  _probe_server_connection(config.server.host, config.server.port, server_name)
397
447
 
398
- foreground = getattr(args, "foreground", False)
399
-
400
- if foreground:
401
- if len(agents) != 1:
402
- print("--foreground requires a single agent nick, not --all", file=sys.stderr)
403
- sys.exit(1)
404
- agent = agents[0]
405
- print(f"Starting agent {agent.nick} in foreground...")
406
- asyncio.run(_run_single_agent(config, agent))
448
+ if getattr(args, "foreground", False):
449
+ _start_foreground(config, agents)
407
450
  else:
408
- if sys.platform == "win32":
409
- if len(agents) == 1:
410
- agent = agents[0]
411
- print(f"Starting agent {agent.nick}...")
412
- asyncio.run(_run_single_agent(config, agent))
413
- else:
414
- print(
415
- "Multi-agent daemon mode not supported on Windows. Start agents individually.",
416
- file=sys.stderr,
417
- )
418
- sys.exit(1)
419
- else:
420
- _run_multi_agents(config, agents)
451
+ _start_background(config, agents)
452
+
453
+
454
+ def _make_backend_config(config: DaemonConfig, backend_daemon_config_cls):
455
+ """Build a backend-specific DaemonConfig from the base config."""
456
+ return backend_daemon_config_cls(
457
+ server=config.server,
458
+ webhooks=config.webhooks,
459
+ buffer_size=config.buffer_size,
460
+ agents=config.agents,
461
+ )
462
+
463
+
464
+ def _create_codex_daemon(config: DaemonConfig, agent: AgentConfig):
465
+ """Create a Codex backend daemon."""
466
+ from culture.clients.codex.config import DaemonConfig as CodexDaemonConfig
467
+ from culture.clients.codex.daemon import CodexDaemon
468
+
469
+ return CodexDaemon(_make_backend_config(config, CodexDaemonConfig), agent)
470
+
471
+
472
+ def _coerce_to_acp_agent(agent: AgentConfig):
473
+ """Ensure agent is an ACPAgentConfig, converting if necessary."""
474
+ from culture.clients.acp.config import AgentConfig as ACPAgentConfig
475
+
476
+ if isinstance(agent, ACPAgentConfig):
477
+ return agent
478
+ return ACPAgentConfig(
479
+ nick=agent.nick,
480
+ agent="acp",
481
+ acp_command=getattr(agent, "acp_command", None) or ["opencode", "acp"],
482
+ directory=agent.directory,
483
+ channels=agent.channels,
484
+ model=agent.model,
485
+ system_prompt=agent.system_prompt,
486
+ tags=agent.tags,
487
+ )
488
+
489
+
490
+ def _create_acp_daemon(config: DaemonConfig, agent: AgentConfig):
491
+ """Create an ACP backend daemon."""
492
+ from culture.clients.acp.config import DaemonConfig as ACPDaemonConfig
493
+ from culture.clients.acp.daemon import ACPDaemon
494
+
495
+ return ACPDaemon(
496
+ _make_backend_config(config, ACPDaemonConfig),
497
+ _coerce_to_acp_agent(agent),
498
+ )
499
+
500
+
501
+ def _create_copilot_daemon(config: DaemonConfig, agent: AgentConfig):
502
+ """Create a Copilot backend daemon."""
503
+ from culture.clients.copilot.config import DaemonConfig as CopilotDaemonConfig
504
+ from culture.clients.copilot.daemon import CopilotDaemon
505
+
506
+ return CopilotDaemon(_make_backend_config(config, CopilotDaemonConfig), agent)
507
+
508
+
509
+ def _create_claude_daemon(config: DaemonConfig, agent: AgentConfig):
510
+ """Create the default Claude backend daemon."""
511
+ from culture.clients.claude.daemon import AgentDaemon
512
+
513
+ return AgentDaemon(config, agent)
514
+
515
+
516
+ _BACKEND_DAEMON_FACTORIES = {
517
+ "codex": _create_codex_daemon,
518
+ "acp": _create_acp_daemon,
519
+ "opencode": _create_acp_daemon,
520
+ "copilot": _create_copilot_daemon,
521
+ }
421
522
 
422
523
 
423
524
  async def _run_single_agent(config: DaemonConfig, agent: AgentConfig) -> None:
424
525
  """Run a single agent daemon in the foreground."""
425
526
  backend = getattr(agent, "agent", "claude")
426
527
 
427
- if backend == "codex":
428
- from culture.clients.codex.config import DaemonConfig as CodexDaemonConfig
429
- from culture.clients.codex.daemon import CodexDaemon
430
-
431
- codex_config = CodexDaemonConfig(
432
- server=config.server,
433
- webhooks=config.webhooks,
434
- buffer_size=config.buffer_size,
435
- agents=config.agents,
436
- )
437
- daemon = CodexDaemon(codex_config, agent)
438
- elif backend in ("acp", "opencode"):
439
- from culture.clients.acp.config import AgentConfig as ACPAgentConfig
440
- from culture.clients.acp.config import DaemonConfig as ACPDaemonConfig
441
- from culture.clients.acp.daemon import ACPDaemon
442
-
443
- acp_config = ACPDaemonConfig(
444
- server=config.server,
445
- webhooks=config.webhooks,
446
- buffer_size=config.buffer_size,
447
- agents=config.agents,
448
- )
449
- if not isinstance(agent, ACPAgentConfig):
450
- acp_agent = ACPAgentConfig(
451
- nick=agent.nick,
452
- agent="acp",
453
- acp_command=getattr(agent, "acp_command", None) or ["opencode", "acp"],
454
- directory=agent.directory,
455
- channels=agent.channels,
456
- model=agent.model,
457
- system_prompt=agent.system_prompt,
458
- tags=agent.tags,
459
- )
460
- else:
461
- acp_agent = agent
462
- daemon = ACPDaemon(acp_config, acp_agent)
463
- elif backend == "copilot":
464
- from culture.clients.copilot.config import DaemonConfig as CopilotDaemonConfig
465
- from culture.clients.copilot.daemon import CopilotDaemon
466
-
467
- copilot_config = CopilotDaemonConfig(
468
- server=config.server,
469
- webhooks=config.webhooks,
470
- buffer_size=config.buffer_size,
471
- agents=config.agents,
472
- )
473
- daemon = CopilotDaemon(copilot_config, agent)
474
- else:
475
- from culture.clients.claude.daemon import AgentDaemon
476
-
477
- daemon = AgentDaemon(config, agent)
528
+ factory = _BACKEND_DAEMON_FACTORIES.get(backend, _create_claude_daemon)
529
+ daemon = factory(config, agent)
478
530
 
479
531
  stop_event = asyncio.Event()
480
532
  daemon.set_stop_event(stop_event)
@@ -524,30 +576,31 @@ def _run_multi_agents(config: DaemonConfig, agents: list[AgentConfig]) -> None:
524
576
  print(f"Started {agent.nick} (PID {pid})")
525
577
 
526
578
 
527
- def _cmd_stop(args: argparse.Namespace) -> None:
528
- config = load_config_or_default(args.config)
529
-
579
+ def _resolve_agents_to_stop(config, args) -> list:
580
+ """Resolve which agents should be stopped, or exit with an error."""
530
581
  if args.all:
531
- agents = config.agents
532
- elif args.nick:
582
+ return config.agents
583
+ if args.nick:
533
584
  agent = config.get_agent(args.nick)
534
585
  if not agent:
535
586
  print(f"Agent '{args.nick}' not found in config", file=sys.stderr)
536
587
  sys.exit(1)
537
- agents = [agent]
538
- else:
539
- if len(config.agents) == 1:
540
- agents = config.agents
541
- elif len(config.agents) == 0:
542
- print(NO_AGENTS_MSG, file=sys.stderr)
543
- sys.exit(1)
544
- else:
545
- print(
546
- "Multiple agents configured. Specify a nick or use --all.",
547
- file=sys.stderr,
548
- )
549
- sys.exit(1)
588
+ return [agent]
589
+ if len(config.agents) == 1:
590
+ return config.agents
591
+ if len(config.agents) == 0:
592
+ print(NO_AGENTS_MSG, file=sys.stderr)
593
+ sys.exit(1)
594
+ print(
595
+ "Multiple agents configured. Specify a nick or use --all.",
596
+ file=sys.stderr,
597
+ )
598
+ sys.exit(1)
550
599
 
600
+
601
+ def _cmd_stop(args: argparse.Namespace) -> None:
602
+ config = load_config_or_default(args.config)
603
+ agents = _resolve_agents_to_stop(config, args)
551
604
  for agent in agents:
552
605
  stop_agent(agent.nick)
553
606
 
@@ -152,6 +152,15 @@ def _bot_stop(args: argparse.Namespace) -> None:
152
152
  print("(Live reload via IPC will be available in a future release.)")
153
153
 
154
154
 
155
+ def _should_include_bot(bot_config, owner: str | None, show_archived: bool) -> bool:
156
+ """Return True if the bot should be included in the listing."""
157
+ if owner and bot_config.owner != owner:
158
+ return False
159
+ if not show_archived and bot_config.archived:
160
+ return False
161
+ return True
162
+
163
+
155
164
  def _load_and_filter_bots(args) -> list:
156
165
  """Load bot configs, filtering by owner and archived status."""
157
166
  from culture.bots.config import BOTS_DIR, load_bot_config
@@ -168,11 +177,8 @@ def _load_and_filter_bots(args) -> list:
168
177
  config = load_bot_config(yaml_path)
169
178
  except Exception:
170
179
  continue
171
- if args.owner and config.owner != args.owner:
172
- continue
173
- if not show_all and config.archived:
174
- continue
175
- bots.append(config)
180
+ if _should_include_bot(config, args.owner, show_all):
181
+ bots.append(config)
176
182
  return bots
177
183
 
178
184
 
@@ -124,36 +124,16 @@ def dispatch(args: argparse.Namespace) -> None:
124
124
  # -----------------------------------------------------------------------
125
125
 
126
126
 
127
- def _cmd_overview(args: argparse.Namespace) -> None:
128
- """Show mesh overview."""
127
+ def _collect_mesh_data(host: str, port: int, server_name: str, message_limit: int):
128
+ """Collect mesh state, exiting with an error message on connection failure."""
129
129
  from culture.overview.collector import collect_mesh_state
130
- from culture.overview.renderer_text import render_text
131
-
132
- config = load_config_or_default(args.config)
133
- message_limit = max(1, min(args.messages, 20))
134
- refresh_interval = max(1, args.refresh)
135
-
136
- if args.serve:
137
- from culture.overview.renderer_web import serve_web
138
130
 
139
- serve_web(
140
- host=config.server.host,
141
- port=config.server.port,
142
- server_name=config.server.name,
143
- room_filter=args.room,
144
- agent_filter=args.agent,
145
- message_limit=message_limit,
146
- refresh_interval=refresh_interval,
147
- )
148
- return
149
-
150
- host, port = config.server.host, config.server.port
151
131
  try:
152
- mesh = asyncio.run(
132
+ return asyncio.run(
153
133
  collect_mesh_state(
154
134
  host=host,
155
135
  port=port,
156
- server_name=config.server.name,
136
+ server_name=server_name,
157
137
  message_limit=message_limit,
158
138
  )
159
139
  )
@@ -165,13 +145,40 @@ def _cmd_overview(args: argparse.Namespace) -> None:
165
145
  sys.exit(1)
166
146
  except TimeoutError:
167
147
  print(
168
- f"Error: server at {host}:{port} not responding" " — it may still be starting up",
148
+ f"Error: server at {host}:{port} not responding — it may still be starting up",
169
149
  file=sys.stderr,
170
150
  )
171
151
  sys.exit(1)
172
152
  except OSError as exc:
173
153
  print(f"Error: {exc}", file=sys.stderr)
174
154
  sys.exit(1)
155
+
156
+
157
+ def _cmd_overview(args: argparse.Namespace) -> None:
158
+ """Show mesh overview."""
159
+ from culture.overview.renderer_text import render_text
160
+
161
+ config = load_config_or_default(args.config)
162
+ message_limit = max(1, min(args.messages, 20))
163
+ refresh_interval = max(1, args.refresh)
164
+
165
+ if args.serve:
166
+ from culture.overview.renderer_web import serve_web
167
+
168
+ serve_web(
169
+ host=config.server.host,
170
+ port=config.server.port,
171
+ server_name=config.server.name,
172
+ room_filter=args.room,
173
+ agent_filter=args.agent,
174
+ message_limit=message_limit,
175
+ refresh_interval=refresh_interval,
176
+ )
177
+ return
178
+
179
+ mesh = _collect_mesh_data(
180
+ config.server.host, config.server.port, config.server.name, message_limit
181
+ )
175
182
  output = render_text(
176
183
  mesh,
177
184
  room_filter=args.room,
@@ -466,6 +473,32 @@ def _wait_for_server_port(port: int, retries: int = 50, interval: float = 0.1) -
466
473
  time.sleep(interval)
467
474
 
468
475
 
476
+ def _dry_run_restart(mesh, server_name: str) -> None:
477
+ """Print what a restart would do without executing."""
478
+ for agent in mesh.agents:
479
+ print(f"[dry-run] Would stop agent {server_name}-{agent.nick}")
480
+ print(f"[dry-run] Would stop server {server_name}")
481
+ print("[dry-run] Would regenerate auto-start entries")
482
+ print(f"[dry-run] Would start server {server_name}")
483
+ for agent in mesh.agents:
484
+ print(f"[dry-run] Would start agent {server_name}-{agent.nick}")
485
+
486
+
487
+ def _restart_single_service(svc_name: str, fallback_cmd: list[str], restart_service_fn) -> None:
488
+ """Restart a service, falling back to a CLI command if no service file exists."""
489
+ print(f" Restarting {svc_name}...")
490
+ if restart_service_fn(svc_name):
491
+ return
492
+ if sys.platform == "win32":
493
+ print(
494
+ " No service file found. Run 'culture mesh setup' to install services; starting via CLI...",
495
+ file=sys.stderr,
496
+ )
497
+ else:
498
+ print(" No service file found, starting via CLI...")
499
+ subprocess.run(fallback_cmd, check=False)
500
+
501
+
469
502
  def _restart_mesh_services(
470
503
  mesh, server_name: str, culture_bin: str, config_path: str, dry_run: bool
471
504
  ) -> None:
@@ -473,13 +506,7 @@ def _restart_mesh_services(
473
506
  print(f"Restarting mesh node '{server_name}'...")
474
507
 
475
508
  if dry_run:
476
- for agent in mesh.agents:
477
- print(f"[dry-run] Would stop agent {server_name}-{agent.nick}")
478
- print(f"[dry-run] Would stop server {server_name}")
479
- print("[dry-run] Would regenerate auto-start entries")
480
- print(f"[dry-run] Would start server {server_name}")
481
- for agent in mesh.agents:
482
- print(f"[dry-run] Would start agent {server_name}-{agent.nick}")
509
+ _dry_run_restart(mesh, server_name)
483
510
  return
484
511
 
485
512
  for agent in mesh.agents:
@@ -511,45 +538,37 @@ def _restart_mesh_services(
511
538
  install_service(f"culture-agent-{full_nick}", agent_cmd, f"culture agent {full_nick}")
512
539
 
513
540
  server_svc = f"culture-server-{server_name}"
514
- print(f" Restarting {server_svc}...")
515
- if not restart_service(server_svc):
516
- if sys.platform == "win32":
517
- print(
518
- " No service file found. Run 'culture mesh setup' to install services.",
519
- file=sys.stderr,
520
- )
521
- else:
522
- print(" No service file found, starting via CLI...")
523
- subprocess.run(
524
- [
525
- culture_bin,
526
- "server",
527
- "start",
528
- "--name",
529
- server_name,
530
- "--host",
531
- mesh.server.host,
532
- "--port",
533
- str(mesh.server.port),
534
- "--mesh-config",
535
- config_path,
536
- ],
537
- check=False,
538
- )
541
+ server_fallback = [
542
+ culture_bin,
543
+ "server",
544
+ "start",
545
+ "--name",
546
+ server_name,
547
+ "--host",
548
+ mesh.server.host,
549
+ "--port",
550
+ str(mesh.server.port),
551
+ "--mesh-config",
552
+ config_path,
553
+ ]
554
+ _restart_single_service(server_svc, server_fallback, restart_service)
539
555
 
540
556
  _wait_for_server_port(mesh.server.port)
541
557
 
542
558
  for agent in mesh.agents:
543
559
  full_nick = f"{server_name}-{agent.nick}"
544
560
  agent_svc = f"culture-agent-{full_nick}"
545
- print(f" Restarting {agent_svc}...")
546
- if not restart_service(agent_svc):
547
- workdir = os.path.expanduser(agent.workdir)
548
- agent_config_path = os.path.join(workdir, CULTURE_DIR, AGENTS_YAML)
549
- subprocess.run(
550
- [culture_bin, "agent", "start", full_nick, "--config", agent_config_path],
551
- check=False,
552
- )
561
+ workdir = os.path.expanduser(agent.workdir)
562
+ agent_config_path = os.path.join(workdir, CULTURE_DIR, AGENTS_YAML)
563
+ agent_fallback = [
564
+ culture_bin,
565
+ "agent",
566
+ "start",
567
+ full_nick,
568
+ "--config",
569
+ agent_config_path,
570
+ ]
571
+ _restart_single_service(agent_svc, agent_fallback, restart_service)
553
572
 
554
573
  print()
555
574