codemie-sdk-python 0.1.22__py3-none-any.whl → 0.1.28__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.

Potentially problematic release.


This version of codemie-sdk-python might be problematic. Click here for more details.

@@ -3,9 +3,9 @@
3
3
  import uuid
4
4
  from datetime import datetime
5
5
  from enum import Enum
6
- from typing import List, Optional, Any, Union
6
+ from typing import List, Optional, Any, Union, Dict
7
7
 
8
- from pydantic import BaseModel, Field, ConfigDict
8
+ from pydantic import BaseModel, Field, ConfigDict, model_validator
9
9
 
10
10
  from .common import User
11
11
  from .integration import Integration
@@ -171,6 +171,28 @@ class ChatMessage(BaseModel):
171
171
  message: Optional[str] = Field(default="")
172
172
 
173
173
 
174
+ class ToolConfig(BaseModel):
175
+ name: str
176
+ tool_creds: Optional[Dict[str, Any]] = None
177
+ integration_id: Optional[str] = None
178
+
179
+ @model_validator(mode="after")
180
+ def validate_credentials_provided(self) -> "ToolConfig":
181
+ """
182
+ Validate that either tool_creds or integration_id is provided.
183
+
184
+ At least one of these fields must be specified for the tool configuration
185
+ to be valid. This ensures that the tool has a way to obtain credentials.
186
+ """
187
+ if not self.tool_creds and not self.integration_id:
188
+ raise ValueError("Either tool_creds or integration_id must be provided")
189
+ if self.tool_creds and self.integration_id:
190
+ raise ValueError(
191
+ "Either tool_creds or integration_id must be provided, but not both"
192
+ )
193
+ return self
194
+
195
+
174
196
  class AssistantChatRequest(BaseModel):
175
197
  """Model for chat request to assistant."""
176
198
 
@@ -197,6 +219,7 @@ class AssistantChatRequest(BaseModel):
197
219
  metadata: Optional[dict[str, Any]] = Field(
198
220
  default=None, description="Provide additional metadata"
199
221
  )
222
+ tools_config: Optional[List[ToolConfig]] = None
200
223
 
201
224
 
202
225
  class BaseModelResponse(BaseModel):
@@ -1,7 +1,7 @@
1
1
  import re
2
2
  from datetime import datetime
3
3
  from enum import Enum
4
- from typing import Optional, List, Union
4
+ from typing import Optional, List, Union, Tuple
5
5
 
6
6
  from pydantic import BaseModel, Field, model_validator, ConfigDict, field_validator
7
7
 
@@ -71,13 +71,23 @@ class Jira(BaseModel):
71
71
 
72
72
 
73
73
  class Google(BaseModel):
74
- """Model for Jira-specific response fields"""
74
+ """Model for Google-specific response fields"""
75
75
 
76
76
  google_doc: str = Field(None, alias="googleDoc")
77
77
 
78
78
  model_config = ConfigDict(extra="ignore")
79
79
 
80
80
 
81
+ class File(BaseModel):
82
+ """Model for File-specific response fields"""
83
+
84
+ files: Optional[List[Tuple[str, bytes, str]]] = (
85
+ None # (filename, content, mime_type)
86
+ )
87
+
88
+ model_config = ConfigDict(extra="ignore")
89
+
90
+
81
91
  class Code(BaseModel):
82
92
  """Model for code repository datasource creation"""
83
93
 
@@ -171,6 +181,13 @@ class GoogleDataSourceRequest(BaseDataSourceRequest, Google):
171
181
  return ["google_doc"]
172
182
 
173
183
 
184
+ class FileDataSourceRequest(BaseDataSourceRequest):
185
+ """Model for File datasource creation requests"""
186
+
187
+ def __init__(self, **data):
188
+ super().__init__(type=DataSourceType.FILE, **data)
189
+
190
+
174
191
  class BaseUpdateDataSourceRequest(BaseDataSourceRequest):
175
192
  """Mixin update-specific reindex fields"""
176
193
 
@@ -234,6 +251,13 @@ class UpdateGoogleDataSourceRequest(BaseUpdateDataSourceRequest):
234
251
  super().__init__(type=DataSourceType.GOOGLE, **data)
235
252
 
236
253
 
254
+ class UpdateFileDataSourceRequest(BaseUpdateDataSourceRequest):
255
+ """Model for File datasource updates"""
256
+
257
+ def __init__(self, **data):
258
+ super().__init__(type=DataSourceType.FILE, **data)
259
+
260
+
237
261
  class DataSource(BaseModel):
238
262
  model_config = ConfigDict(
239
263
  extra="ignore",
@@ -293,5 +317,6 @@ class DataSource(BaseModel):
293
317
  "summarization_prompt": values.get("prompt"),
294
318
  "summarization_model": values.get("summarization_model"),
295
319
  "summarization_docs_generation": values.get("docs_generation"),
320
+ "embeddings_model": values.get("embeddings_model"),
296
321
  }
297
322
  return values
@@ -1,7 +1,8 @@
1
1
  """DataSource service implementation."""
2
2
 
3
3
  import json
4
- from typing import Literal, List
4
+ from typing import Literal, List, Union, Tuple
5
+ from pathlib import Path
5
6
 
6
7
  from ..models.common import PaginationParams
7
8
  from ..models.datasource import (
@@ -12,6 +13,7 @@ from ..models.datasource import (
12
13
  CodeDataSourceRequest,
13
14
  UpdateCodeDataSourceRequest,
14
15
  BaseUpdateDataSourceRequest,
16
+ FileDataSourceRequest,
15
17
  )
16
18
  from ..utils import ApiRequestHandler
17
19
 
@@ -50,6 +52,71 @@ class DatasourceService:
50
52
  json_data=request.model_dump(by_alias=True, exclude_none=True),
51
53
  )
52
54
 
55
+ def create_file_datasource(
56
+ self,
57
+ request: FileDataSourceRequest,
58
+ files: List[Union[str, Tuple[str, bytes, str]]],
59
+ ) -> dict:
60
+ """Create a new file datasource with file uploads.
61
+
62
+ Args:
63
+ request: File datasource creation request
64
+ files: List of files to upload. Each item can be:
65
+ - str: file path (will read file and detect MIME type)
66
+ - Tuple[str, bytes, str]: (filename, content, mime_type)
67
+
68
+ Returns:
69
+ dict: Response from the server containing operation status
70
+ """
71
+ endpoint = "/v1/index/knowledge_base/file"
72
+
73
+ # Prepare multipart form data
74
+ params = request.model_dump(by_alias=True, exclude_none=True)
75
+ file_uploads = []
76
+
77
+ for file_item in files:
78
+ if isinstance(file_item, str):
79
+ # File path provided - read file and detect MIME type
80
+ file_path = Path(file_item)
81
+ with open(file_path, "rb") as f:
82
+ content = f.read()
83
+
84
+ # Basic MIME type detection
85
+ mime_type = self._detect_mime_type(file_path)
86
+ file_uploads.append(("files", (file_path.name, content, mime_type)))
87
+
88
+ elif isinstance(file_item, tuple) and len(file_item) == 3:
89
+ # (filename, content, mime_type) tuple provided
90
+ filename, content, mime_type = file_item
91
+ file_uploads.append(("files", (filename, content, mime_type)))
92
+
93
+ else:
94
+ raise ValueError(
95
+ "Each file must be either a file path (str) or a tuple of (filename, content, mime_type)"
96
+ )
97
+
98
+ return self._api.post_multipart(
99
+ endpoint, dict, params=params, files=file_uploads
100
+ )
101
+
102
+ @staticmethod
103
+ def _detect_mime_type(file_path: Path) -> str:
104
+ """Detect MIME type based on file extension."""
105
+ extension = file_path.suffix.lower()
106
+ mime_types = {
107
+ ".txt": "text/plain",
108
+ ".csv": "text/csv",
109
+ ".json": "application/json",
110
+ ".yaml": "application/x-yaml",
111
+ ".yml": "application/x-yaml",
112
+ ".xml": "application/xml",
113
+ ".pdf": "application/pdf",
114
+ ".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
115
+ ".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
116
+ ".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
117
+ }
118
+ return mime_types.get(extension, "application/octet-stream")
119
+
53
120
  def update(self, datasource_id: str, request: BaseUpdateDataSourceRequest) -> dict:
54
121
  """Update an existing datasource.
55
122
 
codemie_sdk/utils/http.py CHANGED
@@ -46,9 +46,16 @@ class ApiRequestHandler:
46
46
  self._token = token
47
47
  self._verify_ssl = verify_ssl
48
48
 
49
- def _get_headers(self) -> dict:
50
- """Gets request headers with auth token."""
51
- headers = {"Content-Type": "application/json"}
49
+ def _get_headers(self, exclude_content_type: bool = False) -> dict:
50
+ """Gets request headers with auth token.
51
+
52
+ Args:
53
+ exclude_content_type: Whether to exclude Content-Type header (for multipart requests)
54
+ """
55
+ headers = {}
56
+ if not exclude_content_type:
57
+ headers["Content-Type"] = "application/json"
58
+
52
59
  if (
53
60
  "0.0.0.0" in self._base_url
54
61
  or "127.0.0.1" in self._base_url
@@ -176,6 +183,44 @@ class ApiRequestHandler:
176
183
 
177
184
  return self._parse_response(response, response_model, wrap_response)
178
185
 
186
+ @log_request
187
+ def post_multipart(
188
+ self,
189
+ endpoint: str,
190
+ response_model: Type[T],
191
+ params: Optional[Dict[str, Any]] = None,
192
+ data: Optional[Dict[str, Any]] = None,
193
+ files: Optional[List] = None,
194
+ wrap_response: bool = True,
195
+ ) -> T:
196
+ """Makes a POST multipart/form-data request and parses the response.
197
+
198
+ Args:
199
+ endpoint: API endpoint path
200
+ response_model: Pydantic model class or List[Model] for response
201
+ params: Url parameters
202
+ data: Data to be sent as multipart/form-data
203
+ files: List of file tuples for upload
204
+ wrap_response: Whether response is wrapped in 'data' field
205
+
206
+ Returns:
207
+ Parsed response object or list of objects
208
+ """
209
+
210
+ response = requests.post(
211
+ url=f"{self._base_url}{endpoint}",
212
+ headers=self._get_headers(
213
+ exclude_content_type=True
214
+ ), # Let requests set multipart content-type
215
+ params=params,
216
+ data=data,
217
+ files=files,
218
+ verify=self._verify_ssl,
219
+ )
220
+ response.raise_for_status()
221
+
222
+ return self._parse_response(response, response_model, wrap_response)
223
+
179
224
  @log_request
180
225
  def put(
181
226
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codemie-sdk-python
3
- Version: 0.1.22
3
+ Version: 0.1.28
4
4
  Summary: CodeMie SDK for Python
5
5
  Author: Vadym Vlasenko
6
6
  Author-email: vadym_vlasenko@epam.com
@@ -4,9 +4,9 @@ codemie_sdk/auth/credentials.py,sha256=u2eLNsD8fELTgreQghVb0g0kk82zchUkux0M5lzq-
4
4
  codemie_sdk/client/__init__.py,sha256=yf6C39MmrJ6gK9ZHMhBeynKwUUYVSUTQbKxU8-4qpKg,101
5
5
  codemie_sdk/client/client.py,sha256=dVcWqd-ruWd8GOZ3_33C3LnHgUyyxIoCKxKYPYbBPq8,4373
6
6
  codemie_sdk/exceptions.py,sha256=XoVPyognx-JmyVxLHkZPAcX1CMi1OoT1diBFJLU54so,1183
7
- codemie_sdk/models/assistant.py,sha256=nmvA302yHpSw0iwhdrkRHT1dOsz2smlTYCWa7CItNsM,6568
7
+ codemie_sdk/models/assistant.py,sha256=RCVuYcKI_DzGyObJ3e1l4rrcVev-1Hq7crW9XY5pvus,7479
8
8
  codemie_sdk/models/common.py,sha256=V4sJCzwFTF8BPlrd2OKI44Em5HmPmn2Nm8fQNsnBZ_Q,1128
9
- codemie_sdk/models/datasource.py,sha256=Iun6O76o4m-_jbyyumMndpyr4OiN0lwqKb8u5AOTHdM,10037
9
+ codemie_sdk/models/datasource.py,sha256=BrwMG8NLVwNtsJZunXT2HPc9oI-r8rpmc5OrdYHQqkA,10746
10
10
  codemie_sdk/models/integration.py,sha256=F1YBdCK1w5W_jKK8prEsg7A00NghkEBvJgkkr8KpC6w,1764
11
11
  codemie_sdk/models/llm.py,sha256=ppb9-1dx1UFhRuJpSR3ij7H6Pfhe9nO4C4BEOIbToy4,1192
12
12
  codemie_sdk/models/task.py,sha256=J4ZFRY3s8qBGrqB5NLQF0rMbInLh4s7OEZ0ZfmnW0Ho,1476
@@ -14,7 +14,7 @@ codemie_sdk/models/user.py,sha256=Q0rjimZh-IbeaPfq6b6fk6ZaCtwLqWHEIlU863suCS4,17
14
14
  codemie_sdk/models/workflow.py,sha256=CyK-kBnOck2KiRX3gmWF_mcGtqxsGXH3FS3jwYbpz_A,2327
15
15
  codemie_sdk/models/workflow_state.py,sha256=CMYFQZ7sy4QxmnWmc83TFfqP7TG_3rW5MdH5fxsS9kY,1251
16
16
  codemie_sdk/services/assistant.py,sha256=-U5YpqOyKlVplSRPrnDItG8TUpg9qqhO6-F7c7Rz2xU,5110
17
- codemie_sdk/services/datasource.py,sha256=hYH__M5LD33dfh7CCS7HYmEn8izsGkO0nfVa-dpoj6w,5118
17
+ codemie_sdk/services/datasource.py,sha256=2LikRr_V-hgnflMjgbxydHugRMP1eO8_aI33DrVeXQ8,7834
18
18
  codemie_sdk/services/integration.py,sha256=vJnSkXk2C2l0ahX2SUsuA7fKhY2hTuAByynx5Lgh7Ls,4864
19
19
  codemie_sdk/services/llm.py,sha256=0-e4_7RvLHs2giCyoQ5U4KDTh6p5VXgPKNxnDP9ZDFU,1100
20
20
  codemie_sdk/services/task.py,sha256=3e9t8_LMkR4xfeMBwMCo7ZF87PxPS-ZbzDg85ilda2M,1031
@@ -23,7 +23,7 @@ codemie_sdk/services/workflow.py,sha256=aOV13WrFAqMXOPd2jVHbEhg3fpezk4XWo382D5aW
23
23
  codemie_sdk/services/workflow_execution.py,sha256=aGoT3rdTmh5-doAsrmBBjLEuOfvL5aqeo3g9th1_aAw,3647
24
24
  codemie_sdk/services/workflow_execution_state.py,sha256=tXoaa8yT09xgYEUNiHhVULe76TwGwVgZupMIUyyLxdo,2070
25
25
  codemie_sdk/utils/__init__.py,sha256=BXAJJfAzO89-kMYvWWo9wSNhSbGgF3vB1In9sePFhMM,109
26
- codemie_sdk/utils/http.py,sha256=JfyX4gP-grQUI795QL0DJ72aBkiqNd1fs31fUqtSnYE,7757
27
- codemie_sdk_python-0.1.22.dist-info/METADATA,sha256=cH8AVifYpaYU7UjghY6i1VVnwbg3kpCwS5jWLXGo0W0,21614
28
- codemie_sdk_python-0.1.22.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
29
- codemie_sdk_python-0.1.22.dist-info/RECORD,,
26
+ codemie_sdk/utils/http.py,sha256=FWU56W_-vBGbHfX1EC1zsoRjDoNCyNK2HCdNb4IkQVc,9233
27
+ codemie_sdk_python-0.1.28.dist-info/METADATA,sha256=BqZfGZdKdxn7RN5CX_9Eny6H1Na3_e9oedfeBlW5C6E,21614
28
+ codemie_sdk_python-0.1.28.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
29
+ codemie_sdk_python-0.1.28.dist-info/RECORD,,