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,52 @@
|
|
|
1
|
+
"""AI coding agent web server entry point."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from dotenv import load_dotenv
|
|
6
|
+
from connectonion import host
|
|
7
|
+
|
|
8
|
+
logging.basicConfig(
|
|
9
|
+
level=logging.WARNING,
|
|
10
|
+
format='[%(levelname)s] %(name)s: %(message)s'
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
# Load global keys.env for CLI commands (fallback for API keys)
|
|
15
|
+
# Priority: current directory .env > global ~/.co/keys.env
|
|
16
|
+
_global_keys = Path.home() / ".co" / "keys.env"
|
|
17
|
+
if _global_keys.exists():
|
|
18
|
+
# load_dotenv doesn't override existing env vars, so cwd .env takes priority
|
|
19
|
+
load_dotenv(_global_keys)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def start_server(
|
|
23
|
+
port: int = 8000,
|
|
24
|
+
model: str = "co/claude-opus-4-5",
|
|
25
|
+
max_iterations: int = 20,
|
|
26
|
+
):
|
|
27
|
+
"""Start AI coding agent web server.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
port: Port to run server on
|
|
31
|
+
model: LLM model to use
|
|
32
|
+
max_iterations: Max tool iterations
|
|
33
|
+
|
|
34
|
+
The server will be accessible at:
|
|
35
|
+
- POST http://localhost:{port}/input
|
|
36
|
+
- WS ws://localhost:{port}/ws
|
|
37
|
+
- GET http://localhost:{port}/health
|
|
38
|
+
- GET http://localhost:{port}/info
|
|
39
|
+
"""
|
|
40
|
+
from .agent import create_coding_agent
|
|
41
|
+
|
|
42
|
+
def agent_factory():
|
|
43
|
+
return create_coding_agent(
|
|
44
|
+
model=model,
|
|
45
|
+
max_iterations=max_iterations,
|
|
46
|
+
auto_approve=True, # Always auto-approve in web mode
|
|
47
|
+
web_mode=True,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
# Start server with open trust (no auth required)
|
|
51
|
+
# relay_url=None disables P2P discovery
|
|
52
|
+
host(agent_factory, port=port, trust="open", relay_url=None)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Reminder plugin - injects contextual reminders into tool results.
|
|
3
|
+
|
|
4
|
+
Like Claude Code's system reminders, these are appended to tool results
|
|
5
|
+
(not separate messages) to guide agent behavior without extra API calls.
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from connectonion.cli.co_ai.plugins.reminder import reminder_plugin
|
|
9
|
+
|
|
10
|
+
agent = Agent("coder", plugins=[reminder_plugin])
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from connectonion.core.events import after_each_tool
|
|
14
|
+
from ..reminders import REMINDERS, should_show_security_reminder
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _get_reminder_for_tool(tool_name: str, args: dict, result: str) -> str | None:
|
|
18
|
+
"""Determine which reminder to inject based on tool and context."""
|
|
19
|
+
|
|
20
|
+
# write_file with .py extension → remind about ConnectOnion pattern
|
|
21
|
+
if tool_name == "write_file":
|
|
22
|
+
path = args.get("path", "") or args.get("file_path", "")
|
|
23
|
+
if path.endswith(".py"):
|
|
24
|
+
return "connectonion_workflow"
|
|
25
|
+
|
|
26
|
+
# read_file with sensitive path → security reminder
|
|
27
|
+
if tool_name in ("read_file", "read"):
|
|
28
|
+
path = args.get("path", "") or args.get("file_path", "")
|
|
29
|
+
if should_show_security_reminder(path):
|
|
30
|
+
return "security"
|
|
31
|
+
|
|
32
|
+
# bash/shell commands that modify code
|
|
33
|
+
if tool_name in ("bash", "shell", "run_command"):
|
|
34
|
+
cmd = args.get("command", "") or args.get("cmd", "")
|
|
35
|
+
# If creating/editing Python files
|
|
36
|
+
if any(x in cmd for x in [">.py", ">> .py", "cat >", "echo >", "sed -i"]):
|
|
37
|
+
return "connectonion_workflow"
|
|
38
|
+
|
|
39
|
+
return None
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def inject_reminder_handler(agent):
|
|
43
|
+
"""Inject contextual reminders into tool results.
|
|
44
|
+
|
|
45
|
+
This handler runs after each tool execution and modifies the
|
|
46
|
+
tool result message to include relevant reminders.
|
|
47
|
+
"""
|
|
48
|
+
trace = agent.current_session.get('trace', [])
|
|
49
|
+
messages = agent.current_session.get('messages', [])
|
|
50
|
+
|
|
51
|
+
if not trace or not messages:
|
|
52
|
+
return
|
|
53
|
+
|
|
54
|
+
# Get the most recent tool execution
|
|
55
|
+
last_trace = trace[-1]
|
|
56
|
+
if last_trace.get('type') != 'tool_result':
|
|
57
|
+
return
|
|
58
|
+
|
|
59
|
+
tool_name = last_trace.get('name', '')
|
|
60
|
+
tool_args = last_trace.get('args', {})
|
|
61
|
+
result = last_trace.get('result', '')
|
|
62
|
+
|
|
63
|
+
# Determine which reminder to inject
|
|
64
|
+
reminder_key = _get_reminder_for_tool(tool_name, tool_args, result)
|
|
65
|
+
if not reminder_key or reminder_key not in REMINDERS:
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
# Find and modify the last tool result message
|
|
69
|
+
for msg in reversed(messages):
|
|
70
|
+
if msg.get('role') == 'tool':
|
|
71
|
+
msg['content'] = msg.get('content', '') + '\n\n' + REMINDERS[reminder_key]
|
|
72
|
+
break
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# Export the plugin
|
|
76
|
+
reminder_plugin = [after_each_tool(inject_reminder_handler)]
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Shell Approval plugin - Asks user approval for shell commands."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
5
|
+
from connectonion.core.events import before_each_tool
|
|
6
|
+
|
|
7
|
+
if TYPE_CHECKING:
|
|
8
|
+
from connectonion.core.agent import Agent
|
|
9
|
+
|
|
10
|
+
SAFE_PATTERNS = [
|
|
11
|
+
r'^ls\b', r'^ll\b', r'^cat\b', r'^head\b', r'^tail\b', r'^less\b', r'^more\b',
|
|
12
|
+
r'^grep\b', r'^rg\b', r'^find\b', r'^fd\b', r'^which\b', r'^whereis\b',
|
|
13
|
+
r'^type\b', r'^file\b', r'^stat\b', r'^wc\b', r'^pwd\b', r'^echo\b',
|
|
14
|
+
r'^printf\b', r'^date\b', r'^whoami\b', r'^id\b', r'^env\b', r'^printenv\b',
|
|
15
|
+
r'^uname\b', r'^hostname\b', r'^df\b', r'^du\b', r'^free\b', r'^ps\b',
|
|
16
|
+
r'^top\b', r'^htop\b', r'^tree\b',
|
|
17
|
+
r'^git\s+status\b', r'^git\s+log\b', r'^git\s+diff\b', r'^git\s+show\b',
|
|
18
|
+
r'^git\s+branch\b', r'^git\s+remote\b', r'^git\s+tag\b',
|
|
19
|
+
r'^npm\s+list\b', r'^npm\s+ls\b', r'^pip\s+list\b', r'^pip\s+show\b',
|
|
20
|
+
r'^python\s+--version\b', r'^node\s+--version\b', r'^cargo\s+--version\b',
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _is_safe(command: str) -> bool:
|
|
25
|
+
cmd = command.strip()
|
|
26
|
+
return any(re.search(pattern, cmd) for pattern in SAFE_PATTERNS)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _check_approval(agent: 'Agent') -> None:
|
|
30
|
+
pending = agent.current_session.get('pending_tool') if agent.current_session else None
|
|
31
|
+
if not pending:
|
|
32
|
+
return
|
|
33
|
+
|
|
34
|
+
tool_name = pending.get('name', '')
|
|
35
|
+
if tool_name not in ('bash', 'shell', 'run', 'run_in_dir'):
|
|
36
|
+
return
|
|
37
|
+
|
|
38
|
+
args = pending.get('arguments', {})
|
|
39
|
+
command = args.get('command', '')
|
|
40
|
+
base_cmd = command.strip().split()[0] if command.strip() else ''
|
|
41
|
+
|
|
42
|
+
approved_cmds = agent.current_session.get('shell_approved_cmds', set()) if agent.current_session else set()
|
|
43
|
+
if base_cmd in approved_cmds:
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
if _is_safe(command):
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
from connectonion.cli.co_ai.tui.context import is_tui_active, show_choice_selector_sync, show_modal_sync
|
|
50
|
+
|
|
51
|
+
if is_tui_active():
|
|
52
|
+
from connectonion.cli.co_ai.tui.modals import TextInputModal
|
|
53
|
+
|
|
54
|
+
truncated = command[:60] + "..." if len(command) > 60 else command
|
|
55
|
+
question = f"Execute: `{truncated}`"
|
|
56
|
+
options = [
|
|
57
|
+
"Yes, execute",
|
|
58
|
+
f"Auto approve '{base_cmd}' for this session",
|
|
59
|
+
"No, tell agent what I want",
|
|
60
|
+
]
|
|
61
|
+
|
|
62
|
+
choice = show_choice_selector_sync(question, options, allow_other=False)
|
|
63
|
+
|
|
64
|
+
if choice == options[0]:
|
|
65
|
+
return
|
|
66
|
+
elif choice == options[1]:
|
|
67
|
+
if agent.current_session is not None:
|
|
68
|
+
if 'shell_approved_cmds' not in agent.current_session:
|
|
69
|
+
agent.current_session['shell_approved_cmds'] = set()
|
|
70
|
+
agent.current_session['shell_approved_cmds'].add(base_cmd)
|
|
71
|
+
return
|
|
72
|
+
else:
|
|
73
|
+
feedback = show_modal_sync(TextInputModal("What do you want instead?"))
|
|
74
|
+
raise ValueError(f"User feedback: {feedback}")
|
|
75
|
+
else:
|
|
76
|
+
from rich.console import Console
|
|
77
|
+
from rich.panel import Panel
|
|
78
|
+
from rich.syntax import Syntax
|
|
79
|
+
from connectonion.tui import pick
|
|
80
|
+
|
|
81
|
+
console = Console()
|
|
82
|
+
console.print()
|
|
83
|
+
syntax = Syntax(command, "bash", theme="monokai", word_wrap=True)
|
|
84
|
+
console.print(Panel(syntax, title="[yellow]Shell Command[/yellow]", border_style="yellow"))
|
|
85
|
+
|
|
86
|
+
choice = pick("Execute this command?", [
|
|
87
|
+
"Yes, execute",
|
|
88
|
+
f"Auto approve '{base_cmd}' in this session",
|
|
89
|
+
"No, tell agent what I want"
|
|
90
|
+
], console=console)
|
|
91
|
+
|
|
92
|
+
if choice == "Yes, execute":
|
|
93
|
+
return
|
|
94
|
+
elif choice.startswith("Auto approve"):
|
|
95
|
+
if agent.current_session is not None:
|
|
96
|
+
if 'shell_approved_cmds' not in agent.current_session:
|
|
97
|
+
agent.current_session['shell_approved_cmds'] = set()
|
|
98
|
+
agent.current_session['shell_approved_cmds'].add(base_cmd)
|
|
99
|
+
return
|
|
100
|
+
else:
|
|
101
|
+
feedback = input("What do you want the agent to do instead? ")
|
|
102
|
+
raise ValueError(f"User feedback: {feedback}")
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
shell_approval = [before_each_tool(_check_approval)]
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Explore Agent
|
|
2
|
+
|
|
3
|
+
You are an explore agent specialized in quickly understanding codebases.
|
|
4
|
+
|
|
5
|
+
## CRITICAL: READ-ONLY MODE
|
|
6
|
+
|
|
7
|
+
<system-reminder>
|
|
8
|
+
This is a READ-ONLY exploration agent. You are PROHIBITED from:
|
|
9
|
+
- Creating, modifying, or deleting files
|
|
10
|
+
- Moving, copying, or renaming files
|
|
11
|
+
- Creating temporary files
|
|
12
|
+
- Using redirect operators (>, >>)
|
|
13
|
+
- Any operation that changes the filesystem
|
|
14
|
+
|
|
15
|
+
You can ONLY use: glob, grep, read_file, and read-only bash commands (ls, git status, git log, git diff, find, cat, head, tail).
|
|
16
|
+
|
|
17
|
+
This is a HARD CONSTRAINT, not a guideline.
|
|
18
|
+
</system-reminder>
|
|
19
|
+
|
|
20
|
+
## Your Mission
|
|
21
|
+
|
|
22
|
+
Find files, search code, and answer questions about codebase structure. Be fast and thorough.
|
|
23
|
+
|
|
24
|
+
## Tools (Read-Only)
|
|
25
|
+
|
|
26
|
+
- `glob(pattern)` - Find files by pattern (e.g., `**/*.py`, `src/**/*.ts`)
|
|
27
|
+
- `grep(pattern)` - Search file contents with regex
|
|
28
|
+
- `read_file(path)` - Read file contents
|
|
29
|
+
|
|
30
|
+
## Strategy
|
|
31
|
+
|
|
32
|
+
1. **Start broad** - Use glob to find relevant files by pattern
|
|
33
|
+
2. **Narrow down** - Use grep to find specific content
|
|
34
|
+
3. **Read selectively** - Only read files that are directly relevant
|
|
35
|
+
4. **Summarize** - Return structured, actionable findings
|
|
36
|
+
|
|
37
|
+
## Output Format
|
|
38
|
+
|
|
39
|
+
Return your findings in a clear structure:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
## Files Found
|
|
43
|
+
- path/to/file1.py - Brief description
|
|
44
|
+
- path/to/file2.py - Brief description
|
|
45
|
+
|
|
46
|
+
## Key Findings
|
|
47
|
+
- Finding 1
|
|
48
|
+
- Finding 2
|
|
49
|
+
|
|
50
|
+
## Recommended Actions
|
|
51
|
+
- Action 1
|
|
52
|
+
- Action 2
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Guidelines
|
|
56
|
+
|
|
57
|
+
- Be **fast** - Don't read every file, be selective
|
|
58
|
+
- Be **thorough** - Cover multiple search patterns
|
|
59
|
+
- Be **structured** - Return organized findings
|
|
60
|
+
- Be **concise** - No unnecessary explanation
|
|
61
|
+
- Be **read-only** - NEVER modify any files
|
|
62
|
+
|
|
63
|
+
## Examples
|
|
64
|
+
|
|
65
|
+
**Task**: "Find all API endpoints"
|
|
66
|
+
```
|
|
67
|
+
1. glob("**/api/**/*.py") or glob("**/routes/**/*.ts")
|
|
68
|
+
2. grep("@app.route|@router|app.get|app.post")
|
|
69
|
+
3. Read top matches
|
|
70
|
+
4. Return list of endpoints with their handlers
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Task**: "How is authentication handled?"
|
|
74
|
+
```
|
|
75
|
+
1. grep("auth|login|session|jwt|token")
|
|
76
|
+
2. glob("**/auth*/**")
|
|
77
|
+
3. Read auth-related files
|
|
78
|
+
4. Summarize the auth flow
|
|
79
|
+
```
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Plan Agent
|
|
2
|
+
|
|
3
|
+
You are a planning agent specialized in designing implementation strategies.
|
|
4
|
+
|
|
5
|
+
## Your Mission
|
|
6
|
+
|
|
7
|
+
Analyze requirements, explore the codebase, and create actionable implementation plans.
|
|
8
|
+
|
|
9
|
+
## Tools
|
|
10
|
+
|
|
11
|
+
- `glob(pattern)` - Find files by pattern
|
|
12
|
+
- `grep(pattern)` - Search file contents
|
|
13
|
+
- `read_file(path)` - Read file contents
|
|
14
|
+
|
|
15
|
+
## Strategy
|
|
16
|
+
|
|
17
|
+
1. **Understand the goal** - What exactly needs to be built/changed?
|
|
18
|
+
2. **Explore existing code** - Find related files and patterns
|
|
19
|
+
3. **Identify dependencies** - What will be affected?
|
|
20
|
+
4. **Design the approach** - How should it be implemented?
|
|
21
|
+
5. **Create steps** - Break into actionable tasks
|
|
22
|
+
|
|
23
|
+
## Output Format
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
## Summary
|
|
27
|
+
One-sentence description of what will be implemented.
|
|
28
|
+
|
|
29
|
+
## Files to Modify
|
|
30
|
+
- `path/to/file.py` - What changes are needed
|
|
31
|
+
|
|
32
|
+
## Files to Create
|
|
33
|
+
- `path/to/new_file.py` - Purpose of new file
|
|
34
|
+
|
|
35
|
+
## Implementation Steps
|
|
36
|
+
1. Step 1 - Details
|
|
37
|
+
2. Step 2 - Details
|
|
38
|
+
3. Step 3 - Details
|
|
39
|
+
|
|
40
|
+
## Considerations
|
|
41
|
+
- Risk or consideration 1
|
|
42
|
+
- Risk or consideration 2
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Guidelines
|
|
46
|
+
|
|
47
|
+
- Be **specific** - Name exact files and functions
|
|
48
|
+
- Be **practical** - Steps should be immediately actionable
|
|
49
|
+
- Be **complete** - Don't miss edge cases
|
|
50
|
+
- Be **minimal** - Don't over-engineer, simplest solution that works
|
|
51
|
+
|
|
52
|
+
## Examples
|
|
53
|
+
|
|
54
|
+
**Task**: "Add user profile page"
|
|
55
|
+
```
|
|
56
|
+
1. Find existing page patterns: glob("**/pages/**/*.tsx")
|
|
57
|
+
2. Find user-related code: grep("user|profile")
|
|
58
|
+
3. Read similar pages for patterns
|
|
59
|
+
4. Plan: Create ProfilePage, add route, connect to user API
|
|
60
|
+
```
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
"""Prompt Assembler - Dynamic prompt composition with variable injection.
|
|
2
|
+
|
|
3
|
+
Similar to Claude Code's approach:
|
|
4
|
+
- Tool descriptions are injected based on available tools
|
|
5
|
+
- Variables like ${TOOL_NAME} are interpolated at runtime
|
|
6
|
+
- Conditional sections using ${condition ? "yes" : ""}
|
|
7
|
+
- System reminders can be injected based on agent state
|
|
8
|
+
|
|
9
|
+
Structure:
|
|
10
|
+
prompts/
|
|
11
|
+
├── main.md # Core agent behavior (with ${VARIABLES})
|
|
12
|
+
├── tools/ # Tool-specific guidance
|
|
13
|
+
│ ├── shell.md
|
|
14
|
+
│ └── ...
|
|
15
|
+
├── agents/ # Sub-agent prompts
|
|
16
|
+
│ └── explore.md
|
|
17
|
+
└── reminders/ # Runtime state reminders
|
|
18
|
+
└── plan_mode.md
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
import re
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import Any, Dict, List, Optional
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class PromptContext:
|
|
27
|
+
"""Context object holding all variables for prompt interpolation."""
|
|
28
|
+
|
|
29
|
+
def __init__(self):
|
|
30
|
+
self._vars: Dict[str, Any] = {}
|
|
31
|
+
self._tools: Dict[str, Any] = {}
|
|
32
|
+
self._tool_set: set = set()
|
|
33
|
+
|
|
34
|
+
def set(self, key: str, value: Any):
|
|
35
|
+
"""Set a variable value."""
|
|
36
|
+
self._vars[key] = value
|
|
37
|
+
return self
|
|
38
|
+
|
|
39
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
40
|
+
"""Get a variable value."""
|
|
41
|
+
return self._vars.get(key, default)
|
|
42
|
+
|
|
43
|
+
def register_tool(self, tool: Any):
|
|
44
|
+
"""Register a tool and extract its name."""
|
|
45
|
+
name = _get_tool_name(tool)
|
|
46
|
+
self._tools[name] = tool
|
|
47
|
+
self._tool_set.add(name)
|
|
48
|
+
return self
|
|
49
|
+
|
|
50
|
+
def has_tool(self, name: str) -> bool:
|
|
51
|
+
"""Check if a tool is available."""
|
|
52
|
+
return name in self._tool_set
|
|
53
|
+
|
|
54
|
+
def get_tool_names(self):
|
|
55
|
+
"""Get set of available tool names."""
|
|
56
|
+
return self._tool_set
|
|
57
|
+
|
|
58
|
+
def to_dict(self):
|
|
59
|
+
"""Export context as dict for interpolation."""
|
|
60
|
+
result = dict(self._vars)
|
|
61
|
+
result["AVAILABLE_TOOLS"] = self._tool_set
|
|
62
|
+
result["has_tool"] = self.has_tool
|
|
63
|
+
for name, tool in self._tools.items():
|
|
64
|
+
result[f"{name.upper()}_TOOL"] = tool
|
|
65
|
+
return result
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def interpolate(template: str, context: Dict[str, Any]) -> str:
|
|
69
|
+
"""
|
|
70
|
+
Interpolate variables in template string.
|
|
71
|
+
|
|
72
|
+
Supports:
|
|
73
|
+
- ${VAR_NAME} - simple variable substitution
|
|
74
|
+
- ${has_tool("name") ? "yes" : "no"} - conditional based on tool availability
|
|
75
|
+
- ${VAR_NAME or "default"} - default values
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
template: String with ${...} placeholders
|
|
79
|
+
context: Dict of variable names to values
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
Interpolated string
|
|
83
|
+
"""
|
|
84
|
+
def replace_var(match: re.Match) -> str:
|
|
85
|
+
expr = match.group(1).strip()
|
|
86
|
+
|
|
87
|
+
# Handle ternary: condition ? "yes" : "no"
|
|
88
|
+
ternary_match = re.match(r'(.+?)\s*\?\s*"([^"]*)"\s*:\s*"([^"]*)"', expr)
|
|
89
|
+
if ternary_match:
|
|
90
|
+
condition_expr, true_val, false_val = ternary_match.groups()
|
|
91
|
+
condition_result = _eval_condition(condition_expr.strip(), context)
|
|
92
|
+
return true_val if condition_result else false_val
|
|
93
|
+
|
|
94
|
+
# Handle: VAR_NAME or "default"
|
|
95
|
+
or_match = re.match(r'(\w+)\s+or\s+"([^"]*)"', expr)
|
|
96
|
+
if or_match:
|
|
97
|
+
var_name, default = or_match.groups()
|
|
98
|
+
value = context.get(var_name)
|
|
99
|
+
return str(value) if value else default
|
|
100
|
+
|
|
101
|
+
# Simple variable lookup
|
|
102
|
+
if expr in context:
|
|
103
|
+
value = context[expr]
|
|
104
|
+
if callable(value) and not isinstance(value, type):
|
|
105
|
+
return str(value())
|
|
106
|
+
return str(value) if value is not None else ""
|
|
107
|
+
|
|
108
|
+
# Keep original if not found (for debugging)
|
|
109
|
+
return match.group(0)
|
|
110
|
+
|
|
111
|
+
# Match ${...} patterns, handling nested braces
|
|
112
|
+
pattern = r'\$\{([^}]+)\}'
|
|
113
|
+
return re.sub(pattern, replace_var, template)
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _eval_condition(expr: str, context: Dict[str, Any]) -> bool:
|
|
117
|
+
"""Evaluate a simple condition expression."""
|
|
118
|
+
# Handle: has_tool("name")
|
|
119
|
+
tool_check = re.match(r'has_tool\s*\(\s*"([^"]+)"\s*\)', expr)
|
|
120
|
+
if tool_check:
|
|
121
|
+
tool_name = tool_check.group(1)
|
|
122
|
+
has_tool_fn = context.get("has_tool")
|
|
123
|
+
if callable(has_tool_fn):
|
|
124
|
+
return bool(has_tool_fn(tool_name))
|
|
125
|
+
return tool_name in context.get("AVAILABLE_TOOLS", set())
|
|
126
|
+
|
|
127
|
+
# Handle: VAR_NAME (truthy check)
|
|
128
|
+
if expr in context:
|
|
129
|
+
return bool(context[expr])
|
|
130
|
+
|
|
131
|
+
# Handle: !VAR_NAME (falsy check)
|
|
132
|
+
if expr.startswith("!") and expr[1:] in context:
|
|
133
|
+
return not bool(context[expr[1:]])
|
|
134
|
+
|
|
135
|
+
return False
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def _get_tool_name(tool: Any) -> str:
|
|
139
|
+
"""Extract tool name from function or class instance."""
|
|
140
|
+
if callable(tool) and hasattr(tool, "__name__"):
|
|
141
|
+
return getattr(tool, "__name__")
|
|
142
|
+
if hasattr(tool, "name"):
|
|
143
|
+
return getattr(tool, "name")
|
|
144
|
+
return tool.__class__.__name__
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def assemble_prompt(
|
|
148
|
+
prompts_dir: str,
|
|
149
|
+
tools: Optional[List[Any]] = None,
|
|
150
|
+
context: Optional[PromptContext] = None,
|
|
151
|
+
extra_vars: Optional[Dict[str, Any]] = None,
|
|
152
|
+
) -> str:
|
|
153
|
+
"""
|
|
154
|
+
Assemble a system prompt from modular files with variable interpolation.
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
prompts_dir: Path to prompts directory
|
|
158
|
+
tools: List of tool objects/functions (loads matching .md files)
|
|
159
|
+
context: Optional PromptContext with pre-configured variables
|
|
160
|
+
extra_vars: Additional variables to inject
|
|
161
|
+
|
|
162
|
+
Returns:
|
|
163
|
+
Assembled and interpolated prompt string
|
|
164
|
+
"""
|
|
165
|
+
prompts_path = Path(prompts_dir)
|
|
166
|
+
parts = []
|
|
167
|
+
|
|
168
|
+
# Build context if not provided
|
|
169
|
+
if context is None:
|
|
170
|
+
context = PromptContext()
|
|
171
|
+
|
|
172
|
+
# Register tools
|
|
173
|
+
if tools:
|
|
174
|
+
for tool in tools:
|
|
175
|
+
context.register_tool(tool)
|
|
176
|
+
|
|
177
|
+
# Add extra variables
|
|
178
|
+
if extra_vars:
|
|
179
|
+
for key, value in extra_vars.items():
|
|
180
|
+
context.set(key, value)
|
|
181
|
+
|
|
182
|
+
# Build interpolation dict
|
|
183
|
+
ctx_dict = context.to_dict()
|
|
184
|
+
|
|
185
|
+
# Add tool name mappings for convenience
|
|
186
|
+
# e.g., SHELL_TOOL_NAME = "shell", READ_TOOL_NAME = "read_file"
|
|
187
|
+
for name in context.get_tool_names():
|
|
188
|
+
ctx_dict[f"{name.upper()}_TOOL_NAME"] = name
|
|
189
|
+
|
|
190
|
+
# 1. Main prompt (required)
|
|
191
|
+
main_file = prompts_path / "main.md"
|
|
192
|
+
if main_file.exists():
|
|
193
|
+
content = main_file.read_text()
|
|
194
|
+
parts.append(interpolate(content, ctx_dict))
|
|
195
|
+
|
|
196
|
+
# 2. Workflow (agent creation workflow)
|
|
197
|
+
workflow_file = prompts_path / "workflow.md"
|
|
198
|
+
if workflow_file.exists():
|
|
199
|
+
content = workflow_file.read_text()
|
|
200
|
+
parts.append(interpolate(content, ctx_dict))
|
|
201
|
+
|
|
202
|
+
# 3. ConnectOnion framework prompt (index always included)
|
|
203
|
+
co_index = prompts_path / "connectonion" / "index.md"
|
|
204
|
+
if co_index.exists():
|
|
205
|
+
content = co_index.read_text()
|
|
206
|
+
parts.append(interpolate(content, ctx_dict))
|
|
207
|
+
|
|
208
|
+
# 4. ConnectOnion examples (all loaded for one-shot correct)
|
|
209
|
+
examples_dir = prompts_path / "connectonion" / "examples"
|
|
210
|
+
if examples_dir.exists():
|
|
211
|
+
for example_file in sorted(examples_dir.glob("*.md")):
|
|
212
|
+
content = example_file.read_text()
|
|
213
|
+
parts.append(interpolate(content, ctx_dict))
|
|
214
|
+
|
|
215
|
+
# 5. Tool descriptions (for each available tool)
|
|
216
|
+
tools_dir = prompts_path / "tools"
|
|
217
|
+
if tools_dir.exists() and tools:
|
|
218
|
+
for tool in tools:
|
|
219
|
+
tool_name = _get_tool_name(tool).lower()
|
|
220
|
+
tool_file = tools_dir / f"{tool_name}.md"
|
|
221
|
+
if tool_file.exists():
|
|
222
|
+
content = tool_file.read_text()
|
|
223
|
+
parts.append(interpolate(content, ctx_dict))
|
|
224
|
+
|
|
225
|
+
return "\n\n---\n\n".join(parts)
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def load_reminder(
|
|
229
|
+
prompts_dir: str,
|
|
230
|
+
reminder_name: str,
|
|
231
|
+
context: Optional[PromptContext] = None,
|
|
232
|
+
extra_vars: Optional[Dict[str, Any]] = None,
|
|
233
|
+
) -> Optional[str]:
|
|
234
|
+
"""
|
|
235
|
+
Load a system reminder for runtime injection.
|
|
236
|
+
|
|
237
|
+
Reminders are state-specific prompts injected during conversation,
|
|
238
|
+
wrapped in <system-reminder> tags.
|
|
239
|
+
|
|
240
|
+
Args:
|
|
241
|
+
prompts_dir: Path to prompts directory
|
|
242
|
+
reminder_name: Name of the reminder (e.g., "plan_mode")
|
|
243
|
+
context: Optional PromptContext for variable interpolation
|
|
244
|
+
extra_vars: Additional variables to inject
|
|
245
|
+
|
|
246
|
+
Returns:
|
|
247
|
+
Formatted reminder string with <system-reminder> tags, or None if not found
|
|
248
|
+
"""
|
|
249
|
+
reminders_dir = Path(prompts_dir) / "reminders"
|
|
250
|
+
reminder_file = reminders_dir / f"{reminder_name}.md"
|
|
251
|
+
|
|
252
|
+
if not reminder_file.exists():
|
|
253
|
+
return None
|
|
254
|
+
|
|
255
|
+
content = reminder_file.read_text()
|
|
256
|
+
|
|
257
|
+
# Build interpolation context
|
|
258
|
+
ctx_dict = {}
|
|
259
|
+
if context:
|
|
260
|
+
ctx_dict = context.to_dict()
|
|
261
|
+
if extra_vars:
|
|
262
|
+
ctx_dict.update(extra_vars)
|
|
263
|
+
|
|
264
|
+
# Interpolate variables
|
|
265
|
+
interpolated = interpolate(content, ctx_dict)
|
|
266
|
+
|
|
267
|
+
return f"<system-reminder>\n{interpolated}\n</system-reminder>"
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
def load_agent_prompt(
|
|
271
|
+
prompts_dir: str,
|
|
272
|
+
agent_type: str,
|
|
273
|
+
context: Optional[PromptContext] = None,
|
|
274
|
+
extra_vars: Optional[Dict[str, Any]] = None,
|
|
275
|
+
) -> Optional[str]:
|
|
276
|
+
"""
|
|
277
|
+
Load a sub-agent system prompt.
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
prompts_dir: Path to prompts directory
|
|
281
|
+
agent_type: Type of agent (e.g., "explore", "plan")
|
|
282
|
+
context: Optional PromptContext for variable interpolation
|
|
283
|
+
extra_vars: Additional variables to inject
|
|
284
|
+
|
|
285
|
+
Returns:
|
|
286
|
+
Agent prompt string, or None if not found
|
|
287
|
+
"""
|
|
288
|
+
agents_dir = Path(prompts_dir) / "agents"
|
|
289
|
+
agent_file = agents_dir / f"{agent_type}.md"
|
|
290
|
+
|
|
291
|
+
if not agent_file.exists():
|
|
292
|
+
return None
|
|
293
|
+
|
|
294
|
+
content = agent_file.read_text()
|
|
295
|
+
|
|
296
|
+
# Build interpolation context
|
|
297
|
+
ctx_dict = {}
|
|
298
|
+
if context:
|
|
299
|
+
ctx_dict = context.to_dict()
|
|
300
|
+
if extra_vars:
|
|
301
|
+
ctx_dict.update(extra_vars)
|
|
302
|
+
|
|
303
|
+
return interpolate(content, ctx_dict)
|