feat: add psagentai agent with deployment and configuration
Initial project setup including the main agent script, configuration files, profile JSON state, systemd service unit, startup script, deployment documentation, and Python dependencies. Includes .env, venv/, and __pycache__/ which should likely be excluded via .gitignore to avoid committing secrets and artifacts.
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
"""RootModel class and type definitions."""
|
||||
|
||||
from __future__ import annotations as _annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from copy import copy, deepcopy
|
||||
from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar
|
||||
|
||||
from pydantic_core import PydanticUndefined
|
||||
from typing_extensions import Self, dataclass_transform
|
||||
|
||||
from . import PydanticUserError
|
||||
from ._internal import _model_construction, _repr
|
||||
from .main import BaseModel, _object_setattr
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .fields import Field as PydanticModelField
|
||||
from .fields import PrivateAttr as PydanticModelPrivateAttr
|
||||
from .main import IncEx
|
||||
|
||||
# dataclass_transform could be applied to RootModel directly, but `ModelMetaclass`'s dataclass_transform
|
||||
# takes priority (at least with pyright). We trick type checkers into thinking we apply dataclass_transform
|
||||
# on a new metaclass.
|
||||
@dataclass_transform(kw_only_default=False, field_specifiers=(PydanticModelField, PydanticModelPrivateAttr))
|
||||
class _RootModelMetaclass(_model_construction.ModelMetaclass): ...
|
||||
else:
|
||||
_RootModelMetaclass = _model_construction.ModelMetaclass
|
||||
|
||||
__all__ = ('RootModel',)
|
||||
|
||||
RootModelRootType = TypeVar('RootModelRootType')
|
||||
|
||||
|
||||
class RootModel(BaseModel, Generic[RootModelRootType], metaclass=_RootModelMetaclass):
|
||||
"""!!! abstract "Usage Documentation"
|
||||
[`RootModel` and Custom Root Types](../concepts/models.md#rootmodel-and-custom-root-types)
|
||||
|
||||
A Pydantic `BaseModel` for the root object of the model.
|
||||
|
||||
Attributes:
|
||||
root: The root object of the model.
|
||||
__pydantic_root_model__: Whether the model is a RootModel.
|
||||
__pydantic_private__: Private fields in the model.
|
||||
__pydantic_extra__: Extra fields in the model.
|
||||
|
||||
"""
|
||||
|
||||
__pydantic_root_model__ = True
|
||||
__pydantic_private__ = None
|
||||
__pydantic_extra__ = None
|
||||
|
||||
root: RootModelRootType
|
||||
|
||||
def __init_subclass__(cls, **kwargs):
|
||||
extra = cls.model_config.get('extra')
|
||||
if extra is not None:
|
||||
raise PydanticUserError(
|
||||
"`RootModel` does not support setting `model_config['extra']`", code='root-model-extra'
|
||||
)
|
||||
super().__init_subclass__(**kwargs)
|
||||
|
||||
def __init__(self, /, root: RootModelRootType = PydanticUndefined, **data) -> None: # type: ignore
|
||||
__tracebackhide__ = True
|
||||
if data:
|
||||
if root is not PydanticUndefined:
|
||||
raise ValueError(
|
||||
'"RootModel.__init__" accepts either a single positional argument or arbitrary keyword arguments'
|
||||
)
|
||||
root = data # type: ignore
|
||||
self.__pydantic_validator__.validate_python(root, self_instance=self)
|
||||
|
||||
__init__.__pydantic_base_init__ = True # pyright: ignore[reportFunctionMemberAccess]
|
||||
|
||||
@classmethod
|
||||
def model_construct(cls, root: RootModelRootType, _fields_set: set[str] | None = None) -> Self: # type: ignore
|
||||
"""Create a new model using the provided root object and update fields set.
|
||||
|
||||
Args:
|
||||
root: The root object of the model.
|
||||
_fields_set: The set of fields to be updated.
|
||||
|
||||
Returns:
|
||||
The new model.
|
||||
|
||||
Raises:
|
||||
NotImplemented: If the model is not a subclass of `RootModel`.
|
||||
"""
|
||||
return super().model_construct(root=root, _fields_set=_fields_set)
|
||||
|
||||
def __getstate__(self) -> dict[Any, Any]:
|
||||
return {
|
||||
'__dict__': self.__dict__,
|
||||
'__pydantic_fields_set__': self.__pydantic_fields_set__,
|
||||
}
|
||||
|
||||
def __setstate__(self, state: dict[Any, Any]) -> None:
|
||||
_object_setattr(self, '__pydantic_fields_set__', state['__pydantic_fields_set__'])
|
||||
_object_setattr(self, '__dict__', state['__dict__'])
|
||||
|
||||
def __copy__(self) -> Self:
|
||||
"""Returns a shallow copy of the model."""
|
||||
cls = type(self)
|
||||
m = cls.__new__(cls)
|
||||
new_dict = copy(self.__dict__)
|
||||
new_dict['root'] = copy(self.__dict__['root']) # pyright: ignore[reportIndexIssue] (https://github.com/microsoft/pyright/issues/11548)
|
||||
_object_setattr(m, '__dict__', new_dict)
|
||||
_object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__))
|
||||
return m
|
||||
|
||||
def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self:
|
||||
"""Returns a deep copy of the model."""
|
||||
cls = type(self)
|
||||
m = cls.__new__(cls)
|
||||
_object_setattr(m, '__dict__', deepcopy(self.__dict__, memo=memo))
|
||||
# This next line doesn't need a deepcopy because __pydantic_fields_set__ is a set[str],
|
||||
# and attempting a deepcopy would be marginally slower.
|
||||
_object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__))
|
||||
return m
|
||||
|
||||
if TYPE_CHECKING:
|
||||
# This `model_dump()` definition is only provided to get a more accurate return type for type checkers
|
||||
# (no override is actually necessary at runtime). Generally, the return type will be `RootModelRootType`,
|
||||
# assuming that `RootModelRootType` is not a `BaseModel` subclass. If `RootModelRootType` is a `BaseModel`
|
||||
# subclass, then the return type will likely be `dict[str, Any]`, as `model_dump()` calls are recursive.
|
||||
# The return type could even be something different, in the case of a custom serializer. Thus, `Any` is
|
||||
# used here to catch all of these cases.
|
||||
|
||||
def model_dump( # type: ignore
|
||||
self,
|
||||
*,
|
||||
mode: Literal['json', 'python'] | str = 'python',
|
||||
include: IncEx | None = None,
|
||||
exclude: IncEx | None = None,
|
||||
context: Any | None = None,
|
||||
by_alias: bool | None = None,
|
||||
exclude_unset: bool = False,
|
||||
exclude_defaults: bool = False,
|
||||
exclude_none: bool = False,
|
||||
exclude_computed_fields: bool = False,
|
||||
round_trip: bool = False,
|
||||
warnings: bool | Literal['none', 'warn', 'error'] = True,
|
||||
fallback: Callable[[Any], Any] | None = None,
|
||||
serialize_as_any: bool = False,
|
||||
polymorphic_serialization: bool | None = None,
|
||||
) -> Any:
|
||||
"""!!! abstract "Usage Documentation"
|
||||
[`model_dump`](../concepts/serialization.md#python-mode)
|
||||
|
||||
Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.
|
||||
|
||||
Args:
|
||||
mode: The mode in which `to_python` should run.
|
||||
If mode is 'json', the output will only contain JSON serializable types.
|
||||
If mode is 'python', the output may contain non-JSON-serializable Python objects.
|
||||
include: A set of fields to include in the output.
|
||||
exclude: A set of fields to exclude from the output.
|
||||
context: Additional context to pass to the serializer.
|
||||
by_alias: Whether to use the field's alias in the dictionary key if defined.
|
||||
exclude_unset: Whether to exclude fields that have not been explicitly set.
|
||||
exclude_defaults: Whether to exclude fields that are set to their default value.
|
||||
exclude_none: Whether to exclude fields that have a value of `None`.
|
||||
exclude_computed_fields: Whether to exclude computed fields.
|
||||
While this can be useful for round-tripping, it is usually recommended to use the dedicated
|
||||
`round_trip` parameter instead.
|
||||
round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].
|
||||
warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors,
|
||||
"error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError].
|
||||
fallback: A function to call when an unknown value is encountered. If not provided,
|
||||
a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised.
|
||||
serialize_as_any: Whether to serialize fields with duck-typing serialization behavior.
|
||||
polymorphic_serialization: Whether to use model and dataclass polymorphic serialization for this call.
|
||||
|
||||
Returns:
|
||||
A dictionary representation of the model.
|
||||
"""
|
||||
...
|
||||
|
||||
def __eq__(self, other: Any) -> bool:
|
||||
if not isinstance(other, RootModel):
|
||||
return NotImplemented
|
||||
return self.__pydantic_fields__['root'].annotation == other.__pydantic_fields__[
|
||||
'root'
|
||||
].annotation and super().__eq__(other)
|
||||
|
||||
def __repr_args__(self) -> _repr.ReprArgs:
|
||||
yield 'root', self.root
|
||||
Reference in New Issue
Block a user