Static Plugin Broker

class smarter.apps.plugin.manifest.brokers.static_plugin.SAMStaticPluginBroker(*args, **kwargs)[source]

Broker for Smarter API StaticPlugin manifests.

This class is responsible for loading, validating, and parsing Smarter API YAML StaticPlugin manifests, and initializing the corresponding Pydantic model. It provides generic services for StaticPlugins, such as instantiation, creation, update, and deletion.

Responsibilities:

  • Load and validate StaticPlugin manifests.

  • Parse manifest data and initialize the SAMStaticPlugin Pydantic model.

  • Manage plugin lifecycle: create, update, delete, and describe.

  • Interface with Django ORM models for plugin metadata, prompt, selector, and static data.

Parameters:

  • loader: Manifest loader instance (must match expected manifest kind).

  • plugin_meta: Django ORM model for plugin metadata.

  • plugin_data: Django ORM model for static plugin data.

  • user_profile: User profile associated with the plugin.

  • name: Plugin name.

Example Manifest Response:

{
    "apiVersion": "smarter.sh/v1",
    "kind": "Plugin",
    "metadata": {
        "name": "cli_test_plugin",
        "description": "...",
        "version": "0.2.0",
        "tags": [],
        "annotations": null,
        "pluginClass": "static"
    },
    "spec": {
        "prompt": { },
        "selector": { },
        "data": { }
    },
    "status": {
        "created": "2025-06-24T21:38:36.368058+00:00",
        "modified": "2025-06-24T21:38:36.434526+00:00"
    }
}

See also

  • SAMPluginBaseBroker for base broker functionality.

  • SAMStaticPlugin for the manifest model.

  • Django ORM models: PluginMeta, PluginDataStatic, PluginPrompt, PluginSelector.

property ORMMetaModelClass: Type[PluginMeta]

Return the Django ORM meta model class for the broker.

Returns:

The Django ORM meta model class definition for the broker.

Return type:

Type[PluginMeta]

property ORMModelClass: Type[PluginDataStatic]

Returns the Django ORM model class for static plugin data.

This property provides the Django ORM model class that represents the static plugin data associated with this broker. It is used for database operations related to static plugin data.

Returns:

Django ORM model class for static plugin data.

Return type:

Type[PluginDataStatic]

Example:

broker = SAMStaticPluginBroker()
ORMModelClass = broker.ORMModelClass
print(ORMModelClass.__name__)
# Output: "PluginDataStatic"

See also

  • PluginDataStatic Django ORM model.

  • SAMStaticPluginBroker.plugin_data

property SAMModelClass: Type[SAMStaticPlugin]

Return the Pydantic model class for the broker.

Returns:

The Pydantic model class definition for the broker.

Return type:

Type[SAMStaticPlugin]

property SerializerClass: Type[PluginSerializer]

Returns the serializer class for the broker.

This property provides the serializer class definition used by the broker for serializing and deserializing plugin data. It returns the PluginSerializer class, which is specifically designed to handle static plugin data serialization.

Returns:

The serializer class definition for the broker.

Return type:

Type[PluginSerializer]

Example:

broker = SAMStaticPluginBroker()
serializer_class = broker.SerializerClass
print(serializer_class.__name__)
# Output: "PluginSerializer"

See also

  • PluginSerializer for static plugin data serialization.

__init__(*args, **kwargs)[source]

Initialize the SAMStaticPluginBroker instance.

This constructor initializes the broker by calling the parent class’s constructor, which will attempt to bootstrap the class instance with any combination of raw manifest data (in JSON or YAML format), a manifest loader, or existing Django ORM models. If a manifest loader is provided and its kind matches the expected kind for this broker, the manifest is initialized using the loader’s data.

This class can bootstrap itself in any of the following ways:

  • request.body (yaml or json string)

  • name + account (determined via authentication of the request object)

  • SAMLoader instance

  • manifest instance

  • filepath to a manifest file

If raw manifest data is provided, whether as a string or a dictionary, or a SAMLoader instance, the base class constructor will only goes as far as initializing the loader. The actual manifest model initialization is deferred to this constructor, which checks the loader’s kind.

Parameters:
  • args – Positional arguments passed to the parent constructor.

  • kwargs – Keyword arguments passed to the parent constructor.

Example:

broker = SAMStaticPluginBroker(loader=loader, plugin_meta=plugin_meta)

See also

  • SAMPluginBaseBroker.__init__

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:

str

property abstract_broker_logger_prefix: str

Return the logger prefix for the AbstractBroker.

Returns:

The logger prefix for the AbstractBroker.

Return type:

str

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:

str

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_mixin_logger_prefix: str

Returns the logger prefix for the class.

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:

str

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.

Returns:

List of URL path strings that are exempt.

Return type:

list[str]

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 to the database.

This method copies the manifest data to the Django ORM model and saves it to the database. It first ensures the manifest is loaded and validated by calling the base class’s apply method. If the plugin or its metadata is not properly initialized, an error is raised.

Parameters:
  • request (HttpRequest) – Django HTTP request object.

  • args – Additional positional arguments.

  • kwargs – Additional keyword arguments for manifest application.

Returns:

JSON response indicating success or error details.

Return type:

SmarterJournaledJsonResponse

Example:

response = broker.apply(request, name="cli_test_plugin")
print(response.data)
Raises:
  • SAMPluginBrokerError – If the plugin or plugin metadata is not initialized

  • SAMBrokerErrorNotReady – If the plugin is not ready after creation

See also

  • SAMPluginBaseBroker.apply

  • StaticPlugin.create

  • StaticPlugin.save

  • SmarterJournaledJsonResponse

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.

authenticate()

Authenticates the request using the provided API token.

Return type:

bool

cache_invalidations()[source]

Invalidate any relevant caches when the manifest or plugin data changes.

Return type:

None

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:

Optional[Union[str, dict, list]]

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 SmarterValueError is 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]

Chat with the static plugin (not implemented).

Raises:

SAMBrokerErrorNotImplemented – Always raised to indicate that this method is not implemented.

Parameters:
  • request (HttpRequest) – The HTTP request object.

  • args – Additional positional arguments.

  • kwargs – Additional keyword arguments.

Returns:

JSON response indicating error.

Return type:

SmarterJournaledJsonResponse

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.

Parameters:
  • param (Any) – The param to clean.

  • param_name (str) – The name of the param, for logging purposes.

  • url (Optional[str]) – The url from which the param was extracted, for logging purposes.

Returns:

The cleaned param.

Return type:

Optional[str]

clear_cached_properties()

Clears all cached properties in this mixin.

property created: bool

Return True if the broker was created successfully.

Returns:

True if the broker was created successfully.

Return type:

bool

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.

Parameters:

data (dict or str) – The data to convert, either a dict or a JSON/YAML string.

Returns:

The data as a dictionary.

Return type:

dict

Raises:

SmarterValueError – If the data cannot be converted to a dictionary.

delete(request, *args, **kwargs)[source]

Delete the static plugin.

Parameters:
  • request (HttpRequest) – The HTTP request object.

  • args – Additional positional arguments.

  • kwargs – Additional keyword arguments.

Returns:

JSON response indicating success or error.

Return type:

SmarterJournaledJsonResponse

Raises:
  • SAMPluginBrokerError – If the plugin or plugin metadata is not initialized.

  • SAMBrokerErrorNotReady – If the plugin is not ready to be deleted.

See also

  • StaticPlugin.delete

  • SmarterJournaledJsonResponse

  • SAMPluginBaseBroker.set_and_verify_name_param()

deploy(request, *args, **kwargs)[source]

Deploy the static plugin (not implemented).

Raises:

SAMBrokerErrorNotImplemented – Always raised to indicate that this method is not implemented.

Parameters:
  • request (HttpRequest) – The HTTP request object.

  • args – Additional positional arguments.

  • kwargs – Additional keyword arguments.

Returns:

JSON response indicating error.

Return type:

SmarterJournaledJsonResponse

describe(request, *args, **kwargs)[source]

Serialize and return the manifest for a static plugin as a JSON response.

This method collects and validates all required components of a static plugin manifest, including metadata, prompt configuration, selector criteria, and static data. It ensures that all plugin objects are present and ready, and provides informative error responses if any required component is missing or invalid.

The returned manifest contains the following top-level fields:

  • apiVersion: Manifest API version string.

  • kind: Manifest kind (usually “Plugin”).

  • metadata: Plugin metadata (name, description, version, tags, annotations, plugin class).

  • spec: Specification details (prompt configuration, selector criteria, static plugin data).

  • status: Creation and last modification timestamps.

Example response:

{
    "apiVersion": "smarter.sh/v1",
    "kind": "Plugin",
    "metadata": {
        "name": "cli_test_plugin",
        "description": "...",
        "version": "0.2.0",
        "tags": [],
        "annotations": null,
        "pluginClass": "static"
    },
    "spec": {
        "prompt": {  },
        "selector": {  },
        "data": {  }
    },
    "status": {
        "created": "2025-06-24T21:38:36.368058+00:00",
        "modified": "2025-06-24T21:38:36.434526+00:00"
    }
}
Error handling:
  • If manifest is not set, a SAMPluginBrokerError is raised.

Returns:

JSON response containing the plugin manifest or error details.

Return type:

SmarterJournaledJsonResponse

Return type:

SmarterJournaledJsonResponse

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 a static plugin.

This method generates and returns a sample manifest structure for a static plugin, using StaticPlugin.example_manifest. The response is wrapped in a SmarterJournaledJsonResponse for consistent API output.

Parameters:
  • request (HttpRequest) – Django HTTP request object.

  • args – Additional positional arguments.

  • kwargs – Additional keyword arguments passed to the manifest generator.

Returns:

JSON response containing the example manifest.

Return type:

SmarterJournaledJsonResponse

Example:

response = broker.example_manifest(request, foo="bar")
print(response.data)

See also

  • StaticPlugin.example_manifest

  • SmarterJournaledJsonResponse

  • SmarterJournalCliCommands

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:

Return type:

Optional[str]

Returns:

The session key as a string, or None if not found.

property formatted_class_name: str

Returns a formatted class name for logging.

This property provides a human-readable class name string, combining the parent class name (from super().formatted_class_name) with the current class name. This is useful for log messages, debugging, and tracing execution in complex broker hierarchies.

Returns:

Formatted class name string, e.g. BaseBroker.SAMStaticPluginBroker()

Return type:

str

Example:

broker = SAMStaticPluginBroker()
print(broker.formatted_class_name)
# Output: BaseBroker.SAMStaticPluginBroker()

See also

  • SAMPluginBaseBroker.formatted_class_name

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:

str

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:

str

property formatted_state_ready: str

Returns the readiness state formatted for logging.

Returns:

The formatted readiness state as a string.

Return type:

str

generate_session_key()

Generate a session_key based on a unique string and the current datetime.

Return type:

str

Returns:

A unique session key string.

get(request, *args, **kwargs)

Return a JSON response with a list of SQL plugins for this account.

This method queries the database for all SQL plugins associated with the current account, optionally filtered by name, and returns a structured JSON response containing their serialized representations. Each plugin is validated by round-tripping through the Pydantic model.

Parameters:
  • request ("HttpRequest") – The HTTP request object.

  • args – Additional positional arguments (unused).

  • kwargs – Additional keyword arguments, such as filter criteria (e.g., name).

Returns:

A SmarterJournaledJsonResponse containing a list of SQL plugin manifests and metadata.

Return type:

SmarterJournaledJsonResponse

Example:

response = broker.get(request, name="my_plugin")
print(response.data)
Raises:

SAMPluginBrokerError – If a plugin cannot be serialized or validated during the retrieval process.

See also

PluginMeta PluginSerializer SAMSqlPlugin SmarterJournaledJsonResponse SmarterJournalCliCommands SAMKeys SAMMetadataKeys SCLIResponseGet SCLIResponseGetData

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.

Parameters:

serializer (ModelSerializer) – The Django model serializer instance.

Returns:

A list of field names and types.

Return type:

Optional[list[dict[str, str]]]

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:

bool

property is_authenticated: bool

Returns True if the request is authenticated, False otherwise.

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

Returns:

True if the URL is a chatbot endpoint, otherwise False.

Return type:

bool

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:

bool

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:

bool

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:

bool

property is_chatbot_smarter_api_url: bool
Returns True if the URL is of the form:
Returns:

True if the URL matches a smarter API chatbot endpoint, otherwise False.

Return type:

bool

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:

bool

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:

bool

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:

bool

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:

bool

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:

bool

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

Returns:

True if the URL matches the smarter API pattern, otherwise False.

Return type:

bool

Type:

Returns True if the URL is of the form http

Type:

//localhost

property is_valid: bool
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:

bool

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:
Returns:

A SmarterJournaledJsonResponse containing the error response.

Return type:

SmarterJournaledJsonResponse

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:

SmarterJournaledJsonResponse

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:

SmarterJournaledJsonResponse

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:

SmarterJournaledJsonResponse

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:

SmarterJournaledJsonResponse

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:

SmarterJournaledJsonResponse

property kind: str

Returns the manifest kind for this broker.

This property provides the manifest kind string, which is used to identify the type of plugin manifest handled by this broker. For static plugins, this is typically set to MANIFEST_KIND.

Returns:

Manifest kind string (e.g. "Plugin")

Return type:

str

Example:

broker = SAMStaticPluginBroker()
print(broker.kind)
# Output: "Plugin"

See also

  • MANIFEST_KIND constant in smarter.apps.plugin.manifest.models.static_plugin.const

  • SAMStaticPluginBroker.manifest

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 static plugin (not implemented).

Raises:

SAMBrokerErrorNotImplemented – Always raised to indicate that this method is not implemented.

Parameters:
  • request (HttpRequest) – The HTTP request object.

  • args – Additional positional arguments.

  • kwargs – Additional keyword arguments.

Returns:

JSON response indicating error.

Return type:

SmarterJournaledJsonResponse

property manifest: SAMStaticPlugin | None

Returns the manifest for the static plugin as a Pydantic model instance. This can be initialized any of three ways: 1. If already from the constructor, return the cached manifest. 2. If the plugin metadata exists, build the manifest from the Django ORM models. 3. If a manifest loader is provided, build the manifest from the loader data.

This property initializes and returns a SAMStaticPlugin object, representing the full manifest for a static plugin. The manifest is built using data from the manifest loader, including API version, kind, metadata, and specification. Child models (such as metadata and spec) are automatically initialized by Pydantic using the provided data.

Returns:

The initialized static plugin manifest as a Pydantic model, or None if not available.

Return type:

Optional[SAMStaticPlugin]

Example:

broker = SAMStaticPluginBroker()
manifest = broker.manifest
if manifest:
    print(manifest.model_dump_json())

See also

  • SAMStaticPlugin

  • SAMPluginCommonMetadata

  • SAMPluginStaticSpec

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()

Convert the Smarter API manifest metadata into a dictionary suitable for creating or updating a Django ORM ChatBot model.

This method extracts all relevant metadata from the loaded manifest and transforms it into a dictionary format compatible with Django ORM operations. The manifest’s configuration is first dumped and converted from camelCase to snake_case to match Django’s field naming conventions.

The resulting dictionary includes the account, name, description, and version fields from the manifest metadata. This dictionary is intended to be used to supplement the model spec when instantiating or updating a ChatBot ORM model instance in the database.

If the manifest is not loaded or is invalid, an exception is raised to indicate that the broker is not ready to perform the transformation.

Returns:

A dictionary containing all metadata fields required to create or update a Django ORM ChatBot model.

Return type:

dict

Raises:
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.

Parameters:
  • string (str) – The string to be masked.

  • mask_char (str) – The character used for masking.

  • mask_length (int) – The number of characters to mask.

  • string_length (int) – The length of the string to consider for masking.

Returns:

The masked string.

Return type:

str

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 None if 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: PluginDataBase | None

Return the Django ORM model instance for the broker.

Returns:

The Django ORM model instance for the broker.

Return type:

Optional[TimestampedModel]

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:

None

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:

str

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 path: str | None

Extracts the path from the URL.

Returns:

Optional[str]: The path as a string, or None if not found.

Examples

property plugin: StaticPlugin | None

Returns the StaticPlugin instance managed by this broker.

This property lazily initializes and returns a StaticPlugin object, using the current plugin metadata, user profile, manifest, and name. If the plugin has already been initialized, the cached instance is returned.

Returns:

The managed StaticPlugin instance, or None if initialization fails.

Return type:

Optional[StaticPlugin]

Example:

broker = SAMStaticPluginBroker()
plugin = broker.plugin
if plugin:
    print(plugin.name)

See also

  • StaticPlugin

  • SAMStaticPluginBroker.manifest

  • SAMStaticPluginBroker.plugin_meta

property plugin_data: PluginDataStatic | None

Returns the PluginDataStatic object for this broker.

This property retrieves the static plugin data from the database, using the associated plugin_meta. If the data has already been loaded, the cached instance is returned. If plugin_meta is not set, this property returns None.

Returns:

The PluginDataStatic instance for this plugin, or None if not available.

Return type:

Optional[PluginDataStatic]

Example:

broker = SAMStaticPluginBroker()
data = broker.plugin_data
if data:
    print(data.some_field)
Raises:

SAMPluginBrokerError – If there is an error retrieving the plugin data from the database.

See also

  • PluginDataStatic

  • SAMStaticPluginBroker.plugin_meta

plugin_data_orm2pydantic()

Convert plugin data from the Django ORM model format to the Pydantic manifest format.

This method transforms plugin data, typically retrieved as a dictionary from the Django ORM (plugin_data), into a format suitable for Pydantic manifest models. It handles conversion of nested structures, such as parameters, and ensures all fields are properly camel-cased and validated.

Returns:

The plugin data as a dictionary formatted for Pydantic manifest models.

Return type:

dict[str, Any]

Raises:

SAMPluginBrokerError – If the plugin or plugin data is not found, or if conversion fails.

Note

  • This method automatically converts parameter definitions from a dict-of-dicts to a list of dicts, merging required flags for each property.

  • The conversion process expects the plugin data to follow the expected ORM structure. Unexpected formats may result in errors.

Error

Any error during conversion, such as missing plugin data or invalid format, is wrapped and raised as SAMPluginBrokerError.

See also

PluginDataBase SAMPluginBaseBroker.plugin_data() SAMPluginBaseBroker.plugin() SAMPluginSpecCommonData SmarterJournalCliCommands

Example usage:

data = broker.plugin_data_orm2pydantic()
print(data["parameters"])
plugin_init()[source]

Initialize the SAMStaticPluginBroker instance.

This method initializes the broker by calling the parent class’s init method. It sets up any necessary state or configurations required for handling StaticPlugin manifests.

Returns:

None

Example:

broker = SAMStaticPluginBroker()
broker.init()

See also

  • SAMPluginBaseBroker.init

property plugin_meta: PluginMeta | None

Retrieve the PluginMeta ORM instance associated with this broker.

This property returns the plugin metadata object for the current plugin, resolving it by name and account if not already cached. If the metadata cannot be found, None is returned.

Returns:

The PluginMeta instance for this broker, or None if unavailable.

Return type:

Optional[PluginMeta]

Note

The metadata is cached after the first successful lookup for efficient repeated access.

Warning

If the plugin metadata does not exist in the database, no exception is raised; None is returned.

See also

PluginMeta SAMPluginBaseBroker.plugin() SAMPluginBaseBroker.plugin_data()

Example usage:

meta = broker.plugin_meta
if meta:
    print(meta.name, meta.account)
else:
    print("No plugin metadata found.")
plugin_metadata_orm2pydantic()

Convert plugin metadata from the Django ORM model format to the Pydantic manifest format.

This method transforms the plugin metadata, typically retrieved as a dictionary from the Django ORM (PluginMeta), into a Pydantic model (SAMPluginCommonMetadata). It ensures the metadata is properly camel-cased and validated for use in manifest serialization and API responses.

Returns:

The plugin metadata as a Pydantic model.

Return type:

SAMPluginCommonMetadata

Raises:

SAMPluginBrokerError – If the plugin metadata or plugin instance is not found, or if conversion fails.

Error

Any error during conversion, such as missing metadata or invalid format, is wrapped and raised as SAMPluginBrokerError.

See also

PluginMeta SAMPluginCommonMetadata SAMPluginBaseBroker.plugin_meta() SAMPluginBaseBroker.plugin()

Example usage:

metadata = broker.plugin_metadata_orm2pydantic()
print(metadata.name, metadata.description)
property plugin_prompt_orm: PluginPrompt | None

Retrieve the PluginPrompt ORM instance associated with this broker.

This property returns the plugin prompt object for the current plugin metadata. If the prompt cannot be found, None is returned.

Returns:

The PluginPrompt instance for this broker, or None if unavailable.

Return type:

Optional[PluginPrompt]

Note

The prompt is retrieved based on the associated PluginMeta.

plugin_prompt_orm2pydantic()

Convert plugin prompt data from the Django ORM model format to the Pydantic manifest format. This method transforms the plugin prompt data, typically retrieved as a dictionary from the Django ORM (PluginPrompt), into a Pydantic model (SAMPluginCommonSpecPrompt). It ensures the prompt data is properly camel-cased and validated for use in manifest serialization and API responses.

Returns:

The plugin prompt data as a Pydantic model.

Return type:

SAMPluginCommonSpecPrompt

Raises:

SAMPluginBrokerError – If the plugin prompt or plugin instance is not found, or if conversion fails.

Error

Any error during conversion, such as missing prompt data or invalid format, is wrapped and raised as SAMPluginBrokerError.

See also

PluginPrompt SAMPluginCommonSpecPrompt SAMPluginBaseBroker.plugin_prompt() SAMPluginBaseBroker.plugin()

Example usage:

prompt = broker.plugin_prompt_orm2pydantic()
print(prompt.template, prompt.variables)
plugin_selector_orm2pydantic()

Convert plugin selector data from the Django ORM model format to the Pydantic manifest format.

This method transforms the plugin selector data, typically retrieved as a dictionary from the Django ORM (PluginSelector), into a Pydantic model (SAMPluginCommonSpecSelector). It ensures the selector data is properly camel-cased and validated for use in manifest serialization and API responses.

Returns:

The plugin selector data as a Pydantic model.

Return type:

SAMPluginCommonSpecSelector

Raises:

SAMPluginBrokerError – If the plugin selector, plugin metadata, or plugin instance is not found, or if conversion fails.

Error

Any error during conversion, such as missing selector data or invalid format, is wrapped and raised as SAMPluginBrokerError.

See also

PluginSelector SAMPluginCommonSpecSelector SAMPluginBaseBroker.plugin() SAMPluginBaseBroker.plugin_meta()

Example usage:

selector = broker.plugin_selector_orm2pydantic()
print(selector.type, selector.options)
plugin_static_spec_data_orm2pydantic()[source]

Convert plugin static data from the Django ORM model format to the Pydantic manifest format.

This method retrieves the static plugin data associated with the current plugin_meta and converts it into a SAMPluginStaticSpecData Pydantic model. If no data is found, an empty SAMPluginStaticSpecData model is returned.

Returns:

The static plugin data as a Pydantic model.

Return type:

SAMPluginStaticSpecData

Example:

broker = SAMStaticPluginBroker()
static_data = broker.plugin_static_spec_data_orm2pydantic()
print(static_data.model_dump_json())
Raises:

SAMPluginBrokerError – If there is an error retrieving or converting the plugin data.

See also

  • PluginDataStatic

  • SAMPluginStaticSpecData

plugin_static_spec_orm2pydantic()[source]

Convert the static plugin specification from the Django ORM model format to the Pydantic manifest format.

This method constructs a SAMPluginStaticSpec Pydantic model using the prompt, selector, and static data associated with the current plugin_meta. It retrieves each component using their respective ORM-to-Pydantic conversion methods.

Returns:

The static plugin specification as a Pydantic model.

Return type:

SAMPluginStaticSpec

Example:

broker = SAMStaticPluginBroker()
static_spec = broker.plugin_static_spec_orm2pydantic()
print(static_spec.model_dump_json())
Raises:

SAMPluginBrokerError – If there is an error retrieving or converting any component of the plugin specification.

See also

  • SAMPluginStaticSpec

  • SAMPluginCommonSpecPrompt

  • SAMPluginCommonSpecSelector

  • SAMPluginStaticSpecData

plugin_status_pydantic()

Get the plugin status as a Pydantic model.

This method retrieves the plugin status from the Django ORM model and converts it into a Pydantic model (SAMPluginCommonStatus). It ensures that the status information is properly formatted for use in manifest serialization and API responses.

Returns:

The plugin status as a Pydantic model.

Return type:

SAMPluginCommonStatus

See also

SAMPluginCommonStatus SAMPluginBaseBroker.plugin_meta() SAMPluginBaseBroker.plugin()

Example usage:

status = broker.plugin_status_pydantic()
print(status.active, status.last_updated)
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 operations such as applying manifests or querying connections. It checks the presence of the manifest and connection properties.

Returns:

True if the broker is ready, False otherwise.

Return type:

bool

See also

SAMApiConnectionBroker.manifest() SAMApiConnectionBroker.connection()

Example usage::
if broker.ready:

print(“Broker is ready for operations.”)

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:

str

property request: HttpRequest | None

Return the request object.

Returns:

The request object.

Return type:

Optional[HttpRequest]

property request_mixin_logger_prefix: str

Returns the logger prefix for the class.

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:

str

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_case name.

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_case format, with hyphens replaced by underscores.

Return type:

str

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'
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:

SmarterJournaledJsonResponse

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 implement build_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:
  • data (str, dict, or list) – The input to convert. Can be a string, a dictionary (with snake_case keys), or a list containing strings or dictionaries.

  • convert_values (bool, optional) – If True, string values within dictionaries are also converted to camelCase. Default is False.

Returns:

The converted data in camelCase format. Returns a string, dictionary, or list, matching the input type.

Return type:

Optional[Union[str, dict, list]]

Note

  • For dictionaries, only keys are converted by default. If convert_values is 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 SmarterValueError is 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.

Parameters:

data (dict) – The dictionary to sort.

Returns:

A new dictionary with sorted keys.

Return type:

dict

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:

str

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 static plugin (not implemented).

Raises:

SAMBrokerErrorNotImplemented – Always raised to indicate that this method is not implemented.

Parameters:
  • request (HttpRequest) – The HTTP request object.

  • args – Additional positional arguments.

  • kwargs – Additional keyword arguments.

Returns:

JSON response indicating error.

Return type:

SmarterJournaledJsonResponse

property unformatted_class_name: str

Returns the raw class name without formatting.

Returns:

The unformatted class name as a string.

Return type:

str

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:

str

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