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.
- pygeai/_docs/source/conf.py +78 -6
- pygeai/_docs/source/content/api_reference/admin.rst +161 -0
- pygeai/_docs/source/content/api_reference/assistant.rst +326 -0
- pygeai/_docs/source/content/api_reference/auth.rst +379 -0
- pygeai/_docs/source/content/api_reference/embeddings.rst +31 -1
- pygeai/_docs/source/content/api_reference/evaluation.rst +590 -0
- pygeai/_docs/source/content/api_reference/feedback.rst +237 -0
- pygeai/_docs/source/content/api_reference/files.rst +592 -0
- pygeai/_docs/source/content/api_reference/gam.rst +401 -0
- pygeai/_docs/source/content/api_reference/health.rst +58 -0
- pygeai/_docs/source/content/api_reference/project.rst +20 -18
- pygeai/_docs/source/content/api_reference/proxy.rst +318 -0
- pygeai/_docs/source/content/api_reference/rerank.rst +94 -0
- pygeai/_docs/source/content/api_reference/secrets.rst +495 -0
- pygeai/_docs/source/content/api_reference/usage_limits.rst +390 -0
- pygeai/_docs/source/content/api_reference.rst +13 -1
- pygeai/_docs/source/content/debugger.rst +376 -83
- pygeai/_docs/source/content/migration.rst +528 -0
- pygeai/_docs/source/content/modules.rst +1 -1
- pygeai/_docs/source/index.rst +59 -7
- pygeai/_docs/source/pygeai.auth.rst +29 -0
- pygeai/_docs/source/pygeai.cli.commands.rst +16 -0
- pygeai/_docs/source/pygeai.cli.rst +8 -0
- pygeai/_docs/source/pygeai.core.utils.rst +16 -0
- pygeai/_docs/source/pygeai.rst +1 -0
- pygeai/_docs/source/pygeai.tests.auth.rst +21 -0
- pygeai/_docs/source/pygeai.tests.cli.commands.rst +16 -0
- pygeai/_docs/source/pygeai.tests.cli.rst +16 -0
- pygeai/_docs/source/pygeai.tests.core.base.rst +8 -0
- pygeai/_docs/source/pygeai.tests.core.embeddings.rst +16 -0
- pygeai/_docs/source/pygeai.tests.core.files.rst +8 -0
- pygeai/_docs/source/pygeai.tests.core.plugins.rst +21 -0
- pygeai/_docs/source/pygeai.tests.core.rst +1 -0
- pygeai/_docs/source/pygeai.tests.evaluation.dataset.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.plan.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.result.rst +21 -0
- pygeai/_docs/source/pygeai.tests.evaluation.rst +20 -0
- pygeai/_docs/source/pygeai.tests.integration.lab.processes.rst +8 -0
- pygeai/_docs/source/pygeai.tests.organization.rst +8 -0
- pygeai/_docs/source/pygeai.tests.rst +2 -0
- pygeai/_docs/source/pygeai.tests.snippets.auth.rst +10 -0
- pygeai/_docs/source/pygeai.tests.snippets.chat.rst +40 -0
- pygeai/_docs/source/pygeai.tests.snippets.dbg.rst +45 -0
- pygeai/_docs/source/pygeai.tests.snippets.embeddings.rst +40 -0
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.dataset.rst +197 -0
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.plan.rst +133 -0
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.result.rst +37 -0
- pygeai/_docs/source/pygeai.tests.snippets.evaluation.rst +10 -0
- pygeai/_docs/source/pygeai.tests.snippets.organization.rst +40 -0
- pygeai/_docs/source/pygeai.tests.snippets.rst +2 -0
- pygeai/admin/clients.py +12 -32
- pygeai/assistant/clients.py +16 -44
- pygeai/assistant/data/clients.py +1 -0
- pygeai/assistant/data_analyst/clients.py +6 -13
- pygeai/assistant/rag/clients.py +24 -67
- pygeai/auth/clients.py +88 -14
- pygeai/auth/endpoints.py +4 -0
- pygeai/chat/clients.py +192 -25
- pygeai/chat/endpoints.py +2 -1
- pygeai/cli/commands/auth.py +178 -2
- pygeai/cli/commands/chat.py +227 -1
- pygeai/cli/commands/embeddings.py +56 -8
- pygeai/cli/commands/lab/ai_lab.py +0 -2
- pygeai/cli/commands/migrate.py +994 -434
- pygeai/cli/commands/organization.py +241 -0
- pygeai/cli/error_handler.py +116 -0
- pygeai/cli/geai.py +28 -10
- pygeai/cli/parsers.py +8 -2
- pygeai/core/base/clients.py +4 -1
- pygeai/core/common/exceptions.py +11 -10
- pygeai/core/embeddings/__init__.py +19 -0
- pygeai/core/embeddings/clients.py +20 -9
- pygeai/core/embeddings/mappers.py +16 -2
- pygeai/core/embeddings/responses.py +9 -2
- pygeai/core/feedback/clients.py +4 -8
- pygeai/core/files/clients.py +10 -25
- pygeai/core/files/managers.py +42 -0
- pygeai/core/llm/clients.py +11 -26
- pygeai/core/models.py +107 -0
- pygeai/core/plugins/clients.py +4 -7
- pygeai/core/rerank/clients.py +4 -8
- pygeai/core/secrets/clients.py +14 -37
- pygeai/core/services/rest.py +1 -1
- pygeai/core/utils/parsers.py +32 -0
- pygeai/core/utils/validators.py +10 -0
- pygeai/dbg/__init__.py +3 -0
- pygeai/dbg/debugger.py +565 -70
- pygeai/evaluation/clients.py +2 -1
- pygeai/evaluation/dataset/clients.py +46 -44
- pygeai/evaluation/plan/clients.py +28 -26
- pygeai/evaluation/result/clients.py +38 -5
- pygeai/gam/clients.py +10 -25
- pygeai/health/clients.py +4 -7
- pygeai/lab/agents/clients.py +21 -54
- pygeai/lab/agents/endpoints.py +2 -0
- pygeai/lab/clients.py +1 -0
- pygeai/lab/models.py +3 -3
- pygeai/lab/processes/clients.py +45 -127
- pygeai/lab/strategies/clients.py +11 -25
- pygeai/lab/tools/clients.py +23 -67
- pygeai/lab/tools/endpoints.py +3 -0
- pygeai/migration/__init__.py +31 -0
- pygeai/migration/strategies.py +404 -155
- pygeai/migration/tools.py +170 -3
- pygeai/organization/clients.py +135 -51
- pygeai/organization/endpoints.py +6 -1
- pygeai/organization/limits/clients.py +32 -91
- pygeai/organization/managers.py +157 -1
- pygeai/organization/mappers.py +76 -2
- pygeai/organization/responses.py +25 -1
- pygeai/proxy/clients.py +4 -1
- pygeai/tests/admin/test_clients.py +16 -11
- pygeai/tests/assistants/rag/test_clients.py +35 -23
- pygeai/tests/assistants/test_clients.py +22 -15
- pygeai/tests/auth/test_clients.py +191 -7
- pygeai/tests/chat/test_clients.py +211 -1
- pygeai/tests/cli/commands/test_embeddings.py +32 -9
- pygeai/tests/cli/commands/test_evaluation.py +7 -0
- pygeai/tests/cli/commands/test_migrate.py +112 -243
- pygeai/tests/cli/test_error_handler.py +225 -0
- pygeai/tests/cli/test_geai_driver.py +154 -0
- pygeai/tests/cli/test_parsers.py +5 -5
- pygeai/tests/core/embeddings/test_clients.py +144 -0
- pygeai/tests/core/embeddings/test_managers.py +171 -0
- pygeai/tests/core/embeddings/test_mappers.py +142 -0
- pygeai/tests/core/feedback/test_clients.py +2 -0
- pygeai/tests/core/files/test_clients.py +1 -0
- pygeai/tests/core/llm/test_clients.py +14 -9
- pygeai/tests/core/plugins/test_clients.py +5 -3
- pygeai/tests/core/rerank/test_clients.py +1 -0
- pygeai/tests/core/secrets/test_clients.py +19 -13
- pygeai/tests/dbg/test_debugger.py +453 -75
- pygeai/tests/evaluation/dataset/test_clients.py +3 -1
- pygeai/tests/evaluation/plan/test_clients.py +4 -2
- pygeai/tests/evaluation/result/test_clients.py +7 -5
- pygeai/tests/gam/test_clients.py +1 -1
- pygeai/tests/health/test_clients.py +1 -0
- pygeai/tests/lab/agents/test_clients.py +9 -0
- pygeai/tests/lab/processes/test_clients.py +36 -0
- pygeai/tests/lab/processes/test_mappers.py +3 -0
- pygeai/tests/lab/strategies/test_clients.py +14 -9
- pygeai/tests/migration/test_strategies.py +45 -218
- pygeai/tests/migration/test_tools.py +133 -9
- pygeai/tests/organization/limits/test_clients.py +17 -0
- pygeai/tests/organization/test_clients.py +206 -1
- pygeai/tests/organization/test_managers.py +122 -1
- pygeai/tests/proxy/test_clients.py +2 -0
- pygeai/tests/proxy/test_integration.py +1 -0
- pygeai/tests/snippets/auth/__init__.py +0 -0
- pygeai/tests/snippets/chat/chat_completion_with_reasoning_effort.py +18 -0
- pygeai/tests/snippets/chat/get_response.py +15 -0
- pygeai/tests/snippets/chat/get_response_streaming.py +20 -0
- pygeai/tests/snippets/chat/get_response_with_files.py +16 -0
- pygeai/tests/snippets/chat/get_response_with_tools.py +36 -0
- pygeai/tests/snippets/dbg/__init__.py +0 -0
- pygeai/tests/snippets/dbg/basic_debugging.py +32 -0
- pygeai/tests/snippets/dbg/breakpoint_management.py +48 -0
- pygeai/tests/snippets/dbg/stack_navigation.py +45 -0
- pygeai/tests/snippets/dbg/stepping_example.py +40 -0
- pygeai/tests/snippets/embeddings/cache_example.py +31 -0
- pygeai/tests/snippets/embeddings/cohere_example.py +41 -0
- pygeai/tests/snippets/embeddings/openai_base64_example.py +27 -0
- pygeai/tests/snippets/embeddings/openai_example.py +30 -0
- pygeai/tests/snippets/embeddings/similarity_example.py +42 -0
- pygeai/tests/snippets/evaluation/dataset/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/dataset/complete_workflow_example.py +195 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset.py +26 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_from_file.py +11 -0
- pygeai/tests/snippets/evaluation/dataset/create_dataset_row.py +17 -0
- pygeai/tests/snippets/evaluation/dataset/create_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/create_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/delete_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/delete_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/delete_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/get_dataset_row.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/get_expected_source.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/get_filter_variable.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/list_dataset_rows.py +9 -0
- pygeai/tests/snippets/evaluation/dataset/list_datasets.py +6 -0
- pygeai/tests/snippets/evaluation/dataset/list_expected_sources.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/list_filter_variables.py +10 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset.py +15 -0
- pygeai/tests/snippets/evaluation/dataset/update_dataset_row.py +20 -0
- pygeai/tests/snippets/evaluation/dataset/update_expected_source.py +18 -0
- pygeai/tests/snippets/evaluation/dataset/update_filter_variable.py +19 -0
- pygeai/tests/snippets/evaluation/dataset/upload_dataset_rows_file.py +10 -0
- pygeai/tests/snippets/evaluation/plan/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/plan/add_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/complete_workflow_example.py +136 -0
- pygeai/tests/snippets/evaluation/plan/create_evaluation_plan.py +24 -0
- pygeai/tests/snippets/evaluation/plan/create_rag_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/delete_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/delete_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/execute_evaluation_plan.py +11 -0
- pygeai/tests/snippets/evaluation/plan/get_evaluation_plan.py +9 -0
- pygeai/tests/snippets/evaluation/plan/get_plan_system_metric.py +13 -0
- pygeai/tests/snippets/evaluation/plan/get_system_metric.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_evaluation_plans.py +7 -0
- pygeai/tests/snippets/evaluation/plan/list_plan_system_metrics.py +9 -0
- pygeai/tests/snippets/evaluation/plan/list_system_metrics.py +7 -0
- pygeai/tests/snippets/evaluation/plan/update_evaluation_plan.py +22 -0
- pygeai/tests/snippets/evaluation/plan/update_plan_system_metric.py +14 -0
- pygeai/tests/snippets/evaluation/result/__init__.py +0 -0
- pygeai/tests/snippets/evaluation/result/complete_workflow_example.py +150 -0
- pygeai/tests/snippets/evaluation/result/get_evaluation_result.py +26 -0
- pygeai/tests/snippets/evaluation/result/list_evaluation_results.py +17 -0
- pygeai/tests/snippets/migrate/__init__.py +45 -0
- pygeai/tests/snippets/migrate/agent_migration.py +110 -0
- pygeai/tests/snippets/migrate/assistant_migration.py +64 -0
- pygeai/tests/snippets/migrate/orchestrator_examples.py +179 -0
- pygeai/tests/snippets/migrate/process_migration.py +64 -0
- pygeai/tests/snippets/migrate/project_migration.py +42 -0
- pygeai/tests/snippets/migrate/tool_migration.py +64 -0
- pygeai/tests/snippets/organization/create_project.py +2 -2
- pygeai/tests/snippets/organization/get_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_organization_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_members.py +6 -0
- pygeai/tests/snippets/organization/get_project_memberships.py +12 -0
- pygeai/tests/snippets/organization/get_project_roles.py +6 -0
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/METADATA +1 -1
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/RECORD +227 -124
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/WHEEL +0 -0
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/entry_points.txt +0 -0
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/licenses/LICENSE +0 -0
- {pygeai-0.6.0b6.dist-info → pygeai-0.6.0b10.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
GAM OAuth Integration
|
|
2
|
+
=====================
|
|
3
|
+
|
|
4
|
+
The GAM (GeneXus Access Manager) module provides OAuth 2.0 authentication functionality for integrating with GeneXus applications. It enables user authentication, token management, and access to user information.
|
|
5
|
+
|
|
6
|
+
This section covers:
|
|
7
|
+
|
|
8
|
+
* Generating OAuth signin URLs
|
|
9
|
+
* Obtaining access tokens
|
|
10
|
+
* Refreshing tokens
|
|
11
|
+
* Retrieving user information
|
|
12
|
+
|
|
13
|
+
For each operation, you have implementation options using the Low-Level Service Layer.
|
|
14
|
+
|
|
15
|
+
Overview
|
|
16
|
+
--------
|
|
17
|
+
|
|
18
|
+
OAuth 2.0 Flow with GAM:
|
|
19
|
+
|
|
20
|
+
1. **Generate Signin URL**: Create URL for user authentication
|
|
21
|
+
2. **User Authorization**: User authenticates via browser
|
|
22
|
+
3. **Get Access Token**: Exchange credentials/code for access token
|
|
23
|
+
4. **Access Resources**: Use token to access protected resources
|
|
24
|
+
5. **Refresh Token**: Obtain new access token when expired
|
|
25
|
+
|
|
26
|
+
Generate Signin URL
|
|
27
|
+
-------------------
|
|
28
|
+
|
|
29
|
+
Creates an OAuth 2.0 authorization URL for browser-based authentication flows.
|
|
30
|
+
|
|
31
|
+
Low-Level Service Layer
|
|
32
|
+
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
33
|
+
|
|
34
|
+
.. code-block:: python
|
|
35
|
+
|
|
36
|
+
from pygeai.gam.clients import GAMClient
|
|
37
|
+
import secrets
|
|
38
|
+
|
|
39
|
+
client = GAMClient()
|
|
40
|
+
|
|
41
|
+
# Generate random state for CSRF protection
|
|
42
|
+
state = secrets.token_urlsafe(32)
|
|
43
|
+
|
|
44
|
+
signin_url = client.generate_signing_url(
|
|
45
|
+
client_id="your-app-client-id",
|
|
46
|
+
redirect_uri="https://yourapp.com/callback",
|
|
47
|
+
scope="gam_user_data",
|
|
48
|
+
state=state
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
print(f"Redirect user to: {signin_url}")
|
|
52
|
+
# Store state for validation when user returns
|
|
53
|
+
|
|
54
|
+
**Parameters:**
|
|
55
|
+
|
|
56
|
+
* ``client_id``: (Required) Your application's client ID
|
|
57
|
+
* ``redirect_uri``: (Required) Callback URL registered in your app
|
|
58
|
+
* ``scope``: OAuth scope (default: "gam_user_data")
|
|
59
|
+
* ``state``: (Required) Random string for CSRF protection
|
|
60
|
+
* ``response_type``: Response type (default: "code")
|
|
61
|
+
|
|
62
|
+
**Returns:**
|
|
63
|
+
String containing the complete authorization URL.
|
|
64
|
+
|
|
65
|
+
**Scopes:**
|
|
66
|
+
|
|
67
|
+
* ``gam_user_data``: Basic user information
|
|
68
|
+
* ``gam_user_roles``: User roles and permissions
|
|
69
|
+
* Combine with ``+``: ``"gam_user_data+gam_user_roles"``
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
Get Access Token
|
|
73
|
+
----------------
|
|
74
|
+
|
|
75
|
+
Obtains an access token using the Resource Owner Password Credentials grant.
|
|
76
|
+
|
|
77
|
+
Low-Level Service Layer
|
|
78
|
+
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
79
|
+
|
|
80
|
+
.. code-block:: python
|
|
81
|
+
|
|
82
|
+
from pygeai.gam.clients import GAMClient
|
|
83
|
+
|
|
84
|
+
client = GAMClient()
|
|
85
|
+
|
|
86
|
+
token_response = client.get_access_token(
|
|
87
|
+
client_id="your-app-client-id",
|
|
88
|
+
client_secret="your-app-client-secret",
|
|
89
|
+
username="user@example.com",
|
|
90
|
+
password="user-password",
|
|
91
|
+
scope="gam_user_data+gam_user_roles"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
access_token = token_response['access_token']
|
|
95
|
+
refresh_token = token_response['refresh_token']
|
|
96
|
+
expires_in = token_response['expires_in']
|
|
97
|
+
|
|
98
|
+
print(f"Access token: {access_token}")
|
|
99
|
+
print(f"Expires in: {expires_in} seconds")
|
|
100
|
+
|
|
101
|
+
**Parameters:**
|
|
102
|
+
|
|
103
|
+
* ``client_id``: (Required) Application client ID
|
|
104
|
+
* ``client_secret``: (Required) Application client secret
|
|
105
|
+
* ``username``: (Required) User's username/email
|
|
106
|
+
* ``password``: (Required) User's password
|
|
107
|
+
* ``grant_type``: Grant type (default: "password")
|
|
108
|
+
* ``scope``: OAuth scope (default: "gam_user_data")
|
|
109
|
+
* ``authentication_type_name``: Auth type (default: "local")
|
|
110
|
+
* ``repository``: Repository ID for multitenant setups
|
|
111
|
+
* ``initial_properties``: Custom user properties array
|
|
112
|
+
* ``request_token_type``: Token type: "OAuth" or "Web" (default: "OAuth")
|
|
113
|
+
|
|
114
|
+
**Returns:**
|
|
115
|
+
Dictionary containing:
|
|
116
|
+
|
|
117
|
+
* ``access_token``: The access token
|
|
118
|
+
* ``token_type``: Token type (usually "Bearer")
|
|
119
|
+
* ``expires_in``: Token lifetime in seconds
|
|
120
|
+
* ``refresh_token``: Token for refreshing access
|
|
121
|
+
* ``scope``: Granted scopes
|
|
122
|
+
* ``user_guid``: User's unique identifier
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
Refresh Access Token
|
|
126
|
+
---------------------
|
|
127
|
+
|
|
128
|
+
Obtains a new access token using a refresh token.
|
|
129
|
+
|
|
130
|
+
Low-Level Service Layer
|
|
131
|
+
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
132
|
+
|
|
133
|
+
.. code-block:: python
|
|
134
|
+
|
|
135
|
+
from pygeai.gam.clients import GAMClient
|
|
136
|
+
|
|
137
|
+
client = GAMClient()
|
|
138
|
+
|
|
139
|
+
new_token = client.refresh_access_token(
|
|
140
|
+
client_id="your-app-client-id",
|
|
141
|
+
client_secret="your-app-client-secret",
|
|
142
|
+
refresh_token="existing-refresh-token"
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
access_token = new_token['access_token']
|
|
146
|
+
print(f"New access token: {access_token}")
|
|
147
|
+
|
|
148
|
+
**Parameters:**
|
|
149
|
+
|
|
150
|
+
* ``client_id``: (Required) Application client ID
|
|
151
|
+
* ``client_secret``: (Required) Application client secret
|
|
152
|
+
* ``refresh_token``: (Required) Refresh token from previous response
|
|
153
|
+
* ``grant_type``: Must be "refresh_token" (default)
|
|
154
|
+
|
|
155
|
+
**Returns:**
|
|
156
|
+
Dictionary with new access token and refresh token.
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
Get User Information
|
|
160
|
+
--------------------
|
|
161
|
+
|
|
162
|
+
Retrieves authenticated user's information.
|
|
163
|
+
|
|
164
|
+
Low-Level Service Layer
|
|
165
|
+
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
166
|
+
|
|
167
|
+
.. code-block:: python
|
|
168
|
+
|
|
169
|
+
from pygeai.gam.clients import GAMClient
|
|
170
|
+
|
|
171
|
+
client = GAMClient()
|
|
172
|
+
|
|
173
|
+
user_info = client.get_user_info(
|
|
174
|
+
access_token="user-access-token"
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
print(f"User GUID: {user_info['guid']}")
|
|
178
|
+
print(f"Username: {user_info['username']}")
|
|
179
|
+
print(f"Email: {user_info['email']}")
|
|
180
|
+
|
|
181
|
+
**Parameters:**
|
|
182
|
+
|
|
183
|
+
* ``access_token``: (Required) Valid access token
|
|
184
|
+
|
|
185
|
+
**Returns:**
|
|
186
|
+
Dictionary containing user details based on granted scopes.
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
Complete OAuth Flow Example
|
|
190
|
+
----------------------------
|
|
191
|
+
|
|
192
|
+
.. code-block:: python
|
|
193
|
+
|
|
194
|
+
from pygeai.gam.clients import GAMClient
|
|
195
|
+
import time
|
|
196
|
+
|
|
197
|
+
client = GAMClient()
|
|
198
|
+
|
|
199
|
+
# Step 1: Obtain access token
|
|
200
|
+
token_response = client.get_access_token(
|
|
201
|
+
client_id="app-client-id",
|
|
202
|
+
client_secret="app-secret",
|
|
203
|
+
username="user@example.com",
|
|
204
|
+
password="password",
|
|
205
|
+
scope="gam_user_data+gam_user_roles"
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
access_token = token_response['access_token']
|
|
209
|
+
refresh_token = token_response['refresh_token']
|
|
210
|
+
expires_in = token_response['expires_in']
|
|
211
|
+
|
|
212
|
+
print(f"Obtained access token (expires in {expires_in}s)")
|
|
213
|
+
|
|
214
|
+
# Step 2: Get user information
|
|
215
|
+
user_info = client.get_user_info(access_token=access_token)
|
|
216
|
+
|
|
217
|
+
print(f"\nUser Information:")
|
|
218
|
+
print(f" GUID: {user_info['guid']}")
|
|
219
|
+
print(f" Username: {user_info['username']}")
|
|
220
|
+
print(f" Email: {user_info.get('email', 'N/A')}")
|
|
221
|
+
|
|
222
|
+
# Step 3: Simulate token expiration and refresh
|
|
223
|
+
print(f"\nWaiting for token to expire...")
|
|
224
|
+
time.sleep(expires_in + 1)
|
|
225
|
+
|
|
226
|
+
# Step 4: Refresh the access token
|
|
227
|
+
new_token = client.refresh_access_token(
|
|
228
|
+
client_id="app-client-id",
|
|
229
|
+
client_secret="app-secret",
|
|
230
|
+
refresh_token=refresh_token
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
access_token = new_token['access_token']
|
|
234
|
+
print(f"Refreshed access token")
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
Best Practices
|
|
238
|
+
--------------
|
|
239
|
+
|
|
240
|
+
Token Security
|
|
241
|
+
~~~~~~~~~~~~~~
|
|
242
|
+
|
|
243
|
+
* Store tokens securely (encrypted storage, environment variables)
|
|
244
|
+
* Never log or expose tokens in code
|
|
245
|
+
* Use HTTPS for all OAuth communications
|
|
246
|
+
* Implement token rotation
|
|
247
|
+
* Clear tokens from memory after use
|
|
248
|
+
|
|
249
|
+
State Parameter
|
|
250
|
+
~~~~~~~~~~~~~~~
|
|
251
|
+
|
|
252
|
+
* Generate cryptographically random state values
|
|
253
|
+
* Store state in session for validation
|
|
254
|
+
* Validate state when user returns from authentication
|
|
255
|
+
* Prevents CSRF attacks
|
|
256
|
+
|
|
257
|
+
Token Lifecycle
|
|
258
|
+
~~~~~~~~~~~~~~~
|
|
259
|
+
|
|
260
|
+
* Monitor token expiration
|
|
261
|
+
* Refresh tokens proactively before expiration
|
|
262
|
+
* Implement token refresh logic in error handlers
|
|
263
|
+
* Handle refresh token expiration gracefully
|
|
264
|
+
|
|
265
|
+
Scopes
|
|
266
|
+
~~~~~~
|
|
267
|
+
|
|
268
|
+
* Request minimal required scopes
|
|
269
|
+
* Document why each scope is needed
|
|
270
|
+
* Handle scope changes gracefully
|
|
271
|
+
* Validate granted vs requested scopes
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
Security Considerations
|
|
275
|
+
-----------------------
|
|
276
|
+
|
|
277
|
+
CSRF Protection
|
|
278
|
+
~~~~~~~~~~~~~~~
|
|
279
|
+
|
|
280
|
+
Always use and validate the ``state`` parameter:
|
|
281
|
+
|
|
282
|
+
.. code-block:: python
|
|
283
|
+
|
|
284
|
+
import secrets
|
|
285
|
+
|
|
286
|
+
# Generate state
|
|
287
|
+
state = secrets.token_urlsafe(32)
|
|
288
|
+
# Store in session: session['oauth_state'] = state
|
|
289
|
+
|
|
290
|
+
signin_url = client.generate_signing_url(
|
|
291
|
+
client_id="...",
|
|
292
|
+
redirect_uri="...",
|
|
293
|
+
state=state
|
|
294
|
+
)
|
|
295
|
+
|
|
296
|
+
# On callback, validate:
|
|
297
|
+
# if request.args.get('state') != session.get('oauth_state'):
|
|
298
|
+
# raise SecurityError("Invalid state parameter")
|
|
299
|
+
|
|
300
|
+
Password Grant Considerations
|
|
301
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
302
|
+
|
|
303
|
+
* Use password grant only for trusted applications
|
|
304
|
+
* Prefer authorization code flow for web applications
|
|
305
|
+
* Implement rate limiting on token requests
|
|
306
|
+
* Use strong password policies
|
|
307
|
+
* Consider multi-factor authentication
|
|
308
|
+
|
|
309
|
+
Token Storage
|
|
310
|
+
~~~~~~~~~~~~~
|
|
311
|
+
|
|
312
|
+
* Never store tokens in:
|
|
313
|
+
|
|
314
|
+
* Client-side JavaScript
|
|
315
|
+
* URL parameters
|
|
316
|
+
* Logs
|
|
317
|
+
* Version control
|
|
318
|
+
|
|
319
|
+
* Secure storage options:
|
|
320
|
+
|
|
321
|
+
* Server-side session storage
|
|
322
|
+
* Encrypted database fields
|
|
323
|
+
* Secure key management systems
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
Error Handling
|
|
327
|
+
--------------
|
|
328
|
+
|
|
329
|
+
.. code-block:: python
|
|
330
|
+
|
|
331
|
+
from pygeai.gam.clients import GAMClient
|
|
332
|
+
from pygeai.core.common.exceptions import MissingRequirementException, APIError
|
|
333
|
+
|
|
334
|
+
client = GAMClient()
|
|
335
|
+
|
|
336
|
+
# Handle missing parameters
|
|
337
|
+
try:
|
|
338
|
+
url = client.generate_signing_url(
|
|
339
|
+
client_id="id",
|
|
340
|
+
# Missing redirect_uri and state
|
|
341
|
+
)
|
|
342
|
+
except MissingRequirementException as e:
|
|
343
|
+
print(f"Missing required parameters: {e}")
|
|
344
|
+
|
|
345
|
+
# Handle invalid credentials
|
|
346
|
+
try:
|
|
347
|
+
token = client.get_access_token(
|
|
348
|
+
client_id="app-id",
|
|
349
|
+
client_secret="secret",
|
|
350
|
+
username="user",
|
|
351
|
+
password="wrong-password"
|
|
352
|
+
)
|
|
353
|
+
except APIError as e:
|
|
354
|
+
print(f"Authentication failed: {e}")
|
|
355
|
+
|
|
356
|
+
# Handle expired refresh token
|
|
357
|
+
try:
|
|
358
|
+
new_token = client.refresh_access_token(
|
|
359
|
+
client_id="app-id",
|
|
360
|
+
client_secret="secret",
|
|
361
|
+
refresh_token="expired-token"
|
|
362
|
+
)
|
|
363
|
+
except APIError as e:
|
|
364
|
+
print("Refresh token expired, user must re-authenticate")
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
Integration with GEAI
|
|
368
|
+
---------------------
|
|
369
|
+
|
|
370
|
+
Using GAM tokens with GEAI services:
|
|
371
|
+
|
|
372
|
+
.. code-block:: python
|
|
373
|
+
|
|
374
|
+
from pygeai.gam.clients import GAMClient
|
|
375
|
+
from pygeai.assistant.managers import AssistantManager
|
|
376
|
+
|
|
377
|
+
# Authenticate via GAM
|
|
378
|
+
gam_client = GAMClient()
|
|
379
|
+
token_response = gam_client.get_access_token(
|
|
380
|
+
client_id="app-id",
|
|
381
|
+
client_secret="secret",
|
|
382
|
+
username="user@example.com",
|
|
383
|
+
password="password"
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
access_token = token_response['access_token']
|
|
387
|
+
|
|
388
|
+
# Use token with GEAI services
|
|
389
|
+
# (Specific integration depends on service configuration)
|
|
390
|
+
# Some services may accept GAM tokens for authentication
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
Notes
|
|
394
|
+
-----
|
|
395
|
+
|
|
396
|
+
* GAM OAuth follows the OAuth 2.0 specification
|
|
397
|
+
* Password grant is suitable for trusted applications only
|
|
398
|
+
* Refresh tokens have longer lifetimes than access tokens
|
|
399
|
+
* Token response may vary based on ``request_token_type``
|
|
400
|
+
* Multitenant deployments require ``repository`` parameter
|
|
401
|
+
* Custom user properties can be set via ``initial_properties``
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Health & Status
|
|
2
|
+
===============
|
|
3
|
+
|
|
4
|
+
The Health module provides functionality to check the operational status of Globant Enterprise AI services and endpoints.
|
|
5
|
+
|
|
6
|
+
This section covers:
|
|
7
|
+
|
|
8
|
+
* Checking API health status
|
|
9
|
+
* Verifying service availability
|
|
10
|
+
|
|
11
|
+
For each operation, you have two implementation options:
|
|
12
|
+
|
|
13
|
+
* `Command Line`_
|
|
14
|
+
* `Low-Level Service Layer`_
|
|
15
|
+
|
|
16
|
+
.. note::
|
|
17
|
+
The Health module currently does not have a High-Level Service Layer (Manager class).
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
Check API Status
|
|
21
|
+
~~~~~~~~~~~~~~~~
|
|
22
|
+
|
|
23
|
+
Checks the health and availability of the Globant Enterprise AI API.
|
|
24
|
+
|
|
25
|
+
Command Line
|
|
26
|
+
^^^^^^^^^^^^
|
|
27
|
+
|
|
28
|
+
.. code-block:: shell
|
|
29
|
+
|
|
30
|
+
geai status
|
|
31
|
+
|
|
32
|
+
Or using the alias:
|
|
33
|
+
|
|
34
|
+
.. code-block:: shell
|
|
35
|
+
|
|
36
|
+
geai s
|
|
37
|
+
|
|
38
|
+
Low-Level Service Layer
|
|
39
|
+
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
40
|
+
|
|
41
|
+
.. code-block:: python
|
|
42
|
+
|
|
43
|
+
from pygeai.health.clients import HealthClient
|
|
44
|
+
|
|
45
|
+
client = HealthClient()
|
|
46
|
+
|
|
47
|
+
status = client.get_health()
|
|
48
|
+
print(status)
|
|
49
|
+
|
|
50
|
+
Example response:
|
|
51
|
+
|
|
52
|
+
.. code-block:: json
|
|
53
|
+
|
|
54
|
+
{
|
|
55
|
+
"status": "healthy",
|
|
56
|
+
"version": "1.0.0",
|
|
57
|
+
"timestamp": "2026-01-06T12:00:00Z"
|
|
58
|
+
}
|
|
@@ -68,7 +68,7 @@ Use the following code snippet to list projects with the desired detail level:
|
|
|
68
68
|
|
|
69
69
|
.. code-block:: python
|
|
70
70
|
|
|
71
|
-
from pygeai.organization.clients import OrganizationClient
|
|
71
|
+
from pygeai.organization.clients import OrganizationClient
|
|
72
72
|
|
|
73
73
|
client = OrganizationClient()
|
|
74
74
|
project_list = client.get_project_list(detail="full") # Use "summary" for less detail
|
|
@@ -156,7 +156,7 @@ For more control, you can use the low-level service layer. To do so:
|
|
|
156
156
|
|
|
157
157
|
.. code-block:: python
|
|
158
158
|
|
|
159
|
-
from pygeai.organization.clients import OrganizationClient
|
|
159
|
+
from pygeai.organization.clients import OrganizationClient
|
|
160
160
|
|
|
161
161
|
name="Project Name"
|
|
162
162
|
description="Project Description"
|
|
@@ -181,13 +181,13 @@ The high-level service layer offers a more structured approach:
|
|
|
181
181
|
.. code-block:: python
|
|
182
182
|
|
|
183
183
|
from pygeai.organization.managers import OrganizationManager
|
|
184
|
-
from pygeai.core.models import
|
|
184
|
+
from pygeai.core.models import UsageLimit, Project
|
|
185
185
|
|
|
186
186
|
manager = OrganizationManager()
|
|
187
187
|
|
|
188
|
-
usage_limit =
|
|
188
|
+
usage_limit = UsageLimit(
|
|
189
189
|
subscription_type="Monthly", # Options: Freemium, Daily, Weekly, Monthly
|
|
190
|
-
usage_unit="Requests", # Options:
|
|
190
|
+
usage_unit="Requests", # Options: Requests, Cost
|
|
191
191
|
soft_limit=500.0, # Recommended usage limit
|
|
192
192
|
hard_limit=1000.0, # Maximum allowed usage
|
|
193
193
|
renewal_status="Renewable" # Options: Renewable, NonRenewable
|
|
@@ -253,9 +253,9 @@ Use the following code snippet to update a project using the low-level service l
|
|
|
253
253
|
|
|
254
254
|
.. code-block:: python
|
|
255
255
|
|
|
256
|
-
from pygeai.organization.clients import OrganizationClient
|
|
256
|
+
from pygeai.organization.clients import OrganizationClient
|
|
257
257
|
|
|
258
|
-
|
|
258
|
+
project_iid="<project_id>"
|
|
259
259
|
name="<new_project_name>"
|
|
260
260
|
description="<new_project_description>"
|
|
261
261
|
|
|
@@ -284,7 +284,7 @@ Use the following code snippet to update a project using the high-level service
|
|
|
284
284
|
client = OrganizationManager()
|
|
285
285
|
|
|
286
286
|
project = Project(
|
|
287
|
-
|
|
287
|
+
id="<project_id>",
|
|
288
288
|
name="<new_project_name>",
|
|
289
289
|
description="<new_project_description>",
|
|
290
290
|
)
|
|
@@ -335,7 +335,7 @@ Use the following code snippet to delete a project using the low-level service l
|
|
|
335
335
|
|
|
336
336
|
.. code-block:: python
|
|
337
337
|
|
|
338
|
-
from pygeai.organization.clients import OrganizationClient
|
|
338
|
+
from pygeai.organization.clients import OrganizationClient
|
|
339
339
|
|
|
340
340
|
project_id = "<project_id>"
|
|
341
341
|
client = OrganizationClient()
|
|
@@ -346,11 +346,13 @@ Replace <`project_id`> with the actual project Id. For example:
|
|
|
346
346
|
|
|
347
347
|
.. code-block:: python
|
|
348
348
|
|
|
349
|
-
from pygeai.organization.clients import OrganizationClient
|
|
349
|
+
from pygeai.organization.clients import OrganizationClient
|
|
350
350
|
|
|
351
351
|
project_id="12345678-90ab-cdef-1234-567890abcdef"
|
|
352
352
|
client = OrganizationClient()
|
|
353
|
-
deleted_project = client.delete_project(
|
|
353
|
+
deleted_project = client.delete_project(project_id=project_id)
|
|
354
|
+
print(deleted_project)
|
|
355
|
+
|
|
354
356
|
|
|
355
357
|
High level service layer
|
|
356
358
|
^^^^^^^^^^^^^^^^^^^^^^^^
|
|
@@ -370,7 +372,7 @@ Replace <`project_id`> with the actual project Id. For example:
|
|
|
370
372
|
|
|
371
373
|
.. code-block:: python
|
|
372
374
|
|
|
373
|
-
from pygeai.
|
|
375
|
+
from pygeai.organization.managers import OrganizationManager
|
|
374
376
|
|
|
375
377
|
manager = OrganizationManager()
|
|
376
378
|
response = manager.delete_project("12345678-90ab-cdef-1234-567890abcdef")
|
|
@@ -415,9 +417,9 @@ Use the following code snippet to retrieve project data using the low-level serv
|
|
|
415
417
|
|
|
416
418
|
.. code-block:: python
|
|
417
419
|
|
|
418
|
-
from pygeai.organization.clients import OrganizationClient
|
|
420
|
+
from pygeai.organization.clients import OrganizationClient
|
|
419
421
|
|
|
420
|
-
|
|
422
|
+
project_iid="<project_id>"
|
|
421
423
|
client = OrganizationClient()
|
|
422
424
|
project_data = client.get_project_data(project_id=project_id)
|
|
423
425
|
print(project_data)
|
|
@@ -427,7 +429,7 @@ Replace `<project_id>` with the actual project Id. For example:
|
|
|
427
429
|
|
|
428
430
|
.. code-block:: python
|
|
429
431
|
|
|
430
|
-
from pygeai.organization.clients import OrganizationClient
|
|
432
|
+
from pygeai.organization.clients import OrganizationClient
|
|
431
433
|
|
|
432
434
|
project_id="12345678-90ab-cdef-1234-567890abcdef"
|
|
433
435
|
client = OrganizationClient()
|
|
@@ -447,7 +449,7 @@ Use the following code snippet to retrieve project data using the high-level ser
|
|
|
447
449
|
|
|
448
450
|
manager = OrganizationManager(alias="sdkorg")
|
|
449
451
|
|
|
450
|
-
project = manager.get_project_data(
|
|
452
|
+
project = manager.get_project_data(project_iid="<project_id>")
|
|
451
453
|
print(f"project: {project}")
|
|
452
454
|
|
|
453
455
|
|
|
@@ -455,7 +457,7 @@ Replace `<project_id>` with the actual project Id. For example:
|
|
|
455
457
|
|
|
456
458
|
.. code-block:: python
|
|
457
459
|
|
|
458
|
-
from pygeai.
|
|
460
|
+
from pygeai.organization.managers import OrganizationManager
|
|
459
461
|
|
|
460
462
|
manager = OrganizationManager(alias="sdkorg")
|
|
461
463
|
project = manager.get_project_data(project_id="12345678-90ab-cdef-1234-567890abcdef")
|
|
@@ -528,7 +530,7 @@ Use the following code snippet to retrieve project tokens using the high-level s
|
|
|
528
530
|
|
|
529
531
|
.. code-block:: python
|
|
530
532
|
|
|
531
|
-
from pygeai.
|
|
533
|
+
from pygeai.organization.managers import OrganizationManager
|
|
532
534
|
from pygeai.core.base.models import ProjectTokensResponse
|
|
533
535
|
|
|
534
536
|
client = OrganizationManager()
|