codetether 1.2.2__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 (66) hide show
  1. a2a_server/__init__.py +29 -0
  2. a2a_server/a2a_agent_card.py +365 -0
  3. a2a_server/a2a_errors.py +1133 -0
  4. a2a_server/a2a_executor.py +926 -0
  5. a2a_server/a2a_router.py +1033 -0
  6. a2a_server/a2a_types.py +344 -0
  7. a2a_server/agent_card.py +408 -0
  8. a2a_server/agents_server.py +271 -0
  9. a2a_server/auth_api.py +349 -0
  10. a2a_server/billing_api.py +638 -0
  11. a2a_server/billing_service.py +712 -0
  12. a2a_server/billing_webhooks.py +501 -0
  13. a2a_server/config.py +96 -0
  14. a2a_server/database.py +2165 -0
  15. a2a_server/email_inbound.py +398 -0
  16. a2a_server/email_notifications.py +486 -0
  17. a2a_server/enhanced_agents.py +919 -0
  18. a2a_server/enhanced_server.py +160 -0
  19. a2a_server/hosted_worker.py +1049 -0
  20. a2a_server/integrated_agents_server.py +347 -0
  21. a2a_server/keycloak_auth.py +750 -0
  22. a2a_server/livekit_bridge.py +439 -0
  23. a2a_server/marketing_tools.py +1364 -0
  24. a2a_server/mcp_client.py +196 -0
  25. a2a_server/mcp_http_server.py +2256 -0
  26. a2a_server/mcp_server.py +191 -0
  27. a2a_server/message_broker.py +725 -0
  28. a2a_server/mock_mcp.py +273 -0
  29. a2a_server/models.py +494 -0
  30. a2a_server/monitor_api.py +5904 -0
  31. a2a_server/opencode_bridge.py +1594 -0
  32. a2a_server/redis_task_manager.py +518 -0
  33. a2a_server/server.py +726 -0
  34. a2a_server/task_manager.py +668 -0
  35. a2a_server/task_queue.py +742 -0
  36. a2a_server/tenant_api.py +333 -0
  37. a2a_server/tenant_middleware.py +219 -0
  38. a2a_server/tenant_service.py +760 -0
  39. a2a_server/user_auth.py +721 -0
  40. a2a_server/vault_client.py +576 -0
  41. a2a_server/worker_sse.py +873 -0
  42. agent_worker/__init__.py +8 -0
  43. agent_worker/worker.py +4877 -0
  44. codetether/__init__.py +10 -0
  45. codetether/__main__.py +4 -0
  46. codetether/cli.py +112 -0
  47. codetether/worker_cli.py +57 -0
  48. codetether-1.2.2.dist-info/METADATA +570 -0
  49. codetether-1.2.2.dist-info/RECORD +66 -0
  50. codetether-1.2.2.dist-info/WHEEL +5 -0
  51. codetether-1.2.2.dist-info/entry_points.txt +4 -0
  52. codetether-1.2.2.dist-info/licenses/LICENSE +202 -0
  53. codetether-1.2.2.dist-info/top_level.txt +5 -0
  54. codetether_voice_agent/__init__.py +6 -0
  55. codetether_voice_agent/agent.py +445 -0
  56. codetether_voice_agent/codetether_mcp.py +345 -0
  57. codetether_voice_agent/config.py +16 -0
  58. codetether_voice_agent/functiongemma_caller.py +380 -0
  59. codetether_voice_agent/session_playback.py +247 -0
  60. codetether_voice_agent/tools/__init__.py +21 -0
  61. codetether_voice_agent/tools/definitions.py +135 -0
  62. codetether_voice_agent/tools/handlers.py +380 -0
  63. run_server.py +314 -0
  64. ui/monitor-tailwind.html +1790 -0
  65. ui/monitor.html +1775 -0
  66. ui/monitor.js +2662 -0
@@ -0,0 +1,191 @@
1
+ """
2
+ MCP Server implementation providing tools for A2A agents.
3
+ """
4
+
5
+ import asyncio
6
+ import logging
7
+ from typing import Any, Dict, List, Optional
8
+ from datetime import datetime
9
+ import json
10
+ import math
11
+ import sys
12
+ import os
13
+
14
+ # Add the parent directory to Python path for imports
15
+ sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
16
+
17
+ from mcp.server import Server
18
+ from mcp.server.stdio import stdio_server
19
+ from mcp.types import TextContent
20
+
21
+ logger = logging.getLogger(__name__)
22
+
23
+
24
+ class MCPToolServer:
25
+ """MCP server providing tools for A2A agents."""
26
+
27
+ def __init__(self, host: str = "localhost", port: int = 9000):
28
+ self.host = host
29
+ self.port = port
30
+ self.server = Server("a2a-tools")
31
+ self._setup_tools()
32
+
33
+ def _setup_tools(self):
34
+ """Set up available tools."""
35
+
36
+ @self.server.tool()
37
+ async def calculator(
38
+ operation: str,
39
+ a: float,
40
+ b: Optional[float] = None
41
+ ) -> str:
42
+ """
43
+ Perform mathematical calculations.
44
+
45
+ Args:
46
+ operation: The operation to perform (add, subtract, multiply, divide, square, sqrt)
47
+ a: First number
48
+ b: Second number (optional for unary operations)
49
+ """
50
+ try:
51
+ if operation == "add":
52
+ if b is None:
53
+ return json.dumps({"error": "Addition requires two numbers"})
54
+ result = a + b
55
+ elif operation == "subtract":
56
+ if b is None:
57
+ return json.dumps({"error": "Subtraction requires two numbers"})
58
+ result = a - b
59
+ elif operation == "multiply":
60
+ if b is None:
61
+ return json.dumps({"error": "Multiplication requires two numbers"})
62
+ result = a * b
63
+ elif operation == "divide":
64
+ if b is None:
65
+ return json.dumps({"error": "Division requires two numbers"})
66
+ if b == 0:
67
+ return json.dumps({"error": "Cannot divide by zero"})
68
+ result = a / b
69
+ elif operation == "square":
70
+ result = a ** 2
71
+ elif operation == "sqrt":
72
+ if a < 0:
73
+ return json.dumps({"error": "Cannot take square root of negative number"})
74
+ result = math.sqrt(a)
75
+ else:
76
+ return json.dumps({"error": f"Unknown operation: {operation}"})
77
+
78
+ return json.dumps({"result": result, "operation": operation, "inputs": {"a": a, "b": b}})
79
+
80
+ except Exception as e:
81
+ return json.dumps({"error": f"Calculation error: {str(e)}"})
82
+
83
+ @self.server.tool()
84
+ async def weather_info(location: str) -> str:
85
+ """
86
+ Get weather information for a location (mock implementation).
87
+
88
+ Args:
89
+ location: The location to get weather for
90
+ """
91
+ # Mock weather data
92
+ mock_weather = {
93
+ "location": location,
94
+ "temperature": "22°C",
95
+ "condition": "Partly cloudy",
96
+ "humidity": "65%",
97
+ "wind": "10 km/h SW",
98
+ "timestamp": datetime.now().isoformat()
99
+ }
100
+ return json.dumps(mock_weather)
101
+
102
+ @self.server.tool()
103
+ async def text_analyzer(text: str) -> str:
104
+ """
105
+ Analyze text and provide statistics.
106
+
107
+ Args:
108
+ text: The text to analyze
109
+ """
110
+ words = text.split()
111
+ sentences = text.split('.')
112
+ chars = len(text)
113
+ chars_no_spaces = len(text.replace(' ', ''))
114
+
115
+ analysis = {
116
+ "text": text,
117
+ "word_count": len(words),
118
+ "sentence_count": len([s for s in sentences if s.strip()]),
119
+ "character_count": chars,
120
+ "character_count_no_spaces": chars_no_spaces,
121
+ "average_word_length": sum(len(word) for word in words) / len(words) if words else 0,
122
+ "timestamp": datetime.now().isoformat()
123
+ }
124
+ return json.dumps(analysis)
125
+
126
+ @self.server.tool()
127
+ async def memory_store(
128
+ action: str,
129
+ key: Optional[str] = None,
130
+ value: Optional[str] = None
131
+ ) -> str:
132
+ """
133
+ Simple key-value memory store for agents.
134
+
135
+ Args:
136
+ action: Action to perform (store, retrieve, list, delete)
137
+ key: Key for store/retrieve/delete operations
138
+ value: Value for store operation
139
+ """
140
+ if not hasattr(self, '_memory'):
141
+ self._memory = {}
142
+
143
+ try:
144
+ if action == "store":
145
+ if key is None or value is None:
146
+ return json.dumps({"error": "Store action requires both key and value"})
147
+ self._memory[key] = value
148
+ return json.dumps({"action": "store", "key": key, "value": value, "success": True})
149
+
150
+ elif action == "retrieve":
151
+ if key is None:
152
+ return json.dumps({"error": "Retrieve action requires a key"})
153
+ value = self._memory.get(key)
154
+ if value is None:
155
+ return json.dumps({"action": "retrieve", "key": key, "found": False})
156
+ return json.dumps({"action": "retrieve", "key": key, "value": value, "found": True})
157
+
158
+ elif action == "list":
159
+ keys = list(self._memory.keys())
160
+ return json.dumps({"action": "list", "keys": keys, "count": len(keys)})
161
+
162
+ elif action == "delete":
163
+ if key is None:
164
+ return json.dumps({"error": "Delete action requires a key"})
165
+ if key in self._memory:
166
+ del self._memory[key]
167
+ return json.dumps({"action": "delete", "key": key, "success": True})
168
+ return json.dumps({"action": "delete", "key": key, "success": False, "error": "Key not found"})
169
+
170
+ else:
171
+ return json.dumps({"error": f"Unknown action: {action}"})
172
+
173
+ except Exception as e:
174
+ return json.dumps({"error": f"Memory operation error: {str(e)}"})
175
+
176
+ async def run(self):
177
+ """Run the MCP server."""
178
+ logger.info(f"Starting MCP tool server")
179
+
180
+ async with stdio_server() as (read_stream, write_stream):
181
+ await self.server.run(read_stream, write_stream)
182
+
183
+
184
+ async def run_mcp_server():
185
+ """Run the MCP server."""
186
+ server = MCPToolServer()
187
+ await server.run()
188
+
189
+
190
+ if __name__ == "__main__":
191
+ asyncio.run(run_mcp_server())