Pydantic Models

Smarter API LLMClient Manifest Constants.

Smarter API Manifest - Plugin.metadata.

class smarter.apps.llmclient.manifest.models.llmclient.metadata.SAMLLMClientMetadata(*, name: str, description: str | None, version: str | None, tags: List[str] | None = <factory>, annotations: List[dict[str, str | int | float | bool | ~datetime.date | ~datetime.datetime | ~decimal.Decimal | ~uuid.UUID | bytes | list | dict]] | None=<factory>)[source]

Bases: AbstractSAMMetadataBase

Smarter API LLMClient Manifest - Metadata class.

class_identifier: ClassVar[str] = 'LLMClient.metadata'
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

Smarter API Manifest - Plugin.spec.

smarter.apps.llmclient.manifest.models.llmclient.spec.ORIGIN_PATTERN = re.compile('^https?://[a-z0-9]([a-z0-9-]*[a-z0-9])?(\\.[a-z0-9]([a-z0-9-]*[a-z0-9])?)*(:\\d{1,5})?$')

a scheme, a host and an optional port.

Type:

An origin, as browsers send it in the Origin header

class smarter.apps.llmclient.manifest.models.llmclient.spec.SAMLLMClientCustomDomain(*, aws_hosted_zone_id: str, domain_name: str)[source]

Bases: AbstractSAMSpecBase

Smarter API LLMClient Manifest LLMClient.spec.config.customDomain.

aws_hosted_zone_id: str
class_identifier: ClassVar[str] = 'LLMClient.spec.configuration.customDomain'
domain_name: str
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

class smarter.apps.llmclient.manifest.models.llmclient.spec.SAMLLMClientSpec(*, config: SAMLLMClientSpecConfig, plugins: List[str] | None = None, functions: List[str] | None = None, guardrails: List[str] | None = None, mcpClients: List[str] | None = None, apiKey: str | None = None)[source]

Bases: AbstractSAMSpecBase

Smarter API LLMClient Manifest LLMClient.spec.

apiKey: str | None
class_identifier: ClassVar[str] = 'LLMClient.spec'
config: SAMLLMClientSpecConfig
functions: List[str] | None
guardrails: List[str] | None
mcpClients: List[str] | None
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

plugins: List[str] | None
class smarter.apps.llmclient.manifest.models.llmclient.spec.SAMLLMClientSpecConfig(*, prompt: SAMLLMClientSpecConfigPrompt, styles: SAMLLMClientSpecConfigStyles | None = None)[source]

Bases: AbstractSAMSpecBase

Smarter API LLMClient Manifest LLMClient.spec.config.

prompt, which is required, configures the LLMClient, and styles, which is optional, the look of its chat.

Manifests written before the split have their settings directly in spec.config. Apply rejects them, with an error that says where each setting belongs now. See smarter.apps.llmclient.manifest.brokers.llmclient.SAMLLMClientBroker.raise_for_unknown_keys().

class_identifier: ClassVar[str] = 'LLMClient.spec.configuration'
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

prompt: SAMLLMClientSpecConfigPrompt
styles: SAMLLMClientSpecConfigStyles | None
class smarter.apps.llmclient.manifest.models.llmclient.spec.SAMLLMClientSpecConfigPrompt(*, subdomain: str | None = None, customDomain: SAMLLMClientCustomDomain | None = None, deployed: bool = False, provider: str | None = None, defaultModel: str | None = None, defaultSystemRole: Annotated[str | None, ~annotated_types.MaxLen(max_length=2048)] = None, defaultTemperature: Annotated[float | None, ~annotated_types.Ge(ge=0.0), ~annotated_types.Le(le=1.0)] = None, defaultMaxTokens: Annotated[int | None, ~annotated_types.Gt(gt=0)] = None, appName: str | None = None, appAssistant: str | None = None, appWelcomeMessage: str | None = None, appExamplePrompts: List[str] | None = None, appPlaceholder: str | None = None, appInfoUrl: str | None = None, appFileAttachment: bool | None = False, allowedOrigins: List[str] | None = <factory>)[source]

Bases: AbstractSAMSpecBase

Smarter API LLMClient Manifest LLMClient.spec.config.prompt.

What the LLMClient is and does: its LLM provider, model and system prompt, the text of its chat (its name, welcome message, example prompts and placeholder), and where it is published.

allowedOrigins: List[str] | None
appAssistant: str | None
appExamplePrompts: List[str] | None
appFileAttachment: bool | None
appInfoUrl: str | None
appName: str | None
appPlaceholder: str | None
appWelcomeMessage: str | None
class_identifier: ClassVar[str] = 'LLMClient.spec.configuration.prompt'
customDomain: SAMLLMClientCustomDomain | None
defaultMaxTokens: int | None
defaultModel: str | None
defaultSystemRole: str | None
defaultTemperature: float | None
deployed: bool
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

provider: str | None
subdomain: str | None
classmethod validate_allowed_origins(value)[source]

Validate and normalize allowedOrigins: each is http(s)://host[:port], lowercased.

Parameters:

value (List[str] | None) – The origins.

Returns:

The normalized origins, without duplicates, in their order.

Return type:

List[str]

Raises:

ValueError – If an origin has a path, a wildcard, or another scheme.

Smarter API Manifest - LLMClient.spec.config.styles.

The look of the chat in which an LLMClient’s users talk to it: Smarter Chat, the @smarter.sh/ui-chat React component, which the Smarter workbench and every page that embeds the LLMClient render. Smarter Chat is built on chatscope’s @chatscope/chat-ui-kit-react components and their @chatscope/chat-ui-kit-styles theme, so these settings follow that theme’s design: one section per chatscope component (the main container, the conversation header, the message list, incoming and outgoing messages, the message input, the buttons and the typing indicator), and in each section, the theme’s own variables for it, such as $conversation-header-bg-color.

Every setting is optional. A setting that is left out keeps chatscope’s (or Smarter’s) default, so a manifest needs only what it changes. Values are validated here, because they are written into the pages of every site that embeds the LLMClient: colors, lengths and font names must be plain css values, and images must be https urls. When a client sends a manifest, to apply or validate it, each image url is also requested, and must respond with an image: HTTP 200, directly or after redirects. See validate_image_url_is_available().

class smarter.apps.llmclient.manifest.models.llmclient.styles.SAMLLMClientSpecConfigStyles(*, appLogoUrl: str | None = None, appBackgroundImageUrl: str | None = None, appBackgroundImageSize: Literal['cover', 'contain', 'auto'] | None = None, assistantAvatarUrl: str | None = None, userAvatarUrl: str | None = None, fontFamily: str | None = None, googleFont: str | None = None, fontSize: str | None = None, borderRadius: str | None = None, mainContainer: SAMLLMClientStylesMainContainer | None = None, conversationHeader: SAMLLMClientStylesConversationHeader | None = None, messageList: SAMLLMClientStylesMessageList | None = None, incomingMessage: SAMLLMClientStylesMessage | None = None, outgoingMessage: SAMLLMClientStylesMessage | None = None, messageInput: SAMLLMClientStylesMessageInput | None = None, buttons: SAMLLMClientStylesButtons | None = None, typingIndicator: SAMLLMClientStylesTypingIndicator | None = None)[source]

Bases: SAMLLMClientStyleSection

Smarter API LLMClient Manifest LLMClient.spec.config.styles.

The look of Smarter Chat for this LLMClient. Every setting is optional. See the module’s docstring.

appBackgroundImageSize: Literal['cover', 'contain', 'auto'] | None
appBackgroundImageUrl: str | None
appLogoUrl: str | None
assistantAvatarUrl: str | None
borderRadius: str | None
buttons: SAMLLMClientStylesButtons | None
class_identifier: ClassVar[str] = 'LLMClient.styles'
conversationHeader: SAMLLMClientStylesConversationHeader | None
fontFamily: str | None
fontSize: str | None
googleFont: str | None
incomingMessage: SAMLLMClientStylesMessage | None
mainContainer: SAMLLMClientStylesMainContainer | None
messageInput: SAMLLMClientStylesMessageInput | None
messageList: SAMLLMClientStylesMessageList | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

outgoingMessage: SAMLLMClientStylesMessage | None
typingIndicator: SAMLLMClientStylesTypingIndicator | None
userAvatarUrl: str | None
classmethod validate_font_family(value)[source]

Validate fontFamily.

Parameters:

value (str | None) – The font stack, or None.

Returns:

The font stack, or None.

Return type:

str | None

Raises:

ValueError – If the value is not a font stack.

classmethod validate_google_font(value)[source]

Validate googleFont.

Parameters:

value (str | None) – The font’s name, or None.

Returns:

The font’s name, or None.

Return type:

str | None

Raises:

ValueError – If the value is not the name of a font.

classmethod validate_lengths(value)[source]

Validate fontSize and borderRadius.

Parameters:

value (str | None) – The length, or None.

Returns:

The length, or None.

Return type:

str | None

Raises:

ValueError – If the value is not a length.

classmethod validate_urls(value)[source]

Validate the images’ urls, and, in a manifest that a client sent, that each is available.

See smarter.lib.manifest.models.client_manifest_validation().

Parameters:

value (str | None) – The url, or None.

Returns:

The url, or None.

Return type:

str | None

Raises:

ValueError – If the url is not an https url, or, in a client’s manifest, doesn’t respond with an image.

class smarter.apps.llmclient.manifest.models.llmclient.styles.SAMLLMClientStyleSection[source]

Bases: AbstractSAMSpecBase

Base class of the sections of spec.config.styles.

A section’s colors are validated as css colors, and a misspelled setting is an error, rather than being ignored.

model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

classmethod validate_colors(value, info)[source]

Validate every color setting, color and those whose names end with Color, as a css color.

Parameters:
  • value – The setting’s value.

  • info – Pydantic’s validation info, with the setting’s name.

Returns:

The value.

Raises:

ValueError – If a color setting is not a css color.

class smarter.apps.llmclient.manifest.models.llmclient.styles.SAMLLMClientStylesButtons(*, color: str | None = None)[source]

Bases: SAMLLMClientStyleSection

spec.config.styles.buttons: the send and attach buttons, and the header’s buttons.

chatscope’s Button, class .cs-button.

class_identifier: ClassVar[str] = 'LLMClient.styles.buttons'
color: str | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

class smarter.apps.llmclient.manifest.models.llmclient.styles.SAMLLMClientStylesConversationHeader(*, backgroundColor: str | None = None, color: str | None = None, infoColor: str | None = None, borderColor: str | None = None)[source]

Bases: SAMLLMClientStyleSection

spec.config.styles.conversationHeader: the bar at the top of the chat.

It holds the logo, the LLMClient’s name, its model, and the buttons. chatscope’s ConversationHeader, class .cs-conversation-header.

backgroundColor: str | None
borderColor: str | None
class_identifier: ClassVar[str] = 'LLMClient.styles.conversationHeader'
color: str | None
infoColor: str | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

class smarter.apps.llmclient.manifest.models.llmclient.styles.SAMLLMClientStylesMainContainer(*, backgroundColor: str | None = None, color: str | None = None, borderColor: str | None = None)[source]

Bases: SAMLLMClientStyleSection

spec.config.styles.mainContainer: the frame around the whole chat.

chatscope’s MainContainer, class .cs-main-container.

backgroundColor: str | None
borderColor: str | None
class_identifier: ClassVar[str] = 'LLMClient.styles.mainContainer'
color: str | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

class smarter.apps.llmclient.manifest.models.llmclient.styles.SAMLLMClientStylesMessage(*, backgroundColor: str | None = None, color: str | None = None, borderColor: str | None = None, linkColor: str | None = None)[source]

Bases: SAMLLMClientStyleSection

spec.config.styles.incomingMessage and outgoingMessage: the message bubbles.

Incoming messages are the assistant’s, on the left. Outgoing messages are the user’s, on the right. chatscope’s Message, classes .cs-message--incoming and .cs-message--outgoing.

backgroundColor: str | None
borderColor: str | None
class_identifier: ClassVar[str] = 'LLMClient.styles.message'
color: str | None
linkColor: str | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

class smarter.apps.llmclient.manifest.models.llmclient.styles.SAMLLMClientStylesMessageInput(*, backgroundColor: str | None = None, editorBackgroundColor: str | None = None, color: str | None = None, placeholderColor: str | None = None, borderColor: str | None = None)[source]

Bases: SAMLLMClientStyleSection

spec.config.styles.messageInput: the box at the bottom, in which the user types.

chatscope’s MessageInput, class .cs-message-input.

backgroundColor: str | None
borderColor: str | None
class_identifier: ClassVar[str] = 'LLMClient.styles.messageInput'
color: str | None
editorBackgroundColor: str | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

placeholderColor: str | None
class smarter.apps.llmclient.manifest.models.llmclient.styles.SAMLLMClientStylesMessageList(*, backgroundColor: str | None = None, color: str | None = None)[source]

Bases: SAMLLMClientStyleSection

spec.config.styles.messageList: the scrolling area that holds the conversation.

It is painted over appBackgroundImageUrl, so a semi-transparent backgroundColor tints the image. chatscope’s MessageList, class .cs-message-list.

backgroundColor: str | None
class_identifier: ClassVar[str] = 'LLMClient.styles.messageList'
color: str | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

class smarter.apps.llmclient.manifest.models.llmclient.styles.SAMLLMClientStylesTypingIndicator(*, color: str | None = None)[source]

Bases: SAMLLMClientStyleSection

spec.config.styles.typingIndicator: “Assistant is typing”, and its dots, while the LLM answers.

chatscope’s TypingIndicator, class .cs-typing-indicator.

class_identifier: ClassVar[str] = 'LLMClient.styles.typingIndicator'
color: str | None
model_config = {'arbitrary_types_allowed': True, 'extra': 'forbid', 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

smarter.apps.llmclient.manifest.models.llmclient.styles.validate_color(value)[source]

Validate a css color.

Parameters:

value (str | None) – The color, or None.

Returns:

The color, or None.

Return type:

str | None

Raises:

ValueError – If the value is not a color.

smarter.apps.llmclient.manifest.models.llmclient.styles.validate_font_family(value)[source]

Validate a css font stack.

Parameters:

value (str | None) – The font stack, or None.

Returns:

The font stack, or None.

Return type:

str | None

Raises:

ValueError – If the value is not a font stack.

smarter.apps.llmclient.manifest.models.llmclient.styles.validate_image_url(value)[source]

Validate the url of an image.

Parameters:

value (str | None) – The url, or None.

Returns:

The url, or None.

Return type:

str | None

Raises:

ValueError – If the value is not an https url.

smarter.apps.llmclient.manifest.models.llmclient.styles.validate_image_url_is_available(url)[source]

Validate that an image url responds with an image.

The url is requested with HEAD, or with GET if the server doesn’t allow HEAD, through smarter.apps.plugin.plugin.safe_http.fetch(), which refuses urls that aren’t public (server-side request forgery), and follows redirects, validating each one. The response must be HTTP 200, directly or after redirects (e.g. a 301), and must not be a web page. The result is not cached, so that each apply checks that the url is still available.

Parameters:

url (str) – The https url of an image.

Raises:

ValueError – If the url doesn’t respond with an image.

Return type:

None

smarter.apps.llmclient.manifest.models.llmclient.styles.validate_length(value)[source]

Validate a css length.

Parameters:

value (str | None) – The length, or None.

Returns:

The length, or None.

Return type:

str | None

Raises:

ValueError – If the value is not a length.

Smarter API Manifest - Plugin.status.

class smarter.apps.llmclient.manifest.models.llmclient.status.SAMLLMClientStatus(*, recordLocator: str, created: datetime, modified: datetime, dependencies: List[SAMDependency] | None = None, accountNumber: str, username: str, deployed: bool, defaultHost: str, defaultUrl: str, customUrl: str | None, sandboxHost: str, sandboxUrl: str, hostname: str, url: str, urlLLMClient: str, urlChatapp: str, urlChatConfig: str, dnsVerificationStatus: str)[source]

Bases: AbstractSAMStatusBase

Smarter API LLMClient Manifest - Status class.

accountNumber: str
class_identifier: ClassVar[str] = 'LLMClient.status'
customUrl: str | None
defaultHost: str
defaultUrl: str
deployed: bool
dnsVerificationStatus: str
hostname: str
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

sandboxHost: str
sandboxUrl: str
url: str
urlChatConfig: str
urlChatapp: str
urlLLMClient: str
username: str

Smarter API LLMClient Manifest.

class smarter.apps.llmclient.manifest.models.llmclient.model.SAMLLMClient(*, apiVersion: str, kind: str, metadata: SAMLLMClientMetadata, spec: SAMLLMClientSpec, status: SAMLLMClientStatus | None = None)[source]

Bases: AbstractSAMBase

Smarter API Manifest - LLMClient.

class_identifier: ClassVar[str] = 'LLMClient'
metadata: SAMLLMClientMetadata
model_config = {'arbitrary_types_allowed': True, 'from_attributes': True, 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_post_init(context, /)

This function is meant to behave like a BaseModel method to initialize private attributes.

It takes context as an argument since that’s what pydantic-core passes when calling it.

Parameters:
  • self (BaseModel) – The BaseModel instance.

  • context (Any) – The context.

Return type:

None

spec: SAMLLMClientSpec
status: SAMLLMClientStatus | None