connectonion 0.6.2__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 +13 -3
- connectonion/cli/browser_agent/element_finder.py +8 -0
- connectonion/cli/browser_agent/highlight_screenshot.py +9 -1
- connectonion/cli/browser_agent/scroll.py +8 -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.2.dist-info → connectonion-0.6.3.dist-info}/METADATA +10 -3
- connectonion-0.6.3.dist-info/RECORD +469 -0
- connectonion/network/asgi.py +0 -407
- connectonion/network/host.py +0 -616
- connectonion/network/trust.py +0 -166
- connectonion-0.6.2.dist-info/RECORD +0 -129
- /connectonion/cli/{docs → co_ai/prompts/connectonion}/connectonion.md +0 -0
- {connectonion-0.6.2.dist-info → connectonion-0.6.3.dist-info}/WHEEL +0 -0
- {connectonion-0.6.2.dist-info → connectonion-0.6.3.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
# The Great Address Debate: How We Chose Agent Identity for ConnectOnion
|
|
2
|
+
|
|
3
|
+
*September 3, 2025*
|
|
4
|
+
|
|
5
|
+
When building ConnectOnion, we faced a fundamental question: How should agents identify themselves? This seemingly simple decision led us down a fascinating rabbit hole of cryptography, user experience, and philosophical debates about simplicity. Here's the story of how we landed on our solution.
|
|
6
|
+
|
|
7
|
+
## The Journey Begins: What Even Is an Address?
|
|
8
|
+
|
|
9
|
+
We started with a simple need: agents in our network need unique identifiers to communicate. Like phone numbers or email addresses, but for AI agents.
|
|
10
|
+
|
|
11
|
+
Our first instinct? Look at what's already working. Ethereum uses addresses like `0x742d35Cc6634C0532925a3b844Bc454e3b6a5f8e`. Millions of people recognize this format. MetaMask has trained an entire generation. Surely we should just use that?
|
|
12
|
+
|
|
13
|
+
But then we dug deeper.
|
|
14
|
+
|
|
15
|
+
## The Cryptocurrency Temptation
|
|
16
|
+
|
|
17
|
+
The allure was strong:
|
|
18
|
+
- **Ethereum addresses** = instant payment capability
|
|
19
|
+
- **MetaMask** = ready-made wallet infrastructure
|
|
20
|
+
- **Web3** = built-in monetization for agents
|
|
21
|
+
|
|
22
|
+
We could have agents that earn money from day one! An agent completes a translation task, receives USDC. Beautiful.
|
|
23
|
+
|
|
24
|
+
But wait. Ethereum addresses are actually *hashes* of public keys. You can't recover the public key from the address. For our messaging protocol, this means every message needs to include the public key separately. That's 64 extra bytes per message. Forever.
|
|
25
|
+
|
|
26
|
+
## The Performance Reality Check
|
|
27
|
+
|
|
28
|
+
We ran the numbers on signature verification:
|
|
29
|
+
- **Ed25519**: 70,000 signatures/second
|
|
30
|
+
- **Secp256k1** (Ethereum): 20,000 signatures/second
|
|
31
|
+
|
|
32
|
+
For a network of AI agents exchanging thousands of messages, this 3x difference matters. Ed25519 is what Signal uses. What WhatsApp uses. What modern messaging systems use.
|
|
33
|
+
|
|
34
|
+
But Ed25519 isn't compatible with Ethereum. We had to choose: payments or performance?
|
|
35
|
+
|
|
36
|
+
Honestly? This hurt. We wanted both. We spent weeks trying to have our cake and eat it too. "What if we use both keys?" "What if we create a Merkle tree?" "What if we..."
|
|
37
|
+
|
|
38
|
+
Every solution made things more complex. And complex is where bugs live.
|
|
39
|
+
|
|
40
|
+
## The Solana Detour
|
|
41
|
+
|
|
42
|
+
"What about Solana?" we thought. They use Ed25519. They have Base58 addresses like `5FHneW46xGXNe3mZRwtFJNYiSqJ8RXkPmpnfWUrmTWVv`.
|
|
43
|
+
|
|
44
|
+
The good:
|
|
45
|
+
- Fast signatures
|
|
46
|
+
- The address IS the public key (no extra bytes needed)
|
|
47
|
+
- Growing ecosystem
|
|
48
|
+
|
|
49
|
+
The bad:
|
|
50
|
+
- Case-sensitive (type one letter wrong = funds lost)
|
|
51
|
+
- No error detection built-in
|
|
52
|
+
- MetaMask doesn't support it
|
|
53
|
+
- Looks foreign to most users
|
|
54
|
+
|
|
55
|
+
We spent days researching this. Reading Solana's design docs. Looking at adoption numbers. The more we dug, the more we found developers complaining about the same things we worried about.
|
|
56
|
+
|
|
57
|
+
We kept searching.
|
|
58
|
+
|
|
59
|
+
## The Revelation: Modern Chains Are Doing Something Different
|
|
60
|
+
|
|
61
|
+
We discovered that Aptos (from Meta's blockchain team) uses something elegant:
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
0x3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
It's just... the hex-encoded Ed25519 public key. No hashing. No information loss. The address IS the public key.
|
|
68
|
+
|
|
69
|
+
This was our "aha" moment.
|
|
70
|
+
|
|
71
|
+
## Comparing Our Options
|
|
72
|
+
|
|
73
|
+
Here's what we considered:
|
|
74
|
+
|
|
75
|
+
| Format | Example | Pros | Cons |
|
|
76
|
+
|--------|---------|------|------|
|
|
77
|
+
| **Ethereum** | `0x742d35Cc6634C0532925a3b844Bc454e3b6a5f8e` | • Instant payments<br>• MetaMask works<br>• Familiar | • 3x slower signatures<br>• Need extra 64 bytes per message<br>• Hash loses information |
|
|
78
|
+
| **Solana (Base58)** | `5FHneW46xGXNe3mZRwtFJNYiSqJ8RXkPmpnfWUrmTWVv` | • Fast Ed25519<br>• Address = public key<br>• Compact | • Case-sensitive<br>• No error detection<br>• Foreign to users |
|
|
79
|
+
| **Our Choice (Hex Ed25519)** | `0x3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c` | • Fast Ed25519<br>• Familiar format<br>• Address = public key<br>• Simple | • Longer (66 chars)<br>• No direct ETH payments |
|
|
80
|
+
|
|
81
|
+
## Our Solution: Familiar Format, Honest Content
|
|
82
|
+
|
|
83
|
+
We chose hex-encoded Ed25519 public keys with a 0x prefix:
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
0x3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Why this works:
|
|
90
|
+
1. **Looks familiar** - Users see "0x" and think "crypto address"
|
|
91
|
+
2. **No magic** - The address IS the public key (not some hash of a hash of a thing)
|
|
92
|
+
3. **Fast verification** - Ed25519 performance (70,000 signatures/sec)
|
|
93
|
+
4. **Developer-friendly** - `bytes.fromhex(address[2:])` gives you the public key
|
|
94
|
+
|
|
95
|
+
Yes, it's longer than Ethereum addresses (66 vs 42 characters). But in exchange, we get transparency and performance.
|
|
96
|
+
|
|
97
|
+
And here's the beautiful part - when developers eventually discover what these addresses are, there's no disappointment. It's not a "fake" Ethereum address. It's not a proprietary format. It's literally just a hex-encoded public key. Nothing special. Nothing hidden. Just honest, boring cryptography that works.
|
|
98
|
+
|
|
99
|
+
## The User Confusion Problem
|
|
100
|
+
|
|
101
|
+
We realized we were overthinking from a developer's perspective. Most users coming to ConnectOnion think:
|
|
102
|
+
- "I want to build a chatbot"
|
|
103
|
+
- "I want to automate my browser"
|
|
104
|
+
- "I want an AI assistant"
|
|
105
|
+
|
|
106
|
+
NOT:
|
|
107
|
+
- "I need a cryptographic identity"
|
|
108
|
+
- "I need to manage keys"
|
|
109
|
+
- "I need an address for my agent"
|
|
110
|
+
|
|
111
|
+
This hit us during user testing. A developer was trying our framework for the first time. They ran `co init`, saw "Generated agent address: 0x742d35..." and immediately asked:
|
|
112
|
+
|
|
113
|
+
"Do I need MetaMask for this?"
|
|
114
|
+
"No, it's just for agent identity."
|
|
115
|
+
"So... where do I put this address?"
|
|
116
|
+
"You don't, it's automatic."
|
|
117
|
+
"Then why are you showing it to me?"
|
|
118
|
+
|
|
119
|
+
Silence.
|
|
120
|
+
|
|
121
|
+
That's when we knew we'd been building for ourselves, not our users.
|
|
122
|
+
|
|
123
|
+
## The UX Breakthrough: Silent Generation
|
|
124
|
+
|
|
125
|
+
Then came our biggest realization: **Most users don't need to see addresses at all.**
|
|
126
|
+
|
|
127
|
+
We had a long debate about this. The crypto side of our brain said: "Users need to see their keys! They need to save recovery phrases! Security! Ownership!"
|
|
128
|
+
|
|
129
|
+
But the developer tool side argued back: "They're building a Hello World agent. They'll quit if we throw 12 words at them to write down."
|
|
130
|
+
|
|
131
|
+
The solution? Generate everything silently in the background. No questions asked. No decisions required.
|
|
132
|
+
|
|
133
|
+
When you run `co init`, we silently generate an identity in the background. It's saved in `.co/keys/`. The user never sees it unless they need networking later.
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
$ co init
|
|
137
|
+
✅ ConnectOnion project initialized!
|
|
138
|
+
|
|
139
|
+
Next steps:
|
|
140
|
+
1. Add your OpenAI API key
|
|
141
|
+
2. Run: python agent.py
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
No addresses. No recovery phrases. No confusion.
|
|
145
|
+
|
|
146
|
+
"But what about security?" you might ask. Here's the thing - the keys are still there, encrypted and safe in `.co/keys/`. The recovery phrase is saved (yes, we know that's controversial, but pragmatism won). If users want to see them later, they can. But 90% never will, and that's fine.
|
|
147
|
+
|
|
148
|
+
Later, IF they need agent networking:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
$ co network status
|
|
152
|
+
Agent address: 0x3d40...660c
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Progressive disclosure. Complexity revealed only when needed.
|
|
156
|
+
|
|
157
|
+
## The Philosophy: Keep Simple Things Simple
|
|
158
|
+
|
|
159
|
+
This journey taught us something fundamental about ConnectOnion's philosophy:
|
|
160
|
+
|
|
161
|
+
**Don't make users think about things they don't need to think about.**
|
|
162
|
+
|
|
163
|
+
Think about it - when you install Git, it doesn't ask you to generate SSH keys immediately. When you create a Python project, pip doesn't demand you set up PyPI credentials. These things come later, when you actually need them.
|
|
164
|
+
|
|
165
|
+
Why were we different? Why were we throwing cryptographic addresses at someone who just wanted to print "Hello World" from an agent?
|
|
166
|
+
|
|
167
|
+
- Building an agent ≠ Understanding cryptography
|
|
168
|
+
- Writing tools ≠ Managing network identities
|
|
169
|
+
- Getting started ≠ Making irreversible decisions
|
|
170
|
+
|
|
171
|
+
We generate a cryptographically secure identity for every agent, but we don't burden new users with understanding it. It's there when they need it, invisible when they don't.
|
|
172
|
+
|
|
173
|
+
## The Technical Details (For the Curious)
|
|
174
|
+
|
|
175
|
+
For those who care about the implementation:
|
|
176
|
+
|
|
177
|
+
1. **Seed phrase generation**: 12 BIP39 words for recovery
|
|
178
|
+
2. **Key derivation**: Ed25519 from seed for fast signatures
|
|
179
|
+
3. **Address format**: "0x" + hex(public_key)
|
|
180
|
+
4. **Storage**: Encrypted in .co/keys/
|
|
181
|
+
5. **Display**: Truncated (0x3d40...660c) for readability
|
|
182
|
+
|
|
183
|
+
The address can't receive Ethereum payments (it's not a real Ethereum address), but that's okay. If users need payments later, we can add that as a separate feature.
|
|
184
|
+
|
|
185
|
+
## What We Learned
|
|
186
|
+
|
|
187
|
+
The perfect solution isn't always the most technically advanced or the most feature-rich. Sometimes it's the one that:
|
|
188
|
+
|
|
189
|
+
1. **Works silently** - Generate complexity, don't expose it
|
|
190
|
+
2. **Looks familiar** - Use patterns people recognize
|
|
191
|
+
3. **Stays honest** - Don't pretend to be something you're not
|
|
192
|
+
4. **Scales gracefully** - From simple to complex use cases
|
|
193
|
+
|
|
194
|
+
## The Bigger Picture
|
|
195
|
+
|
|
196
|
+
This decision reflects ConnectOnion's core values:
|
|
197
|
+
|
|
198
|
+
- **Simplicity first** - Start simple, add complexity only when needed
|
|
199
|
+
- **Developer respect** - Make the internals clear and hackable
|
|
200
|
+
- **User empathy** - Don't make users learn new concepts unnecessarily
|
|
201
|
+
- **Technical honesty** - Choose the right tool, not the popular one
|
|
202
|
+
|
|
203
|
+
We could have chosen Ethereum compatibility for the hype. We could have chosen Solana style for the tech cred. Instead, we chose what actually works best for our users.
|
|
204
|
+
|
|
205
|
+
## The Key Realization: We're Not a Crypto Project
|
|
206
|
+
|
|
207
|
+
This was perhaps our most important insight. We kept trying to force cryptocurrency concepts onto an AI agent framework. But we're not building a blockchain. We're not creating a token. We're building a tool for developers to create AI agents.
|
|
208
|
+
|
|
209
|
+
The moment of clarity came during a late-night discussion:
|
|
210
|
+
|
|
211
|
+
"Why are we optimizing for payments?"
|
|
212
|
+
"Because... that's what everyone expects?"
|
|
213
|
+
"But our users are building chatbots and automation tools."
|
|
214
|
+
"So why are we making them think about wallets?"
|
|
215
|
+
"..."
|
|
216
|
+
|
|
217
|
+
Once we accepted this, everything became clearer:
|
|
218
|
+
- We don't need payment addresses (that's a separate problem)
|
|
219
|
+
- We don't need MetaMask compatibility (we're not doing transactions)
|
|
220
|
+
- We don't need to follow blockchain conventions (we can do better)
|
|
221
|
+
|
|
222
|
+
We're an AI agent network. Our priorities are different:
|
|
223
|
+
- **Developer simplicity** > Token economics
|
|
224
|
+
- **Fast messaging** > Payment rails
|
|
225
|
+
- **Progressive disclosure** > Upfront complexity
|
|
226
|
+
|
|
227
|
+
It's okay to not be Web3. It's okay to just be a good developer tool.
|
|
228
|
+
|
|
229
|
+
## Moving Forward
|
|
230
|
+
|
|
231
|
+
Will this decision limit us? Maybe. Can't receive ETH directly. Can't use MetaMask natively. But that's okay because we're building an agent network, not a cryptocurrency.
|
|
232
|
+
|
|
233
|
+
And for an agent network, what matters is:
|
|
234
|
+
- Fast message verification (Ed25519 ✓)
|
|
235
|
+
- Simple addressing (hex encoding ✓)
|
|
236
|
+
- Progressive complexity (silent generation ✓)
|
|
237
|
+
- Future flexibility (can add payment layers ✓)
|
|
238
|
+
|
|
239
|
+
The best technical decision was admitting what we are and what we're not. We're ConnectOnion, not ConnectCoin.
|
|
240
|
+
|
|
241
|
+
## The Code That Makes It Work
|
|
242
|
+
|
|
243
|
+
For the technically curious, here's the elegantly simple implementation:
|
|
244
|
+
|
|
245
|
+
```python
|
|
246
|
+
from nacl.signing import SigningKey
|
|
247
|
+
from mnemonic import Mnemonic
|
|
248
|
+
|
|
249
|
+
def create_agent():
|
|
250
|
+
# Generate seed phrase (but don't show it)
|
|
251
|
+
mnemo = Mnemonic("english")
|
|
252
|
+
seed_phrase = mnemo.generate(strength=128)
|
|
253
|
+
seed = mnemo.to_seed(seed_phrase)
|
|
254
|
+
|
|
255
|
+
# Derive Ed25519 key (fast!)
|
|
256
|
+
signing_key = SigningKey(seed[:32])
|
|
257
|
+
|
|
258
|
+
# Create address (just hex-encoded public key)
|
|
259
|
+
address = "0x" + signing_key.verify_key.encode().hex()
|
|
260
|
+
|
|
261
|
+
# Save silently to .co/keys/
|
|
262
|
+
save_identity(address, signing_key, seed_phrase)
|
|
263
|
+
|
|
264
|
+
# User never sees this complexity
|
|
265
|
+
return address # Only shown when needed
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## The Final Balance
|
|
269
|
+
|
|
270
|
+
After all this exploration, here's what we learned about balancing transparency and user-friendliness:
|
|
271
|
+
|
|
272
|
+
**What we show users:**
|
|
273
|
+
- Nothing on init (just works)
|
|
274
|
+
- Truncated address when networking (0x3d40...660c)
|
|
275
|
+
- Full address only when explicitly requested
|
|
276
|
+
|
|
277
|
+
**What we tell developers who dig deeper:**
|
|
278
|
+
- It's just a hex-encoded Ed25519 public key
|
|
279
|
+
- Nothing special, nothing proprietary
|
|
280
|
+
- You can verify signatures directly from the address
|
|
281
|
+
- Yes, we save the recovery phrase locally (pragmatism > dogma)
|
|
282
|
+
|
|
283
|
+
**The trade-offs we accepted:**
|
|
284
|
+
- Can't receive ETH directly → That's fine, we're not a wallet
|
|
285
|
+
- Recovery phrase saved locally → Controversial but practical
|
|
286
|
+
- No MetaMask support → We're not doing blockchain transactions
|
|
287
|
+
- Silent key generation → Users who don't need it never see it
|
|
288
|
+
|
|
289
|
+
## The Lesson
|
|
290
|
+
|
|
291
|
+
Building developer tools is an exercise in hidden complexity. The best hammer doesn't explain metallurgy; it just drives nails.
|
|
292
|
+
|
|
293
|
+
Our agent addresses work the same way. They're cryptographically secure, network-ready, and performance-optimized. But most importantly, they're invisible until you need them.
|
|
294
|
+
|
|
295
|
+
That's not a compromise. That's design.
|
|
296
|
+
|
|
297
|
+
The irony? We spent three months debating address formats, only to realize the best solution was to not show them at all. Sometimes the hardest technical decisions lead to the simplest user experiences.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
*Want to build an agent? Just run `co init`. No addresses required.*
|
|
302
|
+
|
|
303
|
+
*Want to connect agents? The address is already there, waiting.*
|
|
304
|
+
|
|
305
|
+
*That's the ConnectOnion way: Keep simple things simple, make complicated things possible.*
|
connectonion/cli/co_ai/prompts/connectonion/design-decisions/007-authentication-backend-design.md
ADDED
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
# Why We Chose Client-Side Challenges for Authentication
|
|
2
|
+
|
|
3
|
+
*September 2025*
|
|
4
|
+
|
|
5
|
+
When building the authentication system for ConnectOnion's managed keys, we faced a fundamental question: How do we verify that someone owns a private key without ever seeing that private key? This led us to a surprisingly simple solution that goes against conventional wisdom.
|
|
6
|
+
|
|
7
|
+
## The Problem: Public Keys Are... Public
|
|
8
|
+
|
|
9
|
+
We use Ed25519 public keys as addresses (like `0x3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c`). But here's the thing - anyone can see a public key. It's public!
|
|
10
|
+
|
|
11
|
+
So how do we authenticate users based on something everyone can see?
|
|
12
|
+
|
|
13
|
+
The naive approach would be:
|
|
14
|
+
```python
|
|
15
|
+
# WRONG - Don't do this!
|
|
16
|
+
POST /auth
|
|
17
|
+
{ "public_key": "0x3d40...660c" }
|
|
18
|
+
→ Returns JWT token
|
|
19
|
+
|
|
20
|
+
# Why is this wrong?
|
|
21
|
+
# Anyone could get a token for ANY public key!
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## The Standard Solution (That We Didn't Use)
|
|
25
|
+
|
|
26
|
+
Most authentication systems use server-generated challenges:
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
# Step 1: Get challenge from server
|
|
30
|
+
POST /auth/challenge
|
|
31
|
+
{ "public_key": "0x3d40...660c" }
|
|
32
|
+
→ { "challenge": "random_nonce_abc123" }
|
|
33
|
+
|
|
34
|
+
# Step 2: Sign it and send back
|
|
35
|
+
POST /auth/verify
|
|
36
|
+
{
|
|
37
|
+
"public_key": "0x3d40...660c",
|
|
38
|
+
"challenge": "random_nonce_abc123",
|
|
39
|
+
"signature": "signed_abc123"
|
|
40
|
+
}
|
|
41
|
+
→ { "token": "jwt_token" }
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This works! It's secure! It's also... complicated:
|
|
45
|
+
- Two API calls for every authentication
|
|
46
|
+
- Server needs to store challenges temporarily
|
|
47
|
+
- Need to track challenge sessions
|
|
48
|
+
- Handle challenge expiry
|
|
49
|
+
- Clean up old challenges
|
|
50
|
+
- Deal with race conditions
|
|
51
|
+
|
|
52
|
+
We spent a week building this. Then we asked: "Why are we making this so complicated?"
|
|
53
|
+
|
|
54
|
+
## The Revelation: Let Clients Create Their Own Challenges
|
|
55
|
+
|
|
56
|
+
Here's our "aha" moment: **The challenge doesn't need to be random, it just needs to be unique and recent.**
|
|
57
|
+
|
|
58
|
+
The client can create their own challenge using a timestamp:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
# Client side
|
|
62
|
+
timestamp = int(time.time())
|
|
63
|
+
message = f"ConnectOnion-Auth-{public_key}-{timestamp}"
|
|
64
|
+
signature = private_key.sign(message)
|
|
65
|
+
|
|
66
|
+
# One API call
|
|
67
|
+
POST /auth
|
|
68
|
+
{
|
|
69
|
+
"public_key": "0x3d40...660c",
|
|
70
|
+
"message": "ConnectOnion-Auth-0x3d40...660c-1701234567",
|
|
71
|
+
"signature": "abc123..."
|
|
72
|
+
}
|
|
73
|
+
→ { "token": "jwt_token" }
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Why This Is Secure
|
|
77
|
+
|
|
78
|
+
**"But wait!"** you might say. **"If clients create their own challenges, can't they cheat?"**
|
|
79
|
+
|
|
80
|
+
No! Here's why:
|
|
81
|
+
|
|
82
|
+
1. **Only the private key owner can create valid signatures**
|
|
83
|
+
- The math of Ed25519 ensures this
|
|
84
|
+
- You can verify with public key, but can't forge without private key
|
|
85
|
+
|
|
86
|
+
2. **Timestamps prevent replay attacks**
|
|
87
|
+
- Server rejects messages older than 5 minutes
|
|
88
|
+
- Can't reuse old signatures
|
|
89
|
+
|
|
90
|
+
3. **No secrets involved**
|
|
91
|
+
- Timestamp isn't secret
|
|
92
|
+
- Public key isn't secret
|
|
93
|
+
- Only the signature proves ownership
|
|
94
|
+
|
|
95
|
+
## The Complete Implementation
|
|
96
|
+
|
|
97
|
+
Here's our entire authentication flow:
|
|
98
|
+
|
|
99
|
+
**Client:**
|
|
100
|
+
```python
|
|
101
|
+
import time
|
|
102
|
+
from nacl.signing import SigningKey
|
|
103
|
+
|
|
104
|
+
def authenticate(private_key: SigningKey, server_url: str):
|
|
105
|
+
public_key = "0x" + private_key.verify_key.encode().hex()
|
|
106
|
+
timestamp = int(time.time())
|
|
107
|
+
message = f"ConnectOnion-Auth-{public_key}-{timestamp}"
|
|
108
|
+
|
|
109
|
+
signature = private_key.sign(message.encode()).signature
|
|
110
|
+
|
|
111
|
+
response = requests.post(f"{server_url}/auth", json={
|
|
112
|
+
"public_key": public_key,
|
|
113
|
+
"message": message,
|
|
114
|
+
"signature": signature.hex()
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
return response.json()["token"]
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Server:**
|
|
121
|
+
```python
|
|
122
|
+
from fastapi import FastAPI, HTTPException
|
|
123
|
+
from nacl.signing import VerifyKey
|
|
124
|
+
import jwt
|
|
125
|
+
import time
|
|
126
|
+
|
|
127
|
+
app = FastAPI()
|
|
128
|
+
|
|
129
|
+
@app.post("/auth")
|
|
130
|
+
def authenticate(public_key: str, message: str, signature: str):
|
|
131
|
+
# Extract and verify timestamp (prevent replay attacks)
|
|
132
|
+
timestamp = int(message.split("-")[-1])
|
|
133
|
+
if abs(time.time() - timestamp) > 300: # 5 minute window
|
|
134
|
+
raise HTTPException(400, "Message expired")
|
|
135
|
+
|
|
136
|
+
# Verify signature (proves private key ownership)
|
|
137
|
+
verify_key = VerifyKey(bytes.fromhex(public_key[2:]))
|
|
138
|
+
verify_key.verify(message.encode(), bytes.fromhex(signature))
|
|
139
|
+
|
|
140
|
+
# Create JWT token (valid for 24 hours)
|
|
141
|
+
token = jwt.encode(
|
|
142
|
+
{"public_key": public_key, "exp": time.time() + 86400},
|
|
143
|
+
"your-secret-key",
|
|
144
|
+
algorithm="HS256"
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return {"token": token}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## Why JWT After Authentication?
|
|
151
|
+
|
|
152
|
+
Once you've proven you own the private key, we give you a JWT token. Why?
|
|
153
|
+
|
|
154
|
+
**Without JWT:** Every API call needs signature verification (slow)
|
|
155
|
+
**With JWT:** Verify signature once, then use fast token validation
|
|
156
|
+
|
|
157
|
+
The JWT is just a performance optimization. The real security comes from the signature verification.
|
|
158
|
+
|
|
159
|
+
## Security Analysis
|
|
160
|
+
|
|
161
|
+
### What Attacks Does This Prevent?
|
|
162
|
+
|
|
163
|
+
1. **Impersonation**: Can't create signatures without private key ✓
|
|
164
|
+
2. **Replay**: Timestamps expire after 5 minutes ✓
|
|
165
|
+
3. **Man-in-the-middle**: Signatures are bound to specific message ✓
|
|
166
|
+
4. **Token theft**: JWTs expire after 24 hours ✓
|
|
167
|
+
|
|
168
|
+
### What About These Concerns?
|
|
169
|
+
|
|
170
|
+
**Q: "Timestamps aren't random! Isn't that less secure?"**
|
|
171
|
+
A: Randomness prevents prediction, but we don't need unpredictability here. We need uniqueness and recency, which timestamps provide.
|
|
172
|
+
|
|
173
|
+
**Q: "Client controls the timestamp! Can't they lie?"**
|
|
174
|
+
A: They can only lie by ±5 minutes. Doesn't help them. Old signatures are rejected, future signatures are rejected.
|
|
175
|
+
|
|
176
|
+
**Q: "What if clocks are out of sync?"**
|
|
177
|
+
A: 5-minute window handles normal clock drift. For serious drift, NTP exists.
|
|
178
|
+
|
|
179
|
+
## Comparison: Server vs Client Challenges
|
|
180
|
+
|
|
181
|
+
| Aspect | Server Challenge | Client Challenge (Our Choice) |
|
|
182
|
+
|--------|-----------------|------------------------------|
|
|
183
|
+
| API Calls | 2 (challenge + verify) | 1 (just verify) |
|
|
184
|
+
| Server Storage | Required (sessions) | None |
|
|
185
|
+
| Complexity | Medium | Simple |
|
|
186
|
+
| Code Lines | ~100 | ~20 |
|
|
187
|
+
| Stateless | No | Yes |
|
|
188
|
+
| Security | ✓ Secure | ✓ Equally secure |
|
|
189
|
+
|
|
190
|
+
## Real-World Validation
|
|
191
|
+
|
|
192
|
+
After implementing this, we discovered we're not alone:
|
|
193
|
+
- **Discord** uses client-signed timestamps for bot authentication
|
|
194
|
+
- **Telegram** uses similar client-generated challenges
|
|
195
|
+
- **Many Web3 apps** use "Sign this message with timestamp" patterns
|
|
196
|
+
|
|
197
|
+
The industry has quietly converged on this pattern because it works.
|
|
198
|
+
|
|
199
|
+
## Implementation Tips
|
|
200
|
+
|
|
201
|
+
### For ConnectOnion SDK Users
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from connectonion import authenticate
|
|
205
|
+
|
|
206
|
+
# It just works - complexity hidden
|
|
207
|
+
token = authenticate() # Uses local keys from ~/.co/keys/
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### For Direct API Users
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
# Generate signature with your tool of choice
|
|
214
|
+
TIMESTAMP=$(date +%s)
|
|
215
|
+
MESSAGE="ConnectOnion-Auth-${PUBLIC_KEY}-${TIMESTAMP}"
|
|
216
|
+
SIGNATURE=$(echo -n $MESSAGE | sodium sign)
|
|
217
|
+
|
|
218
|
+
# Single POST request
|
|
219
|
+
curl -X POST https://api.openonion.ai/auth \
|
|
220
|
+
-H "Content-Type: application/json" \
|
|
221
|
+
-d "{
|
|
222
|
+
\"public_key\": \"$PUBLIC_KEY\",
|
|
223
|
+
\"message\": \"$MESSAGE\",
|
|
224
|
+
\"signature\": \"$SIGNATURE\"
|
|
225
|
+
}"
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
## The Bottom Line
|
|
229
|
+
|
|
230
|
+
We chose client-generated challenges because:
|
|
231
|
+
- ✅ It's simpler (1 API call vs 2)
|
|
232
|
+
- ✅ It's stateless (no session storage)
|
|
233
|
+
- ✅ It's secure (cryptographically sound)
|
|
234
|
+
- ✅ It's proven (Discord, Telegram use similar patterns)
|
|
235
|
+
|
|
236
|
+
Sometimes the best solution isn't the most sophisticated one. It's the one that does exactly what you need, nothing more, nothing less.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
*Remember: Keep simple things simple. That's the ConnectOnion way.*
|