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
@@ -0,0 +1,191 @@
1
+ """
2
+ Purpose: Ed25519 signature verification and trust-based authentication for hosted agents
3
+ LLM-Note:
4
+ Dependencies: imports from [network/trust/, llm_do.py, nacl.signing] | imported by [network/host/routes.py, network/host/server.py] | tested by [tests/network/test_host_auth.py]
5
+ Data flow: receives request dict with {payload, from, signature} → extract_and_authenticate() verifies Ed25519 signature via verify_signature() using nacl → checks timestamp expiry (5 min window) → applies trust policy (open/careful/strict/custom) → optionally evaluates via trust agent → returns (prompt, identity, sig_valid, error)
6
+ State/Effects: reads trust settings from agent | calls trust agent for evaluation if custom policy | no persistent state
7
+ Integration: exposes verify_signature(payload, signature, public_key) → bool, extract_and_authenticate(data, trust, blacklist, whitelist, agent_address) → (prompt, identity, sig_valid, error), get_agent_address(agent) → str, is_custom_trust(trust) → bool | used by host() to enforce authentication on all requests
8
+ Performance: signature verification uses nacl (fast Ed25519) | 5 minute timestamp window prevents replay | whitelist bypass for trusted callers
9
+ Errors: returns error strings: "unauthorized: ...", "forbidden: ...", "rejected: ..." | does NOT raise exceptions (caller checks error)
10
+ Authentication and signature verification for hosted agents.
11
+ """
12
+
13
+ import hashlib
14
+ import json
15
+ import time
16
+
17
+ from ..trust import create_trust_agent, TRUST_LEVELS
18
+
19
+
20
+ # Signature expiry window (5 minutes)
21
+ SIGNATURE_EXPIRY_SECONDS = 300
22
+
23
+
24
+ def verify_signature(payload: dict, signature: str, public_key: str) -> bool:
25
+ """Verify Ed25519 signature.
26
+
27
+ Args:
28
+ payload: The payload that was signed
29
+ signature: Hex-encoded signature (with or without 0x prefix)
30
+ public_key: Hex-encoded public key (with or without 0x prefix)
31
+
32
+ Returns:
33
+ True if signature is valid, False otherwise
34
+ """
35
+ from nacl.signing import VerifyKey
36
+ from nacl.exceptions import BadSignatureError
37
+
38
+ # Remove 0x prefix if present
39
+ sig_hex = signature[2:] if signature.startswith("0x") else signature
40
+ key_hex = public_key[2:] if public_key.startswith("0x") else public_key
41
+
42
+ # Canonicalize payload (deterministic JSON)
43
+ canonical = json.dumps(payload, sort_keys=True, separators=(",", ":"))
44
+
45
+ try:
46
+ verify_key = VerifyKey(bytes.fromhex(key_hex))
47
+ verify_key.verify(canonical.encode(), bytes.fromhex(sig_hex))
48
+ return True
49
+ except (BadSignatureError, ValueError):
50
+ # BadSignatureError: invalid signature
51
+ # ValueError: invalid hex encoding
52
+ return False
53
+
54
+
55
+ def extract_and_authenticate(data: dict, trust, *, blacklist=None, whitelist=None, agent_address=None):
56
+ """Extract prompt and authenticate request.
57
+
58
+ ALL requests must be signed - this is a protocol requirement.
59
+
60
+ Required format (Ed25519 signed):
61
+ {
62
+ "payload": {"prompt": "...", "to": "0xAgentAddress", "timestamp": 123},
63
+ "from": "0xCallerPublicKey",
64
+ "signature": "0xEd25519Signature..."
65
+ }
66
+
67
+ Trust levels control additional policies AFTER signature verification:
68
+ - "open": Any valid signer allowed
69
+ - "careful": Warnings for unknown signers (default)
70
+ - "strict": Whitelist only
71
+ - Custom policy/Agent: LLM evaluation
72
+
73
+ Returns: (prompt, identity, sig_valid, error)
74
+ """
75
+ # Protocol requirement: ALL requests must be signed
76
+ if "payload" not in data or "signature" not in data:
77
+ return None, None, False, "unauthorized: signed request required"
78
+
79
+ # Verify signature (protocol level - always required)
80
+ prompt, identity, error = _authenticate_signed(
81
+ data, blacklist=blacklist, whitelist=whitelist, agent_address=agent_address
82
+ )
83
+ if error:
84
+ return prompt, identity, False, error
85
+
86
+ # Trust level: additional policies AFTER signature verification
87
+ if trust == "strict" and whitelist and identity not in whitelist:
88
+ return None, identity, True, "forbidden: not in whitelist"
89
+
90
+ # Custom trust policy/agent evaluation
91
+ if is_custom_trust(trust):
92
+ trust_agent = create_trust_agent(trust)
93
+ accepted, reason = evaluate_with_trust_agent(trust_agent, prompt, identity, True)
94
+ if not accepted:
95
+ return None, identity, True, f"rejected: {reason}"
96
+
97
+ return prompt, identity, True, None
98
+
99
+
100
+ def _authenticate_signed(data: dict, *, blacklist=None, whitelist=None, agent_address=None):
101
+ """Authenticate signed request with Ed25519 - ALWAYS REQUIRED.
102
+
103
+ Protocol-level signature verification. All requests must be signed.
104
+
105
+ Returns: (prompt, identity, error) - error is None on success
106
+ """
107
+ payload = data.get("payload", {})
108
+ identity = data.get("from")
109
+ signature = data.get("signature")
110
+
111
+ prompt = payload.get("prompt", "")
112
+ timestamp = payload.get("timestamp")
113
+ to_address = payload.get("to")
114
+
115
+ # Check blacklist first
116
+ if blacklist and identity in blacklist:
117
+ return None, identity, "forbidden: blacklisted"
118
+
119
+ # Check whitelist (bypass signature check - trusted caller)
120
+ if whitelist and identity in whitelist:
121
+ return prompt, identity, None
122
+
123
+ # Validate required fields
124
+ if not identity:
125
+ return None, None, "unauthorized: 'from' field required"
126
+ if not signature:
127
+ return None, identity, "unauthorized: signature required"
128
+ if not timestamp:
129
+ return None, identity, "unauthorized: timestamp required in payload"
130
+
131
+ # Check timestamp expiry (5 minute window)
132
+ now = time.time()
133
+ if abs(now - timestamp) > SIGNATURE_EXPIRY_SECONDS:
134
+ return None, identity, "unauthorized: signature expired"
135
+
136
+ # Optionally verify 'to' matches agent address
137
+ if agent_address and to_address and to_address != agent_address:
138
+ return None, identity, "unauthorized: wrong recipient"
139
+
140
+ # Verify signature
141
+ if not verify_signature(payload, signature, identity):
142
+ return None, identity, "unauthorized: invalid signature"
143
+
144
+ return prompt, identity, None
145
+
146
+
147
+ def get_agent_address(agent) -> str:
148
+ """Generate deterministic address from agent name."""
149
+ h = hashlib.sha256(agent.name.encode()).hexdigest()
150
+ return f"0x{h[:40]}"
151
+
152
+
153
+ def evaluate_with_trust_agent(trust_agent, prompt: str, identity: str, sig_valid: bool) -> tuple[bool, str]:
154
+ """Evaluate request using a custom trust agent (policy or Agent).
155
+
156
+ Only called when trust is a policy string or custom Agent - NOT for simple levels.
157
+
158
+ Args:
159
+ trust_agent: The trust agent created from policy or custom Agent
160
+ prompt: The request prompt
161
+ identity: The requester's identity/address
162
+ sig_valid: Whether the signature is valid
163
+
164
+ Returns:
165
+ (accepted, reason) tuple
166
+ """
167
+ from pydantic import BaseModel
168
+ from ...llm_do import llm_do
169
+
170
+ class TrustDecision(BaseModel):
171
+ accept: bool
172
+ reason: str
173
+
174
+ request_info = f"""Evaluate this request:
175
+ - prompt: {prompt[:200]}{'...' if len(prompt) > 200 else ''}
176
+ - identity: {identity or 'anonymous'}
177
+ - signature_valid: {sig_valid}"""
178
+
179
+ decision = llm_do(
180
+ request_info,
181
+ output=TrustDecision,
182
+ system_prompt=trust_agent.system_prompt,
183
+ )
184
+ return decision.accept, decision.reason
185
+
186
+
187
+ def is_custom_trust(trust) -> bool:
188
+ """Check if trust needs a custom agent (policy or Agent, not a level)."""
189
+ if not isinstance(trust, str):
190
+ return True # It's an Agent
191
+ return trust not in TRUST_LEVELS # It's a policy string
@@ -0,0 +1,135 @@
1
+ """
2
+ Purpose: HTTP/WebSocket route handlers for agent hosting endpoints
3
+ LLM-Note:
4
+ Dependencies: imports from [network/host/session.py, connectonion/__init__.py] | imported by [network/host/server.py, network/asgi/http.py, network/asgi/websocket.py] | tested by [tests/network/test_host_routes.py]
5
+ Data flow: receives HTTP request → input_handler() calls create_agent() for fresh instance → server generates session_id (new) or uses existing (continuation) → calls agent.input(prompt, session) → stores result in SessionStorage → returns {session_id, status, result, duration_ms, session}
6
+ State/Effects: reads/writes SessionStorage via storage.save()/get()/list() | factory creates fresh agent per request (prevents state bleeding) | writes session records with TTL expiry | session_id always server-generated
7
+ Integration: exposes input_handler(create_agent, storage, prompt, result_ttl, session, connection), session_handler(storage, session_id), sessions_handler(storage), health_handler(agent_name, start_time), info_handler(agent_metadata, trust), admin_logs_handler(agent_name), admin_sessions_handler() | used by server.py and ASGI adapters
8
+ Performance: factory creates fresh agent per request (thread-safe, no deep copy issues) | SessionStorage TTL auto-cleanup | session continuation via session dict (multi-turn conversations)
9
+ Errors: session_handler returns None if session_id not found | admin_logs_handler returns {"error": "..."} if log file missing
10
+ Route handlers for hosted agents.
11
+ """
12
+
13
+ import time
14
+ import uuid
15
+ from pathlib import Path
16
+ from typing import Callable
17
+
18
+ from .session import Session, SessionStorage
19
+
20
+
21
+ def input_handler(create_agent: Callable, storage: SessionStorage, prompt: str, result_ttl: int,
22
+ session: dict | None = None, connection=None) -> dict:
23
+ """POST /input (and WebSocket /ws)
24
+
25
+ Args:
26
+ create_agent: Factory function that returns a fresh Agent instance
27
+ storage: SessionStorage for persisting results
28
+ prompt: The user's prompt
29
+ result_ttl: How long to keep the result on server
30
+ session: Optional conversation session for continuation
31
+ connection: WebSocket connection for bidirectional I/O (None for HTTP)
32
+ """
33
+ agent = create_agent() # Fresh instance per request
34
+ agent.io = connection # WebSocket connection or None for HTTP
35
+ now = time.time()
36
+
37
+ # Server generates session_id (new session) or uses existing (continuation)
38
+ # NOTE: We mutate `session` dict here, but it's safe - the dict is created
39
+ # fresh from json.loads() per request, not shared anywhere.
40
+ session = session or {}
41
+ session_id = session.get('session_id') or str(uuid.uuid4())
42
+ session['session_id'] = session_id
43
+
44
+ # Create storage record
45
+ record = Session(
46
+ session_id=session_id,
47
+ status="running",
48
+ prompt=prompt,
49
+ created=now,
50
+ expires=now + result_ttl,
51
+ )
52
+ storage.save(record)
53
+
54
+ # TODO: If agent.input() throws, record stays "running" until TTL expires.
55
+ # This is acceptable: client gets 500 error, record expires naturally.
56
+ start = time.time()
57
+ result = agent.input(prompt, session=session)
58
+ duration_ms = int((time.time() - start) * 1000)
59
+
60
+ record.status = "done"
61
+ record.result = result
62
+ record.duration_ms = duration_ms
63
+ storage.save(record)
64
+
65
+ # Return result with updated session for client to continue conversation
66
+ return {
67
+ "session_id": session_id,
68
+ "status": "done",
69
+ "result": result,
70
+ "duration_ms": duration_ms,
71
+ "session": agent.current_session
72
+ }
73
+
74
+
75
+ def session_handler(storage: SessionStorage, session_id: str) -> dict | None:
76
+ """GET /sessions/{id}"""
77
+ session = storage.get(session_id)
78
+ return session.model_dump() if session else None
79
+
80
+
81
+ def sessions_handler(storage: SessionStorage) -> dict:
82
+ """GET /sessions"""
83
+ return {"sessions": [s.model_dump() for s in storage.list()]}
84
+
85
+
86
+ def health_handler(agent_name: str, start_time: float) -> dict:
87
+ """GET /health"""
88
+ return {"status": "healthy", "agent": agent_name, "uptime": int(time.time() - start_time)}
89
+
90
+
91
+ def info_handler(agent_metadata: dict, trust: str) -> dict:
92
+ """GET /info
93
+
94
+ Returns pre-extracted metadata - no agent creation needed.
95
+ """
96
+ from ... import __version__
97
+ return {
98
+ "name": agent_metadata["name"],
99
+ "address": agent_metadata["address"],
100
+ "tools": agent_metadata["tools"],
101
+ "trust": trust,
102
+ "version": __version__,
103
+ }
104
+
105
+
106
+ def admin_logs_handler(agent_name: str) -> dict:
107
+ """GET /admin/logs - return plain text activity log file."""
108
+ log_path = Path(f".co/logs/{agent_name}.log")
109
+ if log_path.exists():
110
+ return {"content": log_path.read_text()}
111
+ return {"error": "No logs found"}
112
+
113
+
114
+ def admin_sessions_handler() -> dict:
115
+ """GET /admin/sessions - return raw session YAML files as JSON.
116
+
117
+ Returns session files as-is (converted from YAML to JSON). Each session
118
+ contains: name, created, updated, total_cost, total_tokens, turns array.
119
+ Frontend handles the display logic.
120
+ """
121
+ import yaml
122
+ sessions_dir = Path(".co/evals")
123
+ if not sessions_dir.exists():
124
+ return {"sessions": []}
125
+
126
+ sessions = []
127
+ for session_file in sessions_dir.glob("*.yaml"):
128
+ with open(session_file) as f:
129
+ session_data = yaml.safe_load(f)
130
+ if session_data:
131
+ sessions.append(session_data)
132
+
133
+ # Sort by updated date descending (newest first)
134
+ sessions.sort(key=lambda s: s.get("updated", s.get("created", "")), reverse=True)
135
+ return {"sessions": sessions}
@@ -0,0 +1,289 @@
1
+ """
2
+ Purpose: Host agent as HTTP/WebSocket server with trust-based access control
3
+ LLM-Note:
4
+ Dependencies: imports from [network/asgi/, network/trust/, network/host/session.py, network/host/auth.py, network/host/routes.py] | imported by [network/__init__.py as host()] | tested by [tests/network/test_host.py]
5
+ Data flow: host(create_agent, port, trust) → _create_route_handlers() wraps all routes → asgi_create_app() creates FastAPI/Starlette app → uvicorn.run() starts server → each request calls create_agent() for fresh instance → executes via input_handler()/ws_input() → returns result + session | trust enforcement via extract_and_authenticate() at request boundary
6
+ State/Effects: starts HTTP server on specified port | creates .co/logs/ directory | stores sessions in SessionStorage (in-memory with TTL) | optionally announces to relay server | each request gets fresh agent instance (no state bleeding)
7
+ Integration: exposes host(create_agent, port=8000, trust=None, result_ttl=3600, relay_url=None) | creates ASGI app with routes: POST /input, GET /sessions, GET /sessions/{id}, GET /health, GET /info, WebSocket /ws, admin endpoints | trust accepts: "open"/"careful"/"strict" (level), markdown string (policy), or Agent (custom verifier)
8
+ Performance: factory pattern creates fresh agent per request (thread-safe) | SessionStorage auto-expires old results via TTL | WebSocket supports real-time bidirectional I/O | relay connection runs in background thread
9
+ Errors: trust errors return 401/403 via extract_and_authenticate() | missing sessions return None (404) | raises if port already in use
10
+ Host an agent over HTTP/WebSocket.
11
+
12
+ Trust enforcement happens at the host level, not in the Agent.
13
+ This provides clean separation: Agent does work, host controls access.
14
+
15
+ Trust parameter accepts three forms:
16
+ 1. Level (string): "open", "careful", "strict"
17
+ 2. Policy (string): Natural language or file path
18
+ 3. Agent: Custom Agent instance for verification
19
+
20
+ All forms create a trust agent behind the scenes.
21
+
22
+ Worker Isolation:
23
+ Each request calls the create_agent factory to get a fresh agent instance.
24
+ This ensures complete isolation - tools with state (like BrowserTool)
25
+ don't interfere between concurrent requests.
26
+ """
27
+
28
+ import os
29
+ from pathlib import Path
30
+ from typing import Callable, Union
31
+
32
+ from rich.console import Console
33
+ from rich.panel import Panel
34
+
35
+ from ..asgi import create_app as asgi_create_app
36
+ from ..trust import get_default_trust_level
37
+ from .session import SessionStorage
38
+ from .auth import extract_and_authenticate
39
+ from .routes import (
40
+ input_handler,
41
+ session_handler,
42
+ sessions_handler,
43
+ health_handler,
44
+ info_handler,
45
+ admin_logs_handler,
46
+ admin_sessions_handler,
47
+ )
48
+
49
+
50
+ def get_default_trust() -> str:
51
+ """Get default trust based on environment.
52
+
53
+ Returns:
54
+ Trust level based on CONNECTONION_ENV, defaults to 'careful'
55
+ """
56
+ return get_default_trust_level() or "careful"
57
+
58
+
59
+ def _extract_agent_metadata(create_agent: Callable) -> tuple[dict, object]:
60
+ """Extract metadata from a sample agent instance.
61
+
62
+ Returns:
63
+ (metadata dict, sample_agent) - sample_agent for additional extraction
64
+ """
65
+ sample = create_agent()
66
+ metadata = {
67
+ "name": sample.name,
68
+ "tools": sample.tools.names(),
69
+ }
70
+ return metadata, sample
71
+
72
+
73
+ def _create_route_handlers(create_agent: Callable, agent_metadata: dict, result_ttl: int):
74
+ """Create route handler dict for ASGI app.
75
+
76
+ Args:
77
+ create_agent: Factory function that returns a fresh Agent instance.
78
+ Called once per request for isolation.
79
+ agent_metadata: Pre-extracted metadata (name, tools, address) - avoids
80
+ creating agents for health/info endpoints.
81
+ result_ttl: How long to keep results on server in seconds
82
+ """
83
+ agent_name = agent_metadata["name"]
84
+
85
+ def handle_input(storage, prompt, session=None, connection=None):
86
+ return input_handler(create_agent, storage, prompt, result_ttl, session, connection)
87
+
88
+ def handle_ws_input(storage, prompt, connection, session=None):
89
+ return input_handler(create_agent, storage, prompt, result_ttl, session, connection)
90
+
91
+ def handle_health(start_time):
92
+ return health_handler(agent_name, start_time)
93
+
94
+ def handle_info(trust):
95
+ return info_handler(agent_metadata, trust)
96
+
97
+ def handle_admin_logs():
98
+ return admin_logs_handler(agent_name)
99
+
100
+ return {
101
+ "input": handle_input,
102
+ "session": session_handler,
103
+ "sessions": sessions_handler,
104
+ "health": handle_health,
105
+ "info": handle_info,
106
+ "auth": extract_and_authenticate,
107
+ "ws_input": handle_ws_input,
108
+ "admin_logs": handle_admin_logs,
109
+ "admin_sessions": admin_sessions_handler,
110
+ }
111
+
112
+
113
+ def _start_relay_background(create_agent: Callable, relay_url: str, addr_data: dict, agent_summary: str):
114
+ """Start relay connection in background thread.
115
+
116
+ The relay connection runs alongside the HTTP server, allowing the agent
117
+ to be discovered via P2P network while also serving HTTP requests.
118
+
119
+ Args:
120
+ create_agent: Factory function that returns a fresh Agent instance
121
+ relay_url: WebSocket URL for P2P relay
122
+ addr_data: Agent address data (public key, address)
123
+ agent_summary: Summary text for relay announcement
124
+ """
125
+ import asyncio
126
+ import threading
127
+ from .. import announce, relay
128
+
129
+ # Create ANNOUNCE message
130
+ announce_msg = announce.create_announce_message(addr_data, agent_summary, endpoints=[])
131
+
132
+ # Task handler - fresh instance for each request
133
+ # NOTE: agent.input() is synchronous inside async function, but this runs in
134
+ # a separate thread with its own event loop (not uvicorn's). Only blocks the
135
+ # relay thread, not the HTTP server. Could use asyncio.to_thread() if relay
136
+ # needs concurrent task handling or heartbeat during execution.
137
+ async def task_handler(prompt: str) -> str:
138
+ agent = create_agent()
139
+ return agent.input(prompt)
140
+
141
+ async def relay_loop():
142
+ ws = await relay.connect(relay_url)
143
+ await relay.serve_loop(ws, announce_msg, task_handler)
144
+
145
+ def run():
146
+ asyncio.run(relay_loop())
147
+
148
+ thread = threading.Thread(target=run, daemon=True, name="relay-connection")
149
+ thread.start()
150
+ return thread
151
+
152
+
153
+ def host(
154
+ create_agent: Callable,
155
+ port: int = None,
156
+ trust: Union[str, "Agent"] = "careful",
157
+ result_ttl: int = 86400,
158
+ workers: int = 1,
159
+ reload: bool = False,
160
+ *,
161
+ relay_url: str = "wss://oo.openonion.ai",
162
+ blacklist: list | None = None,
163
+ whitelist: list | None = None,
164
+ ):
165
+ """
166
+ Host an agent over HTTP/WebSocket with optional P2P relay discovery.
167
+
168
+ Each request calls create_agent() to get a fresh Agent instance.
169
+ This ensures complete isolation between concurrent requests.
170
+
171
+ State Control via Closure:
172
+ # Isolated state (default, safest) - create inside:
173
+ def create_agent():
174
+ browser = BrowserTool() # Fresh per request
175
+ return Agent("assistant", tools=[browser])
176
+
177
+ # Shared state (advanced) - create outside, capture via closure:
178
+ browser = BrowserTool() # Shared across all requests
179
+ def create_agent():
180
+ return Agent("assistant", tools=[browser])
181
+
182
+ Args:
183
+ create_agent: Function that returns a fresh Agent instance.
184
+ Called once per request. Define tools inside for isolation,
185
+ or outside for shared state.
186
+ port: HTTP port (default: PORT env var or 8000)
187
+ trust: Trust level, policy, or Agent:
188
+ - Level: "open", "careful", "strict"
189
+ - Policy: Natural language or file path
190
+ - Agent: Custom trust agent
191
+ result_ttl: How long to keep results on server in seconds (default 24h)
192
+ workers: Number of worker processes
193
+ reload: Auto-reload on code changes
194
+ relay_url: P2P relay URL (default: production relay)
195
+ - Set to None to disable relay
196
+ blacklist: Blocked identities
197
+ whitelist: Allowed identities
198
+
199
+ Endpoints:
200
+ POST /input - Submit prompt, get result
201
+ GET /sessions/{id} - Get session by ID
202
+ GET /sessions - List all sessions
203
+ GET /health - Health check
204
+ GET /info - Agent info
205
+ WS /ws - WebSocket
206
+ GET /logs - Activity log (requires OPENONION_API_KEY)
207
+ GET /logs/sessions - Activity sessions (requires OPENONION_API_KEY)
208
+ """
209
+ import uvicorn
210
+ from ... import address
211
+
212
+ # Use PORT env var if port not specified (for container deployments)
213
+ if port is None:
214
+ port = int(os.environ.get("PORT", 8000))
215
+
216
+ # Extract metadata once at startup
217
+ agent_metadata, sample = _extract_agent_metadata(create_agent)
218
+ agent_summary = sample.system_prompt[:1000] if sample.system_prompt else f"{agent_metadata['name']} agent"
219
+
220
+ # Load or generate agent identity
221
+ co_dir = Path.cwd() / '.co'
222
+ addr_data = address.load(co_dir)
223
+
224
+ if addr_data is None:
225
+ addr_data = address.generate()
226
+ address.save(addr_data, co_dir)
227
+
228
+ agent_metadata["address"] = addr_data['address']
229
+
230
+ storage = SessionStorage()
231
+ route_handlers = _create_route_handlers(create_agent, agent_metadata, result_ttl)
232
+ app = asgi_create_app(
233
+ route_handlers=route_handlers,
234
+ storage=storage,
235
+ trust=trust,
236
+ blacklist=blacklist,
237
+ whitelist=whitelist,
238
+ )
239
+
240
+ # Start relay connection in background (if enabled)
241
+ if relay_url:
242
+ _start_relay_background(create_agent, relay_url, addr_data, agent_summary)
243
+
244
+ # Display startup info
245
+ relay_status = f"[green]✓[/] {relay_url}" if relay_url else "[dim]disabled[/]"
246
+ Console().print(Panel(
247
+ f"[bold]POST[/] http://localhost:{port}/input\n"
248
+ f"[dim]GET /sessions/{{id}} · /sessions · /health · /info[/]\n"
249
+ f"[dim]WS ws://localhost:{port}/ws\n"
250
+ f"[dim]UI http://localhost:{port}/docs[/]\n\n"
251
+ f"[bold]Address:[/] {agent_metadata['address']}\n"
252
+ f"[bold]Relay:[/] {relay_status}",
253
+ title=f"[green]Agent '{agent_metadata['name']}'[/]"
254
+ ))
255
+
256
+ uvicorn.run(app, host="0.0.0.0", port=port, workers=workers, reload=reload, log_level="warning")
257
+
258
+
259
+ def create_app(create_agent: Callable, storage=None, trust="careful", result_ttl=86400, *, blacklist=None, whitelist=None):
260
+ """Create ASGI app for external uvicorn/gunicorn usage.
261
+
262
+ Each request calls create_agent() to get a fresh Agent instance.
263
+
264
+ Usage:
265
+ from connectonion.network import create_app
266
+
267
+ def create_agent():
268
+ return Agent("assistant", tools=[search])
269
+
270
+ app = create_app(create_agent)
271
+ # uvicorn myagent:app --workers 4
272
+ """
273
+ from .auth import get_agent_address
274
+
275
+ if storage is None:
276
+ storage = SessionStorage()
277
+
278
+ # Extract metadata once at startup
279
+ agent_metadata, sample = _extract_agent_metadata(create_agent)
280
+ agent_metadata["address"] = get_agent_address(sample)
281
+
282
+ route_handlers = _create_route_handlers(create_agent, agent_metadata, result_ttl)
283
+ return asgi_create_app(
284
+ route_handlers=route_handlers,
285
+ storage=storage,
286
+ trust=trust,
287
+ blacklist=blacklist,
288
+ whitelist=whitelist,
289
+ )