connectonion 0.4.12__py3-none-any.whl → 0.5.0__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 (74) hide show
  1. connectonion/__init__.py +11 -5
  2. connectonion/agent.py +44 -42
  3. connectonion/cli/commands/init.py +1 -1
  4. connectonion/cli/commands/project_cmd_lib.py +4 -4
  5. connectonion/cli/commands/reset_commands.py +1 -1
  6. connectonion/cli/docs/co-vibecoding-principles-docs-contexts-all-in-one.md +15 -11
  7. connectonion/cli/templates/minimal/agent.py +2 -2
  8. connectonion/console.py +55 -3
  9. connectonion/events.py +96 -17
  10. connectonion/llm.py +21 -3
  11. connectonion/logger.py +289 -0
  12. connectonion/prompt_files/eval_expected.md +12 -0
  13. connectonion/tool_executor.py +43 -32
  14. connectonion/usage.py +4 -0
  15. connectonion/useful_events_handlers/reflect.py +13 -9
  16. connectonion/useful_plugins/__init__.py +2 -1
  17. connectonion/useful_plugins/calendar_plugin.py +2 -2
  18. connectonion/useful_plugins/eval.py +130 -0
  19. connectonion/useful_plugins/gmail_plugin.py +4 -4
  20. connectonion/useful_plugins/image_result_formatter.py +4 -3
  21. connectonion/useful_plugins/re_act.py +14 -56
  22. connectonion/useful_plugins/shell_approval.py +2 -2
  23. connectonion/useful_tools/memory.py +4 -0
  24. {connectonion-0.4.12.dist-info → connectonion-0.5.0.dist-info}/METADATA +48 -48
  25. {connectonion-0.4.12.dist-info → connectonion-0.5.0.dist-info}/RECORD +27 -71
  26. {connectonion-0.4.12.dist-info → connectonion-0.5.0.dist-info}/WHEEL +1 -2
  27. connectonion/cli/templates/email-agent/.env.example +0 -23
  28. connectonion/cli/templates/email-agent/README.md +0 -240
  29. connectonion/cli/templates/email-agent/agent.py +0 -374
  30. connectonion/cli/templates/email-agent/demo.py +0 -71
  31. connectonion/cli/templates/meta-agent/.env.example +0 -11
  32. connectonion/cli/templates/minimal/.env.example +0 -5
  33. connectonion/cli/templates/playwright/.env.example +0 -5
  34. connectonion-0.4.12.dist-info/top_level.txt +0 -2
  35. tests/__init__.py +0 -0
  36. tests/cli/__init__.py +0 -1
  37. tests/cli/argparse_runner.py +0 -85
  38. tests/cli/conftest.py +0 -5
  39. tests/cli/test_browser_cli.py +0 -61
  40. tests/cli/test_cli.py +0 -143
  41. tests/cli/test_cli_auth_google.py +0 -344
  42. tests/cli/test_cli_auth_microsoft.py +0 -256
  43. tests/cli/test_cli_create.py +0 -283
  44. tests/cli/test_cli_help.py +0 -200
  45. tests/cli/test_cli_init.py +0 -318
  46. tests/conftest.py +0 -283
  47. tests/debug_gemini_models.py +0 -23
  48. tests/fixtures/__init__.py +0 -1
  49. tests/fixtures/test_tools.py +0 -112
  50. tests/fixtures/trust_fixtures.py +0 -257
  51. tests/real_api/__init__.py +0 -0
  52. tests/real_api/conftest.py +0 -9
  53. tests/real_api/test_llm_do.py +0 -174
  54. tests/real_api/test_llm_do_comprehensive.py +0 -527
  55. tests/real_api/test_production_client.py +0 -94
  56. tests/real_api/test_real_anthropic.py +0 -100
  57. tests/real_api/test_real_api.py +0 -113
  58. tests/real_api/test_real_auth.py +0 -130
  59. tests/real_api/test_real_email.py +0 -95
  60. tests/real_api/test_real_gemini.py +0 -96
  61. tests/real_api/test_real_llm_do.py +0 -81
  62. tests/real_api/test_real_managed.py +0 -208
  63. tests/real_api/test_real_multi_llm.py +0 -454
  64. tests/real_api/test_real_openai.py +0 -100
  65. tests/real_api/test_responses_parse.py +0 -88
  66. tests/test_diff_writer.py +0 -126
  67. tests/test_events.py +0 -677
  68. tests/test_gemini_co.py +0 -70
  69. tests/test_image_result_formatter.py +0 -88
  70. tests/test_plugin_system.py +0 -110
  71. tests/utils/__init__.py +0 -1
  72. tests/utils/config_helpers.py +0 -188
  73. tests/utils/mock_helpers.py +0 -237
  74. {connectonion-0.4.12.dist-info → connectonion-0.5.0.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")