codemie-sdk-python 0.1.433__tar.gz → 0.1.435__tar.gz
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.
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/PKG-INFO +1 -1
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/pyproject.toml +1 -1
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/__init__.py +10 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/auth/credentials.py +63 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/client/client.py +43 -23
- codemie_sdk_python-0.1.435/src/codemie_sdk/models/admin.py +87 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/project.py +21 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/skill.py +88 -0
- codemie_sdk_python-0.1.435/src/codemie_sdk/services/admin.py +138 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/project.py +4 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/skill.py +86 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/utils/http.py +1 -1
- codemie_sdk_python-0.1.433/src/codemie_sdk/models/admin.py +0 -27
- codemie_sdk_python-0.1.433/src/codemie_sdk/services/admin.py +0 -58
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/README.md +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/auth/__init__.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/client/__init__.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/exceptions.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/__init__.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/analytics.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/assistant.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/categories.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/common.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/conversation.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/datasource.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/errors.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/file_operation.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/guardrails.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/integration.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/llm.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/mermaid.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/task.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/user.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/vendor_assistant.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/vendor_guardrail.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/vendor_knowledgebase.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/vendor_workflow.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/workflow.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/workflow_execution_payload.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/workflow_state.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/workflow_thoughts.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/analytics.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/assistant.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/categories.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/codemie_guardrails.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/conversation.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/datasource.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/files.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/integration.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/llm.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/mermaid.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/task.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/user.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/vendor_assistant.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/vendor_guardrail.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/vendor_knowledgebase.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/vendor_workflow.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/webhook.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/workflow.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/workflow_execution.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/workflow_execution_state.py +0 -0
- {codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/utils/__init__.py +0 -0
|
@@ -125,6 +125,11 @@ from .models.skill import (
|
|
|
125
125
|
SkillDetailResponse,
|
|
126
126
|
SkillListResponse,
|
|
127
127
|
SkillListPaginatedResponse,
|
|
128
|
+
SkillEventRequest,
|
|
129
|
+
SkillEventItem,
|
|
130
|
+
SkillStatsItem,
|
|
131
|
+
SingleSkillStatsResponse,
|
|
132
|
+
SkillPagination,
|
|
128
133
|
)
|
|
129
134
|
from .services.skill import SkillService
|
|
130
135
|
|
|
@@ -221,5 +226,10 @@ __all__ = [
|
|
|
221
226
|
"SkillDetailResponse",
|
|
222
227
|
"SkillListResponse",
|
|
223
228
|
"SkillListPaginatedResponse",
|
|
229
|
+
"SkillEventRequest",
|
|
230
|
+
"SkillEventItem",
|
|
231
|
+
"SkillStatsItem",
|
|
232
|
+
"SingleSkillStatsResponse",
|
|
233
|
+
"SkillPagination",
|
|
224
234
|
"SkillService",
|
|
225
235
|
]
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/auth/credentials.py
RENAMED
|
@@ -1,10 +1,73 @@
|
|
|
1
1
|
"""Authentication credentials module for CodeMie SDK."""
|
|
2
2
|
|
|
3
|
+
import base64
|
|
4
|
+
import json as _json
|
|
3
5
|
import time
|
|
4
6
|
import requests
|
|
5
7
|
from typing import Callable
|
|
6
8
|
|
|
7
9
|
|
|
10
|
+
def _decode_jwt_exp(token: str) -> float | None:
|
|
11
|
+
"""Return the exp claim from a JWT payload without signature verification."""
|
|
12
|
+
try:
|
|
13
|
+
parts = token.split(".")
|
|
14
|
+
if len(parts) != 3:
|
|
15
|
+
return None
|
|
16
|
+
payload = parts[1]
|
|
17
|
+
padding = 4 - len(payload) % 4
|
|
18
|
+
if padding != 4:
|
|
19
|
+
payload += "=" * padding
|
|
20
|
+
claims = _json.loads(base64.urlsafe_b64decode(payload))
|
|
21
|
+
exp = claims.get("exp")
|
|
22
|
+
return float(exp) if exp is not None else None
|
|
23
|
+
except Exception:
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class LocalAuthCredentials:
|
|
28
|
+
"""Authenticates against the backend local-auth endpoint and caches the JWT."""
|
|
29
|
+
|
|
30
|
+
_TOKEN_EXPIRY_BUFFER_SECONDS = 30
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
api_domain: str,
|
|
35
|
+
email: str,
|
|
36
|
+
password: str,
|
|
37
|
+
verify_ssl: bool = True,
|
|
38
|
+
):
|
|
39
|
+
self._login_url = f"{api_domain.rstrip('/')}/v1/local-auth/login"
|
|
40
|
+
self._email = email
|
|
41
|
+
self._password = password
|
|
42
|
+
self._verify_ssl = verify_ssl
|
|
43
|
+
self._cached_token: str | None = None
|
|
44
|
+
self._token_expires_at: float = 0.0
|
|
45
|
+
|
|
46
|
+
def get_token(self) -> str:
|
|
47
|
+
"""Return cached JWT, re-logging in when expired."""
|
|
48
|
+
now = time.monotonic()
|
|
49
|
+
if self._cached_token and now < self._token_expires_at:
|
|
50
|
+
return self._cached_token
|
|
51
|
+
|
|
52
|
+
response = requests.post(
|
|
53
|
+
self._login_url,
|
|
54
|
+
json={"email": self._email, "password": self._password},
|
|
55
|
+
verify=self._verify_ssl,
|
|
56
|
+
)
|
|
57
|
+
response.raise_for_status()
|
|
58
|
+
self._cached_token = response.json()["access_token"]
|
|
59
|
+
|
|
60
|
+
exp = _decode_jwt_exp(self._cached_token)
|
|
61
|
+
if exp is not None:
|
|
62
|
+
ttl = exp - time.time()
|
|
63
|
+
self._token_expires_at = now + max(
|
|
64
|
+
ttl - self._TOKEN_EXPIRY_BUFFER_SECONDS, 0
|
|
65
|
+
)
|
|
66
|
+
else:
|
|
67
|
+
self._token_expires_at = now + 3570 # 1 h fallback
|
|
68
|
+
return self._cached_token
|
|
69
|
+
|
|
70
|
+
|
|
8
71
|
class KeycloakCredentials:
|
|
9
72
|
"""Keycloak authentication credentials handler."""
|
|
10
73
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from typing import Callable
|
|
4
4
|
|
|
5
|
-
from ..auth.credentials import KeycloakCredentials
|
|
5
|
+
from ..auth.credentials import KeycloakCredentials, LocalAuthCredentials
|
|
6
6
|
from ..services.admin import AdminService
|
|
7
7
|
from ..services.analytics import AnalyticsService
|
|
8
8
|
from ..services.assistant import AssistantService
|
|
@@ -56,18 +56,6 @@ class CodeMieClient:
|
|
|
56
56
|
external_idp: Identity provider ID to validate extern_token with (optional, required if using external_token)
|
|
57
57
|
verify_ssl: Whether to verify SSL certificates (default: True)
|
|
58
58
|
"""
|
|
59
|
-
self.auth = KeycloakCredentials(
|
|
60
|
-
server_url=auth_server_url,
|
|
61
|
-
realm_name=auth_realm_name,
|
|
62
|
-
client_id=auth_client_id,
|
|
63
|
-
client_secret=auth_client_secret,
|
|
64
|
-
username=username,
|
|
65
|
-
password=password,
|
|
66
|
-
external_token=external_token,
|
|
67
|
-
external_idp=external_idp,
|
|
68
|
-
verify_ssl=verify_ssl,
|
|
69
|
-
)
|
|
70
|
-
|
|
71
59
|
self._token: str | None = None
|
|
72
60
|
self._api_domain = codemie_api_domain.rstrip("/")
|
|
73
61
|
self._is_localhost = self._is_localhost_domain(self._api_domain)
|
|
@@ -78,10 +66,34 @@ class CodeMieClient:
|
|
|
78
66
|
|
|
79
67
|
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
|
80
68
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
69
|
+
if self._is_localhost and username and password:
|
|
70
|
+
self._local_auth: LocalAuthCredentials | None = LocalAuthCredentials(
|
|
71
|
+
api_domain=codemie_api_domain,
|
|
72
|
+
email=username,
|
|
73
|
+
password=password,
|
|
74
|
+
verify_ssl=verify_ssl,
|
|
75
|
+
)
|
|
76
|
+
self._token = self._local_auth.get_token()
|
|
77
|
+
_token_source = self._local_auth.get_token
|
|
78
|
+
elif self._is_localhost:
|
|
79
|
+
self._local_auth = None
|
|
80
|
+
self._token = ""
|
|
81
|
+
_token_source = ""
|
|
82
|
+
else:
|
|
83
|
+
self._local_auth = None
|
|
84
|
+
self.auth = KeycloakCredentials(
|
|
85
|
+
server_url=auth_server_url,
|
|
86
|
+
realm_name=auth_realm_name,
|
|
87
|
+
client_id=auth_client_id,
|
|
88
|
+
client_secret=auth_client_secret,
|
|
89
|
+
username=username,
|
|
90
|
+
password=password,
|
|
91
|
+
external_token=external_token,
|
|
92
|
+
external_idp=external_idp,
|
|
93
|
+
verify_ssl=verify_ssl,
|
|
94
|
+
)
|
|
95
|
+
self._token = self.auth.get_token()
|
|
96
|
+
_token_source = self.auth.get_token
|
|
85
97
|
|
|
86
98
|
# Initialize services with verify_ssl parameter and token
|
|
87
99
|
self.admin = AdminService(
|
|
@@ -145,7 +157,10 @@ class CodeMieClient:
|
|
|
145
157
|
@property
|
|
146
158
|
def token(self) -> str:
|
|
147
159
|
"""Get current token or fetch new one if not available."""
|
|
148
|
-
|
|
160
|
+
if self._is_localhost and self._local_auth:
|
|
161
|
+
self._token = self._local_auth.get_token()
|
|
162
|
+
elif not self._is_localhost:
|
|
163
|
+
self._token = self.auth.get_token()
|
|
149
164
|
return self._token
|
|
150
165
|
|
|
151
166
|
@staticmethod
|
|
@@ -162,9 +177,14 @@ class CodeMieClient:
|
|
|
162
177
|
|
|
163
178
|
def refresh_token(self) -> str:
|
|
164
179
|
"""Force token refresh."""
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
180
|
+
if self._is_localhost and self._local_auth:
|
|
181
|
+
self._local_auth._cached_token = None
|
|
182
|
+
self._local_auth._token_expires_at = 0.0
|
|
183
|
+
self._token = self._local_auth.get_token()
|
|
184
|
+
elif self._is_localhost:
|
|
185
|
+
self._token = ""
|
|
186
|
+
else:
|
|
187
|
+
self.auth._cached_token = None
|
|
188
|
+
self.auth._token_expires_at = 0.0
|
|
189
|
+
self._token = self.auth.get_token()
|
|
170
190
|
return self._token
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Admin models for managing applications/projects."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class ApplicationsListResponse(BaseModel):
|
|
7
|
+
"""Response model for list applications endpoint."""
|
|
8
|
+
|
|
9
|
+
model_config = ConfigDict(extra="ignore")
|
|
10
|
+
|
|
11
|
+
applications: list[str] = Field(..., description="List of application names")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ApplicationCreateRequest(BaseModel):
|
|
15
|
+
"""Request model for creating an application/project."""
|
|
16
|
+
|
|
17
|
+
model_config = ConfigDict(extra="ignore")
|
|
18
|
+
|
|
19
|
+
name: str = Field(..., description="Application/project name")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ApplicationCreateResponse(BaseModel):
|
|
23
|
+
"""Response model for create application endpoint."""
|
|
24
|
+
|
|
25
|
+
model_config = ConfigDict(extra="ignore")
|
|
26
|
+
|
|
27
|
+
message: str = Field(..., description="Created application name")
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class LocalUserCreateRequest(BaseModel):
|
|
31
|
+
"""Request model for admin user creation (local auth mode only)."""
|
|
32
|
+
|
|
33
|
+
model_config = ConfigDict(extra="ignore")
|
|
34
|
+
|
|
35
|
+
email: str
|
|
36
|
+
username: str
|
|
37
|
+
password: str
|
|
38
|
+
name: str | None = None
|
|
39
|
+
is_admin: bool = False
|
|
40
|
+
is_maintainer: bool = False
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class LocalUserDetail(BaseModel):
|
|
44
|
+
"""Response model for created/fetched user (local auth mode)."""
|
|
45
|
+
|
|
46
|
+
model_config = ConfigDict(extra="ignore")
|
|
47
|
+
|
|
48
|
+
id: str
|
|
49
|
+
email: str
|
|
50
|
+
username: str
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class AdminUserListItem(BaseModel):
|
|
54
|
+
"""User item returned by the admin list-users endpoint."""
|
|
55
|
+
|
|
56
|
+
model_config = ConfigDict(extra="ignore")
|
|
57
|
+
|
|
58
|
+
id: str
|
|
59
|
+
email: str
|
|
60
|
+
username: str
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class AdminUserListPagination(BaseModel):
|
|
64
|
+
"""Pagination metadata from GET /v1/admin/users."""
|
|
65
|
+
|
|
66
|
+
model_config = ConfigDict(extra="ignore")
|
|
67
|
+
|
|
68
|
+
total: int
|
|
69
|
+
page: int
|
|
70
|
+
per_page: int
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class AdminUserListResponse(BaseModel):
|
|
74
|
+
"""Paginated response from GET /v1/admin/users."""
|
|
75
|
+
|
|
76
|
+
model_config = ConfigDict(extra="ignore")
|
|
77
|
+
|
|
78
|
+
data: list[AdminUserListItem]
|
|
79
|
+
pagination: AdminUserListPagination
|
|
80
|
+
|
|
81
|
+
@property
|
|
82
|
+
def users(self) -> list[AdminUserListItem]:
|
|
83
|
+
return self.data
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def total(self) -> int:
|
|
87
|
+
return self.pagination.total
|
|
@@ -43,6 +43,24 @@ class ProjectMember(BaseModel):
|
|
|
43
43
|
date: datetime | None = None
|
|
44
44
|
|
|
45
45
|
|
|
46
|
+
class ProjectBudgetItem(BaseModel):
|
|
47
|
+
"""Budget assigned to a project (present when include_budgets=true)."""
|
|
48
|
+
|
|
49
|
+
model_config = ConfigDict(extra="ignore")
|
|
50
|
+
|
|
51
|
+
budget_id: str
|
|
52
|
+
name: str
|
|
53
|
+
budget_category: str
|
|
54
|
+
soft_budget: float
|
|
55
|
+
max_budget: float
|
|
56
|
+
budget_duration: str
|
|
57
|
+
budget_reset_at: datetime | None = None
|
|
58
|
+
provider_sync_status: str
|
|
59
|
+
member_count: int
|
|
60
|
+
allocated_member_budget_total: float
|
|
61
|
+
current_spending: float | None = None
|
|
62
|
+
|
|
63
|
+
|
|
46
64
|
class ProjectListItem(BaseModel):
|
|
47
65
|
"""Project list response item."""
|
|
48
66
|
|
|
@@ -58,6 +76,8 @@ class ProjectListItem(BaseModel):
|
|
|
58
76
|
counters: ProjectCounters | None = None
|
|
59
77
|
cost_center_id: UUID | None = None
|
|
60
78
|
cost_center_name: str | None = None
|
|
79
|
+
spending: float | None = None
|
|
80
|
+
budgets: list[ProjectBudgetItem] = []
|
|
61
81
|
|
|
62
82
|
|
|
63
83
|
class PaginationInfo(BaseModel):
|
|
@@ -133,6 +153,7 @@ class ProjectUpdateRequest(BaseModel):
|
|
|
133
153
|
description: str | None = None
|
|
134
154
|
cost_center_id: UUID | None = None
|
|
135
155
|
clear_cost_center: bool = False
|
|
156
|
+
project_member_budget_tracking_enabled: bool | None = None
|
|
136
157
|
|
|
137
158
|
|
|
138
159
|
class ProjectDeleteResponse(BaseModel):
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from enum import Enum
|
|
5
|
+
from typing import Any, Literal
|
|
5
6
|
|
|
6
7
|
from pydantic import BaseModel, ConfigDict, Field
|
|
7
8
|
|
|
@@ -122,3 +123,90 @@ class SkillReactionResponse(BaseModel):
|
|
|
122
123
|
reaction: str
|
|
123
124
|
reaction_at: str = Field(alias="reactionAt")
|
|
124
125
|
resource_type: str | None = Field(None, alias="resourceType")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class SkillPagination(BaseModel):
|
|
129
|
+
"""Shared pagination envelope for skills statistics endpoints."""
|
|
130
|
+
|
|
131
|
+
model_config = ConfigDict(extra="ignore")
|
|
132
|
+
|
|
133
|
+
page: int
|
|
134
|
+
per_page: int
|
|
135
|
+
total: int
|
|
136
|
+
pages: int
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class SkillEventRequest(BaseModel):
|
|
140
|
+
"""Request body for POST /v1/skills/events."""
|
|
141
|
+
|
|
142
|
+
session_id: str
|
|
143
|
+
command: Literal["add", "update", "remove", "list", "find"]
|
|
144
|
+
status: Literal["started", "completed", "failed"]
|
|
145
|
+
scope: Literal["global", "project", "unknown"] | None = None
|
|
146
|
+
error_code: str | None = None
|
|
147
|
+
agent_selection_mode: (
|
|
148
|
+
Literal["explicit", "auto_detected", "prompted", "upstream"] | None
|
|
149
|
+
) = None
|
|
150
|
+
target_agents: list[str] | None = None
|
|
151
|
+
source: str | None = None
|
|
152
|
+
skill_name: str | None = None
|
|
153
|
+
skill_slug: str | None = None
|
|
154
|
+
skill_id: str | None = None
|
|
155
|
+
agent: str = "codemie-skills"
|
|
156
|
+
agent_version: str | None = None
|
|
157
|
+
repository: str | None = None
|
|
158
|
+
branch: str | None = None
|
|
159
|
+
project: str | None = None
|
|
160
|
+
attributes: dict[str, Any] | None = None
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class SkillEventItem(BaseModel):
|
|
164
|
+
"""Single row from the raw event log."""
|
|
165
|
+
|
|
166
|
+
model_config = ConfigDict(extra="ignore")
|
|
167
|
+
|
|
168
|
+
skill_slug: str | None = None
|
|
169
|
+
source: str | None = None
|
|
170
|
+
target_agents: list[str] = Field(default_factory=list)
|
|
171
|
+
date: datetime
|
|
172
|
+
command: str
|
|
173
|
+
user_id: str
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class SkillEventsPaginatedResponse(BaseModel):
|
|
177
|
+
"""Paginated response from GET /v1/skills/events."""
|
|
178
|
+
|
|
179
|
+
model_config = ConfigDict(extra="ignore")
|
|
180
|
+
|
|
181
|
+
data: list[SkillEventItem]
|
|
182
|
+
pagination: SkillPagination
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
class SkillStatsItem(BaseModel):
|
|
186
|
+
"""Per-skill aggregated stats item."""
|
|
187
|
+
|
|
188
|
+
model_config = ConfigDict(extra="ignore")
|
|
189
|
+
|
|
190
|
+
skill_slug: str | None = None
|
|
191
|
+
installs: int
|
|
192
|
+
removals: int
|
|
193
|
+
by_agent: dict[str, int] = Field(default_factory=dict)
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class SkillStatsPaginatedResponse(BaseModel):
|
|
197
|
+
"""Paginated response from GET /v1/skills/events/stats."""
|
|
198
|
+
|
|
199
|
+
model_config = ConfigDict(extra="ignore")
|
|
200
|
+
|
|
201
|
+
data: list[SkillStatsItem]
|
|
202
|
+
pagination: SkillPagination
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
class SingleSkillStatsResponse(BaseModel):
|
|
206
|
+
"""Response from GET /v1/skills/events/{slug}/stats."""
|
|
207
|
+
|
|
208
|
+
model_config = ConfigDict(extra="ignore")
|
|
209
|
+
|
|
210
|
+
installs: int
|
|
211
|
+
removals: int
|
|
212
|
+
by_agent: dict[str, int] = Field(default_factory=dict)
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""Admin service implementation."""
|
|
2
|
+
|
|
3
|
+
from ..models.admin import (
|
|
4
|
+
AdminUserListItem,
|
|
5
|
+
AdminUserListResponse,
|
|
6
|
+
ApplicationsListResponse,
|
|
7
|
+
ApplicationCreateRequest,
|
|
8
|
+
ApplicationCreateResponse,
|
|
9
|
+
LocalUserCreateRequest,
|
|
10
|
+
LocalUserDetail,
|
|
11
|
+
)
|
|
12
|
+
from ..utils import ApiRequestHandler, TokenSource
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class AdminService:
|
|
16
|
+
"""Service for managing CodeMie applications/projects."""
|
|
17
|
+
|
|
18
|
+
def __init__(self, api_domain: str, token: TokenSource, verify_ssl: bool = True):
|
|
19
|
+
"""Initialize the admin service.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
api_domain: Base URL for the CodeMie API
|
|
23
|
+
token: Authentication token
|
|
24
|
+
verify_ssl: Whether to verify SSL certificates
|
|
25
|
+
"""
|
|
26
|
+
self._api = ApiRequestHandler(api_domain, token, verify_ssl)
|
|
27
|
+
|
|
28
|
+
def list_applications(self, project_name: str | None = None) -> list[str]:
|
|
29
|
+
"""Get list of all applications/projects.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
project_name: Optional project name to filter by
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
List of application names
|
|
36
|
+
"""
|
|
37
|
+
params = {}
|
|
38
|
+
if project_name:
|
|
39
|
+
params["search"] = project_name
|
|
40
|
+
|
|
41
|
+
response = self._api.get(
|
|
42
|
+
"/v1/admin/applications",
|
|
43
|
+
ApplicationsListResponse,
|
|
44
|
+
params=params if params else None,
|
|
45
|
+
)
|
|
46
|
+
return response.applications
|
|
47
|
+
|
|
48
|
+
def create_application(self, request: ApplicationCreateRequest) -> str:
|
|
49
|
+
"""Create a new application/project.
|
|
50
|
+
|
|
51
|
+
Args:
|
|
52
|
+
request: Application creation request
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
Created application name
|
|
56
|
+
"""
|
|
57
|
+
response = self._api.post(
|
|
58
|
+
"/v1/admin/application",
|
|
59
|
+
ApplicationCreateResponse,
|
|
60
|
+
json_data=request.model_dump(exclude_none=True),
|
|
61
|
+
)
|
|
62
|
+
return response.message
|
|
63
|
+
|
|
64
|
+
def create_local_user(
|
|
65
|
+
self,
|
|
66
|
+
email: str,
|
|
67
|
+
username: str,
|
|
68
|
+
password: str,
|
|
69
|
+
name: str | None = None,
|
|
70
|
+
is_admin: bool = False,
|
|
71
|
+
is_maintainer: bool = False,
|
|
72
|
+
) -> LocalUserDetail:
|
|
73
|
+
"""Create a user via the admin API (local auth mode only).
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
email: User email address
|
|
77
|
+
username: Username (3-50 chars)
|
|
78
|
+
password: Initial password
|
|
79
|
+
name: Optional display name
|
|
80
|
+
is_admin: Grant admin role
|
|
81
|
+
is_maintainer: Grant maintainer role
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Created user details
|
|
85
|
+
"""
|
|
86
|
+
request = LocalUserCreateRequest(
|
|
87
|
+
email=email,
|
|
88
|
+
username=username,
|
|
89
|
+
password=password,
|
|
90
|
+
name=name,
|
|
91
|
+
is_admin=is_admin,
|
|
92
|
+
is_maintainer=is_maintainer,
|
|
93
|
+
)
|
|
94
|
+
return self._api.post(
|
|
95
|
+
"/v1/admin/users",
|
|
96
|
+
LocalUserDetail,
|
|
97
|
+
json_data=request.model_dump(exclude_none=True),
|
|
98
|
+
wrap_response=False,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
def list_users(
|
|
102
|
+
self,
|
|
103
|
+
search: str | None = None,
|
|
104
|
+
page: int = 0,
|
|
105
|
+
per_page: int = 20,
|
|
106
|
+
) -> list[AdminUserListItem]:
|
|
107
|
+
"""List users via the admin API.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
search: Search string matched against email, username, name
|
|
111
|
+
page: 0-indexed page number
|
|
112
|
+
per_page: Page size
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
List of user items
|
|
116
|
+
"""
|
|
117
|
+
params: dict = {"page": page, "per_page": per_page}
|
|
118
|
+
if search:
|
|
119
|
+
params["search"] = search
|
|
120
|
+
response = self._api.get(
|
|
121
|
+
"/v1/admin/users",
|
|
122
|
+
AdminUserListResponse,
|
|
123
|
+
params=params,
|
|
124
|
+
wrap_response=False,
|
|
125
|
+
)
|
|
126
|
+
return response.users
|
|
127
|
+
|
|
128
|
+
def delete_user(self, user_id: str) -> None:
|
|
129
|
+
"""Deactivate (soft-delete) a user via the admin API.
|
|
130
|
+
|
|
131
|
+
Args:
|
|
132
|
+
user_id: ID of the user to deactivate
|
|
133
|
+
"""
|
|
134
|
+
self._api.delete(
|
|
135
|
+
f"/v1/admin/users/{user_id}",
|
|
136
|
+
dict,
|
|
137
|
+
wrap_response=False,
|
|
138
|
+
)
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/project.py
RENAMED
|
@@ -86,6 +86,7 @@ class ProjectService:
|
|
|
86
86
|
page: int = 0,
|
|
87
87
|
per_page: int = 20,
|
|
88
88
|
include_counters: bool = True,
|
|
89
|
+
include_budgets: bool = False,
|
|
89
90
|
sort_by: Literal["name", "created_at"] | None = None,
|
|
90
91
|
sort_order: Literal["asc", "desc"] = "asc",
|
|
91
92
|
) -> PaginatedProjectListResponse:
|
|
@@ -105,6 +106,7 @@ class ProjectService:
|
|
|
105
106
|
"page": page,
|
|
106
107
|
"per_page": per_page,
|
|
107
108
|
"include_counters": include_counters,
|
|
109
|
+
"include_budgets": include_budgets,
|
|
108
110
|
"sort_order": sort_order,
|
|
109
111
|
}
|
|
110
112
|
|
|
@@ -147,6 +149,7 @@ class ProjectService:
|
|
|
147
149
|
description: str | None = None,
|
|
148
150
|
cost_center_id: UUID | None = None,
|
|
149
151
|
clear_cost_center: bool = False,
|
|
152
|
+
project_member_budget_tracking_enabled: bool | None = None,
|
|
150
153
|
) -> ProjectUpdateResponse:
|
|
151
154
|
"""Update a project.
|
|
152
155
|
|
|
@@ -168,6 +171,7 @@ class ProjectService:
|
|
|
168
171
|
description=description,
|
|
169
172
|
cost_center_id=cost_center_id,
|
|
170
173
|
clear_cost_center=clear_cost_center,
|
|
174
|
+
project_member_budget_tracking_enabled=project_member_budget_tracking_enabled,
|
|
171
175
|
)
|
|
172
176
|
|
|
173
177
|
return self._api.patch(
|
|
@@ -11,10 +11,14 @@ from ..models.skill import (
|
|
|
11
11
|
SkillCategory,
|
|
12
12
|
SkillCreateRequest,
|
|
13
13
|
SkillDetailResponse,
|
|
14
|
+
SkillEventItem,
|
|
15
|
+
SkillEventRequest,
|
|
14
16
|
SkillImportRequest,
|
|
15
17
|
SkillListPaginatedResponse,
|
|
16
18
|
SkillListResponse,
|
|
19
|
+
SkillStatsItem,
|
|
17
20
|
SkillUpdateRequest,
|
|
21
|
+
SingleSkillStatsResponse,
|
|
18
22
|
)
|
|
19
23
|
from ..utils.http import ApiRequestHandler, TokenSource
|
|
20
24
|
|
|
@@ -302,3 +306,85 @@ class SkillService:
|
|
|
302
306
|
Removal confirmation
|
|
303
307
|
"""
|
|
304
308
|
return self._api.delete(f"/v1/skills/{skill_id}/reactions", dict)
|
|
309
|
+
|
|
310
|
+
# Statistics / Event Log
|
|
311
|
+
|
|
312
|
+
def record_event(self, request: SkillEventRequest) -> dict:
|
|
313
|
+
"""Record a skill lifecycle event.
|
|
314
|
+
|
|
315
|
+
Args:
|
|
316
|
+
request: Skill event request
|
|
317
|
+
|
|
318
|
+
Returns:
|
|
319
|
+
Confirmation dict
|
|
320
|
+
"""
|
|
321
|
+
return self._api.post(
|
|
322
|
+
"/v1/skills/events",
|
|
323
|
+
dict,
|
|
324
|
+
json_data=request.model_dump(exclude_none=True),
|
|
325
|
+
)
|
|
326
|
+
|
|
327
|
+
def get_events(
|
|
328
|
+
self,
|
|
329
|
+
from_: str | None = None,
|
|
330
|
+
to: str | None = None,
|
|
331
|
+
limit: int = 100,
|
|
332
|
+
offset: int = 0,
|
|
333
|
+
) -> list[SkillEventItem]:
|
|
334
|
+
"""Get raw skill event log.
|
|
335
|
+
|
|
336
|
+
Args:
|
|
337
|
+
from_: ISO datetime lower bound (inclusive)
|
|
338
|
+
to: ISO datetime upper bound (inclusive)
|
|
339
|
+
limit: Maximum number of results
|
|
340
|
+
offset: Pagination offset
|
|
341
|
+
|
|
342
|
+
Returns:
|
|
343
|
+
List of skill event items
|
|
344
|
+
"""
|
|
345
|
+
params: dict[str, Any] = {"limit": limit, "offset": offset}
|
|
346
|
+
if from_ is not None:
|
|
347
|
+
params["from"] = from_
|
|
348
|
+
if to is not None:
|
|
349
|
+
params["to"] = to
|
|
350
|
+
return self._api.get("/v1/skills/events", list[SkillEventItem], params=params)
|
|
351
|
+
|
|
352
|
+
def get_events_stats(
|
|
353
|
+
self,
|
|
354
|
+
from_: str | None = None,
|
|
355
|
+
to: str | None = None,
|
|
356
|
+
limit: int = 100,
|
|
357
|
+
offset: int = 0,
|
|
358
|
+
) -> list[SkillStatsItem]:
|
|
359
|
+
"""Get per-skill aggregated install/removal counts.
|
|
360
|
+
|
|
361
|
+
Args:
|
|
362
|
+
from_: ISO datetime lower bound (inclusive)
|
|
363
|
+
to: ISO datetime upper bound (inclusive)
|
|
364
|
+
limit: Maximum number of results
|
|
365
|
+
offset: Pagination offset
|
|
366
|
+
|
|
367
|
+
Returns:
|
|
368
|
+
List of skill stats items
|
|
369
|
+
"""
|
|
370
|
+
params: dict[str, Any] = {"limit": limit, "offset": offset}
|
|
371
|
+
if from_ is not None:
|
|
372
|
+
params["from"] = from_
|
|
373
|
+
if to is not None:
|
|
374
|
+
params["to"] = to
|
|
375
|
+
return self._api.get(
|
|
376
|
+
"/v1/skills/events/stats", list[SkillStatsItem], params=params
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
def get_skill_stats(self, slug: str) -> SingleSkillStatsResponse:
|
|
380
|
+
"""Get aggregated stats for a single skill.
|
|
381
|
+
|
|
382
|
+
Args:
|
|
383
|
+
slug: Skill slug identifier
|
|
384
|
+
|
|
385
|
+
Returns:
|
|
386
|
+
Single skill stats
|
|
387
|
+
"""
|
|
388
|
+
return self._api.get(
|
|
389
|
+
f"/v1/skills/events/{slug}/stats", SingleSkillStatsResponse
|
|
390
|
+
)
|
|
@@ -86,7 +86,7 @@ class ApiRequestHandler:
|
|
|
86
86
|
headers["Content-Type"] = "application/json"
|
|
87
87
|
|
|
88
88
|
if include_auth:
|
|
89
|
-
if self._is_localhost:
|
|
89
|
+
if self._is_localhost and not self._token:
|
|
90
90
|
headers["Authorization"] = "dev-codemie-user"
|
|
91
91
|
else:
|
|
92
92
|
token_value = self._token() if callable(self._token) else self._token
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
"""Admin models for managing applications/projects."""
|
|
2
|
-
|
|
3
|
-
from pydantic import BaseModel, ConfigDict, Field
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class ApplicationsListResponse(BaseModel):
|
|
7
|
-
"""Response model for list applications endpoint."""
|
|
8
|
-
|
|
9
|
-
model_config = ConfigDict(extra="ignore")
|
|
10
|
-
|
|
11
|
-
applications: list[str] = Field(..., description="List of application names")
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class ApplicationCreateRequest(BaseModel):
|
|
15
|
-
"""Request model for creating an application/project."""
|
|
16
|
-
|
|
17
|
-
model_config = ConfigDict(extra="ignore")
|
|
18
|
-
|
|
19
|
-
name: str = Field(..., description="Application/project name")
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class ApplicationCreateResponse(BaseModel):
|
|
23
|
-
"""Response model for create application endpoint."""
|
|
24
|
-
|
|
25
|
-
model_config = ConfigDict(extra="ignore")
|
|
26
|
-
|
|
27
|
-
message: str = Field(..., description="Created application name")
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
"""Admin service implementation."""
|
|
2
|
-
|
|
3
|
-
from ..models.admin import (
|
|
4
|
-
ApplicationsListResponse,
|
|
5
|
-
ApplicationCreateRequest,
|
|
6
|
-
ApplicationCreateResponse,
|
|
7
|
-
)
|
|
8
|
-
from ..utils import ApiRequestHandler, TokenSource
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class AdminService:
|
|
12
|
-
"""Service for managing CodeMie applications/projects."""
|
|
13
|
-
|
|
14
|
-
def __init__(self, api_domain: str, token: TokenSource, verify_ssl: bool = True):
|
|
15
|
-
"""Initialize the admin service.
|
|
16
|
-
|
|
17
|
-
Args:
|
|
18
|
-
api_domain: Base URL for the CodeMie API
|
|
19
|
-
token: Authentication token
|
|
20
|
-
verify_ssl: Whether to verify SSL certificates
|
|
21
|
-
"""
|
|
22
|
-
self._api = ApiRequestHandler(api_domain, token, verify_ssl)
|
|
23
|
-
|
|
24
|
-
def list_applications(self, project_name: str | None = None) -> list[str]:
|
|
25
|
-
"""Get list of all applications/projects.
|
|
26
|
-
|
|
27
|
-
Args:
|
|
28
|
-
project_name: Optional project name to filter by
|
|
29
|
-
|
|
30
|
-
Returns:
|
|
31
|
-
List of application names
|
|
32
|
-
"""
|
|
33
|
-
params = {}
|
|
34
|
-
if project_name:
|
|
35
|
-
params["search"] = project_name
|
|
36
|
-
|
|
37
|
-
response = self._api.get(
|
|
38
|
-
"/v1/admin/applications",
|
|
39
|
-
ApplicationsListResponse,
|
|
40
|
-
params=params if params else None,
|
|
41
|
-
)
|
|
42
|
-
return response.applications
|
|
43
|
-
|
|
44
|
-
def create_application(self, request: ApplicationCreateRequest) -> str:
|
|
45
|
-
"""Create a new application/project.
|
|
46
|
-
|
|
47
|
-
Args:
|
|
48
|
-
request: Application creation request
|
|
49
|
-
|
|
50
|
-
Returns:
|
|
51
|
-
Created application name
|
|
52
|
-
"""
|
|
53
|
-
response = self._api.post(
|
|
54
|
-
"/v1/admin/application",
|
|
55
|
-
ApplicationCreateResponse,
|
|
56
|
-
json_data=request.model_dump(exclude_none=True),
|
|
57
|
-
)
|
|
58
|
-
return response.message
|
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/client/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/__init__.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/analytics.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/assistant.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/categories.py
RENAMED
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/conversation.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/file_operation.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/guardrails.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/integration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/vendor_assistant.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/vendor_guardrail.py
RENAMED
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/vendor_workflow.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/workflow.py
RENAMED
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/models/workflow_state.py
RENAMED
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/analytics.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/assistant.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/categories.py
RENAMED
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/conversation.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/datasource.py
RENAMED
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/integration.py
RENAMED
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/mermaid.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/webhook.py
RENAMED
|
File without changes
|
{codemie_sdk_python-0.1.433 → codemie_sdk_python-0.1.435}/src/codemie_sdk/services/workflow.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|