dimo-python-sdk 1.6.0__tar.gz → 1.7.2__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.
Files changed (36) hide show
  1. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/PKG-INFO +25 -3
  2. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/README.md +23 -1
  3. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/api/__init__.py +2 -0
  4. dimo_python_sdk-1.7.2/dimo/api/conversations.py +343 -0
  5. dimo_python_sdk-1.7.2/dimo/api/fetch.py +123 -0
  6. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/dimo.py +4 -0
  7. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/environments.py +4 -0
  8. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo_python_sdk.egg-info/PKG-INFO +25 -3
  9. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo_python_sdk.egg-info/SOURCES.txt +3 -0
  10. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/pyproject.toml +2 -1
  11. dimo_python_sdk-1.7.2/tests/test_conversations.py +693 -0
  12. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/LICENSE +0 -0
  13. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/__init__.py +0 -0
  14. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/api/attestation.py +0 -0
  15. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/api/auth.py +0 -0
  16. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/api/device_definitions.py +0 -0
  17. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/api/token_exchange.py +0 -0
  18. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/api/trips.py +0 -0
  19. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/api/valuations.py +0 -0
  20. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/api/vehicle_triggers.py +0 -0
  21. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/constants.py +0 -0
  22. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/errors.py +0 -0
  23. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/eth_signer.py +0 -0
  24. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/graphql/__init__.py +0 -0
  25. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/graphql/identity.py +0 -0
  26. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/graphql/telemetry.py +0 -0
  27. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/permission_decoder.py +0 -0
  28. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo/request.py +0 -0
  29. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo_python_sdk.egg-info/dependency_links.txt +0 -0
  30. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo_python_sdk.egg-info/requires.txt +0 -0
  31. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/dimo_python_sdk.egg-info/top_level.txt +0 -0
  32. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/setup.cfg +0 -0
  33. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/tests/test_dimo.py +0 -0
  34. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/tests/test_errors.py +0 -0
  35. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/tests/test_permission_decoder.py +0 -0
  36. {dimo_python_sdk-1.6.0 → dimo_python_sdk-1.7.2}/tests/test_request.py +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimo-python-sdk
3
- Version: 1.6.0
3
+ Version: 1.7.2
4
4
  Summary: DIMO SDK in Python
5
- Author-email: Barrett Kowalsky <barrettkowalsky@gmail.com>
5
+ Author-email: Barrett Kowalsky <barrettkowalsky@gmail.com>, James Li <james.li.upenn@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/DIMO-Network/dimo-python-sdk
7
7
  Project-URL: Issues, https://github.com/DIMO-Network/dimo-python-sdk/issues
8
8
  Keywords: dimo,sdk,python,depin,web3
@@ -28,7 +28,29 @@ pip install dimo-python-sdk
28
28
 
29
29
  ## Unit Testing
30
30
 
31
- Coming Soon
31
+ The SDK includes comprehensive unit tests to ensure reliability and correctness. To run the tests:
32
+
33
+ 1. **Install dependencies:**
34
+ ```bash
35
+ pip install -r requirements.txt
36
+ ```
37
+
38
+ 2. **Run all tests:**
39
+ ```bash
40
+ pytest
41
+ ```
42
+
43
+ 3. **Run tests with verbose output:**
44
+ ```bash
45
+ pytest -v
46
+ ```
47
+
48
+ 4. **Run specific test files:**
49
+ ```bash
50
+ pytest tests/test_conversations.py -v
51
+ ```
52
+
53
+ The test suite uses `pytest` and includes tests for all major SDK functionality including authentication, API endpoints, GraphQL queries, and error handling
32
54
 
33
55
  ## API Documentation
34
56
 
@@ -10,7 +10,29 @@ pip install dimo-python-sdk
10
10
 
11
11
  ## Unit Testing
12
12
 
13
- Coming Soon
13
+ The SDK includes comprehensive unit tests to ensure reliability and correctness. To run the tests:
14
+
15
+ 1. **Install dependencies:**
16
+ ```bash
17
+ pip install -r requirements.txt
18
+ ```
19
+
20
+ 2. **Run all tests:**
21
+ ```bash
22
+ pytest
23
+ ```
24
+
25
+ 3. **Run tests with verbose output:**
26
+ ```bash
27
+ pytest -v
28
+ ```
29
+
30
+ 4. **Run specific test files:**
31
+ ```bash
32
+ pytest tests/test_conversations.py -v
33
+ ```
34
+
35
+ The test suite uses `pytest` and includes tests for all major SDK functionality including authentication, API endpoints, GraphQL queries, and error handling
14
36
 
15
37
  ## API Documentation
16
38
 
@@ -1,6 +1,7 @@
1
1
  from .auth import Auth
2
2
  from .attestation import Attestation
3
3
  from .device_definitions import DeviceDefinitions
4
+ from .fetch import Fetch
4
5
  from .token_exchange import TokenExchange
5
6
  from .trips import Trips
6
7
  from .valuations import Valuations
@@ -9,6 +10,7 @@ __all__ = [
9
10
  "Auth",
10
11
  "Attestation",
11
12
  "DeviceDefinitions",
13
+ "Fetch",
12
14
  "TokenExchange",
13
15
  "Trips",
14
16
  "Valuations",
@@ -0,0 +1,343 @@
1
+ from dimo.errors import check_type, check_optional_type, HTTPError
2
+ from typing import Dict, List, Optional, Any, Generator
3
+ from requests import Session, RequestException
4
+ import json
5
+
6
+
7
+ class Conversations:
8
+ """
9
+ Client for the DIMO Conversations API.
10
+
11
+ This API enables developers to create conversational AI agents that can query
12
+ vehicle data, telemetry data, and perform web searches on behalf of users.
13
+
14
+ Key Features:
15
+ - Create AI agents with access to specific vehicles
16
+ - Query vehicle identity (make, model, owner) via GraphQL
17
+ - Query real-time telemetry (speed, fuel, location) via GraphQL
18
+ - Perform location-based web searches
19
+ - Stream responses in real-time using Server-Sent Events (SSE)
20
+ - Multi-agent delegation architecture with specialized subagents
21
+ """
22
+
23
+ def __init__(self, request_method, get_auth_headers, get_full_path, session: Session):
24
+ self._request = request_method
25
+ self._get_auth_headers = get_auth_headers
26
+ self._get_full_path = get_full_path
27
+ self._session = session
28
+
29
+ def health_check(self) -> Dict:
30
+ """
31
+ Check the service status and configuration.
32
+
33
+ Returns:
34
+ dict: Service health information including status, version, proxy, and default_model
35
+
36
+ Example:
37
+ >>> dimo = DIMO("Production")
38
+ >>> health = dimo.conversations.health_check()
39
+ >>> print(health['status'])
40
+ """
41
+ response = self._request("GET", "Conversations", "/")
42
+ return response
43
+
44
+ def create_agent(
45
+ self,
46
+ developer_jwt: str,
47
+ api_key: str,
48
+ user_wallet: str,
49
+ agent_type: str,
50
+ vehicle_ids: Optional[str] = None,
51
+ personality: str = "uncle_mechanic",
52
+ ) -> Dict:
53
+ """
54
+ Create a new conversational agent with the specified configuration.
55
+
56
+ Args:
57
+ developer_jwt (str): Developer JWT token for authentication
58
+ api_key (str): DIMO API key for the agent to access vehicle data
59
+ user_wallet (str): User's wallet address (e.g., "0x2345...")
60
+ agent_type (str): The type of agent to create (e.g., "driver_agent_v1")
61
+ vehicle_ids (str, optional): JSON array string of vehicle token IDs (e.g., "[1, 2, 3]").
62
+ If not provided, agent will have access to all vehicles owned by the user.
63
+ personality (str, optional): Personality preset for the agent. Defaults to "uncle_mechanic"
64
+
65
+ Returns:
66
+ dict: Agent information including agentId and configuration details
67
+
68
+ Behavior:
69
+ - Creates a new agent with the specified type and configuration
70
+ - Validates configuration and mode detection
71
+ - Creates/reuses shared identity subagent
72
+ - Creates per-vehicle telemetry subagents with token exchange
73
+ - Creates shared websearch subagent if enabled
74
+
75
+ Example:
76
+ >>> dimo = DIMO("Production")
77
+ >>> dev_jwt = "your_developer_jwt"
78
+ >>> agent = dimo.conversations.create_agent(
79
+ ... developer_jwt=dev_jwt,
80
+ ... api_key="0x1234567890abcdef...",
81
+ ... user_wallet="0x86b04f6d1D9E79aD7eB31cDEAF37442B00d64605",
82
+ ... agent_type="driver_agent_v1",
83
+ ... vehicle_ids="[1, 2, 3]",
84
+ ... )
85
+ >>> print(agent['agentId'])
86
+ """
87
+ check_type("developer_jwt", developer_jwt, str)
88
+ check_type("api_key", api_key, str)
89
+ check_type("user_wallet", user_wallet, str)
90
+ check_optional_type("vehicle_ids", vehicle_ids, str)
91
+ check_type("agent_type", agent_type, str)
92
+ check_type("personality", personality, str)
93
+
94
+ # Build variables dict
95
+ variables = {"USER_WALLET": user_wallet}
96
+ if vehicle_ids is not None:
97
+ variables["VEHICLE_IDS"] = vehicle_ids
98
+
99
+ # Build request body
100
+ body = {
101
+ "personality": personality,
102
+ "secrets": {"DIMO_API_KEY": api_key},
103
+ "type": agent_type,
104
+ "variables": variables,
105
+ }
106
+
107
+ response = self._request(
108
+ "POST",
109
+ "Conversations",
110
+ "/agents",
111
+ headers=self._get_auth_headers(developer_jwt),
112
+ data=body,
113
+ )
114
+ return response
115
+
116
+ def delete_agent(self, developer_jwt: str, agent_id: str) -> Dict:
117
+ """
118
+ Delete an agent and all associated resources.
119
+
120
+ Args:
121
+ developer_jwt (str): Developer JWT token for authentication
122
+ agent_id (str): The agent ID to delete
123
+
124
+ Returns:
125
+ dict: Confirmation message
126
+
127
+ Behavior:
128
+ - Deletes Letta agent from server
129
+ - Removes metadata from AgentManager
130
+ - Cleanup errors are logged but don't fail the request
131
+
132
+ Example:
133
+ >>> dimo = DIMO("Production")
134
+ >>> dev_jwt = "your_developer_jwt"
135
+ >>> result = dimo.conversations.delete_agent(
136
+ ... developer_jwt=dev_jwt,
137
+ ... agent_id="agent-abc123"
138
+ ... )
139
+ >>> print(result['message'])
140
+ """
141
+ check_type("developer_jwt", developer_jwt, str)
142
+ check_type("agent_id", agent_id, str)
143
+
144
+ response = self._request(
145
+ "DELETE",
146
+ "Conversations",
147
+ f"/agents/{agent_id}",
148
+ headers=self._get_auth_headers(developer_jwt),
149
+ )
150
+ return response
151
+
152
+ def send_message(
153
+ self,
154
+ developer_jwt: str,
155
+ agent_id: str,
156
+ message: str,
157
+ vehicle_ids: Optional[List[int]] = None,
158
+ user: Optional[str] = None,
159
+ ) -> Dict:
160
+ """
161
+ Send a message to an agent and receive the complete response (synchronous).
162
+
163
+ Args:
164
+ developer_jwt (str): Developer JWT token for authentication
165
+ agent_id (str): The agent ID to send the message to
166
+ message (str): The message to send to the agent
167
+ vehicle_ids (list[int], optional): Optional vehicle IDs override
168
+ user (str, optional): Optional user override
169
+
170
+ Returns:
171
+ dict: Response including agentId, message, response, vehiclesQueried, and timestamp
172
+
173
+ Behavior:
174
+ - Synchronous request/response
175
+ - Agent delegates to subagents as needed
176
+ - Returns full response after agent completes reasoning
177
+ - Timeout: 120 seconds for complex queries
178
+
179
+ Example:
180
+ >>> dimo = DIMO("Production")
181
+ >>> dev_jwt = "your_developer_jwt"
182
+ >>> response = dimo.conversations.send_message(
183
+ ... developer_jwt=dev_jwt,
184
+ ... agent_id="agent-abc123",
185
+ ... message="What's the make and model of my vehicle?"
186
+ ... )
187
+ >>> print(response['response'])
188
+ """
189
+ check_type("developer_jwt", developer_jwt, str)
190
+ check_type("agent_id", agent_id, str)
191
+ check_type("message", message, str)
192
+ check_optional_type("vehicle_ids", vehicle_ids, list)
193
+ check_optional_type("user", user, str)
194
+
195
+ body = {"message": message}
196
+ if vehicle_ids is not None:
197
+ body["vehicleIds"] = vehicle_ids
198
+ if user is not None:
199
+ body["user"] = user
200
+
201
+ response = self._request(
202
+ "POST",
203
+ "Conversations",
204
+ f"/agents/{agent_id}/message",
205
+ headers=self._get_auth_headers(developer_jwt),
206
+ data=body,
207
+ )
208
+ return response
209
+
210
+ def stream_message(
211
+ self,
212
+ developer_jwt: str,
213
+ agent_id: str,
214
+ message: str,
215
+ vehicle_ids: Optional[List[int]] = None,
216
+ user: Optional[str] = None,
217
+ ) -> Generator[Dict[str, Any], None, None]:
218
+ """
219
+ Send a message and receive real-time token-by-token streaming response via SSE.
220
+
221
+ Args:
222
+ developer_jwt (str): Developer JWT token for authentication
223
+ agent_id (str): The agent ID to send the message to
224
+ message (str): The message to send to the agent
225
+ vehicle_ids (list[int], optional): Optional vehicle IDs override
226
+ user (str, optional): Optional user override
227
+
228
+ Yields:
229
+ dict: SSE events with either {"content": "token"} or {"done": true, ...metadata}
230
+
231
+ Behavior:
232
+ - Real-time streaming for better UX
233
+ - Token-by-token generation from LLM
234
+ - Final message includes metadata (agentId, vehiclesQueried)
235
+
236
+ Example:
237
+ >>> dimo = DIMO("Production")
238
+ >>> dev_jwt = "your_developer_jwt"
239
+ >>> for chunk in dimo.conversations.stream_message(
240
+ ... developer_jwt=dev_jwt,
241
+ ... agent_id="agent-abc123",
242
+ ... message="What's my current speed?"
243
+ ... ):
244
+ ... if "content" in chunk:
245
+ ... print(chunk["content"], end="", flush=True)
246
+ ... elif "done" in chunk:
247
+ ... print(f"\\nVehicles queried: {chunk['vehiclesQueried']}")
248
+ """
249
+ check_type("developer_jwt", developer_jwt, str)
250
+ check_type("agent_id", agent_id, str)
251
+ check_type("message", message, str)
252
+ check_optional_type("vehicle_ids", vehicle_ids, list)
253
+ check_optional_type("user", user, str)
254
+
255
+ body = {"message": message}
256
+ if vehicle_ids is not None:
257
+ body["vehicleIds"] = vehicle_ids
258
+ if user is not None:
259
+ body["user"] = user
260
+
261
+ headers = self._get_auth_headers(developer_jwt)
262
+ headers["Accept"] = "text/event-stream"
263
+ headers["Content-Type"] = "application/json"
264
+
265
+ # Build full URL
266
+ url = self._get_full_path("Conversations", f"/agents/{agent_id}/stream")
267
+
268
+ # Make streaming request directly with session
269
+ try:
270
+ response = self._session.request(
271
+ method="POST",
272
+ url=url,
273
+ headers=headers,
274
+ data=json.dumps(body),
275
+ stream=True,
276
+ )
277
+ response.raise_for_status()
278
+ except RequestException as exc:
279
+ status = getattr(exc.response, "status_code", None)
280
+ body_error = None
281
+ try:
282
+ body_error = exc.response.json()
283
+ except Exception:
284
+ body_error = exc.response.text if exc.response else None
285
+ raise HTTPError(status=status or -1, message=str(exc), body=body_error)
286
+
287
+ # Parse SSE stream
288
+ for line in response.iter_lines():
289
+ if line:
290
+ line = line.decode("utf-8")
291
+ if line.startswith("data: "):
292
+ data = line[6:] # Remove "data: " prefix
293
+ try:
294
+ yield json.loads(data)
295
+ except json.JSONDecodeError:
296
+ # Skip malformed JSON
297
+ continue
298
+
299
+ def get_history(
300
+ self,
301
+ developer_jwt: str,
302
+ agent_id: str,
303
+ limit: int = 100,
304
+ ) -> Dict:
305
+ """
306
+ Retrieve all messages in a conversation.
307
+
308
+ Args:
309
+ developer_jwt (str): Developer JWT token for authentication
310
+ agent_id (str): The agent ID to get history for
311
+ limit (int): Maximum number of messages to return (default: 100)
312
+
313
+ Returns:
314
+ dict: Conversation history including agentId, messages array, and total count
315
+
316
+ Behavior:
317
+ - Retrieves from Letta server
318
+ - Includes all message roles (user, agent, system)
319
+ - Reverse chronological order (newest first)
320
+
321
+ Example:
322
+ >>> dimo = DIMO("Production")
323
+ >>> dev_jwt = "your_developer_jwt"
324
+ >>> history = dimo.conversations.get_history(
325
+ ... developer_jwt=dev_jwt,
326
+ ... agent_id="agent-abc123",
327
+ ... limit=50
328
+ ... )
329
+ >>> for msg in history['messages']:
330
+ ... print(f"{msg['role']}: {msg['content']}")
331
+ """
332
+ check_type("developer_jwt", developer_jwt, str)
333
+ check_type("agent_id", agent_id, str)
334
+ check_type("limit", limit, int)
335
+
336
+ response = self._request(
337
+ "GET",
338
+ "Conversations",
339
+ f"/agents/{agent_id}/history",
340
+ headers=self._get_auth_headers(developer_jwt),
341
+ params={"limit": limit},
342
+ )
343
+ return response
@@ -0,0 +1,123 @@
1
+ from dimo.errors import check_type, check_optional_type
2
+
3
+
4
+ class Fetch:
5
+
6
+ def __init__(self, request_method, get_auth_headers):
7
+ self._request = request_method
8
+ self._get_auth_headers = get_auth_headers
9
+
10
+ def _build_params(self, **kwargs):
11
+ params = {}
12
+ for key, value in kwargs.items():
13
+ if value is not None:
14
+ params[key] = value
15
+ return params
16
+
17
+ def get_index_keys(
18
+ self,
19
+ vehicle_jwt: str,
20
+ token_id: int,
21
+ after=None,
22
+ before=None,
23
+ id=None,
24
+ limit=None,
25
+ producer=None,
26
+ source=None,
27
+ type=None,
28
+ ) -> dict:
29
+ check_type("vehicle_jwt", vehicle_jwt, str)
30
+ check_type("token_id", token_id, int)
31
+ params = self._build_params(
32
+ after=after, before=before, id=id, limit=limit,
33
+ producer=producer, source=source, type=type,
34
+ )
35
+ url = f"/v1/vehicle/index-keys/{token_id}"
36
+ return self._request(
37
+ "GET",
38
+ "Fetch",
39
+ url,
40
+ params=params,
41
+ headers=self._get_auth_headers(vehicle_jwt),
42
+ )
43
+
44
+ def get_latest_index_key(
45
+ self,
46
+ vehicle_jwt: str,
47
+ token_id: int,
48
+ after=None,
49
+ before=None,
50
+ id=None,
51
+ limit=None,
52
+ producer=None,
53
+ source=None,
54
+ type=None,
55
+ ) -> dict:
56
+ check_type("vehicle_jwt", vehicle_jwt, str)
57
+ check_type("token_id", token_id, int)
58
+ params = self._build_params(
59
+ after=after, before=before, id=id, limit=limit,
60
+ producer=producer, source=source, type=type,
61
+ )
62
+ url = f"/v1/vehicle/latest-index-key/{token_id}"
63
+ return self._request(
64
+ "GET",
65
+ "Fetch",
66
+ url,
67
+ params=params,
68
+ headers=self._get_auth_headers(vehicle_jwt),
69
+ )
70
+
71
+ def get_latest_object(
72
+ self,
73
+ vehicle_jwt: str,
74
+ token_id: int,
75
+ after=None,
76
+ before=None,
77
+ id=None,
78
+ limit=None,
79
+ producer=None,
80
+ source=None,
81
+ type=None,
82
+ ) -> dict:
83
+ check_type("vehicle_jwt", vehicle_jwt, str)
84
+ check_type("token_id", token_id, int)
85
+ params = self._build_params(
86
+ after=after, before=before, id=id, limit=limit,
87
+ producer=producer, source=source, type=type,
88
+ )
89
+ url = f"/v1/vehicle/latest-object/{token_id}"
90
+ return self._request(
91
+ "GET",
92
+ "Fetch",
93
+ url,
94
+ params=params,
95
+ headers=self._get_auth_headers(vehicle_jwt),
96
+ )
97
+
98
+ def get_objects(
99
+ self,
100
+ vehicle_jwt: str,
101
+ token_id: int,
102
+ after=None,
103
+ before=None,
104
+ id=None,
105
+ limit=None,
106
+ producer=None,
107
+ source=None,
108
+ type=None,
109
+ ) -> dict:
110
+ check_type("vehicle_jwt", vehicle_jwt, str)
111
+ check_type("token_id", token_id, int)
112
+ params = self._build_params(
113
+ after=after, before=before, id=id, limit=limit,
114
+ producer=producer, source=source, type=type,
115
+ )
116
+ url = f"/v1/vehicle/objects/{token_id}"
117
+ return self._request(
118
+ "GET",
119
+ "Fetch",
120
+ url,
121
+ params=params,
122
+ headers=self._get_auth_headers(vehicle_jwt),
123
+ )
@@ -2,8 +2,10 @@ from requests import Session
2
2
 
3
3
  from .api.attestation import Attestation
4
4
  from .api.auth import Auth
5
+ from .api.conversations import Conversations
5
6
  from .api.device_definitions import DeviceDefinitions
6
7
  from .api.token_exchange import TokenExchange
8
+ from .api.fetch import Fetch
7
9
  from .api.trips import Trips
8
10
  from .api.valuations import Valuations
9
11
  from .api.vehicle_triggers import VehicleTriggers
@@ -75,7 +77,9 @@ class DIMO:
75
77
  mapping = {
76
78
  "attestation": (Attestation, ("request", "_get_auth_headers")),
77
79
  "auth": (Auth, ("request", "_get_auth_headers", "env", "self")),
80
+ "conversations": (Conversations, ("request", "_get_auth_headers", "_get_full_path", "session")),
78
81
  "device_definitions": (DeviceDefinitions, ("request", "_get_auth_headers")),
82
+ "fetch": (Fetch, ("request", "_get_auth_headers")),
79
83
  "token_exchange": (
80
84
  TokenExchange,
81
85
  ("request", "_get_auth_headers", "identity", "self"),
@@ -2,8 +2,10 @@ dimo_environment = {
2
2
  "Production": {
3
3
  "Attestation": "https://attestation-api.dimo.zone",
4
4
  "Auth": "https://auth.dimo.zone",
5
+ "Conversations": "https://conversations-api.dimo.zone",
5
6
  "Identity": "https://identity-api.dimo.zone/query",
6
7
  "DeviceDefinitions": "https://device-definitions-api.dimo.zone",
8
+ "Fetch": "https://fetch-api.dimo.zone",
7
9
  "Telemetry": "https://telemetry-api.dimo.zone/query",
8
10
  "TokenExchange": "https://token-exchange-api.dimo.zone",
9
11
  "Trips": "https://trips-api.dimo.zone",
@@ -14,8 +16,10 @@ dimo_environment = {
14
16
  "Dev": {
15
17
  "Attestation": "https://attestation-api.dev.dimo.zone",
16
18
  "Auth": "https://auth.dev.dimo.zone",
19
+ "Conversations": "https://conversations-api.dev.dimo.zone",
17
20
  "Identity": "https://identity-api.dev.dimo.zone/query",
18
21
  "DeviceDefinitions": "https://device-definitions-api.dev.dimo.zone",
22
+ "Fetch": "https://fetch-api.dev.dimo.zone",
19
23
  "Telemetry": "https://telemetry-api.dev.dimo.zone/query",
20
24
  "TokenExchange": "https://token-exchange-api.dev.dimo.zone",
21
25
  "Trips": "https://trips-api.dev.dimo.zone",
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dimo-python-sdk
3
- Version: 1.6.0
3
+ Version: 1.7.2
4
4
  Summary: DIMO SDK in Python
5
- Author-email: Barrett Kowalsky <barrettkowalsky@gmail.com>
5
+ Author-email: Barrett Kowalsky <barrettkowalsky@gmail.com>, James Li <james.li.upenn@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/DIMO-Network/dimo-python-sdk
7
7
  Project-URL: Issues, https://github.com/DIMO-Network/dimo-python-sdk/issues
8
8
  Keywords: dimo,sdk,python,depin,web3
@@ -28,7 +28,29 @@ pip install dimo-python-sdk
28
28
 
29
29
  ## Unit Testing
30
30
 
31
- Coming Soon
31
+ The SDK includes comprehensive unit tests to ensure reliability and correctness. To run the tests:
32
+
33
+ 1. **Install dependencies:**
34
+ ```bash
35
+ pip install -r requirements.txt
36
+ ```
37
+
38
+ 2. **Run all tests:**
39
+ ```bash
40
+ pytest
41
+ ```
42
+
43
+ 3. **Run tests with verbose output:**
44
+ ```bash
45
+ pytest -v
46
+ ```
47
+
48
+ 4. **Run specific test files:**
49
+ ```bash
50
+ pytest tests/test_conversations.py -v
51
+ ```
52
+
53
+ The test suite uses `pytest` and includes tests for all major SDK functionality including authentication, API endpoints, GraphQL queries, and error handling
32
54
 
33
55
  ## API Documentation
34
56
 
@@ -12,7 +12,9 @@ dimo/request.py
12
12
  dimo/api/__init__.py
13
13
  dimo/api/attestation.py
14
14
  dimo/api/auth.py
15
+ dimo/api/conversations.py
15
16
  dimo/api/device_definitions.py
17
+ dimo/api/fetch.py
16
18
  dimo/api/token_exchange.py
17
19
  dimo/api/trips.py
18
20
  dimo/api/valuations.py
@@ -25,6 +27,7 @@ dimo_python_sdk.egg-info/SOURCES.txt
25
27
  dimo_python_sdk.egg-info/dependency_links.txt
26
28
  dimo_python_sdk.egg-info/requires.txt
27
29
  dimo_python_sdk.egg-info/top_level.txt
30
+ tests/test_conversations.py
28
31
  tests/test_dimo.py
29
32
  tests/test_errors.py
30
33
  tests/test_permission_decoder.py
@@ -4,9 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dimo-python-sdk"
7
- version = "1.6.0"
7
+ version = "1.7.2"
8
8
  authors = [
9
9
  { name="Barrett Kowalsky", email="barrettkowalsky@gmail.com" },
10
+ { name="James Li", email="james.li.upenn@gmail.com" },
10
11
  ]
11
12
  description = "DIMO SDK in Python"
12
13
  readme = "README.md"