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:
2026-10-25 17:05:13 -03:00
commit 6b3b6541a7
3792 changed files with 805563 additions and 0 deletions
@@ -0,0 +1,286 @@
"""Paragraph-related proxy types."""
from docx.enum.text import WD_LINE_SPACING
from docx.shared import ElementProxy, Emu, Length, Pt, Twips, lazyproperty
from docx.text.tabstops import TabStops
class ParagraphFormat(ElementProxy):
"""Provides access to paragraph formatting such as justification, indentation, line
spacing, space before and after, and widow/orphan control."""
@property
def alignment(self):
"""A member of the :ref:`WdParagraphAlignment` enumeration specifying the
justification setting for this paragraph.
A value of |None| indicates paragraph alignment is inherited from the style
hierarchy.
"""
pPr = self._element.pPr
if pPr is None:
return None
return pPr.jc_val
@alignment.setter
def alignment(self, value):
pPr = self._element.get_or_add_pPr()
pPr.jc_val = value
@property
def first_line_indent(self):
"""|Length| value specifying the relative difference in indentation for the
first line of the paragraph.
A positive value causes the first line to be indented. A negative value produces
a hanging indent. |None| indicates first line indentation is inherited from the
style hierarchy.
"""
pPr = self._element.pPr
if pPr is None:
return None
return pPr.first_line_indent
@first_line_indent.setter
def first_line_indent(self, value):
pPr = self._element.get_or_add_pPr()
pPr.first_line_indent = value
@property
def keep_together(self):
"""|True| if the paragraph should be kept "in one piece" and not broken across a
page boundary when the document is rendered.
|None| indicates its effective value is inherited from the style hierarchy.
"""
pPr = self._element.pPr
if pPr is None:
return None
return pPr.keepLines_val
@keep_together.setter
def keep_together(self, value):
self._element.get_or_add_pPr().keepLines_val = value
@property
def keep_with_next(self):
"""|True| if the paragraph should be kept on the same page as the subsequent
paragraph when the document is rendered.
For example, this property could be used to keep a section heading on the same
page as its first paragraph. |None| indicates its effective value is inherited
from the style hierarchy.
"""
pPr = self._element.pPr
if pPr is None:
return None
return pPr.keepNext_val
@keep_with_next.setter
def keep_with_next(self, value):
self._element.get_or_add_pPr().keepNext_val = value
@property
def left_indent(self):
"""|Length| value specifying the space between the left margin and the left side
of the paragraph.
|None| indicates the left indent value is inherited from the style hierarchy.
Use an |Inches| value object as a convenient way to apply indentation in units
of inches.
"""
pPr = self._element.pPr
if pPr is None:
return None
return pPr.ind_left
@left_indent.setter
def left_indent(self, value):
pPr = self._element.get_or_add_pPr()
pPr.ind_left = value
@property
def line_spacing(self):
"""|float| or |Length| value specifying the space between baselines in
successive lines of the paragraph.
A value of |None| indicates line spacing is inherited from the style hierarchy.
A float value, e.g. ``2.0`` or ``1.75``, indicates spacing is applied in
multiples of line heights. A |Length| value such as ``Pt(12)`` indicates spacing
is a fixed height. The |Pt| value class is a convenient way to apply line
spacing in units of points. Assigning |None| resets line spacing to inherit from
the style hierarchy.
"""
pPr = self._element.pPr
if pPr is None:
return None
return self._line_spacing(pPr.spacing_line, pPr.spacing_lineRule)
@line_spacing.setter
def line_spacing(self, value):
pPr = self._element.get_or_add_pPr()
if value is None:
pPr.spacing_line = None
pPr.spacing_lineRule = None
elif isinstance(value, Length):
pPr.spacing_line = value
if pPr.spacing_lineRule != WD_LINE_SPACING.AT_LEAST:
pPr.spacing_lineRule = WD_LINE_SPACING.EXACTLY
else:
pPr.spacing_line = Emu(value * Twips(240))
pPr.spacing_lineRule = WD_LINE_SPACING.MULTIPLE
@property
def line_spacing_rule(self):
"""A member of the :ref:`WdLineSpacing` enumeration indicating how the value of
:attr:`line_spacing` should be interpreted.
Assigning any of the :ref:`WdLineSpacing` members :attr:`SINGLE`,
:attr:`DOUBLE`, or :attr:`ONE_POINT_FIVE` will cause the value of
:attr:`line_spacing` to be updated to produce the corresponding line spacing.
"""
pPr = self._element.pPr
if pPr is None:
return None
return self._line_spacing_rule(pPr.spacing_line, pPr.spacing_lineRule)
@line_spacing_rule.setter
def line_spacing_rule(self, value):
pPr = self._element.get_or_add_pPr()
if value == WD_LINE_SPACING.SINGLE:
pPr.spacing_line = Twips(240)
pPr.spacing_lineRule = WD_LINE_SPACING.MULTIPLE
elif value == WD_LINE_SPACING.ONE_POINT_FIVE:
pPr.spacing_line = Twips(360)
pPr.spacing_lineRule = WD_LINE_SPACING.MULTIPLE
elif value == WD_LINE_SPACING.DOUBLE:
pPr.spacing_line = Twips(480)
pPr.spacing_lineRule = WD_LINE_SPACING.MULTIPLE
else:
pPr.spacing_lineRule = value
@property
def page_break_before(self):
"""|True| if the paragraph should appear at the top of the page following the
prior paragraph.
|None| indicates its effective value is inherited from the style hierarchy.
"""
pPr = self._element.pPr
if pPr is None:
return None
return pPr.pageBreakBefore_val
@page_break_before.setter
def page_break_before(self, value):
self._element.get_or_add_pPr().pageBreakBefore_val = value
@property
def right_indent(self):
"""|Length| value specifying the space between the right margin and the right
side of the paragraph.
|None| indicates the right indent value is inherited from the style hierarchy.
Use a |Cm| value object as a convenient way to apply indentation in units of
centimeters.
"""
pPr = self._element.pPr
if pPr is None:
return None
return pPr.ind_right
@right_indent.setter
def right_indent(self, value):
pPr = self._element.get_or_add_pPr()
pPr.ind_right = value
@property
def space_after(self):
"""|Length| value specifying the spacing to appear between this paragraph and
the subsequent paragraph.
|None| indicates this value is inherited from the style hierarchy. |Length|
objects provide convenience properties, such as :attr:`~.Length.pt` and
:attr:`~.Length.inches`, that allow easy conversion to various length units.
"""
pPr = self._element.pPr
if pPr is None:
return None
return pPr.spacing_after
@space_after.setter
def space_after(self, value):
self._element.get_or_add_pPr().spacing_after = value
@property
def space_before(self):
"""|Length| value specifying the spacing to appear between this paragraph and
the prior paragraph.
|None| indicates this value is inherited from the style hierarchy. |Length|
objects provide convenience properties, such as :attr:`~.Length.pt` and
:attr:`~.Length.cm`, that allow easy conversion to various length units.
"""
pPr = self._element.pPr
if pPr is None:
return None
return pPr.spacing_before
@space_before.setter
def space_before(self, value):
self._element.get_or_add_pPr().spacing_before = value
@lazyproperty
def tab_stops(self):
"""|TabStops| object providing access to the tab stops defined for this
paragraph format."""
pPr = self._element.get_or_add_pPr()
return TabStops(pPr)
@property
def widow_control(self):
"""|True| if the first and last lines in the paragraph remain on the same page
as the rest of the paragraph when Word repaginates the document.
|None| indicates its effective value is inherited from the style hierarchy.
"""
pPr = self._element.pPr
if pPr is None:
return None
return pPr.widowControl_val
@widow_control.setter
def widow_control(self, value):
self._element.get_or_add_pPr().widowControl_val = value
@staticmethod
def _line_spacing(spacing_line, spacing_lineRule):
"""Return the line spacing value calculated from the combination of
`spacing_line` and `spacing_lineRule`.
Returns a |float| number of lines when `spacing_lineRule` is
``WD_LINE_SPACING.MULTIPLE``, otherwise a |Length| object of absolute line
height is returned. Returns |None| when `spacing_line` is |None|.
"""
if spacing_line is None:
return None
if spacing_lineRule == WD_LINE_SPACING.MULTIPLE:
return spacing_line / Pt(12)
return spacing_line
@staticmethod
def _line_spacing_rule(line, lineRule):
"""Return the line spacing rule value calculated from the combination of `line`
and `lineRule`.
Returns special members of the :ref:`WdLineSpacing` enumeration when line
spacing is single, double, or 1.5 lines.
"""
if lineRule == WD_LINE_SPACING.MULTIPLE:
if line == Twips(240):
return WD_LINE_SPACING.SINGLE
if line == Twips(360):
return WD_LINE_SPACING.ONE_POINT_FIVE
if line == Twips(480):
return WD_LINE_SPACING.DOUBLE
return lineRule