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.
- connectonion/__init__.py +78 -0
- connectonion/address.py +320 -0
- connectonion/agent.py +450 -0
- connectonion/announce.py +84 -0
- connectonion/asgi.py +287 -0
- connectonion/auto_debug_exception.py +181 -0
- connectonion/cli/__init__.py +3 -0
- connectonion/cli/browser_agent/__init__.py +5 -0
- connectonion/cli/browser_agent/browser.py +243 -0
- connectonion/cli/browser_agent/prompt.md +107 -0
- connectonion/cli/commands/__init__.py +1 -0
- connectonion/cli/commands/auth_commands.py +527 -0
- connectonion/cli/commands/browser_commands.py +27 -0
- connectonion/cli/commands/create.py +511 -0
- connectonion/cli/commands/deploy_commands.py +220 -0
- connectonion/cli/commands/doctor_commands.py +173 -0
- connectonion/cli/commands/init.py +469 -0
- connectonion/cli/commands/project_cmd_lib.py +828 -0
- connectonion/cli/commands/reset_commands.py +149 -0
- connectonion/cli/commands/status_commands.py +168 -0
- connectonion/cli/docs/co-vibecoding-principles-docs-contexts-all-in-one.md +2010 -0
- connectonion/cli/docs/connectonion.md +1256 -0
- connectonion/cli/docs.md +123 -0
- connectonion/cli/main.py +148 -0
- connectonion/cli/templates/meta-agent/README.md +287 -0
- connectonion/cli/templates/meta-agent/agent.py +196 -0
- connectonion/cli/templates/meta-agent/prompts/answer_prompt.md +9 -0
- connectonion/cli/templates/meta-agent/prompts/docs_retrieve_prompt.md +15 -0
- connectonion/cli/templates/meta-agent/prompts/metagent.md +71 -0
- connectonion/cli/templates/meta-agent/prompts/think_prompt.md +18 -0
- connectonion/cli/templates/minimal/README.md +56 -0
- connectonion/cli/templates/minimal/agent.py +40 -0
- connectonion/cli/templates/playwright/README.md +118 -0
- connectonion/cli/templates/playwright/agent.py +336 -0
- connectonion/cli/templates/playwright/prompt.md +102 -0
- connectonion/cli/templates/playwright/requirements.txt +3 -0
- connectonion/cli/templates/web-research/agent.py +122 -0
- connectonion/connect.py +128 -0
- connectonion/console.py +539 -0
- connectonion/debug_agent/__init__.py +13 -0
- connectonion/debug_agent/agent.py +45 -0
- connectonion/debug_agent/prompts/debug_assistant.md +72 -0
- connectonion/debug_agent/runtime_inspector.py +406 -0
- connectonion/debug_explainer/__init__.py +10 -0
- connectonion/debug_explainer/explain_agent.py +114 -0
- connectonion/debug_explainer/explain_context.py +263 -0
- connectonion/debug_explainer/explainer_prompt.md +29 -0
- connectonion/debug_explainer/root_cause_analysis_prompt.md +43 -0
- connectonion/debugger_ui.py +1039 -0
- connectonion/decorators.py +208 -0
- connectonion/events.py +248 -0
- connectonion/execution_analyzer/__init__.py +9 -0
- connectonion/execution_analyzer/execution_analysis.py +93 -0
- connectonion/execution_analyzer/execution_analysis_prompt.md +47 -0
- connectonion/host.py +579 -0
- connectonion/interactive_debugger.py +342 -0
- connectonion/llm.py +801 -0
- connectonion/llm_do.py +307 -0
- connectonion/logger.py +300 -0
- connectonion/prompt_files/__init__.py +1 -0
- connectonion/prompt_files/analyze_contact.md +62 -0
- connectonion/prompt_files/eval_expected.md +12 -0
- connectonion/prompt_files/react_evaluate.md +11 -0
- connectonion/prompt_files/react_plan.md +16 -0
- connectonion/prompt_files/reflect.md +22 -0
- connectonion/prompts.py +144 -0
- connectonion/relay.py +200 -0
- connectonion/static/docs.html +688 -0
- connectonion/tool_executor.py +279 -0
- connectonion/tool_factory.py +186 -0
- connectonion/tool_registry.py +105 -0
- connectonion/trust.py +166 -0
- connectonion/trust_agents.py +71 -0
- connectonion/trust_functions.py +88 -0
- connectonion/tui/__init__.py +57 -0
- connectonion/tui/divider.py +39 -0
- connectonion/tui/dropdown.py +251 -0
- connectonion/tui/footer.py +31 -0
- connectonion/tui/fuzzy.py +56 -0
- connectonion/tui/input.py +278 -0
- connectonion/tui/keys.py +35 -0
- connectonion/tui/pick.py +130 -0
- connectonion/tui/providers.py +155 -0
- connectonion/tui/status_bar.py +163 -0
- connectonion/usage.py +161 -0
- connectonion/useful_events_handlers/__init__.py +16 -0
- connectonion/useful_events_handlers/reflect.py +116 -0
- connectonion/useful_plugins/__init__.py +20 -0
- connectonion/useful_plugins/calendar_plugin.py +163 -0
- connectonion/useful_plugins/eval.py +139 -0
- connectonion/useful_plugins/gmail_plugin.py +162 -0
- connectonion/useful_plugins/image_result_formatter.py +127 -0
- connectonion/useful_plugins/re_act.py +78 -0
- connectonion/useful_plugins/shell_approval.py +159 -0
- connectonion/useful_tools/__init__.py +44 -0
- connectonion/useful_tools/diff_writer.py +192 -0
- connectonion/useful_tools/get_emails.py +183 -0
- connectonion/useful_tools/gmail.py +1596 -0
- connectonion/useful_tools/google_calendar.py +613 -0
- connectonion/useful_tools/memory.py +380 -0
- connectonion/useful_tools/microsoft_calendar.py +604 -0
- connectonion/useful_tools/outlook.py +488 -0
- connectonion/useful_tools/send_email.py +205 -0
- connectonion/useful_tools/shell.py +97 -0
- connectonion/useful_tools/slash_command.py +201 -0
- connectonion/useful_tools/terminal.py +285 -0
- connectonion/useful_tools/todo_list.py +241 -0
- connectonion/useful_tools/web_fetch.py +216 -0
- connectonion/xray.py +467 -0
- connectonion-0.5.8.dist-info/METADATA +741 -0
- connectonion-0.5.8.dist-info/RECORD +113 -0
- connectonion-0.5.8.dist-info/WHEEL +4 -0
- 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")
|