ainative-python 2.0.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.
- ainative/__init__.py +46 -0
- ainative/agent_coordination.py +249 -0
- ainative/agent_identity_system.py +1566 -0
- ainative/agent_learning.py +239 -0
- ainative/agent_orchestration.py +202 -0
- ainative/agent_state.py +231 -0
- ainative/agent_swarm/__init__.py +510 -0
- ainative/auth.py +113 -0
- ainative/cli.py +698 -0
- ainative/cli_utils/__init__.py +13 -0
- ainative/cli_utils/diff.py +292 -0
- ainative/cli_utils/formatters.py +227 -0
- ainative/client.py +272 -0
- ainative/commands/__init__.py +28 -0
- ainative/commands/agents.py +238 -0
- ainative/commands/coordination.py +108 -0
- ainative/commands/inspect.py +483 -0
- ainative/commands/learning.py +119 -0
- ainative/commands/local.py +544 -0
- ainative/commands/state.py +144 -0
- ainative/commands/swarm.py +184 -0
- ainative/commands/sync.py +157 -0
- ainative/commands/tasks.py +191 -0
- ainative/exceptions.py +87 -0
- ainative/zerodb/__init__.py +89 -0
- ainative/zerodb/analytics.py +232 -0
- ainative/zerodb/memory.py +260 -0
- ainative/zerodb/projects.py +224 -0
- ainative/zerodb/tables.py +362 -0
- ainative/zerodb/vectors.py +231 -0
- ainative_python-2.0.0.dist-info/METADATA +550 -0
- ainative_python-2.0.0.dist-info/RECORD +35 -0
- ainative_python-2.0.0.dist-info/WHEEL +5 -0
- ainative_python-2.0.0.dist-info/entry_points.txt +2 -0
- ainative_python-2.0.0.dist-info/top_level.txt +1 -0
ainative/cli.py
ADDED
|
@@ -0,0 +1,698 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AINative SDK Command Line Interface
|
|
3
|
+
|
|
4
|
+
Provides a comprehensive CLI for interacting with AINative Studio APIs.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import sys
|
|
9
|
+
import json
|
|
10
|
+
import click
|
|
11
|
+
from typing import Optional, List, Dict, Any
|
|
12
|
+
import numpy as np
|
|
13
|
+
from datetime import datetime, timedelta
|
|
14
|
+
|
|
15
|
+
from . import AINativeClient, __version__
|
|
16
|
+
from .auth import AuthConfig
|
|
17
|
+
from .exceptions import AINativeException, APIError, AuthenticationError
|
|
18
|
+
from .zerodb.memory import MemoryPriority
|
|
19
|
+
from .agent_swarm import AgentType
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Global client instance
|
|
23
|
+
client: Optional[AINativeClient] = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_client() -> AINativeClient:
|
|
27
|
+
"""Get or create global client instance."""
|
|
28
|
+
global client
|
|
29
|
+
if client is None:
|
|
30
|
+
# Load configuration
|
|
31
|
+
api_key = os.getenv("AINATIVE_API_KEY")
|
|
32
|
+
api_secret = os.getenv("AINATIVE_API_SECRET")
|
|
33
|
+
base_url = os.getenv("AINATIVE_BASE_URL")
|
|
34
|
+
org_id = os.getenv("AINATIVE_ORG_ID")
|
|
35
|
+
|
|
36
|
+
if not api_key:
|
|
37
|
+
click.echo("Error: AINATIVE_API_KEY environment variable not set", err=True)
|
|
38
|
+
click.echo("Run: export AINATIVE_API_KEY=your-api-key", err=True)
|
|
39
|
+
sys.exit(1)
|
|
40
|
+
|
|
41
|
+
auth_config = AuthConfig(
|
|
42
|
+
api_key=api_key,
|
|
43
|
+
api_secret=api_secret
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
client = AINativeClient(
|
|
47
|
+
auth_config=auth_config,
|
|
48
|
+
base_url=base_url,
|
|
49
|
+
organization_id=org_id
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
return client
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def handle_error(error: Exception):
|
|
56
|
+
"""Handle and display errors consistently."""
|
|
57
|
+
if isinstance(error, AuthenticationError):
|
|
58
|
+
click.echo(f"Authentication Error: {error.message}", err=True)
|
|
59
|
+
click.echo("Check your API key and try again.", err=True)
|
|
60
|
+
elif isinstance(error, APIError):
|
|
61
|
+
click.echo(f"API Error ({error.status_code}): {error.message}", err=True)
|
|
62
|
+
if error.response_body:
|
|
63
|
+
try:
|
|
64
|
+
body = json.loads(error.response_body)
|
|
65
|
+
if body.get("detail"):
|
|
66
|
+
click.echo(f"Details: {body['detail']}", err=True)
|
|
67
|
+
except json.JSONDecodeError:
|
|
68
|
+
pass
|
|
69
|
+
elif isinstance(error, AINativeException):
|
|
70
|
+
click.echo(f"Error: {error.message}", err=True)
|
|
71
|
+
else:
|
|
72
|
+
click.echo(f"Unexpected error: {str(error)}", err=True)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def format_output(data: Any, format_type: str = "json") -> str:
|
|
76
|
+
"""Format output data for display."""
|
|
77
|
+
if format_type == "json":
|
|
78
|
+
return json.dumps(data, indent=2, default=str)
|
|
79
|
+
elif format_type == "table":
|
|
80
|
+
# Simple table formatting for lists
|
|
81
|
+
if isinstance(data, list) and data:
|
|
82
|
+
if isinstance(data[0], dict):
|
|
83
|
+
headers = list(data[0].keys())
|
|
84
|
+
rows = []
|
|
85
|
+
for item in data:
|
|
86
|
+
row = [str(item.get(header, "")) for header in headers]
|
|
87
|
+
rows.append(row)
|
|
88
|
+
|
|
89
|
+
# Simple table display
|
|
90
|
+
result = "\t".join(headers) + "\n"
|
|
91
|
+
for row in rows:
|
|
92
|
+
result += "\t".join(row) + "\n"
|
|
93
|
+
return result
|
|
94
|
+
return json.dumps(data, indent=2, default=str)
|
|
95
|
+
else:
|
|
96
|
+
return str(data)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
# Main CLI group
|
|
100
|
+
@click.group()
|
|
101
|
+
@click.version_option(version=__version__, prog_name="ainative")
|
|
102
|
+
@click.option("--verbose", "-v", is_flag=True, help="Enable verbose output")
|
|
103
|
+
@click.pass_context
|
|
104
|
+
def cli(ctx, verbose):
|
|
105
|
+
"""AINative SDK Command Line Interface"""
|
|
106
|
+
ctx.ensure_object(dict)
|
|
107
|
+
ctx.obj["verbose"] = verbose
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# Configuration commands
|
|
111
|
+
@cli.group()
|
|
112
|
+
def config():
|
|
113
|
+
"""Configuration management commands"""
|
|
114
|
+
pass
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@config.command()
|
|
118
|
+
@click.argument("key")
|
|
119
|
+
@click.argument("value")
|
|
120
|
+
def set(key, value):
|
|
121
|
+
"""Set configuration value"""
|
|
122
|
+
if key == "api_key":
|
|
123
|
+
click.echo(f"Set AINATIVE_API_KEY environment variable to: {value}")
|
|
124
|
+
click.echo("Run: export AINATIVE_API_KEY=" + value)
|
|
125
|
+
elif key == "base_url":
|
|
126
|
+
click.echo(f"Set AINATIVE_BASE_URL environment variable to: {value}")
|
|
127
|
+
click.echo("Run: export AINATIVE_BASE_URL=" + value)
|
|
128
|
+
else:
|
|
129
|
+
click.echo(f"Unknown configuration key: {key}")
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
@config.command()
|
|
133
|
+
def show():
|
|
134
|
+
"""Show current configuration"""
|
|
135
|
+
config_items = [
|
|
136
|
+
("API Key", os.getenv("AINATIVE_API_KEY", "Not set")),
|
|
137
|
+
("API Secret", "***" if os.getenv("AINATIVE_API_SECRET") else "Not set"),
|
|
138
|
+
("Base URL", os.getenv("AINATIVE_BASE_URL", "Default")),
|
|
139
|
+
("Organization ID", os.getenv("AINATIVE_ORG_ID", "Not set")),
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
for key, value in config_items:
|
|
143
|
+
click.echo(f"{key}: {value}")
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
# Project commands
|
|
147
|
+
@cli.group()
|
|
148
|
+
def projects():
|
|
149
|
+
"""ZeroDB project management commands"""
|
|
150
|
+
pass
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@projects.command()
|
|
154
|
+
@click.option("--limit", default=10, help="Maximum number of projects to return")
|
|
155
|
+
@click.option("--offset", default=0, help="Number of projects to skip")
|
|
156
|
+
@click.option("--status", help="Filter by project status")
|
|
157
|
+
@click.option("--format", "output_format", default="json", type=click.Choice(["json", "table"]))
|
|
158
|
+
def list(limit, offset, status, output_format):
|
|
159
|
+
"""List projects"""
|
|
160
|
+
try:
|
|
161
|
+
client = get_client()
|
|
162
|
+
from .zerodb.projects import ProjectStatus
|
|
163
|
+
|
|
164
|
+
status_filter = None
|
|
165
|
+
if status:
|
|
166
|
+
try:
|
|
167
|
+
status_filter = ProjectStatus(status)
|
|
168
|
+
except ValueError:
|
|
169
|
+
click.echo(f"Invalid status: {status}", err=True)
|
|
170
|
+
return
|
|
171
|
+
|
|
172
|
+
result = client.zerodb.projects.list(
|
|
173
|
+
limit=limit,
|
|
174
|
+
offset=offset,
|
|
175
|
+
status=status_filter
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
click.echo(format_output(result, output_format))
|
|
179
|
+
|
|
180
|
+
except Exception as e:
|
|
181
|
+
handle_error(e)
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
@projects.command()
|
|
185
|
+
@click.argument("name")
|
|
186
|
+
@click.option("--description", help="Project description")
|
|
187
|
+
@click.option("--metadata", help="Project metadata as JSON string")
|
|
188
|
+
def create(name, description, metadata):
|
|
189
|
+
"""Create a new project"""
|
|
190
|
+
try:
|
|
191
|
+
client = get_client()
|
|
192
|
+
|
|
193
|
+
metadata_dict = {}
|
|
194
|
+
if metadata:
|
|
195
|
+
metadata_dict = json.loads(metadata)
|
|
196
|
+
|
|
197
|
+
result = client.zerodb.projects.create(
|
|
198
|
+
name=name,
|
|
199
|
+
description=description,
|
|
200
|
+
metadata=metadata_dict
|
|
201
|
+
)
|
|
202
|
+
|
|
203
|
+
click.echo(f"Created project: {result['id']}")
|
|
204
|
+
click.echo(format_output(result))
|
|
205
|
+
|
|
206
|
+
except Exception as e:
|
|
207
|
+
handle_error(e)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
@projects.command()
|
|
211
|
+
@click.argument("project_id")
|
|
212
|
+
def get(project_id):
|
|
213
|
+
"""Get project details"""
|
|
214
|
+
try:
|
|
215
|
+
client = get_client()
|
|
216
|
+
result = client.zerodb.projects.get(project_id)
|
|
217
|
+
click.echo(format_output(result))
|
|
218
|
+
|
|
219
|
+
except Exception as e:
|
|
220
|
+
handle_error(e)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
@projects.command()
|
|
224
|
+
@click.argument("project_id")
|
|
225
|
+
@click.option("--reason", help="Reason for suspension")
|
|
226
|
+
def suspend(project_id, reason):
|
|
227
|
+
"""Suspend a project"""
|
|
228
|
+
try:
|
|
229
|
+
client = get_client()
|
|
230
|
+
result = client.zerodb.projects.suspend(project_id, reason=reason)
|
|
231
|
+
click.echo(f"Project {project_id} suspended")
|
|
232
|
+
click.echo(format_output(result))
|
|
233
|
+
|
|
234
|
+
except Exception as e:
|
|
235
|
+
handle_error(e)
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
@projects.command()
|
|
239
|
+
@click.argument("project_id")
|
|
240
|
+
def activate(project_id):
|
|
241
|
+
"""Activate a suspended project"""
|
|
242
|
+
try:
|
|
243
|
+
client = get_client()
|
|
244
|
+
result = client.zerodb.projects.activate(project_id)
|
|
245
|
+
click.echo(f"Project {project_id} activated")
|
|
246
|
+
click.echo(format_output(result))
|
|
247
|
+
|
|
248
|
+
except Exception as e:
|
|
249
|
+
handle_error(e)
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
@projects.command()
|
|
253
|
+
@click.argument("project_id")
|
|
254
|
+
@click.confirmation_option(prompt="Are you sure you want to delete this project?")
|
|
255
|
+
def delete(project_id):
|
|
256
|
+
"""Delete a project"""
|
|
257
|
+
try:
|
|
258
|
+
client = get_client()
|
|
259
|
+
result = client.zerodb.projects.delete(project_id)
|
|
260
|
+
click.echo(f"Project {project_id} deleted")
|
|
261
|
+
click.echo(format_output(result))
|
|
262
|
+
|
|
263
|
+
except Exception as e:
|
|
264
|
+
handle_error(e)
|
|
265
|
+
|
|
266
|
+
|
|
267
|
+
# Vector commands
|
|
268
|
+
@cli.group()
|
|
269
|
+
def vectors():
|
|
270
|
+
"""Vector operations commands"""
|
|
271
|
+
pass
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
@vectors.command()
|
|
275
|
+
@click.argument("project_id")
|
|
276
|
+
@click.argument("query", nargs=-1)
|
|
277
|
+
@click.option("--top-k", default=5, help="Number of results to return")
|
|
278
|
+
@click.option("--namespace", default="default", help="Vector namespace")
|
|
279
|
+
@click.option("--include-metadata", is_flag=True, default=True, help="Include metadata in results")
|
|
280
|
+
def search(project_id, query, top_k, namespace, include_metadata):
|
|
281
|
+
"""Search vectors (requires vector as space-separated numbers)"""
|
|
282
|
+
try:
|
|
283
|
+
client = get_client()
|
|
284
|
+
|
|
285
|
+
if not query:
|
|
286
|
+
click.echo("Error: Query vector required", err=True)
|
|
287
|
+
click.echo("Example: ainative vectors search proj_123 0.1 0.2 0.3", err=True)
|
|
288
|
+
return
|
|
289
|
+
|
|
290
|
+
# Convert query to vector
|
|
291
|
+
try:
|
|
292
|
+
query_vector = [float(x) for x in query]
|
|
293
|
+
except ValueError:
|
|
294
|
+
click.echo("Error: Query must be numeric values", err=True)
|
|
295
|
+
return
|
|
296
|
+
|
|
297
|
+
results = client.zerodb.vectors.search(
|
|
298
|
+
project_id=project_id,
|
|
299
|
+
vector=query_vector,
|
|
300
|
+
top_k=top_k,
|
|
301
|
+
namespace=namespace,
|
|
302
|
+
include_metadata=include_metadata
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
click.echo(f"Found {len(results)} results:")
|
|
306
|
+
click.echo(format_output(results))
|
|
307
|
+
|
|
308
|
+
except Exception as e:
|
|
309
|
+
handle_error(e)
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
@vectors.command()
|
|
313
|
+
@click.argument("project_id")
|
|
314
|
+
@click.argument("vector_file", type=click.File("r"))
|
|
315
|
+
@click.option("--namespace", default="default", help="Vector namespace")
|
|
316
|
+
@click.option("--metadata-file", type=click.File("r"), help="JSON file containing metadata")
|
|
317
|
+
def upsert(project_id, vector_file, namespace, metadata_file):
|
|
318
|
+
"""Upsert vectors from JSON file"""
|
|
319
|
+
try:
|
|
320
|
+
client = get_client()
|
|
321
|
+
|
|
322
|
+
# Load vectors
|
|
323
|
+
vectors_data = json.load(vector_file)
|
|
324
|
+
|
|
325
|
+
# Load metadata if provided
|
|
326
|
+
metadata = None
|
|
327
|
+
if metadata_file:
|
|
328
|
+
metadata = json.load(metadata_file)
|
|
329
|
+
|
|
330
|
+
result = client.zerodb.vectors.upsert(
|
|
331
|
+
project_id=project_id,
|
|
332
|
+
vectors=vectors_data,
|
|
333
|
+
metadata=metadata,
|
|
334
|
+
namespace=namespace
|
|
335
|
+
)
|
|
336
|
+
|
|
337
|
+
click.echo("Vectors upserted successfully")
|
|
338
|
+
click.echo(format_output(result))
|
|
339
|
+
|
|
340
|
+
except Exception as e:
|
|
341
|
+
handle_error(e)
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
@vectors.command()
|
|
345
|
+
@click.argument("project_id")
|
|
346
|
+
@click.option("--namespace", help="Vector namespace")
|
|
347
|
+
def stats(project_id, namespace):
|
|
348
|
+
"""Get vector index statistics"""
|
|
349
|
+
try:
|
|
350
|
+
client = get_client()
|
|
351
|
+
result = client.zerodb.vectors.describe_index_stats(
|
|
352
|
+
project_id=project_id,
|
|
353
|
+
namespace=namespace
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
click.echo("Vector Index Statistics:")
|
|
357
|
+
click.echo(format_output(result))
|
|
358
|
+
|
|
359
|
+
except Exception as e:
|
|
360
|
+
handle_error(e)
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
# Memory commands
|
|
364
|
+
@cli.group()
|
|
365
|
+
def memory():
|
|
366
|
+
"""Memory operations commands"""
|
|
367
|
+
pass
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
@memory.command()
|
|
371
|
+
@click.argument("content")
|
|
372
|
+
@click.option("--title", help="Memory title")
|
|
373
|
+
@click.option("--tags", help="Comma-separated tags")
|
|
374
|
+
@click.option("--priority", type=click.Choice(["low", "medium", "high", "critical"]), default="medium")
|
|
375
|
+
@click.option("--project-id", help="Project ID")
|
|
376
|
+
def create(content, title, tags, priority, project_id):
|
|
377
|
+
"""Create a new memory entry"""
|
|
378
|
+
try:
|
|
379
|
+
client = get_client()
|
|
380
|
+
|
|
381
|
+
tag_list = []
|
|
382
|
+
if tags:
|
|
383
|
+
tag_list = [tag.strip() for tag in tags.split(",")]
|
|
384
|
+
|
|
385
|
+
priority_enum = MemoryPriority(priority)
|
|
386
|
+
|
|
387
|
+
result = client.zerodb.memory.create(
|
|
388
|
+
content=content,
|
|
389
|
+
title=title,
|
|
390
|
+
tags=tag_list,
|
|
391
|
+
priority=priority_enum,
|
|
392
|
+
project_id=project_id
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
click.echo(f"Created memory: {result['id']}")
|
|
396
|
+
click.echo(format_output(result))
|
|
397
|
+
|
|
398
|
+
except Exception as e:
|
|
399
|
+
handle_error(e)
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
@memory.command()
|
|
403
|
+
@click.argument("query")
|
|
404
|
+
@click.option("--limit", default=5, help="Number of results to return")
|
|
405
|
+
@click.option("--project-id", help="Project ID filter")
|
|
406
|
+
@click.option("--semantic", is_flag=True, default=True, help="Use semantic search")
|
|
407
|
+
def search(query, limit, project_id, semantic):
|
|
408
|
+
"""Search memory entries"""
|
|
409
|
+
try:
|
|
410
|
+
client = get_client()
|
|
411
|
+
|
|
412
|
+
results = client.zerodb.memory.search(
|
|
413
|
+
query=query,
|
|
414
|
+
limit=limit,
|
|
415
|
+
project_id=project_id,
|
|
416
|
+
semantic=semantic
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
click.echo(f"Found {len(results)} memories:")
|
|
420
|
+
click.echo(format_output(results))
|
|
421
|
+
|
|
422
|
+
except Exception as e:
|
|
423
|
+
handle_error(e)
|
|
424
|
+
|
|
425
|
+
|
|
426
|
+
@memory.command()
|
|
427
|
+
@click.option("--limit", default=10, help="Number of memories to return")
|
|
428
|
+
@click.option("--project-id", help="Project ID filter")
|
|
429
|
+
@click.option("--tags", help="Comma-separated tags filter")
|
|
430
|
+
@click.option("--priority", type=click.Choice(["low", "medium", "high", "critical"]))
|
|
431
|
+
def list(limit, project_id, tags, priority):
|
|
432
|
+
"""List memory entries"""
|
|
433
|
+
try:
|
|
434
|
+
client = get_client()
|
|
435
|
+
|
|
436
|
+
tag_list = None
|
|
437
|
+
if tags:
|
|
438
|
+
tag_list = [tag.strip() for tag in tags.split(",")]
|
|
439
|
+
|
|
440
|
+
priority_filter = None
|
|
441
|
+
if priority:
|
|
442
|
+
priority_filter = MemoryPriority(priority)
|
|
443
|
+
|
|
444
|
+
result = client.zerodb.memory.list(
|
|
445
|
+
limit=limit,
|
|
446
|
+
project_id=project_id,
|
|
447
|
+
tags=tag_list,
|
|
448
|
+
priority=priority_filter
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
click.echo(format_output(result))
|
|
452
|
+
|
|
453
|
+
except Exception as e:
|
|
454
|
+
handle_error(e)
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
# Agent Swarm commands
|
|
458
|
+
@cli.group()
|
|
459
|
+
def swarm():
|
|
460
|
+
"""Agent swarm operations commands"""
|
|
461
|
+
pass
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
@swarm.command("agent-types")
|
|
465
|
+
def agent_types():
|
|
466
|
+
"""List available agent types"""
|
|
467
|
+
try:
|
|
468
|
+
client = get_client()
|
|
469
|
+
result = client.agent_swarm.get_agent_types()
|
|
470
|
+
|
|
471
|
+
click.echo("Available Agent Types:")
|
|
472
|
+
click.echo(format_output(result))
|
|
473
|
+
|
|
474
|
+
except Exception as e:
|
|
475
|
+
handle_error(e)
|
|
476
|
+
|
|
477
|
+
|
|
478
|
+
@swarm.command()
|
|
479
|
+
@click.argument("project_id")
|
|
480
|
+
@click.argument("objective")
|
|
481
|
+
@click.argument("agents_file", type=click.File("r"))
|
|
482
|
+
@click.option("--config-file", type=click.File("r"), help="JSON file with swarm configuration")
|
|
483
|
+
def start(project_id, objective, agents_file, config_file):
|
|
484
|
+
"""Start agent swarm with agents from JSON file"""
|
|
485
|
+
try:
|
|
486
|
+
client = get_client()
|
|
487
|
+
|
|
488
|
+
# Load agents configuration
|
|
489
|
+
agents = json.load(agents_file)
|
|
490
|
+
|
|
491
|
+
# Load swarm configuration if provided
|
|
492
|
+
config = {}
|
|
493
|
+
if config_file:
|
|
494
|
+
config = json.load(config_file)
|
|
495
|
+
|
|
496
|
+
result = client.agent_swarm.start_swarm(
|
|
497
|
+
project_id=project_id,
|
|
498
|
+
agents=agents,
|
|
499
|
+
objective=objective,
|
|
500
|
+
config=config
|
|
501
|
+
)
|
|
502
|
+
|
|
503
|
+
click.echo(f"Started swarm: {result['id']}")
|
|
504
|
+
click.echo(format_output(result))
|
|
505
|
+
|
|
506
|
+
except Exception as e:
|
|
507
|
+
handle_error(e)
|
|
508
|
+
|
|
509
|
+
|
|
510
|
+
@swarm.command()
|
|
511
|
+
@click.argument("swarm_id")
|
|
512
|
+
def status(swarm_id):
|
|
513
|
+
"""Get swarm status"""
|
|
514
|
+
try:
|
|
515
|
+
client = get_client()
|
|
516
|
+
result = client.agent_swarm.get_status(swarm_id)
|
|
517
|
+
|
|
518
|
+
click.echo(f"Swarm Status: {result.get('status', 'unknown')}")
|
|
519
|
+
click.echo(format_output(result))
|
|
520
|
+
|
|
521
|
+
except Exception as e:
|
|
522
|
+
handle_error(e)
|
|
523
|
+
|
|
524
|
+
|
|
525
|
+
@swarm.command()
|
|
526
|
+
@click.argument("swarm_id")
|
|
527
|
+
@click.argument("task")
|
|
528
|
+
@click.option("--context", help="Task context as JSON string")
|
|
529
|
+
@click.option("--agents", help="Comma-separated list of specific agent IDs")
|
|
530
|
+
def orchestrate(swarm_id, task, context, agents):
|
|
531
|
+
"""Orchestrate a task within the swarm"""
|
|
532
|
+
try:
|
|
533
|
+
client = get_client()
|
|
534
|
+
|
|
535
|
+
context_dict = {}
|
|
536
|
+
if context:
|
|
537
|
+
context_dict = json.loads(context)
|
|
538
|
+
|
|
539
|
+
agent_list = None
|
|
540
|
+
if agents:
|
|
541
|
+
agent_list = [agent.strip() for agent in agents.split(",")]
|
|
542
|
+
|
|
543
|
+
result = client.agent_swarm.orchestrate(
|
|
544
|
+
swarm_id=swarm_id,
|
|
545
|
+
task=task,
|
|
546
|
+
context=context_dict,
|
|
547
|
+
agents=agent_list
|
|
548
|
+
)
|
|
549
|
+
|
|
550
|
+
click.echo(f"Task orchestrated: {result.get('task_id', 'unknown')}")
|
|
551
|
+
click.echo(format_output(result))
|
|
552
|
+
|
|
553
|
+
except Exception as e:
|
|
554
|
+
handle_error(e)
|
|
555
|
+
|
|
556
|
+
|
|
557
|
+
@swarm.command()
|
|
558
|
+
@click.argument("swarm_id")
|
|
559
|
+
@click.confirmation_option(prompt="Are you sure you want to stop this swarm?")
|
|
560
|
+
def stop(swarm_id):
|
|
561
|
+
"""Stop an agent swarm"""
|
|
562
|
+
try:
|
|
563
|
+
client = get_client()
|
|
564
|
+
result = client.agent_swarm.stop_swarm(swarm_id)
|
|
565
|
+
|
|
566
|
+
click.echo(f"Swarm {swarm_id} stopped")
|
|
567
|
+
click.echo(format_output(result))
|
|
568
|
+
|
|
569
|
+
except Exception as e:
|
|
570
|
+
handle_error(e)
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
# Analytics commands
|
|
574
|
+
@cli.group()
|
|
575
|
+
def analytics():
|
|
576
|
+
"""Analytics and metrics commands"""
|
|
577
|
+
pass
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
@analytics.command()
|
|
581
|
+
@click.option("--project-id", help="Project ID filter")
|
|
582
|
+
@click.option("--days", default=30, help="Number of days to analyze")
|
|
583
|
+
@click.option("--granularity", default="daily", type=click.Choice(["hourly", "daily", "weekly", "monthly"]))
|
|
584
|
+
def usage(project_id, days, granularity):
|
|
585
|
+
"""Get usage analytics"""
|
|
586
|
+
try:
|
|
587
|
+
client = get_client()
|
|
588
|
+
|
|
589
|
+
end_date = datetime.now()
|
|
590
|
+
start_date = end_date - timedelta(days=days)
|
|
591
|
+
|
|
592
|
+
result = client.zerodb.analytics.get_usage(
|
|
593
|
+
project_id=project_id,
|
|
594
|
+
start_date=start_date,
|
|
595
|
+
end_date=end_date,
|
|
596
|
+
granularity=granularity
|
|
597
|
+
)
|
|
598
|
+
|
|
599
|
+
click.echo(f"Usage Analytics ({days} days, {granularity}):")
|
|
600
|
+
click.echo(format_output(result))
|
|
601
|
+
|
|
602
|
+
except Exception as e:
|
|
603
|
+
handle_error(e)
|
|
604
|
+
|
|
605
|
+
|
|
606
|
+
@analytics.command()
|
|
607
|
+
@click.option("--project-id", help="Project ID filter")
|
|
608
|
+
def costs(project_id):
|
|
609
|
+
"""Get cost analysis"""
|
|
610
|
+
try:
|
|
611
|
+
client = get_client()
|
|
612
|
+
result = client.zerodb.analytics.get_cost_analysis(project_id=project_id)
|
|
613
|
+
|
|
614
|
+
click.echo("Cost Analysis:")
|
|
615
|
+
click.echo(format_output(result))
|
|
616
|
+
|
|
617
|
+
except Exception as e:
|
|
618
|
+
handle_error(e)
|
|
619
|
+
|
|
620
|
+
|
|
621
|
+
@analytics.command()
|
|
622
|
+
@click.argument("metric", type=click.Choice(["vectors", "queries", "storage", "errors"]))
|
|
623
|
+
@click.option("--project-id", help="Project ID filter")
|
|
624
|
+
@click.option("--days", default=30, help="Number of days to analyze")
|
|
625
|
+
def trends(metric, project_id, days):
|
|
626
|
+
"""Get trend data for specific metrics"""
|
|
627
|
+
try:
|
|
628
|
+
client = get_client()
|
|
629
|
+
result = client.zerodb.analytics.get_trends(
|
|
630
|
+
metric=metric,
|
|
631
|
+
project_id=project_id,
|
|
632
|
+
period=days
|
|
633
|
+
)
|
|
634
|
+
|
|
635
|
+
click.echo(f"{metric.title()} Trends ({days} days):")
|
|
636
|
+
click.echo(format_output(result))
|
|
637
|
+
|
|
638
|
+
except Exception as e:
|
|
639
|
+
handle_error(e)
|
|
640
|
+
|
|
641
|
+
|
|
642
|
+
# Health check command
|
|
643
|
+
@cli.command()
|
|
644
|
+
def health():
|
|
645
|
+
"""Check API health status"""
|
|
646
|
+
try:
|
|
647
|
+
client = get_client()
|
|
648
|
+
result = client.health_check()
|
|
649
|
+
|
|
650
|
+
click.echo("API Health Status:")
|
|
651
|
+
click.echo(format_output(result))
|
|
652
|
+
|
|
653
|
+
except Exception as e:
|
|
654
|
+
handle_error(e)
|
|
655
|
+
|
|
656
|
+
|
|
657
|
+
# Register new command groups
|
|
658
|
+
try:
|
|
659
|
+
from .commands import (
|
|
660
|
+
agents_group,
|
|
661
|
+
swarm_group,
|
|
662
|
+
task_group,
|
|
663
|
+
coordination_group,
|
|
664
|
+
learning_group,
|
|
665
|
+
state_group,
|
|
666
|
+
local_group,
|
|
667
|
+
inspect_group,
|
|
668
|
+
sync_group
|
|
669
|
+
)
|
|
670
|
+
cli.add_command(agents_group)
|
|
671
|
+
cli.add_command(swarm_group)
|
|
672
|
+
cli.add_command(task_group)
|
|
673
|
+
cli.add_command(coordination_group)
|
|
674
|
+
cli.add_command(learning_group)
|
|
675
|
+
cli.add_command(state_group)
|
|
676
|
+
cli.add_command(local_group)
|
|
677
|
+
cli.add_command(inspect_group)
|
|
678
|
+
cli.add_command(sync_group)
|
|
679
|
+
except ImportError as e:
|
|
680
|
+
# CLI command groups not available
|
|
681
|
+
# This is OK for initial usage
|
|
682
|
+
pass
|
|
683
|
+
|
|
684
|
+
|
|
685
|
+
def main():
|
|
686
|
+
"""Main CLI entry point"""
|
|
687
|
+
try:
|
|
688
|
+
cli()
|
|
689
|
+
except KeyboardInterrupt:
|
|
690
|
+
click.echo("\nOperation cancelled.", err=True)
|
|
691
|
+
sys.exit(1)
|
|
692
|
+
except Exception as e:
|
|
693
|
+
click.echo(f"Unexpected error: {str(e)}", err=True)
|
|
694
|
+
sys.exit(1)
|
|
695
|
+
|
|
696
|
+
|
|
697
|
+
if __name__ == "__main__":
|
|
698
|
+
main()
|