connectonion 0.6.1__py3-none-any.whl → 0.6.3__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.
- connectonion/__init__.py +46 -9
- connectonion/cli/__init__.py +11 -1
- connectonion/cli/browser_agent/__init__.py +11 -1
- connectonion/cli/browser_agent/browser.py +95 -142
- connectonion/cli/browser_agent/element_finder.py +147 -0
- connectonion/cli/browser_agent/highlight_screenshot.py +182 -0
- connectonion/cli/browser_agent/prompt.md +188 -105
- connectonion/cli/browser_agent/prompts/element_matcher.md +59 -0
- connectonion/cli/browser_agent/prompts/form_filler.md +19 -0
- connectonion/cli/browser_agent/prompts/scroll_strategy.md +36 -0
- connectonion/cli/browser_agent/scripts/extract_elements.js +126 -0
- connectonion/cli/browser_agent/scroll.py +145 -0
- connectonion/cli/co_ai/__init__.py +6 -0
- connectonion/cli/co_ai/agent.py +87 -0
- connectonion/cli/co_ai/agents/__init__.py +5 -0
- connectonion/cli/co_ai/agents/registry.py +57 -0
- connectonion/cli/co_ai/commands/__init__.py +45 -0
- connectonion/cli/co_ai/commands/compact.py +173 -0
- connectonion/cli/co_ai/commands/cost.py +77 -0
- connectonion/cli/co_ai/commands/export.py +60 -0
- connectonion/cli/co_ai/commands/help.py +80 -0
- connectonion/cli/co_ai/commands/init.py +101 -0
- connectonion/cli/co_ai/commands/sessions.py +55 -0
- connectonion/cli/co_ai/commands/tasks.py +63 -0
- connectonion/cli/co_ai/commands/undo.py +103 -0
- connectonion/cli/co_ai/context.py +127 -0
- connectonion/cli/co_ai/main.py +52 -0
- connectonion/cli/co_ai/plugins/__init__.py +6 -0
- connectonion/cli/co_ai/plugins/reminder.py +76 -0
- connectonion/cli/co_ai/plugins/shell_approval.py +105 -0
- connectonion/cli/co_ai/prompts/agents/explore.md +79 -0
- connectonion/cli/co_ai/prompts/agents/plan.md +60 -0
- connectonion/cli/co_ai/prompts/assembler.py +303 -0
- connectonion/cli/{docs/co-vibecoding-principles-docs-contexts-all-in-one.md → co_ai/prompts/connectonion/README.md} +26 -0
- connectonion/cli/co_ai/prompts/connectonion/api.md +457 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/README.md +805 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/auth.md +46 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/browser.md +235 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/copy.md +184 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/create.md +335 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/init.md +431 -0
- connectonion/cli/co_ai/prompts/connectonion/co-directory-structure.md +214 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/agent.md +1078 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/events.md +816 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/llm_do.md +256 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/max_iterations.md +362 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/models.md +641 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/plugins.md +100 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/prompts.md +122 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/tools.md +512 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/transcribe.md +156 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/trust.md +291 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/README.md +18 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/auto_debug.md +1026 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/console.md +129 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/eval-format.md +178 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/eval.md +230 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/exceptions.md +307 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/log.md +117 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/xray.md +215 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/001-choosing-input-method.md +202 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/002-choosing-llm-function-name.md +202 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/003-choosing-trust-keyword.md +141 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/004-cli-create-flow.md +117 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/005-designing-agent-network-protocol.md +503 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/006-agent-address-format.md +305 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/007-authentication-backend-design.md +240 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/008-naming-is-hard.md +228 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/009-why-connect-function.md +167 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/010-cli-ux-progressive-disclosure.md +176 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/011-global-config-identity-management.md +357 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/012-tool-execution-separation.md +259 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/013-debug-and-logging-design.md +253 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/014-hook-system-design.md +510 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/015-interactive-auto-debug-design.md +837 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/016-why-no-zero-knowledge-proofs.md +358 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/017-session-logging-and-eval-format.md +120 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/018-event-api-naming.md +274 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/019-agent-lifecycle-design.md +655 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/020-trust-system-and-network-architecture.md +503 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/021-task-storage-jsonl-design.md +496 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/022-raw-asgi-implementation.md +273 -0
- connectonion/cli/co_ai/prompts/connectonion/examples/agent_reasoning.md +62 -0
- connectonion/cli/co_ai/prompts/connectonion/examples/atomic_tools.md +24 -0
- connectonion/cli/co_ai/prompts/connectonion/examples/load_guide.md +18 -0
- connectonion/cli/co_ai/prompts/connectonion/examples.md +0 -0
- connectonion/cli/co_ai/prompts/connectonion/hook-system-options.md +364 -0
- connectonion/cli/co_ai/prompts/connectonion/index.md +162 -0
- connectonion/cli/co_ai/prompts/connectonion/integrations/README.md +12 -0
- connectonion/cli/co_ai/prompts/connectonion/integrations/auth.md +450 -0
- connectonion/cli/co_ai/prompts/connectonion/integrations/google.md +431 -0
- connectonion/cli/co_ai/prompts/connectonion/integrations/microsoft.md +370 -0
- connectonion/cli/co_ai/prompts/connectonion/network/README.md +14 -0
- connectonion/cli/co_ai/prompts/connectonion/network/connect.md +543 -0
- connectonion/cli/co_ai/prompts/connectonion/network/connection.md +538 -0
- connectonion/cli/co_ai/prompts/connectonion/network/deploy.md +123 -0
- connectonion/cli/co_ai/prompts/connectonion/network/host.md +1049 -0
- connectonion/cli/co_ai/prompts/connectonion/network/protocol/agent-relay-protocol.md +495 -0
- connectonion/cli/co_ai/prompts/connectonion/network/protocol/announce-message.md +115 -0
- connectonion/cli/co_ai/prompts/connectonion/principles.md +124 -0
- connectonion/cli/co_ai/prompts/connectonion/quickstart.md +261 -0
- connectonion/cli/co_ai/prompts/connectonion/roadmap.md +81 -0
- connectonion/cli/co_ai/prompts/connectonion/templates/README.md +77 -0
- connectonion/cli/co_ai/prompts/connectonion/templates/meta-agent.md +152 -0
- connectonion/cli/co_ai/prompts/connectonion/templates/minimal.md +105 -0
- connectonion/cli/co_ai/prompts/connectonion/templates/playwright.md +130 -0
- connectonion/cli/co_ai/prompts/connectonion/templates/web-research.md +144 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/README.md +95 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/chat.md +181 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/divider.md +63 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/dropdown.md +83 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/footer.md +44 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/fuzzy.md +68 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/input.md +84 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/keys.md +77 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/pick.md +71 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/providers.md +89 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/status_bar.md +67 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/README.md +156 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/calendar_plugin.md +68 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/eval.md +89 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/gmail_plugin.md +68 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/image_result_formatter.md +74 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/re_act.md +86 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/shell_approval.md +69 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/README.md +81 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/diff_writer.md +138 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/get_emails.md +499 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/gmail.md +135 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/google_calendar.md +106 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/memory.md +486 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/microsoft_calendar.md +106 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/outlook.md +120 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/send_email.md +403 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/shell.md +95 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/slash_command.md +96 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/terminal.md +97 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/todo_list.md +252 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/web_fetch.md +130 -0
- connectonion/cli/co_ai/prompts/connectonion/vibe-coding-guide.md +97 -0
- connectonion/cli/co_ai/prompts/connectonion/windows-support.md +258 -0
- connectonion/cli/co_ai/prompts/main.md +247 -0
- connectonion/cli/co_ai/prompts/reminders/plan_mode.md +34 -0
- connectonion/cli/co_ai/prompts/summarization.md +55 -0
- connectonion/cli/co_ai/prompts/tools/ask_user.md +61 -0
- connectonion/cli/co_ai/prompts/tools/background.md +57 -0
- connectonion/cli/co_ai/prompts/tools/edit.md +90 -0
- connectonion/cli/co_ai/prompts/tools/glob.md +52 -0
- connectonion/cli/co_ai/prompts/tools/grep.md +55 -0
- connectonion/cli/co_ai/prompts/tools/plan_mode.md +80 -0
- connectonion/cli/co_ai/prompts/tools/read.md +40 -0
- connectonion/cli/co_ai/prompts/tools/shell.md +67 -0
- connectonion/cli/co_ai/prompts/tools/task.md +51 -0
- connectonion/cli/co_ai/prompts/tools/todo.md +139 -0
- connectonion/cli/co_ai/prompts/tools/write.md +47 -0
- connectonion/cli/co_ai/prompts/workflow.md +89 -0
- connectonion/cli/co_ai/reminders.py +159 -0
- connectonion/cli/co_ai/sessions.py +110 -0
- connectonion/cli/co_ai/skills/__init__.py +37 -0
- connectonion/cli/co_ai/skills/builtin/commit/SKILL.md +63 -0
- connectonion/cli/co_ai/skills/builtin/review-pr/SKILL.md +76 -0
- connectonion/cli/co_ai/skills/loader.py +166 -0
- connectonion/cli/co_ai/skills/tool.py +46 -0
- connectonion/cli/co_ai/tools/__init__.py +92 -0
- connectonion/cli/co_ai/tools/ask_user.py +35 -0
- connectonion/cli/co_ai/tools/background.py +201 -0
- connectonion/cli/co_ai/tools/diff_writer.py +291 -0
- connectonion/cli/co_ai/tools/edit.py +89 -0
- connectonion/cli/co_ai/tools/glob.py +84 -0
- connectonion/cli/co_ai/tools/grep.py +158 -0
- connectonion/cli/co_ai/tools/load_guide.py +23 -0
- connectonion/cli/co_ai/tools/multi_edit.py +116 -0
- connectonion/cli/co_ai/tools/plan_mode.py +172 -0
- connectonion/cli/co_ai/tools/read.py +67 -0
- connectonion/cli/co_ai/tools/task.py +59 -0
- connectonion/cli/co_ai/tools/todo_list.py +159 -0
- connectonion/cli/co_ai/tools/write.py +126 -0
- connectonion/cli/commands/__init__.py +11 -1
- connectonion/cli/commands/ai_commands.py +34 -0
- connectonion/cli/commands/copy_commands.py +55 -6
- connectonion/cli/commands/create.py +20 -17
- connectonion/cli/commands/init.py +19 -22
- connectonion/cli/commands/project_cmd_lib.py +15 -0
- connectonion/cli/main.py +11 -0
- connectonion/console.py +15 -1
- connectonion/core/__init__.py +10 -1
- connectonion/core/agent.py +37 -16
- connectonion/core/exceptions.py +74 -0
- connectonion/core/llm.py +54 -6
- connectonion/core/tool_executor.py +32 -31
- connectonion/core/tool_factory.py +47 -10
- connectonion/debug/__init__.py +10 -1
- connectonion/debug/debug_explainer/__init__.py +10 -1
- connectonion/debug/execution_analyzer/__init__.py +10 -1
- connectonion/debug/execution_analyzer/execution_analysis.py +5 -2
- connectonion/debug/runtime_inspector/__init__.py +10 -1
- connectonion/docs/.package-ignore +6 -0
- connectonion/docs/README.md +2036 -0
- connectonion/docs/api.md +457 -0
- connectonion/docs/archive/001-ai-agent-is-just-prompt-plus-function.md +249 -0
- connectonion/docs/archive/README.md +53 -0
- connectonion/docs/archive/archive/consolidation-plan.md +72 -0
- connectonion/docs/archive/archive/core-principles-extracted.md +239 -0
- connectonion/docs/archive/archive/master-principles.md +222 -0
- connectonion/docs/archive/archive/principles.md +293 -0
- connectonion/docs/archive/archive/simplicity-principles.md +221 -0
- connectonion/docs/archive/attack-defense-insights.md +410 -0
- connectonion/docs/archive/business-model.md +305 -0
- connectonion/docs/archive/core-principles-unified.md +190 -0
- connectonion/docs/archive/discussion-journey.md +178 -0
- connectonion/docs/archive/economic-analysis.md +323 -0
- connectonion/docs/archive/features/01-share-and-find.md +256 -0
- connectonion/docs/archive/features/02-agent-authentication.md +93 -0
- connectonion/docs/archive/features/03-test-before-trust.md +71 -0
- connectonion/docs/archive/features/06-reliability-and-offline.md +197 -0
- connectonion/docs/archive/features/README.md +46 -0
- connectonion/docs/archive/features-roadmap.md +247 -0
- connectonion/docs/archive/mcp-comparison-insights.md +215 -0
- connectonion/docs/archive/migration-strategy.md +571 -0
- connectonion/docs/archive/mini-whitepaper.md +293 -0
- connectonion/docs/archive/network-protocol.md +394 -0
- connectonion/docs/archive/semantic-revolution.md +367 -0
- connectonion/docs/archive/technical-architecture.md +453 -0
- connectonion/docs/archive/the-semantic-insight.md +207 -0
- connectonion/docs/archive/threat-model.md +164 -0
- connectonion/docs/cli/README.md +805 -0
- connectonion/docs/cli/auth.md +46 -0
- connectonion/docs/cli/browser.md +235 -0
- connectonion/docs/cli/copy.md +232 -0
- connectonion/docs/cli/create.md +335 -0
- connectonion/docs/cli/init.md +431 -0
- connectonion/docs/co-directory-structure.md +214 -0
- connectonion/docs/concepts/agent.md +1078 -0
- connectonion/docs/concepts/events.md +699 -0
- connectonion/docs/concepts/llm_do.md +256 -0
- connectonion/docs/concepts/max_iterations.md +362 -0
- connectonion/docs/concepts/models.md +641 -0
- connectonion/docs/concepts/plugins.md +100 -0
- connectonion/docs/concepts/prompts.md +122 -0
- connectonion/docs/concepts/session.md +428 -0
- connectonion/docs/concepts/tools.md +512 -0
- connectonion/docs/concepts/transcribe.md +156 -0
- connectonion/docs/concepts/trust.md +291 -0
- connectonion/docs/connectonion.md +1256 -0
- connectonion/docs/debug/README.md +18 -0
- connectonion/docs/debug/auto_debug.md +1026 -0
- connectonion/docs/debug/console.md +129 -0
- connectonion/docs/debug/eval-format.md +178 -0
- connectonion/docs/debug/eval.md +230 -0
- connectonion/docs/debug/exceptions.md +307 -0
- connectonion/docs/debug/log.md +117 -0
- connectonion/docs/debug/xray.md +215 -0
- connectonion/docs/design-decisions/001-choosing-input-method.md +202 -0
- connectonion/docs/design-decisions/002-choosing-llm-function-name.md +202 -0
- connectonion/docs/design-decisions/003-choosing-trust-keyword.md +141 -0
- connectonion/docs/design-decisions/004-cli-create-flow.md +117 -0
- connectonion/docs/design-decisions/005-designing-agent-network-protocol.md +503 -0
- connectonion/docs/design-decisions/006-agent-address-format.md +305 -0
- connectonion/docs/design-decisions/007-authentication-backend-design.md +240 -0
- connectonion/docs/design-decisions/008-naming-is-hard.md +228 -0
- connectonion/docs/design-decisions/009-why-connect-function.md +167 -0
- connectonion/docs/design-decisions/010-cli-ux-progressive-disclosure.md +176 -0
- connectonion/docs/design-decisions/011-global-config-identity-management.md +357 -0
- connectonion/docs/design-decisions/012-tool-execution-separation.md +259 -0
- connectonion/docs/design-decisions/013-debug-and-logging-design.md +253 -0
- connectonion/docs/design-decisions/014-hook-system-design.md +510 -0
- connectonion/docs/design-decisions/015-interactive-auto-debug-design.md +837 -0
- connectonion/docs/design-decisions/016-why-no-zero-knowledge-proofs.md +358 -0
- connectonion/docs/design-decisions/017-session-logging-and-eval-format.md +120 -0
- connectonion/docs/design-decisions/018-event-api-naming.md +274 -0
- connectonion/docs/design-decisions/019-agent-lifecycle-design.md +655 -0
- connectonion/docs/design-decisions/020-trust-system-and-network-architecture.md +503 -0
- connectonion/docs/design-decisions/021-task-storage-jsonl-design.md +496 -0
- connectonion/docs/design-decisions/022-raw-asgi-implementation.md +273 -0
- connectonion/docs/examples.md +0 -0
- connectonion/docs/hook-system-options.md +364 -0
- connectonion/docs/integrations/README.md +12 -0
- connectonion/docs/integrations/auth.md +450 -0
- connectonion/docs/integrations/google.md +431 -0
- connectonion/docs/integrations/microsoft.md +370 -0
- connectonion/docs/network/README.md +14 -0
- connectonion/docs/network/connect.md +629 -0
- connectonion/docs/network/deploy.md +124 -0
- connectonion/docs/network/host.md +1087 -0
- connectonion/docs/network/io.md +538 -0
- connectonion/docs/network/protocol/agent-relay-protocol.md +495 -0
- connectonion/docs/network/protocol/announce-message.md +115 -0
- connectonion/docs/principles.md +124 -0
- connectonion/docs/quickstart.md +261 -0
- connectonion/docs/roadmap.md +81 -0
- connectonion/docs/templates/README.md +77 -0
- connectonion/docs/templates/meta-agent.md +152 -0
- connectonion/docs/templates/minimal.md +105 -0
- connectonion/docs/templates/playwright.md +130 -0
- connectonion/docs/templates/web-research.md +144 -0
- connectonion/docs/tui/README.md +95 -0
- connectonion/docs/tui/chat.md +181 -0
- connectonion/docs/tui/divider.md +63 -0
- connectonion/docs/tui/dropdown.md +83 -0
- connectonion/docs/tui/footer.md +44 -0
- connectonion/docs/tui/fuzzy.md +68 -0
- connectonion/docs/tui/input.md +84 -0
- connectonion/docs/tui/keys.md +77 -0
- connectonion/docs/tui/pick.md +71 -0
- connectonion/docs/tui/providers.md +89 -0
- connectonion/docs/tui/status_bar.md +67 -0
- connectonion/docs/useful_plugins/README.md +160 -0
- connectonion/docs/useful_plugins/calendar_plugin.md +68 -0
- connectonion/docs/useful_plugins/eval.md +89 -0
- connectonion/docs/useful_plugins/gmail_plugin.md +68 -0
- connectonion/docs/useful_plugins/image_result_formatter.md +74 -0
- connectonion/docs/useful_plugins/re_act.md +86 -0
- connectonion/docs/useful_plugins/shell_approval.md +69 -0
- connectonion/docs/useful_plugins/system_reminder.md +210 -0
- connectonion/docs/useful_prompts/README.md +127 -0
- connectonion/docs/useful_prompts/coding_agent.md +214 -0
- connectonion/docs/useful_tools/README.md +81 -0
- connectonion/docs/useful_tools/ask_user.md +103 -0
- connectonion/docs/useful_tools/diff_writer.md +158 -0
- connectonion/docs/useful_tools/get_emails.md +519 -0
- connectonion/docs/useful_tools/gmail.md +155 -0
- connectonion/docs/useful_tools/google_calendar.md +126 -0
- connectonion/docs/useful_tools/memory.md +506 -0
- connectonion/docs/useful_tools/microsoft_calendar.md +126 -0
- connectonion/docs/useful_tools/outlook.md +140 -0
- connectonion/docs/useful_tools/send_email.md +423 -0
- connectonion/docs/useful_tools/shell.md +115 -0
- connectonion/docs/useful_tools/slash_command.md +116 -0
- connectonion/docs/useful_tools/terminal.md +115 -0
- connectonion/docs/useful_tools/todo_list.md +272 -0
- connectonion/docs/useful_tools/web_fetch.md +150 -0
- connectonion/docs/vibe-coding-guide.md +97 -0
- connectonion/docs/windows-support.md +258 -0
- connectonion/logger.py +3 -3
- connectonion/network/__init__.py +19 -6
- connectonion/network/asgi/__init__.py +81 -0
- connectonion/network/asgi/http.py +205 -0
- connectonion/network/asgi/websocket.py +217 -0
- connectonion/network/connect.py +232 -185
- connectonion/network/host/__init__.py +59 -0
- connectonion/network/host/auth.py +191 -0
- connectonion/network/host/routes.py +135 -0
- connectonion/network/host/server.py +289 -0
- connectonion/network/host/session.py +78 -0
- connectonion/network/io/__init__.py +21 -0
- connectonion/network/{connection.py → io/base.py} +17 -42
- connectonion/network/io/websocket.py +55 -0
- connectonion/network/relay.py +37 -16
- connectonion/network/trust/__init__.py +30 -0
- connectonion/network/trust/factory.py +138 -0
- connectonion/network/{trust_agents.py → trust/prompts.py} +3 -3
- connectonion/network/{trust_functions.py → trust/tools.py} +2 -2
- connectonion/prompt_files/__init__.py +11 -1
- connectonion/prompt_files/react_acknowledge.md +26 -0
- connectonion/prompts.py +10 -1
- connectonion/tui/chat.py +10 -1
- connectonion/tui/divider.py +10 -1
- connectonion/tui/dropdown.py +10 -1
- connectonion/tui/footer.py +8 -0
- connectonion/tui/fuzzy.py +11 -1
- connectonion/tui/input.py +118 -70
- connectonion/tui/keys.py +133 -6
- connectonion/tui/providers.py +11 -1
- connectonion/tui/status_bar.py +10 -1
- connectonion/useful_events_handlers/__init__.py +8 -0
- connectonion/useful_events_handlers/reflect.py +19 -4
- connectonion/useful_plugins/__init__.py +2 -1
- connectonion/useful_plugins/eval.py +2 -2
- connectonion/useful_plugins/gmail_plugin.py +3 -3
- connectonion/useful_plugins/image_result_formatter.py +3 -3
- connectonion/useful_plugins/re_act.py +114 -28
- connectonion/useful_plugins/shell_approval.py +2 -2
- connectonion/useful_plugins/system_reminder.py +103 -0
- connectonion/useful_plugins/ui_stream.py +18 -133
- connectonion/useful_prompts/README.md +61 -0
- connectonion/useful_prompts/__init__.py +45 -0
- connectonion/useful_prompts/coding_agent/README.md +106 -0
- connectonion/useful_prompts/coding_agent/assembler.py +123 -0
- connectonion/useful_prompts/coding_agent/prompts/main.md +227 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/ask_user.md +61 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/background.md +57 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/edit.md +90 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/glob.md +52 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/grep.md +55 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/plan_mode.md +80 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/read.md +40 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/shell.md +67 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/task.md +51 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/todo.md +139 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/write.md +48 -0
- connectonion/useful_prompts/system-reminders/security-warning.md +14 -0
- connectonion/useful_prompts/system-reminders/test-reminder.md +11 -0
- connectonion/useful_tools/__init__.py +31 -4
- connectonion/useful_tools/ask_user.py +35 -0
- connectonion/useful_tools/bash.py +69 -0
- connectonion/useful_tools/diff_writer.py +186 -94
- connectonion/useful_tools/edit.py +102 -0
- connectonion/useful_tools/glob_files.py +97 -0
- connectonion/useful_tools/grep_files.py +171 -0
- connectonion/useful_tools/multi_edit.py +116 -0
- connectonion/useful_tools/read_file.py +73 -0
- connectonion/useful_tools/shell.py +50 -45
- connectonion/useful_tools/write_file.py +129 -0
- {connectonion-0.6.1.dist-info → connectonion-0.6.3.dist-info}/METADATA +10 -3
- connectonion-0.6.3.dist-info/RECORD +469 -0
- connectonion/cli/browser_agent/scroll_strategies.py +0 -276
- connectonion/network/asgi.py +0 -407
- connectonion/network/host.py +0 -616
- connectonion/network/trust.py +0 -166
- connectonion-0.6.1.dist-info/RECORD +0 -123
- /connectonion/cli/{docs → co_ai/prompts/connectonion}/connectonion.md +0 -0
- {connectonion-0.6.1.dist-info → connectonion-0.6.3.dist-info}/WHEEL +0 -0
- {connectonion-0.6.1.dist-info → connectonion-0.6.3.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,699 @@
|
|
|
1
|
+
# Event System (on_events)
|
|
2
|
+
|
|
3
|
+
ConnectOnion's event system lets you hook into the agent lifecycle to add custom behavior like logging, performance monitoring, or adding reasoning steps between tool uses.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Quick Start (60 seconds)
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
from connectonion import Agent, after_llm
|
|
11
|
+
|
|
12
|
+
def log_llm_call(agent):
|
|
13
|
+
"""Log LLM calls"""
|
|
14
|
+
last_trace = agent.current_session['trace'][-1]
|
|
15
|
+
if last_trace['type'] == 'llm_call':
|
|
16
|
+
print(f"LLM call took {last_trace['duration_ms']:.0f}ms")
|
|
17
|
+
|
|
18
|
+
agent = Agent(
|
|
19
|
+
"assistant",
|
|
20
|
+
tools=[search],
|
|
21
|
+
on_events=[
|
|
22
|
+
after_llm(log_llm_call)
|
|
23
|
+
]
|
|
24
|
+
)
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Group multiple handlers:**
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
from connectonion import Agent, before_each_tool
|
|
31
|
+
|
|
32
|
+
def check_shell(agent):
|
|
33
|
+
...
|
|
34
|
+
|
|
35
|
+
def check_email(agent):
|
|
36
|
+
...
|
|
37
|
+
|
|
38
|
+
agent = Agent(
|
|
39
|
+
"assistant",
|
|
40
|
+
on_events=[
|
|
41
|
+
before_each_tool(check_shell, check_email), # both handlers for same event
|
|
42
|
+
]
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**That's it!** Your events run automatically at the right lifecycle points.
|
|
47
|
+
|
|
48
|
+
> **Note: Alternative Decorator Syntax**
|
|
49
|
+
>
|
|
50
|
+
> You can also use decorator syntax: `@before_each_tool` instead of `before_each_tool(fn)`.
|
|
51
|
+
> ```python
|
|
52
|
+
> @before_each_tool
|
|
53
|
+
> def check_shell(agent):
|
|
54
|
+
> ...
|
|
55
|
+
>
|
|
56
|
+
> on_events=[check_shell] # works!
|
|
57
|
+
> ```
|
|
58
|
+
> We recommend the wrapper style `before_each_tool(fn)` because it's easier for LLMs to understand when reading your code. But if you find decorators more elegant, feel free to use them.
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Event Types
|
|
63
|
+
|
|
64
|
+
| Event | When It Runs | Fires | Use For |
|
|
65
|
+
|-------|--------------|-------|---------|
|
|
66
|
+
| `after_user_input` | After user provides input | Once per turn | Add context, timestamps, initialize turn state |
|
|
67
|
+
| `before_llm` | Before each LLM call | Multiple per turn | Modify messages for each LLM call |
|
|
68
|
+
| `after_llm` | After LLM responds | Multiple per turn | Log LLM calls, analyze responses |
|
|
69
|
+
| `before_tools` | Before ALL tools in round | Once per round | Prepare shared context for all tools |
|
|
70
|
+
| `before_each_tool` | Before tool execution | Per tool call | Validate args, approval checks (no message changes!) |
|
|
71
|
+
| `after_each_tool` | After each tool completes | Per tool call | Log performance, side effects (no message changes!) |
|
|
72
|
+
| `after_tools` | After ALL tools in round | Once per round | Add reflection, **ONLY place safe to modify messages** |
|
|
73
|
+
| `on_error` | When tool fails | Per tool error | Custom error handling, retries |
|
|
74
|
+
| `on_complete` | After agent finishes | Once per input() | Metrics, cleanup, final summary |
|
|
75
|
+
|
|
76
|
+
> **Note on message injection:** Use `after_tools` (not `after_each_tool`) when adding messages to ensure compatibility with all LLM providers. Anthropic Claude requires tool results to immediately follow tool_calls.
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Your Event Function
|
|
81
|
+
|
|
82
|
+
**All events receive the `agent` instance:**
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
def my_event(agent):
|
|
86
|
+
# Access everything:
|
|
87
|
+
agent.current_session['messages'] # Full conversation
|
|
88
|
+
agent.current_session['trace'] # Execution history
|
|
89
|
+
agent.current_session['iteration'] # Current iteration (1-10)
|
|
90
|
+
agent.current_session['turn'] # Current turn number
|
|
91
|
+
agent.current_session['user_prompt'] # Current user input
|
|
92
|
+
|
|
93
|
+
# Only in before_each_tool events:
|
|
94
|
+
agent.current_session['pending_tool'] # Tool about to execute
|
|
95
|
+
# {'name': 'bash', 'arguments': {'command': 'ls'}, 'id': 'call_123'}
|
|
96
|
+
|
|
97
|
+
# Modify the agent:
|
|
98
|
+
agent.current_session['messages'].append({
|
|
99
|
+
'role': 'system',
|
|
100
|
+
'content': 'Added by my event!'
|
|
101
|
+
})
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
**What's in the trace?**
|
|
105
|
+
|
|
106
|
+
The most recent trace entry shows what just happened:
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
def my_event(agent):
|
|
110
|
+
trace = agent.current_session['trace'][-1]
|
|
111
|
+
|
|
112
|
+
# For user_input:
|
|
113
|
+
trace['type'] # 'user_input'
|
|
114
|
+
trace['content'] # "Search for Python"
|
|
115
|
+
trace['turn'] # 1
|
|
116
|
+
|
|
117
|
+
# For llm_call:
|
|
118
|
+
trace['type'] # 'llm_call'
|
|
119
|
+
trace['model'] # 'gpt-4o-mini'
|
|
120
|
+
trace['duration_ms'] # 234.5
|
|
121
|
+
trace['tool_calls_count'] # 2
|
|
122
|
+
trace['iteration'] # 1
|
|
123
|
+
|
|
124
|
+
# For tool_result:
|
|
125
|
+
trace['type'] # 'tool_result'
|
|
126
|
+
trace['name'] # 'search'
|
|
127
|
+
trace['args'] # {'query': 'Python'}
|
|
128
|
+
trace['result'] # "Python is a programming language..."
|
|
129
|
+
trace['status'] # 'success' | 'error' | 'not_found'
|
|
130
|
+
trace['timing_ms'] # 123.4
|
|
131
|
+
trace['call_id'] # 'call_abc123'
|
|
132
|
+
|
|
133
|
+
# For error status:
|
|
134
|
+
trace['error'] # "Division by zero"
|
|
135
|
+
trace['error_type'] # "ZeroDivisionError"
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
> See [Session](session.md) for complete trace documentation.
|
|
139
|
+
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## Examples
|
|
143
|
+
|
|
144
|
+
### Approve Dangerous Commands (before_each_tool)
|
|
145
|
+
|
|
146
|
+
Use `before_each_tool` to intercept and approve tool calls before execution:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
from connectonion import Agent, before_each_tool
|
|
150
|
+
|
|
151
|
+
def approve_dangerous_commands(agent):
|
|
152
|
+
"""Ask for approval before dangerous bash commands"""
|
|
153
|
+
pending = agent.current_session.get('pending_tool')
|
|
154
|
+
if not pending:
|
|
155
|
+
return
|
|
156
|
+
|
|
157
|
+
# Only check bash commands
|
|
158
|
+
if pending['name'] != 'bash':
|
|
159
|
+
return
|
|
160
|
+
|
|
161
|
+
command = pending['arguments'].get('command', '')
|
|
162
|
+
|
|
163
|
+
# Check for dangerous patterns
|
|
164
|
+
if 'rm ' in command or 'sudo ' in command:
|
|
165
|
+
print(f"\n⚠️ Dangerous command: {command}")
|
|
166
|
+
response = input("Execute? (y/N): ")
|
|
167
|
+
if response.lower() != 'y':
|
|
168
|
+
raise ValueError("Command rejected by user")
|
|
169
|
+
|
|
170
|
+
agent = Agent(
|
|
171
|
+
"assistant",
|
|
172
|
+
tools=[bash],
|
|
173
|
+
on_events=[before_each_tool(approve_dangerous_commands)]
|
|
174
|
+
)
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
**Note:** `pending_tool` is only available during `before_each_tool` events. It contains:
|
|
178
|
+
- `name`: Tool name (e.g., "bash")
|
|
179
|
+
- `arguments`: Tool arguments (e.g., `{'command': 'rm -rf /tmp'}`)
|
|
180
|
+
- `id`: Tool call ID
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
### Add Context Once Per Turn
|
|
185
|
+
|
|
186
|
+
Use `after_user_input` to add context that should only be set once per turn:
|
|
187
|
+
|
|
188
|
+
```python
|
|
189
|
+
from connectonion import Agent, after_user_input
|
|
190
|
+
from datetime import datetime
|
|
191
|
+
|
|
192
|
+
def add_timestamp(agent):
|
|
193
|
+
"""Add current time once when user provides input"""
|
|
194
|
+
agent.current_session['messages'].append({
|
|
195
|
+
'role': 'system',
|
|
196
|
+
'content': f'Current time: {datetime.now().strftime("%Y-%m-%d %H:%M:%S")}'
|
|
197
|
+
})
|
|
198
|
+
|
|
199
|
+
agent = Agent("assistant", tools=[search], on_events=[after_user_input(add_timestamp)])
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Add Reflection After Tools
|
|
203
|
+
|
|
204
|
+
Use `llm_do` to make the agent reflect on tool results and plan next steps. **Important:** Use `after_tools` when adding messages to ensure compatibility with all LLM providers:
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
from connectonion import Agent, after_tools, llm_do
|
|
208
|
+
|
|
209
|
+
def add_reflection(agent):
|
|
210
|
+
"""Add reasoning after all tools in a round complete"""
|
|
211
|
+
trace = agent.current_session['trace'][-1]
|
|
212
|
+
|
|
213
|
+
if trace['type'] == 'tool_result' and trace['status'] == 'success':
|
|
214
|
+
tool_name = trace['name']
|
|
215
|
+
tool_args = trace['args']
|
|
216
|
+
result = trace['result']
|
|
217
|
+
|
|
218
|
+
# Use llm_do to generate reflection
|
|
219
|
+
reflection_prompt = f"""
|
|
220
|
+
You just used the {tool_name} tool with arguments {tool_args}.
|
|
221
|
+
Result: {result[:200]}
|
|
222
|
+
|
|
223
|
+
Provide a brief reflection:
|
|
224
|
+
1. What did we learn?
|
|
225
|
+
2. What should we do next?
|
|
226
|
+
3. Are we making progress toward the goal?
|
|
227
|
+
"""
|
|
228
|
+
|
|
229
|
+
reflection = llm_do(
|
|
230
|
+
reflection_prompt,
|
|
231
|
+
system_prompt="You are a thoughtful analyst. Be concise.",
|
|
232
|
+
temperature=0.3
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
# Add reflection to conversation (safe in after_tools)
|
|
236
|
+
agent.current_session['messages'].append({
|
|
237
|
+
'role': 'assistant',
|
|
238
|
+
'content': f"🤔 Reflection: {reflection}"
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
print(f"💭 Reflection: {reflection[:100]}...")
|
|
242
|
+
|
|
243
|
+
agent = Agent(
|
|
244
|
+
"researcher",
|
|
245
|
+
tools=[search, analyze],
|
|
246
|
+
on_events=[after_tools(add_reflection)] # Use after_tools for message injection
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
# Now the agent will reflect after each round of tool use!
|
|
250
|
+
agent.input("Research the latest AI trends and analyze their impact")
|
|
251
|
+
# 💭 Reflection: We learned about transformer models. Next, we should analyze...
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
### Performance Monitoring
|
|
255
|
+
|
|
256
|
+
```python
|
|
257
|
+
from connectonion import Agent, after_llm, after_each_tool
|
|
258
|
+
|
|
259
|
+
def monitor_llm_performance(agent):
|
|
260
|
+
"""Track LLM call performance"""
|
|
261
|
+
trace = agent.current_session['trace'][-1]
|
|
262
|
+
if trace['type'] == 'llm_call':
|
|
263
|
+
duration = trace['duration_ms']
|
|
264
|
+
model = trace['model']
|
|
265
|
+
if duration > 5000: # More than 5 seconds
|
|
266
|
+
print(f"⚡ Slow LLM call: {model} took {duration/1000:.1f}s")
|
|
267
|
+
|
|
268
|
+
def monitor_tool_performance(agent):
|
|
269
|
+
"""Track slow tool executions"""
|
|
270
|
+
trace = agent.current_session['trace'][-1]
|
|
271
|
+
if trace['type'] == 'tool_result':
|
|
272
|
+
timing = trace.get('timing_ms', 0)
|
|
273
|
+
tool_name = trace['name']
|
|
274
|
+
|
|
275
|
+
if timing > 1000: # More than 1 second
|
|
276
|
+
print(f"⚡ Slow tool: {tool_name} took {timing:.0f}ms")
|
|
277
|
+
|
|
278
|
+
agent = Agent(
|
|
279
|
+
"assistant",
|
|
280
|
+
tools=[search],
|
|
281
|
+
on_events=[
|
|
282
|
+
after_llm(monitor_llm_performance),
|
|
283
|
+
after_each_tool(monitor_tool_performance) # per-tool monitoring
|
|
284
|
+
]
|
|
285
|
+
)
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Custom Error Handling
|
|
289
|
+
|
|
290
|
+
```python
|
|
291
|
+
from connectonion import Agent, on_error
|
|
292
|
+
|
|
293
|
+
def handle_tool_error(agent):
|
|
294
|
+
"""Log and handle tool failures"""
|
|
295
|
+
trace = agent.current_session['trace'][-1]
|
|
296
|
+
if trace['type'] == 'tool_result' and trace['status'] == 'error':
|
|
297
|
+
tool_name = trace['name']
|
|
298
|
+
error = trace.get('error', 'Unknown error')
|
|
299
|
+
error_type = trace.get('error_type', 'Unknown')
|
|
300
|
+
|
|
301
|
+
print(f"⚠️ {tool_name} failed with {error_type}: {error}")
|
|
302
|
+
|
|
303
|
+
# Could send to logging service, retry, etc.
|
|
304
|
+
# Note: If this event raises an exception, the agent stops
|
|
305
|
+
|
|
306
|
+
agent = Agent("assistant", tools=[search], on_events=[on_error(handle_tool_error)])
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Task Completion Handler (on_complete)
|
|
310
|
+
|
|
311
|
+
Use `on_complete` to run logic after the agent finishes a task:
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
from connectonion import Agent, on_complete
|
|
315
|
+
|
|
316
|
+
def log_completion(agent):
|
|
317
|
+
"""Log when task completes"""
|
|
318
|
+
trace = agent.current_session['trace']
|
|
319
|
+
|
|
320
|
+
llm_calls = sum(1 for t in trace if t['type'] == 'llm_call')
|
|
321
|
+
tool_calls = sum(1 for t in trace if t['type'] == 'tool_result')
|
|
322
|
+
errors = sum(1 for t in trace if t.get('status') == 'error')
|
|
323
|
+
|
|
324
|
+
print(f"✅ Task complete: {llm_calls} LLM calls, {tool_calls} tools, {errors} errors")
|
|
325
|
+
|
|
326
|
+
agent = Agent(
|
|
327
|
+
"assistant",
|
|
328
|
+
tools=[search],
|
|
329
|
+
on_events=[on_complete(log_completion)]
|
|
330
|
+
)
|
|
331
|
+
|
|
332
|
+
agent.input("Search for Python")
|
|
333
|
+
# ✅ Task complete: 2 LLM calls, 1 tools, 0 errors
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
**Use cases for `on_complete`:**
|
|
337
|
+
- Final metrics and statistics
|
|
338
|
+
- Cleanup temporary resources
|
|
339
|
+
- Send task completion notifications
|
|
340
|
+
- Log total execution time
|
|
341
|
+
- Update external systems
|
|
342
|
+
|
|
343
|
+
### Session Statistics
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
from connectonion import Agent, after_llm
|
|
347
|
+
|
|
348
|
+
def session_stats(agent):
|
|
349
|
+
"""Print session statistics after each LLM call"""
|
|
350
|
+
trace = agent.current_session['trace']
|
|
351
|
+
|
|
352
|
+
llm_calls = sum(1 for t in trace if t['type'] == 'llm_call')
|
|
353
|
+
tool_calls = sum(1 for t in trace if t['type'] == 'tool_result')
|
|
354
|
+
errors = sum(1 for t in trace if t.get('status') == 'error')
|
|
355
|
+
|
|
356
|
+
print(f"📊 Stats: {llm_calls} LLM calls | {tool_calls} tool calls | {errors} errors")
|
|
357
|
+
|
|
358
|
+
agent = Agent("assistant", tools=[search], on_events=[after_llm(session_stats)])
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Smart Tool Selection with Reflection
|
|
362
|
+
|
|
363
|
+
Help the agent think about which tool to use next:
|
|
364
|
+
|
|
365
|
+
```python
|
|
366
|
+
from connectonion import Agent, after_tools, llm_do
|
|
367
|
+
from pydantic import BaseModel
|
|
368
|
+
|
|
369
|
+
class ToolRecommendation(BaseModel):
|
|
370
|
+
next_tool: str
|
|
371
|
+
reasoning: str
|
|
372
|
+
confidence: float
|
|
373
|
+
|
|
374
|
+
def suggest_next_tool(agent):
|
|
375
|
+
"""Suggest which tool to use next based on current progress"""
|
|
376
|
+
trace = agent.current_session['trace'][-1]
|
|
377
|
+
|
|
378
|
+
if trace['type'] == 'tool_result' and trace['status'] == 'success':
|
|
379
|
+
tool_name = trace['name']
|
|
380
|
+
result = trace['result']
|
|
381
|
+
|
|
382
|
+
# Get list of available tools
|
|
383
|
+
available_tools = agent.list_tools()
|
|
384
|
+
|
|
385
|
+
suggestion_prompt = f"""
|
|
386
|
+
We just used: {tool_name}
|
|
387
|
+
Result: {result[:200]}
|
|
388
|
+
|
|
389
|
+
Available tools: {', '.join(available_tools)}
|
|
390
|
+
|
|
391
|
+
What tool should we use next and why?
|
|
392
|
+
"""
|
|
393
|
+
|
|
394
|
+
suggestion = llm_do(
|
|
395
|
+
suggestion_prompt,
|
|
396
|
+
output=ToolRecommendation,
|
|
397
|
+
system_prompt="You are a strategic planner. Consider the goal and current progress.",
|
|
398
|
+
temperature=0.2
|
|
399
|
+
)
|
|
400
|
+
|
|
401
|
+
# Add suggestion as a system message (safe in after_tools)
|
|
402
|
+
agent.current_session['messages'].append({
|
|
403
|
+
'role': 'system',
|
|
404
|
+
'content': f"Suggestion: Use {suggestion.next_tool}. {suggestion.reasoning}"
|
|
405
|
+
})
|
|
406
|
+
|
|
407
|
+
print(f"💡 Suggested next tool: {suggestion.next_tool} (confidence: {suggestion.confidence})")
|
|
408
|
+
|
|
409
|
+
agent = Agent(
|
|
410
|
+
"strategist",
|
|
411
|
+
tools=[search, analyze, summarize],
|
|
412
|
+
on_events=[after_tools(suggest_next_tool)] # Use after_tools for message injection
|
|
413
|
+
)
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
## Organizing Event Code
|
|
419
|
+
|
|
420
|
+
### Keep Each Function Focused
|
|
421
|
+
|
|
422
|
+
Each helper function should do one thing:
|
|
423
|
+
|
|
424
|
+
```python
|
|
425
|
+
# my_events.py
|
|
426
|
+
|
|
427
|
+
def log_llm_timing(agent):
|
|
428
|
+
"""Single job: Log LLM timing"""
|
|
429
|
+
trace = agent.current_session['trace'][-1]
|
|
430
|
+
if trace['type'] == 'llm_call':
|
|
431
|
+
duration = trace['duration_ms']
|
|
432
|
+
print(f"💬 LLM: {duration:.0f}ms")
|
|
433
|
+
|
|
434
|
+
def log_tool_timing(agent):
|
|
435
|
+
"""Single job: Log tool timing"""
|
|
436
|
+
trace = agent.current_session['trace'][-1]
|
|
437
|
+
if trace['type'] == 'tool_execution':
|
|
438
|
+
timing = trace['timing']
|
|
439
|
+
print(f"🔧 Tool: {timing:.0f}ms")
|
|
440
|
+
|
|
441
|
+
def add_reflection(agent):
|
|
442
|
+
"""Single job: Add reflection after tools"""
|
|
443
|
+
from connectonion import llm_do
|
|
444
|
+
|
|
445
|
+
trace = agent.current_session['trace'][-1]
|
|
446
|
+
if trace['type'] == 'tool_result' and trace['status'] == 'success':
|
|
447
|
+
tool_name = trace['name']
|
|
448
|
+
result = trace['result']
|
|
449
|
+
|
|
450
|
+
# Use llm_do for quick reflection
|
|
451
|
+
reflection = llm_do(
|
|
452
|
+
f"Tool: {tool_name}\nResult: {result[:200]}\n\nWhat did we learn? What's next?",
|
|
453
|
+
system_prompt="You are concise and strategic.",
|
|
454
|
+
temperature=0.3
|
|
455
|
+
)
|
|
456
|
+
|
|
457
|
+
# Add to conversation
|
|
458
|
+
agent.current_session['messages'].append({
|
|
459
|
+
'role': 'assistant',
|
|
460
|
+
'content': f"💭 {reflection}"
|
|
461
|
+
})
|
|
462
|
+
|
|
463
|
+
def suggest_next_action(agent):
|
|
464
|
+
"""Suggest what to do next"""
|
|
465
|
+
trace = agent.current_session['trace'][-1]
|
|
466
|
+
|
|
467
|
+
if trace['type'] == 'tool_result':
|
|
468
|
+
available_tools = agent.list_tools()
|
|
469
|
+
|
|
470
|
+
suggestion = llm_do(
|
|
471
|
+
f"We just used {trace['name']}. Available tools: {available_tools}. What next?",
|
|
472
|
+
system_prompt="Be strategic and brief.",
|
|
473
|
+
temperature=0.2
|
|
474
|
+
)
|
|
475
|
+
|
|
476
|
+
print(f"💡 Suggestion: {suggestion}")
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
### Example: `events/handlers.py`
|
|
480
|
+
|
|
481
|
+
```python
|
|
482
|
+
"""Main event handlers - compose helpers here"""
|
|
483
|
+
from .logging import log_llm_call, log_tool_execution, log_errors
|
|
484
|
+
from .reflection import add_tool_reflection
|
|
485
|
+
|
|
486
|
+
def handle_after_llm(agent):
|
|
487
|
+
"""Handle all after_llm concerns"""
|
|
488
|
+
log_llm_call(agent) # 1. Log LLM calls
|
|
489
|
+
# Order is explicit and easy to modify
|
|
490
|
+
|
|
491
|
+
def handle_after_each_tool(agent):
|
|
492
|
+
"""Handle per-tool concerns (no message injection)"""
|
|
493
|
+
log_tool_execution(agent) # Log execution timing
|
|
494
|
+
# Clear execution order
|
|
495
|
+
|
|
496
|
+
def handle_after_tools(agent):
|
|
497
|
+
"""Handle batch concerns (safe for message injection)"""
|
|
498
|
+
add_tool_reflection(agent) # Add reflection after all tools
|
|
499
|
+
# Safe to add messages here
|
|
500
|
+
|
|
501
|
+
def handle_on_error(agent):
|
|
502
|
+
"""Handle all error concerns"""
|
|
503
|
+
log_errors(agent) # 1. Log the error
|
|
504
|
+
# Could add: send_alert(agent), retry_logic(agent), etc.
|
|
505
|
+
```
|
|
506
|
+
|
|
507
|
+
### Example: `events/__init__.py`
|
|
508
|
+
|
|
509
|
+
```python
|
|
510
|
+
"""Export event handlers for easy import"""
|
|
511
|
+
from .handlers import handle_after_llm, handle_after_each_tool, handle_after_tools, handle_on_error
|
|
512
|
+
|
|
513
|
+
__all__ = ['handle_after_llm', 'handle_after_each_tool', 'handle_after_tools', 'handle_on_error']
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
### Example: `main.py`
|
|
517
|
+
|
|
518
|
+
```python
|
|
519
|
+
"""Main agent - clean and focused"""
|
|
520
|
+
from connectonion import Agent, after_llm, after_each_tool, after_tools, on_error
|
|
521
|
+
from tools import search, calculate
|
|
522
|
+
from events import handle_after_llm, handle_after_each_tool, handle_after_tools, handle_on_error
|
|
523
|
+
|
|
524
|
+
agent = Agent(
|
|
525
|
+
"assistant",
|
|
526
|
+
tools=[search, calculate],
|
|
527
|
+
on_events=[
|
|
528
|
+
after_llm(handle_after_llm),
|
|
529
|
+
after_each_tool(handle_after_each_tool), # per-tool
|
|
530
|
+
after_tools(handle_after_tools), # batch
|
|
531
|
+
on_error(handle_on_error)
|
|
532
|
+
]
|
|
533
|
+
)
|
|
534
|
+
|
|
535
|
+
result = agent.input("Search for Python and calculate 2+2")
|
|
536
|
+
print(result)
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
**Benefits of this structure:**
|
|
540
|
+
- 🎯 **Clear separation** - tools, events, and main logic are separate
|
|
541
|
+
- 🔧 **Single responsibility** - each file/function has one job
|
|
542
|
+
- 🧪 **Easy to test** - test each helper independently
|
|
543
|
+
- 📖 **Easy to read** - anyone can understand the flow
|
|
544
|
+
- 🔄 **Reusable** - helpers can be used across different agents
|
|
545
|
+
- 🏗️ **Scalable** - easy to add new event helpers
|
|
546
|
+
|
|
547
|
+
---
|
|
548
|
+
|
|
549
|
+
## Simple vs Complex Projects
|
|
550
|
+
|
|
551
|
+
### For Simple Projects
|
|
552
|
+
|
|
553
|
+
Just put everything in one file:
|
|
554
|
+
|
|
555
|
+
```python
|
|
556
|
+
# simple_agent.py
|
|
557
|
+
from connectonion import Agent, after_llm
|
|
558
|
+
|
|
559
|
+
def log_llm(agent):
|
|
560
|
+
trace = agent.current_session['trace'][-1]
|
|
561
|
+
if trace['type'] == 'llm_call':
|
|
562
|
+
print(f"LLM: {trace['duration_ms']:.0f}ms")
|
|
563
|
+
|
|
564
|
+
agent = Agent("assistant", tools=[search], on_events=[after_llm(log_llm)])
|
|
565
|
+
```
|
|
566
|
+
|
|
567
|
+
### For Complex Projects
|
|
568
|
+
|
|
569
|
+
Use the folder structure above when you have:
|
|
570
|
+
- Multiple event handlers
|
|
571
|
+
- Multiple concerns (logging, reflection, analytics, etc.)
|
|
572
|
+
- Multiple agents sharing event logic
|
|
573
|
+
- Need for testing and maintenance
|
|
574
|
+
|
|
575
|
+
---
|
|
576
|
+
|
|
577
|
+
## Error Handling
|
|
578
|
+
|
|
579
|
+
**Events fail fast.** If your event raises an exception, the agent stops immediately:
|
|
580
|
+
|
|
581
|
+
```python
|
|
582
|
+
def strict_validator(agent):
|
|
583
|
+
trace = agent.current_session['trace'][-1]
|
|
584
|
+
if trace.get('status') == 'error':
|
|
585
|
+
raise ValueError("Tool execution failed - stopping agent")
|
|
586
|
+
# ☝️ This stops the entire agent
|
|
587
|
+
|
|
588
|
+
agent = Agent(
|
|
589
|
+
"assistant",
|
|
590
|
+
tools=[search],
|
|
591
|
+
on_events=[after_each_tool(strict_validator)] # per-tool validation
|
|
592
|
+
)
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
This ensures events are reliable and bugs don't get silently ignored.
|
|
596
|
+
|
|
597
|
+
---
|
|
598
|
+
|
|
599
|
+
## Reusable Events
|
|
600
|
+
|
|
601
|
+
Create event factories for common patterns:
|
|
602
|
+
|
|
603
|
+
```python
|
|
604
|
+
# my_events.py
|
|
605
|
+
from connectonion import after_llm
|
|
606
|
+
|
|
607
|
+
def llm_timer(threshold_ms=1000):
|
|
608
|
+
"""Factory function for LLM timing alerts"""
|
|
609
|
+
|
|
610
|
+
def check_timing(agent):
|
|
611
|
+
trace = agent.current_session['trace'][-1]
|
|
612
|
+
if trace['type'] == 'llm_call':
|
|
613
|
+
duration = trace['duration_ms']
|
|
614
|
+
if duration > threshold_ms:
|
|
615
|
+
print(f"⚠️ Slow LLM call: {duration:.0f}ms (threshold: {threshold_ms}ms)")
|
|
616
|
+
|
|
617
|
+
return check_timing # Return the function, will be wrapped by after_llm()
|
|
618
|
+
|
|
619
|
+
# Use it:
|
|
620
|
+
from my_events import llm_timer
|
|
621
|
+
from connectonion import after_llm
|
|
622
|
+
|
|
623
|
+
agent = Agent(
|
|
624
|
+
"assistant",
|
|
625
|
+
tools=[search],
|
|
626
|
+
on_events=[
|
|
627
|
+
after_llm(llm_timer(threshold_ms=2000))
|
|
628
|
+
]
|
|
629
|
+
)
|
|
630
|
+
```
|
|
631
|
+
|
|
632
|
+
---
|
|
633
|
+
|
|
634
|
+
## Testing Your Events
|
|
635
|
+
|
|
636
|
+
With single-responsibility functions, testing is easy:
|
|
637
|
+
|
|
638
|
+
```python
|
|
639
|
+
# tests/test_events.py
|
|
640
|
+
from unittest.mock import Mock
|
|
641
|
+
from events.logging import log_llm_call
|
|
642
|
+
from events.reflection import add_tool_reflection
|
|
643
|
+
|
|
644
|
+
def test_log_llm_call(capsys):
|
|
645
|
+
"""Test LLM logging"""
|
|
646
|
+
mock_agent = Mock()
|
|
647
|
+
mock_agent.current_session = {
|
|
648
|
+
'trace': [{'type': 'llm_call', 'model': 'gpt-4o-mini', 'duration_ms': 234.5}]
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
log_llm_call(mock_agent)
|
|
652
|
+
|
|
653
|
+
captured = capsys.readouterr()
|
|
654
|
+
assert "234ms" in captured.out
|
|
655
|
+
|
|
656
|
+
def test_add_tool_reflection():
|
|
657
|
+
"""Test reflection adding"""
|
|
658
|
+
mock_agent = Mock()
|
|
659
|
+
mock_agent.current_session = {
|
|
660
|
+
'trace': [{
|
|
661
|
+
'type': 'tool_execution',
|
|
662
|
+
'status': 'success',
|
|
663
|
+
'tool_name': 'search',
|
|
664
|
+
'result': 'Python is a programming language'
|
|
665
|
+
}],
|
|
666
|
+
'messages': []
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
add_tool_reflection(mock_agent)
|
|
670
|
+
|
|
671
|
+
# Check that a message was added
|
|
672
|
+
assert len(mock_agent.current_session['messages']) == 1
|
|
673
|
+
assert 'assistant' in mock_agent.current_session['messages'][0]['role']
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
---
|
|
677
|
+
|
|
678
|
+
## Common Use Cases
|
|
679
|
+
|
|
680
|
+
- **🧠 Reflection**: Add thinking steps between tool uses with `llm_do`
|
|
681
|
+
- **📝 Logging**: Custom logging to files, databases, or external services
|
|
682
|
+
- **🔍 Debugging**: Print detailed trace information
|
|
683
|
+
- **⚡ Performance**: Measure and optimize execution time
|
|
684
|
+
- **🛡️ Validation**: Enforce constraints on tool arguments or results
|
|
685
|
+
- **🔄 Retry Logic**: Automatically retry failed operations
|
|
686
|
+
- **📊 Analytics**: Send metrics to monitoring systems
|
|
687
|
+
- **🎯 Context Injection**: Add dynamic context once per turn with `after_user_input`
|
|
688
|
+
- **⏰ Timeouts**: Monitor and enforce time limits
|
|
689
|
+
- **🚨 Alerting**: Send notifications on errors or slow operations
|
|
690
|
+
- **💡 Strategy**: Suggest next tools or actions using `llm_do`
|
|
691
|
+
|
|
692
|
+
---
|
|
693
|
+
|
|
694
|
+
## What's Next?
|
|
695
|
+
|
|
696
|
+
- [llm_do](/llm_do) - Learn how to use `llm_do` for one-shot LLM calls in events
|
|
697
|
+
- [Examples](/examples) - See real-world event implementations
|
|
698
|
+
- [API Reference](/api/events) - Detailed API documentation
|
|
699
|
+
- [Trust System](/trust) - Learn about combining events with trust
|