agentirc-cli 4.2.0__tar.gz → 4.2.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.
Files changed (310) hide show
  1. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/CHANGELOG.md +13 -0
  2. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/PKG-INFO +1 -1
  3. agentirc_cli-4.2.1/culture/aio.py +12 -0
  4. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/agent_runner.py +4 -2
  5. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/daemon.py +11 -10
  6. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/irc_transport.py +5 -4
  7. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/daemon.py +10 -9
  8. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/irc_transport.py +5 -4
  9. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/agent_runner.py +4 -2
  10. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/daemon.py +11 -10
  11. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/irc_transport.py +5 -4
  12. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/agent_runner.py +4 -2
  13. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/daemon.py +11 -10
  14. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/irc_transport.py +5 -4
  15. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/console/app.py +8 -7
  16. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/console/client.py +2 -3
  17. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/client.py +3 -2
  18. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/server_link.py +9 -8
  19. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/skills/rooms.py +2 -1
  20. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/agent-harness-spec.md +5 -1
  21. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/packages/agent-harness/daemon.py +11 -10
  22. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/packages/agent-harness/irc_transport.py +5 -4
  23. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/pyproject.toml +1 -1
  24. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_daemon_ipc.py +2 -2
  25. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_mention_target_cleanup.py +6 -6
  26. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/uv.lock +1 -1
  27. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.claude/skills/pr-review/SKILL.md +0 -0
  28. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.claude/skills/run-tests/SKILL.md +0 -0
  29. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.claude/skills/run-tests/scripts/test.sh +0 -0
  30. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.flake8 +0 -0
  31. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.github/workflows/pages.yml +0 -0
  32. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.github/workflows/publish.yml +0 -0
  33. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.github/workflows/security-checks.yml +0 -0
  34. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.github/workflows/tests.yml +0 -0
  35. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.gitignore +0 -0
  36. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.markdownlint-cli2.yaml +0 -0
  37. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.pr_agent.toml +0 -0
  38. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.pre-commit-config.yaml +0 -0
  39. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/.pylintrc +0 -0
  40. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/CLAUDE.md +0 -0
  41. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/CNAME +0 -0
  42. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/Gemfile +0 -0
  43. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/Gemfile.lock +0 -0
  44. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/LICENSE +0 -0
  45. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/README.md +0 -0
  46. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/SECURITY.md +0 -0
  47. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/_config.yml +0 -0
  48. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/_sass/color_schemes/anthropic.scss +0 -0
  49. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/_sass/custom/custom.scss +0 -0
  50. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/__init__.py +0 -0
  51. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/__main__.py +0 -0
  52. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/bots/__init__.py +0 -0
  53. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/bots/bot.py +0 -0
  54. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/bots/bot_manager.py +0 -0
  55. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/bots/config.py +0 -0
  56. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/bots/http_listener.py +0 -0
  57. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/bots/template_engine.py +0 -0
  58. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/bots/virtual_client.py +0 -0
  59. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/cli/__init__.py +0 -0
  60. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/cli/_helpers.py +0 -0
  61. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/cli/agent.py +0 -0
  62. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/cli/bot.py +0 -0
  63. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/cli/channel.py +0 -0
  64. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/cli/mesh.py +0 -0
  65. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/cli/server.py +0 -0
  66. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/cli/skills.py +0 -0
  67. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/__init__.py +0 -0
  68. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/__init__.py +0 -0
  69. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/config.py +0 -0
  70. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/ipc.py +0 -0
  71. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/message_buffer.py +0 -0
  72. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/skill/SKILL.md +0 -0
  73. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/skill/__init__.py +0 -0
  74. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/skill/irc_client.py +0 -0
  75. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/socket_server.py +0 -0
  76. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/supervisor.py +0 -0
  77. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/acp/webhook.py +0 -0
  78. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/__init__.py +0 -0
  79. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/__main__.py +0 -0
  80. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/agent_runner.py +0 -0
  81. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/config.py +0 -0
  82. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/ipc.py +0 -0
  83. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/message_buffer.py +0 -0
  84. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/skill/SKILL.md +0 -0
  85. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/skill/__init__.py +0 -0
  86. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/skill/irc_client.py +0 -0
  87. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/socket_server.py +0 -0
  88. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/supervisor.py +0 -0
  89. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/claude/webhook.py +0 -0
  90. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/__init__.py +0 -0
  91. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/config.py +0 -0
  92. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/ipc.py +0 -0
  93. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/message_buffer.py +0 -0
  94. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/skill/SKILL.md +0 -0
  95. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/skill/__init__.py +0 -0
  96. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/skill/irc_client.py +0 -0
  97. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/socket_server.py +0 -0
  98. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/supervisor.py +0 -0
  99. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/codex/webhook.py +0 -0
  100. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/__init__.py +0 -0
  101. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/config.py +0 -0
  102. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/ipc.py +0 -0
  103. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/message_buffer.py +0 -0
  104. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/skill/SKILL.md +0 -0
  105. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/skill/__init__.py +0 -0
  106. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/skill/irc_client.py +0 -0
  107. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/socket_server.py +0 -0
  108. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/supervisor.py +0 -0
  109. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/clients/copilot/webhook.py +0 -0
  110. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/console/__init__.py +0 -0
  111. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/console/commands.py +0 -0
  112. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/console/widgets/__init__.py +0 -0
  113. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/console/widgets/chat.py +0 -0
  114. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/console/widgets/info_panel.py +0 -0
  115. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/console/widgets/sidebar.py +0 -0
  116. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/credentials.py +0 -0
  117. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/learn_prompt.py +0 -0
  118. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/mesh_config.py +0 -0
  119. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/observer.py +0 -0
  120. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/overview/__init__.py +0 -0
  121. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/overview/collector.py +0 -0
  122. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/overview/model.py +0 -0
  123. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/overview/renderer_text.py +0 -0
  124. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/overview/renderer_web.py +0 -0
  125. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/overview/web/style.css +0 -0
  126. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/persistence.py +0 -0
  127. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/pidfile.py +0 -0
  128. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/protocol/__init__.py +0 -0
  129. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/protocol/commands.py +0 -0
  130. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/protocol/extensions/federation.md +0 -0
  131. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/protocol/extensions/history.md +0 -0
  132. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/protocol/extensions/icons.md +0 -0
  133. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/protocol/extensions/rooms.md +0 -0
  134. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/protocol/extensions/tags.md +0 -0
  135. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/protocol/extensions/threads.md +0 -0
  136. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/protocol/message.py +0 -0
  137. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/protocol/protocol-index.md +0 -0
  138. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/protocol/replies.py +0 -0
  139. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/__init__.py +0 -0
  140. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/__main__.py +0 -0
  141. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/channel.py +0 -0
  142. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/config.py +0 -0
  143. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/ircd.py +0 -0
  144. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/remote_client.py +0 -0
  145. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/room_store.py +0 -0
  146. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/rooms_util.py +0 -0
  147. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/skill.py +0 -0
  148. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/skills/__init__.py +0 -0
  149. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/skills/history.py +0 -0
  150. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/skills/icon.py +0 -0
  151. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/skills/threads.py +0 -0
  152. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/server/thread_store.py +0 -0
  153. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/culture/skills/culture/SKILL.md +0 -0
  154. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/agent-lifecycle.md +0 -0
  155. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/agentic-self-learn.md +0 -0
  156. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/agent-client.md +0 -0
  157. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/design.md +0 -0
  158. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/harness-conformance.md +0 -0
  159. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/index.md +0 -0
  160. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/layer1-core-irc.md +0 -0
  161. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/layer2-attention.md +0 -0
  162. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/layer3-skills.md +0 -0
  163. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/layer4-federation.md +0 -0
  164. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/layer5-agent-harness.md +0 -0
  165. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/server-architecture.md +0 -0
  166. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/architecture/threads.md +0 -0
  167. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/channel-polling.md +0 -0
  168. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/acp/overview.md +0 -0
  169. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/claude/configuration.md +0 -0
  170. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/claude/context-management.md +0 -0
  171. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/claude/irc-tools.md +0 -0
  172. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/claude/overview.md +0 -0
  173. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/claude/setup.md +0 -0
  174. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/claude/supervisor.md +0 -0
  175. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/claude/webhooks.md +0 -0
  176. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/codex/configuration.md +0 -0
  177. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/codex/context-management.md +0 -0
  178. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/codex/irc-tools.md +0 -0
  179. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/codex/overview.md +0 -0
  180. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/codex/setup.md +0 -0
  181. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/codex/supervisor.md +0 -0
  182. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/codex/webhooks.md +0 -0
  183. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/copilot/configuration.md +0 -0
  184. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/copilot/context-management.md +0 -0
  185. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/copilot/irc-tools.md +0 -0
  186. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/copilot/overview.md +0 -0
  187. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/copilot/setup.md +0 -0
  188. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/copilot/supervisor.md +0 -0
  189. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/clients/copilot/webhooks.md +0 -0
  190. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/culture-cli.md +0 -0
  191. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/getting-started.md +0 -0
  192. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/index.md +0 -0
  193. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/operations/SECURITY.md +0 -0
  194. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/operations/bots.md +0 -0
  195. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/operations/ci.md +0 -0
  196. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/operations/cli.md +0 -0
  197. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/operations/docs-site.md +0 -0
  198. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/operations/index.md +0 -0
  199. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/operations/ops-tooling.md +0 -0
  200. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/operations/overview.md +0 -0
  201. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/operations/publishing.md +0 -0
  202. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/resources/github-copilot-sdk-instructions.md +0 -0
  203. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/rooms.md +0 -0
  204. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/server-rename.md +0 -0
  205. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
  206. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
  207. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
  208. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
  209. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
  210. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
  211. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
  212. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
  213. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
  214. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
  215. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
  216. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
  217. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
  218. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
  219. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
  220. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
  221. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
  222. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
  223. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
  224. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
  225. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
  226. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
  227. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/use-cases/01-pair-programming.md +0 -0
  228. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/use-cases/02-code-review-ensemble.md +0 -0
  229. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/use-cases/03-cross-server-delegation.md +0 -0
  230. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/use-cases/04-knowledge-propagation.md +0 -0
  231. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/use-cases/05-the-observer.md +0 -0
  232. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/use-cases/06-cross-server-ops.md +0 -0
  233. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/use-cases/07-supervisor-intervention.md +0 -0
  234. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/use-cases/08-apps-as-agents.md +0 -0
  235. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/use-cases/09-research-swarm.md +0 -0
  236. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/use-cases/10-agent-lifecycle.md +0 -0
  237. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/use-cases-index.md +0 -0
  238. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/docs/what-is-culture.md +0 -0
  239. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/packages/agent-harness/README.md +0 -0
  240. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/packages/agent-harness/config.py +0 -0
  241. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/packages/agent-harness/ipc.py +0 -0
  242. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/packages/agent-harness/message_buffer.py +0 -0
  243. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/packages/agent-harness/skill/SKILL.md +0 -0
  244. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/packages/agent-harness/skill/irc_client.py +0 -0
  245. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/packages/agent-harness/socket_server.py +0 -0
  246. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/packages/agent-harness/webhook.py +0 -0
  247. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
  248. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/plugins/claude-code/skills/culture/SKILL.md +0 -0
  249. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/plugins/claude-code/skills/irc/SKILL.md +0 -0
  250. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
  251. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/sonar-project.properties +0 -0
  252. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/__init__.py +0 -0
  253. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/conftest.py +0 -0
  254. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_acp_daemon.py +0 -0
  255. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_agent_runner.py +0 -0
  256. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_archive.py +0 -0
  257. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_bot.py +0 -0
  258. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_bot_config.py +0 -0
  259. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_bot_manager.py +0 -0
  260. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_bots_integration.py +0 -0
  261. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_channel.py +0 -0
  262. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_codex_daemon.py +0 -0
  263. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_connection.py +0 -0
  264. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_console_client.py +0 -0
  265. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_console_commands.py +0 -0
  266. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_console_connection.py +0 -0
  267. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_console_icons.py +0 -0
  268. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_console_integration.py +0 -0
  269. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_copilot_daemon.py +0 -0
  270. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_daemon.py +0 -0
  271. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_daemon_config.py +0 -0
  272. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_discovery.py +0 -0
  273. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_federation.py +0 -0
  274. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_history.py +0 -0
  275. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_http_listener.py +0 -0
  276. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_integration_layer5.py +0 -0
  277. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_ipc.py +0 -0
  278. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_irc_transport.py +0 -0
  279. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_link_reconnect.py +0 -0
  280. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_mention_alias.py +0 -0
  281. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_mentions.py +0 -0
  282. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_mesh_config.py +0 -0
  283. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_message.py +0 -0
  284. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_message_buffer.py +0 -0
  285. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_messaging.py +0 -0
  286. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_modes.py +0 -0
  287. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_overview_cli.py +0 -0
  288. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_overview_collector.py +0 -0
  289. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_overview_model.py +0 -0
  290. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_overview_renderer.py +0 -0
  291. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_overview_web.py +0 -0
  292. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_persistence.py +0 -0
  293. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_pidfile.py +0 -0
  294. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_poll_loop.py +0 -0
  295. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_room_persistence.py +0 -0
  296. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_rooms.py +0 -0
  297. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_rooms_federation.py +0 -0
  298. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_rooms_integration.py +0 -0
  299. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_server_icon_skill.py +0 -0
  300. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_setup_update_cli.py +0 -0
  301. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_skill_client.py +0 -0
  302. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_skills.py +0 -0
  303. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_socket_server.py +0 -0
  304. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_supervisor.py +0 -0
  305. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_template_engine.py +0 -0
  306. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_thread_buffer.py +0 -0
  307. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_threads.py +0 -0
  308. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_virtual_client.py +0 -0
  309. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_wait_for_port.py +0 -0
  310. {agentirc_cli-4.2.0 → agentirc_cli-4.2.1}/tests/test_webhook.py +0 -0
@@ -4,6 +4,19 @@ 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.2.1] - 2026-04-07
8
+
9
+
10
+ ### Changed
11
+
12
+ - Update dispatch patterns to use declarative maybe_await() utility for handling both sync and async handlers
13
+ - Remove unnecessary async keyword from ~40 handler functions that never use await
14
+
15
+
16
+ ### Fixed
17
+
18
+ - SonarCloud S7503: async functions that never await (issue #83)
19
+
7
20
  ## [4.2.0] - 2026-04-07
8
21
 
9
22
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentirc-cli
3
- Version: 4.2.0
3
+ Version: 4.2.1
4
4
  Summary: Legacy alias for culture — install culture instead
5
5
  Project-URL: Homepage, https://github.com/OriNachum/culture
6
6
  Author: Ori Nachum
@@ -0,0 +1,12 @@
1
+ """Async utilities for culture."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+
7
+
8
+ async def maybe_await(result):
9
+ """Await the result only if it's a coroutine, otherwise return directly."""
10
+ if asyncio.iscoroutine(result):
11
+ return await result
12
+ return result
@@ -14,6 +14,8 @@ import shutil
14
14
  import tempfile
15
15
  from typing import Any, Awaitable, Callable
16
16
 
17
+ from culture.aio import maybe_await
18
+
17
19
  logger = logging.getLogger(__name__)
18
20
 
19
21
 
@@ -33,7 +35,7 @@ class ACPAgentRunner:
33
35
  system_prompt: str = "",
34
36
  on_exit: Callable[[int], Awaitable[None]] | None = None,
35
37
  on_message: Callable[[dict[str, Any]], Awaitable[None]] | None = None,
36
- on_turn_error: Callable[[], Awaitable[None]] | None = None,
38
+ on_turn_error: Callable[[], Awaitable[None] | None] | None = None,
37
39
  ) -> None:
38
40
  self.model = model
39
41
  self.directory = directory
@@ -387,7 +389,7 @@ class ACPAgentRunner:
387
389
  except Exception:
388
390
  logger.exception("ACP turn error")
389
391
  if self.on_turn_error:
390
- await self.on_turn_error()
392
+ await maybe_await(self.on_turn_error())
391
393
  finally:
392
394
  self._busy = False
393
395
 
@@ -16,6 +16,7 @@ import os
16
16
  import time
17
17
  from collections import deque
18
18
 
19
+ from culture.aio import maybe_await
19
20
  from culture.clients.acp.agent_runner import ACPAgentRunner
20
21
  from culture.clients.acp.config import AgentConfig, DaemonConfig
21
22
  from culture.clients.acp.ipc import make_response
@@ -318,7 +319,7 @@ class ACPDaemon:
318
319
  # Agent runner helpers
319
320
  # ------------------------------------------------------------------
320
321
 
321
- async def _on_turn_error(self) -> None:
322
+ def _on_turn_error(self) -> None:
322
323
  """Clean up stale relay target when a prompt fails."""
323
324
  if self._mention_targets:
324
325
  self._mention_targets.popleft()
@@ -436,7 +437,7 @@ class ACPDaemon:
436
437
  if line:
437
438
  await self._transport.send_privmsg(relay_target, line)
438
439
 
439
- async def _capture_agent_status(self, msg: dict) -> None:
440
+ def _capture_agent_status(self, msg: dict) -> None:
440
441
  """Capture the last assistant text for status reporting and fulfill any pending query."""
441
442
  if msg.get("type") == "assistant":
442
443
  for block in msg.get("content", []):
@@ -459,7 +460,7 @@ class ACPDaemon:
459
460
  if self._supervisor:
460
461
  await self._supervisor.observe(msg)
461
462
 
462
- await self._capture_agent_status(msg)
463
+ self._capture_agent_status(msg)
463
464
 
464
465
  def _build_system_prompt(self) -> str:
465
466
  if self.agent.system_prompt:
@@ -589,7 +590,7 @@ class ACPDaemon:
589
590
  handler = self._ipc_dispatch.get(msg_type)
590
591
  if handler is None:
591
592
  return make_response(req_id, ok=False, error=f"Unknown message type: {msg_type!r}")
592
- return await handler(req_id, msg)
593
+ return await maybe_await(handler(req_id, msg))
593
594
  except Exception as exc:
594
595
  logger.exception("IPC handler error for type %r", msg_type)
595
596
  return make_response(req_id, ok=False, error=str(exc))
@@ -598,12 +599,12 @@ class ACPDaemon:
598
599
  # IPC sub-handlers
599
600
  # ------------------------------------------------------------------
600
601
 
601
- async def _ipc_pause(self, req_id: str, msg: dict) -> dict:
602
+ def _ipc_pause(self, req_id: str, msg: dict) -> dict:
602
603
  self._paused = True
603
604
  logger.info("Agent %s paused", self.agent.nick)
604
605
  return make_response(req_id, ok=True)
605
606
 
606
- async def _ipc_resume(self, req_id: str, msg: dict) -> dict:
607
+ def _ipc_resume(self, req_id: str, msg: dict) -> dict:
607
608
  self._paused = False
608
609
  logger.info("Agent %s resumed", self.agent.nick)
609
610
  # NOTE: Catch-up on missed messages is not yet implemented.
@@ -689,7 +690,7 @@ class ACPDaemon:
689
690
  await self._transport.send_privmsg(channel, text)
690
691
  return make_response(req_id, ok=True)
691
692
 
692
- async def _ipc_irc_read(self, req_id: str, msg: dict) -> dict:
693
+ def _ipc_irc_read(self, req_id: str, msg: dict) -> dict:
693
694
  channel = msg.get("channel", "")
694
695
  limit = int(msg.get("limit", 50))
695
696
  if not channel:
@@ -764,7 +765,7 @@ class ACPDaemon:
764
765
  await self._transport.send_thread_close(channel, thread_name, summary)
765
766
  return make_response(req_id, ok=True)
766
767
 
767
- async def _ipc_irc_thread_read(self, req_id: str, msg: dict) -> dict:
768
+ def _ipc_irc_thread_read(self, req_id: str, msg: dict) -> dict:
768
769
  channel = msg.get("channel", "")
769
770
  thread_name = msg.get("thread", "")
770
771
  limit = int(msg.get("limit", 50))
@@ -783,7 +784,7 @@ class ACPDaemon:
783
784
  },
784
785
  )
785
786
 
786
- async def _ipc_irc_channels(self, req_id: str, msg: dict) -> dict:
787
+ def _ipc_irc_channels(self, req_id: str, msg: dict) -> dict:
787
788
  assert self._transport is not None
788
789
  return make_response(req_id, ok=True, data={"channels": self._transport.channels})
789
790
 
@@ -828,7 +829,7 @@ class ACPDaemon:
828
829
  await self._agent_runner.send_prompt("/clear")
829
830
  return make_response(req_id, ok=True)
830
831
 
831
- async def _ipc_shutdown(self, req_id: str, msg: dict) -> dict:
832
+ def _ipc_shutdown(self, req_id: str, msg: dict) -> dict:
832
833
  task = asyncio.create_task(self._graceful_shutdown())
833
834
  self._background_tasks.add(task)
834
835
  task.add_done_callback(self._background_tasks.discard)
@@ -5,6 +5,7 @@ import logging
5
5
  import re
6
6
  from typing import Callable
7
7
 
8
+ from culture.aio import maybe_await
8
9
  from culture.clients.acp.message_buffer import MessageBuffer
9
10
  from culture.protocol.message import Message
10
11
 
@@ -164,7 +165,7 @@ class IRCTransport:
164
165
  async def _handle(self, msg: Message) -> None:
165
166
  handler = self._cmd_handlers.get(msg.command)
166
167
  if handler:
167
- await handler(msg)
168
+ await maybe_await(handler(msg))
168
169
 
169
170
  async def _on_ping(self, msg: Message) -> None:
170
171
  token = msg.params[0] if msg.params else ""
@@ -180,7 +181,7 @@ class IRCTransport:
180
181
  if self.icon:
181
182
  await self._send_raw(f"ICON {self.icon}")
182
183
 
183
- async def _on_privmsg(self, msg: Message) -> None:
184
+ def _on_privmsg(self, msg: Message) -> None:
184
185
  if len(msg.params) < 2:
185
186
  return
186
187
  target = msg.params[0]
@@ -199,7 +200,7 @@ class IRCTransport:
199
200
  ):
200
201
  self.on_mention(target, sender, text)
201
202
 
202
- async def _on_notice(self, msg: Message) -> None:
203
+ def _on_notice(self, msg: Message) -> None:
203
204
  if len(msg.params) < 2:
204
205
  return
205
206
  target = msg.params[0]
@@ -208,7 +209,7 @@ class IRCTransport:
208
209
  if target.startswith("#"):
209
210
  self.buffer.add(target, sender, text)
210
211
 
211
- async def _on_roominvite(self, msg: Message) -> None:
212
+ def _on_roominvite(self, msg: Message) -> None:
212
213
  if len(msg.params) < 3:
213
214
  return
214
215
  channel = msg.params[0]
@@ -6,6 +6,7 @@ import logging
6
6
  import os
7
7
  import time
8
8
 
9
+ from culture.aio import maybe_await
9
10
  from culture.clients.claude.agent_runner import AgentRunner
10
11
  from culture.clients.claude.config import AgentConfig, DaemonConfig
11
12
  from culture.clients.claude.ipc import make_response
@@ -378,7 +379,7 @@ class AgentDaemon:
378
379
  if self._supervisor:
379
380
  await self._supervisor.observe(msg)
380
381
 
381
- await self._capture_agent_status(msg)
382
+ self._capture_agent_status(msg)
382
383
 
383
384
  def _build_system_prompt(self) -> str:
384
385
  if self.agent.system_prompt:
@@ -433,7 +434,7 @@ class AgentDaemon:
433
434
  return True
434
435
  return False
435
436
 
436
- async def _capture_agent_status(self, msg: dict) -> None:
437
+ def _capture_agent_status(self, msg: dict) -> None:
437
438
  """Capture the last assistant text for status reporting and fulfill any pending query."""
438
439
  if msg.get("type") == "assistant":
439
440
  for block in msg.get("content", []):
@@ -516,7 +517,7 @@ class AgentDaemon:
516
517
  handler = self._ipc_dispatch.get(msg_type)
517
518
  if handler is None:
518
519
  return make_response(req_id, ok=False, error=f"Unknown message type: {msg_type!r}")
519
- return await handler(req_id, msg)
520
+ return await maybe_await(handler(req_id, msg))
520
521
  except Exception as exc:
521
522
  logger.exception("IPC handler error for type %r", msg_type)
522
523
  return make_response(req_id, ok=False, error=str(exc))
@@ -525,12 +526,12 @@ class AgentDaemon:
525
526
  # IPC sub-handlers
526
527
  # ------------------------------------------------------------------
527
528
 
528
- async def _ipc_pause(self, req_id: str, msg: dict) -> dict:
529
+ def _ipc_pause(self, req_id: str, msg: dict) -> dict:
529
530
  self._paused = True
530
531
  logger.info("Agent %s paused", self.agent.nick)
531
532
  return make_response(req_id, ok=True)
532
533
 
533
- async def _ipc_resume(self, req_id: str, msg: dict) -> dict:
534
+ def _ipc_resume(self, req_id: str, msg: dict) -> dict:
534
535
  self._paused = False
535
536
  logger.info("Agent %s resumed", self.agent.nick)
536
537
  # NOTE: Catch-up on missed messages is not yet implemented.
@@ -613,7 +614,7 @@ class AgentDaemon:
613
614
  await self._transport.send_privmsg(channel, text)
614
615
  return make_response(req_id, ok=True)
615
616
 
616
- async def _ipc_irc_read(self, req_id: str, msg: dict) -> dict:
617
+ def _ipc_irc_read(self, req_id: str, msg: dict) -> dict:
617
618
  channel = msg.get("channel", "")
618
619
  limit = int(msg.get("limit", 50))
619
620
  if not channel:
@@ -688,7 +689,7 @@ class AgentDaemon:
688
689
  await self._transport.send_thread_close(channel, thread_name, summary)
689
690
  return make_response(req_id, ok=True)
690
691
 
691
- async def _ipc_irc_thread_read(self, req_id: str, msg: dict) -> dict:
692
+ def _ipc_irc_thread_read(self, req_id: str, msg: dict) -> dict:
692
693
  channel = msg.get("channel", "")
693
694
  thread_name = msg.get("thread", "")
694
695
  limit = int(msg.get("limit", 50))
@@ -707,7 +708,7 @@ class AgentDaemon:
707
708
  },
708
709
  )
709
710
 
710
- async def _ipc_irc_channels(self, req_id: str, msg: dict) -> dict:
711
+ def _ipc_irc_channels(self, req_id: str, msg: dict) -> dict:
711
712
  assert self._transport is not None
712
713
  return make_response(req_id, ok=True, data={"channels": self._transport.channels})
713
714
 
@@ -752,7 +753,7 @@ class AgentDaemon:
752
753
  await self._agent_runner.send_prompt("/clear")
753
754
  return make_response(req_id, ok=True)
754
755
 
755
- async def _ipc_shutdown(self, req_id: str, msg: dict) -> dict:
756
+ def _ipc_shutdown(self, req_id: str, msg: dict) -> dict:
756
757
  task = asyncio.create_task(self._graceful_shutdown())
757
758
  self._background_tasks.add(task)
758
759
  task.add_done_callback(self._background_tasks.discard)
@@ -5,6 +5,7 @@ import logging
5
5
  import re
6
6
  from typing import Callable
7
7
 
8
+ from culture.aio import maybe_await
8
9
  from culture.clients.claude.message_buffer import MessageBuffer
9
10
  from culture.protocol.message import Message
10
11
 
@@ -164,7 +165,7 @@ class IRCTransport:
164
165
  async def _handle(self, msg: Message) -> None:
165
166
  handler = self._cmd_handlers.get(msg.command)
166
167
  if handler:
167
- await handler(msg)
168
+ await maybe_await(handler(msg))
168
169
 
169
170
  async def _on_ping(self, msg: Message) -> None:
170
171
  token = msg.params[0] if msg.params else ""
@@ -180,7 +181,7 @@ class IRCTransport:
180
181
  if self.icon:
181
182
  await self._send_raw(f"ICON {self.icon}")
182
183
 
183
- async def _on_privmsg(self, msg: Message) -> None:
184
+ def _on_privmsg(self, msg: Message) -> None:
184
185
  if len(msg.params) < 2:
185
186
  return
186
187
  target = msg.params[0]
@@ -199,7 +200,7 @@ class IRCTransport:
199
200
  ):
200
201
  self.on_mention(target, sender, text)
201
202
 
202
- async def _on_notice(self, msg: Message) -> None:
203
+ def _on_notice(self, msg: Message) -> None:
203
204
  if len(msg.params) < 2:
204
205
  return
205
206
  target = msg.params[0]
@@ -208,7 +209,7 @@ class IRCTransport:
208
209
  if target.startswith("#"):
209
210
  self.buffer.add(target, sender, text)
210
211
 
211
- async def _on_roominvite(self, msg: Message) -> None:
212
+ def _on_roominvite(self, msg: Message) -> None:
212
213
  if len(msg.params) < 3:
213
214
  return
214
215
  channel = msg.params[0]
@@ -10,6 +10,8 @@ import shutil
10
10
  import tempfile
11
11
  from typing import Any, Awaitable, Callable
12
12
 
13
+ from culture.aio import maybe_await
14
+
13
15
  logger = logging.getLogger(__name__)
14
16
 
15
17
 
@@ -23,7 +25,7 @@ class CodexAgentRunner:
23
25
  system_prompt: str = "",
24
26
  on_exit: Callable[[int], Awaitable[None]] | None = None,
25
27
  on_message: Callable[[dict[str, Any]], Awaitable[None]] | None = None,
26
- on_turn_error: Callable[[], Awaitable[None]] | None = None,
28
+ on_turn_error: Callable[[], Awaitable[None] | None] | None = None,
27
29
  ) -> None:
28
30
  self.model = model
29
31
  self.directory = directory
@@ -321,7 +323,7 @@ class CodexAgentRunner:
321
323
  except Exception:
322
324
  logger.exception("Codex turn error")
323
325
  if self.on_turn_error:
324
- await self.on_turn_error()
326
+ await maybe_await(self.on_turn_error())
325
327
 
326
328
  except asyncio.CancelledError:
327
329
  raise
@@ -13,6 +13,7 @@ import os
13
13
  import time
14
14
  from collections import deque
15
15
 
16
+ from culture.aio import maybe_await
16
17
  from culture.clients.codex.agent_runner import CodexAgentRunner
17
18
  from culture.clients.codex.config import AgentConfig, DaemonConfig
18
19
  from culture.clients.codex.ipc import make_response
@@ -293,7 +294,7 @@ class CodexDaemon:
293
294
  # Agent runner helpers
294
295
  # ------------------------------------------------------------------
295
296
 
296
- async def _on_turn_error(self) -> None:
297
+ def _on_turn_error(self) -> None:
297
298
  """Clean up stale relay target when a prompt fails."""
298
299
  if self._mention_targets:
299
300
  self._mention_targets.popleft()
@@ -404,7 +405,7 @@ class CodexDaemon:
404
405
  if line:
405
406
  await self._transport.send_privmsg(relay_target, line)
406
407
 
407
- async def _capture_agent_status(self, msg: dict) -> None:
408
+ def _capture_agent_status(self, msg: dict) -> None:
408
409
  """Capture the last assistant text for status reporting and fulfill any pending query."""
409
410
  if msg.get("type") == "assistant":
410
411
  for block in msg.get("content", []):
@@ -427,7 +428,7 @@ class CodexDaemon:
427
428
  if self._supervisor:
428
429
  await self._supervisor.observe(msg)
429
430
 
430
- await self._capture_agent_status(msg)
431
+ self._capture_agent_status(msg)
431
432
 
432
433
  def _build_system_prompt(self) -> str:
433
434
  if self.agent.system_prompt:
@@ -549,7 +550,7 @@ class CodexDaemon:
549
550
  handler = self._ipc_dispatch.get(msg_type)
550
551
  if handler is None:
551
552
  return make_response(req_id, ok=False, error=f"Unknown message type: {msg_type!r}")
552
- return await handler(req_id, msg)
553
+ return await maybe_await(handler(req_id, msg))
553
554
  except Exception as exc:
554
555
  logger.exception("IPC handler error for type %r", msg_type)
555
556
  return make_response(req_id, ok=False, error=str(exc))
@@ -558,12 +559,12 @@ class CodexDaemon:
558
559
  # IPC sub-handlers
559
560
  # ------------------------------------------------------------------
560
561
 
561
- async def _ipc_pause(self, req_id: str, msg: dict) -> dict:
562
+ def _ipc_pause(self, req_id: str, msg: dict) -> dict:
562
563
  self._paused = True
563
564
  logger.info("Agent %s paused", self.agent.nick)
564
565
  return make_response(req_id, ok=True)
565
566
 
566
- async def _ipc_resume(self, req_id: str, msg: dict) -> dict:
567
+ def _ipc_resume(self, req_id: str, msg: dict) -> dict:
567
568
  self._paused = False
568
569
  logger.info("Agent %s resumed", self.agent.nick)
569
570
  # NOTE: Catch-up on missed messages is not yet implemented.
@@ -649,7 +650,7 @@ class CodexDaemon:
649
650
  await self._transport.send_privmsg(channel, text)
650
651
  return make_response(req_id, ok=True)
651
652
 
652
- async def _ipc_irc_read(self, req_id: str, msg: dict) -> dict:
653
+ def _ipc_irc_read(self, req_id: str, msg: dict) -> dict:
653
654
  channel = msg.get("channel", "")
654
655
  limit = int(msg.get("limit", 50))
655
656
  if not channel:
@@ -724,7 +725,7 @@ class CodexDaemon:
724
725
  await self._transport.send_thread_close(channel, thread_name, summary)
725
726
  return make_response(req_id, ok=True)
726
727
 
727
- async def _ipc_irc_thread_read(self, req_id: str, msg: dict) -> dict:
728
+ def _ipc_irc_thread_read(self, req_id: str, msg: dict) -> dict:
728
729
  channel = msg.get("channel", "")
729
730
  thread_name = msg.get("thread", "")
730
731
  limit = int(msg.get("limit", 50))
@@ -743,7 +744,7 @@ class CodexDaemon:
743
744
  },
744
745
  )
745
746
 
746
- async def _ipc_irc_channels(self, req_id: str, msg: dict) -> dict:
747
+ def _ipc_irc_channels(self, req_id: str, msg: dict) -> dict:
747
748
  assert self._transport is not None
748
749
  return make_response(req_id, ok=True, data={"channels": self._transport.channels})
749
750
 
@@ -788,7 +789,7 @@ class CodexDaemon:
788
789
  await self._agent_runner.send_prompt("/clear")
789
790
  return make_response(req_id, ok=True)
790
791
 
791
- async def _ipc_shutdown(self, req_id: str, msg: dict) -> dict:
792
+ def _ipc_shutdown(self, req_id: str, msg: dict) -> dict:
792
793
  task = asyncio.create_task(self._graceful_shutdown())
793
794
  self._background_tasks.add(task)
794
795
  task.add_done_callback(self._background_tasks.discard)
@@ -5,6 +5,7 @@ import logging
5
5
  import re
6
6
  from typing import Callable
7
7
 
8
+ from culture.aio import maybe_await
8
9
  from culture.clients.codex.message_buffer import MessageBuffer
9
10
  from culture.protocol.message import Message
10
11
 
@@ -164,7 +165,7 @@ class IRCTransport:
164
165
  async def _handle(self, msg: Message) -> None:
165
166
  handler = self._cmd_handlers.get(msg.command)
166
167
  if handler:
167
- await handler(msg)
168
+ await maybe_await(handler(msg))
168
169
 
169
170
  async def _on_ping(self, msg: Message) -> None:
170
171
  token = msg.params[0] if msg.params else ""
@@ -180,7 +181,7 @@ class IRCTransport:
180
181
  if self.icon:
181
182
  await self._send_raw(f"ICON {self.icon}")
182
183
 
183
- async def _on_privmsg(self, msg: Message) -> None:
184
+ def _on_privmsg(self, msg: Message) -> None:
184
185
  if len(msg.params) < 2:
185
186
  return
186
187
  target = msg.params[0]
@@ -199,7 +200,7 @@ class IRCTransport:
199
200
  ):
200
201
  self.on_mention(target, sender, text)
201
202
 
202
- async def _on_notice(self, msg: Message) -> None:
203
+ def _on_notice(self, msg: Message) -> None:
203
204
  if len(msg.params) < 2:
204
205
  return
205
206
  target = msg.params[0]
@@ -208,7 +209,7 @@ class IRCTransport:
208
209
  if target.startswith("#"):
209
210
  self.buffer.add(target, sender, text)
210
211
 
211
- async def _on_roominvite(self, msg: Message) -> None:
212
+ def _on_roominvite(self, msg: Message) -> None:
212
213
  if len(msg.params) < 3:
213
214
  return
214
215
  channel = msg.params[0]
@@ -9,6 +9,8 @@ import shutil
9
9
  import tempfile
10
10
  from typing import Any, Awaitable, Callable
11
11
 
12
+ from culture.aio import maybe_await
13
+
12
14
  logger = logging.getLogger(__name__)
13
15
 
14
16
 
@@ -23,7 +25,7 @@ class CopilotAgentRunner:
23
25
  skill_directories: list[str] | None = None,
24
26
  on_exit: Callable[[int], Awaitable[None]] | None = None,
25
27
  on_message: Callable[[dict[str, Any]], Awaitable[None]] | None = None,
26
- on_turn_error: Callable[[], Awaitable[None]] | None = None,
28
+ on_turn_error: Callable[[], Awaitable[None] | None] | None = None,
27
29
  ) -> None:
28
30
  self.model = model
29
31
  self.directory = directory
@@ -161,7 +163,7 @@ class CopilotAgentRunner:
161
163
  except Exception:
162
164
  logger.exception("Copilot session turn error")
163
165
  if self.on_turn_error:
164
- await self.on_turn_error()
166
+ await maybe_await(self.on_turn_error())
165
167
  if not self._stopping:
166
168
  self._running = False
167
169
  if self.on_exit:
@@ -13,6 +13,7 @@ import os
13
13
  import time
14
14
  from collections import deque
15
15
 
16
+ from culture.aio import maybe_await
16
17
  from culture.clients.copilot.agent_runner import CopilotAgentRunner
17
18
  from culture.clients.copilot.config import AgentConfig, DaemonConfig
18
19
  from culture.clients.copilot.ipc import make_response
@@ -293,7 +294,7 @@ class CopilotDaemon:
293
294
  # Agent runner helpers
294
295
  # ------------------------------------------------------------------
295
296
 
296
- async def _on_turn_error(self) -> None:
297
+ def _on_turn_error(self) -> None:
297
298
  """Clean up stale relay target when a prompt fails."""
298
299
  if self._mention_targets:
299
300
  self._mention_targets.popleft()
@@ -411,7 +412,7 @@ class CopilotDaemon:
411
412
  if line:
412
413
  await self._transport.send_privmsg(relay_target, line)
413
414
 
414
- async def _capture_agent_status(self, msg: dict) -> None:
415
+ def _capture_agent_status(self, msg: dict) -> None:
415
416
  """Capture the last assistant text for status reporting and fulfill any pending query."""
416
417
  if msg.get("type") == "assistant":
417
418
  for block in msg.get("content", []):
@@ -434,7 +435,7 @@ class CopilotDaemon:
434
435
  if self._supervisor:
435
436
  await self._supervisor.observe(msg)
436
437
 
437
- await self._capture_agent_status(msg)
438
+ self._capture_agent_status(msg)
438
439
 
439
440
  def _build_system_prompt(self) -> str:
440
441
  if self.agent.system_prompt:
@@ -556,7 +557,7 @@ class CopilotDaemon:
556
557
  handler = self._ipc_dispatch.get(msg_type)
557
558
  if handler is None:
558
559
  return make_response(req_id, ok=False, error=f"Unknown message type: {msg_type!r}")
559
- return await handler(req_id, msg)
560
+ return await maybe_await(handler(req_id, msg))
560
561
  except Exception as exc:
561
562
  logger.exception("IPC handler error for type %r", msg_type)
562
563
  return make_response(req_id, ok=False, error=str(exc))
@@ -565,12 +566,12 @@ class CopilotDaemon:
565
566
  # IPC sub-handlers
566
567
  # ------------------------------------------------------------------
567
568
 
568
- async def _ipc_pause(self, req_id: str, msg: dict) -> dict:
569
+ def _ipc_pause(self, req_id: str, msg: dict) -> dict:
569
570
  self._paused = True
570
571
  logger.info("Agent %s paused", self.agent.nick)
571
572
  return make_response(req_id, ok=True)
572
573
 
573
- async def _ipc_resume(self, req_id: str, msg: dict) -> dict:
574
+ def _ipc_resume(self, req_id: str, msg: dict) -> dict:
574
575
  self._paused = False
575
576
  logger.info("Agent %s resumed", self.agent.nick)
576
577
  # NOTE: Catch-up on missed messages is not yet implemented.
@@ -656,7 +657,7 @@ class CopilotDaemon:
656
657
  await self._transport.send_privmsg(channel, text)
657
658
  return make_response(req_id, ok=True)
658
659
 
659
- async def _ipc_irc_read(self, req_id: str, msg: dict) -> dict:
660
+ def _ipc_irc_read(self, req_id: str, msg: dict) -> dict:
660
661
  channel = msg.get("channel", "")
661
662
  limit = int(msg.get("limit", 50))
662
663
  if not channel:
@@ -731,7 +732,7 @@ class CopilotDaemon:
731
732
  await self._transport.send_thread_close(channel, thread_name, summary)
732
733
  return make_response(req_id, ok=True)
733
734
 
734
- async def _ipc_irc_thread_read(self, req_id: str, msg: dict) -> dict:
735
+ def _ipc_irc_thread_read(self, req_id: str, msg: dict) -> dict:
735
736
  channel = msg.get("channel", "")
736
737
  thread_name = msg.get("thread", "")
737
738
  limit = int(msg.get("limit", 50))
@@ -750,7 +751,7 @@ class CopilotDaemon:
750
751
  },
751
752
  )
752
753
 
753
- async def _ipc_irc_channels(self, req_id: str, msg: dict) -> dict:
754
+ def _ipc_irc_channels(self, req_id: str, msg: dict) -> dict:
754
755
  assert self._transport is not None
755
756
  return make_response(req_id, ok=True, data={"channels": self._transport.channels})
756
757
 
@@ -795,7 +796,7 @@ class CopilotDaemon:
795
796
  await self._agent_runner.send_prompt("/clear")
796
797
  return make_response(req_id, ok=True)
797
798
 
798
- async def _ipc_shutdown(self, req_id: str, msg: dict) -> dict:
799
+ def _ipc_shutdown(self, req_id: str, msg: dict) -> dict:
799
800
  task = asyncio.create_task(self._graceful_shutdown())
800
801
  self._background_tasks.add(task)
801
802
  task.add_done_callback(self._background_tasks.discard)
@@ -5,6 +5,7 @@ import logging
5
5
  import re
6
6
  from typing import Callable
7
7
 
8
+ from culture.aio import maybe_await
8
9
  from culture.clients.copilot.message_buffer import MessageBuffer
9
10
  from culture.protocol.message import Message
10
11
 
@@ -164,7 +165,7 @@ class IRCTransport:
164
165
  async def _handle(self, msg: Message) -> None:
165
166
  handler = self._cmd_handlers.get(msg.command)
166
167
  if handler:
167
- await handler(msg)
168
+ await maybe_await(handler(msg))
168
169
 
169
170
  async def _on_ping(self, msg: Message) -> None:
170
171
  token = msg.params[0] if msg.params else ""
@@ -180,7 +181,7 @@ class IRCTransport:
180
181
  if self.icon:
181
182
  await self._send_raw(f"ICON {self.icon}")
182
183
 
183
- async def _on_privmsg(self, msg: Message) -> None:
184
+ def _on_privmsg(self, msg: Message) -> None:
184
185
  if len(msg.params) < 2:
185
186
  return
186
187
  target = msg.params[0]
@@ -199,7 +200,7 @@ class IRCTransport:
199
200
  ):
200
201
  self.on_mention(target, sender, text)
201
202
 
202
- async def _on_notice(self, msg: Message) -> None:
203
+ def _on_notice(self, msg: Message) -> None:
203
204
  if len(msg.params) < 2:
204
205
  return
205
206
  target = msg.params[0]
@@ -208,7 +209,7 @@ class IRCTransport:
208
209
  if target.startswith("#"):
209
210
  self.buffer.add(target, sender, text)
210
211
 
211
- async def _on_roominvite(self, msg: Message) -> None:
212
+ def _on_roominvite(self, msg: Message) -> None:
212
213
  if len(msg.params) < 3:
213
214
  return
214
215
  channel = msg.params[0]