SQL Connection Broker
- class smarter.apps.plugin.manifest.brokers.sql_connection.SAMSqlConnectionBroker(*args, **kwargs)[source]
Broker for Smarter API SQL Connection manifests.
This class is responsible for loading, validating, and parsing Smarter API YAML SqlConnection manifests, and initializing the corresponding Pydantic model. It provides generic services for SQL connections, such as instantiation, creation, update, and deletion.
Example Usage:
broker = SAMSqlConnectionBroker() manifest = broker.manifest # Returns the loaded manifest as a Pydantic model orm_dict = broker.manifest_to_django_orm() # Converts manifest to Django ORM dict
See also
SAMConnectionBaseBrokerSAMSqlConnectionSqlConnection
Raises:
SAMBrokerErrorNotReady: If required parameters (e.g., user profile, manifest) are missing.
SAMConnectionBrokerError: For invalid connection data or failed operations.
Important
This broker caches loaded manifests and connections for efficiency. Always check for existence before accessing properties.
- property ORMMetaModelClass: Type[SqlConnection]
Return the Django ORM meta model class for the broker.
- Returns:
The Django ORM meta model class definition for the broker.
- Return type:
Type[SqlConnection]
- property ORMModelClass: Type[SqlConnection]
Returns the Django ORM model class associated with this broker.
This property provides the concrete model used for SQL connection objects in the database. It is essential for operations that require direct interaction with the ORM, such as queries, creation, updates, and deletions.
- Returns:
The Django model class (SqlConnection) for SQL connection records.
See also
SqlConnection
Example Usage:
model_cls = broker.ORMModelClass queryset = model_cls.objects.filter(account=account)
- property SAMModelClass: Type[SAMSqlConnection]
Return the Pydantic model class for the broker.
- Returns:
The Pydantic model class definition for the broker.
- Return type:
Type[SAMSqlConnection]
- property SerializerClass: Type[SqlConnectionSerializer]
Returns the SerializerClass class used by the broker for SQL connection objects.
This property provides the appropriate SerializerClass for converting SqlConnection ORM instances to and from Python data structures, typically for API responses or internal processing.
- Returns:
The SerializerClass class (SqlConnectionSerializer) for SQL connection objects.
See also
SqlConnectionSerializerSqlConnection
Example Usage:
serializer_cls = broker.SerializerClass SerializerClass = serializer_cls(sql_connection_instance) data = SerializerClass.data
- property abstract_broker_logger_cache_invalidation_prefix: str
Return the logger prefix for the AbstractBroker cache invalidation.
- Returns:
The logger prefix for the AbstractBroker.
- Return type:
- property abstract_broker_logger_prefix: str
Return the logger prefix for the AbstractBroker.
- Returns:
The logger prefix for the AbstractBroker.
- Return type:
- property abstract_broker_ready_state: str
Return a string representation of the AbstractBroker’s ready state.
- Returns:
“READY” if the AbstractBroker is ready, otherwise “NOT_READY”.
- Return type:
- property account: Account | None
Returns the account for the current user. Handle lazy instantiation from user or user_profile.
- Returns:
The account for the current user.
- Return type:
Account or None
- property account_number: str | None
A helper function to get the account number from the account.
- Returns:
The account number for the current account.
- Return type:
str or None
- property accountmixin_ready_state: str
Returns a string representation of the AccountMixin ready state.
- Returns:
String representation of the AccountMixin ready state.
- Return type:
- property amnesty_urls: list[str]
Returns a list of URLs that are exempt from certain checks.
This is a placeholder and should be overridden in subclasses.
- property api_subdomain: str | None
Extracts the API subdomain from the URL.
- Returns:
The API subdomain or None if not found.
example:
- https://hr.3141-5926-5359.alpha.api.example.com/chatbot/ returns 'hr'
- property api_token: bytes | None
Get the API token from the request.
- Returns:
The API token as bytes if present in the Authorization header, otherwise None.
Example:
request_mixin = SmarterRequestMixin(request) token = request_mixin.api_token
- Returns:
The API token as bytes, or None if not present.
- property api_version: str
The API version of the manifest.
- Returns:
The API version of the manifest.
- Return type:
Optional[str]
- apply(request, *args, **kwargs)[source]
Apply the manifest: copy manifest data to the Django ORM model and save to the database.
This method loads and validates the manifest, transforms it into a Django ORM model dictionary, and updates or creates the corresponding SqlConnection object in the database. Read-only fields (such as
id,created_at,updated_at) are excluded from updates. Calls the base classapply()to ensure manifest validation before proceeding.Note
tags are handled separately because they are of type TaggableManager and require a different method to set them.
- Parameters:
request ("HttpRequest") – The Django HTTP request object.
args – Additional positional arguments (unused).
kwargs – Additional keyword arguments (unused).
- Return type:
- Returns:
A SmarterJournaledJsonResponse with the result of the apply operation.
- Raises:
SAMBrokerErrorNotReady – If no connection is found or required data is missing.
SAMConnectionBrokerError – If saving the model fails or data is invalid.
See also
SqlConnectionSmarterJournaledJsonResponseSmarterJournalCliCommandsSAMKeysSAMMetadataKeysSAMSqlConnectionSpecConnectionKeys
Example Usage:
response = broker.apply(request) print(response.data)
- property auth_header: str | None
Get the Authorization header from the request.
Example:
request_mixin = SmarterRequestMixin(request) print(request_mixin.auth_header)
This property checks for the “Authorization” header in the request headers or in the Django META dictionary.
- Returns:
The value of the “Authorization” header as a string, or None if not present.
- cache_invalidations()[source]
Invalidate any relevant caches when the manifest or connection data changes.
- Return type:
- property cache_key: str | None
Returns a cache key for the request.
This is used to cache the chat request thread. The key is a combination of: - the class name, - authenticated username, - the chat name, - and the client UID.
Currently used by the ApiV1CliChatConfigApiView and ApiV1CliChatApiView as a means of sharing the session_key.
- Parameters:
name – A generic object or resource name.
uid – UID of the client, assumed to have been created from the machine MAC address and the hostname of the client.
- Returns:
A unique cache key string.
Example:
request_mixin = SmarterRequestMixin(request) key = request_mixin.cache_key print(key) # e.g., 'a1b2c3d4e5f6...'
- camel_to_snake(data)
Converts camelCase strings, dictionary keys, or lists of such, to snake_case format.
- Parameters:
data (str, dict, or list) – The input to convert. Can be a string, a dictionary (with camelCase keys), or a list containing strings or dictionaries.
- Returns:
The converted data in snake_case format. Returns a string, dictionary, or list, matching the input type.
- Return type:
Note
For dictionaries, only keys are converted. Values are preserved as-is, except for nested dictionaries, which are also converted.
Spaces in keys are replaced with underscores.
Multiple consecutive underscores are collapsed into a single underscore.
Nested dictionaries and lists are processed recursively.
Warning
If the input is not a string, dictionary, or list, a
SmarterValueErroris raised.Example usage:
from smarter.common.utils import camel_to_snake # Convert a string print(camel_to_snake("userName")) # Output: user_name # Convert a dictionary data = { "userName": "alice", "userProfile": { "firstName": "Alice", "lastName": "Smith" } } print(camel_to_snake(data)) # Output: {'user_name': 'alice', 'user_profile': {'first_name': 'Alice', 'last_name': 'Smith'}} # Convert a list of strings print(camel_to_snake(["firstName", "lastName"])) # Output: ['first_name', 'last_name']
- chat(request, *args, **kwargs)[source]
Return a JSON response for chat interactions. This is not implemented for SQL connections.
- Raises:
SAMBrokerErrorNotImplemented – Always, as chat functionality is not supported for SQL connections.
- Parameters:
request ("HttpRequest") – The Django HTTP request object.
args – Additional positional arguments (unused).
kwargs – Additional keyword arguments (unused).
- Returns:
Never returns; always raises an error.
- Return type:
- clean_cli_param(param, param_name='unknown', url=None)
Remove any leading or trailing whitespace from the param.
Ensure that the param is a string.
Return the cleaned param.
- clear_cached_properties()
Clears all cached properties in this mixin.
- property connection: SqlConnection | None
Return the SqlConnection ORM instance for the current manifest and account.
This property retrieves the Django ORM object representing the SQL connection described by the manifest. If the connection does not exist in the database, it will be created from the manifest data (if available). The result is cached for efficiency.
- Returns:
The SqlConnection instance, or None if not found and cannot be created.
- Raises:
SAMConnectionBrokerError – If the manifest data is invalid or the ORM object cannot be created.
Important
The connection is cached after the first lookup or creation. If the underlying data changes, clear the cache to force a reload.
If neither a manifest nor an existing ORM object is available, this property returns None and logs an error.
See also
SqlConnection
Example Usage:
conn = broker.connection if conn: print(conn.connection_string) else: print("No connection found or could not be created.")
- connection_init()[source]
Initialize or reset the connection and related cached properties.
This method clears the cached SqlConnection instance and associated secrets, allowing for re-initialization or reloading of the connection data.
Example Usage:
broker.connection_init() connection = broker.connection # Re-initialized connection
- Return type:
- property created: bool
Return True if the broker was created successfully.
- Returns:
True if the broker was created successfully.
- Return type:
- property data: str | dict | list | None
Get the request body data as a dictionary, list or str.
Used for setting the session_key.
- Returns:
The request body data as a dict, list, or str, or None if not available.
Example:
request_mixin = SmarterRequestMixin(request) data = request_mixin.data print(data) # e.g., {'session_key': 'abc123', ...}
- data_to_dict(data)
Converts data to a dictionary, handling different types of input.
This method accepts either a dictionary or a string. If a string is provided, it will attempt to parse it as JSON first, and if that fails, as YAML. If parsing fails or the data type is unsupported, a SmarterValueError is raised.
- delete(request, *args, **kwargs)[source]
Delete the current SQL connection from the database.
This method removes the SqlConnection ORM instance associated with the current manifest and account. If the connection exists, it is deleted from the database and a success response is returned. If no connection is found, an error is raised.
- Parameters:
request ("HttpRequest") – The Django HTTP request object.
args – Additional positional arguments (unused).
kwargs – Additional keyword arguments (unused).
- Return type:
- Returns:
A SmarterJournaledJsonResponse indicating the result of the delete operation.
- Raises:
SAMBrokerErrorNotReady – If no connection is found to delete.
SAMConnectionBrokerError – If an error occurs during deletion.
See also
SqlConnectionSmarterJournaledJsonResponse
Example Usage:
response = broker.delete(request) if response.status == "ok": print("Connection deleted successfully.") else: print("Delete failed:", response.data)
- deploy(request, *args, **kwargs)[source]
Deploy the SQL connection. This is not implemented for SQL connections.
- Raises:
SAMBrokerErrorNotImplemented – Always, as deploy functionality is not supported for SQL connections.
- Parameters:
request ("HttpRequest") – The Django HTTP request object.
args – Additional positional arguments (unused).
kwargs – Additional keyword arguments (unused).
- Returns:
Never returns; always raises an error.
- Return type:
- describe(request, *args, **kwargs)[source]
Return a JSON response with the manifest data for the current SQL connection.
This method retrieves the current SqlConnection ORM instance, serializes its data (including metadata and status), and returns a structured JSON response suitable for API consumers or UI display. It also includes connection status such as the connection string and validation result.
- Parameters:
request ("HttpRequest") – The Django HTTP request object.
args – Additional positional arguments (unused).
kwargs – Additional keyword arguments (e.g., name).
- Return type:
- Returns:
A SmarterJournaledJsonResponse containing the manifest and connection status.
- Raises:
SAMBrokerErrorNotReady – If the user is not authenticated or the connection cannot be found.
SAMConnectionBrokerError – If serialization or data transformation fails.
See also
SqlConnectionSAMSqlConnectionSmarterJournaledJsonResponseSAMKeysSAMMetadataKeysSAMSqlConnectionStatusKeys
Example Usage:
response = broker.describe(request, name="my_connection") print(response.data)
- property domain: str | None
Extracts the domain from the URL.
- Returns:
The domain or None if not found.
examples:
- https://hr.3141-5926-5359.alpha.api.example.com/chatbot/ returns 'hr.3141-5926-5359.alpha.api.example.com'
- eval_chatbot_url()
If we are a chatbot, based on analysis of the URL format then we need to make a follow up check of the user and account.
Examples
- 1.) For named urls, we extract the account number from the url,
then we load the account and admin user for that account.
- 2.) For smarter api urls, we would extract the chatbot id from the url,
then we would load the chatbot, account, and admin user for that account.
- 3.) For cli api urls, we would extract the chatbot name from the url,
then we would load the chatbot, account, and admin user for that account.
- example_manifest(request, *args, **kwargs)[source]
Return an example manifest for the SqlConnection model.
This method generates and returns a sample manifest for a SQL connection, including all required fields and example values for supported database engines and authentication methods. The response is formatted as a JSON object suitable for use in API documentation, testing, or as a template for user submissions.
- Parameters:
request ("HttpRequest") – The Django HTTP request object.
args – Additional positional arguments (unused).
kwargs – Additional keyword arguments (unused).
- Return type:
- Returns:
A SmarterJournaledJsonResponse containing the example manifest.
See also
SAMSqlConnectionSAMSqlConnectionSpecSmarterJournaledJsonResponseDbEnginesDBMSAuthenticationMethodsSmarterJournalCliCommands
Example Usage:
response = broker.example_manifest(request) print(response.data)
- find_session_key()
Returns the unique chat session key value for this request.
The session_key is managed by the /config/ endpoint for the chatbot. The React app calls this endpoint at app initialization to get a JSON dict that includes, among other info, this session_key, which uniquely identifies the device and the individual chatbot session for the device.
For subsequent chat prompt requests, the session_key is intended to be sent in the body of the request as a key-value pair, e.g. {“session_key”: “1234567890”}.
This method will also check the request headers and cookies for the session_key. The session key can be found in one of the following:
URL parameter: http://localhost:9357/workbench/example/config/?session_key=1aeee4c1f183354247f43f80261573da921b0167c7c843b28afd3cb5ebba0d9a
Request JSON body: {‘session_key’: ‘1aeee4c1f183354247f43f80261573da921b0167c7c843b28afd3cb5ebba0d9a’}
Request header: {‘session_key’: ‘1aeee4c1f183354247f43f80261573da921b0167c7c843b28afd3cb5ebba0d9a’}
Cookie
A session_key generator
- property formatted_class_name: str
Returns a formatted class name string for logging.
This property generates a readable class name, including its parent class, to improve log clarity and traceability. Useful for debugging and monitoring, especially in complex inheritance scenarios.
- Returns:
A string representing the fully qualified class name, e.g.
ParentClass.SAMSqlConnectionBroker().
See also
SAMConnectionBaseBroker.formatted_class_name()
Example Usage:
logger.info(broker.formatted_class_name) # Output: ParentClass.SAMSqlConnectionBroker()
- property formatted_class_name_cache_invalidations: str
Return the logger prefix for the AbstractBroker cache invalidations.
- Returns:
The logger prefix for the AbstractBroker cache invalidations.
- Return type:
- property formatted_state_not_ready: str
Returns the not-ready state formatted for logging.
- Returns:
The formatted not-ready state as a string.
- Return type:
- property formatted_state_ready: str
Returns the readiness state formatted for logging.
- Returns:
The formatted readiness state as a string.
- Return type:
- generate_session_key()
Generate a session_key based on a unique string and the current datetime.
- Return type:
- Returns:
A unique session key string.
- get(request, *args, **kwargs)[source]
Retrieve SqlConnection manifests based on search criteria. This method fetches SqlConnection objects from the database that match the provided search parameters (e.g., name) and returns their serialized representations in a JSON response.
- Raises:
SAMBrokerErrorNotReady – If the required parameters (e.g., name) are not provided.
SAMConnectionBrokerError – If there is an error during data retrieval or serialization.
- Parameters:
request ("HttpRequest") – The Django HTTP request object.
args – Additional positional arguments (unused).
kwargs – Additional keyword arguments for search criteria (e.g., name).
- Return type:
- Returns:
A SmarterJournaledJsonResponse containing the serialized SqlConnection data
See also
SqlConnectionSqlConnectionSerializerSmarterJournaledJsonResponseSmarterJournalCliCommandsSAMKeysSAMMetadataKeysSCLIResponseGetSCLIResponseGetData
- get_cookie_value(cookie_name)
Retrieve the value of a cookie from the request object.
- Parameters:
request – Django HttpRequest object
cookie_name – Name of the cookie to retrieve
- Returns:
Value of the cookie or None if the cookie does not exist
- get_model_titles(serializer)
For tabular output from get() implementations. Returns a list of field names and types from the Django model serializer.
- get_or_create_secret(user_profile, name, value=None, description=None, expiration=None)
Get or create a Smarter Secret in the database. This is used to store secrets that are passed in the manifest.
- Parameters:
user_profile (UserProfile) – The UserProfile to associate the secret with.
name (str) – The name of the secret.
value (Optional[str]) – The value of the secret.
description (Optional[str]) – A description of the secret.
expiration (Optional[datetime]) – The expiration date of the secret.
- Returns:
The created or retrieved Secret object.
- Return type:
Secret
- invalidate_cached_properties()
Invalidates all cached properties on the instance to force re-evaluation.
This method removes all attributes cached by @cached_property decorators from the instance’s __dict__. It is useful for testing or when the request object changes and you need to ensure that all dependent properties are recalculated.
Example:
from smarter.lib.django.request import SmarterRequestMixin class Foo(SmarterRequestMixin): pass foo = Foo(request) foo.invalidate_cached_properties(request)
- Raises:
None –
- property ip_address: str | None
Get the client’s IP address from the request object.
This property attempts to extract the IP address from the request’s META dictionary, using the “REMOTE_ADDR” key. If the IP address is not available, it returns None.
- Returns:
The client’s IP address as a string, or None if not found.
- Return type:
Optional[str]
Example:
request_mixin = SmarterRequestMixin(request) ip = request_mixin.ip_address print(ip) # e.g., '192.168.1.100'
- property is_accountmixin_ready: bool
Returns True if the AccountMixin is ready to be used. This is a convenience property that checks if the account and user are initialized. AccountMixin is considered ready if: - self.user is an instance of User - self.user_profile is an instance of UserProfile - self.account is an instance of Account
- Returns:
True if the AccountMixin is ready to be used.
- Return type:
- property is_chatbot: bool
Returns True if the URL resolves to a chatbot endpoint.
Conditions are checked in a lazy sequence to avoid unnecessary processing.
Examples
http://localhost:9357/workbench/chatbots/<str:hashed_id>/chat/
http://localhost:9357/workbench/chatbots/<str:hashed_id>/config/
http://localhost:9357/workbench/chatbots/<str:hashed_id>/manifest/
- Returns:
True if the URL is a chatbot endpoint, otherwise False.
- Return type:
- property is_chatbot_cli_api_url: bool
9357/api/v1/cli/chat/example/.
- The expected path parts are:
[‘api’, ‘v1’, ‘cli’, ‘chat’, ‘example’]
- Returns:
True if the URL matches the CLI chatbot API pattern, otherwise False.
- Return type:
- Type:
Returns True if the URL is of the form http
- Type:
//localhost
- property is_chatbot_named_url: bool
Returns True if the url is of the form:
- Returns:
True if the URL matches the named chatbot pattern, otherwise False.
- Return type:
- property is_chatbot_sandbox_url: bool
Example URLs for chatbot sandbox endpoints.
Examples
Web console urls: - http://localhost:9357/workbench/chatbots/<str:hashed_id>/chat/ - http://localhost:9357/workbench/chatbots/<str:hashed_id>/config/ - http://localhost:9357/workbench/chatbots/<str:hashed_id>/manifest/
Api urls: - http://localhost:9357/api/v1/prompt/1/chat/ - http://localhost:9357/api/v1/prompt/1/config/
Manifest view urls: https://alpha.platform.smarter.sh/workbench/chatbots/hashed_id/ https://<environment_domain>/workbench/chatbots/<str:hashed_id>/ path_parts: [‘workbench’, ‘chatbots’, ‘rxy123hashedx’]
- Returns:
True if the URL matches a chatbot sandbox endpoint, otherwise False.
- Return type:
- property is_chatbot_smarter_api_url: bool
- Returns True if the URL is of the form:
http://localhost:9357/api/v1/workbench/1/chat/ path_parts: [‘api’, ‘v1’, ‘workbench’, ‘<int:pk>’, ‘chat’]
http://localhost:9357/api/v1/chatbots/1556/chat/ path_parts: [‘api’, ‘v1’, ‘chatbots’, ‘<int:pk>’, ‘chat’]
- Returns:
True if the URL matches a smarter API chatbot endpoint, otherwise False.
- Return type:
- property is_config: bool
Returns True if the URL resolves to a config endpoint.
Examples
http://testserver/api/v1/cli/chat/config/testc7098865f39202d5/ http://localhost:9357/workbench/example/config/?session_key=1aeee4c1f183354247f43f80261573da921b0167c7c843b28afd3cb5ebba0d9a http://localhost:9357/api/v1/workbench/<int:chatbot_id>/chat/config/ http://example.api.localhost:9357/config
- Returns:
True if the URL is a config endpoint, otherwise False.
- Return type:
- property is_dashboard: bool
Returns True if the URL resolves to a dashboard endpoint.
- Returns:
True if the URL is a dashboard endpoint, otherwise False.
- Return type:
- property is_default_domain: bool
Returns True if the URL is the default domain for the environment.
Example
api.alpha.platform.smarter.sh
- Returns:
bool: True if the URL is the default environment domain, otherwise False.
- property is_environment_root_domain: bool
Returns True if the URL resolves to the environment root domain.
- Returns:
True if the URL is the environment root domain, otherwise False.
- Return type:
- is_internal_api_request(request)
Check if the request is an internal API request.
This method checks for a custom attribute on the request object that indicates whether the request is an internal API request. This can be used to bypass certain authentication or permission checks for internal requests.
- Parameters:
request (HttpRequest) – The Django request object.
- Returns:
True if it’s an internal API request, False otherwise.
- Return type:
- property is_ready_abstract_broker: bool
Return True if the AbstractBroker is ready for operations.
An AbstractBroker is considered ready if: - The AccountMixin is ready. - The RequestMixin is ready. - either a valid manifest is loaded or a ready SAMLoader is present.
- Returns:
True if the AbstractBroker is ready for operations.
- Return type:
- property is_requestmixin_ready: bool
Returns True if the request mixin is ready for processing. This is a convenience property to check if the request is ready.
- Returns:
True if the request mixin is ready, False otherwise.
- property is_smarter_api: bool
9357/api/v1/.
Examples
path_parts: [‘api’, ‘v1’, ‘chatbots’, ‘1’, ‘chat’]
- Returns:
True if the URL matches the smarter API pattern, otherwise False.
- Return type:
- Type:
Returns True if the URL is of the form http
- Type:
//localhost
- property is_valid: bool
Return True if the SqlConnection instance exists and is valid.
This property checks whether the current SQL connection object is present and passes its internal validation logic. If the connection does not exist or validation fails, returns False and logs a warning.
- Returns:
True if the connection exists and is valid, False otherwise.
Note
returns False if no connection is found.
If validation fails, a warning is logged with the reason. Check logs for trouble shooting.
See also
SqlConnection
Example Usage:
if broker.is_valid: print("Connection is valid and ready.") else: print("Connection is missing or invalid.")
- property is_workbench: bool
Returns True if the URL resolves to a workbench endpoint.
- Returns:
True if the URL is a workbench endpoint, otherwise False.
- Return type:
- json_response_err(command, e)
Return a structured error response that can be unpacked and rendered by the cli in a variety of formats.
- Parameters:
command (SmarterJournalCliCommands) – The command that was executed.
e (Exception) – The exception that was raised.
- Returns:
A SmarterJournaledJsonResponse containing the error response.
- Return type:
- json_response_err_notfound(command, message=None)
Return a common not found response.
- Parameters:
command (SmarterJournalCliCommands) – The command that was executed.
message (Optional[str]) – An optional custom message to include in the response.
- Returns:
A SmarterJournaledJsonResponse containing the not found response.
- Return type:
- json_response_err_notimplemented(command)
Return a common not implemented response.
- Parameters:
command (SmarterJournalCliCommands) – The command that was executed.
- Returns:
A SmarterJournaledJsonResponse containing the not implemented response.
- Return type:
- json_response_err_notready(command)
Return a common not ready response.
- Parameters:
command (SmarterJournalCliCommands) – The command that was executed.
- Returns:
A SmarterJournaledJsonResponse containing the not ready response.
- Return type:
- json_response_err_readonly(command)
Return a common read-only response.
- Parameters:
command (SmarterJournalCliCommands) – The command that was executed.
- Returns:
A SmarterJournaledJsonResponse containing the read-only response.
- Return type:
- json_response_ok(command, data=None, message=None)
Return a common success response.
- Parameters:
command (SmarterJournalCliCommands) – The command that was executed.
data (Optional[dict]) – The data to return in the response.
message (Optional[str]) – An optional message to include in the response.
- Returns:
A SmarterJournaledJsonResponse containing the success response.
- Return type:
- property kind: str
Returns the manifest kind string for this broker.
This property identifies the type of manifest handled by the broker, which is used for validation, routing, and manifest processing logic. The value is typically a constant defined for the SQL connection manifest.
- Returns:
The manifest kind string (e.g.,
"SqlConnection").
See also
MANIFEST_KIND
Example Usage:
if broker.kind == "SqlConnection": # Proceed with SQL connection-specific logic
- kind_setter(value)
Set the kind of manifest. Validates that the kind is a valid SmarterJournalThings value.
- Raises:
SmarterValueError – If the kind is not valid.
- Parameters:
value (str) – The kind of manifest to set.
- property loader: SAMLoader | None
The SAMLoader instance for this broker.
- Returns:
The SAMLoader instance for this broker.
- Return type:
Optional[SAMLoader]
- log_abstract_broker_state()
Log the current state of the AbstractBroker instance for debugging purposes.
- Returns:
None
- log_account_mixin_ready_status()
Logs the ready status of the AccountMixin.
- log_request_mixin_ready_status()
Logs the ready status of the SmarterRequestMixin.
- logs(request, *args, **kwargs)[source]
Retrieve logs for the SQL connection. This is not implemented for SQL connections.
- Raises:
SAMBrokerErrorNotImplemented – Always, as log retrieval is not supported for SQL connections.
- Parameters:
request ("HttpRequest") – The Django HTTP request object.
args – Additional positional arguments (unused).
kwargs – Additional keyword arguments (unused).
- Returns:
Never returns; always raises an error.
- Return type:
- property manifest: SAMSqlConnection | None
Returns the manifest for the SQL connection as a SAMSqlConnection Pydantic model.
This property loads and initializes the top-level manifest model for a SQL connection. If the manifest has already been loaded, it is returned from cache. Otherwise, if the loader is available and its manifest kind matches, a new SAMSqlConnection model is constructed using the manifest data provided by the loader.
Child models within the manifest are automatically initialized by Pydantic when the top-level model is constructed.
- Returns:
The manifest as a SAMSqlConnection instance, or None if not available.
Important
The manifest is cached after initial load for performance. If you need to reload the manifest, you must clear the cache manually.
See also
SAMSqlConnectionMANIFEST_KINDSAMConnectionCommonMetadataSAMSqlConnectionSpec
Example Usage:
manifest = broker.manifest if manifest: print(manifest.metadata.name)
- manifest_setter(value)
Set the manifest for the broker and override all AbstractBroker model properties based on the manifest data.
- Parameters:
value (Optional[Union[AbstractSAMBase, dict]]) – The manifest to set, either as a Pydantic model or a dictionary.
- manifest_to_django_orm()[source]
Transform the Smarter API user manifest into a Django ORM model dictionary.
This method converts the loaded and validated manifest (Pydantic model) into a dictionary suitable for creating or updating a SqlConnection Django ORM instance. It handles field name conversions, secret resolution, and metadata population.
- Return type:
- Returns:
A dictionary representing the ORM model fields and values.
- Raises:
SAMBrokerErrorNotReady – If the user profile or manifest/connection spec is not set.
SAMConnectionBrokerError – If the manifest data is invalid or cannot be converted.
Important
This method will resolve and attach password and proxy password secrets as model fields. Read-only fields (such as
id,created_at,updated_at) are not included in the result.See also
SqlConnectionSecret
Example Usage:
orm_dict = broker.manifest_to_django_orm() connection = SqlConnection(**orm_dict) connection.save()
- mask_string(string='', mask_char='*', mask_length=4, string_length=8)
Masks a string for secure logging.
This utility function masks all but the last unmasked_chars characters of the input string, replacing them with asterisks. It is useful for logging sensitive information like API keys or passwords.
- property name: str | None
Retrieve the unique name identifier for the ChatBot instance managed by this broker.
This property accesses the name used to distinguish the ChatBot within the database and across the Smarter platform. The name is first returned from an internal cache if available. If not cached, and if a manifest is present, the name is extracted from the manifest’s metadata and stored for subsequent access.
The name is essential for database queries, model lookups, and for associating related resources such as API keys, plugins, and functions with the correct ChatBot instance.
- Returns:
The name of the ChatBot as a string, or
Noneif the name is not set or cannot be determined.- Return type:
Optional[str]
Note
The name property is a critical identifier used throughout the broker to ensure correct mapping between manifest data and persistent application state.
- name_cached_property_setter(value)
A workaround to the limitation that you cannot use both @cached_property and a setter for the same attribute name (name). In Python, you cannot have a property (or cached_property) and a setter with the same name unless you use the @property decorator (not @cached_property).
We need the cached_property so that the lazy evaluation of the name only happens once, and subsequent accesses return the cached value for performance. However, we also need to be able to set the name explicitly in some cases,
- Parameters:
value (str) – The name to set for the manifest.
- property orm_instance: MetaDataWithOwnershipModel | None
Return the Django ORM model instance for the broker. There are multiple strategies to retrieve the ORM instance:
If the instance is already cached in self._orm_instance, return it.
If the broker is not ready or the name is not set, log a warning and return None.
Attempt to retrieve the ORM instance using the user_profile and name. If not found, attempt to retrieve using the admin user_profile for the account. If still not found, attempt to retrieve using the Smarter platform admin user_profile.
Cache the retrieved instance for future access.
- Returns:
The Django ORM model instance for the broker.
- Return type:
Optional[MetaDataWithOwnershipModel]
- property orm_meta_instance: MetaDataWithOwnershipModel | None
Return the Django ORM meta model instance for the broker. This is a cached property that retrieves the ORM meta instance based on the user_profile and kind. For simple relational models, the ORM meta class is the same as the ORM class, and the meta instance is the same as the ORM instance.
This property is used for resolving more complex ORM relationships where the name and user_profile fields are stored in a parent Django model.
- orm_meta_instance_setter()
Initialize the ORM metadata for the broker instance.
This method attempts to initialize the ORM metadata by querying the ORMMetaModelClass using the broker’s name and user_profile. If the ORM metadata is successfully retrieved, it is stored in the orm_meta_instance attribute. If the ORM metadata does not exist or an error occurs, the _orm_instance attribute is set to None.
- Return type:
- Returns:
None
- property params: QueryDict | None
Return the query parameters from the url of the request. there are two scenarios to consider: 1. the request is a Django HttpRequest object (the expected case) 2. the request is a Python PreparedRequest object (the edge case)
- Returns:
The query parameters from the url of the request.
- Return type:
Optional[QueryDict]
- property parsed_url: ParseResult | None
Expose the private ParseResult URL object as a public property.
- Returns:
The parsed URL as a ParseResult object.
Example:
request_mixin = SmarterRequestMixin(request) parsed = request_mixin.parsed_url print(parsed.netloc) # e.g., 'example.com'
- pascal_to_snake(name)
Converts a PascalCase string to pascal_case snake_case format.
- Parameters:
name (str) – The PascalCase string to convert.
- Returns:
The converted string in snake_case format.
- Return type:
Note
Spaces in the input string are replaced with underscores.
Multiple consecutive underscores are collapsed into a single underscore.
Example usage:
from smarter.common.utils import pascal_to_snake print(pascal_to_snake("UserProfile")) # Output: user_profile print(pascal_to_snake("FirstName LastName")) # Output: first_name_last_name
- property password_secret: Secret | None
Return the password secret for the SQL connection.
This property retrieves the Secret object associated with the password for the current SQL connection, either from the manifest or the ORM model. If the secret does not exist, a warning is logged and None is returned.
- Returns:
The password Secret instance, or None if not found.
- Raises:
Secret.DoesNotExist – If the password secret cannot be found in the database.
Important
The password secret is cached after the first lookup for efficiency. If the underlying secret changes, you must clear the cache to force a reload.
See also
Example Usage:
secret = broker.password_secret if secret: print(secret.value) else: print("Password secret not found.")
- property path: str | None
Extracts the path from the URL.
- Returns:
Optional[str]: The path as a string, or None if not found.
Examples
https://hr.3141-5926-5359.alpha.api.example.com/chatbot/ returns ‘/chatbot/’
- property proxy_password_secret: Secret | None
Return the proxy password secret for the SQL connection.
This property retrieves the Secret object associated with the proxy password for the current SQL connection, either from the manifest or the ORM model. If the secret does not exist, a warning is logged and None is returned.
- Returns:
The proxy password Secret instance, or None if not found.
- Raises:
Secret.DoesNotExist – If the proxy password secret cannot be found in the database.
Important
The proxy password secret is cached after the first lookup for efficiency. If the underlying secret changes, you must clear the cache to force a reload.
If the proxy password secret is missing, proxy authentication may fail. Always check for None before use.
See also
Example Usage:
proxy_secret = broker.proxy_password_secret if proxy_secret: print(proxy_secret.value) else: print("Proxy password secret not found.")
- property qualified_request: bool
A cursory screening of the WSGI request object to look for any disqualifying conditions that confirm this is not a request that we are interested in.
The request is considered “qualified” if all of the following are true:
The request object (self._smarter_request) is present.
The URL path is present and non-empty.
The request does not originate from an internal AWS Kubernetes subnet (netloc starts with 192.168).
The path is not in the list of amnesty_urls.
The path does not start with /admin/.
The path does not start with /docs/.
The path does not end with a static file extension (e.g., .css, .js, .png, .jpg, .jpeg, .gif, .svg, .woff, .woff2, .ttf, .eot, .ico).
- Returns:
True if the request passes all checks and is of interest, otherwise False.
Example:
# True case: a valid chatbot request request_mixin = SmarterRequestMixin(request) if request_mixin.qualified_request: print("This is a qualified chatbot request.") # False case: a static asset or admin/docs request static_request = SmarterRequestMixin(static_asset_request) if not static_request.qualified_request: print("This request is not of interest.")
- property ready: bool
Check if the broker is ready for operations.
This property determines whether the broker has been properly initialized and is ready to perform its functions. A broker is considered ready if it has a valid manifest loaded, either from raw data, a loader, or existing Django ORM models.
- Returns:
Trueif the broker is ready,Falseotherwise.- Return type:
- property ready_state: str
Return a string representation of the broker’s ready state.
- Returns:
“READY” if the broker is ready, otherwise “NOT_READY”.
- Return type:
- property request: HttpRequest | None
Return the request object.
- Returns:
The request object.
- Return type:
Optional[HttpRequest]
- property request_mixin_ready_state: str
Returns a string representation of the request mixin’s ready state.
- Returns:
A string indicating whether the request mixin is ready or not.
- rfc1034_compliant_str(val)
Generates a RFC 1034-compliant name string suitable for use as a DNS label or resource identifier.
- Parameters:
val (str) – The input string to convert to RFC 1034-compliant format.
- Returns:
A string that is: - lower case - contains only alphanumeric characters and hyphens - starts and ends with an alphanumeric character - has a maximum length of 63 characters
- Return type:
- Raises:
SmarterValueError – If the input is not a string or is empty after conversion.
Note
Underscores in the input are replaced with hyphens.
Invalid characters (anything other than a-z, 0-9, or ‘-’) are removed.
Leading and trailing hyphens are stripped.
The result is truncated to 63 characters if necessary.
Warning
This function is intended for generating DNS-safe names. It does not guarantee uniqueness or suitability for all RFC 1034 use cases.
Example usage:
from smarter.common.utils import rfc1034_compliant_str # Basic usage print(rfc1034_compliant_str("My_ChatBot_2025")) # Output: my-chatbot-2025 # With special characters print(rfc1034_compliant_str("My@Bot!_Name")) # Output: my-bot-name # With long input long_name = "ThisIsAReallyLongChatBotNameThatShouldBeTruncatedToSixtyThreeCharacters_Extra" print(rfc1034_compliant_str(long_name)) # Output: thisisareallylongchatbotnamethatshouldbetruncatedtosixtythreecharacters
- rfc1034_compliant_to_snake(val)
Converts a RFC 1034-compliant name (typically used for DNS labels or resource identifiers) to a more human-readable
snake_casename.This function is useful for translating machine-friendly names (which use hyphens as word separators) into Pythonic identifiers (which use underscores).
- Parameters:
val (str) – The RFC 1034-compliant name to convert. This should be a string containing only lowercase letters, numbers, and hyphens.
- Returns:
The converted name in
snake_caseformat, with hyphens replaced by underscores.- Return type:
- Raises:
SmarterValueError – If the input is not a string.
Note
Only hyphens are replaced; other characters are preserved.
The function does not validate that the input is strictly RFC 1034-compliant. It assumes the input is already sanitized.
Warning
This function does not handle conversion of other non-alphanumeric characters. If the input contains characters other than hyphens, underscores, letters, or numbers, they will remain unchanged.
Example usage:
from smarter.common.utils import rfc1034_compliant_to_snake # Basic conversion print(rfc1034_compliant_to_snake("my-chatbot-2025")) # Output: my_chatbot_2025 # Input with no hyphens print(rfc1034_compliant_to_snake("simplelabel")) # Output: simplelabel # Input with multiple hyphens print(rfc1034_compliant_to_snake("this-is-a-test-label")) # Output: this_is_a_test_label # Input with invalid type try: rfc1034_compliant_to_snake(12345) except SmarterValueError as e: print(e) # Output: Could not convert RFC 1034 compliant name from <class 'int'>
- property root_domain: str | None
Extracts the root domain from the URL.
- Returns:
The root domain or None if not found.
Example:
request_mixin = SmarterRequestMixin(request) print(request_mixin.root_domain) # For 'https://hr.3141-5926-5359.alpha.api.example.com/chatbot/' → 'smarter.sh' # For 'http://localhost:9357/' → 'localhost'
- sam_connection_metadata()
Return the common connection metadata from the manifest.
- Returns:
The connection metadata.
- Return type:
- Raises:
NotImplementedError – If the manifest does not have connection metadata.
See also
SAMConnectionCommonMetadataExample usage:
metadata = broker.sam_connection_metadata()
- sam_connection_status()
Return the common connection status from the manifest.
- Return type:
- schema(request, *args, **kwargs)
Return the published JSON schema for the Pydantic model.
- Parameters:
request (HttpRequest) – The HTTP request object.
args – Additional positional arguments.
kwargs – Additional keyword arguments.
- Returns:
A SmarterJournaledJsonResponse containing the JSON schema.
- Return type:
- property session_key: str
Getter for the session_key property.
The session_key is a unique identifier for a chat session. It is used to identify the chat session across multiple requests. If the session_key is not already set, it attempts to find it in the URL parameters. Barring that, it generates a new one.
- Returns:
The session key as a string.
Example:
request_mixin = SmarterRequestMixin(request) session_key = request_mixin.session_key print(session_key) # e.g., '38486326c21ef4bcb7e7bc305bdb062f16ee97ed8d2462dedb4565c860cd8ecc'
- set_and_verify_name_param(*args, command=None, **kwargs)
Set self.name from the ‘name’ query string param and then verify that it was actually passed.
- Parameters:
command (Optional[SmarterJournalCliCommands]) – The command being executed, for error reporting purposes.
- Raises:
SAMBrokerErrorNotReady – If neither a manifest nor a name param is provided.
- Returns:
None
- set_is_internal_api_request(request, value=True)
Set the internal API request attribute on the request object.
This method allows you to mark a request as an internal API request by setting a custom attribute on the request object. This can be used in middleware or views to indicate that the request should be treated as internal.
- Parameters:
request (HttpRequest) – The Django request object.
value (bool) – The value to set for the internal API request attribute (default is True).
- Returns:
The modified Django request object.
- Return type:
HttpRequest
- smarter_build_absolute_uri(request)
Attempts to get the absolute URI from a request object.
This utility function tries to retrieve the request URL from any valid child class of
django.http.HttpRequest. It is especially useful in unit tests or scenarios where the request object may not implementbuild_absolute_uri().- Parameters:
request (Optional[HttpRequest]) – The request object.
- Returns:
The absolute request URL.
- Return type:
Optional[str]
- Raises:
SmarterValueError – If the URI cannot be built from the request.
- property smarter_request: Request | HttpRequest | WSGIRequest | MagicMock | None
Returns the current request object.
This property is named to avoid potential name collisions in child classes. This property is preferred over standard Django request types in that it more elegantly resolves idiosyncratic usage like Unit tests, Sphinx docs, and other non-standard request objects.
Example:
request_mixin = SmarterRequestMixin(request) req = request_mixin.smarter_request
- Returns:
The current request object.
- property smarter_request_chatbot_id: int | None
Extract the chatbot id from the URL.
Example
http://localhost:9357/workbench/chatbots/rMTAwMDAyNwx/chat/
returns the pk id that when decoded from the hashed ID format corresponds to the chatbot id.
- Returns:
The chatbot id as an integer, or None if not found.
- property smarter_request_chatbot_name: str | None
Extract the chatbot name from the URL.
Example
http://example.3141-5926-5359.api.localhost:9357/config
returns “example”
- Returns:
The chatbot name as a string, or None if not found.
- property smarter_request_user: AnonymousUser | User | None
Returns the user associated with the request
This property is named to avoid potential name collisions in child classes. It retrieves the user from the request object if available.
Example:
request_mixin = SmarterRequestMixin(request) user = request_mixin.smarter_request_user
- Returns:
The user associated with the request, or None if not available.
- snake_to_camel(data, convert_values=False)
Converts snake_case strings, dictionary keys, or lists of such, to camelCase format.
- Parameters:
- Returns:
The converted data in camelCase format. Returns a string, dictionary, or list, matching the input type.
- Return type:
Note
For dictionaries, only keys are converted by default. If
convert_valuesis set, string values are also converted.Nested dictionaries and lists are processed recursively.
Warning
If the input is not a string, dictionary, or list, a
SmarterValueErroris raised.Example usage:
from smarter.common.utils import snake_to_camel # Convert a string print(snake_to_camel("user_name")) # Output: userName # Convert a dictionary data = { "user_name": "alice", "user_profile": { "first_name": "Alice", "last_name": "Smith" } } print(snake_to_camel(data)) # Output: {'userName': 'alice', 'userProfile': {'firstName': 'Alice', 'lastName': 'Smith'}} # Convert a list of strings print(snake_to_camel(["first_name", "last_name"])) # Output: ['firstName', 'lastName'] # Convert values as well data = {"user_name": "first_name"} print(snake_to_camel(data, convert_values=True)) # Output: {'userName': 'firstName'}
- sorted_dict(data)
Returns a new dictionary with keys sorted.
- property subdomain: str | None
Extracts the subdomain from the URL.
- Returns:
The subdomain or None if not found.
Example:
request_mixin = SmarterRequestMixin(request) sub = request_mixin.subdomain print(sub) # e.g., 'hr.3141-5926-5359.alpha' for # 'https://hr.3141-5926-5359.alpha.api.example.com/chatbot/'
- property thing: SmarterJournalThings
The Smarter Journal Thing for this broker.
- Returns:
The Smarter Journal Thing for this broker.
- Return type:
SmarterJournalThings, an enumeration of all Smarter AI resource types.
- property timestamp
Create a consistent timestamp based on the time that this object was instantiated.
- Returns:
The timestamp as a datetime object.
Example:
request_mixin = SmarterRequestMixin(request) ts = request_mixin.timestamp print(ts) # e.g., 2025-12-01 12:34:56.789012
- to_json()
Serialize the broker instance to a JSON string.
- Returns:
A JSON string representation of the broker instance.
- Return type:
- property uid: str | None
Unique identifier for the client.
This is assumed to be a combination of the machine MAC address and the hostname.
- Returns:
The client UID as a string, or None if not available.
Example:
request_mixin = SmarterRequestMixin(request) uid = request_mixin.uid print(uid) # e.g., '00:1A:2B:3C:4D:5E-myhost'
- undeploy(request, *args, **kwargs)[source]
Undeploy the SQL connection. This is not implemented for SQL connections.
- Raises:
SAMBrokerErrorNotImplemented – Always, as undeploy functionality is not supported for SQL connections.
- Parameters:
request ("HttpRequest") – The Django HTTP request object.
args – Additional positional arguments (unused).
kwargs – Additional keyword arguments (unused).
- Returns:
Never returns; always raises an error.
- Return type:
- property unformatted_class_name: str
Returns the raw class name without formatting.
- Returns:
The unformatted class name as a string.
- Return type:
This is useful for logging or serialization where the plain class name is needed.
- property unique_client_string: str
Generate a unique string based on several request attributes.
This string is used for generating session_key and client_key.
- The unique string is composed of:
Account number
URL
User agent
IP address
Timestamp
- Returns:
A unique string representing the client and request context.
- Return type:
Example:
request_mixin = SmarterRequestMixin(request) unique_str = request_mixin.unique_client_string print(unique_str)
- property uri: str | None
Return the full uri of the request.
- Returns:
The full uri of the request.
- Return type:
Optional[str]
- property url: str | None
The string representation of the ParseResult object stored in _parsed_url.
- Returns:
The URL as a string.
Example:
request_mixin = SmarterRequestMixin(request) url_str = request_mixin.url print(url_str) # e.g., 'https://example.com/path/'
- property url_account_number: str | None
Extract the account number from the URL using the pattern defined in SmarterValidator.VALID_ACCOUNT_NUMBER_PATTERN.
Example
http://example.3141-5926-5359.api.localhost:9357/config
returns “3141-5926-5359”
- Returns:
The account number as a string, or None if not found.
- property url_path_parts: list[str]
Extract the path parts from the URL.
- Returns:
A list of strings representing each part of the URL path.
Example:
request_mixin = SmarterRequestMixin(request) parts = request_mixin.url_path_parts print(parts) # e.g., ['api', 'v1', 'workbench', '1', 'chat']
- property user: AnonymousUser | User | None
Returns the user for the current user. Handle lazy instantiation from user_profile or account.
- Returns:
The user for the current user.
- Return type:
User or None
- property user_agent: str | None
Get the client’s user agent string from the request object.
This property attempts to extract the user agent from the request’s META dictionary, using the “HTTP_USER_AGENT” key. If the user agent is not available, it returns a default value.
- Returns:
The client’s user agent string, or None if not found.
- Return type:
Optional[str]
Example:
request_mixin = SmarterRequestMixin(request) ua = request_mixin.user_agent print(ua) # e.g., 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)...'
- property user_profile: UserProfile | None
Returns the user_profile for the current user. Handle lazy instantiation from user or account.
- Returns:
The user_profile for the current user.
- Return type:
UserProfile or None