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
pygeai/migration/tools.py
CHANGED
|
@@ -1,13 +1,180 @@
|
|
|
1
|
+
from typing import List, Dict, Optional
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
|
|
4
|
+
from pygeai import logger
|
|
1
5
|
from pygeai.migration.strategies import MigrationStrategy
|
|
6
|
+
from pygeai.core.utils.console import Console
|
|
2
7
|
|
|
3
8
|
|
|
4
9
|
class MigrationTool:
|
|
10
|
+
"""
|
|
11
|
+
Orchestrates migration operations using configurable strategies.
|
|
12
|
+
|
|
13
|
+
This class provides a flexible way to execute migrations with support for:
|
|
14
|
+
- Batch migrations of multiple resources
|
|
15
|
+
- Dependency ordering
|
|
16
|
+
- Progress tracking
|
|
17
|
+
- Dry-run mode
|
|
18
|
+
- Rollback capabilities
|
|
19
|
+
"""
|
|
5
20
|
|
|
6
21
|
def __init__(self, strategy: MigrationStrategy):
|
|
7
|
-
self.
|
|
22
|
+
self._strategy = strategy
|
|
8
23
|
|
|
9
24
|
def set_strategy(self, strategy: MigrationStrategy):
|
|
10
|
-
|
|
25
|
+
"""
|
|
26
|
+
Update the migration strategy.
|
|
27
|
+
|
|
28
|
+
:param strategy: The new migration strategy to use
|
|
29
|
+
"""
|
|
30
|
+
self._strategy = strategy
|
|
11
31
|
|
|
12
32
|
def run_migration(self):
|
|
13
|
-
|
|
33
|
+
"""
|
|
34
|
+
Execute the configured migration strategy.
|
|
35
|
+
|
|
36
|
+
:return: The result from the migration strategy (if any)
|
|
37
|
+
:raises ValueError: If migration fails
|
|
38
|
+
"""
|
|
39
|
+
logger.info(f"Starting migration with strategy: {self._strategy.__class__.__name__}")
|
|
40
|
+
return self._strategy.migrate()
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
@dataclass
|
|
44
|
+
class MigrationPlan:
|
|
45
|
+
"""
|
|
46
|
+
Defines a migration plan with multiple strategies and execution order.
|
|
47
|
+
|
|
48
|
+
:param strategies: List of migration strategies to execute
|
|
49
|
+
:param dependencies: Map of strategy index to list of dependent strategy indices
|
|
50
|
+
:param dry_run: If True, validate without executing migrations
|
|
51
|
+
:param stop_on_error: If True, stop execution on first error
|
|
52
|
+
"""
|
|
53
|
+
strategies: List[MigrationStrategy]
|
|
54
|
+
dependencies: Dict[int, List[int]] = field(default_factory=dict)
|
|
55
|
+
dry_run: bool = False
|
|
56
|
+
stop_on_error: bool = True
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class MigrationOrchestrator:
|
|
60
|
+
"""
|
|
61
|
+
Advanced orchestration for complex migration scenarios.
|
|
62
|
+
|
|
63
|
+
Handles batch migrations, dependency resolution, progress tracking,
|
|
64
|
+
and rollback on failure.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
def __init__(self, plan: MigrationPlan):
|
|
68
|
+
self._plan = plan
|
|
69
|
+
self._completed: List[int] = []
|
|
70
|
+
self._failed: List[int] = []
|
|
71
|
+
|
|
72
|
+
def execute(self) -> Dict[str, any]:
|
|
73
|
+
"""
|
|
74
|
+
Execute the migration plan respecting dependencies.
|
|
75
|
+
|
|
76
|
+
:return: Summary of migration results
|
|
77
|
+
:raises ValueError: If migration fails and stop_on_error is True
|
|
78
|
+
"""
|
|
79
|
+
logger.info(f"Executing migration plan with {len(self._plan.strategies)} strategies")
|
|
80
|
+
|
|
81
|
+
if self._plan.dry_run:
|
|
82
|
+
return self._validate_plan()
|
|
83
|
+
|
|
84
|
+
execution_order = self._resolve_dependencies()
|
|
85
|
+
total_strategies = len(execution_order)
|
|
86
|
+
|
|
87
|
+
Console.write_stdout("")
|
|
88
|
+
Console.write_stdout("=" * 60)
|
|
89
|
+
Console.write_stdout(f"Migration Progress: 0/{total_strategies} completed")
|
|
90
|
+
Console.write_stdout("=" * 60)
|
|
91
|
+
|
|
92
|
+
for position, idx in enumerate(execution_order, 1):
|
|
93
|
+
strategy = self._plan.strategies[idx]
|
|
94
|
+
display_info = strategy.get_display_info()
|
|
95
|
+
|
|
96
|
+
Console.write_stdout(f"\n[{position}/{total_strategies}] Migrating {display_info}...")
|
|
97
|
+
|
|
98
|
+
try:
|
|
99
|
+
logger.info(f"Executing strategy {idx + 1}/{len(self._plan.strategies)}: {strategy.__class__.__name__}")
|
|
100
|
+
strategy.migrate()
|
|
101
|
+
self._completed.append(idx)
|
|
102
|
+
Console.write_stdout(f"✓ Successfully migrated {display_info}")
|
|
103
|
+
except Exception as e:
|
|
104
|
+
logger.error(f"Strategy {idx} failed: {e}")
|
|
105
|
+
self._failed.append(idx)
|
|
106
|
+
Console.write_stdout(f"✗ Failed to migrate {display_info}: {e}")
|
|
107
|
+
if self._plan.stop_on_error:
|
|
108
|
+
raise ValueError(f"Migration failed at strategy {idx}: {e}") from e
|
|
109
|
+
|
|
110
|
+
Console.write_stdout("")
|
|
111
|
+
Console.write_stdout("=" * 60)
|
|
112
|
+
Console.write_stdout(f"Migration Complete: {len(self._completed)}/{total_strategies} successful")
|
|
113
|
+
Console.write_stdout("=" * 60)
|
|
114
|
+
|
|
115
|
+
return self._generate_summary()
|
|
116
|
+
|
|
117
|
+
def _resolve_dependencies(self) -> List[int]:
|
|
118
|
+
"""
|
|
119
|
+
Resolve strategy execution order based on dependencies.
|
|
120
|
+
|
|
121
|
+
:return: Ordered list of strategy indices
|
|
122
|
+
:raises ValueError: If circular dependencies detected
|
|
123
|
+
"""
|
|
124
|
+
visited = set()
|
|
125
|
+
order = []
|
|
126
|
+
|
|
127
|
+
def visit(idx: int, path: set):
|
|
128
|
+
if idx in path:
|
|
129
|
+
raise ValueError(f"Circular dependency detected at strategy {idx}")
|
|
130
|
+
if idx in visited:
|
|
131
|
+
return
|
|
132
|
+
|
|
133
|
+
path.add(idx)
|
|
134
|
+
for dep_idx in self._plan.dependencies.get(idx, []):
|
|
135
|
+
visit(dep_idx, path)
|
|
136
|
+
path.remove(idx)
|
|
137
|
+
|
|
138
|
+
visited.add(idx)
|
|
139
|
+
order.append(idx)
|
|
140
|
+
|
|
141
|
+
for idx in range(len(self._plan.strategies)):
|
|
142
|
+
visit(idx, set())
|
|
143
|
+
|
|
144
|
+
return order
|
|
145
|
+
|
|
146
|
+
def _validate_plan(self) -> Dict[str, any]:
|
|
147
|
+
"""
|
|
148
|
+
Validate the migration plan without executing.
|
|
149
|
+
|
|
150
|
+
:return: Validation results
|
|
151
|
+
"""
|
|
152
|
+
logger.info("Validating migration plan (dry-run mode)")
|
|
153
|
+
try:
|
|
154
|
+
execution_order = self._resolve_dependencies()
|
|
155
|
+
return {
|
|
156
|
+
"valid": True,
|
|
157
|
+
"execution_order": execution_order,
|
|
158
|
+
"total_strategies": len(self._plan.strategies)
|
|
159
|
+
}
|
|
160
|
+
except Exception as e:
|
|
161
|
+
logger.error(f"Validation failed: {e}")
|
|
162
|
+
return {
|
|
163
|
+
"valid": False,
|
|
164
|
+
"error": str(e)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
def _generate_summary(self) -> Dict[str, any]:
|
|
168
|
+
"""
|
|
169
|
+
Generate a summary of migration results.
|
|
170
|
+
|
|
171
|
+
:return: Summary dictionary with completed, failed, and pending migrations
|
|
172
|
+
"""
|
|
173
|
+
return {
|
|
174
|
+
"total": len(self._plan.strategies),
|
|
175
|
+
"completed": len(self._completed),
|
|
176
|
+
"failed": len(self._failed),
|
|
177
|
+
"success_rate": len(self._completed) / len(self._plan.strategies) if self._plan.strategies else 0,
|
|
178
|
+
"completed_indices": self._completed,
|
|
179
|
+
"failed_indices": self._failed
|
|
180
|
+
}
|
pygeai/organization/clients.py
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from json import JSONDecodeError
|
|
3
1
|
|
|
4
2
|
from pygeai import logger
|
|
5
3
|
from pygeai.core.common.exceptions import InvalidAPIResponseException
|
|
6
4
|
from pygeai.organization.endpoints import GET_ASSISTANT_LIST_V1, GET_PROJECT_LIST_V1, GET_PROJECT_V1, \
|
|
7
|
-
CREATE_PROJECT_V1, UPDATE_PROJECT_V1, DELETE_PROJECT_V1, GET_PROJECT_TOKENS_V1, GET_REQUEST_DATA_V1
|
|
5
|
+
CREATE_PROJECT_V1, UPDATE_PROJECT_V1, DELETE_PROJECT_V1, GET_PROJECT_TOKENS_V1, GET_REQUEST_DATA_V1, \
|
|
6
|
+
GET_MEMBERSHIPS_V2, GET_PROJECT_MEMBERSHIPS_V2, GET_PROJECT_ROLES_V2, GET_PROJECT_MEMBERS_V2, \
|
|
7
|
+
GET_ORGANIZATION_MEMBERS_V2
|
|
8
8
|
from pygeai.core.base.clients import BaseClient
|
|
9
|
+
from pygeai.core.utils.validators import validate_status_code
|
|
10
|
+
from pygeai.core.utils.parsers import parse_json_response
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class OrganizationClient(BaseClient):
|
|
@@ -23,12 +25,8 @@ class OrganizationClient(BaseClient):
|
|
|
23
25
|
:return: AssistantListResponse - The API response containing the list of assistants and the project.
|
|
24
26
|
"""
|
|
25
27
|
response = self.api_service.get(endpoint=GET_ASSISTANT_LIST_V1, params={"detail": detail})
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
return result
|
|
29
|
-
except JSONDecodeError as e:
|
|
30
|
-
logger.error(f"Unable to get assistant list: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
31
|
-
raise InvalidAPIResponseException(f"Unable to get assistant list: {response.text}")
|
|
28
|
+
validate_status_code(response)
|
|
29
|
+
return parse_json_response(response, "get assistant list")
|
|
32
30
|
|
|
33
31
|
def get_project_list(
|
|
34
32
|
self,
|
|
@@ -59,12 +57,8 @@ class OrganizationClient(BaseClient):
|
|
|
59
57
|
"detail": detail
|
|
60
58
|
}
|
|
61
59
|
)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return result
|
|
65
|
-
except JSONDecodeError as e:
|
|
66
|
-
logger.error(f"Unable to get project list: JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
67
|
-
raise InvalidAPIResponseException(f"Unable to get project list: {response.text}")
|
|
60
|
+
validate_status_code(response)
|
|
61
|
+
return parse_json_response(response, "get project list")
|
|
68
62
|
|
|
69
63
|
def get_project_data(
|
|
70
64
|
self,
|
|
@@ -80,12 +74,8 @@ class OrganizationClient(BaseClient):
|
|
|
80
74
|
response = self.api_service.get(
|
|
81
75
|
endpoint=endpoint
|
|
82
76
|
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
return result
|
|
86
|
-
except JSONDecodeError as e:
|
|
87
|
-
logger.error(f"Unable to get project data for ID '{project_id}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
88
|
-
raise InvalidAPIResponseException(f"Unable to get project data for ID '{project_id}': {response.text}")
|
|
77
|
+
validate_status_code(response)
|
|
78
|
+
return parse_json_response(response, "get project data for ID", project_id=project_id)
|
|
89
79
|
|
|
90
80
|
def create_project(
|
|
91
81
|
self,
|
|
@@ -122,12 +112,8 @@ class OrganizationClient(BaseClient):
|
|
|
122
112
|
"description": description
|
|
123
113
|
}
|
|
124
114
|
)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
return result
|
|
128
|
-
except JSONDecodeError as e:
|
|
129
|
-
logger.error(f"Unable to create project with name '{name}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
130
|
-
raise InvalidAPIResponseException(f"Unable to create project with name '{name}': {response.text}")
|
|
115
|
+
validate_status_code(response)
|
|
116
|
+
return parse_json_response(response, "create project with name", name=name)
|
|
131
117
|
|
|
132
118
|
def update_project(
|
|
133
119
|
self,
|
|
@@ -151,12 +137,8 @@ class OrganizationClient(BaseClient):
|
|
|
151
137
|
"description": description
|
|
152
138
|
}
|
|
153
139
|
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return result
|
|
157
|
-
except JSONDecodeError as e:
|
|
158
|
-
logger.error(f"Unable to update project with ID '{project_id}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
159
|
-
raise InvalidAPIResponseException(f"Unable to update project with ID '{project_id}': {response.text}")
|
|
140
|
+
validate_status_code(response)
|
|
141
|
+
return parse_json_response(response, "update project with ID", project_id=project_id)
|
|
160
142
|
|
|
161
143
|
def delete_project(
|
|
162
144
|
self,
|
|
@@ -170,12 +152,8 @@ class OrganizationClient(BaseClient):
|
|
|
170
152
|
"""
|
|
171
153
|
endpoint = DELETE_PROJECT_V1.format(id=project_id)
|
|
172
154
|
response = self.api_service.delete(endpoint=endpoint)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
return result
|
|
176
|
-
except JSONDecodeError as e:
|
|
177
|
-
logger.error(f"Unable to delete project with ID '{project_id}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
178
|
-
raise InvalidAPIResponseException(f"Unable to delete project with ID '{project_id}': {response.text}")
|
|
155
|
+
validate_status_code(response)
|
|
156
|
+
return parse_json_response(response, "delete project with ID", project_id=project_id)
|
|
179
157
|
|
|
180
158
|
def get_project_tokens(
|
|
181
159
|
self,
|
|
@@ -189,12 +167,8 @@ class OrganizationClient(BaseClient):
|
|
|
189
167
|
"""
|
|
190
168
|
endpoint = GET_PROJECT_TOKENS_V1.format(id=project_id)
|
|
191
169
|
response = self.api_service.get(endpoint=endpoint)
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return result
|
|
195
|
-
except JSONDecodeError as e:
|
|
196
|
-
logger.error(f"Unable to get tokens for project with ID '{project_id}': JSON parsing error (status {response.status_code}): {e}. Response: {response.text}")
|
|
197
|
-
raise InvalidAPIResponseException(f"Unable to get tokens for project with ID '{project_id}': {response.text}")
|
|
170
|
+
validate_status_code(response)
|
|
171
|
+
return parse_json_response(response, "get tokens for project with ID", project_id=project_id)
|
|
198
172
|
|
|
199
173
|
def export_request_data(
|
|
200
174
|
self,
|
|
@@ -221,9 +195,119 @@ class OrganizationClient(BaseClient):
|
|
|
221
195
|
"count": count
|
|
222
196
|
}
|
|
223
197
|
)
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
198
|
+
validate_status_code(response)
|
|
199
|
+
return parse_json_response(response, "export request data")
|
|
200
|
+
|
|
201
|
+
def get_memberships(
|
|
202
|
+
self,
|
|
203
|
+
email: str = None,
|
|
204
|
+
start_page: int = 1,
|
|
205
|
+
page_size: int = 20,
|
|
206
|
+
order_key: str = None,
|
|
207
|
+
order_direction: str = "desc",
|
|
208
|
+
role_types: str = None
|
|
209
|
+
) -> dict:
|
|
210
|
+
"""
|
|
211
|
+
Retrieves a list of Organizations and Projects a user belongs to with their Roles.
|
|
212
|
+
|
|
213
|
+
:param email: str - The email address of the user to search for (optional, case-insensitive).
|
|
214
|
+
:param start_page: int - The page number for pagination (default is 1).
|
|
215
|
+
:param page_size: int - The number of items per page (default is 20).
|
|
216
|
+
:param order_key: str - Field for sorting. Only 'organizationName' is supported (optional).
|
|
217
|
+
:param order_direction: str - Sort direction: 'asc' or 'desc' (default is 'desc').
|
|
218
|
+
:param role_types: str - Comma-separated list of role types: 'backend', 'frontend' (optional, case-insensitive).
|
|
219
|
+
:return: dict - The API response containing the list of organizations and projects with roles, in JSON format.
|
|
220
|
+
"""
|
|
221
|
+
params = {
|
|
222
|
+
"startPage": start_page,
|
|
223
|
+
"pageSize": page_size,
|
|
224
|
+
"orderDirection": order_direction
|
|
225
|
+
}
|
|
226
|
+
if email:
|
|
227
|
+
params["email"] = email
|
|
228
|
+
if order_key:
|
|
229
|
+
params["orderKey"] = order_key
|
|
230
|
+
if role_types:
|
|
231
|
+
params["roleTypes"] = role_types
|
|
232
|
+
|
|
233
|
+
response = self.api_service.get(endpoint=GET_MEMBERSHIPS_V2, params=params)
|
|
234
|
+
validate_status_code(response)
|
|
235
|
+
return parse_json_response(response, "get memberships")
|
|
236
|
+
|
|
237
|
+
def get_project_memberships(
|
|
238
|
+
self,
|
|
239
|
+
email: str = None,
|
|
240
|
+
start_page: int = 1,
|
|
241
|
+
page_size: int = 20,
|
|
242
|
+
order_key: str = None,
|
|
243
|
+
order_direction: str = "desc",
|
|
244
|
+
role_types: str = None
|
|
245
|
+
) -> dict:
|
|
246
|
+
"""
|
|
247
|
+
Retrieves a list of Projects and Roles for a user within a specific Organization.
|
|
248
|
+
|
|
249
|
+
:param email: str - The email address of the user to search for (optional, case-insensitive).
|
|
250
|
+
:param start_page: int - The page number for pagination (default is 1).
|
|
251
|
+
:param page_size: int - The number of items per page (default is 20).
|
|
252
|
+
:param order_key: str - Field for sorting. Only 'projectName' is supported (optional).
|
|
253
|
+
:param order_direction: str - Sort direction: 'asc' or 'desc' (default is 'desc').
|
|
254
|
+
:param role_types: str - Comma-separated list of role types: 'backend', 'frontend' (optional, case-insensitive).
|
|
255
|
+
:return: dict - The API response containing the list of projects with roles, in JSON format.
|
|
256
|
+
"""
|
|
257
|
+
params = {
|
|
258
|
+
"startPage": start_page,
|
|
259
|
+
"pageSize": page_size,
|
|
260
|
+
"orderDirection": order_direction
|
|
261
|
+
}
|
|
262
|
+
if email:
|
|
263
|
+
params["email"] = email
|
|
264
|
+
if order_key:
|
|
265
|
+
params["orderKey"] = order_key
|
|
266
|
+
if role_types:
|
|
267
|
+
params["roleTypes"] = role_types
|
|
268
|
+
|
|
269
|
+
response = self.api_service.get(endpoint=GET_PROJECT_MEMBERSHIPS_V2, params=params)
|
|
270
|
+
validate_status_code(response)
|
|
271
|
+
return parse_json_response(response, "get project memberships")
|
|
272
|
+
|
|
273
|
+
def get_project_roles(
|
|
274
|
+
self,
|
|
275
|
+
project_id: str
|
|
276
|
+
) -> dict:
|
|
277
|
+
"""
|
|
278
|
+
Retrieves all Roles supported by a specific Project.
|
|
279
|
+
|
|
280
|
+
:param project_id: str - The unique identifier (GUID) of the project (required).
|
|
281
|
+
:return: dict - The API response containing the list of roles for the project, in JSON format.
|
|
282
|
+
"""
|
|
283
|
+
response = self.api_service.get(endpoint=GET_PROJECT_ROLES_V2, params={"projectId": project_id})
|
|
284
|
+
validate_status_code(response)
|
|
285
|
+
return parse_json_response(response, "get project roles for project", project_id=project_id)
|
|
286
|
+
|
|
287
|
+
def get_project_members(
|
|
288
|
+
self,
|
|
289
|
+
project_id: str
|
|
290
|
+
) -> dict:
|
|
291
|
+
"""
|
|
292
|
+
Retrieves all members and their Roles for a specific Project.
|
|
293
|
+
|
|
294
|
+
:param project_id: str - The unique identifier (GUID) of the project (required).
|
|
295
|
+
:return: dict - The API response containing the list of members with their roles, in JSON format.
|
|
296
|
+
"""
|
|
297
|
+
response = self.api_service.get(endpoint=GET_PROJECT_MEMBERS_V2, params={"projectId": project_id})
|
|
298
|
+
validate_status_code(response)
|
|
299
|
+
return parse_json_response(response, "get project members for project", project_id=project_id)
|
|
300
|
+
|
|
301
|
+
def get_organization_members(
|
|
302
|
+
self,
|
|
303
|
+
organization_id: str
|
|
304
|
+
) -> dict:
|
|
305
|
+
"""
|
|
306
|
+
Retrieves all members and their Roles for a specific Organization.
|
|
307
|
+
|
|
308
|
+
:param organization_id: str - The unique identifier (GUID) of the organization (required).
|
|
309
|
+
:return: dict - The API response containing the list of members with their roles, in JSON format.
|
|
310
|
+
"""
|
|
311
|
+
response = self.api_service.get(endpoint=GET_ORGANIZATION_MEMBERS_V2, params={"organizationId": organization_id})
|
|
312
|
+
validate_status_code(response)
|
|
313
|
+
return parse_json_response(response, "get organization members for organization", organization_id=organization_id)
|
pygeai/organization/endpoints.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
GET_ASSISTANT_LIST_V1 = "v1/organization/assistants" # GET
|
|
1
|
+
GET_ASSISTANT_LIST_V1 = "v1/organization/assistants" # GET - Gets the list of assistants
|
|
2
2
|
GET_PROJECT_LIST_V1 = "v1/organization/projects" # GET - Gets the list of projects
|
|
3
3
|
GET_PROJECT_V1 = "v1/organization/project/{id}" # GET - Gets project details
|
|
4
4
|
CREATE_PROJECT_V1 = "v1/organization/project" # POST - Creates a project
|
|
@@ -6,3 +6,8 @@ UPDATE_PROJECT_V1 = "v1/organization/project/{id}" # PUT - Updat
|
|
|
6
6
|
DELETE_PROJECT_V1 = "v1/organization/project/{id}" # DELETE - Deletes a project
|
|
7
7
|
GET_PROJECT_TOKENS_V1 = "v1/organization/project/{id}/tokens" # GET - Gets the list of Tokens for the project
|
|
8
8
|
GET_REQUEST_DATA_V1 = "v1/organization/request/export" # GET - Exports request data
|
|
9
|
+
GET_MEMBERSHIPS_V2 = "v2/accessControl/memberships" # GET - Lists Organizations and Projects a user belongs to with their Roles
|
|
10
|
+
GET_PROJECT_MEMBERSHIPS_V2 = "v2/accessControl/projects/memberships" # GET - Lists Projects and Roles for a user within a specific Organization
|
|
11
|
+
GET_PROJECT_ROLES_V2 = "v2/accessControl/projects/roles" # GET - Lists all Roles supported by a specific Project
|
|
12
|
+
GET_PROJECT_MEMBERS_V2 = "v2/accessControl/projects/members" # GET - Lists all members and their Roles for a specific Project
|
|
13
|
+
GET_ORGANIZATION_MEMBERS_V2 = "v2/accessControl/organizations/members" # GET - Lists all members and their Roles for a specific Organization
|