Skip to content

storage

Class info

Classes

Name Children Inherits
FileStorageConfig
llmling_agent_config.storage
File storage configuration.
    • BaseStorageProviderConfig
    Mem0Config
    llmling_agent_config.storage
    Configuration for mem0 storage.
      • BaseStorageProviderConfig
      MemoryStorageConfig
      llmling_agent_config.storage
      In-memory storage configuration for testing.
        • BaseStorageProviderConfig
        SQLStorageConfig
        llmling_agent_config.storage
        SQL database storage configuration.
          • BaseStorageProviderConfig
          StorageManager
          llmling_agent.storage
          Manages multiple storage providers.
            TaskManager
            llmling_agent.utils.tasks
            Mixin for managing async tasks.
              TextLogConfig
              llmling_agent_config.storage
              Text log configuration.
                • BaseStorageProviderConfig

                🛈 DocStrings

                Storage manager for handling multiple providers.

                StorageManager

                Manages multiple storage providers.

                Handles: - Provider initialization and cleanup - Message distribution to providers - History loading from capable providers - Global logging filters

                Source code in src/llmling_agent/storage.py
                 36
                 37
                 38
                 39
                 40
                 41
                 42
                 43
                 44
                 45
                 46
                 47
                 48
                 49
                 50
                 51
                 52
                 53
                 54
                 55
                 56
                 57
                 58
                 59
                 60
                 61
                 62
                 63
                 64
                 65
                 66
                 67
                 68
                 69
                 70
                 71
                 72
                 73
                 74
                 75
                 76
                 77
                 78
                 79
                 80
                 81
                 82
                 83
                 84
                 85
                 86
                 87
                 88
                 89
                 90
                 91
                 92
                 93
                 94
                 95
                 96
                 97
                 98
                 99
                100
                101
                102
                103
                104
                105
                106
                107
                108
                109
                110
                111
                112
                113
                114
                115
                116
                117
                118
                119
                120
                121
                122
                123
                124
                125
                126
                127
                128
                129
                130
                131
                132
                133
                134
                135
                136
                137
                138
                139
                140
                141
                142
                143
                144
                145
                146
                147
                148
                149
                150
                151
                152
                153
                154
                155
                156
                157
                158
                159
                160
                161
                162
                163
                164
                165
                166
                167
                168
                169
                170
                171
                172
                173
                174
                175
                176
                177
                178
                179
                180
                181
                182
                183
                184
                185
                186
                187
                188
                189
                190
                191
                192
                193
                194
                195
                196
                197
                198
                199
                200
                201
                202
                203
                204
                205
                206
                207
                208
                209
                210
                211
                212
                213
                214
                215
                216
                217
                218
                219
                220
                221
                222
                223
                224
                225
                226
                227
                228
                229
                230
                231
                232
                233
                234
                235
                236
                237
                238
                239
                240
                241
                242
                243
                244
                245
                246
                247
                248
                249
                250
                251
                252
                253
                254
                255
                256
                257
                258
                259
                260
                261
                262
                263
                264
                265
                266
                267
                268
                269
                270
                271
                272
                273
                274
                275
                276
                277
                278
                279
                280
                281
                282
                283
                284
                285
                286
                287
                288
                289
                290
                291
                292
                293
                294
                295
                296
                297
                298
                299
                300
                301
                302
                303
                304
                305
                306
                307
                308
                309
                310
                311
                312
                313
                314
                315
                316
                317
                318
                319
                320
                321
                322
                323
                324
                325
                326
                327
                328
                329
                330
                331
                332
                333
                334
                335
                336
                337
                338
                339
                340
                341
                342
                343
                344
                345
                346
                347
                348
                349
                350
                351
                352
                353
                354
                355
                356
                357
                358
                359
                360
                361
                362
                363
                364
                365
                366
                367
                368
                369
                370
                371
                372
                373
                374
                375
                376
                377
                378
                379
                380
                381
                382
                383
                384
                385
                386
                387
                388
                389
                390
                391
                392
                393
                394
                395
                396
                397
                398
                399
                400
                401
                402
                403
                404
                405
                406
                407
                408
                409
                410
                411
                412
                413
                414
                415
                416
                417
                418
                419
                420
                421
                422
                423
                424
                425
                class StorageManager:
                    """Manages multiple storage providers.
                
                    Handles:
                    - Provider initialization and cleanup
                    - Message distribution to providers
                    - History loading from capable providers
                    - Global logging filters
                    """
                
                    def __init__(self, config: StorageConfig):
                        """Initialize storage manager.
                
                        Args:
                            config: Storage configuration including providers and filters
                        """
                        self.config = config
                        self.task_manager = TaskManager()
                        self.providers = [
                            self._create_provider(cfg) for cfg in self.config.effective_providers
                        ]
                
                    async def __aenter__(self) -> Self:
                        """Initialize all providers."""
                        for provider in self.providers:
                            await provider.__aenter__()
                        return self
                
                    async def __aexit__(
                        self,
                        exc_type: type[BaseException] | None,
                        exc_val: BaseException | None,
                        exc_tb: TracebackType | None,
                    ):
                        """Clean up all providers."""
                        errors = []
                        for provider in self.providers:
                            try:
                                await provider.__aexit__(exc_type, exc_val, exc_tb)
                            except Exception as e:
                                errors.append(e)
                                logger.exception("Error cleaning up provider: %r", provider)
                
                        await self.task_manager.cleanup_tasks()
                
                        if errors:
                            msg = "Provider cleanup errors"
                            raise ExceptionGroup(msg, errors)
                
                    def cleanup(self):
                        """Clean up all providers."""
                        for provider in self.providers:
                            try:
                                provider.cleanup()
                            except Exception:
                                logger.exception("Error cleaning up provider: %r", provider)
                        self.providers.clear()
                
                    def _create_provider(self, config: BaseStorageProviderConfig) -> StorageProvider:
                        """Create provider instance from configuration."""
                        # Extract common settings from BaseStorageProviderConfig
                        match self.config.filter_mode:
                            case "and" if self.config.agents and config.agents:
                                logged_agents = self.config.agents & config.agents
                            case "and":
                                logged_agents = self.config.agents or config.agents or set()
                            case "override":
                                logged_agents = (
                                    config.agents
                                    if config.agents is not None
                                    else self.config.agents or set()
                                )
                
                        provider_config = config.model_copy(
                            update={
                                "log_messages": config.log_messages and self.config.log_messages,
                                "log_conversations": config.log_conversations
                                and self.config.log_conversations,
                                "log_tool_calls": config.log_tool_calls and self.config.log_tool_calls,
                                "log_commands": config.log_commands and self.config.log_commands,
                                "log_context": config.log_context and self.config.log_context,
                                "agents": logged_agents,
                            }
                        )
                
                        match provider_config:
                            case SQLStorageConfig():
                                from sqlmodel import create_engine
                
                                from llmling_agent_storage.sql_provider import SQLModelProvider
                
                                engine = create_engine(
                                    provider_config.url, pool_size=provider_config.pool_size
                                )
                                return SQLModelProvider(provider_config, engine)
                            case FileStorageConfig():
                                from llmling_agent_storage.file_provider import FileProvider
                
                                return FileProvider(provider_config)
                            case TextLogConfig():
                                from llmling_agent_storage.text_log_provider import TextLogProvider
                
                                return TextLogProvider(provider_config)
                
                            case Mem0Config():
                                from llmling_agent_storage.mem0 import Mem0StorageProvider
                
                                return Mem0StorageProvider(provider_config)
                
                            case MemoryStorageConfig():
                                from llmling_agent_storage.memory_provider import MemoryStorageProvider
                
                                return MemoryStorageProvider(provider_config)
                            case _:
                                msg = f"Unknown provider type: {provider_config}"
                                raise ValueError(msg)
                
                    def get_history_provider(self, preferred: str | None = None) -> StorageProvider:
                        """Get provider for loading history.
                
                        Args:
                            preferred: Optional preferred provider name
                
                        Returns:
                            First capable provider based on priority:
                            1. Preferred provider if specified and capable
                            2. Default provider if specified and capable
                            3. First capable provider
                            4. Raises error if no capable provider found
                        """
                
                        # Function to find capable provider by name
                        def find_provider(name: str) -> StorageProvider | None:
                            for p in self.providers:
                                if (
                                    not getattr(p, "write_only", False)
                                    and p.can_load_history
                                    and p.__class__.__name__.lower() == name.lower()
                                ):
                                    return p
                            return None
                
                        # Try preferred provider
                        if preferred and (provider := find_provider(preferred)):
                            return provider
                
                        # Try default provider
                        if self.config.default_provider:
                            if provider := find_provider(self.config.default_provider):
                                return provider
                            msg = "Default provider %s not found or not capable of loading history"
                            logger.warning(msg, self.config.default_provider)
                
                        # Find first capable provider
                        for provider in self.providers:
                            if not getattr(provider, "write_only", False) and provider.can_load_history:
                                return provider
                
                        msg = "No capable provider found for loading history"
                        raise RuntimeError(msg)
                
                    async def filter_messages(
                        self,
                        query: SessionQuery,
                        preferred_provider: str | None = None,
                    ) -> list[ChatMessage[str]]:
                        """Get messages matching query.
                
                        Args:
                            query: Filter criteria
                            preferred_provider: Optional preferred provider to use
                        """
                        provider = self.get_history_provider(preferred_provider)
                        return await provider.filter_messages(query)
                
                    async def log_message(
                        self,
                        *,
                        conversation_id: str,
                        message_id: str,
                        content: str,
                        role: str,
                        name: str | None = None,
                        cost_info: TokenCost | None = None,
                        model: str | None = None,
                        response_time: float | None = None,
                        forwarded_from: list[str] | None = None,
                    ):
                        """Log message to all providers."""
                        if not self.config.log_messages:
                            return
                
                        for provider in self.providers:
                            if provider.should_log_agent(name or "no name"):
                                self.task_manager.create_task(
                                    provider.log_message(
                                        conversation_id=conversation_id,
                                        message_id=message_id,
                                        content=content,
                                        role=role,
                                        name=name,
                                        cost_info=cost_info,
                                        model=model,
                                        response_time=response_time,
                                        forwarded_from=forwarded_from,
                                    )
                                )
                
                    async def log_conversation(
                        self,
                        *,
                        conversation_id: str,
                        node_name: str,
                        start_time: datetime | None = None,
                    ):
                        """Log conversation to all providers."""
                        if not self.config.log_conversations:
                            return
                
                        for provider in self.providers:
                            self.task_manager.create_task(
                                provider.log_conversation(
                                    conversation_id=conversation_id,
                                    node_name=node_name,
                                    start_time=start_time,
                                )
                            )
                
                    async def log_tool_call(
                        self,
                        *,
                        conversation_id: str,
                        message_id: str,
                        tool_call: ToolCallInfo,
                    ):
                        """Log tool call to all providers."""
                        if not self.config.log_tool_calls:
                            return
                
                        for provider in self.providers:
                            self.task_manager.create_task(
                                provider.log_tool_call(
                                    conversation_id=conversation_id,
                                    message_id=message_id,
                                    tool_call=tool_call,
                                )
                            )
                
                    async def log_command(
                        self,
                        *,
                        agent_name: str,
                        session_id: str,
                        command: str,
                        context_type: type | None = None,
                        metadata: dict[str, JsonValue] | None = None,
                    ):
                        """Log command to all providers."""
                        if not self.config.log_commands:
                            return
                
                        for provider in self.providers:
                            self.task_manager.create_task(
                                provider.log_command(
                                    agent_name=agent_name,
                                    session_id=session_id,
                                    command=command,
                                    context_type=context_type,
                                    metadata=metadata,
                                )
                            )
                
                    async def log_context_message(
                        self,
                        *,
                        conversation_id: str,
                        content: str,
                        role: str,
                        name: str | None = None,
                        model: str | None = None,
                    ):
                        """Log context message to all providers."""
                        for provider in self.providers:
                            self.task_manager.create_task(
                                provider.log_context_message(
                                    conversation_id=conversation_id,
                                    content=content,
                                    role=role,
                                    name=name,
                                    model=model,
                                )
                            )
                
                    async def reset(
                        self,
                        *,
                        agent_name: str | None = None,
                        hard: bool = False,
                    ) -> tuple[int, int]:
                        """Reset storage in all providers concurrently."""
                
                        async def reset_provider(provider: StorageProvider) -> tuple[int, int]:
                            try:
                                return await provider.reset(agent_name=agent_name, hard=hard)
                            except Exception:
                                msg = "Error resetting provider: %r"
                                logger.exception(msg, provider.__class__.__name__)
                                return (0, 0)
                
                        results = await asyncio.gather(
                            *(reset_provider(provider) for provider in self.providers)
                        )
                        # Return the counts from the last provider (maintaining existing behavior)
                        return results[-1] if results else (0, 0)
                
                    async def get_conversation_counts(
                        self,
                        *,
                        agent_name: str | None = None,
                    ) -> tuple[int, int]:
                        """Get counts from primary provider."""
                        provider = self.get_history_provider()
                        return await provider.get_conversation_counts(agent_name=agent_name)
                
                    async def get_commands(
                        self,
                        agent_name: str,
                        session_id: str,
                        *,
                        limit: int | None = None,
                        current_session_only: bool = False,
                        preferred_provider: str | None = None,
                    ) -> list[str]:
                        """Get command history."""
                        if not self.config.log_commands:
                            return []
                
                        provider = self.get_history_provider(preferred_provider)
                        return await provider.get_commands(
                            agent_name=agent_name,
                            session_id=session_id,
                            limit=limit,
                            current_session_only=current_session_only,
                        )
                
                    # Sync wrappers
                    def reset_sync(self, *args, **kwargs) -> tuple[int, int]:
                        """Sync wrapper for reset."""
                        return self.task_manager.run_task_sync(self.reset(*args, **kwargs))
                
                    def get_conversation_counts_sync(self, *args, **kwargs) -> tuple[int, int]:
                        """Sync wrapper for get_conversation_counts."""
                        return self.task_manager.run_task_sync(
                            self.get_conversation_counts(*args, **kwargs)
                        )
                
                    def log_conversation_sync(self, *args, **kwargs):
                        """Sync wrapper for log_conversation."""
                        for provider in self.providers:
                            provider.log_conversation_sync(*args, **kwargs)
                
                    def log_message_sync(self, *args, **kwargs):
                        """Sync wrapper for log_message."""
                        for provider in self.providers:
                            provider.log_message_sync(*args, **kwargs)
                
                    def log_tool_call_sync(self, *args, **kwargs):
                        """Sync wrapper for log_tool_call."""
                        for provider in self.providers:
                            provider.log_tool_call_sync(*args, **kwargs)
                
                    def log_command_sync(self, *args, **kwargs):
                        """Sync wrapper for log_command."""
                        for provider in self.providers:
                            provider.log_command_sync(*args, **kwargs)
                
                    def get_commands_sync(self, *args, **kwargs) -> list[str]:
                        """Sync wrapper for get_commands."""
                        provider = self.get_history_provider()
                        return provider.get_commands_sync(*args, **kwargs)
                
                    def filter_messages_sync(self, *args, **kwargs) -> list[ChatMessage[str]]:
                        """Sync wrapper for filter_messages."""
                        provider = self.get_history_provider()
                        return provider.filter_messages_sync(*args, **kwargs)
                
                    def log_context_message_sync(self, *args, **kwargs):
                        """Sync wrapper for log_context_message."""
                        for provider in self.providers:
                            provider.log_context_message_sync(*args, **kwargs)
                

                __aenter__ async

                __aenter__() -> Self
                

                Initialize all providers.

                Source code in src/llmling_agent/storage.py
                58
                59
                60
                61
                62
                async def __aenter__(self) -> Self:
                    """Initialize all providers."""
                    for provider in self.providers:
                        await provider.__aenter__()
                    return self
                

                __aexit__ async

                __aexit__(
                    exc_type: type[BaseException] | None,
                    exc_val: BaseException | None,
                    exc_tb: TracebackType | None,
                )
                

                Clean up all providers.

                Source code in src/llmling_agent/storage.py
                64
                65
                66
                67
                68
                69
                70
                71
                72
                73
                74
                75
                76
                77
                78
                79
                80
                81
                82
                83
                async def __aexit__(
                    self,
                    exc_type: type[BaseException] | None,
                    exc_val: BaseException | None,
                    exc_tb: TracebackType | None,
                ):
                    """Clean up all providers."""
                    errors = []
                    for provider in self.providers:
                        try:
                            await provider.__aexit__(exc_type, exc_val, exc_tb)
                        except Exception as e:
                            errors.append(e)
                            logger.exception("Error cleaning up provider: %r", provider)
                
                    await self.task_manager.cleanup_tasks()
                
                    if errors:
                        msg = "Provider cleanup errors"
                        raise ExceptionGroup(msg, errors)
                

                __init__

                __init__(config: StorageConfig)
                

                Initialize storage manager.

                Parameters:

                Name Type Description Default
                config StorageConfig

                Storage configuration including providers and filters

                required
                Source code in src/llmling_agent/storage.py
                46
                47
                48
                49
                50
                51
                52
                53
                54
                55
                56
                def __init__(self, config: StorageConfig):
                    """Initialize storage manager.
                
                    Args:
                        config: Storage configuration including providers and filters
                    """
                    self.config = config
                    self.task_manager = TaskManager()
                    self.providers = [
                        self._create_provider(cfg) for cfg in self.config.effective_providers
                    ]
                

                cleanup

                cleanup()
                

                Clean up all providers.

                Source code in src/llmling_agent/storage.py
                85
                86
                87
                88
                89
                90
                91
                92
                def cleanup(self):
                    """Clean up all providers."""
                    for provider in self.providers:
                        try:
                            provider.cleanup()
                        except Exception:
                            logger.exception("Error cleaning up provider: %r", provider)
                    self.providers.clear()
                

                filter_messages async

                filter_messages(
                    query: SessionQuery, preferred_provider: str | None = None
                ) -> list[ChatMessage[str]]
                

                Get messages matching query.

                Parameters:

                Name Type Description Default
                query SessionQuery

                Filter criteria

                required
                preferred_provider str | None

                Optional preferred provider to use

                None
                Source code in src/llmling_agent/storage.py
                197
                198
                199
                200
                201
                202
                203
                204
                205
                206
                207
                208
                209
                async def filter_messages(
                    self,
                    query: SessionQuery,
                    preferred_provider: str | None = None,
                ) -> list[ChatMessage[str]]:
                    """Get messages matching query.
                
                    Args:
                        query: Filter criteria
                        preferred_provider: Optional preferred provider to use
                    """
                    provider = self.get_history_provider(preferred_provider)
                    return await provider.filter_messages(query)
                

                filter_messages_sync

                filter_messages_sync(*args, **kwargs) -> list[ChatMessage[str]]
                

                Sync wrapper for filter_messages.

                Source code in src/llmling_agent/storage.py
                417
                418
                419
                420
                def filter_messages_sync(self, *args, **kwargs) -> list[ChatMessage[str]]:
                    """Sync wrapper for filter_messages."""
                    provider = self.get_history_provider()
                    return provider.filter_messages_sync(*args, **kwargs)
                

                get_commands async

                get_commands(
                    agent_name: str,
                    session_id: str,
                    *,
                    limit: int | None = None,
                    current_session_only: bool = False,
                    preferred_provider: str | None = None,
                ) -> list[str]
                

                Get command history.

                Source code in src/llmling_agent/storage.py
                360
                361
                362
                363
                364
                365
                366
                367
                368
                369
                370
                371
                372
                373
                374
                375
                376
                377
                378
                379
                async def get_commands(
                    self,
                    agent_name: str,
                    session_id: str,
                    *,
                    limit: int | None = None,
                    current_session_only: bool = False,
                    preferred_provider: str | None = None,
                ) -> list[str]:
                    """Get command history."""
                    if not self.config.log_commands:
                        return []
                
                    provider = self.get_history_provider(preferred_provider)
                    return await provider.get_commands(
                        agent_name=agent_name,
                        session_id=session_id,
                        limit=limit,
                        current_session_only=current_session_only,
                    )
                

                get_commands_sync

                get_commands_sync(*args, **kwargs) -> list[str]
                

                Sync wrapper for get_commands.

                Source code in src/llmling_agent/storage.py
                412
                413
                414
                415
                def get_commands_sync(self, *args, **kwargs) -> list[str]:
                    """Sync wrapper for get_commands."""
                    provider = self.get_history_provider()
                    return provider.get_commands_sync(*args, **kwargs)
                

                get_conversation_counts async

                get_conversation_counts(*, agent_name: str | None = None) -> tuple[int, int]
                

                Get counts from primary provider.

                Source code in src/llmling_agent/storage.py
                351
                352
                353
                354
                355
                356
                357
                358
                async def get_conversation_counts(
                    self,
                    *,
                    agent_name: str | None = None,
                ) -> tuple[int, int]:
                    """Get counts from primary provider."""
                    provider = self.get_history_provider()
                    return await provider.get_conversation_counts(agent_name=agent_name)
                

                get_conversation_counts_sync

                get_conversation_counts_sync(*args, **kwargs) -> tuple[int, int]
                

                Sync wrapper for get_conversation_counts.

                Source code in src/llmling_agent/storage.py
                386
                387
                388
                389
                390
                def get_conversation_counts_sync(self, *args, **kwargs) -> tuple[int, int]:
                    """Sync wrapper for get_conversation_counts."""
                    return self.task_manager.run_task_sync(
                        self.get_conversation_counts(*args, **kwargs)
                    )
                

                get_history_provider

                get_history_provider(preferred: str | None = None) -> StorageProvider
                

                Get provider for loading history.

                Parameters:

                Name Type Description Default
                preferred str | None

                Optional preferred provider name

                None

                Returns:

                Type Description
                StorageProvider

                First capable provider based on priority:

                StorageProvider
                1. Preferred provider if specified and capable
                StorageProvider
                1. Default provider if specified and capable
                StorageProvider
                1. First capable provider
                StorageProvider
                1. Raises error if no capable provider found
                Source code in src/llmling_agent/storage.py
                153
                154
                155
                156
                157
                158
                159
                160
                161
                162
                163
                164
                165
                166
                167
                168
                169
                170
                171
                172
                173
                174
                175
                176
                177
                178
                179
                180
                181
                182
                183
                184
                185
                186
                187
                188
                189
                190
                191
                192
                193
                194
                195
                def get_history_provider(self, preferred: str | None = None) -> StorageProvider:
                    """Get provider for loading history.
                
                    Args:
                        preferred: Optional preferred provider name
                
                    Returns:
                        First capable provider based on priority:
                        1. Preferred provider if specified and capable
                        2. Default provider if specified and capable
                        3. First capable provider
                        4. Raises error if no capable provider found
                    """
                
                    # Function to find capable provider by name
                    def find_provider(name: str) -> StorageProvider | None:
                        for p in self.providers:
                            if (
                                not getattr(p, "write_only", False)
                                and p.can_load_history
                                and p.__class__.__name__.lower() == name.lower()
                            ):
                                return p
                        return None
                
                    # Try preferred provider
                    if preferred and (provider := find_provider(preferred)):
                        return provider
                
                    # Try default provider
                    if self.config.default_provider:
                        if provider := find_provider(self.config.default_provider):
                            return provider
                        msg = "Default provider %s not found or not capable of loading history"
                        logger.warning(msg, self.config.default_provider)
                
                    # Find first capable provider
                    for provider in self.providers:
                        if not getattr(provider, "write_only", False) and provider.can_load_history:
                            return provider
                
                    msg = "No capable provider found for loading history"
                    raise RuntimeError(msg)
                

                log_command async

                log_command(
                    *,
                    agent_name: str,
                    session_id: str,
                    command: str,
                    context_type: type | None = None,
                    metadata: dict[str, JsonValue] | None = None,
                )
                

                Log command to all providers.

                Source code in src/llmling_agent/storage.py
                284
                285
                286
                287
                288
                289
                290
                291
                292
                293
                294
                295
                296
                297
                298
                299
                300
                301
                302
                303
                304
                305
                306
                async def log_command(
                    self,
                    *,
                    agent_name: str,
                    session_id: str,
                    command: str,
                    context_type: type | None = None,
                    metadata: dict[str, JsonValue] | None = None,
                ):
                    """Log command to all providers."""
                    if not self.config.log_commands:
                        return
                
                    for provider in self.providers:
                        self.task_manager.create_task(
                            provider.log_command(
                                agent_name=agent_name,
                                session_id=session_id,
                                command=command,
                                context_type=context_type,
                                metadata=metadata,
                            )
                        )
                

                log_command_sync

                log_command_sync(*args, **kwargs)
                

                Sync wrapper for log_command.

                Source code in src/llmling_agent/storage.py
                407
                408
                409
                410
                def log_command_sync(self, *args, **kwargs):
                    """Sync wrapper for log_command."""
                    for provider in self.providers:
                        provider.log_command_sync(*args, **kwargs)
                

                log_context_message async

                log_context_message(
                    *,
                    conversation_id: str,
                    content: str,
                    role: str,
                    name: str | None = None,
                    model: str | None = None,
                )
                

                Log context message to all providers.

                Source code in src/llmling_agent/storage.py
                308
                309
                310
                311
                312
                313
                314
                315
                316
                317
                318
                319
                320
                321
                322
                323
                324
                325
                326
                327
                async def log_context_message(
                    self,
                    *,
                    conversation_id: str,
                    content: str,
                    role: str,
                    name: str | None = None,
                    model: str | None = None,
                ):
                    """Log context message to all providers."""
                    for provider in self.providers:
                        self.task_manager.create_task(
                            provider.log_context_message(
                                conversation_id=conversation_id,
                                content=content,
                                role=role,
                                name=name,
                                model=model,
                            )
                        )
                

                log_context_message_sync

                log_context_message_sync(*args, **kwargs)
                

                Sync wrapper for log_context_message.

                Source code in src/llmling_agent/storage.py
                422
                423
                424
                425
                def log_context_message_sync(self, *args, **kwargs):
                    """Sync wrapper for log_context_message."""
                    for provider in self.providers:
                        provider.log_context_message_sync(*args, **kwargs)
                

                log_conversation async

                log_conversation(
                    *, conversation_id: str, node_name: str, start_time: datetime | None = None
                )
                

                Log conversation to all providers.

                Source code in src/llmling_agent/storage.py
                244
                245
                246
                247
                248
                249
                250
                251
                252
                253
                254
                255
                256
                257
                258
                259
                260
                261
                262
                async def log_conversation(
                    self,
                    *,
                    conversation_id: str,
                    node_name: str,
                    start_time: datetime | None = None,
                ):
                    """Log conversation to all providers."""
                    if not self.config.log_conversations:
                        return
                
                    for provider in self.providers:
                        self.task_manager.create_task(
                            provider.log_conversation(
                                conversation_id=conversation_id,
                                node_name=node_name,
                                start_time=start_time,
                            )
                        )
                

                log_conversation_sync

                log_conversation_sync(*args, **kwargs)
                

                Sync wrapper for log_conversation.

                Source code in src/llmling_agent/storage.py
                392
                393
                394
                395
                def log_conversation_sync(self, *args, **kwargs):
                    """Sync wrapper for log_conversation."""
                    for provider in self.providers:
                        provider.log_conversation_sync(*args, **kwargs)
                

                log_message async

                log_message(
                    *,
                    conversation_id: str,
                    message_id: str,
                    content: str,
                    role: str,
                    name: str | None = None,
                    cost_info: TokenCost | None = None,
                    model: str | None = None,
                    response_time: float | None = None,
                    forwarded_from: list[str] | None = None,
                )
                

                Log message to all providers.

                Source code in src/llmling_agent/storage.py
                211
                212
                213
                214
                215
                216
                217
                218
                219
                220
                221
                222
                223
                224
                225
                226
                227
                228
                229
                230
                231
                232
                233
                234
                235
                236
                237
                238
                239
                240
                241
                242
                async def log_message(
                    self,
                    *,
                    conversation_id: str,
                    message_id: str,
                    content: str,
                    role: str,
                    name: str | None = None,
                    cost_info: TokenCost | None = None,
                    model: str | None = None,
                    response_time: float | None = None,
                    forwarded_from: list[str] | None = None,
                ):
                    """Log message to all providers."""
                    if not self.config.log_messages:
                        return
                
                    for provider in self.providers:
                        if provider.should_log_agent(name or "no name"):
                            self.task_manager.create_task(
                                provider.log_message(
                                    conversation_id=conversation_id,
                                    message_id=message_id,
                                    content=content,
                                    role=role,
                                    name=name,
                                    cost_info=cost_info,
                                    model=model,
                                    response_time=response_time,
                                    forwarded_from=forwarded_from,
                                )
                            )
                

                log_message_sync

                log_message_sync(*args, **kwargs)
                

                Sync wrapper for log_message.

                Source code in src/llmling_agent/storage.py
                397
                398
                399
                400
                def log_message_sync(self, *args, **kwargs):
                    """Sync wrapper for log_message."""
                    for provider in self.providers:
                        provider.log_message_sync(*args, **kwargs)
                

                log_tool_call async

                log_tool_call(*, conversation_id: str, message_id: str, tool_call: ToolCallInfo)
                

                Log tool call to all providers.

                Source code in src/llmling_agent/storage.py
                264
                265
                266
                267
                268
                269
                270
                271
                272
                273
                274
                275
                276
                277
                278
                279
                280
                281
                282
                async def log_tool_call(
                    self,
                    *,
                    conversation_id: str,
                    message_id: str,
                    tool_call: ToolCallInfo,
                ):
                    """Log tool call to all providers."""
                    if not self.config.log_tool_calls:
                        return
                
                    for provider in self.providers:
                        self.task_manager.create_task(
                            provider.log_tool_call(
                                conversation_id=conversation_id,
                                message_id=message_id,
                                tool_call=tool_call,
                            )
                        )
                

                log_tool_call_sync

                log_tool_call_sync(*args, **kwargs)
                

                Sync wrapper for log_tool_call.

                Source code in src/llmling_agent/storage.py
                402
                403
                404
                405
                def log_tool_call_sync(self, *args, **kwargs):
                    """Sync wrapper for log_tool_call."""
                    for provider in self.providers:
                        provider.log_tool_call_sync(*args, **kwargs)
                

                reset async

                reset(*, agent_name: str | None = None, hard: bool = False) -> tuple[int, int]
                

                Reset storage in all providers concurrently.

                Source code in src/llmling_agent/storage.py
                329
                330
                331
                332
                333
                334
                335
                336
                337
                338
                339
                340
                341
                342
                343
                344
                345
                346
                347
                348
                349
                async def reset(
                    self,
                    *,
                    agent_name: str | None = None,
                    hard: bool = False,
                ) -> tuple[int, int]:
                    """Reset storage in all providers concurrently."""
                
                    async def reset_provider(provider: StorageProvider) -> tuple[int, int]:
                        try:
                            return await provider.reset(agent_name=agent_name, hard=hard)
                        except Exception:
                            msg = "Error resetting provider: %r"
                            logger.exception(msg, provider.__class__.__name__)
                            return (0, 0)
                
                    results = await asyncio.gather(
                        *(reset_provider(provider) for provider in self.providers)
                    )
                    # Return the counts from the last provider (maintaining existing behavior)
                    return results[-1] if results else (0, 0)
                

                reset_sync

                reset_sync(*args, **kwargs) -> tuple[int, int]
                

                Sync wrapper for reset.

                Source code in src/llmling_agent/storage.py
                382
                383
                384
                def reset_sync(self, *args, **kwargs) -> tuple[int, int]:
                    """Sync wrapper for reset."""
                    return self.task_manager.run_task_sync(self.reset(*args, **kwargs))