connectonion 0.6.2__py3-none-any.whl → 0.6.4__py3-none-any.whl

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 (410) hide show
  1. connectonion/__init__.py +46 -9
  2. connectonion/cli/__init__.py +11 -1
  3. connectonion/cli/browser_agent/__init__.py +11 -1
  4. connectonion/cli/browser_agent/browser.py +13 -3
  5. connectonion/cli/browser_agent/element_finder.py +8 -0
  6. connectonion/cli/browser_agent/highlight_screenshot.py +9 -1
  7. connectonion/cli/browser_agent/scroll.py +8 -0
  8. connectonion/cli/co_ai/__init__.py +6 -0
  9. connectonion/cli/co_ai/agent.py +87 -0
  10. connectonion/cli/co_ai/agents/__init__.py +5 -0
  11. connectonion/cli/co_ai/agents/registry.py +57 -0
  12. connectonion/cli/co_ai/commands/__init__.py +45 -0
  13. connectonion/cli/co_ai/commands/compact.py +173 -0
  14. connectonion/cli/co_ai/commands/cost.py +77 -0
  15. connectonion/cli/co_ai/commands/export.py +60 -0
  16. connectonion/cli/co_ai/commands/help.py +80 -0
  17. connectonion/cli/co_ai/commands/init.py +101 -0
  18. connectonion/cli/co_ai/commands/sessions.py +55 -0
  19. connectonion/cli/co_ai/commands/tasks.py +63 -0
  20. connectonion/cli/co_ai/commands/undo.py +103 -0
  21. connectonion/cli/co_ai/context.py +127 -0
  22. connectonion/cli/co_ai/main.py +52 -0
  23. connectonion/cli/co_ai/plugins/__init__.py +5 -0
  24. connectonion/cli/co_ai/plugins/system_reminder.py +154 -0
  25. connectonion/cli/co_ai/prompts/agents/explore.md +79 -0
  26. connectonion/cli/co_ai/prompts/agents/plan.md +60 -0
  27. connectonion/cli/co_ai/prompts/assembler.py +303 -0
  28. connectonion/cli/{docs/co-vibecoding-principles-docs-contexts-all-in-one.md → co_ai/prompts/connectonion/README.md} +26 -0
  29. connectonion/cli/co_ai/prompts/connectonion/api.md +457 -0
  30. connectonion/cli/co_ai/prompts/connectonion/cli/README.md +805 -0
  31. connectonion/cli/co_ai/prompts/connectonion/cli/auth.md +46 -0
  32. connectonion/cli/co_ai/prompts/connectonion/cli/browser.md +235 -0
  33. connectonion/cli/co_ai/prompts/connectonion/cli/copy.md +184 -0
  34. connectonion/cli/co_ai/prompts/connectonion/cli/create.md +335 -0
  35. connectonion/cli/co_ai/prompts/connectonion/cli/init.md +431 -0
  36. connectonion/cli/co_ai/prompts/connectonion/co-directory-structure.md +214 -0
  37. connectonion/cli/co_ai/prompts/connectonion/concepts/agent.md +1078 -0
  38. connectonion/cli/co_ai/prompts/connectonion/concepts/events.md +816 -0
  39. connectonion/cli/co_ai/prompts/connectonion/concepts/llm_do.md +256 -0
  40. connectonion/cli/co_ai/prompts/connectonion/concepts/max_iterations.md +362 -0
  41. connectonion/cli/co_ai/prompts/connectonion/concepts/models.md +641 -0
  42. connectonion/cli/co_ai/prompts/connectonion/concepts/plugins.md +100 -0
  43. connectonion/cli/co_ai/prompts/connectonion/concepts/prompts.md +122 -0
  44. connectonion/cli/co_ai/prompts/connectonion/concepts/tools.md +512 -0
  45. connectonion/cli/co_ai/prompts/connectonion/concepts/transcribe.md +156 -0
  46. connectonion/cli/co_ai/prompts/connectonion/concepts/trust.md +291 -0
  47. connectonion/cli/co_ai/prompts/connectonion/debug/README.md +18 -0
  48. connectonion/cli/co_ai/prompts/connectonion/debug/auto_debug.md +1026 -0
  49. connectonion/cli/co_ai/prompts/connectonion/debug/console.md +129 -0
  50. connectonion/cli/co_ai/prompts/connectonion/debug/eval-format.md +178 -0
  51. connectonion/cli/co_ai/prompts/connectonion/debug/eval.md +230 -0
  52. connectonion/cli/co_ai/prompts/connectonion/debug/exceptions.md +307 -0
  53. connectonion/cli/co_ai/prompts/connectonion/debug/log.md +117 -0
  54. connectonion/cli/co_ai/prompts/connectonion/debug/xray.md +215 -0
  55. connectonion/cli/co_ai/prompts/connectonion/design-decisions/001-choosing-input-method.md +202 -0
  56. connectonion/cli/co_ai/prompts/connectonion/design-decisions/002-choosing-llm-function-name.md +202 -0
  57. connectonion/cli/co_ai/prompts/connectonion/design-decisions/003-choosing-trust-keyword.md +141 -0
  58. connectonion/cli/co_ai/prompts/connectonion/design-decisions/004-cli-create-flow.md +117 -0
  59. connectonion/cli/co_ai/prompts/connectonion/design-decisions/005-designing-agent-network-protocol.md +503 -0
  60. connectonion/cli/co_ai/prompts/connectonion/design-decisions/006-agent-address-format.md +305 -0
  61. connectonion/cli/co_ai/prompts/connectonion/design-decisions/007-authentication-backend-design.md +240 -0
  62. connectonion/cli/co_ai/prompts/connectonion/design-decisions/008-naming-is-hard.md +228 -0
  63. connectonion/cli/co_ai/prompts/connectonion/design-decisions/009-why-connect-function.md +167 -0
  64. connectonion/cli/co_ai/prompts/connectonion/design-decisions/010-cli-ux-progressive-disclosure.md +176 -0
  65. connectonion/cli/co_ai/prompts/connectonion/design-decisions/011-global-config-identity-management.md +357 -0
  66. connectonion/cli/co_ai/prompts/connectonion/design-decisions/012-tool-execution-separation.md +259 -0
  67. connectonion/cli/co_ai/prompts/connectonion/design-decisions/013-debug-and-logging-design.md +253 -0
  68. connectonion/cli/co_ai/prompts/connectonion/design-decisions/014-hook-system-design.md +510 -0
  69. connectonion/cli/co_ai/prompts/connectonion/design-decisions/015-interactive-auto-debug-design.md +837 -0
  70. connectonion/cli/co_ai/prompts/connectonion/design-decisions/016-why-no-zero-knowledge-proofs.md +358 -0
  71. connectonion/cli/co_ai/prompts/connectonion/design-decisions/017-session-logging-and-eval-format.md +120 -0
  72. connectonion/cli/co_ai/prompts/connectonion/design-decisions/018-event-api-naming.md +274 -0
  73. connectonion/cli/co_ai/prompts/connectonion/design-decisions/019-agent-lifecycle-design.md +655 -0
  74. connectonion/cli/co_ai/prompts/connectonion/design-decisions/020-trust-system-and-network-architecture.md +503 -0
  75. connectonion/cli/co_ai/prompts/connectonion/design-decisions/021-task-storage-jsonl-design.md +496 -0
  76. connectonion/cli/co_ai/prompts/connectonion/design-decisions/022-raw-asgi-implementation.md +273 -0
  77. connectonion/cli/co_ai/prompts/connectonion/examples/agent_reasoning.md +62 -0
  78. connectonion/cli/co_ai/prompts/connectonion/examples/atomic_tools.md +24 -0
  79. connectonion/cli/co_ai/prompts/connectonion/examples/load_guide.md +18 -0
  80. connectonion/cli/co_ai/prompts/connectonion/examples.md +0 -0
  81. connectonion/cli/co_ai/prompts/connectonion/hook-system-options.md +364 -0
  82. connectonion/cli/co_ai/prompts/connectonion/index.md +162 -0
  83. connectonion/cli/co_ai/prompts/connectonion/integrations/README.md +12 -0
  84. connectonion/cli/co_ai/prompts/connectonion/integrations/auth.md +450 -0
  85. connectonion/cli/co_ai/prompts/connectonion/integrations/google.md +431 -0
  86. connectonion/cli/co_ai/prompts/connectonion/integrations/microsoft.md +370 -0
  87. connectonion/cli/co_ai/prompts/connectonion/network/README.md +14 -0
  88. connectonion/cli/co_ai/prompts/connectonion/network/connect.md +543 -0
  89. connectonion/cli/co_ai/prompts/connectonion/network/connection.md +538 -0
  90. connectonion/cli/co_ai/prompts/connectonion/network/deploy.md +123 -0
  91. connectonion/cli/co_ai/prompts/connectonion/network/host.md +1049 -0
  92. connectonion/cli/co_ai/prompts/connectonion/network/protocol/agent-relay-protocol.md +495 -0
  93. connectonion/cli/co_ai/prompts/connectonion/network/protocol/announce-message.md +115 -0
  94. connectonion/cli/co_ai/prompts/connectonion/principles.md +124 -0
  95. connectonion/cli/co_ai/prompts/connectonion/quickstart.md +261 -0
  96. connectonion/cli/co_ai/prompts/connectonion/roadmap.md +81 -0
  97. connectonion/cli/co_ai/prompts/connectonion/templates/README.md +77 -0
  98. connectonion/cli/co_ai/prompts/connectonion/templates/meta-agent.md +152 -0
  99. connectonion/cli/co_ai/prompts/connectonion/templates/minimal.md +105 -0
  100. connectonion/cli/co_ai/prompts/connectonion/templates/playwright.md +130 -0
  101. connectonion/cli/co_ai/prompts/connectonion/templates/web-research.md +144 -0
  102. connectonion/cli/co_ai/prompts/connectonion/tui/README.md +95 -0
  103. connectonion/cli/co_ai/prompts/connectonion/tui/chat.md +181 -0
  104. connectonion/cli/co_ai/prompts/connectonion/tui/divider.md +63 -0
  105. connectonion/cli/co_ai/prompts/connectonion/tui/dropdown.md +83 -0
  106. connectonion/cli/co_ai/prompts/connectonion/tui/footer.md +44 -0
  107. connectonion/cli/co_ai/prompts/connectonion/tui/fuzzy.md +68 -0
  108. connectonion/cli/co_ai/prompts/connectonion/tui/input.md +84 -0
  109. connectonion/cli/co_ai/prompts/connectonion/tui/keys.md +77 -0
  110. connectonion/cli/co_ai/prompts/connectonion/tui/pick.md +71 -0
  111. connectonion/cli/co_ai/prompts/connectonion/tui/providers.md +89 -0
  112. connectonion/cli/co_ai/prompts/connectonion/tui/status_bar.md +67 -0
  113. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/README.md +156 -0
  114. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/calendar_plugin.md +68 -0
  115. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/eval.md +89 -0
  116. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/gmail_plugin.md +68 -0
  117. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/image_result_formatter.md +74 -0
  118. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/re_act.md +86 -0
  119. connectonion/cli/co_ai/prompts/connectonion/useful_plugins/shell_approval.md +69 -0
  120. connectonion/cli/co_ai/prompts/connectonion/useful_tools/README.md +81 -0
  121. connectonion/cli/co_ai/prompts/connectonion/useful_tools/diff_writer.md +138 -0
  122. connectonion/cli/co_ai/prompts/connectonion/useful_tools/get_emails.md +499 -0
  123. connectonion/cli/co_ai/prompts/connectonion/useful_tools/gmail.md +135 -0
  124. connectonion/cli/co_ai/prompts/connectonion/useful_tools/google_calendar.md +106 -0
  125. connectonion/cli/co_ai/prompts/connectonion/useful_tools/memory.md +486 -0
  126. connectonion/cli/co_ai/prompts/connectonion/useful_tools/microsoft_calendar.md +106 -0
  127. connectonion/cli/co_ai/prompts/connectonion/useful_tools/outlook.md +120 -0
  128. connectonion/cli/co_ai/prompts/connectonion/useful_tools/send_email.md +403 -0
  129. connectonion/cli/co_ai/prompts/connectonion/useful_tools/shell.md +95 -0
  130. connectonion/cli/co_ai/prompts/connectonion/useful_tools/slash_command.md +96 -0
  131. connectonion/cli/co_ai/prompts/connectonion/useful_tools/terminal.md +97 -0
  132. connectonion/cli/co_ai/prompts/connectonion/useful_tools/todo_list.md +252 -0
  133. connectonion/cli/co_ai/prompts/connectonion/useful_tools/web_fetch.md +130 -0
  134. connectonion/cli/co_ai/prompts/connectonion/vibe-coding-guide.md +97 -0
  135. connectonion/cli/co_ai/prompts/connectonion/windows-support.md +258 -0
  136. connectonion/cli/co_ai/prompts/main.md +247 -0
  137. connectonion/cli/co_ai/prompts/summarization.md +55 -0
  138. connectonion/cli/co_ai/prompts/system-reminders/agent.md +23 -0
  139. connectonion/cli/co_ai/prompts/system-reminders/plan_mode.md +13 -0
  140. connectonion/cli/co_ai/prompts/system-reminders/security.md +14 -0
  141. connectonion/cli/co_ai/prompts/system-reminders/simplicity.md +14 -0
  142. connectonion/cli/co_ai/prompts/tools/ask_user.md +61 -0
  143. connectonion/cli/co_ai/prompts/tools/background.md +57 -0
  144. connectonion/cli/co_ai/prompts/tools/edit.md +90 -0
  145. connectonion/cli/co_ai/prompts/tools/glob.md +52 -0
  146. connectonion/cli/co_ai/prompts/tools/grep.md +55 -0
  147. connectonion/cli/co_ai/prompts/tools/plan_mode.md +80 -0
  148. connectonion/cli/co_ai/prompts/tools/read.md +40 -0
  149. connectonion/cli/co_ai/prompts/tools/shell.md +67 -0
  150. connectonion/cli/co_ai/prompts/tools/task.md +51 -0
  151. connectonion/cli/co_ai/prompts/tools/todo.md +139 -0
  152. connectonion/cli/co_ai/prompts/tools/write.md +47 -0
  153. connectonion/cli/co_ai/prompts/workflow.md +89 -0
  154. connectonion/cli/co_ai/sessions.py +110 -0
  155. connectonion/cli/co_ai/skills/__init__.py +37 -0
  156. connectonion/cli/co_ai/skills/builtin/commit/SKILL.md +63 -0
  157. connectonion/cli/co_ai/skills/builtin/review-pr/SKILL.md +76 -0
  158. connectonion/cli/co_ai/skills/loader.py +166 -0
  159. connectonion/cli/co_ai/skills/tool.py +46 -0
  160. connectonion/cli/co_ai/tools/__init__.py +92 -0
  161. connectonion/cli/co_ai/tools/ask_user.py +35 -0
  162. connectonion/cli/co_ai/tools/background.py +201 -0
  163. connectonion/cli/co_ai/tools/diff_writer.py +291 -0
  164. connectonion/cli/co_ai/tools/edit.py +89 -0
  165. connectonion/cli/co_ai/tools/glob.py +84 -0
  166. connectonion/cli/co_ai/tools/grep.py +158 -0
  167. connectonion/cli/co_ai/tools/load_guide.py +23 -0
  168. connectonion/cli/co_ai/tools/multi_edit.py +116 -0
  169. connectonion/cli/co_ai/tools/plan_mode.py +169 -0
  170. connectonion/cli/co_ai/tools/read.py +61 -0
  171. connectonion/cli/co_ai/tools/task.py +59 -0
  172. connectonion/cli/co_ai/tools/todo_list.py +159 -0
  173. connectonion/cli/co_ai/tools/write.py +126 -0
  174. connectonion/cli/commands/__init__.py +11 -1
  175. connectonion/cli/commands/ai_commands.py +34 -0
  176. connectonion/cli/commands/copy_commands.py +55 -6
  177. connectonion/cli/commands/create.py +20 -17
  178. connectonion/cli/commands/init.py +19 -22
  179. connectonion/cli/commands/project_cmd_lib.py +15 -0
  180. connectonion/cli/main.py +11 -0
  181. connectonion/console.py +15 -1
  182. connectonion/core/__init__.py +10 -1
  183. connectonion/core/agent.py +37 -16
  184. connectonion/core/exceptions.py +74 -0
  185. connectonion/core/llm.py +54 -6
  186. connectonion/core/tool_executor.py +32 -31
  187. connectonion/core/tool_factory.py +47 -10
  188. connectonion/debug/__init__.py +10 -1
  189. connectonion/debug/debug_explainer/__init__.py +10 -1
  190. connectonion/debug/execution_analyzer/__init__.py +10 -1
  191. connectonion/debug/execution_analyzer/execution_analysis.py +5 -2
  192. connectonion/debug/runtime_inspector/__init__.py +10 -1
  193. connectonion/docs/.package-ignore +6 -0
  194. connectonion/docs/README.md +2036 -0
  195. connectonion/docs/api.md +457 -0
  196. connectonion/docs/archive/001-ai-agent-is-just-prompt-plus-function.md +249 -0
  197. connectonion/docs/archive/README.md +53 -0
  198. connectonion/docs/archive/archive/consolidation-plan.md +72 -0
  199. connectonion/docs/archive/archive/core-principles-extracted.md +239 -0
  200. connectonion/docs/archive/archive/master-principles.md +222 -0
  201. connectonion/docs/archive/archive/principles.md +293 -0
  202. connectonion/docs/archive/archive/simplicity-principles.md +221 -0
  203. connectonion/docs/archive/attack-defense-insights.md +410 -0
  204. connectonion/docs/archive/business-model.md +305 -0
  205. connectonion/docs/archive/core-principles-unified.md +190 -0
  206. connectonion/docs/archive/discussion-journey.md +178 -0
  207. connectonion/docs/archive/economic-analysis.md +323 -0
  208. connectonion/docs/archive/features/01-share-and-find.md +256 -0
  209. connectonion/docs/archive/features/02-agent-authentication.md +93 -0
  210. connectonion/docs/archive/features/03-test-before-trust.md +71 -0
  211. connectonion/docs/archive/features/06-reliability-and-offline.md +197 -0
  212. connectonion/docs/archive/features/README.md +46 -0
  213. connectonion/docs/archive/features-roadmap.md +247 -0
  214. connectonion/docs/archive/mcp-comparison-insights.md +215 -0
  215. connectonion/docs/archive/migration-strategy.md +571 -0
  216. connectonion/docs/archive/mini-whitepaper.md +293 -0
  217. connectonion/docs/archive/network-protocol.md +394 -0
  218. connectonion/docs/archive/semantic-revolution.md +367 -0
  219. connectonion/docs/archive/technical-architecture.md +453 -0
  220. connectonion/docs/archive/the-semantic-insight.md +207 -0
  221. connectonion/docs/archive/threat-model.md +164 -0
  222. connectonion/docs/cli/README.md +805 -0
  223. connectonion/docs/cli/auth.md +46 -0
  224. connectonion/docs/cli/browser.md +235 -0
  225. connectonion/docs/cli/copy.md +232 -0
  226. connectonion/docs/cli/create.md +335 -0
  227. connectonion/docs/cli/init.md +431 -0
  228. connectonion/docs/co-directory-structure.md +214 -0
  229. connectonion/docs/concepts/agent.md +1078 -0
  230. connectonion/docs/concepts/events.md +699 -0
  231. connectonion/docs/concepts/llm_do.md +256 -0
  232. connectonion/docs/concepts/max_iterations.md +362 -0
  233. connectonion/docs/concepts/models.md +641 -0
  234. connectonion/docs/concepts/plugins.md +101 -0
  235. connectonion/docs/concepts/prompts.md +122 -0
  236. connectonion/docs/concepts/session.md +428 -0
  237. connectonion/docs/concepts/tools.md +512 -0
  238. connectonion/docs/concepts/transcribe.md +156 -0
  239. connectonion/docs/concepts/trust.md +291 -0
  240. connectonion/docs/connectonion.md +1256 -0
  241. connectonion/docs/debug/README.md +18 -0
  242. connectonion/docs/debug/auto_debug.md +1026 -0
  243. connectonion/docs/debug/console.md +129 -0
  244. connectonion/docs/debug/eval-format.md +178 -0
  245. connectonion/docs/debug/eval.md +230 -0
  246. connectonion/docs/debug/exceptions.md +307 -0
  247. connectonion/docs/debug/log.md +117 -0
  248. connectonion/docs/debug/xray.md +215 -0
  249. connectonion/docs/design-decisions/001-choosing-input-method.md +202 -0
  250. connectonion/docs/design-decisions/002-choosing-llm-function-name.md +202 -0
  251. connectonion/docs/design-decisions/003-choosing-trust-keyword.md +141 -0
  252. connectonion/docs/design-decisions/004-cli-create-flow.md +117 -0
  253. connectonion/docs/design-decisions/005-designing-agent-network-protocol.md +503 -0
  254. connectonion/docs/design-decisions/006-agent-address-format.md +305 -0
  255. connectonion/docs/design-decisions/007-authentication-backend-design.md +240 -0
  256. connectonion/docs/design-decisions/008-naming-is-hard.md +228 -0
  257. connectonion/docs/design-decisions/009-why-connect-function.md +167 -0
  258. connectonion/docs/design-decisions/010-cli-ux-progressive-disclosure.md +176 -0
  259. connectonion/docs/design-decisions/011-global-config-identity-management.md +357 -0
  260. connectonion/docs/design-decisions/012-tool-execution-separation.md +259 -0
  261. connectonion/docs/design-decisions/013-debug-and-logging-design.md +253 -0
  262. connectonion/docs/design-decisions/014-hook-system-design.md +510 -0
  263. connectonion/docs/design-decisions/015-interactive-auto-debug-design.md +837 -0
  264. connectonion/docs/design-decisions/016-why-no-zero-knowledge-proofs.md +358 -0
  265. connectonion/docs/design-decisions/017-session-logging-and-eval-format.md +120 -0
  266. connectonion/docs/design-decisions/018-event-api-naming.md +274 -0
  267. connectonion/docs/design-decisions/019-agent-lifecycle-design.md +655 -0
  268. connectonion/docs/design-decisions/020-trust-system-and-network-architecture.md +503 -0
  269. connectonion/docs/design-decisions/021-task-storage-jsonl-design.md +496 -0
  270. connectonion/docs/design-decisions/022-raw-asgi-implementation.md +273 -0
  271. connectonion/docs/examples.md +0 -0
  272. connectonion/docs/hook-system-options.md +364 -0
  273. connectonion/docs/integrations/README.md +12 -0
  274. connectonion/docs/integrations/auth.md +450 -0
  275. connectonion/docs/integrations/google.md +431 -0
  276. connectonion/docs/integrations/microsoft.md +370 -0
  277. connectonion/docs/network/README.md +14 -0
  278. connectonion/docs/network/connect.md +629 -0
  279. connectonion/docs/network/deploy.md +124 -0
  280. connectonion/docs/network/host.md +1087 -0
  281. connectonion/docs/network/io.md +538 -0
  282. connectonion/docs/network/protocol/agent-relay-protocol.md +495 -0
  283. connectonion/docs/network/protocol/announce-message.md +115 -0
  284. connectonion/docs/principles.md +124 -0
  285. connectonion/docs/quickstart.md +261 -0
  286. connectonion/docs/roadmap.md +81 -0
  287. connectonion/docs/templates/README.md +77 -0
  288. connectonion/docs/templates/meta-agent.md +152 -0
  289. connectonion/docs/templates/minimal.md +105 -0
  290. connectonion/docs/templates/playwright.md +130 -0
  291. connectonion/docs/templates/web-research.md +144 -0
  292. connectonion/docs/tui/README.md +95 -0
  293. connectonion/docs/tui/chat.md +181 -0
  294. connectonion/docs/tui/divider.md +63 -0
  295. connectonion/docs/tui/dropdown.md +83 -0
  296. connectonion/docs/tui/footer.md +44 -0
  297. connectonion/docs/tui/fuzzy.md +68 -0
  298. connectonion/docs/tui/input.md +84 -0
  299. connectonion/docs/tui/keys.md +77 -0
  300. connectonion/docs/tui/pick.md +71 -0
  301. connectonion/docs/tui/providers.md +89 -0
  302. connectonion/docs/tui/status_bar.md +67 -0
  303. connectonion/docs/useful_plugins/README.md +160 -0
  304. connectonion/docs/useful_plugins/calendar_plugin.md +68 -0
  305. connectonion/docs/useful_plugins/eval.md +89 -0
  306. connectonion/docs/useful_plugins/gmail_plugin.md +68 -0
  307. connectonion/docs/useful_plugins/image_result_formatter.md +74 -0
  308. connectonion/docs/useful_plugins/re_act.md +86 -0
  309. connectonion/docs/useful_plugins/shell_approval.md +69 -0
  310. connectonion/docs/useful_plugins/system_reminder.md +210 -0
  311. connectonion/docs/useful_plugins/tool_approval.md +139 -0
  312. connectonion/docs/useful_prompts/README.md +127 -0
  313. connectonion/docs/useful_prompts/coding_agent.md +214 -0
  314. connectonion/docs/useful_tools/README.md +81 -0
  315. connectonion/docs/useful_tools/ask_user.md +103 -0
  316. connectonion/docs/useful_tools/diff_writer.md +158 -0
  317. connectonion/docs/useful_tools/get_emails.md +519 -0
  318. connectonion/docs/useful_tools/gmail.md +155 -0
  319. connectonion/docs/useful_tools/google_calendar.md +126 -0
  320. connectonion/docs/useful_tools/memory.md +506 -0
  321. connectonion/docs/useful_tools/microsoft_calendar.md +126 -0
  322. connectonion/docs/useful_tools/outlook.md +140 -0
  323. connectonion/docs/useful_tools/send_email.md +423 -0
  324. connectonion/docs/useful_tools/shell.md +115 -0
  325. connectonion/docs/useful_tools/slash_command.md +116 -0
  326. connectonion/docs/useful_tools/terminal.md +115 -0
  327. connectonion/docs/useful_tools/todo_list.md +272 -0
  328. connectonion/docs/useful_tools/web_fetch.md +150 -0
  329. connectonion/docs/vibe-coding-guide.md +97 -0
  330. connectonion/docs/windows-support.md +258 -0
  331. connectonion/logger.py +3 -3
  332. connectonion/network/__init__.py +19 -6
  333. connectonion/network/asgi/__init__.py +81 -0
  334. connectonion/network/asgi/http.py +205 -0
  335. connectonion/network/asgi/websocket.py +217 -0
  336. connectonion/network/connect.py +232 -185
  337. connectonion/network/host/__init__.py +59 -0
  338. connectonion/network/host/auth.py +191 -0
  339. connectonion/network/host/routes.py +135 -0
  340. connectonion/network/host/server.py +289 -0
  341. connectonion/network/host/session.py +78 -0
  342. connectonion/network/io/__init__.py +21 -0
  343. connectonion/network/{connection.py → io/base.py} +17 -42
  344. connectonion/network/io/websocket.py +55 -0
  345. connectonion/network/relay.py +37 -16
  346. connectonion/network/trust/__init__.py +30 -0
  347. connectonion/network/trust/factory.py +138 -0
  348. connectonion/network/{trust_agents.py → trust/prompts.py} +3 -3
  349. connectonion/network/{trust_functions.py → trust/tools.py} +2 -2
  350. connectonion/prompt_files/__init__.py +11 -1
  351. connectonion/prompt_files/react_acknowledge.md +26 -0
  352. connectonion/prompts.py +10 -1
  353. connectonion/tui/chat.py +10 -1
  354. connectonion/tui/divider.py +10 -1
  355. connectonion/tui/dropdown.py +10 -1
  356. connectonion/tui/footer.py +8 -0
  357. connectonion/tui/fuzzy.py +11 -1
  358. connectonion/tui/input.py +118 -70
  359. connectonion/tui/keys.py +133 -6
  360. connectonion/tui/providers.py +11 -1
  361. connectonion/tui/status_bar.py +10 -1
  362. connectonion/useful_events_handlers/__init__.py +8 -0
  363. connectonion/useful_events_handlers/reflect.py +19 -4
  364. connectonion/useful_plugins/__init__.py +3 -1
  365. connectonion/useful_plugins/eval.py +2 -2
  366. connectonion/useful_plugins/gmail_plugin.py +3 -3
  367. connectonion/useful_plugins/image_result_formatter.py +3 -3
  368. connectonion/useful_plugins/re_act.py +114 -28
  369. connectonion/useful_plugins/shell_approval.py +2 -2
  370. connectonion/useful_plugins/system_reminder.py +103 -0
  371. connectonion/useful_plugins/tool_approval.py +233 -0
  372. connectonion/useful_plugins/ui_stream.py +18 -133
  373. connectonion/useful_prompts/README.md +61 -0
  374. connectonion/useful_prompts/__init__.py +45 -0
  375. connectonion/useful_prompts/coding_agent/README.md +106 -0
  376. connectonion/useful_prompts/coding_agent/assembler.py +123 -0
  377. connectonion/useful_prompts/coding_agent/prompts/main.md +227 -0
  378. connectonion/useful_prompts/coding_agent/prompts/tools/ask_user.md +61 -0
  379. connectonion/useful_prompts/coding_agent/prompts/tools/background.md +57 -0
  380. connectonion/useful_prompts/coding_agent/prompts/tools/edit.md +90 -0
  381. connectonion/useful_prompts/coding_agent/prompts/tools/glob.md +52 -0
  382. connectonion/useful_prompts/coding_agent/prompts/tools/grep.md +55 -0
  383. connectonion/useful_prompts/coding_agent/prompts/tools/plan_mode.md +80 -0
  384. connectonion/useful_prompts/coding_agent/prompts/tools/read.md +40 -0
  385. connectonion/useful_prompts/coding_agent/prompts/tools/shell.md +67 -0
  386. connectonion/useful_prompts/coding_agent/prompts/tools/task.md +51 -0
  387. connectonion/useful_prompts/coding_agent/prompts/tools/todo.md +139 -0
  388. connectonion/useful_prompts/coding_agent/prompts/tools/write.md +48 -0
  389. connectonion/useful_prompts/system-reminders/security-warning.md +14 -0
  390. connectonion/useful_prompts/system-reminders/test-reminder.md +11 -0
  391. connectonion/useful_tools/__init__.py +31 -4
  392. connectonion/useful_tools/ask_user.py +35 -0
  393. connectonion/useful_tools/bash.py +69 -0
  394. connectonion/useful_tools/diff_writer.py +186 -94
  395. connectonion/useful_tools/edit.py +102 -0
  396. connectonion/useful_tools/glob_files.py +97 -0
  397. connectonion/useful_tools/grep_files.py +171 -0
  398. connectonion/useful_tools/multi_edit.py +116 -0
  399. connectonion/useful_tools/read_file.py +73 -0
  400. connectonion/useful_tools/shell.py +50 -45
  401. connectonion/useful_tools/write_file.py +129 -0
  402. {connectonion-0.6.2.dist-info → connectonion-0.6.4.dist-info}/METADATA +10 -3
  403. connectonion-0.6.4.dist-info/RECORD +472 -0
  404. connectonion/network/asgi.py +0 -407
  405. connectonion/network/host.py +0 -616
  406. connectonion/network/trust.py +0 -166
  407. connectonion-0.6.2.dist-info/RECORD +0 -129
  408. /connectonion/cli/{docs → co_ai/prompts/connectonion}/connectonion.md +0 -0
  409. {connectonion-0.6.2.dist-info → connectonion-0.6.4.dist-info}/WHEEL +0 -0
  410. {connectonion-0.6.2.dist-info → connectonion-0.6.4.dist-info}/entry_points.txt +0 -0
@@ -1,20 +1,24 @@
1
1
  """
2
- Purpose: ReAct (Reasoning + Acting) plugin that adds planning and reflection to agent execution
2
+ Purpose: ReAct (Reasoning + Acting) plugin that adds intent recognition and reflection to agent execution
3
3
  LLM-Note:
4
- Dependencies: imports from [pathlib, typing, events.after_user_input, llm_do, useful_events_handlers.reflect] | imported by [useful_plugins/__init__.py] | uses prompt file [prompt_files/react_plan.md] | tested by [tests/unit/test_re_act_plugin.py]
5
- Data flow: after_user_input → plan_task() generates a plan using llm_do() stores in agent.current_session['plan'] → after_tools → reflect() from useful_events_handlers evaluates results → generates reflection for next step
6
- State/Effects: modifies agent.current_session['plan'] and ['expected'] | makes LLM calls for planning and reflection | no file I/O | no network besides LLM
7
- Integration: exposes re_act plugin list with [plan_task, reflect] event handlers | used via Agent(plugins=[re_act]) | works with eval plugin for debugging
8
- Performance: 1-2 LLM calls per turn (plan + reflect) | adds latency but improves agent reasoning
4
+ Dependencies: imports from [pathlib, typing, events.after_user_input, llm_do, useful_events_handlers.reflect] | imported by [useful_plugins/__init__.py] | uses prompt file [prompt_files/react_acknowledge.md] | tested by [tests/unit/test_re_act_plugin.py]
5
+ Data flow: after_user_input → acknowledge_request() → after_tools → reflect()
6
+ State/Effects: modifies agent.current_session['intent'] | makes LLM calls for intent, reflection | no file I/O
7
+ Integration: exposes re_act plugin list with [acknowledge_request, reflect] event handlers | used via Agent(plugins=[re_act])
8
+ Performance: 2 LLM calls per turn (intent + reflect) | adds latency but improves agent reasoning
9
9
  Errors: no explicit error handling | LLM failures propagate | silent skip if no user_prompt
10
10
 
11
11
  ReAct plugin - Reasoning and Acting pattern for AI agents.
12
12
 
13
- Implements the ReAct (Reason + Act) pattern:
14
- 1. After user input: Plan what to do
15
- 2. After tool execution: Reflect on results and plan next step
13
+ Implements a simplified ReAct pattern:
14
+ 1. After user input: Acknowledge request (show we understood)
15
+ 2. After tool execution: Reflect on results
16
16
 
17
- For evaluation/debugging, use the separate `eval` plugin.
17
+ Planning is left to the main agent - this plugin just adds intent recognition and reflection.
18
+
19
+ Trace kinds for frontend rendering:
20
+ - kind='intent' → Show as "Understanding..." card
21
+ - kind='reflect' → Show as "Reflecting..." card
18
22
 
19
23
  Usage:
20
24
  from connectonion import Agent
@@ -37,42 +41,124 @@ if TYPE_CHECKING:
37
41
  from ..core.agent import Agent
38
42
 
39
43
  # Prompts
40
- PLAN_PROMPT = Path(__file__).parent.parent / "prompt_files" / "react_plan.md"
44
+ ACKNOWLEDGE_PROMPT = Path(__file__).parent.parent / "prompt_files" / "react_acknowledge.md"
45
+
46
+
47
+ def _format_conversation(
48
+ messages: list,
49
+ max_tokens: int = 4000,
50
+ max_messages: int = 50,
51
+ ) -> str:
52
+ """Format conversation history with smart truncation.
53
+
54
+ Only truncates when context exceeds budget. Priorities:
55
+ 1. User messages: always kept full (important context)
56
+ 2. Recent assistant messages: kept longer
57
+ 3. Older assistant messages: truncated first
58
+
59
+ Args:
60
+ messages: List of message dicts with 'role' and 'content'
61
+ max_tokens: Approximate token budget (~4 chars per token)
62
+ max_messages: Max number of messages to consider
63
+ """
64
+ max_chars = max_tokens * 4 # ~4 chars per token approximation
65
+
66
+ recent = messages[-max_messages:] if len(messages) > max_messages else messages
67
+ if not recent:
68
+ return ""
69
+
70
+ # First pass: calculate total size with full messages
71
+ total_chars = sum(len(m.get('content', '')) for m in recent)
72
+
73
+ # If under budget, return everything full
74
+ if total_chars <= max_chars:
75
+ lines = []
76
+ for msg in recent:
77
+ role = msg.get('role', 'unknown')
78
+ content = msg.get('content', '')
79
+ if content:
80
+ lines.append(f"{role}: {content}")
81
+ return "\n".join(lines)
82
+
83
+ # Over budget: smart truncation
84
+ # User messages kept full, truncate assistant messages
85
+ user_chars = sum(len(m.get('content', '')) for m in recent if m.get('role') == 'user')
86
+ available_for_assistant = max_chars - user_chars
87
+
88
+ assistant_msgs = [m for m in recent if m.get('role') == 'assistant' and m.get('content')]
89
+ if not assistant_msgs:
90
+ return "\n".join(f"user: {m.get('content', '')}" for m in recent if m.get('role') == 'user')
91
+
92
+ # Distribute chars to assistant messages (more to recent ones)
93
+ n = len(assistant_msgs)
94
+ weights = [1 + (i / n) for i in range(n)] # older=1.0, recent=~2.0
95
+ total_weight = sum(weights)
96
+ char_budgets = [int(available_for_assistant * w / total_weight) for w in weights]
97
+
98
+ # Build output
99
+ lines = []
100
+ assistant_idx = 0
101
+ for msg in recent:
102
+ role = msg.get('role', 'unknown')
103
+ content = msg.get('content', '')
104
+ if not content:
105
+ continue
106
+
107
+ if role == 'user':
108
+ lines.append(f"user: {content}")
109
+ elif role == 'assistant':
110
+ budget = char_budgets[assistant_idx] if assistant_idx < len(char_budgets) else 200
111
+ assistant_idx += 1
112
+ if len(content) > budget:
113
+ content = content[:budget] + "..."
114
+ lines.append(f"assistant: {content}")
115
+
116
+ return "\n".join(lines)
41
117
 
42
118
 
43
119
  @after_user_input
44
- def plan_task(agent: 'Agent') -> None:
45
- """Plan the task after receiving user input."""
120
+ def acknowledge_request(agent: 'Agent') -> None:
121
+ """Immediately acknowledge the user's request to show we understood."""
46
122
  user_prompt = agent.current_session.get('user_prompt', '')
47
123
  if not user_prompt:
48
124
  return
49
125
 
50
- tool_names = agent.tools.names() if agent.tools else []
51
- tools_str = ", ".join(tool_names) if tool_names else "no tools"
126
+ # Include conversation history for context
127
+ messages = agent.current_session.get('messages', [])
128
+ conversation = _format_conversation(messages)
52
129
 
53
- prompt = f"""User request: {user_prompt}
130
+ prompt = f"""Conversation so far:
131
+ {conversation}
54
132
 
55
- Available tools: {tools_str}
133
+ Current user input: {user_prompt}
56
134
 
57
- Brief plan (1-2 sentences): what to do first?"""
135
+ Acknowledge this request (1-2 sentences):"""
58
136
 
59
- agent.logger.print("[dim]/planning...[/dim]")
137
+ model = "co/gemini-2.5-flash"
138
+ agent.logger.print(f"[dim]/understanding ({model})...[/dim]")
60
139
 
61
- plan = llm_do(
140
+ ack = llm_do(
62
141
  prompt,
63
- model="co/gemini-2.5-flash",
64
- temperature=0.2,
65
- system_prompt=PLAN_PROMPT
142
+ model=model,
143
+ temperature=0.3,
144
+ system_prompt=ACKNOWLEDGE_PROMPT
66
145
  )
67
146
 
68
- # Store plan as expected outcome (used by eval plugin if present)
69
- agent.current_session['expected'] = plan
147
+ agent.current_session['intent'] = ack
148
+
149
+ agent._record_trace({
150
+ 'type': 'thinking',
151
+ 'kind': 'intent',
152
+ 'content': ack,
153
+ })
70
154
 
155
+ # Add to messages so LLM sees the understanding
71
156
  agent.current_session['messages'].append({
72
157
  'role': 'assistant',
73
- 'content': f"💭 {plan}"
158
+ 'content': ack
74
159
  })
75
160
 
76
161
 
77
- # Bundle as plugin: plan (after_user_input) + reflect (after_tools)
78
- re_act = [plan_task, reflect]
162
+ # Bundle as plugin: acknowledge (after_user_input) + reflect (after_tools)
163
+ # Planning is handled by the main agent
164
+ re_act = [acknowledge_request, reflect]
@@ -105,9 +105,9 @@ def _check_approval(agent: 'Agent') -> None:
105
105
  if not pending:
106
106
  return
107
107
 
108
- # Only check bash/shell tools
108
+ # Only check bash/shell tools (including run_in_dir)
109
109
  tool_name = pending['name']
110
- if tool_name not in ('bash', 'shell', 'run'):
110
+ if tool_name not in ('bash', 'shell', 'run', 'run_in_dir'):
111
111
  return
112
112
 
113
113
  # Get command from arguments
@@ -0,0 +1,103 @@
1
+ """
2
+ System Reminder Plugin - Injects contextual guidance into tool results.
3
+
4
+ Usage:
5
+ from connectonion.useful_plugins import system_reminder
6
+ agent = Agent("assistant", plugins=[system_reminder])
7
+
8
+ To customize, use `co copy system_reminder` which copies both the plugin
9
+ and the prompt files to your project.
10
+ """
11
+
12
+ from pathlib import Path
13
+ import fnmatch
14
+ from typing import TYPE_CHECKING
15
+
16
+ from ..core.events import after_each_tool
17
+
18
+ if TYPE_CHECKING:
19
+ from ..core.agent import Agent
20
+
21
+ # Default reminders directory
22
+ REMINDERS_DIR = Path(__file__).parent.parent / "useful_prompts" / "system-reminders"
23
+
24
+
25
+ def _parse_frontmatter(text):
26
+ """Parse YAML frontmatter from markdown."""
27
+ if not text.startswith('---'):
28
+ return {}, text
29
+ parts = text.split('---', 2)
30
+ if len(parts) < 3:
31
+ return {}, text
32
+ import yaml
33
+ return yaml.safe_load(parts[1]) or {}, parts[2].strip()
34
+
35
+
36
+ def _load_reminders(reminders_dir):
37
+ """Load all .md reminder files from directory."""
38
+ reminders_dir = Path(reminders_dir)
39
+ if not reminders_dir.exists():
40
+ return {}
41
+ reminders = {}
42
+ for f in reminders_dir.glob("*.md"):
43
+ meta, body = _parse_frontmatter(f.read_text())
44
+ if meta.get('name'):
45
+ reminders[meta['name']] = {'content': body, 'triggers': meta.get('triggers', [])}
46
+ return reminders
47
+
48
+
49
+ def _matches_pattern(pattern, value):
50
+ """Check if value matches glob pattern(s)."""
51
+ if not pattern or not value:
52
+ return False
53
+ patterns = [pattern] if isinstance(pattern, str) else pattern
54
+ return any(fnmatch.fnmatch(value, p) for p in patterns)
55
+
56
+
57
+ def _find_reminder(reminders, tool_name, args):
58
+ """Find matching reminder content."""
59
+ for reminder in reminders.values():
60
+ for trigger in reminder['triggers']:
61
+ if trigger.get('tool') and trigger['tool'] != tool_name:
62
+ continue
63
+ if trigger.get('path_pattern'):
64
+ path = args.get('path') or args.get('file_path', '')
65
+ if not _matches_pattern(trigger['path_pattern'], path):
66
+ continue
67
+ if trigger.get('command_pattern'):
68
+ cmd = args.get('command') or args.get('cmd', '')
69
+ if not _matches_pattern(trigger['command_pattern'], cmd):
70
+ continue
71
+ # All conditions matched
72
+ content = reminder['content']
73
+ path = args.get('path') or args.get('file_path', '')
74
+ return content.replace('${file_path}', path).replace('${tool_name}', tool_name)
75
+ return None
76
+
77
+
78
+ # Load reminders once at import
79
+ _REMINDERS = _load_reminders(REMINDERS_DIR)
80
+
81
+
82
+ @after_each_tool
83
+ def inject_reminder(agent: 'Agent') -> None:
84
+ """Inject matching system reminder into tool result."""
85
+ trace = agent.current_session.get('trace', [])
86
+ messages = agent.current_session.get('messages', [])
87
+ if not trace or not messages:
88
+ return
89
+
90
+ last = trace[-1]
91
+ if last.get('type') != 'tool_result':
92
+ return
93
+
94
+ content = _find_reminder(_REMINDERS, last.get('name', ''), last.get('args', {}))
95
+ if content:
96
+ for msg in reversed(messages):
97
+ if msg.get('role') == 'tool':
98
+ msg['content'] = msg.get('content', '') + '\n\n' + content
99
+ break
100
+
101
+
102
+ # Export plugin
103
+ system_reminder = [inject_reminder]
@@ -0,0 +1,233 @@
1
+ """
2
+ Purpose: Web-based tool approval plugin - request user approval before dangerous tools
3
+ LLM-Note:
4
+ Dependencies: imports from [core/events.py] | imported by [useful_plugins/__init__.py] | tested by [tests/unit/test_tool_approval.py]
5
+ Data flow: before_each_tool fires → check if dangerous tool → io.send(approval_needed) → io.receive() blocks → approved: continue, rejected: raise ValueError
6
+ State/Effects: stores approved_tools in session for "session" scope approvals | blocks on io.receive() until client responds | logs all approval decisions via agent.logger
7
+ Integration: exposes tool_approval plugin list | uses agent.io for WebSocket communication | requires client to handle "approval_needed" events
8
+ Errors: raises ValueError on rejection (stops batch, feedback sent to LLM)
9
+
10
+ Tool Approval Plugin - Request client approval before executing dangerous tools.
11
+
12
+ WebSocket-only. Uses io.send/receive pattern:
13
+ 1. Sends {type: "approval_needed", tool, arguments} to client
14
+ 2. Blocks until client responds with {approved: bool, scope?, feedback?}
15
+ 3. If approved: execute tool (optionally save to session memory)
16
+ 4. If rejected: raise ValueError, stopping batch, LLM sees feedback
17
+
18
+ Tool Classification:
19
+ - SAFE_TOOLS: Read-only operations (read, glob, grep, etc.) - never need approval
20
+ - DANGEROUS_TOOLS: Write/execute operations (bash, write, edit, etc.) - always need approval
21
+ - Unknown tools: Treated as safe (no approval needed)
22
+
23
+ Session Memory:
24
+ - scope="once": Approve for this call only
25
+ - scope="session": Approve for rest of session (no re-prompting)
26
+
27
+ Rejection Behavior:
28
+ - Raises ValueError with user feedback
29
+ - Stops entire tool batch (remaining tools skipped)
30
+ - LLM receives error message and can adjust approach
31
+
32
+ Usage:
33
+ from connectonion import Agent
34
+ from connectonion.useful_plugins import tool_approval
35
+
36
+ agent = Agent("assistant", tools=[bash, write], plugins=[tool_approval])
37
+
38
+ Client Protocol:
39
+ # Receive from server:
40
+ {"type": "approval_needed", "tool": "bash", "arguments": {"command": "npm install"}}
41
+
42
+ # Send response:
43
+ {"approved": true, "scope": "session"} # Approve for session
44
+ {"approved": true, "scope": "once"} # Approve once
45
+ {"approved": false, "feedback": "Use yarn instead"} # Reject with feedback
46
+ """
47
+
48
+ from typing import TYPE_CHECKING
49
+
50
+ from ..core.events import before_each_tool
51
+
52
+ if TYPE_CHECKING:
53
+ from ..core.agent import Agent
54
+
55
+
56
+ # Tools that NEVER need approval (read-only, safe)
57
+ # These tools cannot modify system state or have external side effects.
58
+ # Add new read-only tools here to skip approval prompts.
59
+ SAFE_TOOLS = {
60
+ # File reading - read contents without modification
61
+ 'read', 'read_file',
62
+ # Search operations - find files/content without modification
63
+ 'glob', 'grep', 'search',
64
+ # Info operations - query metadata only
65
+ 'list_files', 'get_file_info',
66
+ # Agent operations - sub-agents handle their own approval
67
+ 'task',
68
+ # Documentation - load reference materials
69
+ 'load_guide',
70
+ # Planning - state management without side effects
71
+ 'enter_plan_mode', 'exit_plan_mode', 'write_plan',
72
+ # Task management - read-only task status
73
+ 'task_output',
74
+ # User interaction - prompts user, not system modification
75
+ 'ask_user',
76
+ }
77
+
78
+ # Tools that ALWAYS need approval (destructive/side-effects)
79
+ # These tools can modify files, execute code, or have external effects.
80
+ # User approval required before execution in web mode.
81
+ DANGEROUS_TOOLS = {
82
+ # Shell execution - arbitrary command execution
83
+ 'bash', 'shell', 'run', 'run_in_dir',
84
+ # File modification - write/edit file contents
85
+ 'write', 'edit', 'multi_edit',
86
+ # Background tasks - long-running command execution
87
+ 'run_background',
88
+ # Task control - terminate running processes
89
+ 'kill_task',
90
+ # External communication - send data outside system
91
+ 'send_email', 'post',
92
+ # Deletion - remove files/resources
93
+ 'delete', 'remove',
94
+ }
95
+
96
+
97
+ # Session state helpers for approval memory
98
+ # These functions manage the session['approval'] dict which tracks
99
+ # which tools have been approved for the current session.
100
+
101
+ def _init_approval_state(session: dict) -> None:
102
+ """Initialize approval state in session if not present.
103
+
104
+ Creates session['approval']['approved_tools'] dict for storing
105
+ tool approvals with scope='session'.
106
+ """
107
+ if 'approval' not in session:
108
+ session['approval'] = {
109
+ 'approved_tools': {}, # tool_name -> 'session'
110
+ }
111
+
112
+
113
+ def _is_approved_for_session(session: dict, tool_name: str) -> bool:
114
+ """Check if tool was approved for this session.
115
+
116
+ Returns True if user previously approved this tool with scope='session'.
117
+ """
118
+ approval = session.get('approval', {})
119
+ return approval.get('approved_tools', {}).get(tool_name) == 'session'
120
+
121
+
122
+ def _save_session_approval(session: dict, tool_name: str) -> None:
123
+ """Save tool as approved for this session.
124
+
125
+ Future calls to the same tool will skip approval prompts.
126
+ """
127
+ _init_approval_state(session)
128
+ session['approval']['approved_tools'][tool_name] = 'session'
129
+
130
+
131
+ def _log(agent: 'Agent', message: str, style: str = None) -> None:
132
+ """Log message via agent's logger if available.
133
+
134
+ Args:
135
+ agent: Agent instance
136
+ message: Message to log
137
+ style: Rich style string (e.g., "[green]", "[red]")
138
+ """
139
+ if hasattr(agent, 'logger') and agent.logger:
140
+ agent.logger.print(message, style)
141
+
142
+
143
+ @before_each_tool
144
+ def check_approval(agent: 'Agent') -> None:
145
+ """Check if tool needs approval and request from client.
146
+
147
+ Flow:
148
+ 1. Skip if no IO (not web mode)
149
+ 2. Skip if safe tool
150
+ 3. Skip if unknown tool (default: safe)
151
+ 4. Skip if already approved for session
152
+ 5. Send approval_needed, wait for response
153
+ 6. If approved: optionally save to session, continue
154
+ 7. If rejected: raise ValueError (stops batch)
155
+
156
+ Logging:
157
+ - Logs approval requests, approvals, and rejections
158
+ - Uses agent.logger.print() for terminal output
159
+
160
+ Raises:
161
+ ValueError: If user rejects the tool (includes feedback if provided)
162
+ """
163
+ # No IO = not web mode, skip
164
+ if not agent.io:
165
+ return
166
+
167
+ # Get pending tool info
168
+ pending = agent.current_session.get('pending_tool')
169
+ if not pending:
170
+ return
171
+
172
+ tool_name = pending['name']
173
+ tool_args = pending['arguments']
174
+
175
+ # Safe tools don't need approval
176
+ if tool_name in SAFE_TOOLS:
177
+ return
178
+
179
+ # Unknown tools (not in SAFE or DANGEROUS) are treated as safe
180
+ if tool_name not in DANGEROUS_TOOLS:
181
+ return
182
+
183
+ # Already approved for this session
184
+ if _is_approved_for_session(agent.current_session, tool_name):
185
+ _log(agent, f"[dim]⏭ {tool_name} (session-approved)[/dim]")
186
+ return
187
+
188
+ # Send approval request to client
189
+ agent.io.send({
190
+ 'type': 'approval_needed',
191
+ 'tool': tool_name,
192
+ 'arguments': tool_args,
193
+ })
194
+
195
+ # Wait for client response (BLOCKS)
196
+ response = agent.io.receive()
197
+
198
+ # Handle connection closed
199
+ if response.get('type') == 'io_closed':
200
+ _log(agent, f"[red]✗ {tool_name} - connection closed[/red]")
201
+ raise ValueError(f"Connection closed while waiting for approval of '{tool_name}'")
202
+
203
+ # Check approval
204
+ approved = response.get('approved', False)
205
+
206
+ if approved:
207
+ # Save to session if scope is "session"
208
+ scope = response.get('scope', 'once')
209
+ if scope == 'session':
210
+ _save_session_approval(agent.current_session, tool_name)
211
+ _log(agent, f"[green]✓ {tool_name} approved (session)[/green]")
212
+ else:
213
+ _log(agent, f"[green]✓ {tool_name} approved (once)[/green]")
214
+ # Continue to execute tool
215
+ return
216
+
217
+ # Rejected - raise ValueError to stop batch
218
+ feedback = response.get('feedback', '')
219
+ if feedback:
220
+ _log(agent, f"[red]✗ {tool_name} rejected: {feedback}[/red]")
221
+ else:
222
+ _log(agent, f"[red]✗ {tool_name} rejected[/red]")
223
+
224
+ error_msg = f"User rejected tool '{tool_name}'."
225
+ if feedback:
226
+ error_msg += f" Feedback: {feedback}"
227
+ raise ValueError(error_msg)
228
+
229
+
230
+ # Export as plugin (list of event handlers)
231
+ # Usage: Agent("name", plugins=[tool_approval])
232
+ # The plugin registers check_approval as a before_each_tool handler
233
+ tool_approval = [check_approval]