connectonion 0.6.1__py3-none-any.whl → 0.6.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- connectonion/__init__.py +46 -9
- connectonion/cli/__init__.py +11 -1
- connectonion/cli/browser_agent/__init__.py +11 -1
- connectonion/cli/browser_agent/browser.py +95 -142
- connectonion/cli/browser_agent/element_finder.py +147 -0
- connectonion/cli/browser_agent/highlight_screenshot.py +182 -0
- connectonion/cli/browser_agent/prompt.md +188 -105
- connectonion/cli/browser_agent/prompts/element_matcher.md +59 -0
- connectonion/cli/browser_agent/prompts/form_filler.md +19 -0
- connectonion/cli/browser_agent/prompts/scroll_strategy.md +36 -0
- connectonion/cli/browser_agent/scripts/extract_elements.js +126 -0
- connectonion/cli/browser_agent/scroll.py +145 -0
- connectonion/cli/co_ai/__init__.py +6 -0
- connectonion/cli/co_ai/agent.py +87 -0
- connectonion/cli/co_ai/agents/__init__.py +5 -0
- connectonion/cli/co_ai/agents/registry.py +57 -0
- connectonion/cli/co_ai/commands/__init__.py +45 -0
- connectonion/cli/co_ai/commands/compact.py +173 -0
- connectonion/cli/co_ai/commands/cost.py +77 -0
- connectonion/cli/co_ai/commands/export.py +60 -0
- connectonion/cli/co_ai/commands/help.py +80 -0
- connectonion/cli/co_ai/commands/init.py +101 -0
- connectonion/cli/co_ai/commands/sessions.py +55 -0
- connectonion/cli/co_ai/commands/tasks.py +63 -0
- connectonion/cli/co_ai/commands/undo.py +103 -0
- connectonion/cli/co_ai/context.py +127 -0
- connectonion/cli/co_ai/main.py +52 -0
- connectonion/cli/co_ai/plugins/__init__.py +6 -0
- connectonion/cli/co_ai/plugins/reminder.py +76 -0
- connectonion/cli/co_ai/plugins/shell_approval.py +105 -0
- connectonion/cli/co_ai/prompts/agents/explore.md +79 -0
- connectonion/cli/co_ai/prompts/agents/plan.md +60 -0
- connectonion/cli/co_ai/prompts/assembler.py +303 -0
- connectonion/cli/{docs/co-vibecoding-principles-docs-contexts-all-in-one.md → co_ai/prompts/connectonion/README.md} +26 -0
- connectonion/cli/co_ai/prompts/connectonion/api.md +457 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/README.md +805 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/auth.md +46 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/browser.md +235 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/copy.md +184 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/create.md +335 -0
- connectonion/cli/co_ai/prompts/connectonion/cli/init.md +431 -0
- connectonion/cli/co_ai/prompts/connectonion/co-directory-structure.md +214 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/agent.md +1078 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/events.md +816 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/llm_do.md +256 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/max_iterations.md +362 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/models.md +641 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/plugins.md +100 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/prompts.md +122 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/tools.md +512 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/transcribe.md +156 -0
- connectonion/cli/co_ai/prompts/connectonion/concepts/trust.md +291 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/README.md +18 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/auto_debug.md +1026 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/console.md +129 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/eval-format.md +178 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/eval.md +230 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/exceptions.md +307 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/log.md +117 -0
- connectonion/cli/co_ai/prompts/connectonion/debug/xray.md +215 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/001-choosing-input-method.md +202 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/002-choosing-llm-function-name.md +202 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/003-choosing-trust-keyword.md +141 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/004-cli-create-flow.md +117 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/005-designing-agent-network-protocol.md +503 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/006-agent-address-format.md +305 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/007-authentication-backend-design.md +240 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/008-naming-is-hard.md +228 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/009-why-connect-function.md +167 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/010-cli-ux-progressive-disclosure.md +176 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/011-global-config-identity-management.md +357 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/012-tool-execution-separation.md +259 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/013-debug-and-logging-design.md +253 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/014-hook-system-design.md +510 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/015-interactive-auto-debug-design.md +837 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/016-why-no-zero-knowledge-proofs.md +358 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/017-session-logging-and-eval-format.md +120 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/018-event-api-naming.md +274 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/019-agent-lifecycle-design.md +655 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/020-trust-system-and-network-architecture.md +503 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/021-task-storage-jsonl-design.md +496 -0
- connectonion/cli/co_ai/prompts/connectonion/design-decisions/022-raw-asgi-implementation.md +273 -0
- connectonion/cli/co_ai/prompts/connectonion/examples/agent_reasoning.md +62 -0
- connectonion/cli/co_ai/prompts/connectonion/examples/atomic_tools.md +24 -0
- connectonion/cli/co_ai/prompts/connectonion/examples/load_guide.md +18 -0
- connectonion/cli/co_ai/prompts/connectonion/examples.md +0 -0
- connectonion/cli/co_ai/prompts/connectonion/hook-system-options.md +364 -0
- connectonion/cli/co_ai/prompts/connectonion/index.md +162 -0
- connectonion/cli/co_ai/prompts/connectonion/integrations/README.md +12 -0
- connectonion/cli/co_ai/prompts/connectonion/integrations/auth.md +450 -0
- connectonion/cli/co_ai/prompts/connectonion/integrations/google.md +431 -0
- connectonion/cli/co_ai/prompts/connectonion/integrations/microsoft.md +370 -0
- connectonion/cli/co_ai/prompts/connectonion/network/README.md +14 -0
- connectonion/cli/co_ai/prompts/connectonion/network/connect.md +543 -0
- connectonion/cli/co_ai/prompts/connectonion/network/connection.md +538 -0
- connectonion/cli/co_ai/prompts/connectonion/network/deploy.md +123 -0
- connectonion/cli/co_ai/prompts/connectonion/network/host.md +1049 -0
- connectonion/cli/co_ai/prompts/connectonion/network/protocol/agent-relay-protocol.md +495 -0
- connectonion/cli/co_ai/prompts/connectonion/network/protocol/announce-message.md +115 -0
- connectonion/cli/co_ai/prompts/connectonion/principles.md +124 -0
- connectonion/cli/co_ai/prompts/connectonion/quickstart.md +261 -0
- connectonion/cli/co_ai/prompts/connectonion/roadmap.md +81 -0
- connectonion/cli/co_ai/prompts/connectonion/templates/README.md +77 -0
- connectonion/cli/co_ai/prompts/connectonion/templates/meta-agent.md +152 -0
- connectonion/cli/co_ai/prompts/connectonion/templates/minimal.md +105 -0
- connectonion/cli/co_ai/prompts/connectonion/templates/playwright.md +130 -0
- connectonion/cli/co_ai/prompts/connectonion/templates/web-research.md +144 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/README.md +95 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/chat.md +181 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/divider.md +63 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/dropdown.md +83 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/footer.md +44 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/fuzzy.md +68 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/input.md +84 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/keys.md +77 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/pick.md +71 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/providers.md +89 -0
- connectonion/cli/co_ai/prompts/connectonion/tui/status_bar.md +67 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/README.md +156 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/calendar_plugin.md +68 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/eval.md +89 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/gmail_plugin.md +68 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/image_result_formatter.md +74 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/re_act.md +86 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_plugins/shell_approval.md +69 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/README.md +81 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/diff_writer.md +138 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/get_emails.md +499 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/gmail.md +135 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/google_calendar.md +106 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/memory.md +486 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/microsoft_calendar.md +106 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/outlook.md +120 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/send_email.md +403 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/shell.md +95 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/slash_command.md +96 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/terminal.md +97 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/todo_list.md +252 -0
- connectonion/cli/co_ai/prompts/connectonion/useful_tools/web_fetch.md +130 -0
- connectonion/cli/co_ai/prompts/connectonion/vibe-coding-guide.md +97 -0
- connectonion/cli/co_ai/prompts/connectonion/windows-support.md +258 -0
- connectonion/cli/co_ai/prompts/main.md +247 -0
- connectonion/cli/co_ai/prompts/reminders/plan_mode.md +34 -0
- connectonion/cli/co_ai/prompts/summarization.md +55 -0
- connectonion/cli/co_ai/prompts/tools/ask_user.md +61 -0
- connectonion/cli/co_ai/prompts/tools/background.md +57 -0
- connectonion/cli/co_ai/prompts/tools/edit.md +90 -0
- connectonion/cli/co_ai/prompts/tools/glob.md +52 -0
- connectonion/cli/co_ai/prompts/tools/grep.md +55 -0
- connectonion/cli/co_ai/prompts/tools/plan_mode.md +80 -0
- connectonion/cli/co_ai/prompts/tools/read.md +40 -0
- connectonion/cli/co_ai/prompts/tools/shell.md +67 -0
- connectonion/cli/co_ai/prompts/tools/task.md +51 -0
- connectonion/cli/co_ai/prompts/tools/todo.md +139 -0
- connectonion/cli/co_ai/prompts/tools/write.md +47 -0
- connectonion/cli/co_ai/prompts/workflow.md +89 -0
- connectonion/cli/co_ai/reminders.py +159 -0
- connectonion/cli/co_ai/sessions.py +110 -0
- connectonion/cli/co_ai/skills/__init__.py +37 -0
- connectonion/cli/co_ai/skills/builtin/commit/SKILL.md +63 -0
- connectonion/cli/co_ai/skills/builtin/review-pr/SKILL.md +76 -0
- connectonion/cli/co_ai/skills/loader.py +166 -0
- connectonion/cli/co_ai/skills/tool.py +46 -0
- connectonion/cli/co_ai/tools/__init__.py +92 -0
- connectonion/cli/co_ai/tools/ask_user.py +35 -0
- connectonion/cli/co_ai/tools/background.py +201 -0
- connectonion/cli/co_ai/tools/diff_writer.py +291 -0
- connectonion/cli/co_ai/tools/edit.py +89 -0
- connectonion/cli/co_ai/tools/glob.py +84 -0
- connectonion/cli/co_ai/tools/grep.py +158 -0
- connectonion/cli/co_ai/tools/load_guide.py +23 -0
- connectonion/cli/co_ai/tools/multi_edit.py +116 -0
- connectonion/cli/co_ai/tools/plan_mode.py +172 -0
- connectonion/cli/co_ai/tools/read.py +67 -0
- connectonion/cli/co_ai/tools/task.py +59 -0
- connectonion/cli/co_ai/tools/todo_list.py +159 -0
- connectonion/cli/co_ai/tools/write.py +126 -0
- connectonion/cli/commands/__init__.py +11 -1
- connectonion/cli/commands/ai_commands.py +34 -0
- connectonion/cli/commands/copy_commands.py +55 -6
- connectonion/cli/commands/create.py +20 -17
- connectonion/cli/commands/init.py +19 -22
- connectonion/cli/commands/project_cmd_lib.py +15 -0
- connectonion/cli/main.py +11 -0
- connectonion/console.py +15 -1
- connectonion/core/__init__.py +10 -1
- connectonion/core/agent.py +37 -16
- connectonion/core/exceptions.py +74 -0
- connectonion/core/llm.py +54 -6
- connectonion/core/tool_executor.py +32 -31
- connectonion/core/tool_factory.py +47 -10
- connectonion/debug/__init__.py +10 -1
- connectonion/debug/debug_explainer/__init__.py +10 -1
- connectonion/debug/execution_analyzer/__init__.py +10 -1
- connectonion/debug/execution_analyzer/execution_analysis.py +5 -2
- connectonion/debug/runtime_inspector/__init__.py +10 -1
- connectonion/docs/.package-ignore +6 -0
- connectonion/docs/README.md +2036 -0
- connectonion/docs/api.md +457 -0
- connectonion/docs/archive/001-ai-agent-is-just-prompt-plus-function.md +249 -0
- connectonion/docs/archive/README.md +53 -0
- connectonion/docs/archive/archive/consolidation-plan.md +72 -0
- connectonion/docs/archive/archive/core-principles-extracted.md +239 -0
- connectonion/docs/archive/archive/master-principles.md +222 -0
- connectonion/docs/archive/archive/principles.md +293 -0
- connectonion/docs/archive/archive/simplicity-principles.md +221 -0
- connectonion/docs/archive/attack-defense-insights.md +410 -0
- connectonion/docs/archive/business-model.md +305 -0
- connectonion/docs/archive/core-principles-unified.md +190 -0
- connectonion/docs/archive/discussion-journey.md +178 -0
- connectonion/docs/archive/economic-analysis.md +323 -0
- connectonion/docs/archive/features/01-share-and-find.md +256 -0
- connectonion/docs/archive/features/02-agent-authentication.md +93 -0
- connectonion/docs/archive/features/03-test-before-trust.md +71 -0
- connectonion/docs/archive/features/06-reliability-and-offline.md +197 -0
- connectonion/docs/archive/features/README.md +46 -0
- connectonion/docs/archive/features-roadmap.md +247 -0
- connectonion/docs/archive/mcp-comparison-insights.md +215 -0
- connectonion/docs/archive/migration-strategy.md +571 -0
- connectonion/docs/archive/mini-whitepaper.md +293 -0
- connectonion/docs/archive/network-protocol.md +394 -0
- connectonion/docs/archive/semantic-revolution.md +367 -0
- connectonion/docs/archive/technical-architecture.md +453 -0
- connectonion/docs/archive/the-semantic-insight.md +207 -0
- connectonion/docs/archive/threat-model.md +164 -0
- connectonion/docs/cli/README.md +805 -0
- connectonion/docs/cli/auth.md +46 -0
- connectonion/docs/cli/browser.md +235 -0
- connectonion/docs/cli/copy.md +232 -0
- connectonion/docs/cli/create.md +335 -0
- connectonion/docs/cli/init.md +431 -0
- connectonion/docs/co-directory-structure.md +214 -0
- connectonion/docs/concepts/agent.md +1078 -0
- connectonion/docs/concepts/events.md +699 -0
- connectonion/docs/concepts/llm_do.md +256 -0
- connectonion/docs/concepts/max_iterations.md +362 -0
- connectonion/docs/concepts/models.md +641 -0
- connectonion/docs/concepts/plugins.md +100 -0
- connectonion/docs/concepts/prompts.md +122 -0
- connectonion/docs/concepts/session.md +428 -0
- connectonion/docs/concepts/tools.md +512 -0
- connectonion/docs/concepts/transcribe.md +156 -0
- connectonion/docs/concepts/trust.md +291 -0
- connectonion/docs/connectonion.md +1256 -0
- connectonion/docs/debug/README.md +18 -0
- connectonion/docs/debug/auto_debug.md +1026 -0
- connectonion/docs/debug/console.md +129 -0
- connectonion/docs/debug/eval-format.md +178 -0
- connectonion/docs/debug/eval.md +230 -0
- connectonion/docs/debug/exceptions.md +307 -0
- connectonion/docs/debug/log.md +117 -0
- connectonion/docs/debug/xray.md +215 -0
- connectonion/docs/design-decisions/001-choosing-input-method.md +202 -0
- connectonion/docs/design-decisions/002-choosing-llm-function-name.md +202 -0
- connectonion/docs/design-decisions/003-choosing-trust-keyword.md +141 -0
- connectonion/docs/design-decisions/004-cli-create-flow.md +117 -0
- connectonion/docs/design-decisions/005-designing-agent-network-protocol.md +503 -0
- connectonion/docs/design-decisions/006-agent-address-format.md +305 -0
- connectonion/docs/design-decisions/007-authentication-backend-design.md +240 -0
- connectonion/docs/design-decisions/008-naming-is-hard.md +228 -0
- connectonion/docs/design-decisions/009-why-connect-function.md +167 -0
- connectonion/docs/design-decisions/010-cli-ux-progressive-disclosure.md +176 -0
- connectonion/docs/design-decisions/011-global-config-identity-management.md +357 -0
- connectonion/docs/design-decisions/012-tool-execution-separation.md +259 -0
- connectonion/docs/design-decisions/013-debug-and-logging-design.md +253 -0
- connectonion/docs/design-decisions/014-hook-system-design.md +510 -0
- connectonion/docs/design-decisions/015-interactive-auto-debug-design.md +837 -0
- connectonion/docs/design-decisions/016-why-no-zero-knowledge-proofs.md +358 -0
- connectonion/docs/design-decisions/017-session-logging-and-eval-format.md +120 -0
- connectonion/docs/design-decisions/018-event-api-naming.md +274 -0
- connectonion/docs/design-decisions/019-agent-lifecycle-design.md +655 -0
- connectonion/docs/design-decisions/020-trust-system-and-network-architecture.md +503 -0
- connectonion/docs/design-decisions/021-task-storage-jsonl-design.md +496 -0
- connectonion/docs/design-decisions/022-raw-asgi-implementation.md +273 -0
- connectonion/docs/examples.md +0 -0
- connectonion/docs/hook-system-options.md +364 -0
- connectonion/docs/integrations/README.md +12 -0
- connectonion/docs/integrations/auth.md +450 -0
- connectonion/docs/integrations/google.md +431 -0
- connectonion/docs/integrations/microsoft.md +370 -0
- connectonion/docs/network/README.md +14 -0
- connectonion/docs/network/connect.md +629 -0
- connectonion/docs/network/deploy.md +124 -0
- connectonion/docs/network/host.md +1087 -0
- connectonion/docs/network/io.md +538 -0
- connectonion/docs/network/protocol/agent-relay-protocol.md +495 -0
- connectonion/docs/network/protocol/announce-message.md +115 -0
- connectonion/docs/principles.md +124 -0
- connectonion/docs/quickstart.md +261 -0
- connectonion/docs/roadmap.md +81 -0
- connectonion/docs/templates/README.md +77 -0
- connectonion/docs/templates/meta-agent.md +152 -0
- connectonion/docs/templates/minimal.md +105 -0
- connectonion/docs/templates/playwright.md +130 -0
- connectonion/docs/templates/web-research.md +144 -0
- connectonion/docs/tui/README.md +95 -0
- connectonion/docs/tui/chat.md +181 -0
- connectonion/docs/tui/divider.md +63 -0
- connectonion/docs/tui/dropdown.md +83 -0
- connectonion/docs/tui/footer.md +44 -0
- connectonion/docs/tui/fuzzy.md +68 -0
- connectonion/docs/tui/input.md +84 -0
- connectonion/docs/tui/keys.md +77 -0
- connectonion/docs/tui/pick.md +71 -0
- connectonion/docs/tui/providers.md +89 -0
- connectonion/docs/tui/status_bar.md +67 -0
- connectonion/docs/useful_plugins/README.md +160 -0
- connectonion/docs/useful_plugins/calendar_plugin.md +68 -0
- connectonion/docs/useful_plugins/eval.md +89 -0
- connectonion/docs/useful_plugins/gmail_plugin.md +68 -0
- connectonion/docs/useful_plugins/image_result_formatter.md +74 -0
- connectonion/docs/useful_plugins/re_act.md +86 -0
- connectonion/docs/useful_plugins/shell_approval.md +69 -0
- connectonion/docs/useful_plugins/system_reminder.md +210 -0
- connectonion/docs/useful_prompts/README.md +127 -0
- connectonion/docs/useful_prompts/coding_agent.md +214 -0
- connectonion/docs/useful_tools/README.md +81 -0
- connectonion/docs/useful_tools/ask_user.md +103 -0
- connectonion/docs/useful_tools/diff_writer.md +158 -0
- connectonion/docs/useful_tools/get_emails.md +519 -0
- connectonion/docs/useful_tools/gmail.md +155 -0
- connectonion/docs/useful_tools/google_calendar.md +126 -0
- connectonion/docs/useful_tools/memory.md +506 -0
- connectonion/docs/useful_tools/microsoft_calendar.md +126 -0
- connectonion/docs/useful_tools/outlook.md +140 -0
- connectonion/docs/useful_tools/send_email.md +423 -0
- connectonion/docs/useful_tools/shell.md +115 -0
- connectonion/docs/useful_tools/slash_command.md +116 -0
- connectonion/docs/useful_tools/terminal.md +115 -0
- connectonion/docs/useful_tools/todo_list.md +272 -0
- connectonion/docs/useful_tools/web_fetch.md +150 -0
- connectonion/docs/vibe-coding-guide.md +97 -0
- connectonion/docs/windows-support.md +258 -0
- connectonion/logger.py +3 -3
- connectonion/network/__init__.py +19 -6
- connectonion/network/asgi/__init__.py +81 -0
- connectonion/network/asgi/http.py +205 -0
- connectonion/network/asgi/websocket.py +217 -0
- connectonion/network/connect.py +232 -185
- connectonion/network/host/__init__.py +59 -0
- connectonion/network/host/auth.py +191 -0
- connectonion/network/host/routes.py +135 -0
- connectonion/network/host/server.py +289 -0
- connectonion/network/host/session.py +78 -0
- connectonion/network/io/__init__.py +21 -0
- connectonion/network/{connection.py → io/base.py} +17 -42
- connectonion/network/io/websocket.py +55 -0
- connectonion/network/relay.py +37 -16
- connectonion/network/trust/__init__.py +30 -0
- connectonion/network/trust/factory.py +138 -0
- connectonion/network/{trust_agents.py → trust/prompts.py} +3 -3
- connectonion/network/{trust_functions.py → trust/tools.py} +2 -2
- connectonion/prompt_files/__init__.py +11 -1
- connectonion/prompt_files/react_acknowledge.md +26 -0
- connectonion/prompts.py +10 -1
- connectonion/tui/chat.py +10 -1
- connectonion/tui/divider.py +10 -1
- connectonion/tui/dropdown.py +10 -1
- connectonion/tui/footer.py +8 -0
- connectonion/tui/fuzzy.py +11 -1
- connectonion/tui/input.py +118 -70
- connectonion/tui/keys.py +133 -6
- connectonion/tui/providers.py +11 -1
- connectonion/tui/status_bar.py +10 -1
- connectonion/useful_events_handlers/__init__.py +8 -0
- connectonion/useful_events_handlers/reflect.py +19 -4
- connectonion/useful_plugins/__init__.py +2 -1
- connectonion/useful_plugins/eval.py +2 -2
- connectonion/useful_plugins/gmail_plugin.py +3 -3
- connectonion/useful_plugins/image_result_formatter.py +3 -3
- connectonion/useful_plugins/re_act.py +114 -28
- connectonion/useful_plugins/shell_approval.py +2 -2
- connectonion/useful_plugins/system_reminder.py +103 -0
- connectonion/useful_plugins/ui_stream.py +18 -133
- connectonion/useful_prompts/README.md +61 -0
- connectonion/useful_prompts/__init__.py +45 -0
- connectonion/useful_prompts/coding_agent/README.md +106 -0
- connectonion/useful_prompts/coding_agent/assembler.py +123 -0
- connectonion/useful_prompts/coding_agent/prompts/main.md +227 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/ask_user.md +61 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/background.md +57 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/edit.md +90 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/glob.md +52 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/grep.md +55 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/plan_mode.md +80 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/read.md +40 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/shell.md +67 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/task.md +51 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/todo.md +139 -0
- connectonion/useful_prompts/coding_agent/prompts/tools/write.md +48 -0
- connectonion/useful_prompts/system-reminders/security-warning.md +14 -0
- connectonion/useful_prompts/system-reminders/test-reminder.md +11 -0
- connectonion/useful_tools/__init__.py +31 -4
- connectonion/useful_tools/ask_user.py +35 -0
- connectonion/useful_tools/bash.py +69 -0
- connectonion/useful_tools/diff_writer.py +186 -94
- connectonion/useful_tools/edit.py +102 -0
- connectonion/useful_tools/glob_files.py +97 -0
- connectonion/useful_tools/grep_files.py +171 -0
- connectonion/useful_tools/multi_edit.py +116 -0
- connectonion/useful_tools/read_file.py +73 -0
- connectonion/useful_tools/shell.py +50 -45
- connectonion/useful_tools/write_file.py +129 -0
- {connectonion-0.6.1.dist-info → connectonion-0.6.3.dist-info}/METADATA +10 -3
- connectonion-0.6.3.dist-info/RECORD +469 -0
- connectonion/cli/browser_agent/scroll_strategies.py +0 -276
- connectonion/network/asgi.py +0 -407
- connectonion/network/host.py +0 -616
- connectonion/network/trust.py +0 -166
- connectonion-0.6.1.dist-info/RECORD +0 -123
- /connectonion/cli/{docs → co_ai/prompts/connectonion}/connectonion.md +0 -0
- {connectonion-0.6.1.dist-info → connectonion-0.6.3.dist-info}/WHEEL +0 -0
- {connectonion-0.6.1.dist-info → connectonion-0.6.3.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Purpose: Grep tool for content searching
|
|
3
|
+
LLM-Note:
|
|
4
|
+
Dependencies: imports from [re, pathlib, typing, .glob_files] | imported by [useful_tools/__init__]
|
|
5
|
+
Data flow: Agent calls grep(pattern) -> searches files -> returns matches
|
|
6
|
+
State/Effects: reads filesystem (no writes)
|
|
7
|
+
Integration: exposes grep(pattern, path, file_pattern, output_mode) function | used as agent tool
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
grep("def main") # Find "def main" in all files
|
|
11
|
+
grep("TODO|FIXME", file_pattern="*.py") # Find TODOs in Python files
|
|
12
|
+
grep("class.*Agent", output_mode="content") # Show matching lines
|
|
13
|
+
grep("import", output_mode="count") # Count imports per file
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
import re
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import Optional, Literal
|
|
19
|
+
|
|
20
|
+
from .glob_files import IGNORE_DIRS
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def grep(
|
|
24
|
+
pattern: str,
|
|
25
|
+
path: Optional[str] = None,
|
|
26
|
+
file_pattern: Optional[str] = None,
|
|
27
|
+
output_mode: Literal["files", "content", "count"] = "files",
|
|
28
|
+
context_lines: int = 0,
|
|
29
|
+
ignore_case: bool = False,
|
|
30
|
+
max_results: int = 50,
|
|
31
|
+
) -> str:
|
|
32
|
+
"""
|
|
33
|
+
Search for content in files using regex.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
pattern: Regular expression pattern to search for
|
|
37
|
+
path: File or directory to search in (default: current directory)
|
|
38
|
+
file_pattern: Glob pattern to filter files (e.g., "*.py", "*.ts")
|
|
39
|
+
output_mode:
|
|
40
|
+
- "files": Return only matching file paths (default)
|
|
41
|
+
- "content": Return matching lines with context
|
|
42
|
+
- "count": Return match counts per file
|
|
43
|
+
context_lines: Number of lines to show before/after match (for content mode)
|
|
44
|
+
ignore_case: Case insensitive search
|
|
45
|
+
max_results: Maximum number of results to return
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Search results based on output_mode
|
|
49
|
+
|
|
50
|
+
Examples:
|
|
51
|
+
grep("def main") # Find "def main" in all files
|
|
52
|
+
grep("TODO|FIXME", file_pattern="*.py") # Find TODOs in Python files
|
|
53
|
+
grep("class.*Agent", output_mode="content") # Show matching lines
|
|
54
|
+
grep("import", output_mode="count") # Count imports per file
|
|
55
|
+
"""
|
|
56
|
+
base = Path(path) if path else Path.cwd()
|
|
57
|
+
|
|
58
|
+
if not base.exists():
|
|
59
|
+
return f"Error: Path '{base}' does not exist"
|
|
60
|
+
|
|
61
|
+
# Compile regex
|
|
62
|
+
flags = re.IGNORECASE if ignore_case else 0
|
|
63
|
+
try:
|
|
64
|
+
regex = re.compile(pattern, flags)
|
|
65
|
+
except re.error as e:
|
|
66
|
+
return f"Error: Invalid regex pattern: {e}"
|
|
67
|
+
|
|
68
|
+
# Collect files to search
|
|
69
|
+
if base.is_file():
|
|
70
|
+
files = [base]
|
|
71
|
+
else:
|
|
72
|
+
if file_pattern:
|
|
73
|
+
files = list(base.glob(f"**/{file_pattern}"))
|
|
74
|
+
else:
|
|
75
|
+
files = list(base.glob("**/*"))
|
|
76
|
+
|
|
77
|
+
files = [f for f in files if f.is_file() and not _should_ignore(f) and _is_text_file(f)]
|
|
78
|
+
|
|
79
|
+
results = []
|
|
80
|
+
total_matches = 0
|
|
81
|
+
|
|
82
|
+
for file in files:
|
|
83
|
+
if total_matches >= max_results:
|
|
84
|
+
break
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
content = file.read_text(encoding="utf-8", errors="ignore")
|
|
88
|
+
lines = content.splitlines()
|
|
89
|
+
except Exception:
|
|
90
|
+
continue
|
|
91
|
+
|
|
92
|
+
file_matches = []
|
|
93
|
+
for i, line in enumerate(lines):
|
|
94
|
+
if regex.search(line):
|
|
95
|
+
file_matches.append((i + 1, line)) # 1-indexed line number
|
|
96
|
+
|
|
97
|
+
if not file_matches:
|
|
98
|
+
continue
|
|
99
|
+
|
|
100
|
+
rel_path = _relative_path(file, base)
|
|
101
|
+
|
|
102
|
+
if output_mode == "files":
|
|
103
|
+
results.append(str(rel_path))
|
|
104
|
+
total_matches += 1
|
|
105
|
+
|
|
106
|
+
elif output_mode == "count":
|
|
107
|
+
results.append(f"{rel_path}: {len(file_matches)} matches")
|
|
108
|
+
total_matches += 1
|
|
109
|
+
|
|
110
|
+
elif output_mode == "content":
|
|
111
|
+
results.append(f"\n{rel_path}:")
|
|
112
|
+
for line_num, line_text in file_matches[:10]: # Limit per file
|
|
113
|
+
# Add context if requested
|
|
114
|
+
if context_lines > 0:
|
|
115
|
+
start = max(0, line_num - 1 - context_lines)
|
|
116
|
+
end = min(len(lines), line_num + context_lines)
|
|
117
|
+
for ctx_i in range(start, end):
|
|
118
|
+
prefix = ">" if ctx_i == line_num - 1 else " "
|
|
119
|
+
results.append(f" {prefix} {ctx_i + 1}: {lines[ctx_i]}")
|
|
120
|
+
results.append("")
|
|
121
|
+
else:
|
|
122
|
+
results.append(f" {line_num}: {line_text}")
|
|
123
|
+
total_matches += 1
|
|
124
|
+
|
|
125
|
+
if total_matches >= max_results:
|
|
126
|
+
break
|
|
127
|
+
|
|
128
|
+
if not results:
|
|
129
|
+
return f"No matches found for '{pattern}'"
|
|
130
|
+
|
|
131
|
+
output = "\n".join(results)
|
|
132
|
+
|
|
133
|
+
if total_matches >= max_results:
|
|
134
|
+
output += f"\n\n... results truncated at {max_results}"
|
|
135
|
+
|
|
136
|
+
return output
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def _should_ignore(path: Path) -> bool:
|
|
140
|
+
"""Check if path should be ignored."""
|
|
141
|
+
parts = path.parts
|
|
142
|
+
for part in parts:
|
|
143
|
+
if part in IGNORE_DIRS:
|
|
144
|
+
return True
|
|
145
|
+
for ignore in IGNORE_DIRS:
|
|
146
|
+
if "*" in ignore and Path(part).match(ignore):
|
|
147
|
+
return True
|
|
148
|
+
return False
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _is_text_file(path: Path) -> bool:
|
|
152
|
+
"""Check if file is likely a text file."""
|
|
153
|
+
# Skip binary file extensions
|
|
154
|
+
binary_extensions = {
|
|
155
|
+
".pyc", ".pyo", ".so", ".dylib", ".dll", ".exe",
|
|
156
|
+
".png", ".jpg", ".jpeg", ".gif", ".ico", ".svg",
|
|
157
|
+
".pdf", ".doc", ".docx", ".xls", ".xlsx",
|
|
158
|
+
".zip", ".tar", ".gz", ".rar", ".7z",
|
|
159
|
+
".mp3", ".mp4", ".wav", ".avi", ".mov",
|
|
160
|
+
".ttf", ".woff", ".woff2", ".eot",
|
|
161
|
+
".lock", ".bin", ".dat",
|
|
162
|
+
}
|
|
163
|
+
return path.suffix.lower() not in binary_extensions
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def _relative_path(path: Path, base: Path) -> Path:
|
|
167
|
+
"""Get relative path, handling edge cases."""
|
|
168
|
+
try:
|
|
169
|
+
return path.relative_to(base)
|
|
170
|
+
except ValueError:
|
|
171
|
+
return path
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Purpose: Atomic multiple string replacements in a single file (Claude Code-style)
|
|
3
|
+
LLM-Note:
|
|
4
|
+
Dependencies: imports from [pathlib, typing] | imported by [useful_tools/__init__]
|
|
5
|
+
Data flow: Agent calls multi_edit(file_path, edits) -> validates all edits -> applies sequentially -> returns status
|
|
6
|
+
State/Effects: reads and writes file on filesystem | atomic (all succeed or none applied)
|
|
7
|
+
Integration: exposes multi_edit(file_path, edits) function | used as agent tool
|
|
8
|
+
Errors: returns error if file not found | returns error if any old_string not found | rolls back on failure
|
|
9
|
+
|
|
10
|
+
Usage:
|
|
11
|
+
multi_edit("app.py", [
|
|
12
|
+
{"old_string": "def foo():", "new_string": "def bar():"},
|
|
13
|
+
{"old_string": "return None", "new_string": "return True"},
|
|
14
|
+
])
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
from typing import List, TypedDict
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class EditOperation(TypedDict, total=False):
|
|
22
|
+
"""Single edit operation."""
|
|
23
|
+
old_string: str # Required: exact string to replace
|
|
24
|
+
new_string: str # Required: replacement string
|
|
25
|
+
replace_all: bool # Optional: replace all occurrences (default: False)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def multi_edit(
|
|
29
|
+
file_path: str,
|
|
30
|
+
edits: List[EditOperation],
|
|
31
|
+
) -> str:
|
|
32
|
+
"""
|
|
33
|
+
Apply multiple string replacements to a file atomically.
|
|
34
|
+
|
|
35
|
+
All edits succeed or none are applied. Edits are applied sequentially,
|
|
36
|
+
so earlier edits affect the text that later edits search for.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
file_path: Path to the file to edit
|
|
40
|
+
edits: List of edit operations, each with:
|
|
41
|
+
- old_string: Exact string to replace
|
|
42
|
+
- new_string: Replacement string
|
|
43
|
+
- replace_all: If True, replace all occurrences (default: False)
|
|
44
|
+
|
|
45
|
+
Returns:
|
|
46
|
+
Success message or error description
|
|
47
|
+
|
|
48
|
+
Examples:
|
|
49
|
+
multi_edit("app.py", [
|
|
50
|
+
{"old_string": "def foo():", "new_string": "def bar():"},
|
|
51
|
+
{"old_string": "foo()", "new_string": "bar()", "replace_all": True},
|
|
52
|
+
])
|
|
53
|
+
"""
|
|
54
|
+
path = Path(file_path)
|
|
55
|
+
|
|
56
|
+
if not path.exists():
|
|
57
|
+
return f"Error: File '{file_path}' does not exist"
|
|
58
|
+
|
|
59
|
+
if not path.is_file():
|
|
60
|
+
return f"Error: '{file_path}' is not a file"
|
|
61
|
+
|
|
62
|
+
if not edits:
|
|
63
|
+
return "Error: No edits provided"
|
|
64
|
+
|
|
65
|
+
# Read original content
|
|
66
|
+
original_content = path.read_text(encoding="utf-8")
|
|
67
|
+
content = original_content
|
|
68
|
+
|
|
69
|
+
# Validate and apply edits
|
|
70
|
+
applied = []
|
|
71
|
+
for i, edit in enumerate(edits):
|
|
72
|
+
old_string = edit.get("old_string", "")
|
|
73
|
+
new_string = edit.get("new_string", "")
|
|
74
|
+
replace_all = edit.get("replace_all", False)
|
|
75
|
+
|
|
76
|
+
if not old_string:
|
|
77
|
+
return f"Error: Edit {i+1} missing 'old_string'"
|
|
78
|
+
|
|
79
|
+
# Check if old_string exists in current content
|
|
80
|
+
count = content.count(old_string)
|
|
81
|
+
|
|
82
|
+
if count == 0:
|
|
83
|
+
# Show what edits were successful before failure
|
|
84
|
+
if applied:
|
|
85
|
+
applied_msg = "\n".join([f" {j+1}. Replaced '{e['old']}'" for j, e in enumerate(applied)])
|
|
86
|
+
return (
|
|
87
|
+
f"Error: Edit {i+1} failed - string not found after previous edits.\n"
|
|
88
|
+
f"Looking for: {repr(old_string[:100])}\n\n"
|
|
89
|
+
f"Successfully applied before failure:\n{applied_msg}\n\n"
|
|
90
|
+
f"No changes were saved (atomic operation)."
|
|
91
|
+
)
|
|
92
|
+
return f"Error: Edit {i+1} - string not found in '{file_path}': {repr(old_string[:100])}"
|
|
93
|
+
|
|
94
|
+
if count > 1 and not replace_all:
|
|
95
|
+
return (
|
|
96
|
+
f"Error: Edit {i+1} - string appears {count} times. "
|
|
97
|
+
f"Use replace_all=True or provide more context.\n"
|
|
98
|
+
f"String: {repr(old_string[:100])}"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
# Apply this edit
|
|
102
|
+
if replace_all:
|
|
103
|
+
content = content.replace(old_string, new_string)
|
|
104
|
+
applied.append({"old": old_string[:50], "count": count})
|
|
105
|
+
else:
|
|
106
|
+
content = content.replace(old_string, new_string, 1)
|
|
107
|
+
applied.append({"old": old_string[:50], "count": 1})
|
|
108
|
+
|
|
109
|
+
# All edits validated and applied in memory - now write to file
|
|
110
|
+
path.write_text(content, encoding="utf-8")
|
|
111
|
+
|
|
112
|
+
# Build success message
|
|
113
|
+
total_replacements = sum(e["count"] for e in applied)
|
|
114
|
+
if len(edits) == 1:
|
|
115
|
+
return f"Successfully edited '{file_path}'"
|
|
116
|
+
return f"Successfully applied {len(edits)} edits ({total_replacements} replacements) to '{file_path}'"
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Purpose: Read file tool with line numbers
|
|
3
|
+
LLM-Note:
|
|
4
|
+
Dependencies: imports from [pathlib, typing] | imported by [useful_tools/__init__]
|
|
5
|
+
Data flow: Agent calls read_file(path) -> reads file -> returns content with line numbers
|
|
6
|
+
State/Effects: reads file from filesystem
|
|
7
|
+
Integration: exposes read_file(path, offset, limit) function | used as agent tool
|
|
8
|
+
|
|
9
|
+
Usage:
|
|
10
|
+
read_file("app.py") # Read entire file
|
|
11
|
+
read_file("large.log", offset=100) # Start from line 100
|
|
12
|
+
read_file("data.csv", limit=50) # First 50 lines
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Optional
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def read_file(
|
|
20
|
+
path: str,
|
|
21
|
+
offset: Optional[int] = None,
|
|
22
|
+
limit: Optional[int] = None,
|
|
23
|
+
) -> str:
|
|
24
|
+
"""
|
|
25
|
+
Read and return the contents of a file with line numbers.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
path: Path to the file to read
|
|
29
|
+
offset: Line number to start from (1-indexed, default: 1)
|
|
30
|
+
limit: Number of lines to read (default: 2000)
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
File contents with line numbers
|
|
34
|
+
|
|
35
|
+
Examples:
|
|
36
|
+
read_file("app.py") # Read entire file
|
|
37
|
+
read_file("large.log", offset=100) # Start from line 100
|
|
38
|
+
read_file("data.csv", limit=50) # First 50 lines
|
|
39
|
+
"""
|
|
40
|
+
file_path = Path(path)
|
|
41
|
+
|
|
42
|
+
if not file_path.exists():
|
|
43
|
+
return f"Error: File '{path}' does not exist"
|
|
44
|
+
|
|
45
|
+
if not file_path.is_file():
|
|
46
|
+
return f"Error: '{path}' is not a file"
|
|
47
|
+
|
|
48
|
+
content = file_path.read_text(encoding="utf-8", errors="replace")
|
|
49
|
+
lines = content.splitlines()
|
|
50
|
+
|
|
51
|
+
total_lines = len(lines)
|
|
52
|
+
|
|
53
|
+
# Apply offset and limit
|
|
54
|
+
start = (offset - 1) if offset and offset > 0 else 0
|
|
55
|
+
end = (start + limit) if limit else len(lines)
|
|
56
|
+
|
|
57
|
+
selected_lines = lines[start:end]
|
|
58
|
+
|
|
59
|
+
# Format with line numbers
|
|
60
|
+
result_lines = []
|
|
61
|
+
for i, line in enumerate(selected_lines, start=start + 1):
|
|
62
|
+
# Truncate very long lines
|
|
63
|
+
if len(line) > 500:
|
|
64
|
+
line = line[:500] + "..."
|
|
65
|
+
result_lines.append(f"{i:>6}\t{line}")
|
|
66
|
+
|
|
67
|
+
result = "\n".join(result_lines)
|
|
68
|
+
|
|
69
|
+
# Add info about truncation
|
|
70
|
+
if end < total_lines:
|
|
71
|
+
result += f"\n\n... ({total_lines - end} more lines)"
|
|
72
|
+
|
|
73
|
+
return result
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
LLM-Note:
|
|
4
|
-
Dependencies: imports from [subprocess] | imported by [useful_tools/__init__.py] | tested by [tests/unit/test_shell_tool.py]
|
|
5
|
-
Data flow: Agent calls Shell.run(command) → subprocess.run() executes in shell → captures stdout+stderr → returns combined output string
|
|
6
|
-
State/Effects: executes shell commands on host system | can modify filesystem, install packages, run programs | uses working directory specified in constructor | no persistent state
|
|
7
|
-
Integration: exposes Shell class with run(command), run_in_dir(command, directory) | used as agent tool via Agent(tools=[Shell()])
|
|
8
|
-
Performance: process spawn overhead per command | command execution time varies | no caching
|
|
9
|
-
Errors: returns error message if command fails | captures stderr in output | no exceptions raised (returns error strings)
|
|
10
|
-
|
|
11
|
-
Shell tool for executing terminal commands.
|
|
2
|
+
Shell tool for executing terminal commands (cross-platform).
|
|
12
3
|
|
|
13
4
|
Usage:
|
|
14
5
|
from connectonion import Agent, Shell
|
|
@@ -19,13 +10,16 @@ Usage:
|
|
|
19
10
|
# Agent can now use:
|
|
20
11
|
# - run(command) - Execute shell command, returns output
|
|
21
12
|
# - run_in_dir(command, directory) - Execute in specific directory
|
|
13
|
+
|
|
14
|
+
Note: Uses system default shell (bash/sh on Unix, cmd on Windows).
|
|
15
|
+
For Unix-specific bash, use the `bash` function from bash.py instead.
|
|
22
16
|
"""
|
|
23
17
|
|
|
24
18
|
import subprocess
|
|
25
19
|
|
|
26
20
|
|
|
27
21
|
class Shell:
|
|
28
|
-
"""Shell command execution tool."""
|
|
22
|
+
"""Shell command execution tool (cross-platform)."""
|
|
29
23
|
|
|
30
24
|
def __init__(self, cwd: str = "."):
|
|
31
25
|
"""Initialize Shell tool.
|
|
@@ -35,54 +29,61 @@ class Shell:
|
|
|
35
29
|
"""
|
|
36
30
|
self.cwd = cwd
|
|
37
31
|
|
|
38
|
-
def run(self, command: str) -> str:
|
|
32
|
+
def run(self, command: str, timeout: int = 120) -> str:
|
|
39
33
|
"""Execute a shell command, returns output.
|
|
40
34
|
|
|
41
35
|
Args:
|
|
42
36
|
command: Shell command to execute (e.g., "ls -la", "git status")
|
|
37
|
+
timeout: Seconds before timeout (default: 120, max: 600)
|
|
43
38
|
|
|
44
39
|
Returns:
|
|
45
40
|
Command output (stdout + stderr)
|
|
46
41
|
"""
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
if len(output) > 1000:
|
|
65
|
-
output = output[:1000] + f"\n... (truncated, {len(output):,} total chars)"
|
|
66
|
-
return output
|
|
67
|
-
|
|
68
|
-
def run_in_dir(self, command: str, directory: str) -> str:
|
|
42
|
+
timeout = min(timeout, 600)
|
|
43
|
+
|
|
44
|
+
try:
|
|
45
|
+
result = subprocess.run(
|
|
46
|
+
command,
|
|
47
|
+
shell=True,
|
|
48
|
+
capture_output=True,
|
|
49
|
+
text=True,
|
|
50
|
+
cwd=self.cwd,
|
|
51
|
+
timeout=timeout
|
|
52
|
+
)
|
|
53
|
+
except subprocess.TimeoutExpired:
|
|
54
|
+
return f"Error: Command timed out after {timeout} seconds"
|
|
55
|
+
|
|
56
|
+
return self._format_output(result)
|
|
57
|
+
|
|
58
|
+
def run_in_dir(self, command: str, directory: str, timeout: int = 120) -> str:
|
|
69
59
|
"""Execute command in a specific directory.
|
|
70
60
|
|
|
71
61
|
Args:
|
|
72
62
|
command: Shell command to execute
|
|
73
63
|
directory: Directory to run the command in
|
|
64
|
+
timeout: Seconds before timeout (default: 120, max: 600)
|
|
74
65
|
|
|
75
66
|
Returns:
|
|
76
67
|
Command output (stdout + stderr)
|
|
77
68
|
"""
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
69
|
+
timeout = min(timeout, 600)
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
result = subprocess.run(
|
|
73
|
+
command,
|
|
74
|
+
shell=True,
|
|
75
|
+
capture_output=True,
|
|
76
|
+
text=True,
|
|
77
|
+
cwd=directory,
|
|
78
|
+
timeout=timeout
|
|
79
|
+
)
|
|
80
|
+
except subprocess.TimeoutExpired:
|
|
81
|
+
return f"Error: Command timed out after {timeout} seconds"
|
|
82
|
+
|
|
83
|
+
return self._format_output(result)
|
|
84
|
+
|
|
85
|
+
def _format_output(self, result: subprocess.CompletedProcess) -> str:
|
|
86
|
+
"""Format subprocess result into readable output."""
|
|
86
87
|
parts = []
|
|
87
88
|
if result.stdout:
|
|
88
89
|
parts.append(result.stdout.rstrip())
|
|
@@ -92,6 +93,10 @@ class Shell:
|
|
|
92
93
|
parts.append(f"\nExit code: {result.returncode}")
|
|
93
94
|
|
|
94
95
|
output = "\n".join(parts) if parts else "(no output)"
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
|
|
97
|
+
# Truncate large outputs
|
|
98
|
+
max_chars = 10000
|
|
99
|
+
if len(output) > max_chars:
|
|
100
|
+
output = output[:max_chars] + f"\n... (truncated, {len(output):,} total chars)"
|
|
101
|
+
|
|
102
|
+
return output
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Purpose: Write file tool with Claude Code-style approval (web mode)
|
|
3
|
+
LLM-Note:
|
|
4
|
+
Dependencies: imports from [.diff_writer] | imported by [useful_tools/__init__]
|
|
5
|
+
Data flow: Agent calls write(path, content) -> DiffWriter handles approval via io -> writes file
|
|
6
|
+
State/Effects: writes file to filesystem | sends events via io for approval
|
|
7
|
+
Integration: exposes write(path, content) function and Write class | used as agent tool
|
|
8
|
+
|
|
9
|
+
This is a wrapper around DiffWriter for simpler function-based usage.
|
|
10
|
+
For class-based usage with mode control, use DiffWriter directly.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
from .diff_writer import DiffWriter, MODE_NORMAL, MODE_AUTO, MODE_PLAN
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Global writer instance for function-based API
|
|
20
|
+
_writer: Optional[DiffWriter] = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def _get_writer() -> DiffWriter:
|
|
24
|
+
"""Get or create the global writer instance."""
|
|
25
|
+
global _writer
|
|
26
|
+
if _writer is None:
|
|
27
|
+
_writer = DiffWriter(mode=MODE_AUTO) # Default to auto for function API
|
|
28
|
+
return _writer
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def write(path: str, content: str) -> str:
|
|
32
|
+
"""
|
|
33
|
+
Write content to a file (full overwrite).
|
|
34
|
+
|
|
35
|
+
For new files or when replacing most of the content.
|
|
36
|
+
Use edit() for small, targeted changes instead.
|
|
37
|
+
|
|
38
|
+
Args:
|
|
39
|
+
path: File path to write to
|
|
40
|
+
content: Complete file content
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
Success message or error description
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
write("new_file.py", "print('hello')")
|
|
47
|
+
write("config.json", '{"debug": true}')
|
|
48
|
+
"""
|
|
49
|
+
writer = _get_writer()
|
|
50
|
+
return writer.write(path, content)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class FileWriter:
|
|
54
|
+
"""File writer with Claude Code-style permission modes (web mode).
|
|
55
|
+
|
|
56
|
+
Use this class when you need mode control (normal/auto/plan).
|
|
57
|
+
For simple writes, use the write() function instead.
|
|
58
|
+
|
|
59
|
+
Usage:
|
|
60
|
+
writer = FileWriter(mode="normal") # Prompt for every write
|
|
61
|
+
writer = FileWriter(mode="auto") # Auto-approve all writes
|
|
62
|
+
writer = FileWriter(mode="plan") # Read-only, preview only
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def __init__(self, mode: str = MODE_NORMAL):
|
|
66
|
+
"""Initialize Write tool.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
mode: Permission mode - "normal" (prompt), "auto" (auto-approve), "plan" (read-only)
|
|
70
|
+
"""
|
|
71
|
+
self._writer = DiffWriter(mode=mode)
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def io(self):
|
|
75
|
+
"""IO channel for web mode."""
|
|
76
|
+
return self._writer.io
|
|
77
|
+
|
|
78
|
+
@io.setter
|
|
79
|
+
def io(self, value):
|
|
80
|
+
"""Set IO channel."""
|
|
81
|
+
self._writer.io = value
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def mode(self):
|
|
85
|
+
"""Current permission mode."""
|
|
86
|
+
return self._writer.mode
|
|
87
|
+
|
|
88
|
+
@mode.setter
|
|
89
|
+
def mode(self, value):
|
|
90
|
+
"""Set permission mode."""
|
|
91
|
+
self._writer.mode = value
|
|
92
|
+
|
|
93
|
+
def write(self, path: str, content: str) -> str:
|
|
94
|
+
"""Write content to a file. Both path and content are REQUIRED.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
path: File path to write to (REQUIRED)
|
|
98
|
+
content: Complete file content (REQUIRED)
|
|
99
|
+
|
|
100
|
+
Returns:
|
|
101
|
+
Success message or error
|
|
102
|
+
|
|
103
|
+
Example:
|
|
104
|
+
write(path="/tmp/agent.py", content="from connectonion import Agent...")
|
|
105
|
+
"""
|
|
106
|
+
return self._writer.write(path, content)
|
|
107
|
+
|
|
108
|
+
def diff(self, path: str, content: str) -> str:
|
|
109
|
+
"""Show diff without writing (preview mode).
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
path: File path to compare against
|
|
113
|
+
content: New content to compare
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
Diff string in unified format
|
|
117
|
+
"""
|
|
118
|
+
return self._writer.diff(path, content)
|
|
119
|
+
|
|
120
|
+
def read(self, path: str) -> str:
|
|
121
|
+
"""Read file contents.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
path: File path to read
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
File contents or error message
|
|
128
|
+
"""
|
|
129
|
+
return self._writer.read(path)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: connectonion
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.3
|
|
4
4
|
Summary: A simple Python framework for creating AI agents with behavior tracking
|
|
5
5
|
Project-URL: Homepage, https://github.com/openonion/connectonion
|
|
6
6
|
Project-URL: Documentation, https://docs.connectonion.com
|
|
@@ -334,9 +334,16 @@ analyst = Agent("analyst", tools=[analyze], plugins=[reflection])
|
|
|
334
334
|
- **Reusable capabilities**: Package event handlers into bundles
|
|
335
335
|
- **Simple pattern**: A plugin is just a list of event handlers
|
|
336
336
|
- **Easy composition**: Combine multiple plugins together
|
|
337
|
-
- **Built-in
|
|
337
|
+
- **Built-in plugins**: re_act, eval, system_reminder, image_result_formatter, and more
|
|
338
338
|
|
|
339
|
-
|
|
339
|
+
**Built-in plugins** are ready to use:
|
|
340
|
+
```python
|
|
341
|
+
from connectonion.useful_plugins import re_act, system_reminder
|
|
342
|
+
|
|
343
|
+
agent = Agent("assistant", tools=[search], plugins=[re_act, system_reminder])
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
[Learn more about plugins](docs/plugin.md) | [Built-in plugins](docs/useful_plugins/)
|
|
340
347
|
|
|
341
348
|
## 🔧 Core Concepts
|
|
342
349
|
|