diff --git a/src/pluggedinkit/__init__.py b/src/pluggedinkit/__init__.py index 3beb2f0..df56f1b 100644 --- a/src/pluggedinkit/__init__.py +++ b/src/pluggedinkit/__init__.py @@ -44,6 +44,14 @@ RagStorageStats, ModelInfo, AIMetadata, + # Jungian Intelligence types + IndividuationComponents, + IndividuationResponse, + IndividuationHistoryEntry, + ArchetypedPattern, + ArchetypeSearchResponse, + SynchronicityPattern, + DreamConsolidation, ) from .services.agents import ( Agent, @@ -56,6 +64,7 @@ AgentService, AsyncAgentService, ) +from .services.jungian import JungianService, AsyncJungianService __all__ = [ "PluggedInClient", @@ -103,4 +112,14 @@ "AgentDetails", "AgentService", "AsyncAgentService", + # Jungian Intelligence types + "IndividuationComponents", + "IndividuationResponse", + "IndividuationHistoryEntry", + "ArchetypedPattern", + "ArchetypeSearchResponse", + "SynchronicityPattern", + "DreamConsolidation", + "JungianService", + "AsyncJungianService", ] diff --git a/src/pluggedinkit/client.py b/src/pluggedinkit/client.py index f52df0a..cbf1a43 100644 --- a/src/pluggedinkit/client.py +++ b/src/pluggedinkit/client.py @@ -14,6 +14,7 @@ ) from .services.clipboard import ClipboardService, AsyncClipboardService from .services.documents import DocumentService, AsyncDocumentService +from .services.jungian import JungianService, AsyncJungianService from .services.rag import RagService, AsyncRagService from .services.uploads import UploadService, AsyncUploadService from .services.agents import AgentService, AsyncAgentService @@ -100,6 +101,7 @@ def __init__( # Initialize services self.clipboard = ClipboardService(self) self.documents = DocumentService(self) + self.jungian = JungianService(self) self.rag = RagService(self) self.uploads = UploadService(self) self.agents = AgentService(self) @@ -201,6 +203,7 @@ def __init__( # Initialize async services self.clipboard = AsyncClipboardService(self) self.documents = AsyncDocumentService(self) + self.jungian = AsyncJungianService(self) self.rag = AsyncRagService(self) self.uploads = AsyncUploadService(self) self.agents = AsyncAgentService(self) diff --git a/src/pluggedinkit/services/__init__.py b/src/pluggedinkit/services/__init__.py index cff8617..019e5ae 100644 --- a/src/pluggedinkit/services/__init__.py +++ b/src/pluggedinkit/services/__init__.py @@ -2,6 +2,7 @@ from .clipboard import AsyncClipboardService, ClearAllResult, ClipboardService from .documents import AsyncDocumentService, DocumentService +from .jungian import AsyncJungianService, JungianService from .rag import AsyncRagService, RagService from .uploads import AsyncUploadService, UploadService @@ -11,6 +12,8 @@ "ClearAllResult", "DocumentService", "AsyncDocumentService", + "JungianService", + "AsyncJungianService", "RagService", "AsyncRagService", "UploadService", diff --git a/src/pluggedinkit/services/jungian.py b/src/pluggedinkit/services/jungian.py new file mode 100644 index 0000000..979d464 --- /dev/null +++ b/src/pluggedinkit/services/jungian.py @@ -0,0 +1,301 @@ +"""Jungian Intelligence Layer service for Plugged.in SDK + +Provides access to the Jungian-inspired intelligence layer including +archetype-aware pattern search, individuation scoring, synchronicity +detection, and dream-cycle consolidation history. +""" + +from typing import TYPE_CHECKING, Any, Dict, List, Optional + +from ..exceptions import PluggedInError +from ..types import ( + ArchetypedPattern, + ArchetypeSearchResponse, + DreamConsolidation, + IndividuationHistoryEntry, + IndividuationResponse, + SynchronicityPattern, +) + +if TYPE_CHECKING: + from ..client import AsyncPluggedInClient, PluggedInClient + + +# ----------------------------------------------------------------------------- +# Shared Helper Functions +# ----------------------------------------------------------------------------- + + +def _parse_archetype_search(data: Dict[str, Any]) -> ArchetypeSearchResponse: + """Parse the archetype search response into typed model.""" + patterns_raw = data.get("patterns", []) + patterns = [ArchetypedPattern(**p) for p in patterns_raw] + return ArchetypeSearchResponse(patterns=patterns) + + +def _parse_individuation(data: Dict[str, Any]) -> IndividuationResponse: + """Parse the individuation score response into typed model.""" + return IndividuationResponse(**data) + + +def _parse_individuation_history(data: Any) -> List[IndividuationHistoryEntry]: + """Parse the individuation history response into typed list.""" + if isinstance(data, list): + return [IndividuationHistoryEntry(**entry) for entry in data] + # If wrapped in an object, try the 'history' key + if isinstance(data, dict): + entries = data.get("history", data.get("entries", [])) + return [IndividuationHistoryEntry(**entry) for entry in entries] + return [] + + +def _parse_synchronicity_patterns(data: Any) -> List[SynchronicityPattern]: + """Parse synchronicity patterns response.""" + if isinstance(data, list): + return [SynchronicityPattern(**p) for p in data] + if isinstance(data, dict): + patterns = data.get("patterns", []) + return [SynchronicityPattern(**p) for p in patterns] + return [] + + +def _parse_dream_history(data: Any) -> List[DreamConsolidation]: + """Parse dream consolidation history response.""" + if isinstance(data, list): + return [DreamConsolidation(**d) for d in data] + if isinstance(data, dict): + entries = data.get("history", data.get("consolidations", [])) + return [DreamConsolidation(**d) for d in entries] + return [] + + +# ----------------------------------------------------------------------------- +# Synchronous Jungian Service +# ----------------------------------------------------------------------------- + + +class JungianService: + """Synchronous Jungian Intelligence Layer service for Plugged.in. + + Provides archetype-aware pattern search, individuation scoring, + synchronicity detection, and dream-cycle consolidation history. + """ + + def __init__(self, client: "PluggedInClient"): + self.client = client + + def search_with_context( + self, + query: str, + tool_name: Optional[str] = None, + outcome: Optional[str] = None, + ) -> ArchetypeSearchResponse: + """Search patterns with archetype context injection. + + Sends a query to the archetype inject endpoint which returns + patterns enriched with Jungian archetype classifications. + + Args: + query: Natural language search query + tool_name: Optional tool name for context + outcome: Optional outcome description for context + + Returns: + ArchetypeSearchResponse with classified patterns + + Raises: + PluggedInError: If the API request fails + """ + payload: Dict[str, Any] = {"query": query} + if tool_name is not None: + payload["tool_name"] = tool_name + if outcome is not None: + payload["outcome"] = outcome + + response = self.client.request( + "POST", "/api/memory/archetype/inject", json=payload + ) + return _parse_archetype_search(response.json()) + + def get_individuation_score(self) -> IndividuationResponse: + """Get the current individuation score. + + The individuation score measures the agent's psychological + development across four components: memory depth, learning + velocity, collective contribution, and self-awareness. + + Returns: + IndividuationResponse with score, level, trend, and components + + Raises: + PluggedInError: If the API request fails + """ + response = self.client.request("GET", "/api/memory/individuation") + return _parse_individuation(response.json()) + + def get_individuation_history( + self, days: int = 30 + ) -> List[IndividuationHistoryEntry]: + """Get individuation score history over a time period. + + Args: + days: Number of days of history to retrieve (default: 30) + + Returns: + List of IndividuationHistoryEntry ordered by date + + Raises: + PluggedInError: If the API request fails + """ + response = self.client.request( + "GET", + "/api/memory/individuation", + params={"history": "true", "days": str(days)}, + ) + return _parse_individuation_history(response.json()) + + def get_synchronicity_patterns(self) -> List[SynchronicityPattern]: + """Get detected synchronicity patterns. + + Synchronicity patterns are meaningful coincidences detected + across multiple profiles in the collective unconscious layer. + + Returns: + List of SynchronicityPattern instances + + Raises: + PluggedInError: If the API request fails + """ + response = self.client.request("GET", "/api/memory/sync/patterns") + return _parse_synchronicity_patterns(response.json()) + + def get_dream_history(self) -> List[DreamConsolidation]: + """Get dream-cycle consolidation history. + + Dream consolidations represent periodic memory compression + cycles that merge similar patterns and reduce token usage. + + Returns: + List of DreamConsolidation records + + Raises: + PluggedInError: If the API request fails + """ + response = self.client.request("GET", "/api/memory/dream/history") + return _parse_dream_history(response.json()) + + +# ----------------------------------------------------------------------------- +# Asynchronous Jungian Service +# ----------------------------------------------------------------------------- + + +class AsyncJungianService: + """Asynchronous Jungian Intelligence Layer service for Plugged.in. + + Provides archetype-aware pattern search, individuation scoring, + synchronicity detection, and dream-cycle consolidation history. + """ + + def __init__(self, client: "AsyncPluggedInClient"): + self.client = client + + async def search_with_context( + self, + query: str, + tool_name: Optional[str] = None, + outcome: Optional[str] = None, + ) -> ArchetypeSearchResponse: + """Search patterns with archetype context injection. + + Sends a query to the archetype inject endpoint which returns + patterns enriched with Jungian archetype classifications. + + Args: + query: Natural language search query + tool_name: Optional tool name for context + outcome: Optional outcome description for context + + Returns: + ArchetypeSearchResponse with classified patterns + + Raises: + PluggedInError: If the API request fails + """ + payload: Dict[str, Any] = {"query": query} + if tool_name is not None: + payload["tool_name"] = tool_name + if outcome is not None: + payload["outcome"] = outcome + + response = await self.client.request( + "POST", "/api/memory/archetype/inject", json=payload + ) + return _parse_archetype_search(response.json()) + + async def get_individuation_score(self) -> IndividuationResponse: + """Get the current individuation score. + + The individuation score measures the agent's psychological + development across four components: memory depth, learning + velocity, collective contribution, and self-awareness. + + Returns: + IndividuationResponse with score, level, trend, and components + + Raises: + PluggedInError: If the API request fails + """ + response = await self.client.request("GET", "/api/memory/individuation") + return _parse_individuation(response.json()) + + async def get_individuation_history( + self, days: int = 30 + ) -> List[IndividuationHistoryEntry]: + """Get individuation score history over a time period. + + Args: + days: Number of days of history to retrieve (default: 30) + + Returns: + List of IndividuationHistoryEntry ordered by date + + Raises: + PluggedInError: If the API request fails + """ + response = await self.client.request( + "GET", + "/api/memory/individuation", + params={"history": "true", "days": str(days)}, + ) + return _parse_individuation_history(response.json()) + + async def get_synchronicity_patterns(self) -> List[SynchronicityPattern]: + """Get detected synchronicity patterns. + + Synchronicity patterns are meaningful coincidences detected + across multiple profiles in the collective unconscious layer. + + Returns: + List of SynchronicityPattern instances + + Raises: + PluggedInError: If the API request fails + """ + response = await self.client.request("GET", "/api/memory/sync/patterns") + return _parse_synchronicity_patterns(response.json()) + + async def get_dream_history(self) -> List[DreamConsolidation]: + """Get dream-cycle consolidation history. + + Dream consolidations represent periodic memory compression + cycles that merge similar patterns and reduce token usage. + + Returns: + List of DreamConsolidation records + + Raises: + PluggedInError: If the API request fails + """ + response = await self.client.request("GET", "/api/memory/dream/history") + return _parse_dream_history(response.json()) diff --git a/src/pluggedinkit/types.py b/src/pluggedinkit/types.py index aaaf352..90ad2c2 100644 --- a/src/pluggedinkit/types.py +++ b/src/pluggedinkit/types.py @@ -387,3 +387,85 @@ class ClipboardDeleteResponse(BaseModel): success: bool deleted: Optional[bool] = None error: Optional[str] = None + + +# --- Jungian Intelligence Layer --- + + +class IndividuationComponents(BaseModel): + """Components that make up the individuation score""" + memory_depth: int = Field(alias="memoryDepth") + learning_velocity: int = Field(alias="learningVelocity") + collective_contribution: int = Field(alias="collectiveContribution") + self_awareness: int = Field(alias="selfAwareness") + + class Config: + populate_by_name = True + + +class IndividuationResponse(BaseModel): + """Response for individuation score query""" + total: int + level: str + weekly_trend: str = Field(alias="weeklyTrend") + tip: str + components: IndividuationComponents + + class Config: + populate_by_name = True + + +class IndividuationHistoryEntry(BaseModel): + """A single entry in the individuation score history""" + date: str + total: int + level: str + components: IndividuationComponents + + class Config: + populate_by_name = True + + +class ArchetypedPattern(BaseModel): + """A pattern with archetype classification from the Jungian layer""" + uuid: str + archetype: str + archetype_label: str = Field(alias="archetypeLabel") + archetype_weight: float = Field(alias="archetypeWeight") + pattern_type: str = Field(alias="patternType") + description: str + pattern: str + confidence: float + similarity: float + + class Config: + populate_by_name = True + + +class ArchetypeSearchResponse(BaseModel): + """Response for archetype-aware pattern search""" + patterns: List[ArchetypedPattern] + + +class SynchronicityPattern(BaseModel): + """A meaningful coincidence pattern detected across profiles""" + uuid: str + pattern_type: str = Field(alias="patternType") + description: str + confidence: float + unique_profiles: int = Field(alias="uniqueProfiles") + + class Config: + populate_by_name = True + + +class DreamConsolidation(BaseModel): + """A dream-cycle consolidation record""" + uuid: str + source_count: int = Field(alias="sourceCount") + token_savings: int = Field(alias="tokenSavings") + cluster_similarity: float = Field(alias="clusterSimilarity") + created_at: str = Field(alias="createdAt") + + class Config: + populate_by_name = True