daita-agents 0.2.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 (69) hide show
  1. daita/__init__.py +216 -0
  2. daita/agents/__init__.py +33 -0
  3. daita/agents/base.py +743 -0
  4. daita/agents/substrate.py +1141 -0
  5. daita/cli/__init__.py +145 -0
  6. daita/cli/__main__.py +7 -0
  7. daita/cli/ascii_art.py +44 -0
  8. daita/cli/core/__init__.py +0 -0
  9. daita/cli/core/create.py +254 -0
  10. daita/cli/core/deploy.py +473 -0
  11. daita/cli/core/deployments.py +309 -0
  12. daita/cli/core/import_detector.py +219 -0
  13. daita/cli/core/init.py +481 -0
  14. daita/cli/core/logs.py +239 -0
  15. daita/cli/core/managed_deploy.py +709 -0
  16. daita/cli/core/run.py +648 -0
  17. daita/cli/core/status.py +421 -0
  18. daita/cli/core/test.py +239 -0
  19. daita/cli/core/webhooks.py +172 -0
  20. daita/cli/main.py +588 -0
  21. daita/cli/utils.py +541 -0
  22. daita/config/__init__.py +62 -0
  23. daita/config/base.py +159 -0
  24. daita/config/settings.py +184 -0
  25. daita/core/__init__.py +262 -0
  26. daita/core/decision_tracing.py +701 -0
  27. daita/core/exceptions.py +480 -0
  28. daita/core/focus.py +251 -0
  29. daita/core/interfaces.py +76 -0
  30. daita/core/plugin_tracing.py +550 -0
  31. daita/core/relay.py +779 -0
  32. daita/core/reliability.py +381 -0
  33. daita/core/scaling.py +459 -0
  34. daita/core/tools.py +554 -0
  35. daita/core/tracing.py +770 -0
  36. daita/core/workflow.py +1144 -0
  37. daita/display/__init__.py +1 -0
  38. daita/display/console.py +160 -0
  39. daita/execution/__init__.py +58 -0
  40. daita/execution/client.py +856 -0
  41. daita/execution/exceptions.py +92 -0
  42. daita/execution/models.py +317 -0
  43. daita/llm/__init__.py +60 -0
  44. daita/llm/anthropic.py +291 -0
  45. daita/llm/base.py +530 -0
  46. daita/llm/factory.py +101 -0
  47. daita/llm/gemini.py +355 -0
  48. daita/llm/grok.py +219 -0
  49. daita/llm/mock.py +172 -0
  50. daita/llm/openai.py +220 -0
  51. daita/plugins/__init__.py +141 -0
  52. daita/plugins/base.py +37 -0
  53. daita/plugins/base_db.py +167 -0
  54. daita/plugins/elasticsearch.py +849 -0
  55. daita/plugins/mcp.py +481 -0
  56. daita/plugins/mongodb.py +520 -0
  57. daita/plugins/mysql.py +362 -0
  58. daita/plugins/postgresql.py +342 -0
  59. daita/plugins/redis_messaging.py +500 -0
  60. daita/plugins/rest.py +537 -0
  61. daita/plugins/s3.py +770 -0
  62. daita/plugins/slack.py +729 -0
  63. daita/utils/__init__.py +18 -0
  64. daita_agents-0.2.0.dist-info/METADATA +409 -0
  65. daita_agents-0.2.0.dist-info/RECORD +69 -0
  66. daita_agents-0.2.0.dist-info/WHEEL +5 -0
  67. daita_agents-0.2.0.dist-info/entry_points.txt +2 -0
  68. daita_agents-0.2.0.dist-info/licenses/LICENSE +56 -0
  69. daita_agents-0.2.0.dist-info/top_level.txt +1 -0
daita/cli/core/logs.py ADDED
@@ -0,0 +1,239 @@
1
+ """
2
+ Simple logs display for Daita CLI.
3
+ Shows deployment history and logs like git log from cloud API.
4
+ """
5
+ import os
6
+ import aiohttp
7
+ from datetime import datetime
8
+ from ..utils import find_project_root
9
+
10
+
11
+ async def show_deployment_logs(environment=None, limit=10, follow=False, verbose=False):
12
+ """Show deployment logs (like git log) from cloud API."""
13
+
14
+ # Check API key first
15
+ api_key = os.getenv('DAITA_API_KEY')
16
+ if not api_key:
17
+ from ..utils import show_upgrade_message
18
+ show_upgrade_message()
19
+ return
20
+
21
+ # Get current project name for display
22
+ project_root = find_project_root()
23
+ current_project = None
24
+ if project_root:
25
+ import yaml
26
+ config_file = project_root / 'daita-project.yaml'
27
+ if config_file.exists():
28
+ try:
29
+ with open(config_file, 'r') as f:
30
+ config = yaml.safe_load(f)
31
+ current_project = config.get('name')
32
+ except:
33
+ current_project = None
34
+
35
+ # Load deployments from cloud API
36
+ deployments, api_error = await _load_cloud_deployments(environment, limit)
37
+
38
+ if api_error:
39
+ print(f" Failed to fetch deployments: {api_error}")
40
+ if verbose:
41
+ print(f" API Key: {api_key[:20]}...")
42
+ print(f" Endpoint: {os.getenv('DAITA_API_ENDPOINT', 'https://api.daita.ai')}")
43
+ return
44
+
45
+ if not deployments:
46
+ if current_project:
47
+ if environment:
48
+ print(f" No deployments found ({current_project}, {environment})")
49
+ else:
50
+ print(f" No deployments found ({current_project})")
51
+ print(" Run 'daita push staging' to create your first deployment")
52
+ else:
53
+ print(" No deployments found")
54
+ if environment:
55
+ print(f" No deployments found for environment: {environment}")
56
+ else:
57
+ print(" Run 'daita push staging' to create your first deployment")
58
+ return
59
+
60
+ # Filter by environment if specified (additional client-side filtering)
61
+ if environment:
62
+ deployments = [d for d in deployments if d['environment'] == environment]
63
+ if not deployments:
64
+ print(f" No deployments found for environment: {environment}")
65
+ return
66
+
67
+ # Take most recent deployments (API already returns newest first)
68
+ deployments = deployments[:limit]
69
+
70
+ # Find the most recent active deployment
71
+ latest_active_deployment = None
72
+ for deployment in deployments:
73
+ if deployment.get('status') == 'active':
74
+ latest_active_deployment = deployment
75
+ break
76
+
77
+ # Build header with scope indication
78
+ header_parts = []
79
+ if current_project:
80
+ header_parts.append(current_project)
81
+ if environment:
82
+ header_parts.append(environment)
83
+
84
+ if header_parts:
85
+ scope_info = f" ({', '.join(header_parts)})"
86
+ elif current_project is None:
87
+ scope_info = " (Organization)"
88
+ else:
89
+ scope_info = ""
90
+
91
+ print(f" Deployment History{scope_info}")
92
+ print("")
93
+
94
+ for i, deployment in enumerate(deployments):
95
+ is_current = (latest_active_deployment and
96
+ deployment.get('deployment_id') == latest_active_deployment.get('deployment_id'))
97
+ _show_deployment(deployment, verbose, is_latest=is_current)
98
+ if i < len(deployments) - 1:
99
+ print("")
100
+
101
+ if follow:
102
+ print(f"\n Following logs... (Press Ctrl+C to stop)")
103
+ try:
104
+ import asyncio
105
+ while True:
106
+ await asyncio.sleep(5)
107
+ # Check for new deployments
108
+ new_deployments, error = await _load_cloud_deployments(environment, limit)
109
+ if error:
110
+ continue # Skip this check if API fails
111
+
112
+ if len(new_deployments) > len(deployments):
113
+ latest = new_deployments[-1]
114
+ print(f"\n New deployment:")
115
+ _show_deployment(latest, verbose, is_latest=True)
116
+ deployments = new_deployments
117
+ except KeyboardInterrupt:
118
+ print(f"\n Stopped following logs")
119
+
120
+ def _show_deployment(deployment, verbose, is_latest=False):
121
+ """Show a single deployment entry."""
122
+ env = deployment['environment']
123
+ timestamp = deployment['deployed_at']
124
+ version = deployment.get('version', '1.0.0')
125
+ project = deployment.get('project_name', 'Unknown')
126
+
127
+ # Format timestamp
128
+ if timestamp:
129
+ # Handle ISO format from API
130
+ if 'T' in timestamp:
131
+ dt = datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
132
+ time_str = dt.strftime('%Y-%m-%d %H:%M:%S')
133
+ else:
134
+ time_str = timestamp
135
+ else:
136
+ time_str = 'Unknown time'
137
+
138
+ # Status indicator
139
+ status = "●" if is_latest else "○"
140
+ current = " (current)" if is_latest else ""
141
+
142
+ print(f"{status} {env}: {project} v{version}{current}")
143
+ print(f" {time_str}")
144
+
145
+ if verbose:
146
+ # Show detailed info
147
+ agents = deployment.get('agents_config', [])
148
+ workflows = deployment.get('workflows_config', [])
149
+
150
+ if agents:
151
+ agent_names = [agent.get('name', 'unknown') for agent in agents]
152
+ print(f" Agents: {', '.join(agent_names)}")
153
+ if workflows:
154
+ workflow_names = [wf.get('name', 'unknown') for wf in workflows]
155
+ print(f" Workflows: {', '.join(workflow_names)}")
156
+
157
+ # Show deployment ID
158
+ deploy_id = deployment.get('deployment_id', 'N/A')
159
+ if len(deploy_id) > 8:
160
+ deploy_id = deploy_id[:8] # Show first 8 characters
161
+ print(f" ID: {deploy_id}")
162
+
163
+ # Show status
164
+ status = deployment.get('status', 'unknown')
165
+ print(f" Status: {status}")
166
+
167
+ async def _load_cloud_deployments(environment=None, limit=10):
168
+ """Load deployment history from cloud API."""
169
+ try:
170
+ api_key = os.getenv('DAITA_API_KEY')
171
+ if not api_key:
172
+ return [], "API key not found"
173
+
174
+ # Get current project name to filter deployments when in project directory
175
+ project_root = find_project_root()
176
+ if project_root:
177
+ import yaml
178
+ config_file = project_root / 'daita-project.yaml'
179
+ current_project = None
180
+ if config_file.exists():
181
+ try:
182
+ with open(config_file, 'r') as f:
183
+ config = yaml.safe_load(f)
184
+ current_project = config.get('name')
185
+ except:
186
+ current_project = None
187
+ else:
188
+ current_project = None
189
+
190
+ api_endpoint = os.getenv('DAITA_API_ENDPOINT', 'https://ondk4sdyv0.execute-api.us-east-1.amazonaws.com')
191
+
192
+ headers = {
193
+ "Authorization": f"Bearer {api_key}",
194
+ "User-Agent": "Daita-CLI/1.0.0"
195
+ }
196
+
197
+ async with aiohttp.ClientSession() as session:
198
+ # Build URL with filters
199
+ url = f"{api_endpoint}/api/v1/deployments/api-key"
200
+ params = {}
201
+ if environment:
202
+ params['environment'] = environment
203
+ if current_project:
204
+ params['project_name'] = current_project
205
+ if limit and limit != 10:
206
+ params['per_page'] = min(limit, 100) # API limit
207
+
208
+ async with session.get(url, headers=headers, params=params, timeout=30) as response:
209
+ if response.status == 200:
210
+ data = await response.json()
211
+
212
+ # Handle paginated response from API (like in status.py)
213
+ if isinstance(data, dict) and 'deployments' in data:
214
+ deployments = data['deployments']
215
+ else:
216
+ deployments = data if isinstance(data, list) else []
217
+
218
+ # Return deployments in API format (no conversion needed)
219
+ return deployments, None
220
+ elif response.status == 401:
221
+ return [], "Invalid API key"
222
+ elif response.status == 403:
223
+ return [], "Access denied - check API key permissions"
224
+ else:
225
+ error_text = await response.text()
226
+ return [], f"API error {response.status}: {error_text[:100]}"
227
+ except Exception as e:
228
+ if "timeout" in str(e).lower():
229
+ return [], "Request timeout - check your connection"
230
+ elif "dns" in str(e).lower() or "name" in str(e).lower():
231
+ return [], f"Cannot resolve API endpoint - check DAITA_API_ENDPOINT setting"
232
+ else:
233
+ return [], f"Network error: {str(e)}"
234
+
235
+ def _get_deployment_id(deployment):
236
+ """Generate short deployment ID."""
237
+ import hashlib
238
+ content = f"{deployment['deployed_at']}{deployment['environment']}"
239
+ return hashlib.md5(content.encode()).hexdigest()[:8]