Repository navigation
Expand file tree
/
Copy pathpyproject.toml
More file actions
172 lines (158 loc) · 5.33 KB
/
Copy pathpyproject.toml
File metadata and controls
172 lines (158 loc) · 5.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
[project]
name = "sentient"
version = "3.0.0b1"
description = "Sentient - a local-first, configurable, self-evolving personal assistant"
readme = "README.md"
requires-python = ">=3.12"
license = { text = "AGPL-3.0-only" }
authors = [{ name = "Existence" }]
dependencies = [
# core daemon
"fastapi>=0.162.0",
"uvicorn[standard]>=0.54.0",
"pydantic>=2.14.1",
"pydantic-settings>=2.16.2",
"pyyaml>=6.0.3",
"httpx>=0.28.1",
# llm providers (one SDK, every provider, native tool calling)
"litellm>=1.106.6",
# storage: one sqlite file, vectors + full-text search inside it
"aiosqlite>=0.22.1",
"sqlite-vec>=0.1.9",
# secrets live in the OS keychain, never in config files
"keyring>=25.7.0",
# cli
"typer>=0.27.3",
"rich>=15.0.0",
# scheduling helpers (rrule)
"python-dateutil>=2.9.0.post0",
# IANA timezone database (Windows has none built in)
"tzdata>=2026.6",
"tzlocal>=5.4.5",
# last-resort repair of malformed JSON from small local models
"json-repair>=0.64.2",
# file uploads in the gateway
"python-multipart>=0.0.32",
# integrations: external MCP servers, keyless web search, news feeds
"mcp>=2.3.0",
"ddgs>=9.16.1",
"feedparser>=6.0.14",
# text extraction for attachments and memory import
"pypdf>=6.21.4",
"python-docx>=1.2.0",
# browser control, IMAP push, device TLS + discovery, pairing QR codes
"playwright>=1.64.1",
"aioimaplib>=2.0.3",
"cryptography>=50.0.2",
"zeroconf>=0.151.5",
"segno>=1.6.6",
# local vision models through Ollama: LiteLLM converts images with Pillow
"pillow>=12.3.0",
]
[project.optional-dependencies]
voice = [
"numpy>=2.5.4",
"soundfile>=0.14.0",
"faster-whisper>=1.2.1",
"pyttsx3>=2.99",
"kokoro-onnx>=0.6.1",
# openWakeWord pulls tflite-runtime on Linux, which has no Python 3.12 wheels; Linux uses the default
# Whisper wake engine instead (Sentient runs openWakeWord through ONNX where it is installed).
"openwakeword>=0.6; sys_platform != 'linux'",
]
# optional: webcam for the reference device node (sentient node --camera 0)
node = [
"opencv-python-headless>=5.0.0.93",
]
# optional: WhatsApp as a messaging channel (a linked device on your own account, ADR 0020).
# neonize wraps whatsmeow and ships it as a shared library in its wheel: nothing else to install.
whatsapp = [
"neonize>=0.5.2",
]
# optional: run faster-whisper on an NVIDIA GPU without a system CUDA install
voice-gpu = [
"nvidia-cublas-cu12>=12.9.2.10",
"nvidia-cudnn-cu12>=9.27.0.42",
]
dev = [
"pytest>=9.2.0",
"pytest-asyncio>=1.4.1",
"ruff>=0.17.3",
"respx>=0.23.1",
"pytest-timeout>=2.4.0",
# runs the tests in parallel (pytest -n auto); CI uses it to keep the Windows job short
"pytest-xdist>=3.8.0",
# CI runs a failed test once more and lists it as flaky (docs/DEVELOPING.md, Flaky tests)
"pytest-rerunfailures>=16.7",
# packaging: freezes the engine for the installer (packaging/build_engine.py)
"pyinstaller>=6.22.3",
# changelog: one file per change in changes/, joined into CHANGELOG.md at release time
"towncrier>=26.9.0",
]
[project.scripts]
sentient = "sentient.cli:app"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.build.targets.wheel]
packages = ["sentient"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]
# keep the temp folders of failed tests only, and of the last run only (they reached 5 GB); see docs/DEVELOPING.md
tmp_path_retention_policy = "failed"
tmp_path_retention_count = 1
# Changelog entries: one file per change in changes/ (see changes/README.md). At release time
# `python packaging/release_changelog.py <version>` turns them into a version section of CHANGELOG.md.
[tool.towncrier]
name = "Sentient"
directory = "changes"
filename = "CHANGELOG.md"
template = "changes/template.md"
start_string = "<!-- towncrier release notes start -->\n"
title_format = "## [{version}] - {project_date}"
issue_format = "#{issue}"
orphan_prefix = "+"
wrap = false
ignore = ["README.md", "template.md", ".gitkeep"]
# Keep a Changelog headings, in its order
[[tool.towncrier.type]]
directory = "added"
name = "Added"
showcontent = true
[[tool.towncrier.type]]
directory = "changed"
name = "Changed"
showcontent = true
[[tool.towncrier.type]]
directory = "deprecated"
name = "Deprecated"
showcontent = true
[[tool.towncrier.type]]
directory = "removed"
name = "Removed"
showcontent = true
[[tool.towncrier.type]]
directory = "fixed"
name = "Fixed"
showcontent = true
[[tool.towncrier.type]]
directory = "security"
name = "Security"
showcontent = true
[tool.ruff]
line-length = 100
target-version = "py312"
extend-exclude = ["src", "venv"]
[tool.ruff.lint]
# Explicit ruleset so results do not depend on a developer's global ruff config.
select = ["E", "F", "I", "UP", "B", "RUF", "SIM", "TRY", "DTZ", "RET"]
ignore = [
"E501", # line length: handled by the formatter
"RUF012", # ToolPlugin class attributes are intentionally mutable declarations
"B008", # typer.Option() in defaults is the documented typer style
"DTZ011", # date.today() for daily-note file names is intentionally local
"TRY003", # long exception messages are fine
"TRY300", # return-in-try is readable here
"TRY400", # log.warning in fallback paths is deliberate (not always an error)
]