agentirc-cli 4.3.6__tar.gz → 4.3.7__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 (318) hide show
  1. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/CHANGELOG.md +12 -0
  2. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/PKG-INFO +1 -1
  3. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/bots/bot_manager.py +7 -3
  4. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/bots/config.py +1 -0
  5. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/agent.py +1 -1
  6. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/channel.py +1 -1
  7. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/mesh.py +1 -2
  8. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/shared/constants.py +2 -1
  9. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/shared/ipc.py +3 -3
  10. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/agent_runner.py +8 -4
  11. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/daemon.py +20 -14
  12. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/irc_transport.py +5 -5
  13. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/skill/irc_client.py +2 -2
  14. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/socket_server.py +4 -4
  15. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/agent_runner.py +2 -1
  16. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/daemon.py +20 -14
  17. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/irc_transport.py +5 -5
  18. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/skill/irc_client.py +2 -2
  19. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/socket_server.py +4 -4
  20. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/agent_runner.py +8 -4
  21. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/daemon.py +20 -14
  22. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/irc_transport.py +5 -5
  23. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/skill/irc_client.py +2 -2
  24. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/socket_server.py +4 -4
  25. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/daemon.py +20 -14
  26. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/irc_transport.py +5 -5
  27. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/skill/irc_client.py +2 -2
  28. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/socket_server.py +4 -4
  29. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/console/client.py +1 -1
  30. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/observer.py +3 -3
  31. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/overview/collector.py +18 -18
  32. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/overview/web/style.css +1 -1
  33. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/pidfile.py +1 -1
  34. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/client.py +1 -1
  35. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/ircd.py +2 -2
  36. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/server_link.py +6 -6
  37. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/skill.py +3 -3
  38. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/packages/agent-harness/daemon.py +11 -10
  39. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/packages/agent-harness/irc_transport.py +5 -5
  40. agentirc_cli-4.3.7/packages/agent-harness/message_buffer.py +63 -0
  41. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/packages/agent-harness/skill/irc_client.py +2 -2
  42. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/packages/agent-harness/socket_server.py +4 -4
  43. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/pyproject.toml +1 -1
  44. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/conftest.py +8 -5
  45. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_acp_daemon.py +0 -6
  46. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_agent_runner.py +2 -1
  47. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_console_commands.py +0 -2
  48. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_console_connection.py +0 -4
  49. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_console_icons.py +1 -2
  50. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_federation.py +40 -34
  51. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_link_reconnect.py +16 -15
  52. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_mentions.py +3 -7
  53. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_rooms.py +5 -5
  54. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_supervisor.py +2 -1
  55. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_webhook.py +1 -1
  56. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/uv.lock +1 -1
  57. agentirc_cli-4.3.6/packages/agent-harness/message_buffer.py +0 -65
  58. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.claude/skills/pr-review/SKILL.md +0 -0
  59. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.claude/skills/run-tests/SKILL.md +0 -0
  60. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.claude/skills/run-tests/scripts/test.sh +0 -0
  61. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.flake8 +0 -0
  62. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.github/workflows/pages.yml +0 -0
  63. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.github/workflows/publish.yml +0 -0
  64. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.github/workflows/security-checks.yml +0 -0
  65. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.github/workflows/tests.yml +0 -0
  66. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.gitignore +0 -0
  67. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.markdownlint-cli2.yaml +0 -0
  68. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.pr_agent.toml +0 -0
  69. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.pre-commit-config.yaml +0 -0
  70. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/.pylintrc +0 -0
  71. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/CLAUDE.md +0 -0
  72. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/CNAME +0 -0
  73. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/Gemfile +0 -0
  74. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/Gemfile.lock +0 -0
  75. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/LICENSE +0 -0
  76. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/README.md +0 -0
  77. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/SECURITY.md +0 -0
  78. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/_config.yml +0 -0
  79. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/_sass/color_schemes/anthropic.scss +0 -0
  80. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/_sass/custom/custom.scss +0 -0
  81. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/__init__.py +0 -0
  82. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/__main__.py +0 -0
  83. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/aio.py +0 -0
  84. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/bots/__init__.py +0 -0
  85. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/bots/bot.py +0 -0
  86. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/bots/http_listener.py +0 -0
  87. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/bots/template_engine.py +0 -0
  88. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/bots/virtual_client.py +0 -0
  89. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/__init__.py +0 -0
  90. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/bot.py +0 -0
  91. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/server.py +0 -0
  92. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/shared/__init__.py +0 -0
  93. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/shared/display.py +0 -0
  94. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/shared/formatting.py +0 -0
  95. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/shared/mesh.py +0 -0
  96. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/shared/process.py +0 -0
  97. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/cli/skills.py +0 -0
  98. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/__init__.py +0 -0
  99. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/__init__.py +0 -0
  100. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/config.py +0 -0
  101. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/ipc.py +0 -0
  102. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/message_buffer.py +0 -0
  103. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/skill/SKILL.md +0 -0
  104. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/skill/__init__.py +0 -0
  105. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/supervisor.py +0 -0
  106. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/acp/webhook.py +0 -0
  107. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/__init__.py +0 -0
  108. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/__main__.py +0 -0
  109. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/config.py +0 -0
  110. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/ipc.py +0 -0
  111. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/message_buffer.py +0 -0
  112. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/skill/SKILL.md +0 -0
  113. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/skill/__init__.py +0 -0
  114. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/supervisor.py +0 -0
  115. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/claude/webhook.py +0 -0
  116. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/__init__.py +0 -0
  117. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/config.py +0 -0
  118. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/ipc.py +0 -0
  119. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/message_buffer.py +0 -0
  120. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/skill/SKILL.md +0 -0
  121. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/skill/__init__.py +0 -0
  122. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/supervisor.py +0 -0
  123. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/codex/webhook.py +0 -0
  124. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/__init__.py +0 -0
  125. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/agent_runner.py +0 -0
  126. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/config.py +0 -0
  127. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/ipc.py +0 -0
  128. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/message_buffer.py +0 -0
  129. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/skill/SKILL.md +0 -0
  130. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/skill/__init__.py +0 -0
  131. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/supervisor.py +0 -0
  132. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/clients/copilot/webhook.py +0 -0
  133. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/console/__init__.py +0 -0
  134. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/console/app.py +0 -0
  135. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/console/commands.py +0 -0
  136. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/console/widgets/__init__.py +0 -0
  137. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/console/widgets/chat.py +0 -0
  138. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/console/widgets/info_panel.py +0 -0
  139. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/console/widgets/sidebar.py +0 -0
  140. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/credentials.py +0 -0
  141. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/formatting.py +0 -0
  142. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/learn_prompt.py +0 -0
  143. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/mesh_config.py +0 -0
  144. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/overview/__init__.py +0 -0
  145. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/overview/model.py +0 -0
  146. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/overview/renderer_text.py +0 -0
  147. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/overview/renderer_web.py +0 -0
  148. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/persistence.py +0 -0
  149. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/protocol/__init__.py +0 -0
  150. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/protocol/commands.py +0 -0
  151. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/protocol/extensions/federation.md +0 -0
  152. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/protocol/extensions/history.md +0 -0
  153. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/protocol/extensions/icons.md +0 -0
  154. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/protocol/extensions/rooms.md +0 -0
  155. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/protocol/extensions/tags.md +0 -0
  156. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/protocol/extensions/threads.md +0 -0
  157. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/protocol/message.py +0 -0
  158. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/protocol/protocol-index.md +0 -0
  159. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/protocol/replies.py +0 -0
  160. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/__init__.py +0 -0
  161. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/__main__.py +0 -0
  162. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/channel.py +0 -0
  163. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/config.py +0 -0
  164. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/remote_client.py +0 -0
  165. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/room_store.py +0 -0
  166. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/rooms_util.py +0 -0
  167. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/skills/__init__.py +0 -0
  168. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/skills/history.py +0 -0
  169. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/skills/icon.py +0 -0
  170. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/skills/rooms.py +0 -0
  171. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/skills/threads.py +0 -0
  172. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/server/thread_store.py +0 -0
  173. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/culture/skills/culture/SKILL.md +0 -0
  174. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/agent-lifecycle.md +0 -0
  175. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/agentic-self-learn.md +0 -0
  176. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/agent-client.md +0 -0
  177. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/agent-harness-spec.md +0 -0
  178. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/design.md +0 -0
  179. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/harness-conformance.md +0 -0
  180. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/index.md +0 -0
  181. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/layer1-core-irc.md +0 -0
  182. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/layer2-attention.md +0 -0
  183. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/layer3-skills.md +0 -0
  184. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/layer4-federation.md +0 -0
  185. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/layer5-agent-harness.md +0 -0
  186. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/server-architecture.md +0 -0
  187. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/architecture/threads.md +0 -0
  188. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/channel-polling.md +0 -0
  189. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/acp/overview.md +0 -0
  190. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/claude/configuration.md +0 -0
  191. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/claude/context-management.md +0 -0
  192. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/claude/irc-tools.md +0 -0
  193. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/claude/overview.md +0 -0
  194. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/claude/setup.md +0 -0
  195. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/claude/supervisor.md +0 -0
  196. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/claude/webhooks.md +0 -0
  197. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/codex/configuration.md +0 -0
  198. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/codex/context-management.md +0 -0
  199. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/codex/irc-tools.md +0 -0
  200. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/codex/overview.md +0 -0
  201. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/codex/setup.md +0 -0
  202. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/codex/supervisor.md +0 -0
  203. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/codex/webhooks.md +0 -0
  204. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/copilot/configuration.md +0 -0
  205. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/copilot/context-management.md +0 -0
  206. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/copilot/irc-tools.md +0 -0
  207. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/copilot/overview.md +0 -0
  208. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/copilot/setup.md +0 -0
  209. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/copilot/supervisor.md +0 -0
  210. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/clients/copilot/webhooks.md +0 -0
  211. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/culture-cli.md +0 -0
  212. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/getting-started.md +0 -0
  213. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/index.md +0 -0
  214. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/operations/SECURITY.md +0 -0
  215. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/operations/bots.md +0 -0
  216. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/operations/ci.md +0 -0
  217. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/operations/cli.md +0 -0
  218. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/operations/docs-site.md +0 -0
  219. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/operations/index.md +0 -0
  220. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/operations/ops-tooling.md +0 -0
  221. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/operations/overview.md +0 -0
  222. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/operations/publishing.md +0 -0
  223. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/resources/github-copilot-sdk-instructions.md +0 -0
  224. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/rooms.md +0 -0
  225. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/server-rename.md +0 -0
  226. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/plans/2026-03-19-layer1-core-irc.md +0 -0
  227. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/plans/2026-03-21-layer5-agent-harness.md +0 -0
  228. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/plans/2026-03-30-overview.md +0 -0
  229. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/plans/2026-03-30-rooms-management.md +0 -0
  230. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/plans/2026-04-02-conversation-threads.md +0 -0
  231. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/plans/2026-04-02-ops-tooling.md +0 -0
  232. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/plans/2026-04-04-culture-rename.md +0 -0
  233. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/plans/2026-04-05-docs-speak-culture.md +0 -0
  234. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/plans/2026-04-06-console-chat.md +0 -0
  235. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-03-19-agentirc-design.md +0 -0
  236. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-03-21-layer5-agent-harness-design.md +0 -0
  237. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-03-30-overview-design.md +0 -0
  238. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-03-30-rooms-management-design.md +0 -0
  239. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-04-02-conversation-threads-design.md +0 -0
  240. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-04-02-ops-tooling-design.md +0 -0
  241. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-04-03-bots-webhooks-design.md +0 -0
  242. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-04-04-culture-rename-design.md +0 -0
  243. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-04-05-docs-speak-culture-design.md +0 -0
  244. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-04-05-lifecycle-reframe-design.md +0 -0
  245. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-04-06-cli-reorganization-design.md +0 -0
  246. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-04-06-console-chat-design.md +0 -0
  247. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/superpowers/specs/2026-04-07-entity-archiving-design.md +0 -0
  248. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/use-cases/01-pair-programming.md +0 -0
  249. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/use-cases/02-code-review-ensemble.md +0 -0
  250. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/use-cases/03-cross-server-delegation.md +0 -0
  251. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/use-cases/04-knowledge-propagation.md +0 -0
  252. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/use-cases/05-the-observer.md +0 -0
  253. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/use-cases/06-cross-server-ops.md +0 -0
  254. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/use-cases/07-supervisor-intervention.md +0 -0
  255. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/use-cases/08-apps-as-agents.md +0 -0
  256. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/use-cases/09-research-swarm.md +0 -0
  257. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/use-cases/10-agent-lifecycle.md +0 -0
  258. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/use-cases-index.md +0 -0
  259. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/docs/what-is-culture.md +0 -0
  260. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/packages/agent-harness/README.md +0 -0
  261. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/packages/agent-harness/config.py +0 -0
  262. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/packages/agent-harness/ipc.py +0 -0
  263. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/packages/agent-harness/skill/SKILL.md +0 -0
  264. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/packages/agent-harness/webhook.py +0 -0
  265. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/plugins/claude-code/.claude-plugin/plugin.json +0 -0
  266. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/plugins/claude-code/skills/culture/SKILL.md +0 -0
  267. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/plugins/claude-code/skills/irc/SKILL.md +0 -0
  268. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/plugins/codex/skills/culture-irc/SKILL.md +0 -0
  269. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/sonar-project.properties +0 -0
  270. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/__init__.py +0 -0
  271. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_archive.py +0 -0
  272. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_bot.py +0 -0
  273. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_bot_config.py +0 -0
  274. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_bot_manager.py +0 -0
  275. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_bots_integration.py +0 -0
  276. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_channel.py +0 -0
  277. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_codex_daemon.py +0 -0
  278. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_connection.py +0 -0
  279. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_console_client.py +0 -0
  280. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_console_integration.py +0 -0
  281. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_copilot_daemon.py +0 -0
  282. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_daemon.py +0 -0
  283. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_daemon_config.py +0 -0
  284. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_daemon_ipc.py +0 -0
  285. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_discovery.py +0 -0
  286. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_history.py +0 -0
  287. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_http_listener.py +0 -0
  288. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_integration_layer5.py +0 -0
  289. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_ipc.py +0 -0
  290. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_irc_transport.py +0 -0
  291. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_mention_alias.py +0 -0
  292. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_mention_target_cleanup.py +0 -0
  293. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_mesh_config.py +0 -0
  294. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_message.py +0 -0
  295. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_message_buffer.py +0 -0
  296. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_messaging.py +0 -0
  297. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_modes.py +0 -0
  298. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_overview_cli.py +0 -0
  299. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_overview_collector.py +0 -0
  300. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_overview_model.py +0 -0
  301. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_overview_renderer.py +0 -0
  302. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_overview_web.py +0 -0
  303. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_persistence.py +0 -0
  304. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_pidfile.py +0 -0
  305. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_poll_loop.py +0 -0
  306. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_room_persistence.py +0 -0
  307. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_rooms_federation.py +0 -0
  308. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_rooms_integration.py +0 -0
  309. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_server_icon_skill.py +0 -0
  310. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_setup_update_cli.py +0 -0
  311. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_skill_client.py +0 -0
  312. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_skills.py +0 -0
  313. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_socket_server.py +0 -0
  314. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_template_engine.py +0 -0
  315. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_thread_buffer.py +0 -0
  316. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_threads.py +0 -0
  317. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_virtual_client.py +0 -0
  318. {agentirc_cli-4.3.6 → agentirc_cli-4.3.7}/tests/test_wait_for_port.py +0 -0
@@ -4,6 +4,18 @@ 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.7] - 2026-04-07
8
+
9
+
10
+ ### Fixed
11
+
12
+ - Extract duplicate string constants (S1192, #85)
13
+ - Remove redundant exception classes in except clauses (S5713, #86)
14
+ - Clean up unused variables and function parameters (S1481/S1172, #88)
15
+ - Remove f-strings without replacement fields (S3457, #89)
16
+ - Address hardcoded credential warnings with test constants (S2068, #90)
17
+ - Fix miscellaneous code quality issues: asyncio.timeout, nested ternaries, empty methods, CSS contrast (S7483/S3358/S1186/S7924, #91)
18
+
7
19
  ## [4.3.6] - 2026-04-07
8
20
 
9
21
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentirc-cli
3
- Version: 4.3.6
3
+ Version: 4.3.7
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
@@ -6,15 +6,19 @@ import logging
6
6
  from typing import TYPE_CHECKING
7
7
 
8
8
  from culture.bots.bot import Bot
9
- from culture.bots.config import BOTS_DIR, BotConfig, load_bot_config, save_bot_config
9
+ from culture.bots.config import (
10
+ BOT_CONFIG_FILE,
11
+ BOTS_DIR,
12
+ BotConfig,
13
+ load_bot_config,
14
+ save_bot_config,
15
+ )
10
16
 
11
17
  if TYPE_CHECKING:
12
18
  from culture.server.ircd import IRCd
13
19
 
14
20
  logger = logging.getLogger(__name__)
15
21
 
16
- BOT_CONFIG_FILE = "bot.yaml"
17
-
18
22
 
19
23
  class BotManager:
20
24
  """Loads, starts, stops, and dispatches webhooks to bots."""
@@ -10,6 +10,7 @@ from pathlib import Path
10
10
  import yaml
11
11
 
12
12
  BOTS_DIR = Path(os.path.expanduser("~/.culture/bots"))
13
+ BOT_CONFIG_FILE = "bot.yaml"
13
14
 
14
15
 
15
16
  @dataclass
@@ -399,7 +399,7 @@ def _probe_server_connection(host: str, port: int, server_name: str) -> None:
399
399
  try:
400
400
  with _socket.create_connection((host, port), timeout=2):
401
401
  pass
402
- except (ConnectionRefusedError, OSError):
402
+ except OSError:
403
403
  hint = ""
404
404
  server_pid = read_pid(f"server-{server_name}")
405
405
  if not server_pid or not is_process_alive(server_pid):
@@ -55,7 +55,7 @@ def dispatch(args: argparse.Namespace) -> None:
55
55
  sys.exit(1)
56
56
  try:
57
57
  handler(args)
58
- except (ConnectionError, ConnectionRefusedError, TimeoutError, OSError) as exc:
58
+ except (TimeoutError, OSError) as exc:
59
59
  msg = str(exc)
60
60
  if (
61
61
  "Timed out" in msg
@@ -15,7 +15,6 @@ from culture.clients.claude.config import (
15
15
  load_config,
16
16
  load_config_or_default,
17
17
  )
18
- from culture.pidfile import is_process_alive, read_pid
19
18
 
20
19
  from .shared.constants import AGENTS_YAML, CULTURE_DIR, DEFAULT_CONFIG
21
20
  from .shared.mesh import build_server_start_cmd, generate_mesh_from_agents
@@ -469,7 +468,7 @@ def _wait_for_server_port(port: int, retries: int = 50, interval: float = 0.1) -
469
468
  try:
470
469
  with _socket.create_connection(("localhost", port), timeout=1):
471
470
  return
472
- except (ConnectionRefusedError, OSError):
471
+ except OSError:
473
472
  time.sleep(interval)
474
473
 
475
474
 
@@ -2,6 +2,8 @@
2
2
 
3
3
  import os
4
4
 
5
+ from culture.bots.config import BOT_CONFIG_FILE # noqa: F401
6
+
5
7
  DEFAULT_CONFIG = os.path.expanduser("~/.culture/agents.yaml")
6
8
  LOG_DIR = os.path.expanduser("~/.culture/logs")
7
9
 
@@ -9,7 +11,6 @@ _CONFIG_HELP = "Config file path"
9
11
  _SERVER_NAME_HELP = "Server name"
10
12
  _BOT_NAME_HELP = "Bot name"
11
13
 
12
- BOT_CONFIG_FILE = "bot.yaml"
13
14
  DEFAULT_CHANNEL = "#general"
14
15
  NO_AGENTS_MSG = "No agents configured"
15
16
  CULTURE_DIR = ".culture"
@@ -24,7 +24,7 @@ async def ipc_request(socket_path: str, msg_type: str, **kwargs) -> dict | None:
24
24
  asyncio.open_unix_connection(socket_path),
25
25
  timeout=3.0,
26
26
  )
27
- except (ConnectionRefusedError, FileNotFoundError, OSError):
27
+ except OSError:
28
28
  return None
29
29
  try:
30
30
  req = make_request(msg_type, **kwargs)
@@ -40,13 +40,13 @@ async def ipc_request(socket_path: str, msg_type: str, **kwargs) -> dict | None:
40
40
  msg = decode_message(data)
41
41
  if msg and msg.get("type") == "response":
42
42
  return msg
43
- except (asyncio.TimeoutError, ConnectionError, BrokenPipeError, OSError):
43
+ except OSError:
44
44
  return None
45
45
  finally:
46
46
  writer.close()
47
47
  try:
48
48
  await writer.wait_closed()
49
- except (ConnectionError, BrokenPipeError, OSError):
49
+ except OSError:
50
50
  pass
51
51
 
52
52
 
@@ -151,7 +151,8 @@ class ACPAgentRunner:
151
151
  return
152
152
  try:
153
153
  self._process.terminate()
154
- await asyncio.wait_for(self._process.wait(), timeout=5)
154
+ async with asyncio.timeout(5):
155
+ await self._process.wait()
155
156
  except (asyncio.TimeoutError, ProcessLookupError):
156
157
  try:
157
158
  self._process.kill()
@@ -209,7 +210,8 @@ class ACPAgentRunner:
209
210
  await self._process.stdin.drain()
210
211
 
211
212
  try:
212
- return await asyncio.wait_for(future, timeout=timeout)
213
+ async with asyncio.timeout(timeout):
214
+ return await future
213
215
  except (asyncio.TimeoutError, asyncio.CancelledError):
214
216
  self._pending.pop(req_id, None)
215
217
  if not future.done():
@@ -244,14 +246,16 @@ class ACPAgentRunner:
244
246
  if not self._process:
245
247
  return -1
246
248
  try:
247
- return await asyncio.wait_for(self._process.wait(), timeout=5)
249
+ async with asyncio.timeout(5):
250
+ return await self._process.wait()
248
251
  except asyncio.TimeoutError:
249
252
  try:
250
253
  self._process.kill()
251
254
  except ProcessLookupError:
252
255
  pass
253
256
  try:
254
- return await asyncio.wait_for(self._process.wait(), timeout=1)
257
+ async with asyncio.timeout(1):
258
+ return await self._process.wait()
255
259
  except asyncio.TimeoutError:
256
260
  return -1
257
261
 
@@ -31,6 +31,8 @@ logger = logging.getLogger(__name__)
31
31
 
32
32
  # IPC validation error messages
33
33
  _ERR_MISSING_CHANNEL = "Missing 'channel'"
34
+ _ERR_MISSING_CHANNEL_THREAD = "Missing 'channel' or 'thread'"
35
+ _ERR_MISSING_CHANNEL_THREAD_MSG = "Missing 'channel', 'thread', or 'message'"
34
36
 
35
37
  MAX_CRASH_COUNT = 3
36
38
  CRASH_WINDOW_SECONDS = 300
@@ -304,7 +306,7 @@ class ACPDaemon:
304
306
  prompt = (
305
307
  f"[IRC Channel Poll: {channel}] Recent unread messages:\n"
306
308
  f"{lines}\n\n"
307
- f"Respond naturally if any messages need your attention."
309
+ "Respond naturally if any messages need your attention."
308
310
  )
309
311
  self._mention_targets.append(channel)
310
312
  task = asyncio.create_task(self._agent_runner.send_prompt(prompt))
@@ -485,10 +487,10 @@ class ACPDaemon:
485
487
  return self.agent.system_prompt
486
488
  return (
487
489
  f"You are {self.agent.nick}, an AI agent on the culture IRC network.\n"
488
- f"You have IRC tools available via the irc skill. Use them to communicate.\n"
490
+ "You have IRC tools available via the irc skill. Use them to communicate.\n"
489
491
  f"Your working directory is {self.agent.directory}.\n"
490
- f"Check IRC channels periodically with irc_read() for new messages.\n"
491
- f"When you finish a task, share results in the appropriate channel with irc_send()."
492
+ "Check IRC channels periodically with irc_read() for new messages.\n"
493
+ "When you finish a task, share results in the appropriate channel with irc_send()."
492
494
  )
493
495
 
494
496
  async def _record_crash_time(self, exit_code: int) -> None:
@@ -642,6 +644,13 @@ class ACPDaemon:
642
644
  if query and running and not self._paused:
643
645
  description = await self._query_agent_status()
644
646
 
647
+ if self._paused:
648
+ activity = "paused"
649
+ elif running:
650
+ activity = "working"
651
+ else:
652
+ activity = "idle"
653
+
645
654
  return make_response(
646
655
  req_id,
647
656
  ok=True,
@@ -650,7 +659,7 @@ class ACPDaemon:
650
659
  "paused": self._paused,
651
660
  "turn_count": turn_count,
652
661
  "last_activation": self._last_activation,
653
- "activity": "paused" if self._paused else ("working" if running else "idle"),
662
+ "activity": activity,
654
663
  "description": description,
655
664
  },
656
665
  )
@@ -687,7 +696,8 @@ class ACPDaemon:
687
696
  "[SYSTEM] Briefly describe what you are currently working on "
688
697
  "in one sentence. Reply with just the description, no preamble."
689
698
  )
690
- await asyncio.wait_for(self._status_query_event.wait(), timeout=10.0)
699
+ async with asyncio.timeout(10.0):
700
+ await self._status_query_event.wait()
691
701
  return self._truncate_first_line(self._status_query_response) or "nothing"
692
702
  except asyncio.TimeoutError:
693
703
  return "busy (no response)"
@@ -744,9 +754,7 @@ class ACPDaemon:
744
754
  thread_name = msg.get("thread", "")
745
755
  text = msg.get("message", "")
746
756
  if not channel or not thread_name or not text:
747
- return make_response(
748
- req_id, ok=False, error="Missing 'channel', 'thread', or 'message'"
749
- )
757
+ return make_response(req_id, ok=False, error=_ERR_MISSING_CHANNEL_THREAD_MSG)
750
758
  assert self._transport is not None
751
759
  await self._transport.send_thread_create(channel, thread_name, text)
752
760
  return make_response(req_id, ok=True)
@@ -756,9 +764,7 @@ class ACPDaemon:
756
764
  thread_name = msg.get("thread", "")
757
765
  text = msg.get("message", "")
758
766
  if not channel or not thread_name or not text:
759
- return make_response(
760
- req_id, ok=False, error="Missing 'channel', 'thread', or 'message'"
761
- )
767
+ return make_response(req_id, ok=False, error=_ERR_MISSING_CHANNEL_THREAD_MSG)
762
768
  assert self._transport is not None
763
769
  await self._transport.send_thread_reply(channel, thread_name, text)
764
770
  return make_response(req_id, ok=True)
@@ -776,7 +782,7 @@ class ACPDaemon:
776
782
  thread_name = msg.get("thread", "")
777
783
  summary = msg.get("summary", "")
778
784
  if not channel or not thread_name:
779
- return make_response(req_id, ok=False, error="Missing 'channel' or 'thread'")
785
+ return make_response(req_id, ok=False, error=_ERR_MISSING_CHANNEL_THREAD)
780
786
  assert self._transport is not None
781
787
  await self._transport.send_thread_close(channel, thread_name, summary)
782
788
  return make_response(req_id, ok=True)
@@ -786,7 +792,7 @@ class ACPDaemon:
786
792
  thread_name = msg.get("thread", "")
787
793
  limit = int(msg.get("limit", 50))
788
794
  if not channel or not thread_name:
789
- return make_response(req_id, ok=False, error="Missing 'channel' or 'thread'")
795
+ return make_response(req_id, ok=False, error=_ERR_MISSING_CHANNEL_THREAD)
790
796
  assert self._buffer is not None
791
797
  messages = self._buffer.read_thread(channel, thread_name, limit=limit)
792
798
  return make_response(
@@ -60,7 +60,7 @@ class IRCTransport:
60
60
  async def _do_connect(self) -> None:
61
61
  try:
62
62
  self._reader, self._writer = await asyncio.open_connection(self.host, self.port)
63
- except (ConnectionRefusedError, OSError) as exc:
63
+ except OSError as exc:
64
64
  raise ConnectionError(
65
65
  f"Cannot connect to IRC server at {self.host}:{self.port} "
66
66
  f"- is the server running?"
@@ -77,12 +77,12 @@ class IRCTransport:
77
77
  if self._writer:
78
78
  try:
79
79
  await self._send_raw("QUIT :daemon shutdown")
80
- except (ConnectionError, OSError):
80
+ except OSError:
81
81
  pass
82
82
  self._writer.close()
83
83
  try:
84
84
  await self._writer.wait_closed()
85
- except (ConnectionError, BrokenPipeError):
85
+ except ConnectionError:
86
86
  pass
87
87
  self.connected = False
88
88
 
@@ -139,7 +139,7 @@ class IRCTransport:
139
139
  await self._handle(msg)
140
140
  except asyncio.CancelledError:
141
141
  raise
142
- except (ConnectionError, OSError):
142
+ except OSError:
143
143
  logger.warning("IRC connection lost")
144
144
  finally:
145
145
  self.connected = False
@@ -159,7 +159,7 @@ class IRCTransport:
159
159
  logger.info("Reconnected to IRC")
160
160
  self._reconnecting = False
161
161
  return
162
- except (ConnectionError, OSError):
162
+ except OSError:
163
163
  delay = min(delay * 2, 60)
164
164
 
165
165
  async def _handle(self, msg: Message) -> None:
@@ -56,7 +56,7 @@ class SkillClient:
56
56
  self._writer.close()
57
57
  try:
58
58
  await self._writer.wait_closed()
59
- except (ConnectionError, BrokenPipeError, OSError):
59
+ except OSError:
60
60
  pass
61
61
  self._writer = None
62
62
  self._reader = None
@@ -91,7 +91,7 @@ class SkillClient:
91
91
  if msg is None:
92
92
  continue
93
93
  self._dispatch_message(msg)
94
- except (asyncio.IncompleteReadError, ConnectionError, OSError):
94
+ except (asyncio.IncompleteReadError, OSError):
95
95
  pass
96
96
  finally:
97
97
  self._fail_pending("Connection lost")
@@ -32,7 +32,7 @@ class SocketServer:
32
32
  try:
33
33
  writer.close()
34
34
  await writer.wait_closed()
35
- except (ConnectionError, BrokenPipeError, OSError):
35
+ except OSError:
36
36
  pass
37
37
  self._clients.clear()
38
38
  if self._server:
@@ -52,7 +52,7 @@ class SocketServer:
52
52
  try:
53
53
  writer.write(data)
54
54
  await writer.drain()
55
- except (ConnectionError, BrokenPipeError, OSError):
55
+ except OSError:
56
56
  self._clients.remove(writer)
57
57
  else:
58
58
  await self._whisper_queue.put(data)
@@ -76,7 +76,7 @@ class SocketServer:
76
76
  await writer.drain()
77
77
  except asyncio.QueueEmpty:
78
78
  break
79
- except (ConnectionError, BrokenPipeError, OSError):
79
+ except OSError:
80
80
  break
81
81
 
82
82
  async def _process_client_messages(
@@ -112,7 +112,7 @@ class SocketServer:
112
112
  writer.write(encode_message(err_resp))
113
113
  await writer.drain()
114
114
  return True
115
- except (ConnectionError, BrokenPipeError, OSError):
115
+ except OSError:
116
116
  return False
117
117
 
118
118
  def _cleanup_client(self, writer: asyncio.StreamWriter) -> None:
@@ -81,7 +81,8 @@ class AgentRunner:
81
81
  self._prompt_queue.put_nowait("")
82
82
  if self._task and not self._task.done():
83
83
  try:
84
- await asyncio.wait_for(asyncio.shield(self._task), timeout=5.0)
84
+ async with asyncio.timeout(5.0):
85
+ await asyncio.shield(self._task)
85
86
  except (asyncio.TimeoutError, asyncio.CancelledError):
86
87
  self._task.cancel()
87
88
  await asyncio.gather(self._task, return_exceptions=True)
@@ -25,6 +25,8 @@ CRASH_RESTART_DELAY = 5
25
25
 
26
26
  # IPC validation error messages
27
27
  _ERR_MISSING_CHANNEL = "Missing 'channel'"
28
+ _ERR_MISSING_CHANNEL_THREAD = "Missing 'channel' or 'thread'"
29
+ _ERR_MISSING_CHANNEL_THREAD_MSG = "Missing 'channel', 'thread', or 'message'"
28
30
 
29
31
 
30
32
  class AgentDaemon:
@@ -260,7 +262,7 @@ class AgentDaemon:
260
262
  prompt = (
261
263
  f"[IRC Channel Poll: {channel}] Recent unread messages:\n"
262
264
  f"{lines}\n\n"
263
- f"Respond naturally if any messages need your attention."
265
+ "Respond naturally if any messages need your attention."
264
266
  )
265
267
  task = asyncio.create_task(self._agent_runner.send_prompt(prompt))
266
268
  self._background_tasks.add(task)
@@ -398,10 +400,10 @@ class AgentDaemon:
398
400
  return self.agent.system_prompt
399
401
  return (
400
402
  f"You are {self.agent.nick}, an AI agent on the culture IRC network.\n"
401
- f"You have IRC tools available via the irc skill. Use them to communicate.\n"
403
+ "You have IRC tools available via the irc skill. Use them to communicate.\n"
402
404
  f"Your working directory is {self.agent.directory}.\n"
403
- f"Check IRC channels periodically with irc_read() for new messages.\n"
404
- f"When you finish a task, share results in the appropriate channel with irc_send()."
405
+ "Check IRC channels periodically with irc_read() for new messages.\n"
406
+ "When you finish a task, share results in the appropriate channel with irc_send()."
405
407
  )
406
408
 
407
409
  async def _record_crash_time(self, exit_code: int) -> None:
@@ -563,6 +565,13 @@ class AgentDaemon:
563
565
  if query and running and not self._paused:
564
566
  description = await self._query_agent_status()
565
567
 
568
+ if self._paused:
569
+ activity = "paused"
570
+ elif running:
571
+ activity = "working"
572
+ else:
573
+ activity = "idle"
574
+
566
575
  return make_response(
567
576
  req_id,
568
577
  ok=True,
@@ -571,7 +580,7 @@ class AgentDaemon:
571
580
  "paused": self._paused,
572
581
  "turn_count": turn_count,
573
582
  "last_activation": self._last_activation,
574
- "activity": "paused" if self._paused else ("working" if running else "idle"),
583
+ "activity": activity,
575
584
  "description": description,
576
585
  },
577
586
  )
@@ -605,7 +614,8 @@ class AgentDaemon:
605
614
  "[SYSTEM] Briefly describe what you are currently working on "
606
615
  "in one sentence. Reply with just the description, no preamble."
607
616
  )
608
- await asyncio.wait_for(self._status_query_event.wait(), timeout=10.0)
617
+ async with asyncio.timeout(10.0):
618
+ await self._status_query_event.wait()
609
619
  return self._truncate_first_line(self._status_query_response) or "nothing"
610
620
  except asyncio.TimeoutError:
611
621
  return "busy (no response)"
@@ -662,9 +672,7 @@ class AgentDaemon:
662
672
  thread_name = msg.get("thread", "")
663
673
  text = msg.get("message", "")
664
674
  if not channel or not thread_name or not text:
665
- return make_response(
666
- req_id, ok=False, error="Missing 'channel', 'thread', or 'message'"
667
- )
675
+ return make_response(req_id, ok=False, error=_ERR_MISSING_CHANNEL_THREAD_MSG)
668
676
  assert self._transport is not None
669
677
  await self._transport.send_thread_create(channel, thread_name, text)
670
678
  return make_response(req_id, ok=True)
@@ -674,9 +682,7 @@ class AgentDaemon:
674
682
  thread_name = msg.get("thread", "")
675
683
  text = msg.get("message", "")
676
684
  if not channel or not thread_name or not text:
677
- return make_response(
678
- req_id, ok=False, error="Missing 'channel', 'thread', or 'message'"
679
- )
685
+ return make_response(req_id, ok=False, error=_ERR_MISSING_CHANNEL_THREAD_MSG)
680
686
  assert self._transport is not None
681
687
  await self._transport.send_thread_reply(channel, thread_name, text)
682
688
  return make_response(req_id, ok=True)
@@ -694,7 +700,7 @@ class AgentDaemon:
694
700
  thread_name = msg.get("thread", "")
695
701
  summary = msg.get("summary", "")
696
702
  if not channel or not thread_name:
697
- return make_response(req_id, ok=False, error="Missing 'channel' or 'thread'")
703
+ return make_response(req_id, ok=False, error=_ERR_MISSING_CHANNEL_THREAD)
698
704
  assert self._transport is not None
699
705
  await self._transport.send_thread_close(channel, thread_name, summary)
700
706
  return make_response(req_id, ok=True)
@@ -704,7 +710,7 @@ class AgentDaemon:
704
710
  thread_name = msg.get("thread", "")
705
711
  limit = int(msg.get("limit", 50))
706
712
  if not channel or not thread_name:
707
- return make_response(req_id, ok=False, error="Missing 'channel' or 'thread'")
713
+ return make_response(req_id, ok=False, error=_ERR_MISSING_CHANNEL_THREAD)
708
714
  assert self._buffer is not None
709
715
  messages = self._buffer.read_thread(channel, thread_name, limit=limit)
710
716
  return make_response(
@@ -60,7 +60,7 @@ class IRCTransport:
60
60
  async def _do_connect(self) -> None:
61
61
  try:
62
62
  self._reader, self._writer = await asyncio.open_connection(self.host, self.port)
63
- except (ConnectionRefusedError, OSError) as exc:
63
+ except OSError as exc:
64
64
  raise ConnectionError(
65
65
  f"Cannot connect to IRC server at {self.host}:{self.port} "
66
66
  f"- is the server running?"
@@ -77,12 +77,12 @@ class IRCTransport:
77
77
  if self._writer:
78
78
  try:
79
79
  await self._send_raw("QUIT :daemon shutdown")
80
- except (ConnectionError, OSError):
80
+ except OSError:
81
81
  pass
82
82
  self._writer.close()
83
83
  try:
84
84
  await self._writer.wait_closed()
85
- except (ConnectionError, BrokenPipeError):
85
+ except ConnectionError:
86
86
  pass
87
87
  self.connected = False
88
88
 
@@ -139,7 +139,7 @@ class IRCTransport:
139
139
  await self._handle(msg)
140
140
  except asyncio.CancelledError:
141
141
  raise
142
- except (ConnectionError, OSError):
142
+ except OSError:
143
143
  logger.warning("IRC connection lost")
144
144
  finally:
145
145
  self.connected = False
@@ -159,7 +159,7 @@ class IRCTransport:
159
159
  logger.info("Reconnected to IRC")
160
160
  self._reconnecting = False
161
161
  return
162
- except (ConnectionError, OSError):
162
+ except OSError:
163
163
  delay = min(delay * 2, 60)
164
164
 
165
165
  async def _handle(self, msg: Message) -> None:
@@ -56,7 +56,7 @@ class SkillClient:
56
56
  self._writer.close()
57
57
  try:
58
58
  await self._writer.wait_closed()
59
- except (ConnectionError, BrokenPipeError, OSError):
59
+ except OSError:
60
60
  pass
61
61
  self._writer = None
62
62
  self._reader = None
@@ -84,7 +84,7 @@ class SkillClient:
84
84
  if msg is None:
85
85
  continue
86
86
  self._dispatch_message(msg)
87
- except (asyncio.IncompleteReadError, ConnectionError, OSError):
87
+ except (asyncio.IncompleteReadError, OSError):
88
88
  pass
89
89
  finally:
90
90
  # Resolve any still-pending futures with an error
@@ -32,7 +32,7 @@ class SocketServer:
32
32
  try:
33
33
  writer.close()
34
34
  await writer.wait_closed()
35
- except (ConnectionError, BrokenPipeError, OSError):
35
+ except OSError:
36
36
  pass
37
37
  self._clients.clear()
38
38
  if self._server:
@@ -55,7 +55,7 @@ class SocketServer:
55
55
  try:
56
56
  writer.write(data)
57
57
  await writer.drain()
58
- except (ConnectionError, BrokenPipeError, OSError):
58
+ except OSError:
59
59
  self._clients.remove(writer)
60
60
  else:
61
61
  # No clients yet — queue for delivery when one connects.
@@ -80,7 +80,7 @@ class SocketServer:
80
80
  await writer.drain()
81
81
  except asyncio.QueueEmpty:
82
82
  break
83
- except (ConnectionError, BrokenPipeError, OSError):
83
+ except OSError:
84
84
  break
85
85
 
86
86
  async def _process_client_messages(
@@ -116,7 +116,7 @@ class SocketServer:
116
116
  writer.write(encode_message(err_resp))
117
117
  await writer.drain()
118
118
  return True
119
- except (ConnectionError, BrokenPipeError, OSError):
119
+ except OSError:
120
120
  return False
121
121
 
122
122
  def _cleanup_client(self, writer: asyncio.StreamWriter) -> None:
@@ -128,7 +128,8 @@ class CodexAgentRunner:
128
128
  return
129
129
  try:
130
130
  self._process.terminate()
131
- await asyncio.wait_for(self._process.wait(), timeout=5)
131
+ async with asyncio.timeout(5):
132
+ await self._process.wait()
132
133
  except (asyncio.TimeoutError, ProcessLookupError):
133
134
  try:
134
135
  self._process.kill()
@@ -185,7 +186,8 @@ class CodexAgentRunner:
185
186
  await self._process.stdin.drain()
186
187
 
187
188
  try:
188
- return await asyncio.wait_for(future, timeout=30)
189
+ async with asyncio.timeout(30):
190
+ return await future
189
191
  except (asyncio.TimeoutError, asyncio.CancelledError):
190
192
  self._pending.pop(req_id, None)
191
193
  if not future.done():
@@ -220,14 +222,16 @@ class CodexAgentRunner:
220
222
  if not self._process:
221
223
  return -1
222
224
  try:
223
- return await asyncio.wait_for(self._process.wait(), timeout=5)
225
+ async with asyncio.timeout(5):
226
+ return await self._process.wait()
224
227
  except asyncio.TimeoutError:
225
228
  try:
226
229
  self._process.kill()
227
230
  except ProcessLookupError:
228
231
  pass
229
232
  try:
230
- return await asyncio.wait_for(self._process.wait(), timeout=1)
233
+ async with asyncio.timeout(1):
234
+ return await self._process.wait()
231
235
  except asyncio.TimeoutError:
232
236
  return -1
233
237