connectonion 0.4.12__py3-none-any.whl → 0.5.1__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 +11 -5
- connectonion/agent.py +44 -42
- connectonion/cli/commands/init.py +1 -1
- connectonion/cli/commands/project_cmd_lib.py +4 -4
- connectonion/cli/commands/reset_commands.py +1 -1
- connectonion/cli/docs/co-vibecoding-principles-docs-contexts-all-in-one.md +15 -11
- connectonion/cli/templates/minimal/agent.py +2 -2
- connectonion/console.py +55 -3
- connectonion/events.py +96 -17
- connectonion/llm.py +21 -3
- connectonion/logger.py +289 -0
- connectonion/prompt_files/eval_expected.md +12 -0
- connectonion/tool_executor.py +43 -32
- connectonion/usage.py +4 -0
- connectonion/useful_events_handlers/reflect.py +13 -9
- connectonion/useful_plugins/__init__.py +2 -1
- connectonion/useful_plugins/calendar_plugin.py +2 -2
- connectonion/useful_plugins/eval.py +130 -0
- connectonion/useful_plugins/gmail_plugin.py +4 -4
- connectonion/useful_plugins/image_result_formatter.py +4 -3
- connectonion/useful_plugins/re_act.py +14 -56
- connectonion/useful_plugins/shell_approval.py +2 -2
- connectonion/useful_tools/memory.py +4 -0
- {connectonion-0.4.12.dist-info → connectonion-0.5.1.dist-info}/METADATA +49 -49
- {connectonion-0.4.12.dist-info → connectonion-0.5.1.dist-info}/RECORD +27 -71
- {connectonion-0.4.12.dist-info → connectonion-0.5.1.dist-info}/WHEEL +1 -2
- connectonion/cli/templates/email-agent/.env.example +0 -23
- connectonion/cli/templates/email-agent/README.md +0 -240
- connectonion/cli/templates/email-agent/agent.py +0 -374
- connectonion/cli/templates/email-agent/demo.py +0 -71
- connectonion/cli/templates/meta-agent/.env.example +0 -11
- connectonion/cli/templates/minimal/.env.example +0 -5
- connectonion/cli/templates/playwright/.env.example +0 -5
- connectonion-0.4.12.dist-info/top_level.txt +0 -2
- tests/__init__.py +0 -0
- tests/cli/__init__.py +0 -1
- tests/cli/argparse_runner.py +0 -85
- tests/cli/conftest.py +0 -5
- tests/cli/test_browser_cli.py +0 -61
- tests/cli/test_cli.py +0 -143
- tests/cli/test_cli_auth_google.py +0 -344
- tests/cli/test_cli_auth_microsoft.py +0 -256
- tests/cli/test_cli_create.py +0 -283
- tests/cli/test_cli_help.py +0 -200
- tests/cli/test_cli_init.py +0 -318
- tests/conftest.py +0 -283
- tests/debug_gemini_models.py +0 -23
- tests/fixtures/__init__.py +0 -1
- tests/fixtures/test_tools.py +0 -112
- tests/fixtures/trust_fixtures.py +0 -257
- tests/real_api/__init__.py +0 -0
- tests/real_api/conftest.py +0 -9
- tests/real_api/test_llm_do.py +0 -174
- tests/real_api/test_llm_do_comprehensive.py +0 -527
- tests/real_api/test_production_client.py +0 -94
- tests/real_api/test_real_anthropic.py +0 -100
- tests/real_api/test_real_api.py +0 -113
- tests/real_api/test_real_auth.py +0 -130
- tests/real_api/test_real_email.py +0 -95
- tests/real_api/test_real_gemini.py +0 -96
- tests/real_api/test_real_llm_do.py +0 -81
- tests/real_api/test_real_managed.py +0 -208
- tests/real_api/test_real_multi_llm.py +0 -454
- tests/real_api/test_real_openai.py +0 -100
- tests/real_api/test_responses_parse.py +0 -88
- tests/test_diff_writer.py +0 -126
- tests/test_events.py +0 -677
- tests/test_gemini_co.py +0 -70
- tests/test_image_result_formatter.py +0 -88
- tests/test_plugin_system.py +0 -110
- tests/utils/__init__.py +0 -1
- tests/utils/config_helpers.py +0 -188
- tests/utils/mock_helpers.py +0 -237
- {connectonion-0.4.12.dist-info → connectonion-0.5.1.dist-info}/entry_points.txt +0 -0
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Real API tests for the llm_do function with structured output.
|
|
3
|
-
|
|
4
|
-
These tests make actual API calls to various providers and may cost money.
|
|
5
|
-
Run with: pytest tests/test_real_llm_do.py -v
|
|
6
|
-
|
|
7
|
-
Requires API keys for OpenAI, Anthropic, and Gemini set in the environment.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
import os
|
|
11
|
-
import pytest
|
|
12
|
-
from pathlib import Path
|
|
13
|
-
from dotenv import load_dotenv
|
|
14
|
-
from pydantic import BaseModel, Field
|
|
15
|
-
|
|
16
|
-
from connectonion import llm_do
|
|
17
|
-
|
|
18
|
-
# Load environment variables from tests/.env
|
|
19
|
-
env_path = Path(__file__).parent / ".env"
|
|
20
|
-
if env_path.exists():
|
|
21
|
-
load_dotenv(env_path)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
# Define a Pydantic model for testing structured output
|
|
25
|
-
class CharacterAnalysis(BaseModel):
|
|
26
|
-
"""A model to hold the analysis of a fictional character."""
|
|
27
|
-
name: str = Field(description="The name of the character.")
|
|
28
|
-
role: str = Field(description="The character's primary role in their story (e.g., protagonist, antagonist, sidekick).")
|
|
29
|
-
power_level: int = Field(description="An estimated power level for the character, on a scale of 1 to 100.")
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class TestRealLLMDoStructuredOutput:
|
|
33
|
-
"""Test llm_do with real API calls for structured output."""
|
|
34
|
-
|
|
35
|
-
def test_structured_output_openai(self):
|
|
36
|
-
"""Test structured output with an OpenAI model."""
|
|
37
|
-
result = llm_do(
|
|
38
|
-
"Analyze the character 'Frodo Baggins' from The Lord of the Rings.",
|
|
39
|
-
output=CharacterAnalysis,
|
|
40
|
-
model="gpt-4o-mini"
|
|
41
|
-
)
|
|
42
|
-
assert isinstance(result, CharacterAnalysis)
|
|
43
|
-
assert result.name.lower() == "frodo baggins"
|
|
44
|
-
assert result.role.lower() == "protagonist"
|
|
45
|
-
assert 1 <= result.power_level <= 100
|
|
46
|
-
|
|
47
|
-
def test_structured_output_anthropic(self):
|
|
48
|
-
"""Test structured output with an Anthropic model."""
|
|
49
|
-
result = llm_do(
|
|
50
|
-
"Analyze the character 'Sherlock Holmes'.",
|
|
51
|
-
output=CharacterAnalysis,
|
|
52
|
-
model="claude-3-5-haiku-20241022"
|
|
53
|
-
)
|
|
54
|
-
assert isinstance(result, CharacterAnalysis)
|
|
55
|
-
assert result.name.lower() == "sherlock holmes"
|
|
56
|
-
assert result.role.lower() == "protagonist"
|
|
57
|
-
assert 1 <= result.power_level <= 100
|
|
58
|
-
|
|
59
|
-
def test_structured_output_gemini(self):
|
|
60
|
-
"""Test structured output with a Google Gemini model."""
|
|
61
|
-
result = llm_do(
|
|
62
|
-
"Analyze the character 'Darth Vader' from Star Wars.",
|
|
63
|
-
output=CharacterAnalysis,
|
|
64
|
-
model="gemini-2.5-pro"
|
|
65
|
-
)
|
|
66
|
-
assert isinstance(result, CharacterAnalysis)
|
|
67
|
-
assert result.name.lower() == "darth vader"
|
|
68
|
-
assert result.role.lower() == "antagonist"
|
|
69
|
-
assert 1 <= result.power_level <= 100
|
|
70
|
-
|
|
71
|
-
def test_structured_output_connectonion(self):
|
|
72
|
-
"""Test structured output with a ConnectOnion managed (co/) model."""
|
|
73
|
-
result = llm_do(
|
|
74
|
-
"Analyze the character 'Harry Potter'.",
|
|
75
|
-
output=CharacterAnalysis,
|
|
76
|
-
model="co/gpt-4o-mini"
|
|
77
|
-
)
|
|
78
|
-
assert isinstance(result, CharacterAnalysis)
|
|
79
|
-
assert result.name.lower() == "harry potter"
|
|
80
|
-
assert result.role.lower() == "protagonist"
|
|
81
|
-
assert 1 <= result.power_level <= 100
|
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
"""Test LLM functionality with co/ models."""
|
|
2
|
-
|
|
3
|
-
import os
|
|
4
|
-
import sys
|
|
5
|
-
import json
|
|
6
|
-
import time
|
|
7
|
-
import requests
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
from nacl.signing import SigningKey
|
|
10
|
-
from nacl.encoding import HexEncoder
|
|
11
|
-
|
|
12
|
-
# Add parent to path
|
|
13
|
-
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
14
|
-
|
|
15
|
-
def test_co_model_direct_api():
|
|
16
|
-
"""Test calling co/ model directly through API."""
|
|
17
|
-
|
|
18
|
-
print("Testing co/ Model Direct API Call")
|
|
19
|
-
print("="*50)
|
|
20
|
-
|
|
21
|
-
# First authenticate to get a token
|
|
22
|
-
signing_key = SigningKey.generate()
|
|
23
|
-
public_key = "0x" + signing_key.verify_key.encode(encoder=HexEncoder).decode()
|
|
24
|
-
timestamp = int(time.time())
|
|
25
|
-
message = f"ConnectOnion-Auth-{public_key}-{timestamp}"
|
|
26
|
-
signature = signing_key.sign(message.encode()).signature.hex()
|
|
27
|
-
|
|
28
|
-
# Get token
|
|
29
|
-
auth_response = requests.post(
|
|
30
|
-
"https://oo.openonion.ai/auth",
|
|
31
|
-
json={
|
|
32
|
-
"public_key": public_key,
|
|
33
|
-
"message": message,
|
|
34
|
-
"signature": signature
|
|
35
|
-
}
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
if auth_response.status_code != 200:
|
|
39
|
-
print(f"❌ Authentication failed: {auth_response.status_code}")
|
|
40
|
-
return False
|
|
41
|
-
|
|
42
|
-
token = auth_response.json()["token"]
|
|
43
|
-
print(f"✅ Got token: {token[:20]}...")
|
|
44
|
-
|
|
45
|
-
# Test LLM completion with co/ model
|
|
46
|
-
print("\nTesting LLM completion...")
|
|
47
|
-
|
|
48
|
-
payload = {
|
|
49
|
-
"model": "co/gpt-4o-mini", # With co/ prefix as CLI sends
|
|
50
|
-
"messages": [
|
|
51
|
-
{"role": "system", "content": "You are a helpful assistant."},
|
|
52
|
-
{"role": "user", "content": "Say 'Hello from ConnectOnion!' in exactly 3 words."}
|
|
53
|
-
],
|
|
54
|
-
"temperature": 0.1,
|
|
55
|
-
"max_tokens": 10
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
print(f"Model: {payload['model']}")
|
|
59
|
-
print(f"Prompt: {payload['messages'][1]['content']}")
|
|
60
|
-
|
|
61
|
-
response = requests.post(
|
|
62
|
-
"https://oo.openonion.ai/api/llm/completions",
|
|
63
|
-
json=payload,
|
|
64
|
-
headers={"Authorization": f"Bearer {token}"}
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
print(f"Response Status: {response.status_code}")
|
|
68
|
-
|
|
69
|
-
if response.status_code == 200:
|
|
70
|
-
data = response.json()
|
|
71
|
-
content = data.get("choices", [{}])[0].get("message", {}).get("content", "")
|
|
72
|
-
print(f"✅ LLM Response: {content}")
|
|
73
|
-
return True
|
|
74
|
-
else:
|
|
75
|
-
print(f"❌ LLM call failed: {response.text[:200]}")
|
|
76
|
-
return False
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def test_llm_do_function():
|
|
80
|
-
"""Test using llm_do function with co/ model."""
|
|
81
|
-
|
|
82
|
-
print("\n\nTesting llm_do Function with co/ Model")
|
|
83
|
-
print("="*50)
|
|
84
|
-
|
|
85
|
-
try:
|
|
86
|
-
from connectonion.llm_do import llm_do, _get_auth_token
|
|
87
|
-
|
|
88
|
-
# Check if we have a token (would need to run 'co auth' first)
|
|
89
|
-
token = _get_auth_token()
|
|
90
|
-
|
|
91
|
-
if token:
|
|
92
|
-
print(f"✅ Found saved token: {token[:20]}...")
|
|
93
|
-
|
|
94
|
-
# Test llm_do with co/ model
|
|
95
|
-
print("\nCalling llm_do with co/gpt-4o-mini...")
|
|
96
|
-
|
|
97
|
-
# Set production mode
|
|
98
|
-
os.environ.pop("OPENONION_DEV", None)
|
|
99
|
-
|
|
100
|
-
try:
|
|
101
|
-
response = llm_do(
|
|
102
|
-
"Reply with exactly: 'ConnectOnion works!'",
|
|
103
|
-
model="co/gpt-4o-mini",
|
|
104
|
-
temperature=0.1
|
|
105
|
-
)
|
|
106
|
-
print(f"✅ Response: {response}")
|
|
107
|
-
return True
|
|
108
|
-
except Exception as e:
|
|
109
|
-
print(f"❌ llm_do failed: {e}")
|
|
110
|
-
|
|
111
|
-
# Check if it's an auth issue
|
|
112
|
-
if "authentication token" in str(e).lower():
|
|
113
|
-
print(" Run 'co auth' first to authenticate")
|
|
114
|
-
return False
|
|
115
|
-
else:
|
|
116
|
-
print("⚠️ No saved token found")
|
|
117
|
-
print(" Would need to run 'co auth' first")
|
|
118
|
-
print(" Skipping llm_do test")
|
|
119
|
-
return None
|
|
120
|
-
|
|
121
|
-
except ImportError as e:
|
|
122
|
-
print(f"❌ Import error: {e}")
|
|
123
|
-
return False
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
def test_model_name_variations():
|
|
127
|
-
"""Test that API handles model names correctly."""
|
|
128
|
-
|
|
129
|
-
print("\n\nTesting Model Name Variations")
|
|
130
|
-
print("="*50)
|
|
131
|
-
|
|
132
|
-
# Get a token first
|
|
133
|
-
signing_key = SigningKey.generate()
|
|
134
|
-
public_key = "0x" + signing_key.verify_key.encode(encoder=HexEncoder).decode()
|
|
135
|
-
timestamp = int(time.time())
|
|
136
|
-
message = f"ConnectOnion-Auth-{public_key}-{timestamp}"
|
|
137
|
-
signature = signing_key.sign(message.encode()).signature.hex()
|
|
138
|
-
|
|
139
|
-
auth_response = requests.post(
|
|
140
|
-
"https://oo.openonion.ai/auth",
|
|
141
|
-
json={"public_key": public_key, "message": message, "signature": signature}
|
|
142
|
-
)
|
|
143
|
-
|
|
144
|
-
if auth_response.status_code != 200:
|
|
145
|
-
print("❌ Failed to authenticate")
|
|
146
|
-
return False
|
|
147
|
-
|
|
148
|
-
token = auth_response.json()["token"]
|
|
149
|
-
|
|
150
|
-
# Test different model name formats
|
|
151
|
-
test_cases = [
|
|
152
|
-
("co/gpt-4o-mini", "With co/ prefix (as CLI sends)"),
|
|
153
|
-
("gpt-4o-mini", "Without co/ prefix (raw model name)"),
|
|
154
|
-
]
|
|
155
|
-
|
|
156
|
-
results = []
|
|
157
|
-
for model_name, description in test_cases:
|
|
158
|
-
print(f"\nTesting: {description}")
|
|
159
|
-
print(f" Model: {model_name}")
|
|
160
|
-
|
|
161
|
-
response = requests.post(
|
|
162
|
-
"https://oo.openonion.ai/api/llm/completions",
|
|
163
|
-
json={
|
|
164
|
-
"model": model_name,
|
|
165
|
-
"messages": [
|
|
166
|
-
{"role": "user", "content": "Reply 'OK'"}
|
|
167
|
-
],
|
|
168
|
-
"max_tokens": 5
|
|
169
|
-
},
|
|
170
|
-
headers={"Authorization": f"Bearer {token}"}
|
|
171
|
-
)
|
|
172
|
-
|
|
173
|
-
if response.status_code == 200:
|
|
174
|
-
print(f" ✅ Success")
|
|
175
|
-
results.append(True)
|
|
176
|
-
else:
|
|
177
|
-
print(f" ❌ Failed: {response.status_code}")
|
|
178
|
-
results.append(False)
|
|
179
|
-
|
|
180
|
-
return all(results)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
if __name__ == "__main__":
|
|
184
|
-
print("ConnectOnion co/ Models Test Suite\n")
|
|
185
|
-
|
|
186
|
-
# Run tests
|
|
187
|
-
test1 = test_co_model_direct_api()
|
|
188
|
-
test2 = test_llm_do_function()
|
|
189
|
-
test3 = test_model_name_variations()
|
|
190
|
-
|
|
191
|
-
# Summary
|
|
192
|
-
print("\n" + "="*50)
|
|
193
|
-
print("Test Summary:")
|
|
194
|
-
print(f" Direct API Call: {'✅ PASSED' if test1 else '❌ FAILED'}")
|
|
195
|
-
|
|
196
|
-
if test2 is None:
|
|
197
|
-
print(f" llm_do Function: ⏭️ SKIPPED (no token)")
|
|
198
|
-
else:
|
|
199
|
-
print(f" llm_do Function: {'✅ PASSED' if test2 else '❌ FAILED'}")
|
|
200
|
-
|
|
201
|
-
print(f" Model Name Variations: {'✅ PASSED' if test3 else '❌ FAILED'}")
|
|
202
|
-
|
|
203
|
-
if test1 and test3:
|
|
204
|
-
print("\n🎉 Core functionality working!")
|
|
205
|
-
if test2 is None:
|
|
206
|
-
print(" Run 'co auth' to test llm_do function")
|
|
207
|
-
else:
|
|
208
|
-
print("\n⚠️ Some tests failed")
|