pygeai 0.6.0b6__py3-none-any.whl → 0.6.0b10__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 (227) hide show
  1. pygeai/_docs/source/conf.py +78 -6
  2. pygeai/_docs/source/content/api_reference/admin.rst +161 -0
  3. pygeai/_docs/source/content/api_reference/assistant.rst +326 -0
  4. pygeai/_docs/source/content/api_reference/auth.rst +379 -0
  5. pygeai/_docs/source/content/api_reference/embeddings.rst +31 -1
  6. pygeai/_docs/source/content/api_reference/evaluation.rst +590 -0
  7. pygeai/_docs/source/content/api_reference/feedback.rst +237 -0
  8. pygeai/_docs/source/content/api_reference/files.rst +592 -0
  9. pygeai/_docs/source/content/api_reference/gam.rst +401 -0
  10. pygeai/_docs/source/content/api_reference/health.rst +58 -0
  11. pygeai/_docs/source/content/api_reference/project.rst +20 -18
  12. pygeai/_docs/source/content/api_reference/proxy.rst +318 -0
  13. pygeai/_docs/source/content/api_reference/rerank.rst +94 -0
  14. pygeai/_docs/source/content/api_reference/secrets.rst +495 -0
  15. pygeai/_docs/source/content/api_reference/usage_limits.rst +390 -0
  16. pygeai/_docs/source/content/api_reference.rst +13 -1
  17. pygeai/_docs/source/content/debugger.rst +376 -83
  18. pygeai/_docs/source/content/migration.rst +528 -0
  19. pygeai/_docs/source/content/modules.rst +1 -1
  20. pygeai/_docs/source/index.rst +59 -7
  21. pygeai/_docs/source/pygeai.auth.rst +29 -0
  22. pygeai/_docs/source/pygeai.cli.commands.rst +16 -0
  23. pygeai/_docs/source/pygeai.cli.rst +8 -0
  24. pygeai/_docs/source/pygeai.core.utils.rst +16 -0
  25. pygeai/_docs/source/pygeai.rst +1 -0
  26. pygeai/_docs/source/pygeai.tests.auth.rst +21 -0
  27. pygeai/_docs/source/pygeai.tests.cli.commands.rst +16 -0
  28. pygeai/_docs/source/pygeai.tests.cli.rst +16 -0
  29. pygeai/_docs/source/pygeai.tests.core.base.rst +8 -0
  30. pygeai/_docs/source/pygeai.tests.core.embeddings.rst +16 -0
  31. pygeai/_docs/source/pygeai.tests.core.files.rst +8 -0
  32. pygeai/_docs/source/pygeai.tests.core.plugins.rst +21 -0
  33. pygeai/_docs/source/pygeai.tests.core.rst +1 -0
  34. pygeai/_docs/source/pygeai.tests.evaluation.dataset.rst +21 -0
  35. pygeai/_docs/source/pygeai.tests.evaluation.plan.rst +21 -0
  36. pygeai/_docs/source/pygeai.tests.evaluation.result.rst +21 -0
  37. pygeai/_docs/source/pygeai.tests.evaluation.rst +20 -0
  38. pygeai/_docs/source/pygeai.tests.integration.lab.processes.rst +8 -0
  39. pygeai/_docs/source/pygeai.tests.organization.rst +8 -0
  40. pygeai/_docs/source/pygeai.tests.rst +2 -0
  41. pygeai/_docs/source/pygeai.tests.snippets.auth.rst +10 -0
  42. pygeai/_docs/source/pygeai.tests.snippets.chat.rst +40 -0
  43. pygeai/_docs/source/pygeai.tests.snippets.dbg.rst +45 -0
  44. pygeai/_docs/source/pygeai.tests.snippets.embeddings.rst +40 -0
  45. pygeai/_docs/source/pygeai.tests.snippets.evaluation.dataset.rst +197 -0
  46. pygeai/_docs/source/pygeai.tests.snippets.evaluation.plan.rst +133 -0
  47. pygeai/_docs/source/pygeai.tests.snippets.evaluation.result.rst +37 -0
  48. pygeai/_docs/source/pygeai.tests.snippets.evaluation.rst +10 -0
  49. pygeai/_docs/source/pygeai.tests.snippets.organization.rst +40 -0
  50. pygeai/_docs/source/pygeai.tests.snippets.rst +2 -0
  51. pygeai/admin/clients.py +12 -32
  52. pygeai/assistant/clients.py +16 -44
  53. pygeai/assistant/data/clients.py +1 -0
  54. pygeai/assistant/data_analyst/clients.py +6 -13
  55. pygeai/assistant/rag/clients.py +24 -67
  56. pygeai/auth/clients.py +88 -14
  57. pygeai/auth/endpoints.py +4 -0
  58. pygeai/chat/clients.py +192 -25
  59. pygeai/chat/endpoints.py +2 -1
  60. pygeai/cli/commands/auth.py +178 -2
  61. pygeai/cli/commands/chat.py +227 -1
  62. pygeai/cli/commands/embeddings.py +56 -8
  63. pygeai/cli/commands/lab/ai_lab.py +0 -2
  64. pygeai/cli/commands/migrate.py +994 -434
  65. pygeai/cli/commands/organization.py +241 -0
  66. pygeai/cli/error_handler.py +116 -0
  67. pygeai/cli/geai.py +28 -10
  68. pygeai/cli/parsers.py +8 -2
  69. pygeai/core/base/clients.py +4 -1
  70. pygeai/core/common/exceptions.py +11 -10
  71. pygeai/core/embeddings/__init__.py +19 -0
  72. pygeai/core/embeddings/clients.py +20 -9
  73. pygeai/core/embeddings/mappers.py +16 -2
  74. pygeai/core/embeddings/responses.py +9 -2
  75. pygeai/core/feedback/clients.py +4 -8
  76. pygeai/core/files/clients.py +10 -25
  77. pygeai/core/files/managers.py +42 -0
  78. pygeai/core/llm/clients.py +11 -26
  79. pygeai/core/models.py +107 -0
  80. pygeai/core/plugins/clients.py +4 -7
  81. pygeai/core/rerank/clients.py +4 -8
  82. pygeai/core/secrets/clients.py +14 -37
  83. pygeai/core/services/rest.py +1 -1
  84. pygeai/core/utils/parsers.py +32 -0
  85. pygeai/core/utils/validators.py +10 -0
  86. pygeai/dbg/__init__.py +3 -0
  87. pygeai/dbg/debugger.py +565 -70
  88. pygeai/evaluation/clients.py +2 -1
  89. pygeai/evaluation/dataset/clients.py +46 -44
  90. pygeai/evaluation/plan/clients.py +28 -26
  91. pygeai/evaluation/result/clients.py +38 -5
  92. pygeai/gam/clients.py +10 -25
  93. pygeai/health/clients.py +4 -7
  94. pygeai/lab/agents/clients.py +21 -54
  95. pygeai/lab/agents/endpoints.py +2 -0
  96. pygeai/lab/clients.py +1 -0
  97. pygeai/lab/models.py +3 -3
  98. pygeai/lab/processes/clients.py +45 -127
  99. pygeai/lab/strategies/clients.py +11 -25
  100. pygeai/lab/tools/clients.py +23 -67
  101. pygeai/lab/tools/endpoints.py +3 -0
  102. pygeai/migration/__init__.py +31 -0
  103. pygeai/migration/strategies.py +404 -155
  104. pygeai/migration/tools.py +170 -3
  105. pygeai/organization/clients.py +135 -51
  106. pygeai/organization/endpoints.py +6 -1
  107. pygeai/organization/limits/clients.py +32 -91
  108. pygeai/organization/managers.py +157 -1
  109. pygeai/organization/mappers.py +76 -2
  110. pygeai/organization/responses.py +25 -1
  111. pygeai/proxy/clients.py +4 -1
  112. pygeai/tests/admin/test_clients.py +16 -11
  113. pygeai/tests/assistants/rag/test_clients.py +35 -23
  114. pygeai/tests/assistants/test_clients.py +22 -15
  115. pygeai/tests/auth/test_clients.py +191 -7
  116. pygeai/tests/chat/test_clients.py +211 -1
  117. pygeai/tests/cli/commands/test_embeddings.py +32 -9
  118. pygeai/tests/cli/commands/test_evaluation.py +7 -0
  119. pygeai/tests/cli/commands/test_migrate.py +112 -243
  120. pygeai/tests/cli/test_error_handler.py +225 -0
  121. pygeai/tests/cli/test_geai_driver.py +154 -0
  122. pygeai/tests/cli/test_parsers.py +5 -5
  123. pygeai/tests/core/embeddings/test_clients.py +144 -0
  124. pygeai/tests/core/embeddings/test_managers.py +171 -0
  125. pygeai/tests/core/embeddings/test_mappers.py +142 -0
  126. pygeai/tests/core/feedback/test_clients.py +2 -0
  127. pygeai/tests/core/files/test_clients.py +1 -0
  128. pygeai/tests/core/llm/test_clients.py +14 -9
  129. pygeai/tests/core/plugins/test_clients.py +5 -3
  130. pygeai/tests/core/rerank/test_clients.py +1 -0
  131. pygeai/tests/core/secrets/test_clients.py +19 -13
  132. pygeai/tests/dbg/test_debugger.py +453 -75
  133. pygeai/tests/evaluation/dataset/test_clients.py +3 -1
  134. pygeai/tests/evaluation/plan/test_clients.py +4 -2
  135. pygeai/tests/evaluation/result/test_clients.py +7 -5
  136. pygeai/tests/gam/test_clients.py +1 -1
  137. pygeai/tests/health/test_clients.py +1 -0
  138. pygeai/tests/lab/agents/test_clients.py +9 -0
  139. pygeai/tests/lab/processes/test_clients.py +36 -0
  140. pygeai/tests/lab/processes/test_mappers.py +3 -0
  141. pygeai/tests/lab/strategies/test_clients.py +14 -9
  142. pygeai/tests/migration/test_strategies.py +45 -218
  143. pygeai/tests/migration/test_tools.py +133 -9
  144. pygeai/tests/organization/limits/test_clients.py +17 -0
  145. pygeai/tests/organization/test_clients.py +206 -1
  146. pygeai/tests/organization/test_managers.py +122 -1
  147. pygeai/tests/proxy/test_clients.py +2 -0
  148. pygeai/tests/proxy/test_integration.py +1 -0
  149. pygeai/tests/snippets/auth/__init__.py +0 -0
  150. pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -0
  151. pygeai/tests/snippets/chat/get_response.py +15 -0
  152. pygeai/tests/snippets/chat/get_response_streaming.py +20 -0
  153. pygeai/tests/snippets/chat/get_response_with_files.py +16 -0
  154. pygeai/tests/snippets/chat/get_response_with_tools.py +36 -0
  155. pygeai/tests/snippets/dbg/__init__.py +0 -0
  156. pygeai/tests/snippets/dbg/basic_debugging.py +32 -0
  157. pygeai/tests/snippets/dbg/breakpoint_management.py +48 -0
  158. pygeai/tests/snippets/dbg/stack_navigation.py +45 -0
  159. pygeai/tests/snippets/dbg/stepping_example.py +40 -0
  160. pygeai/tests/snippets/embeddings/cache_example.py +31 -0
  161. pygeai/tests/snippets/embeddings/cohere_example.py +41 -0
  162. pygeai/tests/snippets/embeddings/openai_base64_example.py +27 -0
  163. pygeai/tests/snippets/embeddings/openai_example.py +30 -0
  164. pygeai/tests/snippets/embeddings/similarity_example.py +42 -0
  165. pygeai/tests/snippets/evaluation/dataset/__init__.py +0 -0
  166. pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +195 -0
  167. pygeai/tests/snippets/evaluation/dataset/create_dataset.py +26 -0
  168. pygeai/tests/snippets/evaluation/dataset/create_dataset_from_file.py +11 -0
  169. pygeai/tests/snippets/evaluation/dataset/create_dataset_row.py +17 -0
  170. pygeai/tests/snippets/evaluation/dataset/create_expected_source.py +18 -0
  171. pygeai/tests/snippets/evaluation/dataset/create_filter_variable.py +19 -0
  172. pygeai/tests/snippets/evaluation/dataset/delete_dataset.py +9 -0
  173. pygeai/tests/snippets/evaluation/dataset/delete_dataset_row.py +10 -0
  174. pygeai/tests/snippets/evaluation/dataset/delete_expected_source.py +15 -0
  175. pygeai/tests/snippets/evaluation/dataset/delete_filter_variable.py +15 -0
  176. pygeai/tests/snippets/evaluation/dataset/get_dataset.py +9 -0
  177. pygeai/tests/snippets/evaluation/dataset/get_dataset_row.py +10 -0
  178. pygeai/tests/snippets/evaluation/dataset/get_expected_source.py +15 -0
  179. pygeai/tests/snippets/evaluation/dataset/get_filter_variable.py +15 -0
  180. pygeai/tests/snippets/evaluation/dataset/list_dataset_rows.py +9 -0
  181. pygeai/tests/snippets/evaluation/dataset/list_datasets.py +6 -0
  182. pygeai/tests/snippets/evaluation/dataset/list_expected_sources.py +10 -0
  183. pygeai/tests/snippets/evaluation/dataset/list_filter_variables.py +10 -0
  184. pygeai/tests/snippets/evaluation/dataset/update_dataset.py +15 -0
  185. pygeai/tests/snippets/evaluation/dataset/update_dataset_row.py +20 -0
  186. pygeai/tests/snippets/evaluation/dataset/update_expected_source.py +18 -0
  187. pygeai/tests/snippets/evaluation/dataset/update_filter_variable.py +19 -0
  188. pygeai/tests/snippets/evaluation/dataset/upload_dataset_rows_file.py +10 -0
  189. pygeai/tests/snippets/evaluation/plan/__init__.py +0 -0
  190. pygeai/tests/snippets/evaluation/plan/add_plan_system_metric.py +13 -0
  191. pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +136 -0
  192. pygeai/tests/snippets/evaluation/plan/create_evaluation_plan.py +24 -0
  193. pygeai/tests/snippets/evaluation/plan/create_rag_evaluation_plan.py +22 -0
  194. pygeai/tests/snippets/evaluation/plan/delete_evaluation_plan.py +9 -0
  195. pygeai/tests/snippets/evaluation/plan/delete_plan_system_metric.py +13 -0
  196. pygeai/tests/snippets/evaluation/plan/execute_evaluation_plan.py +11 -0
  197. pygeai/tests/snippets/evaluation/plan/get_evaluation_plan.py +9 -0
  198. pygeai/tests/snippets/evaluation/plan/get_plan_system_metric.py +13 -0
  199. pygeai/tests/snippets/evaluation/plan/get_system_metric.py +9 -0
  200. pygeai/tests/snippets/evaluation/plan/list_evaluation_plans.py +7 -0
  201. pygeai/tests/snippets/evaluation/plan/list_plan_system_metrics.py +9 -0
  202. pygeai/tests/snippets/evaluation/plan/list_system_metrics.py +7 -0
  203. pygeai/tests/snippets/evaluation/plan/update_evaluation_plan.py +22 -0
  204. pygeai/tests/snippets/evaluation/plan/update_plan_system_metric.py +14 -0
  205. pygeai/tests/snippets/evaluation/result/__init__.py +0 -0
  206. pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +150 -0
  207. pygeai/tests/snippets/evaluation/result/get_evaluation_result.py +26 -0
  208. pygeai/tests/snippets/evaluation/result/list_evaluation_results.py +17 -0
  209. pygeai/tests/snippets/migrate/__init__.py +45 -0
  210. pygeai/tests/snippets/migrate/agent_migration.py +110 -0
  211. pygeai/tests/snippets/migrate/assistant_migration.py +64 -0
  212. pygeai/tests/snippets/migrate/orchestrator_examples.py +179 -0
  213. pygeai/tests/snippets/migrate/process_migration.py +64 -0
  214. pygeai/tests/snippets/migrate/project_migration.py +42 -0
  215. pygeai/tests/snippets/migrate/tool_migration.py +64 -0
  216. pygeai/tests/snippets/organization/create_project.py +2 -2
  217. pygeai/tests/snippets/organization/get_memberships.py +12 -0
  218. pygeai/tests/snippets/organization/get_organization_members.py +6 -0
  219. pygeai/tests/snippets/organization/get_project_members.py +6 -0
  220. pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
  221. pygeai/tests/snippets/organization/get_project_roles.py +6 -0
  222. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/METADATA +1 -1
  223. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/RECORD +227 -124
  224. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/WHEEL +0 -0
  225. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/entry_points.txt +0 -0
  226. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/licenses/LICENSE +0 -0
  227. {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/top_level.txt +0 -0
@@ -288,6 +288,202 @@ export_request_data_options = [
288
288
  )
289
289
  ]
290
290
 
291
+
292
+ def get_memberships(option_list: list):
293
+ email = None
294
+ start_page = 1
295
+ page_size = 20
296
+ order_key = None
297
+ order_direction = "desc"
298
+ role_types = None
299
+
300
+ for option_flag, option_arg in option_list:
301
+ if option_flag.name == "email":
302
+ email = option_arg
303
+ if option_flag.name == "start_page":
304
+ start_page = int(option_arg)
305
+ if option_flag.name == "page_size":
306
+ page_size = int(option_arg)
307
+ if option_flag.name == "order_key":
308
+ order_key = option_arg
309
+ if option_flag.name == "order_direction":
310
+ order_direction = option_arg
311
+ if option_flag.name == "role_types":
312
+ role_types = option_arg
313
+
314
+ client = OrganizationClient()
315
+ result = client.get_memberships(email, start_page, page_size, order_key, order_direction, role_types)
316
+ Console.write_stdout(f"Memberships: \n{result}")
317
+
318
+
319
+ get_memberships_options = [
320
+ Option(
321
+ "email",
322
+ ["--email", "-e"],
323
+ "Email address of the user (optional, case-insensitive)",
324
+ True
325
+ ),
326
+ Option(
327
+ "start_page",
328
+ ["--start-page"],
329
+ "Page number for pagination (default: 1)",
330
+ True
331
+ ),
332
+ Option(
333
+ "page_size",
334
+ ["--page-size"],
335
+ "Number of items per page (default: 20)",
336
+ True
337
+ ),
338
+ Option(
339
+ "order_key",
340
+ ["--order-key"],
341
+ "Field for sorting (only 'organizationName' supported)",
342
+ True
343
+ ),
344
+ Option(
345
+ "order_direction",
346
+ ["--order-direction"],
347
+ "Sort direction: asc or desc (default: desc)",
348
+ True
349
+ ),
350
+ Option(
351
+ "role_types",
352
+ ["--role-types"],
353
+ "Comma-separated list: backend, frontend (optional, case-insensitive)",
354
+ True
355
+ ),
356
+ ]
357
+
358
+
359
+ def get_project_memberships(option_list: list):
360
+ email = None
361
+ start_page = 1
362
+ page_size = 20
363
+ order_key = None
364
+ order_direction = "desc"
365
+ role_types = None
366
+
367
+ for option_flag, option_arg in option_list:
368
+ if option_flag.name == "email":
369
+ email = option_arg
370
+ if option_flag.name == "start_page":
371
+ start_page = int(option_arg)
372
+ if option_flag.name == "page_size":
373
+ page_size = int(option_arg)
374
+ if option_flag.name == "order_key":
375
+ order_key = option_arg
376
+ if option_flag.name == "order_direction":
377
+ order_direction = option_arg
378
+ if option_flag.name == "role_types":
379
+ role_types = option_arg
380
+
381
+ client = OrganizationClient()
382
+ result = client.get_project_memberships(email, start_page, page_size, order_key, order_direction, role_types)
383
+ Console.write_stdout(f"Project memberships: \n{result}")
384
+
385
+
386
+ get_project_memberships_options = [
387
+ Option(
388
+ "email",
389
+ ["--email", "-e"],
390
+ "Email address of the user (optional, case-insensitive)",
391
+ True
392
+ ),
393
+ Option(
394
+ "start_page",
395
+ ["--start-page"],
396
+ "Page number for pagination (default: 1)",
397
+ True
398
+ ),
399
+ Option(
400
+ "page_size",
401
+ ["--page-size"],
402
+ "Number of items per page (default: 20)",
403
+ True
404
+ ),
405
+ Option(
406
+ "order_key",
407
+ ["--order-key"],
408
+ "Field for sorting (only 'projectName' supported)",
409
+ True
410
+ ),
411
+ Option(
412
+ "order_direction",
413
+ ["--order-direction"],
414
+ "Sort direction: asc or desc (default: desc)",
415
+ True
416
+ ),
417
+ Option(
418
+ "role_types",
419
+ ["--role-types"],
420
+ "Comma-separated list: backend, frontend (optional, case-insensitive)",
421
+ True
422
+ ),
423
+ ]
424
+
425
+
426
+ def get_project_roles(option_list: list):
427
+ project_id = None
428
+ for option_flag, option_arg in option_list:
429
+ if option_flag.name == "project_id":
430
+ project_id = option_arg
431
+
432
+ if not project_id:
433
+ raise MissingRequirementException("Cannot retrieve project roles without project-id")
434
+
435
+ client = OrganizationClient()
436
+ result = client.get_project_roles(project_id)
437
+ Console.write_stdout(f"Project roles: \n{result}")
438
+
439
+
440
+ get_project_roles_options = [
441
+ PROJECT_ID_OPTION,
442
+ ]
443
+
444
+
445
+ def get_project_members(option_list: list):
446
+ project_id = None
447
+ for option_flag, option_arg in option_list:
448
+ if option_flag.name == "project_id":
449
+ project_id = option_arg
450
+
451
+ if not project_id:
452
+ raise MissingRequirementException("Cannot retrieve project members without project-id")
453
+
454
+ client = OrganizationClient()
455
+ result = client.get_project_members(project_id)
456
+ Console.write_stdout(f"Project members: \n{result}")
457
+
458
+
459
+ get_project_members_options = [
460
+ PROJECT_ID_OPTION,
461
+ ]
462
+
463
+
464
+ def get_organization_members(option_list: list):
465
+ organization_id = None
466
+ for option_flag, option_arg in option_list:
467
+ if option_flag.name == "organization_id":
468
+ organization_id = option_arg
469
+
470
+ if not organization_id:
471
+ raise MissingRequirementException("Cannot retrieve organization members without organization-id")
472
+
473
+ client = OrganizationClient()
474
+ result = client.get_organization_members(organization_id)
475
+ Console.write_stdout(f"Organization members: \n{result}")
476
+
477
+
478
+ get_organization_members_options = [
479
+ Option(
480
+ "organization_id",
481
+ ["--organization-id", "--oid"],
482
+ "GUID of the organization (required)",
483
+ True
484
+ ),
485
+ ]
486
+
291
487
  organization_commands = [
292
488
  Command(
293
489
  "help",
@@ -370,4 +566,49 @@ organization_commands = [
370
566
  [],
371
567
  export_request_data_options
372
568
  ),
569
+ Command(
570
+ "get_memberships",
571
+ ["get-memberships"],
572
+ "Get user memberships across organizations and projects",
573
+ get_memberships,
574
+ ArgumentsEnum.OPTIONAL,
575
+ [],
576
+ get_memberships_options
577
+ ),
578
+ Command(
579
+ "get_project_memberships",
580
+ ["get-project-memberships"],
581
+ "Get user project memberships within an organization",
582
+ get_project_memberships,
583
+ ArgumentsEnum.OPTIONAL,
584
+ [],
585
+ get_project_memberships_options
586
+ ),
587
+ Command(
588
+ "get_project_roles",
589
+ ["get-project-roles"],
590
+ "Get all roles supported by a project",
591
+ get_project_roles,
592
+ ArgumentsEnum.REQUIRED,
593
+ [],
594
+ get_project_roles_options
595
+ ),
596
+ Command(
597
+ "get_project_members",
598
+ ["get-project-members"],
599
+ "Get all members and their roles for a project",
600
+ get_project_members,
601
+ ArgumentsEnum.REQUIRED,
602
+ [],
603
+ get_project_members_options
604
+ ),
605
+ Command(
606
+ "get_organization_members",
607
+ ["get-organization-members"],
608
+ "Get all members and their roles for an organization",
609
+ get_organization_members,
610
+ ArgumentsEnum.REQUIRED,
611
+ [],
612
+ get_organization_members_options
613
+ ),
373
614
  ]
@@ -0,0 +1,116 @@
1
+ import traceback
2
+ from difflib import SequenceMatcher
3
+ from typing import List, Optional
4
+
5
+ from pygeai import logger
6
+ from pygeai.cli.commands import Command, Option
7
+ from pygeai.core.utils.console import Console
8
+
9
+
10
+ class ExitCode:
11
+ SUCCESS = 0
12
+ USER_INPUT_ERROR = 1
13
+ MISSING_REQUIREMENT = 2
14
+ SERVICE_ERROR = 3
15
+ KEYBOARD_INTERRUPT = 130
16
+ UNEXPECTED_ERROR = 255
17
+
18
+
19
+ class ErrorHandler:
20
+
21
+ @staticmethod
22
+ def format_error(error_type: str, message: str, suggestion: Optional[str] = None, show_help: bool = True) -> str:
23
+ output = f"ERROR: {message}"
24
+
25
+ if suggestion:
26
+ output += f"\n → {suggestion}"
27
+
28
+ if show_help:
29
+ output += "\n\nRun 'geai help' for usage information."
30
+
31
+ return output
32
+
33
+ @staticmethod
34
+ def find_similar_items(item: str, available_items: List[str], threshold: float = 0.6) -> List[str]:
35
+ similarities = []
36
+ for available in available_items:
37
+ ratio = SequenceMatcher(None, item.lower(), available.lower()).ratio()
38
+ if ratio >= threshold:
39
+ similarities.append((available, ratio))
40
+
41
+ similarities.sort(key=lambda x: x[1], reverse=True)
42
+ return [item[0] for item in similarities[:3]]
43
+
44
+ @staticmethod
45
+ def get_available_commands(commands: List[Command]) -> List[str]:
46
+ all_identifiers = []
47
+ for cmd in commands:
48
+ all_identifiers.extend(cmd.identifiers)
49
+ return all_identifiers
50
+
51
+ @staticmethod
52
+ def get_available_options(options: List[Option]) -> List[str]:
53
+ all_identifiers = []
54
+ for opt in options:
55
+ all_identifiers.extend(opt.identifiers)
56
+ return all_identifiers
57
+
58
+ @staticmethod
59
+ def handle_unknown_command(command: str, available_commands: List[Command]) -> str:
60
+ cmd_identifiers = ErrorHandler.get_available_commands(available_commands)
61
+ similar = ErrorHandler.find_similar_items(command, cmd_identifiers)
62
+
63
+ message = f"'{command}' is not a valid command."
64
+
65
+ if similar:
66
+ suggestion = f"Did you mean: {', '.join(similar)}?"
67
+ else:
68
+ suggestion = f"Available commands: {', '.join(sorted(set([cmd.identifiers[0] for cmd in available_commands])))}"
69
+
70
+ return ErrorHandler.format_error("Unknown Command", message, suggestion)
71
+
72
+ @staticmethod
73
+ def handle_unknown_option(option: str, available_options: List[Option]) -> str:
74
+ opt_identifiers = ErrorHandler.get_available_options(available_options)
75
+ similar = ErrorHandler.find_similar_items(option, opt_identifiers)
76
+
77
+ message = f"'{option}' is not a valid option."
78
+
79
+ if similar:
80
+ suggestion = f"Did you mean: {', '.join(similar)}?"
81
+ else:
82
+ suggestion = f"Available options: {', '.join(sorted(set([opt.identifiers[0] for opt in available_options])))}"
83
+
84
+ return ErrorHandler.format_error("Unknown Option", message, suggestion)
85
+
86
+ @staticmethod
87
+ def handle_missing_requirement(requirement_message: str) -> str:
88
+ message = requirement_message
89
+ suggestion = "Please provide all required parameters."
90
+ return ErrorHandler.format_error("Missing Requirement", message, suggestion)
91
+
92
+ @staticmethod
93
+ def handle_invalid_agent(error_message: str) -> str:
94
+ message = f"Failed to retrieve or validate the agent.\n Details: {error_message}"
95
+ suggestion = "Check your agent configuration and ensure the agent exists."
96
+ return ErrorHandler.format_error("Invalid Agent", message, suggestion)
97
+
98
+ @staticmethod
99
+ def handle_wrong_argument(error_message: str, usage: str) -> str:
100
+ Console.write_stderr(f"usage: {usage}")
101
+ message = error_message
102
+ suggestion = "Check the command syntax and try again."
103
+ return ErrorHandler.format_error("Invalid Argument", message, suggestion)
104
+
105
+ @staticmethod
106
+ def handle_keyboard_interrupt() -> str:
107
+ return "\n\nOperation cancelled by user."
108
+
109
+ @staticmethod
110
+ def handle_unexpected_error(exception: Exception) -> str:
111
+ logger.error(f"Unexpected error occurred: {exception}")
112
+ logger.error(traceback.format_exc())
113
+
114
+ message = "An unexpected error occurred. This may be a bug."
115
+ suggestion = f"Please report this issue to geai-sdk@globant.com with the following details:\n Error: {str(exception)}\n Run with geai-dbg for more details."
116
+ return ErrorHandler.format_error("Critical Error", message, suggestion, show_help=False)
pygeai/cli/geai.py CHANGED
@@ -5,6 +5,7 @@ from pygeai.cli.commands.base import base_commands, base_options
5
5
  from pygeai.cli.commands import ArgumentsEnum, Command
6
6
  from pygeai.cli.parsers import CommandParser
7
7
  from pygeai.cli.texts.help import CLI_USAGE
8
+ from pygeai.cli.error_handler import ErrorHandler, ExitCode
8
9
  from pygeai.core.base.session import get_session
9
10
  from pygeai.core.common.exceptions import UnknownArgumentError, MissingRequirementException, WrongArgumentError, \
10
11
  InvalidAgentException
@@ -64,19 +65,37 @@ class CLIDriver:
64
65
  arguments = []
65
66
 
66
67
  self.process_command(command, arguments)
67
- except (UnknownArgumentError, WrongArgumentError) as e:
68
- Console.write_stderr(f"usage: {CLI_USAGE}")
69
- Console.write_stderr(str(e))
70
- Console.write_stderr()
68
+ return ExitCode.SUCCESS
69
+ except UnknownArgumentError as e:
70
+ if hasattr(e, 'available_commands') and e.available_commands:
71
+ error_msg = ErrorHandler.handle_unknown_command(e.arg, e.available_commands)
72
+ elif hasattr(e, 'available_options') and e.available_options:
73
+ error_msg = ErrorHandler.handle_unknown_option(e.arg, e.available_options)
74
+ else:
75
+ error_msg = ErrorHandler.format_error("Unknown Argument", str(e))
76
+
77
+ Console.write_stderr(error_msg)
78
+ return ExitCode.USER_INPUT_ERROR
79
+ except WrongArgumentError as e:
80
+ error_msg = ErrorHandler.handle_wrong_argument(str(e), CLI_USAGE)
81
+ Console.write_stderr(error_msg)
82
+ return ExitCode.USER_INPUT_ERROR
71
83
  except MissingRequirementException as e:
72
- Console.write_stderr(f"ERROR: Something is missing! \nDetail: {e}")
84
+ error_msg = ErrorHandler.handle_missing_requirement(str(e))
85
+ Console.write_stderr(error_msg)
86
+ return ExitCode.MISSING_REQUIREMENT
73
87
  except InvalidAgentException as e:
74
- Console.write_stderr(f"ERROR: There was an error retrieving the agent. \nDetail: {e}")
88
+ error_msg = ErrorHandler.handle_invalid_agent(str(e))
89
+ Console.write_stderr(error_msg)
90
+ return ExitCode.SERVICE_ERROR
75
91
  except KeyboardInterrupt:
76
- Console.write_stdout()
92
+ message = ErrorHandler.handle_keyboard_interrupt()
93
+ Console.write_stdout(message)
94
+ return ExitCode.KEYBOARD_INTERRUPT
77
95
  except Exception as e:
78
- Console.write_stderr(f"CRITICAL: There has ben an unexpected error. Please report this bug to geai-sdk@globant.com. Error: {e}")
79
- return 255
96
+ error_msg = ErrorHandler.handle_unexpected_error(e)
97
+ Console.write_stderr(error_msg)
98
+ return ExitCode.UNEXPECTED_ERROR
80
99
 
81
100
  def process_command(self, command: Command, arguments: list[str]):
82
101
  """
@@ -107,4 +126,3 @@ class CLIDriver:
107
126
  else:
108
127
  option_list = CommandParser(None, subcommand.options).extract_option_list(subcommand_arguments)
109
128
  subcommand.action(option_list)
110
-
pygeai/cli/parsers.py CHANGED
@@ -18,7 +18,10 @@ class CommandParser:
18
18
  """
19
19
  command = self._get_associated_command(arg)
20
20
  if not command:
21
- raise UnknownArgumentError(f"'{arg}' is not a valid command. Run with help or h to check usage.")
21
+ error = UnknownArgumentError(f"'{arg}' is not a valid command.")
22
+ error.arg = arg
23
+ error.available_commands = self.available_commands
24
+ raise error
22
25
 
23
26
  return command
24
27
 
@@ -39,7 +42,10 @@ class CommandParser:
39
42
 
40
43
  flag = self._get_associated_option(arg)
41
44
  if not flag:
42
- raise UnknownArgumentError(f"'{arg}' is not a valid option. Run with help or h to check usage.")
45
+ error = UnknownArgumentError(f"'{arg}' is not a valid option.")
46
+ error.arg = arg
47
+ error.available_options = self.available_options
48
+ raise error
43
49
 
44
50
  if flag.requires_args:
45
51
  complementary_arg = True
@@ -3,6 +3,7 @@ from abc import ABC
3
3
  from pygeai.core.base.session import get_session, Session
4
4
  from pygeai.core.common.exceptions import MissingRequirementException
5
5
  from pygeai.core.services.rest import ApiService
6
+ from pygeai.core.utils.validators import validate_status_code
6
7
 
7
8
 
8
9
  class BaseClient(ABC):
@@ -19,7 +20,9 @@ class BaseClient(ABC):
19
20
  if not self.__session:
20
21
  raise MissingRequirementException("API KEY and BASE URL must be defined in order to use this functionality")
21
22
  elif api_key and base_url:
22
- self.__session = Session(api_key=api_key, base_url=base_url)
23
+ self.__session = get_session()
24
+ self.__session.api_key = api_key
25
+ self.__session.base_url = base_url
23
26
  else:
24
27
  self.__session = get_session()
25
28
 
@@ -6,55 +6,56 @@ class GEAIException(Exception):
6
6
 
7
7
 
8
8
  class UnknownArgumentError(GEAIException):
9
- """Argument provided is not valid"""
9
+ """Raised when an unknown or invalid command/option is provided"""
10
10
  pass
11
11
 
12
12
 
13
13
  class MissingRequirementException(GEAIException):
14
- """Requirement not available"""
14
+ """Raised when a required parameter or argument is missing"""
15
15
  pass
16
16
 
17
17
 
18
18
  class WrongArgumentError(GEAIException):
19
- """Wrongly formatted arguments"""
19
+ """Raised when arguments are incorrectly formatted or invalid"""
20
20
  pass
21
21
 
22
22
 
23
23
  class ServerResponseError(GEAIException):
24
- """There was an error in the request to the server"""
24
+ """Raised when the server returns an error response"""
25
25
  pass
26
26
 
27
27
 
28
28
  class APIError(GEAIException):
29
- """There was an error in the request to the server"""
29
+ """Raised when an API request fails"""
30
30
  pass
31
31
 
32
32
 
33
33
  class InvalidPathException(GEAIException):
34
- """There was an error trying to find the file in the specified path"""
34
+ """Raised when a file or directory path is invalid or not found"""
35
35
  pass
36
36
 
37
37
 
38
38
  class InvalidJSONException(GEAIException):
39
- """There was an error trying to load data from the JSON file"""
39
+ """Raised when JSON data cannot be parsed or is malformed"""
40
40
  pass
41
41
 
42
42
 
43
43
  class InvalidAPIResponseException(GEAIException):
44
- """There was an error handling response from the server"""
44
+ """Raised when the API response format is unexpected or invalid"""
45
45
  pass
46
46
 
47
47
 
48
48
  class InvalidResponseException(GEAIException):
49
- """There was an error getting a response from the server"""
49
+ """Raised when a response cannot be retrieved or processed"""
50
50
  pass
51
51
 
52
52
 
53
53
  class InvalidAgentException(GEAIException):
54
- """There was an error getting a response from the server"""
54
+ """Raised when an agent cannot be retrieved, validated, or is misconfigured"""
55
55
  pass
56
56
 
57
57
 
58
58
  class APIResponseError(GEAIException):
59
+ """Raised when there is an error in the API response"""
59
60
  pass
60
61
 
@@ -0,0 +1,19 @@
1
+ from pygeai.core.embeddings.clients import EmbeddingsClient
2
+ from pygeai.core.embeddings.managers import EmbeddingsManager
3
+ from pygeai.core.embeddings.models import EmbeddingConfiguration
4
+ from pygeai.core.embeddings.responses import (
5
+ EmbeddingResponse,
6
+ EmbeddingData,
7
+ UsageInfo,
8
+ TokenDetails
9
+ )
10
+
11
+ __all__ = [
12
+ 'EmbeddingsClient',
13
+ 'EmbeddingsManager',
14
+ 'EmbeddingConfiguration',
15
+ 'EmbeddingResponse',
16
+ 'EmbeddingData',
17
+ 'UsageInfo',
18
+ 'TokenDetails'
19
+ ]
@@ -1,9 +1,10 @@
1
- from json import JSONDecodeError
2
1
 
3
2
  from pygeai import logger
4
3
  from pygeai.core.base.clients import BaseClient
5
- from pygeai.core.common.exceptions import InvalidAPIResponseException
4
+ from pygeai.core.common.exceptions import InvalidAPIResponseException, APIResponseError
6
5
  from pygeai.core.embeddings.endpoints import GENERATE_EMBEDDINGS
6
+ from pygeai.core.utils.validators import validate_status_code
7
+ from pygeai.core.utils.parsers import parse_json_response
7
8
 
8
9
 
9
10
  class EmbeddingsClient(BaseClient):
@@ -42,7 +43,21 @@ class EmbeddingsClient(BaseClient):
42
43
 
43
44
  :return: dict - A dictionary containing the embedding results, including the model used, the generated
44
45
  embedding vectors, and usage statistics.
46
+ :raises ValueError: If validation fails for input parameters.
45
47
  """
48
+ if not input_list or len(input_list) == 0:
49
+ raise ValueError("input_list cannot be empty")
50
+
51
+ for idx, inp in enumerate(input_list):
52
+ if not inp or (isinstance(inp, str) and inp.strip() == ""):
53
+ raise ValueError(f"Input at index {idx} cannot be empty")
54
+
55
+ if encoding_format is not None and encoding_format not in ['float', 'base64']:
56
+ raise ValueError("encoding_format must be either 'float' or 'base64'")
57
+
58
+ if dimensions is not None and dimensions <= 0:
59
+ raise ValueError("dimensions must be a positive integer")
60
+
46
61
  data = {
47
62
  'model': model,
48
63
  'input': input_list,
@@ -73,10 +88,6 @@ class EmbeddingsClient(BaseClient):
73
88
  data=data,
74
89
  headers=headers
75
90
  )
76
- try:
77
- result = response.json()
78
- return result
79
- except JSONDecodeError as e:
80
- logger.error(f"Unable to generate embeddings: JSON parsin error: {e}; Response: {response.text}")
81
- raise InvalidAPIResponseException(f"Unable to generate embeddings: {response.text}")
82
-
91
+ validate_status_code(response)
92
+ return parse_json_response(response, "generate embeddings")
93
+
@@ -1,4 +1,4 @@
1
- from pygeai.core.embeddings.responses import EmbeddingResponse, EmbeddingData, UsageInfo
1
+ from pygeai.core.embeddings.responses import EmbeddingResponse, EmbeddingData, UsageInfo, TokenDetails
2
2
 
3
3
 
4
4
  class EmbeddingsResponseMapper:
@@ -29,10 +29,24 @@ class EmbeddingsResponseMapper:
29
29
 
30
30
  @classmethod
31
31
  def map_to_usage_info(cls, data: dict) -> UsageInfo:
32
+ completion_tokens_details_data = data.get('completion_tokens_details')
33
+ prompt_tokens_details_data = data.get('prompt_tokens_details')
34
+
32
35
  return UsageInfo(
33
36
  prompt_tokens=data.get('prompt_tokens', 0),
34
37
  total_cost=data.get('total_cost', 0.0),
35
38
  total_tokens=data.get('total_tokens', 0),
36
39
  currency=data.get('currency', ''),
37
- prompt_cost=data.get('prompt_cost', 0.0)
40
+ prompt_cost=data.get('prompt_cost', 0.0),
41
+ completion_tokens_details=cls._parse_token_details(completion_tokens_details_data),
42
+ prompt_tokens_details=cls._parse_token_details(prompt_tokens_details_data)
43
+ )
44
+
45
+ @classmethod
46
+ def _parse_token_details(cls, data: dict) -> TokenDetails | None:
47
+ if data is None:
48
+ return None
49
+ return TokenDetails(
50
+ reasoning_tokens=data.get('reasoning_tokens'),
51
+ cached_tokens=data.get('cached_tokens')
38
52
  )
@@ -1,11 +1,16 @@
1
- from typing import List
1
+ from typing import List, Union, Optional
2
2
 
3
3
  from pydantic.main import BaseModel
4
4
 
5
5
 
6
+ class TokenDetails(BaseModel):
7
+ reasoning_tokens: Optional[int] = None
8
+ cached_tokens: Optional[int] = None
9
+
10
+
6
11
  class EmbeddingData(BaseModel):
7
12
  index: int
8
- embedding: List[float]
13
+ embedding: Union[List[float], str]
9
14
  object: str
10
15
 
11
16
 
@@ -15,6 +20,8 @@ class UsageInfo(BaseModel):
15
20
  total_tokens: int
16
21
  currency: str
17
22
  prompt_cost: float
23
+ completion_tokens_details: Optional[TokenDetails] = None
24
+ prompt_tokens_details: Optional[TokenDetails] = None
18
25
 
19
26
 
20
27
  class EmbeddingResponse(BaseModel):