connectonion 0.5.8__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.
Files changed (113) hide show
  1. connectonion/__init__.py +78 -0
  2. connectonion/address.py +320 -0
  3. connectonion/agent.py +450 -0
  4. connectonion/announce.py +84 -0
  5. connectonion/asgi.py +287 -0
  6. connectonion/auto_debug_exception.py +181 -0
  7. connectonion/cli/__init__.py +3 -0
  8. connectonion/cli/browser_agent/__init__.py +5 -0
  9. connectonion/cli/browser_agent/browser.py +243 -0
  10. connectonion/cli/browser_agent/prompt.md +107 -0
  11. connectonion/cli/commands/__init__.py +1 -0
  12. connectonion/cli/commands/auth_commands.py +527 -0
  13. connectonion/cli/commands/browser_commands.py +27 -0
  14. connectonion/cli/commands/create.py +511 -0
  15. connectonion/cli/commands/deploy_commands.py +220 -0
  16. connectonion/cli/commands/doctor_commands.py +173 -0
  17. connectonion/cli/commands/init.py +469 -0
  18. connectonion/cli/commands/project_cmd_lib.py +828 -0
  19. connectonion/cli/commands/reset_commands.py +149 -0
  20. connectonion/cli/commands/status_commands.py +168 -0
  21. connectonion/cli/docs/co-vibecoding-principles-docs-contexts-all-in-one.md +2010 -0
  22. connectonion/cli/docs/connectonion.md +1256 -0
  23. connectonion/cli/docs.md +123 -0
  24. connectonion/cli/main.py +148 -0
  25. connectonion/cli/templates/meta-agent/README.md +287 -0
  26. connectonion/cli/templates/meta-agent/agent.py +196 -0
  27. connectonion/cli/templates/meta-agent/prompts/answer_prompt.md +9 -0
  28. connectonion/cli/templates/meta-agent/prompts/docs_retrieve_prompt.md +15 -0
  29. connectonion/cli/templates/meta-agent/prompts/metagent.md +71 -0
  30. connectonion/cli/templates/meta-agent/prompts/think_prompt.md +18 -0
  31. connectonion/cli/templates/minimal/README.md +56 -0
  32. connectonion/cli/templates/minimal/agent.py +40 -0
  33. connectonion/cli/templates/playwright/README.md +118 -0
  34. connectonion/cli/templates/playwright/agent.py +336 -0
  35. connectonion/cli/templates/playwright/prompt.md +102 -0
  36. connectonion/cli/templates/playwright/requirements.txt +3 -0
  37. connectonion/cli/templates/web-research/agent.py +122 -0
  38. connectonion/connect.py +128 -0
  39. connectonion/console.py +539 -0
  40. connectonion/debug_agent/__init__.py +13 -0
  41. connectonion/debug_agent/agent.py +45 -0
  42. connectonion/debug_agent/prompts/debug_assistant.md +72 -0
  43. connectonion/debug_agent/runtime_inspector.py +406 -0
  44. connectonion/debug_explainer/__init__.py +10 -0
  45. connectonion/debug_explainer/explain_agent.py +114 -0
  46. connectonion/debug_explainer/explain_context.py +263 -0
  47. connectonion/debug_explainer/explainer_prompt.md +29 -0
  48. connectonion/debug_explainer/root_cause_analysis_prompt.md +43 -0
  49. connectonion/debugger_ui.py +1039 -0
  50. connectonion/decorators.py +208 -0
  51. connectonion/events.py +248 -0
  52. connectonion/execution_analyzer/__init__.py +9 -0
  53. connectonion/execution_analyzer/execution_analysis.py +93 -0
  54. connectonion/execution_analyzer/execution_analysis_prompt.md +47 -0
  55. connectonion/host.py +579 -0
  56. connectonion/interactive_debugger.py +342 -0
  57. connectonion/llm.py +801 -0
  58. connectonion/llm_do.py +307 -0
  59. connectonion/logger.py +300 -0
  60. connectonion/prompt_files/__init__.py +1 -0
  61. connectonion/prompt_files/analyze_contact.md +62 -0
  62. connectonion/prompt_files/eval_expected.md +12 -0
  63. connectonion/prompt_files/react_evaluate.md +11 -0
  64. connectonion/prompt_files/react_plan.md +16 -0
  65. connectonion/prompt_files/reflect.md +22 -0
  66. connectonion/prompts.py +144 -0
  67. connectonion/relay.py +200 -0
  68. connectonion/static/docs.html +688 -0
  69. connectonion/tool_executor.py +279 -0
  70. connectonion/tool_factory.py +186 -0
  71. connectonion/tool_registry.py +105 -0
  72. connectonion/trust.py +166 -0
  73. connectonion/trust_agents.py +71 -0
  74. connectonion/trust_functions.py +88 -0
  75. connectonion/tui/__init__.py +57 -0
  76. connectonion/tui/divider.py +39 -0
  77. connectonion/tui/dropdown.py +251 -0
  78. connectonion/tui/footer.py +31 -0
  79. connectonion/tui/fuzzy.py +56 -0
  80. connectonion/tui/input.py +278 -0
  81. connectonion/tui/keys.py +35 -0
  82. connectonion/tui/pick.py +130 -0
  83. connectonion/tui/providers.py +155 -0
  84. connectonion/tui/status_bar.py +163 -0
  85. connectonion/usage.py +161 -0
  86. connectonion/useful_events_handlers/__init__.py +16 -0
  87. connectonion/useful_events_handlers/reflect.py +116 -0
  88. connectonion/useful_plugins/__init__.py +20 -0
  89. connectonion/useful_plugins/calendar_plugin.py +163 -0
  90. connectonion/useful_plugins/eval.py +139 -0
  91. connectonion/useful_plugins/gmail_plugin.py +162 -0
  92. connectonion/useful_plugins/image_result_formatter.py +127 -0
  93. connectonion/useful_plugins/re_act.py +78 -0
  94. connectonion/useful_plugins/shell_approval.py +159 -0
  95. connectonion/useful_tools/__init__.py +44 -0
  96. connectonion/useful_tools/diff_writer.py +192 -0
  97. connectonion/useful_tools/get_emails.py +183 -0
  98. connectonion/useful_tools/gmail.py +1596 -0
  99. connectonion/useful_tools/google_calendar.py +613 -0
  100. connectonion/useful_tools/memory.py +380 -0
  101. connectonion/useful_tools/microsoft_calendar.py +604 -0
  102. connectonion/useful_tools/outlook.py +488 -0
  103. connectonion/useful_tools/send_email.py +205 -0
  104. connectonion/useful_tools/shell.py +97 -0
  105. connectonion/useful_tools/slash_command.py +201 -0
  106. connectonion/useful_tools/terminal.py +285 -0
  107. connectonion/useful_tools/todo_list.py +241 -0
  108. connectonion/useful_tools/web_fetch.py +216 -0
  109. connectonion/xray.py +467 -0
  110. connectonion-0.5.8.dist-info/METADATA +741 -0
  111. connectonion-0.5.8.dist-info/RECORD +113 -0
  112. connectonion-0.5.8.dist-info/WHEEL +4 -0
  113. connectonion-0.5.8.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,149 @@
1
+ """
2
+ Purpose: Delete global ConnectOnion configuration and create fresh account with new Ed25519 keypair
3
+ LLM-Note:
4
+ Dependencies: imports from [sys, shutil, toml, pathlib, rich.console, rich.prompt, rich.panel, address, auth_commands.authenticate, __version__, datetime] | imported by [cli/main.py via handle_reset()] | tested by [tests/cli/test_cli_reset.py]
5
+ Data flow: receives no args → checks ~/.co/ exists → prompts user for 'Y' confirmation with clear warnings → deletes ~/.co/keys/, ~/.co/config.toml, ~/.co/keys.env → recreates directory structure → address.generate() creates new Ed25519 keypair with seed phrase → address.save() saves to ~/.co/keys/ → creates new config.toml with fresh agent identity → calls authenticate(global_dir, save_to_project=False) to register new account and get bonus credits → displays seed phrase in Rich panel → warns user to update project .env files
6
+ State/Effects: DESTRUCTIVE OPERATION | deletes entire ~/.co/ directory contents (keys, config, keys.env) | creates fresh ~/.co/ with new keypair | calls authenticate() which creates new backend account and writes OPENONION_API_KEY to keys.env | writes to stdout via rich.Console with warnings and confirmations | existing projects still have old API key (requires manual 'co init' to update)
7
+ Integration: exposes handle_reset() for CLI | similar to ensure_global_config() in init.py but deletes first | relies on address.generate() for new Ed25519 keypair | calls authenticate() to register new account | displays seed phrase via Rich panel | requires explicit 'Y' confirmation to proceed
8
+ Performance: file deletion is fast (<100ms) | address.generate() is fast (<100ms) | authenticate() makes network call (2-5s) | config file writes are I/O bound
9
+ Errors: gracefully handles missing ~/.co/ (nothing to reset) | requires uppercase 'Y' for confirmation (case-sensitive) | cancels if user types anything else | authenticate() may fail but reset still completes | warns user about data loss before proceeding
10
+ """
11
+
12
+ import sys
13
+ import shutil
14
+ import toml
15
+ from pathlib import Path
16
+ from rich.console import Console
17
+ from rich.prompt import Prompt
18
+ from rich.panel import Panel
19
+
20
+ from ... import address
21
+ from .auth_commands import authenticate
22
+
23
+ console = Console()
24
+
25
+
26
+ def handle_reset():
27
+ """Reset ConnectOnion global configuration and create new account.
28
+
29
+ WARNING: This will delete all your data including:
30
+ - Your Ed25519 keypair and account access
31
+ - Your balance and transaction history
32
+ - All configuration and credentials
33
+
34
+ You will get a fresh new account.
35
+ """
36
+ global_dir = Path.home() / ".co"
37
+
38
+ # Check if global config exists
39
+ if not global_dir.exists():
40
+ console.print("\nāŒ [bold red]No global configuration found[/bold red]")
41
+ console.print("[yellow]Nothing to reset. Run 'co init' to set up ConnectOnion.[/yellow]\n")
42
+ return
43
+
44
+ # Show clear warning
45
+ console.print("\n[bold yellow]āš ļø WARNING: This will DELETE ALL your ConnectOnion data[/bold yellow]\n")
46
+ console.print("[red]You will lose:[/red]")
47
+ console.print(" • Your account and balance")
48
+ console.print(" • All transaction history")
49
+ console.print(" • Your Ed25519 keypair")
50
+ console.print(" • All configurations and credentials\n")
51
+
52
+ console.print("[green]You will get:[/green]")
53
+ console.print(" • Fresh new account")
54
+ console.print(" • New Ed25519 keypair with seed phrase\n")
55
+
56
+ console.print("[yellow]šŸ’” Save your 12-word seed phrase if you want to recover your current account![/yellow]\n")
57
+
58
+ confirmation = Prompt.ask("[bold red]Type 'Y' to confirm reset[/bold red]")
59
+
60
+ if confirmation.upper() != "Y":
61
+ console.print("\n[yellow]Cancelled.[/yellow]\n")
62
+ return
63
+
64
+ # Delete everything
65
+ keys_dir = global_dir / "keys"
66
+ if keys_dir.exists():
67
+ shutil.rmtree(keys_dir)
68
+ console.print("āœ“ Deleted ~/.co/keys/")
69
+
70
+ config_path = global_dir / "config.toml"
71
+ if config_path.exists():
72
+ config_path.unlink()
73
+ console.print("āœ“ Deleted ~/.co/config.toml")
74
+
75
+ keys_env = global_dir / "keys.env"
76
+ if keys_env.exists():
77
+ keys_env.unlink()
78
+ console.print("āœ“ Deleted ~/.co/keys.env")
79
+
80
+ # Recreate directory structure
81
+ global_dir.mkdir(exist_ok=True)
82
+ keys_dir.mkdir(exist_ok=True)
83
+ (global_dir / "logs").mkdir(exist_ok=True)
84
+
85
+ # Generate new keypair
86
+ console.print("\nšŸ”‘ Generating new Ed25519 keypair...")
87
+ addr_data = address.generate()
88
+ address.save(addr_data, global_dir)
89
+
90
+ console.print(f"āœ“ Generated new keypair")
91
+ console.print(f"āœ“ Your new address: [bold]{addr_data['short_address']}[/bold]")
92
+
93
+ # Show seed phrase
94
+ console.print(Panel.fit(
95
+ f"[bold yellow]{addr_data['seed_phrase']}[/bold yellow]",
96
+ title="šŸ” Your 12-Word Seed Phrase (SAVE THIS!)",
97
+ border_style="yellow"
98
+ ))
99
+
100
+ # Create new config
101
+ from ... import __version__
102
+ from datetime import datetime
103
+
104
+ config = {
105
+ "connectonion": {
106
+ "framework_version": __version__,
107
+ "created": datetime.now().isoformat(),
108
+ },
109
+ "cli": {
110
+ "version": "1.0.0",
111
+ },
112
+ "agent": {
113
+ "address": addr_data["address"],
114
+ "short_address": addr_data["short_address"],
115
+ "email": f"{addr_data['address'][:10]}@mail.openonion.ai",
116
+ "email_active": False,
117
+ "created_at": datetime.now().isoformat(),
118
+ "algorithm": "ed25519",
119
+ "default_model": "co/gemini-2.5-pro",
120
+ "max_iterations": 10,
121
+ },
122
+ }
123
+
124
+ with open(config_path, 'w', encoding='utf-8') as f:
125
+ toml.dump(config, f)
126
+ console.print("āœ“ Created ~/.co/config.toml")
127
+
128
+ keys_env.touch()
129
+ if sys.platform != 'win32':
130
+ keys_env.chmod(0o600)
131
+ console.print("āœ“ Created ~/.co/keys.env")
132
+
133
+ # Authenticate to get fresh bonus
134
+ console.print("\nšŸ” Authenticating with OpenOnion...")
135
+ success = authenticate(global_dir, save_to_project=False)
136
+
137
+ if success:
138
+ console.print("\n[bold green]āœ… Reset complete! Your new account is ready.[/bold green]")
139
+ console.print("\n[yellow]šŸ’” Save your 12-word seed phrase somewhere safe![/yellow]")
140
+
141
+ console.print("\n[bold yellow]āš ļø IMPORTANT: Update your project .env files![/bold yellow]")
142
+ console.print("\n[yellow]Your existing projects still have the old API key.[/yellow]")
143
+ console.print("[yellow]To use your new account in each project:[/yellow]")
144
+ console.print(" [bold cyan]1.[/bold cyan] cd into the project directory")
145
+ console.print(" [bold cyan]2.[/bold cyan] Run: [bold]co init[/bold]")
146
+ console.print("\n[dim]This will update the project's .env file with your new account.[/dim]\n")
147
+ else:
148
+ console.print("\n[yellow]āš ļø Reset complete, but authentication failed.[/yellow]")
149
+ console.print("[yellow]Run 'co auth' to authenticate manually.[/yellow]\n")
@@ -0,0 +1,168 @@
1
+ """
2
+ Purpose: Display account status including balance, usage, and email configuration without re-authenticating
3
+ LLM-Note:
4
+ Dependencies: imports from [os, toml, requests, pathlib, rich.console, rich.panel, dotenv.load_dotenv, jwt, address] | imported by [cli/main.py via handle_status()] | calls backend at [https://oo.openonion.ai/api/v1/auth] | tested by [tests/cli/test_cli_status.py]
5
+ Data flow: receives no args → _load_api_key() checks OPENONION_API_KEY from env/local .env/global ~/.co/keys.env → _load_config() loads agent info from .co/config.toml or ~/.co/config.toml → address.load() reads Ed25519 keypair → creates fresh auth message with timestamp → address.sign() creates signature → POST to /api/v1/auth to get current user data → displays balance, credits, total spent, email, agent ID → warns if balance <= 0
6
+ State/Effects: no state modifications | makes network GET request to oo.openonion.ai | reads from env vars, .env, ~/.co/keys.env, config.toml | writes to stdout via rich.Console and rich.Panel | does NOT update any files
7
+ Integration: exposes handle_status() for CLI | similar to authenticate() but read-only | relies on address module for signature generation | uses requests for HTTP calls | displays Rich panel with account info | checks OPENONION_API_KEY in 3 locations (priority: env var > local .env > global ~/.co/keys.env)
8
+ Performance: network call to backend (1-2s) | signature generation is fast (<10ms) | file I/O for config and .env files
9
+ Errors: fails gracefully if OPENONION_API_KEY not found (prints message to run 'co auth') | fails if keys missing in .co/keys/ | fails if backend unreachable (prints HTTP error) | handles response errors with status code display
10
+ """
11
+
12
+ import os
13
+ import toml
14
+ import requests
15
+ from pathlib import Path
16
+ from rich.console import Console
17
+ from rich.panel import Panel
18
+ from dotenv import load_dotenv
19
+
20
+ console = Console()
21
+
22
+
23
+ def _load_api_key() -> str:
24
+ """Load OPENONION_API_KEY from environment.
25
+
26
+ Checks in order:
27
+ 1. Environment variable
28
+ 2. Local .env file
29
+ 3. Global ~/.co/keys.env file
30
+
31
+ Returns:
32
+ API key if found, None otherwise
33
+ """
34
+ # Check environment variable first
35
+ api_key = os.getenv("OPENONION_API_KEY")
36
+ if api_key:
37
+ return api_key
38
+
39
+ # Check local .env
40
+ local_env = Path(".env")
41
+ if local_env.exists():
42
+ load_dotenv(local_env)
43
+ api_key = os.getenv("OPENONION_API_KEY")
44
+ if api_key:
45
+ return api_key
46
+
47
+ # Check global ~/.co/keys.env
48
+ global_env = Path.home() / ".co" / "keys.env"
49
+ if global_env.exists():
50
+ load_dotenv(global_env)
51
+ api_key = os.getenv("OPENONION_API_KEY")
52
+ if api_key:
53
+ return api_key
54
+
55
+ return None
56
+
57
+
58
+ def _load_config() -> dict:
59
+ """Load config from .co/config.toml or ~/.co/config.toml.
60
+
61
+ Returns:
62
+ Config dict if found, empty dict otherwise
63
+ """
64
+ # Check local .co/config.toml first
65
+ local_config = Path(".co") / "config.toml"
66
+ if local_config.exists():
67
+ return toml.load(local_config)
68
+
69
+ # Check global ~/.co/config.toml
70
+ global_config = Path.home() / ".co" / "config.toml"
71
+ if global_config.exists():
72
+ return toml.load(global_config)
73
+
74
+ return {}
75
+
76
+
77
+ def handle_status():
78
+ """Check account status without re-authenticating.
79
+
80
+ Shows:
81
+ - Agent ID
82
+ - Email address
83
+ - Balance (remaining credits)
84
+ - Total spent
85
+ - Last seen
86
+ - Warnings if balance is low
87
+ """
88
+ # Load API key
89
+ api_key = _load_api_key()
90
+ if not api_key:
91
+ console.print("\nāŒ [bold red]No API key found[/bold red]")
92
+ console.print("\n[cyan]Authenticate first:[/cyan]")
93
+ console.print(" [bold]co auth[/bold] Authenticate with OpenOnion\n")
94
+ return
95
+
96
+ # Load config for agent info
97
+ config = _load_config()
98
+ agent_info = config.get("agent", {})
99
+
100
+ # Decode JWT to extract public_key and re-authenticate to get fresh data
101
+ import jwt
102
+ import time
103
+ from ... import address
104
+
105
+ # Load keys to re-sign
106
+ co_dir = Path(".co")
107
+ if not (co_dir.exists() and (co_dir / "keys" / "agent.key").exists()):
108
+ co_dir = Path.home() / ".co"
109
+
110
+ addr_data = address.load(co_dir)
111
+ if not addr_data:
112
+ console.print("\nāŒ [bold red]No keys found[/bold red]")
113
+ console.print("[yellow]Run 'co auth' first.[/yellow]\n")
114
+ return
115
+
116
+ public_key = addr_data["address"]
117
+ timestamp = int(time.time())
118
+ message = f"ConnectOnion-Auth-{public_key}-{timestamp}"
119
+ signature = address.sign(addr_data, message.encode()).hex()
120
+
121
+ # Call auth endpoint to get fresh user data
122
+ response = requests.post(
123
+ "https://oo.openonion.ai/api/v1/auth",
124
+ json={
125
+ "public_key": public_key,
126
+ "signature": signature,
127
+ "message": message
128
+ }
129
+ )
130
+
131
+ if response.status_code != 200:
132
+ console.print(f"\nāŒ [bold red]Error {response.status_code}[/bold red]")
133
+ console.print(f"[yellow]{response.text}[/yellow]\n")
134
+ return
135
+
136
+ data = response.json()
137
+ user = data.get("user", {})
138
+ email_info = user.get("email") or {}
139
+
140
+ # Build info display
141
+ api_key_display = f"{api_key[:20]}..." if len(api_key) > 20 else api_key
142
+
143
+ # Compute short address from full address (first 6 chars + ... + last 4 chars)
144
+ short_address = f"{public_key[:6]}...{public_key[-4:]}"
145
+
146
+ info_lines = [
147
+ f"[cyan]Agent Address:[/cyan] {public_key}",
148
+ f"[cyan]Agent ID:[/cyan] {short_address}",
149
+ f"[cyan]Email:[/cyan] {email_info.get('address') or os.getenv('AGENT_EMAIL', 'Not configured')}",
150
+ f"[cyan]API Key:[/cyan] {api_key_display}",
151
+ f"[cyan]Balance:[/cyan] ${user.get('balance_usd', 0.0):.4f}",
152
+ f"[cyan]Total Spent:[/cyan] ${user.get('total_cost_usd', 0.0):.4f}",
153
+ f"[cyan]Credits:[/cyan] ${user.get('credits_usd', 0.0):.4f}",
154
+ ]
155
+
156
+ console.print("\n")
157
+ console.print(Panel.fit(
158
+ "\n".join(info_lines),
159
+ title="šŸ“Š Account Status",
160
+ border_style="cyan"
161
+ ))
162
+
163
+ if user.get('balance_usd', 0) <= 0:
164
+ console.print("\n[yellow]āš ļø Low balance! Purchase tokens at https://oo.openonion.ai[/yellow]")
165
+
166
+ console.print("\n[yellow]šŸ’” Tips:[/yellow]")
167
+ console.print(" • Use 'co auth' to refresh your token")
168
+ console.print(" • Visit https://oo.openonion.ai to manage your account\n")