lucidicai 3.4.1__py3-none-any.whl → 3.4.2__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.
lucidicai/__init__.py CHANGED
@@ -41,7 +41,7 @@ from .api.resources.prompt import Prompt
41
41
  from .integrations.livekit import setup_livekit
42
42
 
43
43
  # Version
44
- __version__ = "3.4.1"
44
+ __version__ = "3.4.2"
45
45
 
46
46
  # All exports
47
47
  __all__ = [
lucidicai/api/client.py CHANGED
@@ -207,6 +207,19 @@ class HttpClient:
207
207
  data = self._add_timestamp(data)
208
208
  return self.request("PUT", endpoint, json=data)
209
209
 
210
+ def patch(self, endpoint: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
211
+ """Make a synchronous PATCH request.
212
+
213
+ Args:
214
+ endpoint: API endpoint (without base URL)
215
+ data: Request body data
216
+
217
+ Returns:
218
+ Response data as dictionary
219
+ """
220
+ data = self._add_timestamp(data)
221
+ return self.request("PATCH", endpoint, json=data)
222
+
210
223
  def delete(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
211
224
  """Make a synchronous DELETE request.
212
225
 
@@ -301,6 +314,19 @@ class HttpClient:
301
314
  data = self._add_timestamp(data)
302
315
  return await self.arequest("PUT", endpoint, json=data)
303
316
 
317
+ async def apatch(self, endpoint: str, data: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
318
+ """Make an asynchronous PATCH request.
319
+
320
+ Args:
321
+ endpoint: API endpoint (without base URL)
322
+ data: Request body data
323
+
324
+ Returns:
325
+ Response data as dictionary
326
+ """
327
+ data = self._add_timestamp(data)
328
+ return await self.arequest("PATCH", endpoint, json=data)
329
+
304
330
  async def adelete(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
305
331
  """Make an asynchronous DELETE request.
306
332
 
@@ -2,7 +2,7 @@
2
2
  import logging
3
3
  import time
4
4
  from dataclasses import dataclass
5
- from typing import Any, Dict, Optional, Tuple, TYPE_CHECKING
5
+ from typing import Any, Dict, List, Optional, Tuple, TYPE_CHECKING
6
6
 
7
7
  from ..client import HttpClient
8
8
 
@@ -58,6 +58,21 @@ class PromptResource:
58
58
  self._production = production
59
59
  self._cache: Dict[Tuple[str, str], Dict[str, Any]] = {}
60
60
 
61
+ def _invalidate_cache(self, prompt_name: str, label: Optional[str] = None) -> None:
62
+ """Invalidate cached prompt entries.
63
+
64
+ Args:
65
+ prompt_name: Name of the prompt to invalidate.
66
+ label: If provided, only invalidate the specific (prompt_name, label) entry.
67
+ If None, invalidate all entries matching prompt_name.
68
+ """
69
+ if label is not None:
70
+ self._cache.pop((prompt_name, label), None)
71
+ else:
72
+ keys_to_remove = [k for k in self._cache if k[0] == prompt_name]
73
+ for k in keys_to_remove:
74
+ del self._cache[k]
75
+
61
76
  def _is_cache_valid(self, cache_key: Tuple[str, str], cache_ttl: int) -> bool:
62
77
  """Check if a cached prompt is still valid.
63
78
 
@@ -106,7 +121,7 @@ class PromptResource:
106
121
  metadata = self._cache[cache_key]["metadata"]
107
122
  else:
108
123
  response = self.http.get(
109
- "getprompt",
124
+ "sdk/prompts",
110
125
  {"prompt_name": prompt_name, "label": label, "agent_id": self._config.agent_id},
111
126
  )
112
127
  raw_content = response.get("prompt_content", "")
@@ -150,7 +165,7 @@ class PromptResource:
150
165
  metadata = self._cache[cache_key]["metadata"]
151
166
  else:
152
167
  response = await self.http.aget(
153
- "getprompt",
168
+ "sdk/prompts",
154
169
  {"prompt_name": prompt_name, "label": label, "agent_id": self._config.agent_id},
155
170
  )
156
171
  raw_content = response.get("prompt_content", "")
@@ -173,3 +188,155 @@ class PromptResource:
173
188
  logger.error(f"[PromptResource] Failed to get prompt: {e}")
174
189
  return Prompt(raw_content="", content="", metadata={})
175
190
  raise
191
+
192
+ def update(
193
+ self,
194
+ prompt_name: str,
195
+ prompt_content: str,
196
+ description: Optional[str] = None,
197
+ metadata: Optional[Dict[str, Any]] = None,
198
+ labels: Optional[List[str]] = None,
199
+ ) -> Prompt:
200
+ """Update a prompt, creating a new immutable version.
201
+
202
+ Args:
203
+ prompt_name: Name of the prompt to update.
204
+ prompt_content: New content for the prompt.
205
+ description: Optional description for the prompt version.
206
+ metadata: Optional metadata dict to attach to the prompt version.
207
+ labels: Optional list of labels to assign to the new version.
208
+
209
+ Returns:
210
+ A Prompt object with the new content and metadata from the response.
211
+ """
212
+ try:
213
+ body: Dict[str, Any] = {
214
+ "agent_id": self._config.agent_id,
215
+ "prompt_name": prompt_name,
216
+ "prompt_content": prompt_content,
217
+ }
218
+ if description is not None:
219
+ body["description"] = description
220
+ if metadata is not None:
221
+ body["metadata"] = metadata
222
+ if labels is not None:
223
+ body["labels"] = labels
224
+
225
+ response = self.http.put("sdk/prompts", data=body)
226
+ response_metadata = response.get("metadata", {})
227
+
228
+ self._invalidate_cache(prompt_name)
229
+
230
+ return Prompt(raw_content=prompt_content, content=prompt_content, metadata=response_metadata)
231
+ except Exception as e:
232
+ if self._production:
233
+ logger.error(f"[PromptResource] Failed to update prompt: {e}")
234
+ return Prompt(raw_content="", content="", metadata={})
235
+ raise
236
+
237
+ async def aupdate(
238
+ self,
239
+ prompt_name: str,
240
+ prompt_content: str,
241
+ description: Optional[str] = None,
242
+ metadata: Optional[Dict[str, Any]] = None,
243
+ labels: Optional[List[str]] = None,
244
+ ) -> Prompt:
245
+ """Update a prompt, creating a new immutable version (asynchronous).
246
+
247
+ See update() for full documentation.
248
+ """
249
+ try:
250
+ body: Dict[str, Any] = {
251
+ "agent_id": self._config.agent_id,
252
+ "prompt_name": prompt_name,
253
+ "prompt_content": prompt_content,
254
+ }
255
+ if description is not None:
256
+ body["description"] = description
257
+ if metadata is not None:
258
+ body["metadata"] = metadata
259
+ if labels is not None:
260
+ body["labels"] = labels
261
+
262
+ response = await self.http.aput("sdk/prompts", data=body)
263
+ response_metadata = response.get("metadata", {})
264
+
265
+ self._invalidate_cache(prompt_name)
266
+
267
+ return Prompt(raw_content=prompt_content, content=prompt_content, metadata=response_metadata)
268
+ except Exception as e:
269
+ if self._production:
270
+ logger.error(f"[PromptResource] Failed to update prompt: {e}")
271
+ return Prompt(raw_content="", content="", metadata={})
272
+ raise
273
+
274
+ def update_metadata(
275
+ self,
276
+ prompt_name: str,
277
+ label: str,
278
+ metadata: Dict[str, Any],
279
+ ) -> Prompt:
280
+ """Update metadata on an existing prompt version.
281
+
282
+ Sends a PATCH request to update only the metadata for the prompt version
283
+ identified by (prompt_name, label). The prompt content is not returned
284
+ by this endpoint, so the returned Prompt will have empty content fields.
285
+
286
+ Args:
287
+ prompt_name: Name of the prompt.
288
+ label: Label identifying the prompt version to update.
289
+ metadata: Metadata dict to set on the prompt version.
290
+
291
+ Returns:
292
+ A Prompt object with empty content and the updated metadata.
293
+ """
294
+ try:
295
+ body: Dict[str, Any] = {
296
+ "agent_id": self._config.agent_id,
297
+ "prompt_name": prompt_name,
298
+ "label": label,
299
+ "metadata": metadata,
300
+ }
301
+
302
+ response = self.http.patch("sdk/prompts", data=body)
303
+ response_metadata = response.get("metadata", {})
304
+
305
+ self._invalidate_cache(prompt_name, label)
306
+
307
+ return Prompt(raw_content="", content="", metadata=response_metadata)
308
+ except Exception as e:
309
+ if self._production:
310
+ logger.error(f"[PromptResource] Failed to update prompt metadata: {e}")
311
+ return Prompt(raw_content="", content="", metadata={})
312
+ raise
313
+
314
+ async def aupdate_metadata(
315
+ self,
316
+ prompt_name: str,
317
+ label: str,
318
+ metadata: Dict[str, Any],
319
+ ) -> Prompt:
320
+ """Update metadata on an existing prompt version (asynchronous).
321
+
322
+ See update_metadata() for full documentation.
323
+ """
324
+ try:
325
+ body: Dict[str, Any] = {
326
+ "agent_id": self._config.agent_id,
327
+ "prompt_name": prompt_name,
328
+ "label": label,
329
+ "metadata": metadata,
330
+ }
331
+
332
+ response = await self.http.apatch("sdk/prompts", data=body)
333
+ response_metadata = response.get("metadata", {})
334
+
335
+ self._invalidate_cache(prompt_name, label)
336
+
337
+ return Prompt(raw_content="", content="", metadata=response_metadata)
338
+ except Exception as e:
339
+ if self._production:
340
+ logger.error(f"[PromptResource] Failed to update prompt metadata: {e}")
341
+ return Prompt(raw_content="", content="", metadata={})
342
+ raise
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: lucidicai
3
- Version: 3.4.1
3
+ Version: 3.4.2
4
4
  Summary: Lucidic AI Python SDK
5
5
  Author: Andy Liang
6
6
  Author-email: andy@lucidic.ai
@@ -1,4 +1,4 @@
1
- lucidicai/__init__.py,sha256=d0jiR0fpY1JbmHuczLu7sni-Qk9zZXe5M8zHxURe4RA,1376
1
+ lucidicai/__init__.py,sha256=rplyrx17fDqB9QiVEhs6wCO3T_-mzza-aZlgCTD3d0k,1376
2
2
  lucidicai/action.py,sha256=sPRd1hTIVXDqnvG9ZXWEipUFh0bsXcE0Fm7RVqmVccM,237
3
3
  lucidicai/client.py,sha256=BGKP91_Oj5kHQU0osYf1T_BWakL8KIhs0AgUc5X99sU,15104
4
4
  lucidicai/constants.py,sha256=zN8O7TjoRHRlaGa9CZUWppS73rhzKGwaEkF9XMTV0Cg,1160
@@ -19,14 +19,14 @@ lucidicai/state.py,sha256=4Tb1X6l2or6w_e62FYSuEeghAv3xXm5gquKwzCpvdok,235
19
19
  lucidicai/step.py,sha256=_oBIyTBZBvNkUkYHIrwWd75KMSlMtR9Ws2Lo71Lyff8,2522
20
20
  lucidicai/streaming.py,sha256=QOLAzhwxetvx711J8VcphY5kXWPJz9XEBJrmHveRKMc,9796
21
21
  lucidicai/api/__init__.py,sha256=UOYuFZupG0TgzMAxbLNgpodDXhDRXBgMva8ZblgBN9Y,31
22
- lucidicai/api/client.py,sha256=0Ia5cXo5OKifhP-63TPAWPuy2bWCzR9VN4BpWIMo34w,13212
22
+ lucidicai/api/client.py,sha256=T3EIDReCsHQ4vqgwKdsVxZ0gz_XrFQLIoJNhS7lhRuo,14054
23
23
  lucidicai/api/resources/__init__.py,sha256=DDgviDW3Su-G1ofkZGlaJMc2pzYJqrbBnEruNg1whCM,416
24
24
  lucidicai/api/resources/dataset.py,sha256=I6g9ah4vaqEH1jyeouBn7xvC0oAuDNPeyl-bmtNj-T0,17400
25
25
  lucidicai/api/resources/evals.py,sha256=_3nLE6dMLht844mWw7kl_hctjv5JIuC6MP06YWUgLnI,7235
26
26
  lucidicai/api/resources/event.py,sha256=GTIU5sIbLNTWAHk4rB120xWTRkhnraz9JNfamEygyNo,14267
27
27
  lucidicai/api/resources/experiment.py,sha256=fOIKJ5d89bHJBVZ3wjbhY_6XF3kLHz9TE3BVPA5pNpA,3563
28
28
  lucidicai/api/resources/feature_flag.py,sha256=ii412DIkZCEAhrXdGydcpQKveqGlFq4NlgdmWQnU83c,2259
29
- lucidicai/api/resources/prompt.py,sha256=M2ZovMX74-ULksMXzXPXVgBziRcTcmz40GnDcJx30Q0,6053
29
+ lucidicai/api/resources/prompt.py,sha256=kddb9X05om9xbWBLjUGoCFEsao-J-vyqjn_RzZIyht0,12278
30
30
  lucidicai/api/resources/session.py,sha256=jW_bftHdunhLHl_3-k0nqB5FrtLhlFeCF0tMFE82nNw,20761
31
31
  lucidicai/core/__init__.py,sha256=b0YQkd8190Y_GgwUcmf0tOiSLARd7L4kq4jwfhhGAyI,39
32
32
  lucidicai/core/config.py,sha256=q4h-yR35Ay_3znL7vavri6ScfeM69RjHShNNzjoQthc,10194
@@ -93,7 +93,7 @@ lucidicai/utils/images.py,sha256=z8mlIKgFfrIbuk-l4L2rB62uw_uPO79sHPXPY7eLu2A,128
93
93
  lucidicai/utils/logger.py,sha256=R3B3gSee64F6UVHUrShihBq_O7W7bgfrBiVDXTO3Isg,4777
94
94
  lucidicai/utils/queue.py,sha256=8DQwnGw7pINEJ0dNSkB0PhdPW-iBQQ-YZg23poe4umE,17323
95
95
  lucidicai/utils/serialization.py,sha256=KdOREZd7XBxFBAZ86DePMfYPzSVyKr4RcgUa82aFxrs,820
96
- lucidicai-3.4.1.dist-info/METADATA,sha256=oPV8Sh8GPs876yl42Vk7ZyAe2HyD8NW9K_jxO1p8kf4,902
97
- lucidicai-3.4.1.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
98
- lucidicai-3.4.1.dist-info/top_level.txt,sha256=vSSdM3lclF4I5tyVC0xxUk8eIRnnYXMe1hW-eO91HUo,10
99
- lucidicai-3.4.1.dist-info/RECORD,,
96
+ lucidicai-3.4.2.dist-info/METADATA,sha256=oPoV8nkD9_mkCoivkZfoYoisDtd7bR0cHFMZOPjuFhU,902
97
+ lucidicai-3.4.2.dist-info/WHEEL,sha256=Xo9-1PvkuimrydujYJAjF7pCkriuXBpUPEjma1nZyJ0,92
98
+ lucidicai-3.4.2.dist-info/top_level.txt,sha256=vSSdM3lclF4I5tyVC0xxUk8eIRnnYXMe1hW-eO91HUo,10
99
+ lucidicai-3.4.2.dist-info/RECORD,,