-
-
Notifications
You must be signed in to change notification settings - Fork 38
Expand file tree
/
Copy pathpyproject.toml
More file actions
209 lines (203 loc) · 9.53 KB
/
Copy pathpyproject.toml
File metadata and controls
209 lines (203 loc) · 9.53 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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
[build-system]
requires = ["setuptools>=83.0.0"]
build-backend = "setuptools.build_meta"
[project]
name = "tinyagentos"
version = "1.0.0-beta.52"
description = "Self-hosted AI agent memory system for low-power hardware"
license = { file = "LICENSE" }
# Upper-capped at <3.14 because litellm (the proxy extra, the agent/model proxy
# runtime) supports only >=3.10,<3.14. A fresh distro that defaults python3 to
# 3.14 would otherwise build the venv on 3.14 and abort with "No matching
# distribution found for litellm". The installer also steers the venv to a
# supported interpreter; this cap makes the constraint explicit to pip and uv.
requires-python = ">=3.11,<3.14"
dependencies = [
# Cap below 0.137: fastapi 0.137.0 regressed include_router so that a
# mounted APIRouter contributes none of its routes to the app, leaving
# create_app() with an empty API surface. 0.136.3 is the last good release.
"fastapi>=0.115.0,<0.137",
"uvicorn[standard]>=0.52.1",
"httpx>=0.27.0",
# Retry loop behind tinyagentos/clients/retry.py — every outbound inference
# call and every adapter /message proxy runs through it. Apache-2.0, pure
# py3-none-any wheel with no runtime dependencies of its own.
"tenacity>=9.1.4",
"jinja2>=3.1.0",
"pyyaml>=6.0",
"aiosqlite>=0.20.0",
"argon2-cffi>=23.1.0",
"sqlcipher3>=0.6.2",
"psutil>=5.9.0",
"python-multipart>=0.0.9",
# Project canvas board renders low-fidelity PNG snapshots for vision
# agents (tinyagentos/projects/canvas/render.py).
"Pillow>=10.0",
"lxml>=5.0.0",
"readability-lxml>=0.8.1",
# Memory system — published to PyPI
"taosmd==0.4.0",
# WebSocket client for dashboard proxy (shortcut_proxy.py)
"websockets>=12.0",
# Web Push VAPID signing — pulls in cryptography, http-ece, py-vapid
"pywebpush>=1.14",
# mDNS/Bonjour publisher so the controller is reachable at
# http://taos.local:<port>/ on the LAN without users knowing its IP
# (tinyagentos/services/mdns_publisher.py).
"zeroconf>=0.150.0",
"matrix-nio>=0.26.0",
# Diff/patch for the notes revision log: computes and applies text diffs
# for the Time Machine history layer (tinyagentos/notes/shared_docs_store.py).
"diff-match-patch>=20230430",
# Cron expression parsing for project routines (schedule -> next_fire).
"croniter>=6.2.4",
# Process-shared lock serialising the local-token bindings RMW
# (tinyagentos/auth.py bind_local_token_agent). Previously only present
# transitively; declare it directly so the import is guaranteed.
"filelock>=3.12",
# ES256 signing for APNs JWTs (tinyagentos/push/apns.py), imported at
# startup via app.py. Previously only pulled in transitively through
# pywebpush; declare it directly so the import is guaranteed.
"cryptography>=50.0.0",
# Unicode-aware slugs for agent/handle names (tinyagentos/config.py). The
# ASCII-only regex it replaces deleted every non-Latin code point, so a
# Chinese or Cyrillic agent name could not be created at all.
# NEVER install the "unidecode" extra: it pulls GPL-only Unidecode, which
# is a blocker for the commercial licence. See docs/dependency-licences.md.
"python-slugify>=8.0.4",
# PEP 440 version parsing/ordering for the worker update check
# (tinyagentos/worker/update_check.py) and the optional-app catalog
# (tinyagentos/routes/apps.py). Previously only reachable through the
# proxy extra and the dev group, so a bare `uv sync` did not install it.
"packaging>=24",
# YouTube/X knowledge ingestion shells out to the yt-dlp CLI
# (tinyagentos/knowledge_fetchers/{youtube,x}.py). install-server.sh used to
# `pip install yt-dlp` after the editable install, which put a package on
# every production box that uv.lock had never resolved — so an upstream
# relicence or CVE reached users without tripping any gate. Declared here so
# it goes through the lockfile like everything else.
"yt-dlp>=2025.1.15",
]
[project.optional-dependencies]
worker = ["pystray>=0.19.0", "Pillow>=10.0"]
# The LiteLLM proxy, WITHOUT litellm's own `[proxy]` extra.
#
# `litellm[proxy]` lists `litellm-enterprise` as a plain member, and that wheel
# carries `License-Expression: LicenseRef-Proprietary` (BerriAI). Nothing in
# taOS imports it — `grep -rn litellm_enterprise tinyagentos/` is empty — but a
# licence governs *distribution*, not import: every server install landed it in
# the shipped venv, so a commercial taOS licensee redistributing that venv was
# redistributing BerriAI proprietary code. litellm itself is MIT and is fine.
#
# pip cannot subtract one member of someone else's extra, so litellm's proxy
# requirements are inlined below, verbatim from litellm 1.94.2's own
# `[project.optional-dependencies].proxy`, minus `litellm-enterprise`. Verified
# by booting the proxy the way llm_proxy.start() does (master-key mode and the
# in-house-key custom_auth mode) against this exact set: /health/readiness,
# /health, /v1/models, /v1/chat/completions and /v1/embeddings all serve with no
# litellm_enterprise in the venv.
#
# litellm is capped to the minor this list mirrors. `pip install -e ".[proxy]"`
# resolves fresh — it does NOT read uv.lock — so an uncapped floor would let a
# fresh install pull a newer litellm whose proxy extra has grown requirements
# this list does not carry. Concretely: litellm 1.99.0 adds `hiredis` and makes
# `expression` an eager import, and a venv built from the 1.94 subset dies at
# startup with ModuleNotFoundError. Bumping the cap means re-reading upstream's
# proxy extra and re-syncing this list; tests/test_install_licences.py holds the
# rule and scripts/check_install_licences.py re-checks the resolved licences.
proxy = [
"litellm>=1.94.2,<1.95",
"prisma>=0.11.0",
# --- litellm 1.94.2 [proxy], minus litellm-enterprise ---
"apscheduler>=3.11.2,<4.0",
"azure-identity>=1.25.2,<2.0",
"azure-storage-blob>=12.28.0,<13.0",
"backoff>=2.2.1,<3.0",
"boto3>=1.43.1,<2.0",
"cryptography>=49.0.0,<51.0",
"expression>=5.6.0,<6.0",
"fastapi>=0.136.3,<1.0",
"fastapi-sso>=0.19.0,<1.0",
"granian>=2.7.4,<3.0",
"gunicorn>=23.0.0,<24.0",
"inquirerpy>=0.3.4,<1.0",
"litellm-proxy-extras>=0.4.79.post2",
"mcp>=1.28.1,<2.0",
"orjson>=3.11.6,<4.0",
"polars>=1.38.1,<2.0",
"pydantic-settings>=2.14.1,<3.0",
"pyjwt>=2.13.0,<3.0",
"pynacl>=1.6.2,<2.0",
"pyroscope-io>=0.8.16,<1.0; sys_platform != 'win32'",
"python-multipart>=0.0.27,<1.0",
"pyyaml>=6.0.3,<7.0",
"restrictedpython>=8.1,<9.0",
"rich>=13.9.4,<14.0",
"rq>=2.7.0,<3.0",
"soundfile>=0.12.1,<1.0",
"starlette>=1.0.1,<2.0",
"uvicorn>=0.33.0,<1.0",
"uvloop>=0.21.0,<1.0; sys_platform != 'win32'",
"websockets>=15.0.1,<16.0",
]
# Model torrent mesh (optional): libtorrent has no PyPI wheel on most platforms
# (OS-level libtorrent-rasterbar / python3-libtorrent), so it must not be a core
# dependency or fresh installs abort. torrent_downloader guards the import and
# falls back to a direct download when it is absent.
torrent = ["libtorrent>=2.0.9"]
e2e = [
"pytest>=9.1.1",
"pytest-playwright>=0.5.0",
]
[dependency-groups]
dev = [
"pytest>=9.1.1",
"pytest-asyncio>=0.23.0",
"pytest-timeout>=2.3.0",
"pytest-xdist>=3.5.0",
# Shards the suite across parallel CI jobs. xdist parallelises WITHIN a job
# and a hosted runner has 2 vCPU, so -n auto caps at 2 workers no matter how
# many tests there are; the only remaining lever is more jobs (#2135).
"pytest-split>=0.9.0",
"httpx",
"respx>=0.21.0",
"websockets>=12.0",
]
[tool.setuptools.packages.find]
include = ["tinyagentos*"]
[project.scripts]
tinyagentos = "tinyagentos.app:main"
tinyagentos-worker = "tinyagentos.worker.__main__:main"
taos = "tinyagentos.app:main"
taos-gui = "tinyagentos.app:gui"
taos-worker-ctl = "tinyagentos.cli.worker:main"
taosctl = "tinyagentos.cli.taosctl.__main__:main"
[tool.pytest.ini_options]
# Per-test timeout: a single hung test fails fast and named instead of
# silently eating the entire 45-minute CI budget. 120 s covers the
# slowest legitimate tests (async DB-heavy flows) with headroom to spare.
# thread method works on all platforms including macOS; signal would be
# faster but requires the main thread.
timeout = 120
timeout_method = "thread"
markers = [
"e2e: End-to-end browser tests (require running server)",
"slow: Tests requiring a live stack (skipped in local CI; run with pytest -m slow)",
# Opt OUT of real CSRF enforcement for this test/class/module. CSRF is ON
# by default (tests/conftest.py); this marker is the only way to disable
# it, and every module carrying it is inventoried in
# tests/test_csrf_bypass_debt.py so the list cannot grow unnoticed.
"csrf_bypass: run this test with verify_csrf stubbed to a no-op (legacy debt)",
"skip_if_no_embed_backend: skip when no embed backend can serve the test (qmd unreachable and onnxruntime absent)",
]
filterwarnings = [
# Asyncio teardown emits unraisable RuntimeError("Event loop is closed")
# warnings when finalisers (httpx clients, aiosqlite connections) fire
# during interpreter shutdown after the loop is gone. Harmless — tests
# have already passed — but trips GitHub Actions log parser into
# ##[error] annotations. Narrow filter: only matches the well-known
# "Exception ignored in:" prefix that pytest uses for these, so
# genuine unraisable exceptions in __del__ or forgotten awaitables
# still surface as test failures.
"ignore:Exception ignored in:pytest.PytestUnraisableExceptionWarning",
]