11from datetime import datetime
22from typing import Optional
33from pydantic import BaseModel , Field
4+ from src .client .obp_client import OBPClient
45
56class OpeyCheckpointEntity (BaseModel ):
67 """OBP Dynamic Entity representation of a LangGraph checkpoint."""
@@ -19,19 +20,15 @@ def obp_entity_name(cls) -> str:
1920
2021 @classmethod
2122 def to_obp_schema (cls ) -> dict :
23+ json_schema = cls .model_json_schema ()
2224 return {
2325 "hasPersonalEntity" : True ,
2426 cls .obp_entity_name (): {
25- "description" : "LangGraph checkpoint snapshots for Opey AI conversations" ,
26- "required" : [ "thread_id" , "checkpoint_id" , "checkpoint_ns" , "checkpoint_data " ],
27+ "description" : cls . __doc__ . strip () ,
28+ "required" : json_schema [ "required " ],
2729 "properties" : {
28- "thread_id" : {"type" : "string" , "description" : "Thread identifier" },
29- "checkpoint_id" : {"type" : "string" , "description" : "Unique checkpoint ID (UUID)" },
30- "checkpoint_ns" : {"type" : "string" , "description" : "Checkpoint namespace" },
31- "parent_checkpoint_id" : {"type" : "string" , "description" : "Parent checkpoint ID for history" },
32- "checkpoint_data" : {"type" : "string" , "description" : "JSON-serialized checkpoint (channel_values, versions, etc.)" },
33- "metadata" : {"type" : "string" , "description" : "JSON-serialized metadata (step, source, writes)" },
34- "created_at" : {"type" : "string" , "description" : "ISO timestamp" }
30+ k : {"type" : v .get ("type" , "string" ), "description" : v .get ("description" , "" )}
31+ for k , v in json_schema ["properties" ].items ()
3532 }
3633 }
3734 }
@@ -54,24 +51,48 @@ def obp_entity_name(cls) -> str:
5451
5552 @classmethod
5653 def to_obp_schema (cls ) -> dict :
57- """OBP Dynamic Entity schema definition."""
54+ json_schema = cls . model_json_schema ()
5855 return {
5956 "hasPersonalEntity" : True ,
6057 cls .obp_entity_name (): {
61- "description" : "Pending writes for LangGraph checkpoints" ,
62- "required" : [ "thread_id" , "checkpoint_id" , "checkpoint_ns" , "task_id" , "channel" , "value" , "idx " ],
58+ "description" : cls . __doc__ . strip () ,
59+ "required" : json_schema [ "required " ],
6360 "properties" : {
64- "thread_id" : {"type" : "string" },
65- "checkpoint_id" : {"type" : "string" },
66- "checkpoint_ns" : {"type" : "string" },
67- "task_id" : {"type" : "string" , "description" : "Task that produced this write" },
68- "idx" : {"type" : "integer" , "description" : "Write index within task" },
69- "channel" : {"type" : "string" , "description" : "Channel name" },
70- "value" : {"type" : "string" , "description" : "Serialized write value" }
61+ k : {"type" : v .get ("type" , "string" ), "description" : v .get ("description" , "" )}
62+ for k , v in json_schema ["properties" ].items ()
7163 }
7264 }
7365 }
7466
67+ class DynamicEntitiesManager :
68+ """Wrapper for DynamicEntities CRUD endpoints."""
69+ def __init__ (self , obp_client : OBPClient , endpoint_url : str ):
70+
71+ self .endpoint_url = endpoint_url
72+ self .client = obp_client
73+
74+
75+ async def create (self , entity : OpeyCheckpointEntity | OpeyCheckpointWriteEntity ):
76+ await self .client .async_obp_requests (
77+ method = "POST" ,
78+ body = str (entity .model_dump ()),
79+ path = self .endpoint_url
80+ )
81+
82+ async def delete (self , entity_id : str ):
83+ await self .client .async_obp_requests (
84+ method = "DELETE" ,
85+ body = "" ,
86+ path = f"{ self .endpoint_url } /{ entity_id } "
87+ )
88+
89+ async def read (self , entity_id : str ) -> dict :
90+ response = await self .client .async_obp_requests (
91+ method = "GET" ,
92+ body = "" ,
93+ path = f"{ self .endpoint_url } /{ entity_id } "
94+ )
95+ return response
7596
7697opey_checkpoint_entity = {
7798 "hasPersonalEntity" : True ,
@@ -105,4 +126,4 @@ def to_obp_schema(cls) -> dict:
105126 "value" : {"type" : "string" , "description" : "JSON-serialized write value" }
106127 }
107128 }
108- }
129+ }
0 commit comments