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
connectonion/network/host.py
DELETED
|
@@ -1,616 +0,0 @@
|
|
|
1
|
-
"""Host an agent over HTTP/WebSocket.
|
|
2
|
-
|
|
3
|
-
Trust enforcement happens at the host level, not in the Agent.
|
|
4
|
-
This provides clean separation: Agent does work, host controls access.
|
|
5
|
-
|
|
6
|
-
Trust parameter accepts three forms:
|
|
7
|
-
1. Level (string): "open", "careful", "strict"
|
|
8
|
-
2. Policy (string): Natural language or file path
|
|
9
|
-
3. Agent: Custom Agent instance for verification
|
|
10
|
-
|
|
11
|
-
All forms create a trust agent behind the scenes.
|
|
12
|
-
|
|
13
|
-
Worker Isolation:
|
|
14
|
-
Each request gets a fresh deep copy of the agent template.
|
|
15
|
-
This ensures complete isolation - tools with state (like BrowserTool)
|
|
16
|
-
don't interfere between concurrent requests.
|
|
17
|
-
"""
|
|
18
|
-
import copy
|
|
19
|
-
import hashlib
|
|
20
|
-
import json
|
|
21
|
-
import logging
|
|
22
|
-
import os
|
|
23
|
-
import time
|
|
24
|
-
import uuid
|
|
25
|
-
from pathlib import Path
|
|
26
|
-
from typing import Optional, Union
|
|
27
|
-
|
|
28
|
-
from pydantic import BaseModel
|
|
29
|
-
from rich.console import Console
|
|
30
|
-
from rich.panel import Panel
|
|
31
|
-
|
|
32
|
-
from .asgi import create_app as asgi_create_app
|
|
33
|
-
from .trust import create_trust_agent, get_default_trust_level, TRUST_LEVELS
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def get_default_trust() -> str:
|
|
37
|
-
"""Get default trust based on environment.
|
|
38
|
-
|
|
39
|
-
Returns:
|
|
40
|
-
Trust level based on CONNECTONION_ENV, defaults to 'careful'
|
|
41
|
-
"""
|
|
42
|
-
return get_default_trust_level() or "careful"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
# === Types ===
|
|
46
|
-
|
|
47
|
-
class Session(BaseModel):
|
|
48
|
-
"""Session record for tracking agent requests.
|
|
49
|
-
|
|
50
|
-
Uses Pydantic BaseModel for:
|
|
51
|
-
- Native JSON serialization via .model_dump()
|
|
52
|
-
- Type validation
|
|
53
|
-
- API response compatibility
|
|
54
|
-
"""
|
|
55
|
-
session_id: str
|
|
56
|
-
status: str
|
|
57
|
-
prompt: str
|
|
58
|
-
result: Optional[str] = None
|
|
59
|
-
created: Optional[float] = None
|
|
60
|
-
expires: Optional[float] = None
|
|
61
|
-
duration_ms: Optional[int] = None
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
# === Storage ===
|
|
65
|
-
|
|
66
|
-
class SessionStorage:
|
|
67
|
-
"""JSONL file storage. Append-only, last entry wins."""
|
|
68
|
-
|
|
69
|
-
def __init__(self, path: str = ".co/session_results.jsonl"):
|
|
70
|
-
self.path = Path(path)
|
|
71
|
-
self.path.parent.mkdir(exist_ok=True)
|
|
72
|
-
|
|
73
|
-
def save(self, session: Session):
|
|
74
|
-
with open(self.path, "a") as f:
|
|
75
|
-
f.write(session.model_dump_json() + "\n")
|
|
76
|
-
|
|
77
|
-
def get(self, session_id: str) -> Session | None:
|
|
78
|
-
if not self.path.exists():
|
|
79
|
-
return None
|
|
80
|
-
now = time.time()
|
|
81
|
-
with open(self.path) as f:
|
|
82
|
-
lines = f.readlines()
|
|
83
|
-
for line in reversed(lines):
|
|
84
|
-
data = json.loads(line)
|
|
85
|
-
if data["session_id"] == session_id:
|
|
86
|
-
session = Session(**data)
|
|
87
|
-
# Return if running or not expired
|
|
88
|
-
if session.status == "running" or not session.expires or session.expires > now:
|
|
89
|
-
return session
|
|
90
|
-
return None # Expired
|
|
91
|
-
return None
|
|
92
|
-
|
|
93
|
-
def list(self) -> list[Session]:
|
|
94
|
-
if not self.path.exists():
|
|
95
|
-
return []
|
|
96
|
-
sessions = {}
|
|
97
|
-
now = time.time()
|
|
98
|
-
with open(self.path) as f:
|
|
99
|
-
for line in f:
|
|
100
|
-
data = json.loads(line)
|
|
101
|
-
sessions[data["session_id"]] = Session(**data)
|
|
102
|
-
# Filter out expired non-running sessions
|
|
103
|
-
valid = [s for s in sessions.values()
|
|
104
|
-
if s.status == "running" or not s.expires or s.expires > now]
|
|
105
|
-
# Sort by created desc (newest first)
|
|
106
|
-
return sorted(valid, key=lambda s: s.created or 0, reverse=True)
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
# === Handlers (pure functions) ===
|
|
110
|
-
|
|
111
|
-
def input_handler(agent_template, storage: SessionStorage, prompt: str, result_ttl: int,
|
|
112
|
-
session: dict | None = None) -> dict:
|
|
113
|
-
"""POST /input
|
|
114
|
-
|
|
115
|
-
Args:
|
|
116
|
-
agent_template: The agent template (deep copied per request for isolation)
|
|
117
|
-
storage: SessionStorage for persisting results
|
|
118
|
-
prompt: The user's prompt
|
|
119
|
-
result_ttl: How long to keep the result on server
|
|
120
|
-
session: Optional conversation session for continuation
|
|
121
|
-
"""
|
|
122
|
-
agent = copy.deepcopy(agent_template)
|
|
123
|
-
now = time.time()
|
|
124
|
-
|
|
125
|
-
# Get or generate session_id
|
|
126
|
-
session_id = session.get('session_id') if session else None
|
|
127
|
-
if not session_id:
|
|
128
|
-
session_id = str(uuid.uuid4())
|
|
129
|
-
# If session was provided but missing session_id, add it
|
|
130
|
-
if session:
|
|
131
|
-
session['session_id'] = session_id
|
|
132
|
-
|
|
133
|
-
# Create storage record
|
|
134
|
-
record = Session(
|
|
135
|
-
session_id=session_id,
|
|
136
|
-
status="running",
|
|
137
|
-
prompt=prompt,
|
|
138
|
-
created=now,
|
|
139
|
-
expires=now + result_ttl,
|
|
140
|
-
)
|
|
141
|
-
storage.save(record)
|
|
142
|
-
|
|
143
|
-
start = time.time()
|
|
144
|
-
result = agent.input(prompt, session=session)
|
|
145
|
-
duration_ms = int((time.time() - start) * 1000)
|
|
146
|
-
|
|
147
|
-
record.status = "done"
|
|
148
|
-
record.result = result
|
|
149
|
-
record.duration_ms = duration_ms
|
|
150
|
-
storage.save(record)
|
|
151
|
-
|
|
152
|
-
# Return result with updated session for client to continue conversation
|
|
153
|
-
return {
|
|
154
|
-
"session_id": session_id,
|
|
155
|
-
"status": "done",
|
|
156
|
-
"result": result,
|
|
157
|
-
"duration_ms": duration_ms,
|
|
158
|
-
"session": agent.current_session
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
def session_handler(storage: SessionStorage, session_id: str) -> dict | None:
|
|
163
|
-
"""GET /sessions/{id}"""
|
|
164
|
-
session = storage.get(session_id)
|
|
165
|
-
return session.model_dump() if session else None
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
def sessions_handler(storage: SessionStorage) -> dict:
|
|
169
|
-
"""GET /sessions"""
|
|
170
|
-
return {"sessions": [s.model_dump() for s in storage.list()]}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
def health_handler(agent, start_time: float) -> dict:
|
|
174
|
-
"""GET /health"""
|
|
175
|
-
return {"status": "healthy", "agent": agent.name, "uptime": int(time.time() - start_time)}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
def info_handler(agent, trust: str) -> dict:
|
|
179
|
-
"""GET /info"""
|
|
180
|
-
from .. import __version__
|
|
181
|
-
tools = agent.tools.names() if hasattr(agent.tools, "names") else []
|
|
182
|
-
return {
|
|
183
|
-
"name": agent.name,
|
|
184
|
-
"address": get_agent_address(agent),
|
|
185
|
-
"tools": tools,
|
|
186
|
-
"trust": trust,
|
|
187
|
-
"version": __version__,
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
# === Auth Helpers ===
|
|
192
|
-
|
|
193
|
-
# Signature expiry window (5 minutes)
|
|
194
|
-
SIGNATURE_EXPIRY_SECONDS = 300
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
def verify_signature(payload: dict, signature: str, public_key: str) -> bool:
|
|
198
|
-
"""Verify Ed25519 signature.
|
|
199
|
-
|
|
200
|
-
Args:
|
|
201
|
-
payload: The payload that was signed
|
|
202
|
-
signature: Hex-encoded signature (with or without 0x prefix)
|
|
203
|
-
public_key: Hex-encoded public key (with or without 0x prefix)
|
|
204
|
-
|
|
205
|
-
Returns:
|
|
206
|
-
True if signature is valid, False otherwise
|
|
207
|
-
"""
|
|
208
|
-
from nacl.signing import VerifyKey
|
|
209
|
-
from nacl.exceptions import BadSignatureError
|
|
210
|
-
|
|
211
|
-
# Remove 0x prefix if present
|
|
212
|
-
sig_hex = signature[2:] if signature.startswith("0x") else signature
|
|
213
|
-
key_hex = public_key[2:] if public_key.startswith("0x") else public_key
|
|
214
|
-
|
|
215
|
-
# Canonicalize payload (deterministic JSON)
|
|
216
|
-
canonical = json.dumps(payload, sort_keys=True, separators=(",", ":"))
|
|
217
|
-
|
|
218
|
-
try:
|
|
219
|
-
verify_key = VerifyKey(bytes.fromhex(key_hex))
|
|
220
|
-
verify_key.verify(canonical.encode(), bytes.fromhex(sig_hex))
|
|
221
|
-
return True
|
|
222
|
-
except (BadSignatureError, ValueError):
|
|
223
|
-
# BadSignatureError: invalid signature
|
|
224
|
-
# ValueError: invalid hex encoding
|
|
225
|
-
return False
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
def extract_and_authenticate(data: dict, trust, *, blacklist=None, whitelist=None, agent_address=None):
|
|
229
|
-
"""Extract prompt and authenticate request.
|
|
230
|
-
|
|
231
|
-
ALL requests must be signed - this is a protocol requirement.
|
|
232
|
-
|
|
233
|
-
Required format (Ed25519 signed):
|
|
234
|
-
{
|
|
235
|
-
"payload": {"prompt": "...", "to": "0xAgentAddress", "timestamp": 123},
|
|
236
|
-
"from": "0xCallerPublicKey",
|
|
237
|
-
"signature": "0xEd25519Signature..."
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
Trust levels control additional policies AFTER signature verification:
|
|
241
|
-
- "open": Any valid signer allowed
|
|
242
|
-
- "careful": Warnings for unknown signers (default)
|
|
243
|
-
- "strict": Whitelist only
|
|
244
|
-
- Custom policy/Agent: LLM evaluation
|
|
245
|
-
|
|
246
|
-
Returns: (prompt, identity, sig_valid, error)
|
|
247
|
-
"""
|
|
248
|
-
# Protocol requirement: ALL requests must be signed
|
|
249
|
-
if "payload" not in data or "signature" not in data:
|
|
250
|
-
return None, None, False, "unauthorized: signed request required"
|
|
251
|
-
|
|
252
|
-
# Verify signature (protocol level - always required)
|
|
253
|
-
prompt, identity, error = _authenticate_signed(
|
|
254
|
-
data, blacklist=blacklist, whitelist=whitelist, agent_address=agent_address
|
|
255
|
-
)
|
|
256
|
-
if error:
|
|
257
|
-
return prompt, identity, False, error
|
|
258
|
-
|
|
259
|
-
# Trust level: additional policies AFTER signature verification
|
|
260
|
-
if trust == "strict" and whitelist and identity not in whitelist:
|
|
261
|
-
return None, identity, True, "forbidden: not in whitelist"
|
|
262
|
-
|
|
263
|
-
# Custom trust policy/agent evaluation
|
|
264
|
-
if is_custom_trust(trust):
|
|
265
|
-
trust_agent = create_trust_agent(trust)
|
|
266
|
-
accepted, reason = evaluate_with_trust_agent(trust_agent, prompt, identity, True)
|
|
267
|
-
if not accepted:
|
|
268
|
-
return None, identity, True, f"rejected: {reason}"
|
|
269
|
-
|
|
270
|
-
return prompt, identity, True, None
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
def _authenticate_signed(data: dict, *, blacklist=None, whitelist=None, agent_address=None):
|
|
274
|
-
"""Authenticate signed request with Ed25519 - ALWAYS REQUIRED.
|
|
275
|
-
|
|
276
|
-
Protocol-level signature verification. All requests must be signed.
|
|
277
|
-
|
|
278
|
-
Returns: (prompt, identity, error) - error is None on success
|
|
279
|
-
"""
|
|
280
|
-
payload = data.get("payload", {})
|
|
281
|
-
identity = data.get("from")
|
|
282
|
-
signature = data.get("signature")
|
|
283
|
-
|
|
284
|
-
prompt = payload.get("prompt", "")
|
|
285
|
-
timestamp = payload.get("timestamp")
|
|
286
|
-
to_address = payload.get("to")
|
|
287
|
-
|
|
288
|
-
# Check blacklist first
|
|
289
|
-
if blacklist and identity in blacklist:
|
|
290
|
-
return None, identity, "forbidden: blacklisted"
|
|
291
|
-
|
|
292
|
-
# Check whitelist (bypass signature check - trusted caller)
|
|
293
|
-
if whitelist and identity in whitelist:
|
|
294
|
-
return prompt, identity, None
|
|
295
|
-
|
|
296
|
-
# Validate required fields
|
|
297
|
-
if not identity:
|
|
298
|
-
return None, None, "unauthorized: 'from' field required"
|
|
299
|
-
if not signature:
|
|
300
|
-
return None, identity, "unauthorized: signature required"
|
|
301
|
-
if not timestamp:
|
|
302
|
-
return None, identity, "unauthorized: timestamp required in payload"
|
|
303
|
-
|
|
304
|
-
# Check timestamp expiry (5 minute window)
|
|
305
|
-
now = time.time()
|
|
306
|
-
if abs(now - timestamp) > SIGNATURE_EXPIRY_SECONDS:
|
|
307
|
-
return None, identity, "unauthorized: signature expired"
|
|
308
|
-
|
|
309
|
-
# Optionally verify 'to' matches agent address
|
|
310
|
-
if agent_address and to_address and to_address != agent_address:
|
|
311
|
-
return None, identity, "unauthorized: wrong recipient"
|
|
312
|
-
|
|
313
|
-
# Verify signature
|
|
314
|
-
if not verify_signature(payload, signature, identity):
|
|
315
|
-
return None, identity, "unauthorized: invalid signature"
|
|
316
|
-
|
|
317
|
-
return prompt, identity, None
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
def get_agent_address(agent) -> str:
|
|
321
|
-
"""Generate deterministic address from agent name."""
|
|
322
|
-
h = hashlib.sha256(agent.name.encode()).hexdigest()
|
|
323
|
-
return f"0x{h[:40]}"
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
def evaluate_with_trust_agent(trust_agent, prompt: str, identity: str, sig_valid: bool) -> tuple[bool, str]:
|
|
327
|
-
"""Evaluate request using a custom trust agent (policy or Agent).
|
|
328
|
-
|
|
329
|
-
Only called when trust is a policy string or custom Agent - NOT for simple levels.
|
|
330
|
-
|
|
331
|
-
Args:
|
|
332
|
-
trust_agent: The trust agent created from policy or custom Agent
|
|
333
|
-
prompt: The request prompt
|
|
334
|
-
identity: The requester's identity/address
|
|
335
|
-
sig_valid: Whether the signature is valid
|
|
336
|
-
|
|
337
|
-
Returns:
|
|
338
|
-
(accepted, reason) tuple
|
|
339
|
-
"""
|
|
340
|
-
from pydantic import BaseModel
|
|
341
|
-
from ..llm_do import llm_do
|
|
342
|
-
|
|
343
|
-
class TrustDecision(BaseModel):
|
|
344
|
-
accept: bool
|
|
345
|
-
reason: str
|
|
346
|
-
|
|
347
|
-
request_info = f"""Evaluate this request:
|
|
348
|
-
- prompt: {prompt[:200]}{'...' if len(prompt) > 200 else ''}
|
|
349
|
-
- identity: {identity or 'anonymous'}
|
|
350
|
-
- signature_valid: {sig_valid}"""
|
|
351
|
-
|
|
352
|
-
decision = llm_do(
|
|
353
|
-
request_info,
|
|
354
|
-
output=TrustDecision,
|
|
355
|
-
system_prompt=trust_agent.system_prompt,
|
|
356
|
-
)
|
|
357
|
-
return decision.accept, decision.reason
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
def is_custom_trust(trust) -> bool:
|
|
361
|
-
"""Check if trust needs a custom agent (policy or Agent, not a level)."""
|
|
362
|
-
if not isinstance(trust, str):
|
|
363
|
-
return True # It's an Agent
|
|
364
|
-
return trust not in TRUST_LEVELS # It's a policy string
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
# === Admin Handlers ===
|
|
368
|
-
|
|
369
|
-
def admin_logs_handler(agent_name: str) -> dict:
|
|
370
|
-
"""GET /admin/logs - return plain text activity log file."""
|
|
371
|
-
log_path = Path(f".co/logs/{agent_name}.log")
|
|
372
|
-
if log_path.exists():
|
|
373
|
-
return {"content": log_path.read_text()}
|
|
374
|
-
return {"error": "No logs found"}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
def admin_sessions_handler() -> dict:
|
|
378
|
-
"""GET /admin/sessions - return raw session YAML files as JSON.
|
|
379
|
-
|
|
380
|
-
Returns session files as-is (converted from YAML to JSON). Each session
|
|
381
|
-
contains: name, created, updated, total_cost, total_tokens, turns array.
|
|
382
|
-
Frontend handles the display logic.
|
|
383
|
-
"""
|
|
384
|
-
import yaml
|
|
385
|
-
sessions_dir = Path(".co/evals")
|
|
386
|
-
if not sessions_dir.exists():
|
|
387
|
-
return {"sessions": []}
|
|
388
|
-
|
|
389
|
-
sessions = []
|
|
390
|
-
for session_file in sessions_dir.glob("*.yaml"):
|
|
391
|
-
with open(session_file) as f:
|
|
392
|
-
session_data = yaml.safe_load(f)
|
|
393
|
-
if session_data:
|
|
394
|
-
sessions.append(session_data)
|
|
395
|
-
|
|
396
|
-
# Sort by updated date descending (newest first)
|
|
397
|
-
sessions.sort(key=lambda s: s.get("updated", s.get("created", "")), reverse=True)
|
|
398
|
-
return {"sessions": sessions}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
# === Entry Point ===
|
|
402
|
-
|
|
403
|
-
def _create_handlers(agent_template, result_ttl: int):
|
|
404
|
-
"""Create handler dict for ASGI app.
|
|
405
|
-
|
|
406
|
-
Args:
|
|
407
|
-
agent_template: Agent used as template (deep-copied per request for isolation)
|
|
408
|
-
result_ttl: How long to keep results on server in seconds
|
|
409
|
-
"""
|
|
410
|
-
def ws_input(prompt: str, connection) -> str:
|
|
411
|
-
"""WebSocket input with bidirectional connection support."""
|
|
412
|
-
agent_template.reset_conversation()
|
|
413
|
-
agent_template.connection = connection
|
|
414
|
-
return agent_template.input(prompt)
|
|
415
|
-
|
|
416
|
-
return {
|
|
417
|
-
"input": lambda storage, prompt, ttl, session=None: input_handler(agent_template, storage, prompt, ttl, session),
|
|
418
|
-
"session": session_handler,
|
|
419
|
-
"sessions": sessions_handler,
|
|
420
|
-
"health": lambda start_time: health_handler(agent_template, start_time),
|
|
421
|
-
"info": lambda trust: info_handler(agent_template, trust),
|
|
422
|
-
"auth": extract_and_authenticate,
|
|
423
|
-
"ws_input": ws_input,
|
|
424
|
-
# Admin endpoints (auth required via OPENONION_API_KEY)
|
|
425
|
-
"admin_logs": lambda: admin_logs_handler(agent_template.name),
|
|
426
|
-
"admin_sessions": admin_sessions_handler,
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
def _start_relay_background(agent_template, relay_url: str, addr_data: dict):
|
|
431
|
-
"""Start relay connection in background thread.
|
|
432
|
-
|
|
433
|
-
The relay connection runs alongside the HTTP server, allowing the agent
|
|
434
|
-
to be discovered via P2P network while also serving HTTP requests.
|
|
435
|
-
|
|
436
|
-
Args:
|
|
437
|
-
agent_template: Agent used as template (deep-copied per request for isolation)
|
|
438
|
-
relay_url: WebSocket URL for P2P relay
|
|
439
|
-
addr_data: Agent address data (public key, address)
|
|
440
|
-
"""
|
|
441
|
-
import asyncio
|
|
442
|
-
import threading
|
|
443
|
-
from . import announce, relay
|
|
444
|
-
|
|
445
|
-
# Create ANNOUNCE message
|
|
446
|
-
summary = agent_template.system_prompt[:1000] if agent_template.system_prompt else f"{agent_template.name} agent"
|
|
447
|
-
announce_msg = announce.create_announce_message(addr_data, summary, endpoints=[])
|
|
448
|
-
|
|
449
|
-
# Task handler - deep copy for each request
|
|
450
|
-
async def task_handler(prompt: str) -> str:
|
|
451
|
-
agent = copy.deepcopy(agent_template)
|
|
452
|
-
return agent.input(prompt)
|
|
453
|
-
|
|
454
|
-
async def relay_loop():
|
|
455
|
-
ws = await relay.connect(relay_url)
|
|
456
|
-
await relay.serve_loop(ws, announce_msg, task_handler)
|
|
457
|
-
|
|
458
|
-
def run():
|
|
459
|
-
asyncio.run(relay_loop())
|
|
460
|
-
|
|
461
|
-
thread = threading.Thread(target=run, daemon=True, name="relay-connection")
|
|
462
|
-
thread.start()
|
|
463
|
-
return thread
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
def host(
|
|
467
|
-
agent,
|
|
468
|
-
port: int = None,
|
|
469
|
-
trust: Union[str, "Agent"] = "careful",
|
|
470
|
-
result_ttl: int = 86400,
|
|
471
|
-
workers: int = 1,
|
|
472
|
-
reload: bool = False,
|
|
473
|
-
*,
|
|
474
|
-
relay_url: str = "wss://oo.openonion.ai/ws/announce",
|
|
475
|
-
blacklist: list | None = None,
|
|
476
|
-
whitelist: list | None = None,
|
|
477
|
-
):
|
|
478
|
-
"""
|
|
479
|
-
Host an agent over HTTP/WebSocket with optional P2P relay discovery.
|
|
480
|
-
|
|
481
|
-
The agent is used as a template - each request gets a fresh deep copy
|
|
482
|
-
for complete isolation. This ensures tools with state (like BrowserTool)
|
|
483
|
-
don't interfere between concurrent requests.
|
|
484
|
-
|
|
485
|
-
Args:
|
|
486
|
-
agent: Agent template (deep-copied per request for isolation)
|
|
487
|
-
port: HTTP port (default: PORT env var or 8000)
|
|
488
|
-
trust: Trust level, policy, or Agent:
|
|
489
|
-
- Level: "open", "careful", "strict"
|
|
490
|
-
- Policy: Natural language or file path
|
|
491
|
-
- Agent: Custom trust agent
|
|
492
|
-
result_ttl: How long to keep results on server in seconds (default 24h)
|
|
493
|
-
workers: Number of worker processes
|
|
494
|
-
reload: Auto-reload on code changes
|
|
495
|
-
relay_url: P2P relay URL (default: production relay)
|
|
496
|
-
- Set to None to disable relay
|
|
497
|
-
blacklist: Blocked identities
|
|
498
|
-
whitelist: Allowed identities
|
|
499
|
-
|
|
500
|
-
Endpoints:
|
|
501
|
-
POST /input - Submit prompt, get result
|
|
502
|
-
GET /sessions/{id} - Get session by ID
|
|
503
|
-
GET /sessions - List all sessions
|
|
504
|
-
GET /health - Health check
|
|
505
|
-
GET /info - Agent info
|
|
506
|
-
WS /ws - WebSocket
|
|
507
|
-
GET /logs - Activity log (requires OPENONION_API_KEY)
|
|
508
|
-
GET /logs/sessions - Activity sessions (requires OPENONION_API_KEY)
|
|
509
|
-
"""
|
|
510
|
-
import uvicorn
|
|
511
|
-
from .. import address
|
|
512
|
-
|
|
513
|
-
# Use PORT env var if port not specified (for container deployments)
|
|
514
|
-
if port is None:
|
|
515
|
-
port = int(os.environ.get("PORT", 8000))
|
|
516
|
-
|
|
517
|
-
# Load or generate agent identity
|
|
518
|
-
co_dir = Path.cwd() / '.co'
|
|
519
|
-
addr_data = address.load(co_dir)
|
|
520
|
-
|
|
521
|
-
if addr_data is None:
|
|
522
|
-
addr_data = address.generate()
|
|
523
|
-
address.save(addr_data, co_dir)
|
|
524
|
-
|
|
525
|
-
agent_address = addr_data['address']
|
|
526
|
-
|
|
527
|
-
storage = SessionStorage()
|
|
528
|
-
handlers = _create_handlers(agent, result_ttl)
|
|
529
|
-
app = asgi_create_app(
|
|
530
|
-
handlers=handlers,
|
|
531
|
-
storage=storage,
|
|
532
|
-
trust=trust,
|
|
533
|
-
result_ttl=result_ttl,
|
|
534
|
-
blacklist=blacklist,
|
|
535
|
-
whitelist=whitelist,
|
|
536
|
-
)
|
|
537
|
-
|
|
538
|
-
# Start relay connection in background (if enabled)
|
|
539
|
-
if relay_url:
|
|
540
|
-
_start_relay_background(agent, relay_url, addr_data)
|
|
541
|
-
|
|
542
|
-
# Display startup info
|
|
543
|
-
relay_status = f"[green]✓[/] {relay_url}" if relay_url else "[dim]disabled[/]"
|
|
544
|
-
Console().print(Panel(
|
|
545
|
-
f"[bold]POST[/] http://localhost:{port}/input\n"
|
|
546
|
-
f"[dim]GET /sessions/{{id}} · /sessions · /health · /info[/]\n"
|
|
547
|
-
f"[dim]WS ws://localhost:{port}/ws\n"
|
|
548
|
-
f"[dim]UI http://localhost:{port}/docs[/]\n\n"
|
|
549
|
-
f"[bold]Address:[/] {agent_address}\n"
|
|
550
|
-
f"[bold]Relay:[/] {relay_status}",
|
|
551
|
-
title=f"[green]Agent '{agent.name}'[/]"
|
|
552
|
-
))
|
|
553
|
-
|
|
554
|
-
uvicorn.run(app, host="0.0.0.0", port=port, workers=workers, reload=reload, log_level="warning")
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
# === Export ASGI App ===
|
|
558
|
-
|
|
559
|
-
def _make_app(agent, trust: Union[str, "Agent"] = "careful", result_ttl=86400, *, blacklist=None, whitelist=None):
|
|
560
|
-
"""Create ASGI app for external uvicorn/gunicorn usage.
|
|
561
|
-
|
|
562
|
-
The agent is used as a template - each request gets a fresh deep copy
|
|
563
|
-
for complete isolation.
|
|
564
|
-
|
|
565
|
-
Args:
|
|
566
|
-
agent: Agent template (deep-copied per request for isolation)
|
|
567
|
-
trust: Trust level, policy, or Agent
|
|
568
|
-
result_ttl: How long to keep results on server in seconds
|
|
569
|
-
blacklist: Blocked identities
|
|
570
|
-
whitelist: Allowed identities
|
|
571
|
-
|
|
572
|
-
Usage:
|
|
573
|
-
# myagent.py
|
|
574
|
-
from connectonion import Agent, host
|
|
575
|
-
agent = Agent("translator", tools=[translate])
|
|
576
|
-
app = host.app(agent)
|
|
577
|
-
|
|
578
|
-
# Then run with:
|
|
579
|
-
# uvicorn myagent:app --workers 4
|
|
580
|
-
"""
|
|
581
|
-
storage = SessionStorage()
|
|
582
|
-
handlers = _create_handlers(agent, result_ttl)
|
|
583
|
-
return asgi_create_app(
|
|
584
|
-
handlers=handlers,
|
|
585
|
-
storage=storage,
|
|
586
|
-
trust=trust,
|
|
587
|
-
result_ttl=result_ttl,
|
|
588
|
-
blacklist=blacklist,
|
|
589
|
-
whitelist=whitelist,
|
|
590
|
-
)
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
# Attach app factory to host function
|
|
594
|
-
host.app = _make_app
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
# Backward-compatible create_app (use host.app() for new code)
|
|
598
|
-
def create_app_compat(agent, storage, trust="careful", result_ttl=86400, *, blacklist=None, whitelist=None):
|
|
599
|
-
"""Create ASGI app (backward-compatible wrapper).
|
|
600
|
-
|
|
601
|
-
The agent is used as a template (deep-copied per request for isolation).
|
|
602
|
-
Prefer using host.app(agent) for new code.
|
|
603
|
-
"""
|
|
604
|
-
handlers = _create_handlers(agent, result_ttl)
|
|
605
|
-
return asgi_create_app(
|
|
606
|
-
handlers=handlers,
|
|
607
|
-
storage=storage,
|
|
608
|
-
trust=trust,
|
|
609
|
-
result_ttl=result_ttl,
|
|
610
|
-
blacklist=blacklist,
|
|
611
|
-
whitelist=whitelist,
|
|
612
|
-
)
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
# Re-export for backward compatibility
|
|
616
|
-
create_app = create_app_compat
|