pygeai 0.6.0b10__py3-none-any.whl → 0.6.0b12__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 (135) hide show
  1. pygeai/_docs/source/content/ai_lab/cli.rst +4 -4
  2. pygeai/_docs/source/content/ai_lab/models.rst +169 -35
  3. pygeai/_docs/source/content/ai_lab/runner.rst +2 -2
  4. pygeai/_docs/source/content/ai_lab/spec.rst +9 -9
  5. pygeai/_docs/source/content/ai_lab/usage.rst +34 -34
  6. pygeai/_docs/source/content/ai_lab.rst +1 -1
  7. pygeai/_docs/source/content/analytics.rst +598 -0
  8. pygeai/_docs/source/content/api_reference/chat.rst +428 -2
  9. pygeai/_docs/source/content/api_reference/embeddings.rst +1 -1
  10. pygeai/_docs/source/content/api_reference/project.rst +184 -0
  11. pygeai/_docs/source/content/api_reference/rag.rst +2 -2
  12. pygeai/_docs/source/content/authentication.rst +295 -0
  13. pygeai/_docs/source/content/cli.rst +79 -2
  14. pygeai/_docs/source/content/debugger.rst +1 -1
  15. pygeai/_docs/source/content/migration.rst +19 -2
  16. pygeai/_docs/source/index.rst +2 -0
  17. pygeai/_docs/source/pygeai.analytics.rst +53 -0
  18. pygeai/_docs/source/pygeai.cli.commands.rst +8 -0
  19. pygeai/_docs/source/pygeai.rst +1 -0
  20. pygeai/_docs/source/pygeai.tests.analytics.rst +45 -0
  21. pygeai/_docs/source/pygeai.tests.auth.rst +8 -0
  22. pygeai/_docs/source/pygeai.tests.rst +1 -1
  23. pygeai/analytics/__init__.py +0 -0
  24. pygeai/analytics/clients.py +505 -0
  25. pygeai/analytics/endpoints.py +35 -0
  26. pygeai/analytics/managers.py +606 -0
  27. pygeai/analytics/mappers.py +207 -0
  28. pygeai/analytics/responses.py +240 -0
  29. pygeai/chat/clients.py +46 -1
  30. pygeai/chat/endpoints.py +1 -0
  31. pygeai/cli/commands/analytics.py +525 -0
  32. pygeai/cli/commands/base.py +16 -0
  33. pygeai/cli/commands/chat.py +95 -0
  34. pygeai/cli/commands/common.py +28 -24
  35. pygeai/cli/commands/migrate.py +75 -6
  36. pygeai/cli/commands/organization.py +265 -0
  37. pygeai/cli/commands/validators.py +144 -1
  38. pygeai/cli/error_handler.py +41 -6
  39. pygeai/cli/geai.py +99 -16
  40. pygeai/cli/parsers.py +75 -31
  41. pygeai/cli/texts/help.py +75 -6
  42. pygeai/core/base/clients.py +18 -4
  43. pygeai/core/base/session.py +46 -7
  44. pygeai/core/common/config.py +25 -2
  45. pygeai/core/common/exceptions.py +64 -1
  46. pygeai/core/services/rest.py +20 -2
  47. pygeai/evaluation/clients.py +5 -3
  48. pygeai/lab/agents/clients.py +3 -3
  49. pygeai/lab/agents/endpoints.py +2 -2
  50. pygeai/lab/agents/mappers.py +50 -2
  51. pygeai/lab/clients.py +5 -2
  52. pygeai/lab/managers.py +7 -9
  53. pygeai/lab/models.py +70 -2
  54. pygeai/lab/tools/clients.py +1 -59
  55. pygeai/migration/__init__.py +3 -1
  56. pygeai/migration/strategies.py +72 -3
  57. pygeai/organization/clients.py +110 -1
  58. pygeai/organization/endpoints.py +11 -7
  59. pygeai/organization/managers.py +134 -2
  60. pygeai/organization/mappers.py +28 -2
  61. pygeai/organization/responses.py +11 -1
  62. pygeai/tests/analytics/__init__.py +0 -0
  63. pygeai/tests/analytics/test_clients.py +86 -0
  64. pygeai/tests/analytics/test_managers.py +94 -0
  65. pygeai/tests/analytics/test_mappers.py +84 -0
  66. pygeai/tests/analytics/test_responses.py +73 -0
  67. pygeai/tests/auth/test_oauth.py +172 -0
  68. pygeai/tests/cli/commands/test_migrate.py +14 -1
  69. pygeai/tests/cli/commands/test_organization.py +69 -1
  70. pygeai/tests/cli/test_error_handler.py +4 -4
  71. pygeai/tests/cli/test_geai_driver.py +1 -1
  72. pygeai/tests/lab/agents/test_mappers.py +128 -1
  73. pygeai/tests/lab/test_models.py +2 -0
  74. pygeai/tests/lab/tools/test_clients.py +2 -31
  75. pygeai/tests/organization/test_clients.py +180 -1
  76. pygeai/tests/organization/test_managers.py +40 -0
  77. pygeai/tests/snippets/analytics/__init__.py +0 -0
  78. pygeai/tests/snippets/analytics/get_agent_usage_per_user.py +16 -0
  79. pygeai/tests/snippets/analytics/get_agents_created_and_modified.py +11 -0
  80. pygeai/tests/snippets/analytics/get_average_cost_per_request.py +10 -0
  81. pygeai/tests/snippets/analytics/get_overall_error_rate.py +10 -0
  82. pygeai/tests/snippets/analytics/get_top_10_agents_by_requests.py +12 -0
  83. pygeai/tests/snippets/analytics/get_total_active_users.py +10 -0
  84. pygeai/tests/snippets/analytics/get_total_cost.py +10 -0
  85. pygeai/tests/snippets/analytics/get_total_requests_per_day.py +12 -0
  86. pygeai/tests/snippets/analytics/get_total_tokens.py +12 -0
  87. pygeai/tests/snippets/chat/get_response_complete_example.py +67 -0
  88. pygeai/tests/snippets/chat/get_response_with_instructions.py +19 -0
  89. pygeai/tests/snippets/chat/get_response_with_metadata.py +24 -0
  90. pygeai/tests/snippets/chat/get_response_with_parallel_tools.py +58 -0
  91. pygeai/tests/snippets/chat/get_response_with_reasoning.py +21 -0
  92. pygeai/tests/snippets/chat/get_response_with_store.py +38 -0
  93. pygeai/tests/snippets/chat/get_response_with_truncation.py +24 -0
  94. pygeai/tests/snippets/lab/agents/create_agent_with_permissions.py +39 -0
  95. pygeai/tests/snippets/lab/agents/create_agent_with_properties.py +46 -0
  96. pygeai/tests/snippets/lab/agents/get_agent_with_new_fields.py +62 -0
  97. pygeai/tests/snippets/lab/agents/update_agent_properties.py +50 -0
  98. pygeai/tests/snippets/organization/add_project_member.py +10 -0
  99. pygeai/tests/snippets/organization/add_project_member_batch.py +44 -0
  100. {pygeai-0.6.0b10.dist-info → pygeai-0.6.0b12.dist-info}/METADATA +1 -1
  101. {pygeai-0.6.0b10.dist-info → pygeai-0.6.0b12.dist-info}/RECORD +105 -95
  102. pygeai/_docs/source/pygeai.tests.snippets.assistants.data_analyst.rst +0 -37
  103. pygeai/_docs/source/pygeai.tests.snippets.assistants.rag.rst +0 -85
  104. pygeai/_docs/source/pygeai.tests.snippets.assistants.rst +0 -78
  105. pygeai/_docs/source/pygeai.tests.snippets.auth.rst +0 -10
  106. pygeai/_docs/source/pygeai.tests.snippets.chat.rst +0 -125
  107. pygeai/_docs/source/pygeai.tests.snippets.dbg.rst +0 -45
  108. pygeai/_docs/source/pygeai.tests.snippets.embeddings.rst +0 -61
  109. pygeai/_docs/source/pygeai.tests.snippets.evaluation.dataset.rst +0 -197
  110. pygeai/_docs/source/pygeai.tests.snippets.evaluation.plan.rst +0 -133
  111. pygeai/_docs/source/pygeai.tests.snippets.evaluation.result.rst +0 -37
  112. pygeai/_docs/source/pygeai.tests.snippets.evaluation.rst +0 -20
  113. pygeai/_docs/source/pygeai.tests.snippets.extras.rst +0 -37
  114. pygeai/_docs/source/pygeai.tests.snippets.files.rst +0 -53
  115. pygeai/_docs/source/pygeai.tests.snippets.gam.rst +0 -21
  116. pygeai/_docs/source/pygeai.tests.snippets.lab.agents.rst +0 -93
  117. pygeai/_docs/source/pygeai.tests.snippets.lab.processes.jobs.rst +0 -21
  118. pygeai/_docs/source/pygeai.tests.snippets.lab.processes.kbs.rst +0 -45
  119. pygeai/_docs/source/pygeai.tests.snippets.lab.processes.rst +0 -46
  120. pygeai/_docs/source/pygeai.tests.snippets.lab.rst +0 -82
  121. pygeai/_docs/source/pygeai.tests.snippets.lab.samples.rst +0 -21
  122. pygeai/_docs/source/pygeai.tests.snippets.lab.strategies.rst +0 -45
  123. pygeai/_docs/source/pygeai.tests.snippets.lab.tools.rst +0 -85
  124. pygeai/_docs/source/pygeai.tests.snippets.lab.use_cases.rst +0 -117
  125. pygeai/_docs/source/pygeai.tests.snippets.migrate.rst +0 -10
  126. pygeai/_docs/source/pygeai.tests.snippets.organization.rst +0 -109
  127. pygeai/_docs/source/pygeai.tests.snippets.rag.rst +0 -85
  128. pygeai/_docs/source/pygeai.tests.snippets.rerank.rst +0 -21
  129. pygeai/_docs/source/pygeai.tests.snippets.rst +0 -32
  130. pygeai/_docs/source/pygeai.tests.snippets.secrets.rst +0 -10
  131. pygeai/_docs/source/pygeai.tests.snippets.usage_limit.rst +0 -77
  132. {pygeai-0.6.0b10.dist-info → pygeai-0.6.0b12.dist-info}/WHEEL +0 -0
  133. {pygeai-0.6.0b10.dist-info → pygeai-0.6.0b12.dist-info}/entry_points.txt +0 -0
  134. {pygeai-0.6.0b10.dist-info → pygeai-0.6.0b12.dist-info}/licenses/LICENSE +0 -0
  135. {pygeai-0.6.0b10.dist-info → pygeai-0.6.0b12.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,525 @@
1
+ from pygeai.cli.commands import Command, Option, ArgumentsEnum
2
+ from pygeai.cli.commands.builders import build_help_text
3
+ from pygeai.cli.texts.help import ANALYTICS_HELP_TEXT
4
+ from pygeai.core.common.exceptions import MissingRequirementException
5
+ from pygeai.core.utils.console import Console
6
+ from pygeai.analytics.managers import AnalyticsManager
7
+ import csv
8
+ from datetime import datetime, timedelta
9
+
10
+
11
+ def show_help():
12
+ help_text = build_help_text(analytics_commands, ANALYTICS_HELP_TEXT)
13
+ Console.write_stdout(help_text)
14
+
15
+
16
+ def get_default_date_range():
17
+ today = datetime.now()
18
+ first_day_current_month = today.replace(day=1)
19
+ last_day_last_month = first_day_current_month - timedelta(days=1)
20
+ first_day_last_month = last_day_last_month.replace(day=1)
21
+
22
+ start_date = first_day_last_month.strftime('%Y-%m-%d')
23
+ end_date = last_day_last_month.strftime('%Y-%m-%d')
24
+
25
+ return start_date, end_date
26
+
27
+
28
+ START_DATE_OPTION = Option(
29
+ "start_date",
30
+ ["--start-date", "-s"],
31
+ "Start date in YYYY-MM-DD format (defaults to first day of last month)",
32
+ True
33
+ )
34
+
35
+ END_DATE_OPTION = Option(
36
+ "end_date",
37
+ ["--end-date", "-e"],
38
+ "End date in YYYY-MM-DD format (defaults to last day of last month)",
39
+ True
40
+ )
41
+
42
+ AGENT_NAME_OPTION = Option(
43
+ "agent_name",
44
+ ["--agent-name", "-a"],
45
+ "Name of the agent to filter results",
46
+ True
47
+ )
48
+
49
+ CSV_EXPORT_OPTION = Option(
50
+ "csv_file",
51
+ ["--csv", "-c"],
52
+ "Export results to CSV file",
53
+ True
54
+ )
55
+
56
+
57
+ def get_agents_created_and_modified(option_list: list):
58
+ start_date = None
59
+ end_date = None
60
+ for option_flag, option_arg in option_list:
61
+ if option_flag.name == "start_date":
62
+ start_date = option_arg
63
+ if option_flag.name == "end_date":
64
+ end_date = option_arg
65
+
66
+ if not (start_date and end_date):
67
+ raise MissingRequirementException("Cannot retrieve agents created and modified without start-date and end-date")
68
+
69
+ manager = AnalyticsManager()
70
+ result = manager.get_agents_created_and_modified(start_date, end_date)
71
+ Console.write_stdout(f"Agents created and modified:\n Created: {result.createdAgents}\n Modified: {result.modifiedAgents}")
72
+
73
+
74
+ agents_created_options = [START_DATE_OPTION, END_DATE_OPTION]
75
+
76
+
77
+ def get_total_requests_per_day(option_list: list):
78
+ start_date = None
79
+ end_date = None
80
+ agent_name = None
81
+ for option_flag, option_arg in option_list:
82
+ if option_flag.name == "start_date":
83
+ start_date = option_arg
84
+ if option_flag.name == "end_date":
85
+ end_date = option_arg
86
+ if option_flag.name == "agent_name":
87
+ agent_name = option_arg
88
+
89
+ if not (start_date and end_date):
90
+ raise MissingRequirementException("Cannot retrieve total requests per day without start-date and end-date")
91
+
92
+ manager = AnalyticsManager()
93
+ result = manager.get_total_requests_per_day(start_date, end_date, agent_name)
94
+ Console.write_stdout(f"Total requests per day:")
95
+ for item in result.requestsPerDay:
96
+ Console.write_stdout(f" {item.date}: {item.totalRequests} requests ({item.totalRequestsWithError} errors)")
97
+
98
+
99
+ total_requests_per_day_options = [START_DATE_OPTION, END_DATE_OPTION, AGENT_NAME_OPTION]
100
+
101
+
102
+ def get_total_cost(option_list: list):
103
+ start_date = None
104
+ end_date = None
105
+ for option_flag, option_arg in option_list:
106
+ if option_flag.name == "start_date":
107
+ start_date = option_arg
108
+ if option_flag.name == "end_date":
109
+ end_date = option_arg
110
+
111
+ if not (start_date and end_date):
112
+ raise MissingRequirementException("Cannot retrieve total cost without start-date and end-date")
113
+
114
+ manager = AnalyticsManager()
115
+ result = manager.get_total_cost(start_date, end_date)
116
+ Console.write_stdout(f"Total cost: ${result.totalCost:.2f}")
117
+
118
+
119
+ total_cost_options = [START_DATE_OPTION, END_DATE_OPTION]
120
+
121
+
122
+ def get_average_cost_per_request(option_list: list):
123
+ start_date = None
124
+ end_date = None
125
+ for option_flag, option_arg in option_list:
126
+ if option_flag.name == "start_date":
127
+ start_date = option_arg
128
+ if option_flag.name == "end_date":
129
+ end_date = option_arg
130
+
131
+ if not (start_date and end_date):
132
+ raise MissingRequirementException("Cannot retrieve average cost per request without start-date and end-date")
133
+
134
+ manager = AnalyticsManager()
135
+ result = manager.get_average_cost_per_request(start_date, end_date)
136
+ Console.write_stdout(f"Average cost per request: ${result.averageCost:.4f}")
137
+
138
+
139
+ average_cost_per_request_options = [START_DATE_OPTION, END_DATE_OPTION]
140
+
141
+
142
+ def get_total_tokens(option_list: list):
143
+ start_date = None
144
+ end_date = None
145
+ for option_flag, option_arg in option_list:
146
+ if option_flag.name == "start_date":
147
+ start_date = option_arg
148
+ if option_flag.name == "end_date":
149
+ end_date = option_arg
150
+
151
+ if not (start_date and end_date):
152
+ raise MissingRequirementException("Cannot retrieve total tokens without start-date and end-date")
153
+
154
+ manager = AnalyticsManager()
155
+ result = manager.get_total_tokens(start_date, end_date)
156
+ Console.write_stdout(f"Total tokens:\n Input: {result.totalInputTokens}\n Output: {result.totalOutputTokens}\n Total: {result.totalTokens}")
157
+
158
+
159
+ total_tokens_options = [START_DATE_OPTION, END_DATE_OPTION]
160
+
161
+
162
+ def get_overall_error_rate(option_list: list):
163
+ start_date = None
164
+ end_date = None
165
+ for option_flag, option_arg in option_list:
166
+ if option_flag.name == "start_date":
167
+ start_date = option_arg
168
+ if option_flag.name == "end_date":
169
+ end_date = option_arg
170
+
171
+ if not (start_date and end_date):
172
+ raise MissingRequirementException("Cannot retrieve overall error rate without start-date and end-date")
173
+
174
+ manager = AnalyticsManager()
175
+ result = manager.get_overall_error_rate(start_date, end_date)
176
+ Console.write_stdout(f"Overall error rate: {result.errorRate:.2%}")
177
+
178
+
179
+ error_rate_options = [START_DATE_OPTION, END_DATE_OPTION]
180
+
181
+
182
+ def get_top_agents_by_requests(option_list: list):
183
+ start_date = None
184
+ end_date = None
185
+ for option_flag, option_arg in option_list:
186
+ if option_flag.name == "start_date":
187
+ start_date = option_arg
188
+ if option_flag.name == "end_date":
189
+ end_date = option_arg
190
+
191
+ if not (start_date and end_date):
192
+ raise MissingRequirementException("Cannot retrieve top agents by requests without start-date and end-date")
193
+
194
+ manager = AnalyticsManager()
195
+ result = manager.get_top_10_agents_by_requests(start_date, end_date)
196
+ Console.write_stdout("Top 10 agents by requests:")
197
+ for idx, agent in enumerate(result.topAgents, 1):
198
+ Console.write_stdout(f" {idx}. {agent.agentName}: {agent.totalRequests} requests")
199
+
200
+
201
+ top_agents_options = [START_DATE_OPTION, END_DATE_OPTION]
202
+
203
+
204
+ def get_total_active_users(option_list: list):
205
+ start_date = None
206
+ end_date = None
207
+ for option_flag, option_arg in option_list:
208
+ if option_flag.name == "start_date":
209
+ start_date = option_arg
210
+ if option_flag.name == "end_date":
211
+ end_date = option_arg
212
+
213
+ if not (start_date and end_date):
214
+ raise MissingRequirementException("Cannot retrieve total active users without start-date and end-date")
215
+
216
+ manager = AnalyticsManager()
217
+ result = manager.get_total_active_users(start_date, end_date)
218
+ Console.write_stdout(f"Total active users: {result.totalActiveUsers}")
219
+
220
+
221
+ active_users_options = [START_DATE_OPTION, END_DATE_OPTION]
222
+
223
+
224
+ def get_full_report(option_list: list):
225
+ start_date = None
226
+ end_date = None
227
+ csv_file = None
228
+ for option_flag, option_arg in option_list:
229
+ if option_flag.name == "start_date":
230
+ start_date = option_arg
231
+ if option_flag.name == "end_date":
232
+ end_date = option_arg
233
+ if option_flag.name == "csv_file":
234
+ csv_file = option_arg
235
+
236
+ if not start_date or not end_date:
237
+ start_date, end_date = get_default_date_range()
238
+ Console.write_stdout(f"Using default date range: {start_date} to {end_date}")
239
+
240
+ manager = AnalyticsManager()
241
+
242
+ Console.write_stdout(f"\n{'='*80}")
243
+ Console.write_stdout(f"ANALYTICS FULL REPORT - Period: {start_date} to {end_date}")
244
+ Console.write_stdout(f"{'='*80}\n")
245
+
246
+ report_data = {}
247
+
248
+ try:
249
+ Console.write_stdout("LAB METRICS")
250
+ Console.write_stdout("-" * 80)
251
+ agents_created = manager.get_agents_created_and_modified(start_date, end_date)
252
+ Console.write_stdout(f"Agents Created: {agents_created.createdAgents}")
253
+ Console.write_stdout(f"Agents Modified: {agents_created.modifiedAgents}")
254
+ report_data["Agents Created"] = agents_created.createdAgents
255
+ report_data["Agents Modified"] = agents_created.modifiedAgents
256
+ except Exception as e:
257
+ Console.write_stdout(f"Error retrieving agents data: {e}")
258
+
259
+ try:
260
+ flows_created = manager.get_flows_created_and_modified(start_date, end_date)
261
+ Console.write_stdout(f"Flows Created: {flows_created.createdFlows}")
262
+ Console.write_stdout(f"Flows Modified: {flows_created.modifiedFlows}")
263
+ report_data["Flows Created"] = flows_created.createdFlows
264
+ report_data["Flows Modified"] = flows_created.modifiedFlows
265
+ except Exception as e:
266
+ Console.write_stdout(f"Error retrieving flows data: {e}")
267
+
268
+ try:
269
+ processes_created = manager.get_processes_created_and_modified(start_date, end_date)
270
+ Console.write_stdout(f"Processes Created: {processes_created.createdProcesses}")
271
+ Console.write_stdout(f"Processes Modified: {processes_created.modifiedProcesses}")
272
+ report_data["Processes Created"] = processes_created.createdProcesses
273
+ report_data["Processes Modified"] = processes_created.modifiedProcesses
274
+ except Exception as e:
275
+ Console.write_stdout(f"Error retrieving processes data: {e}")
276
+
277
+ Console.write_stdout("\nREQUEST METRICS")
278
+ Console.write_stdout("-" * 80)
279
+
280
+ try:
281
+ total_requests = manager.get_total_requests(start_date, end_date)
282
+ Console.write_stdout(f"Total Requests: {total_requests.totalRequests}")
283
+ report_data["Total Requests"] = total_requests.totalRequests
284
+ except Exception as e:
285
+ Console.write_stdout(f"Error retrieving total requests: {e}")
286
+
287
+ try:
288
+ total_errors = manager.get_total_requests_with_error(start_date, end_date)
289
+ Console.write_stdout(f"Total Requests with Error: {total_errors.totalRequestsWithError}")
290
+ report_data["Total Requests with Error"] = total_errors.totalRequestsWithError
291
+ except Exception as e:
292
+ Console.write_stdout(f"Error retrieving error requests: {e}")
293
+
294
+ try:
295
+ error_rate = manager.get_overall_error_rate(start_date, end_date)
296
+ Console.write_stdout(f"Overall Error Rate: {error_rate.errorRate:.2%}")
297
+ report_data["Overall Error Rate (%)"] = f"{error_rate.errorRate:.2%}"
298
+ except Exception as e:
299
+ Console.write_stdout(f"Error retrieving error rate: {e}")
300
+
301
+ try:
302
+ avg_request_time = manager.get_average_request_time(start_date, end_date)
303
+ Console.write_stdout(f"Average Request Time: {avg_request_time.averageTime:.2f} ms")
304
+ report_data["Average Request Time (ms)"] = f"{avg_request_time.averageTime:.2f}"
305
+ except Exception as e:
306
+ Console.write_stdout(f"Error retrieving average request time: {e}")
307
+
308
+ Console.write_stdout("\nCOST METRICS")
309
+ Console.write_stdout("-" * 80)
310
+
311
+ try:
312
+ total_cost = manager.get_total_cost(start_date, end_date)
313
+ Console.write_stdout(f"Total Cost: ${total_cost.totalCost:.2f}")
314
+ report_data["Total Cost (USD)"] = f"{total_cost.totalCost:.2f}"
315
+ except Exception as e:
316
+ Console.write_stdout(f"Error retrieving total cost: {e}")
317
+
318
+ try:
319
+ avg_cost = manager.get_average_cost_per_request(start_date, end_date)
320
+ Console.write_stdout(f"Average Cost per Request: ${avg_cost.averageCost:.4f}")
321
+ report_data["Average Cost per Request (USD)"] = f"{avg_cost.averageCost:.4f}"
322
+ except Exception as e:
323
+ Console.write_stdout(f"Error retrieving average cost: {e}")
324
+
325
+ Console.write_stdout("\nTOKEN METRICS")
326
+ Console.write_stdout("-" * 80)
327
+
328
+ try:
329
+ total_tokens = manager.get_total_tokens(start_date, end_date)
330
+ Console.write_stdout(f"Total Input Tokens: {total_tokens.totalInputTokens}")
331
+ Console.write_stdout(f"Total Output Tokens: {total_tokens.totalOutputTokens}")
332
+ Console.write_stdout(f"Total Tokens: {total_tokens.totalTokens}")
333
+ report_data["Total Input Tokens"] = total_tokens.totalInputTokens
334
+ report_data["Total Output Tokens"] = total_tokens.totalOutputTokens
335
+ report_data["Total Tokens"] = total_tokens.totalTokens
336
+ except Exception as e:
337
+ Console.write_stdout(f"Error retrieving token data: {e}")
338
+
339
+ try:
340
+ avg_tokens = manager.get_average_tokens_per_request(start_date, end_date)
341
+ Console.write_stdout(f"Average Input Tokens per Request: {avg_tokens.averageInputTokens:.2f}")
342
+ Console.write_stdout(f"Average Output Tokens per Request: {avg_tokens.averageOutputTokens:.2f}")
343
+ Console.write_stdout(f"Average Total Tokens per Request: {avg_tokens.averageTotalTokens:.2f}")
344
+ report_data["Average Input Tokens per Request"] = f"{avg_tokens.averageInputTokens:.2f}"
345
+ report_data["Average Output Tokens per Request"] = f"{avg_tokens.averageOutputTokens:.2f}"
346
+ report_data["Average Total Tokens per Request"] = f"{avg_tokens.averageTotalTokens:.2f}"
347
+ except Exception as e:
348
+ Console.write_stdout(f"Error retrieving average tokens: {e}")
349
+
350
+ Console.write_stdout("\nUSER & AGENT METRICS")
351
+ Console.write_stdout("-" * 80)
352
+
353
+ try:
354
+ active_users = manager.get_total_active_users(start_date, end_date)
355
+ Console.write_stdout(f"Total Active Users: {active_users.totalActiveUsers}")
356
+ report_data["Total Active Users"] = active_users.totalActiveUsers
357
+ except Exception as e:
358
+ Console.write_stdout(f"Error retrieving active users: {e}")
359
+
360
+ try:
361
+ active_agents = manager.get_total_active_agents(start_date, end_date)
362
+ Console.write_stdout(f"Total Active Agents: {active_agents.totalActiveAgents}")
363
+ report_data["Total Active Agents"] = active_agents.totalActiveAgents
364
+ except Exception as e:
365
+ Console.write_stdout(f"Error retrieving active agents: {e}")
366
+
367
+ try:
368
+ active_projects = manager.get_total_active_projects(start_date, end_date)
369
+ Console.write_stdout(f"Total Active Projects: {active_projects.totalActiveProjects}")
370
+ report_data["Total Active Projects"] = active_projects.totalActiveProjects
371
+ except Exception as e:
372
+ Console.write_stdout(f"Error retrieving active projects: {e}")
373
+
374
+ Console.write_stdout("\nTOP 10 AGENTS BY REQUESTS")
375
+ Console.write_stdout("-" * 80)
376
+
377
+ try:
378
+ top_agents_requests = manager.get_top_10_agents_by_requests(start_date, end_date)
379
+ for idx, agent in enumerate(top_agents_requests.topAgents, 1):
380
+ Console.write_stdout(f"{idx}. {agent.agentName}: {agent.totalRequests} requests")
381
+ except Exception as e:
382
+ Console.write_stdout(f"Error retrieving top agents by requests: {e}")
383
+
384
+ Console.write_stdout("\nTOP 10 AGENTS BY TOKENS")
385
+ Console.write_stdout("-" * 80)
386
+
387
+ try:
388
+ top_agents_tokens = manager.get_top_10_agents_by_tokens(start_date, end_date)
389
+ for idx, agent in enumerate(top_agents_tokens.topAgents, 1):
390
+ Console.write_stdout(f"{idx}. {agent.agentName}: {agent.totalTokens} tokens")
391
+ except Exception as e:
392
+ Console.write_stdout(f"Error retrieving top agents by tokens: {e}")
393
+
394
+ Console.write_stdout("\nTOP 10 USERS BY REQUESTS")
395
+ Console.write_stdout("-" * 80)
396
+
397
+ try:
398
+ top_users_requests = manager.get_top_10_users_by_requests(start_date, end_date)
399
+ for idx, user in enumerate(top_users_requests.topUsers, 1):
400
+ Console.write_stdout(f"{idx}. {user.userEmail}: {user.totalRequests} requests")
401
+ except Exception as e:
402
+ Console.write_stdout(f"Error retrieving top users by requests: {e}")
403
+
404
+ Console.write_stdout("\nTOP 10 USERS BY COST")
405
+ Console.write_stdout("-" * 80)
406
+
407
+ try:
408
+ top_users_cost = manager.get_top_10_users_by_cost(start_date, end_date)
409
+ for idx, user in enumerate(top_users_cost.topUsers, 1):
410
+ Console.write_stdout(f"{idx}. {user.userEmail}: ${user.totalCost:.2f}")
411
+ except Exception as e:
412
+ Console.write_stdout(f"Error retrieving top users by cost: {e}")
413
+
414
+ Console.write_stdout(f"\n{'='*80}\n")
415
+
416
+ if csv_file:
417
+ try:
418
+ with open(csv_file, 'w', newline='') as f:
419
+ writer = csv.writer(f)
420
+ writer.writerow(['Metric', 'Value'])
421
+ writer.writerow(['Report Period', f"{start_date} to {end_date}"])
422
+ writer.writerow(['Generated At', datetime.now().strftime('%Y-%m-%d %H:%M:%S')])
423
+ writer.writerow([])
424
+ for key, value in report_data.items():
425
+ writer.writerow([key, value])
426
+ Console.write_stdout(f"Report exported to: {csv_file}")
427
+ except Exception as e:
428
+ Console.write_stdout(f"Error exporting to CSV: {e}")
429
+
430
+
431
+ full_report_options = [START_DATE_OPTION, END_DATE_OPTION, CSV_EXPORT_OPTION]
432
+
433
+
434
+ analytics_commands = [
435
+ Command(
436
+ "help",
437
+ ["help", "h"],
438
+ "Display analytics help text",
439
+ show_help,
440
+ ArgumentsEnum.NOT_AVAILABLE,
441
+ [],
442
+ []
443
+ ),
444
+ Command(
445
+ "agents_created",
446
+ ["agents-created", "ac"],
447
+ "Get total agents created and modified",
448
+ get_agents_created_and_modified,
449
+ ArgumentsEnum.OPTIONAL,
450
+ [],
451
+ agents_created_options
452
+ ),
453
+ Command(
454
+ "requests_per_day",
455
+ ["requests-per-day", "rpd"],
456
+ "Get total requests per day",
457
+ get_total_requests_per_day,
458
+ ArgumentsEnum.OPTIONAL,
459
+ [],
460
+ total_requests_per_day_options
461
+ ),
462
+ Command(
463
+ "total_cost",
464
+ ["total-cost", "tc"],
465
+ "Get total cost for the period",
466
+ get_total_cost,
467
+ ArgumentsEnum.OPTIONAL,
468
+ [],
469
+ total_cost_options
470
+ ),
471
+ Command(
472
+ "average_cost",
473
+ ["average-cost", "ac"],
474
+ "Get average cost per request",
475
+ get_average_cost_per_request,
476
+ ArgumentsEnum.OPTIONAL,
477
+ [],
478
+ average_cost_per_request_options
479
+ ),
480
+ Command(
481
+ "total_tokens",
482
+ ["total-tokens", "tt"],
483
+ "Get total tokens consumed",
484
+ get_total_tokens,
485
+ ArgumentsEnum.OPTIONAL,
486
+ [],
487
+ total_tokens_options
488
+ ),
489
+ Command(
490
+ "error_rate",
491
+ ["error-rate", "er"],
492
+ "Get overall error rate",
493
+ get_overall_error_rate,
494
+ ArgumentsEnum.OPTIONAL,
495
+ [],
496
+ error_rate_options
497
+ ),
498
+ Command(
499
+ "top_agents",
500
+ ["top-agents", "ta"],
501
+ "Get top 10 agents by requests",
502
+ get_top_agents_by_requests,
503
+ ArgumentsEnum.OPTIONAL,
504
+ [],
505
+ top_agents_options
506
+ ),
507
+ Command(
508
+ "active_users",
509
+ ["active-users", "au"],
510
+ "Get total active users",
511
+ get_total_active_users,
512
+ ArgumentsEnum.OPTIONAL,
513
+ [],
514
+ active_users_options
515
+ ),
516
+ Command(
517
+ "full_report",
518
+ ["full-report", "fr"],
519
+ "Get comprehensive analytics report",
520
+ get_full_report,
521
+ ArgumentsEnum.OPTIONAL,
522
+ [],
523
+ full_report_options
524
+ ),
525
+ ]
@@ -1,5 +1,6 @@
1
1
  from pygeai.cli.commands import ArgumentsEnum, Command, Option
2
2
  from pygeai.cli.commands.admin import admin_commands
3
+ from pygeai.cli.commands.analytics import analytics_commands
3
4
  from pygeai.cli.commands.assistant import assistant_commands
4
5
  from pygeai.cli.commands.auth import auth_commands
5
6
  from pygeai.cli.commands.builders import build_help_text
@@ -121,6 +122,15 @@ base_commands = [
121
122
  organization_commands,
122
123
  [],
123
124
  ),
125
+ Command(
126
+ "analytics",
127
+ ["analytics", "anl"],
128
+ "Invoke analytics endpoints to retrieve metrics and insights",
129
+ None,
130
+ ArgumentsEnum.REQUIRED,
131
+ analytics_commands,
132
+ [],
133
+ ),
124
134
  Command(
125
135
  "assistant",
126
136
  ["assistant", "ast"],
@@ -295,4 +305,10 @@ base_options = (
295
305
  "Set output file to save the command result",
296
306
  True
297
307
  ),
308
+ Option(
309
+ "verbose",
310
+ ["--verbose", "-v"],
311
+ "Enable verbose mode with detailed logging output",
312
+ False
313
+ ),
298
314
  )
@@ -661,6 +661,92 @@ generate_image_options = [
661
661
  ]
662
662
 
663
663
 
664
+ def get_edit_image(option_list: list):
665
+ model = None
666
+ prompt = None
667
+ image = None
668
+ size = None
669
+ n = 1
670
+ quality = None
671
+
672
+ for option_flag, option_arg in option_list:
673
+ if option_flag.name == "model":
674
+ model = option_arg
675
+ if option_flag.name == "prompt":
676
+ prompt = option_arg
677
+ if option_flag.name == "image":
678
+ image = option_arg
679
+ if option_flag.name == "size":
680
+ size = option_arg
681
+ if option_flag.name == "n":
682
+ try:
683
+ n = int(option_arg)
684
+ if n < 1 or n > 10:
685
+ raise WrongArgumentError("n must be an integer between 1 and 10.")
686
+ except ValueError:
687
+ raise WrongArgumentError("n must be a valid integer.")
688
+ if option_flag.name == "quality":
689
+ quality = option_arg
690
+
691
+ if not (model and prompt and image and size):
692
+ raise MissingRequirementException("Cannot edit image without specifying model, prompt, image, and size.")
693
+
694
+ client = ChatClient()
695
+ try:
696
+ result = client.edit_image(
697
+ model=model,
698
+ prompt=prompt,
699
+ image=image,
700
+ size=size,
701
+ n=n,
702
+ quality=quality
703
+ )
704
+ Console.write_stdout(f"Image editing result: \n{result}\n")
705
+ except Exception as e:
706
+ logger.error(f"Error editing image: {e}")
707
+ Console.write_stderr(f"Failed to edit image: {e}")
708
+
709
+
710
+ edit_image_options = [
711
+ Option(
712
+ "model",
713
+ ["--model", "-m"],
714
+ "The model specification for image editing, e.g., 'openai/gpt-image-1'.",
715
+ True
716
+ ),
717
+ Option(
718
+ "prompt",
719
+ ["--prompt", "-p"],
720
+ "Description of the desired edit, e.g., 'remove the ball'.",
721
+ True
722
+ ),
723
+ Option(
724
+ "image",
725
+ ["--image", "-img"],
726
+ "URL of the image to be edited, e.g., 'https://example.com/image.jpg'.",
727
+ True
728
+ ),
729
+ Option(
730
+ "size",
731
+ ["--size", "-s"],
732
+ "Desired dimensions of the output image in pixels, e.g., '1024x1024'.",
733
+ True
734
+ ),
735
+ Option(
736
+ "n",
737
+ ["--n"],
738
+ "Number of edited images to generate (1-10, depending on the model). Default is 1.",
739
+ True
740
+ ),
741
+ Option(
742
+ "quality",
743
+ ["--quality", "-q"],
744
+ "Rendering quality, e.g., 'high', 'medium', 'low'.",
745
+ True
746
+ ),
747
+ ]
748
+
749
+
664
750
  def get_response(option_list: list):
665
751
  model = None
666
752
  input_text = None
@@ -912,6 +998,15 @@ chat_commands = [
912
998
  [],
913
999
  generate_image_options
914
1000
  ),
1001
+ Command(
1002
+ "edit_image",
1003
+ ["edit-image", "edit-img"],
1004
+ "Edit an existing image using the specified model and parameters",
1005
+ get_edit_image,
1006
+ ArgumentsEnum.REQUIRED,
1007
+ [],
1008
+ edit_image_options
1009
+ ),
915
1010
  Command(
916
1011
  "response",
917
1012
  ["response", "resp"],