diff --git a/examples/add_agent_post_example.py b/examples/add_agent_post_example.py new file mode 100644 index 0000000..186f87a --- /dev/null +++ b/examples/add_agent_post_example.py @@ -0,0 +1,52 @@ +import os +import uuid + +from cvec import CVec +from cvec.models.agent_post import AgentPostRecommendation, AgentPostTag, Severity + + +def main() -> None: + # Initialize CVec client + cvec = CVec( + host=os.environ.get("CVEC_HOST", "https://your-subdomain.cvector.dev"), + api_key=os.environ.get("CVEC_API_KEY", "your-api-key"), + ) + + recommendations = [ + AgentPostRecommendation( + content="Critical recommendation", + severity=Severity.CRITICAL, + ), + AgentPostRecommendation( + content="Warning recommendation", + severity=Severity.WARNING, + ), + AgentPostRecommendation( + content="Info recommendation", + severity=Severity.INFO, + ), + ] + + tags = [ + AgentPostTag( + content="urgent", + severity=Severity.CRITICAL, + ), + AgentPostTag( + content="monitoring", + severity=Severity.INFO, + ), + ] + + cvec.add_agent_post( + title="Test post", + author="Operational Agent", + image_id=str(uuid.uuid4()), # Replace with actual image UUID uploaded to S3 + content="SDK add post test.", + recommendations=recommendations, + tags=tags, + ) + + +if __name__ == "__main__": + main() diff --git a/src/cvec/cvec.py b/src/cvec/cvec.py index b61306e..19a6ef4 100644 --- a/src/cvec/cvec.py +++ b/src/cvec/cvec.py @@ -7,6 +7,7 @@ from urllib.parse import urlencode, urljoin from urllib.request import Request, urlopen +from cvec.models.agent_post import AgentPost, AgentPostRecommendation, AgentPostTag from cvec.models.eav_column import EAVColumn from cvec.models.eav_filter import EAVFilter from cvec.models.eav_table import EAVTable @@ -426,6 +427,35 @@ def get_modeling_metrics_data_arrow( assert isinstance(result, bytes) return result + def add_agent_post( + self, + title: str, + author: str, + image_id: Optional[str] = None, + content: Optional[str] = None, + recommendations: Optional[List[AgentPostRecommendation]] = None, + tags: Optional[List[AgentPostTag]] = None, + ) -> None: + """ + Add an agent post. + + Note: If image_id is provided, the image must be uploaded to S3 beforehand. + The image_id should be the UUID used as the filename (without .png extension) + in the S3 bucket at the tenant's path. + """ + + post = AgentPost( + title=title, + author=author, + image_id=image_id, + content=content, + recommendations=recommendations, + tags=tags, + ) + payload = post.model_dump(mode="json", exclude_none=True) + + self._make_request("POST", "/api/agent_posts/add", json_data=payload) + def _login_with_supabase(self, email: str, password: str) -> None: """ Login to Supabase and get access/refresh tokens. diff --git a/src/cvec/models/__init__.py b/src/cvec/models/__init__.py index dd1a3b0..5986c12 100644 --- a/src/cvec/models/__init__.py +++ b/src/cvec/models/__init__.py @@ -1,3 +1,9 @@ +from .agent_post import ( + AgentPost, + AgentPostRecommendation, + AgentPostTag, + Severity, +) from .eav_column import EAVColumn from .eav_filter import EAVFilter from .eav_table import EAVTable @@ -5,10 +11,14 @@ from .span import Span __all__ = [ + "AgentPost", + "AgentPostRecommendation", + "AgentPostTag", "EAVColumn", "EAVFilter", "EAVTable", "Metric", "MetricDataPoint", + "Severity", "Span", ] diff --git a/src/cvec/models/agent_post.py b/src/cvec/models/agent_post.py new file mode 100644 index 0000000..6d3eccc --- /dev/null +++ b/src/cvec/models/agent_post.py @@ -0,0 +1,43 @@ +from enum import Enum +from typing import List, Optional + +from pydantic import BaseModel, Field + + +class Severity(str, Enum): + """Severity level for recommendations and tags.""" + + CRITICAL = "critical" + WARNING = "warning" + INFO = "info" + + +class AgentPostRecommendation(BaseModel): + """ + Represents a recommendation for creating an agent post. + """ + + content: str = Field(..., min_length=1) + severity: Severity + + +class AgentPostTag(BaseModel): + """ + Represents a tag for creating an agent post. + """ + + content: str = Field(..., min_length=1) + severity: Severity + + +class AgentPost(BaseModel): + """ + Represents an agent post with optional recommendations and tags. + """ + + author: str + title: str + content: Optional[str] = None + image_id: Optional[str] = None + recommendations: Optional[List[AgentPostRecommendation]] = None + tags: Optional[List[AgentPostTag]] = None