telemt-sdk 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. telemt_sdk-1.0.0/.gitignore +11 -0
  2. telemt_sdk-1.0.0/.python-version +1 -0
  3. telemt_sdk-1.0.0/CONTRIBUTING.md +63 -0
  4. telemt_sdk-1.0.0/LICENSE +21 -0
  5. telemt_sdk-1.0.0/PKG-INFO +377 -0
  6. telemt_sdk-1.0.0/README.en.md +346 -0
  7. telemt_sdk-1.0.0/README.md +355 -0
  8. telemt_sdk-1.0.0/docs/api-reference.md +170 -0
  9. telemt_sdk-1.0.0/docs/maintaining.md +110 -0
  10. telemt_sdk-1.0.0/docs/testing.md +79 -0
  11. telemt_sdk-1.0.0/pyproject.toml +74 -0
  12. telemt_sdk-1.0.0/scripts/__init__.py +1 -0
  13. telemt_sdk-1.0.0/scripts/check_release.py +40 -0
  14. telemt_sdk-1.0.0/scripts/release_notes.py +129 -0
  15. telemt_sdk-1.0.0/src/telemt/__init__.py +34 -0
  16. telemt_sdk-1.0.0/src/telemt/client.py +177 -0
  17. telemt_sdk-1.0.0/src/telemt/exceptions.py +50 -0
  18. telemt_sdk-1.0.0/src/telemt/models/__init__.py +345 -0
  19. telemt_sdk-1.0.0/src/telemt/models/base.py +39 -0
  20. telemt_sdk-1.0.0/src/telemt/models/operations.py +39 -0
  21. telemt_sdk-1.0.0/src/telemt/models/requests.py +216 -0
  22. telemt_sdk-1.0.0/src/telemt/models/responses.py +972 -0
  23. telemt_sdk-1.0.0/src/telemt/models/web.py +469 -0
  24. telemt_sdk-1.0.0/src/telemt/py.typed +0 -0
  25. telemt_sdk-1.0.0/src/telemt/resources.py +416 -0
  26. telemt_sdk-1.0.0/tests/__init__.py +0 -0
  27. telemt_sdk-1.0.0/tests/conftest.py +42 -0
  28. telemt_sdk-1.0.0/tests/fixtures/live-responses.json +3533 -0
  29. telemt_sdk-1.0.0/tests/fixtures/source-contracts.json +5700 -0
  30. telemt_sdk-1.0.0/tests/integration/__init__.py +0 -0
  31. telemt_sdk-1.0.0/tests/integration/telemt.toml +46 -0
  32. telemt_sdk-1.0.0/tests/integration/test_live.py +196 -0
  33. telemt_sdk-1.0.0/tests/test_client.py +325 -0
  34. telemt_sdk-1.0.0/tests/test_models.py +96 -0
  35. telemt_sdk-1.0.0/tests/test_recorded_responses.py +42 -0
  36. telemt_sdk-1.0.0/tests/test_regressions.py +188 -0
  37. telemt_sdk-1.0.0/tests/test_release.py +51 -0
  38. telemt_sdk-1.0.0/tests/test_release_notes.py +89 -0
  39. telemt_sdk-1.0.0/tests/test_resources.py +267 -0
  40. telemt_sdk-1.0.0/tests/test_source_contracts.py +56 -0
  41. telemt_sdk-1.0.0/tests/typing/public_api.py +43 -0
  42. telemt_sdk-1.0.0/uv.lock +663 -0
@@ -0,0 +1,11 @@
1
+ .idea/
2
+ .venv*/
3
+ __pycache__/
4
+ *.py[cod]
5
+ .pytest_cache/
6
+ .ruff_cache/
7
+ .mypy_cache/
8
+ .coverage*
9
+ htmlcov/
10
+ dist/
11
+ *.egg-info/
@@ -0,0 +1 @@
1
+ 3.14
@@ -0,0 +1,63 @@
1
+ # Contributing
2
+
3
+ Use a separate branch for changes. For a bug report, include a minimal reproduction,
4
+ the Python/SDK/Telemt versions and the relevant API error code. Remove secrets and
5
+ private configuration before opening an issue.
6
+
7
+ ## Development setup
8
+
9
+ Install [uv](https://docs.astral.sh/uv/getting-started/installation/), then:
10
+
11
+ ```bash
12
+ git clone https://github.com/Peakora-VPN/telemt-sdk.git
13
+ cd telemt-sdk
14
+ uv python install 3.13 3.14 3.15
15
+ uv sync --locked
16
+ ```
17
+
18
+ If an older uv installation does not recognize a Python version, update uv first.
19
+ Dependencies belong in `pyproject.toml`; commit `uv.lock` when changing them.
20
+
21
+ ## Checks
22
+
23
+ ```bash
24
+ uv run ruff check .
25
+ uv run ruff format --check .
26
+ uv run mypy
27
+ uv run pytest --cov=telemt --cov-report=term-missing
28
+ uv run --isolated --python 3.13 pytest
29
+ uv run --isolated --python 3.15 pytest
30
+ uv build
31
+ ```
32
+
33
+ Run `uv run ruff format .` to apply formatting. Mypy uses strict mode for the SDK,
34
+ release verification script and consumer examples in `tests/typing`.
35
+
36
+ The default test suite is offline. It checks transport/error behavior, request validation,
37
+ all resource routes, recorded real-server responses and response contracts extracted from
38
+ Telemt's Rust types. Optional tests against a disposable server are described in
39
+ [Testing against Telemt](docs/testing.md).
40
+
41
+ CI runs Ruff and mypy, then tests on Python 3.13, 3.14 and 3.15 under Linux and Windows, and builds
42
+ the wheel and source distribution. Do not remove a supported interpreter from the matrix
43
+ to make a failing check pass.
44
+
45
+ ## Changing the API
46
+
47
+ Check both Telemt's API documentation and its handlers/serialization types. Update the
48
+ request or response model, the resource method, public exports, tests and the method
49
+ reference together. Preserve the difference between an omitted PATCH field and explicit
50
+ JSON `null`. Keep configuration revisions attached to individual responses.
51
+
52
+ When updating compatibility fixtures, record the upstream commit and how the responses
53
+ were obtained. Add a focused regression test for a behavioral fix; route existence alone
54
+ does not prove the result is decoded correctly. Include a consumer type assertion when
55
+ changing a public return type.
56
+
57
+ ## Pull requests
58
+
59
+ Explain the observed problem, the new behavior and the checks you ran. Note any API change
60
+ that requires callers to update. Contributions are provided under the repository's
61
+ [MIT license](LICENSE).
62
+
63
+ Publishing setup is documented separately in [Maintaining](docs/maintaining.md).
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Peakora-VPN
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,377 @@
1
+ Metadata-Version: 2.5
2
+ Name: telemt-sdk
3
+ Version: 1.0.0
4
+ Summary: Typed asynchronous Python SDK for the Telemt Control API
5
+ Project-URL: Homepage, https://github.com/Peakora-VPN/telemt-sdk
6
+ Project-URL: Issues, https://github.com/Peakora-VPN/telemt-sdk/issues
7
+ Project-URL: Documentation, https://github.com/Peakora-VPN/telemt-sdk#readme
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Framework :: AsyncIO
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3 :: Only
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: 3.14
16
+ Classifier: Programming Language :: Python :: 3.15
17
+ Classifier: Typing :: Typed
18
+ Requires-Python: >=3.13
19
+ Requires-Dist: httpx<1,>=0.28.1
20
+ Requires-Dist: pydantic<3,>=2.12
21
+ Description-Content-Type: text/markdown
22
+
23
+ <p align="center">
24
+ <a href="https://github.com/Peakora-VPN/telemt-sdk/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/Peakora-VPN/telemt-sdk/ci.yml?style=for-the-badge&amp;logo=githubactions&amp;logoColor=white&amp;label=CI" alt="CI status"></a>
25
+ <a href="https://pypi.org/project/telemt-sdk/"><img src="https://img.shields.io/pypi/v/telemt-sdk?style=for-the-badge&amp;logo=pypi&amp;logoColor=white&amp;color=3776AB" alt="PyPI version"></a>
26
+ <a href="#совместимость"><img src="https://img.shields.io/badge/Python-3.13%20%7C%203.14%20%7C%203.15-3776AB?style=for-the-badge&amp;logo=python&amp;logoColor=white" alt="Python 3.13, 3.14 and 3.15"></a>
27
+ <a href="https://github.com/Peakora-VPN/telemt-sdk/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-22C55E?style=for-the-badge" alt="MIT license"></a>
28
+ </p>
29
+ <p align="center">
30
+ <a href="https://docs.astral.sh/uv/"><img src="https://img.shields.io/badge/managed%20with-uv-DE5FE9?style=flat-square&amp;logo=uv" alt="Managed with uv"></a>
31
+ <a href="https://docs.astral.sh/ruff/"><img src="https://img.shields.io/badge/code%20style-Ruff-D7FF64?style=flat-square&amp;logo=ruff&amp;logoColor=black" alt="Code style: Ruff"></a>
32
+ <a href="https://typing.python.org/"><img src="https://img.shields.io/badge/typing-PEP%20561-6366F1?style=flat-square" alt="Typed Python package"></a>
33
+ </p>
34
+
35
+ <p align="center"><a href="https://github.com/Peakora-VPN/telemt-sdk/blob/main/README.md">Русский</a> · <a href="https://github.com/Peakora-VPN/telemt-sdk/blob/main/README.en.md">English</a></p>
36
+
37
+ <h1 align="center">telemt-sdk</h1>
38
+ <p align="center">Асинхронный типизированный Python SDK для Telemt Control API.</p>
39
+ <p align="center">
40
+ <a href="#быстрый-старт">Быстрый старт</a> ·
41
+ <a href="https://github.com/Peakora-VPN/telemt-sdk/blob/main/docs/api-reference.md">Справочник API</a> ·
42
+ <a href="https://github.com/Peakora-VPN/telemt-sdk/blob/main/CONTRIBUTING.md">Участие в разработке</a> ·
43
+ <a href="https://github.com/Peakora-VPN/telemt-sdk/issues">Сообщить об ошибке</a>
44
+ </p>
45
+
46
+ <p align="center"><strong>🤝 Спонсор проекта — Peakora VPN</strong></p>
47
+ <p align="center">
48
+ <a href="https://peakora.network/">
49
+ <img src="https://peakora.network/social-preview.png" width="600" alt="Peakora VPN — интернет в вашем ритме">
50
+ </a>
51
+ </p>
52
+ <p align="center">
53
+ Защищённый доступ в интернет и к AI-сервисам с подключением через Telegram.<br>
54
+ <a href="https://peakora.network/">Подробнее о Peakora →</a>
55
+ </p>
56
+
57
+ Управляйте пользователями прокси, квотами, конфигурацией, диагностикой и WEB-сессиями из Python.
58
+ `TelemtClient` объединяет операции в ресурсные объекты, переиспользует HTTP-соединения
59
+ и возвращает Pydantic-модели с конкретными аннотациями типов, включая вложенные данные.
60
+
61
+ - **48 операций API:** пользователи, состояние сервиса, статистика, перезагрузка и управление WEB runtime.
62
+ - **Полностью асинхронный интерфейс:** `async with`, `await` и параллельное чтение через `asyncio.gather`.
63
+ - **Типизированные запросы и ответы:** валидация входных данных, подсказки IDE и маркер `py.typed`.
64
+ - **Контроль конкурентных изменений:** передача ревизии ответа для защиты обновлений конфигурации.
65
+ - **Понятные ошибки:** отдельные классы исключений сохраняют HTTP-статус, код Telemt и идентификатор запроса.
66
+
67
+ SDK работает с HTTP API управления [Telemt](https://github.com/telemt/telemt).
68
+ Передачу MTProto-трафика и подключения клиентов Telegram обеспечивает сам Telemt.
69
+
70
+ ## Установка
71
+
72
+ Требуется Python **3.13, 3.14 или 3.15**. Имя пакета — `telemt-sdk`, имя импорта — `telemt`.
73
+
74
+ После появления релиза в [PyPI](https://pypi.org/project/telemt-sdk/):
75
+
76
+ ```bash
77
+ uv add telemt-sdk
78
+ ```
79
+
80
+ Или через pip:
81
+
82
+ ```bash
83
+ python -m pip install telemt-sdk
84
+ ```
85
+
86
+ До первого релиза можно работать из клонированного репозитория: выполните `uv sync --locked`
87
+ в его каталоге. Зависимости SDK — [HTTPX](https://www.python-httpx.org/)
88
+ и [Pydantic](https://docs.pydantic.dev/latest/).
89
+
90
+ ## Быстрый старт
91
+
92
+ Включите Control API в конфигурации Telemt и задайте `TELEMT_AUTH_HEADER` равным точному
93
+ значению `server.api.auth_header`. Этот пример читает состояние сервера:
94
+
95
+ ```python
96
+ import asyncio
97
+ import os
98
+
99
+ from telemt import TelemtClient
100
+
101
+
102
+ async def main() -> None:
103
+ async with TelemtClient(
104
+ "http://127.0.0.1:9091",
105
+ auth_header=os.environ["TELEMT_AUTH_HEADER"],
106
+ ) as client:
107
+ health = await client.health.get()
108
+ print(health.data.status)
109
+
110
+ users = await client.users.list()
111
+ for user in users.data:
112
+ print(user.username, user.enabled, user.current_connections)
113
+
114
+
115
+ asyncio.run(main())
116
+ ```
117
+
118
+ SDK передаёт `auth_header` в заголовке `Authorization` без изменений и не добавляет `Bearer`.
119
+ Если на сервере настроено значение `Bearer ...`, передавайте строку целиком.
120
+ Если авторизация не настроена, аргумент можно опустить. Используйте адрес слушателя
121
+ Control API, а не порт MTProto или WEB ingress.
122
+
123
+ ## Настройка клиента
124
+
125
+ | Аргумент | По умолчанию | Назначение |
126
+ | --- | --- | --- |
127
+ | `base_url` | Обязателен | Абсолютный HTTP(S) URL. `/v1` добавляется, если отсутствует. Префикс reverse proxy сохраняется. |
128
+ | `auth_header` | `None` | Точное значение заголовка `Authorization`, настроенного на сервере. |
129
+ | `timeout` | `30.0` | Тайм-аут HTTPX в секундах или `httpx.Timeout` с отдельными лимитами подключения, чтения, записи и ожидания соединения. |
130
+ | `http_client` | `None` | Необязательный `httpx.AsyncClient` для настройки TLS, прокси, транспорта и пула соединений. |
131
+
132
+ Адреса `https://proxy.example.com/control` и `https://proxy.example.com/control/v1`
133
+ оба направляют запросы в `/control/v1/...`. Учётные данные, query-параметры и фрагменты
134
+ в `base_url` не допускаются.
135
+
136
+ Используйте один клиент для нескольких запросов в пределах одного event loop:
137
+
138
+ ```python
139
+ health, stats = await asyncio.gather(client.health.get(), client.stats.summary())
140
+ print(stats.data.connections_total)
141
+ ```
142
+
143
+ Закрывайте соединения через `async with` или `await client.aclose()`. Закрытый клиент
144
+ нельзя использовать повторно. Если вы передаёте собственный HTTPX-клиент, его временем
145
+ жизни управляете вы:
146
+
147
+ ```python
148
+ import httpx
149
+
150
+ async with httpx.AsyncClient(limits=httpx.Limits(max_connections=20)) as http:
151
+ async with TelemtClient(
152
+ "https://proxy.example.com",
153
+ auth_header=auth_header,
154
+ timeout=httpx.Timeout(30.0, connect=5.0),
155
+ http_client=http,
156
+ ) as client:
157
+ info = await client.system.info()
158
+ ```
159
+
160
+ Параметры SDK и явно переданная авторизация имеют приоритет над настройками HTTPX.
161
+ Редиректы и автоматические повторы запросов отключены: изменение могло дойти до сервера
162
+ до истечения тайм-аута.
163
+
164
+ ## Пользователи и квоты
165
+
166
+ ```python
167
+ from telemt.models import CreateUserRequest, PatchUserRequest, RotateSecretRequest
168
+
169
+ created = await client.users.create(
170
+ CreateUserRequest(
171
+ username="alice",
172
+ max_tcp_conns=10,
173
+ data_quota_bytes=10_000_000_000,
174
+ quota_period="monthly",
175
+ )
176
+ )
177
+ # created.data.secret содержит сгенерированный секрет; не записывайте его в логи.
178
+ print(created.data.user.username)
179
+
180
+ updated = await client.users.update(
181
+ "alice",
182
+ PatchUserRequest(max_tcp_conns=20, expiration_rfc3339="2027-01-01T00:00:00Z"),
183
+ revision=created.revision,
184
+ )
185
+
186
+ rotated = await client.users.rotate_secret("alice", RotateSecretRequest())
187
+ await client.users.reset_quota("alice")
188
+ await client.users.disable("alice")
189
+ await client.users.enable("alice")
190
+ # Удаляйте пользователя явно, когда учётная запись больше не нужна:
191
+ # await client.users.delete("alice")
192
+ ```
193
+
194
+ Секреты и рекламные теги состоят из 32 шестнадцатеричных символов. Имя пользователя
195
+ содержит от 1 до 64 латинских букв, цифр, точек, дефисов или подчёркиваний. Имена `.`
196
+ и `..` отклоняются, поскольку HTTPX нормализует такие сегменты пути. Для периодического
197
+ сброса квоты доступны `daily`, `weekly` и `monthly`; при создании пользователя требуется
198
+ положительное значение `data_quota_bytes`.
199
+
200
+ ### Семантика PATCH
201
+
202
+ Пропущенное поле, `None` и ноль имеют разное значение:
203
+
204
+ | Запрос | Результат |
205
+ | --- | --- |
206
+ | `PatchUserRequest()` | Оставить настройки без изменений. |
207
+ | `PatchUserRequest(max_tcp_conns=None)` | Удалить индивидуальное ограничение пользователя. |
208
+ | `PatchUserRequest(max_tcp_conns=0)` | Передать явный ноль; его смысл для этой настройки определяет Telemt. |
209
+ | `PatchUserRequest(enabled=False)` | Отключить пользователя. |
210
+ | `PatchUserRequest(secret=None)` | Оставить секрет без изменений, как это делает Telemt. |
211
+
212
+ Для генерации нового секрета используйте `rotate_secret()`. Модели запросов отклоняют
213
+ неизвестные поля и недопустимые значения. Проверки, зависящие от состояния сервера,
214
+ например существование пользователя, выполняет Telemt и возвращает соответствующую ошибку API.
215
+
216
+ ## Ответы и ревизии
217
+
218
+ Каждый метод возвращает `APIResponse[T]`:
219
+
220
+ | Поле | Тип | Назначение |
221
+ | --- | --- | --- |
222
+ | `data` | `T` | Типизированный результат операции, например `UserInfo` или `list[UserInfo]`. |
223
+ | `revision` | `str` | Ревизия конфигурации сервера для этого ответа. |
224
+ | `status_code` | `int` | Фактический HTTP-статус ответа. |
225
+ | `ok` | `Literal[True]` | Успешно разобранный ответ API. |
226
+
227
+ Вложенные данные тоже представлены моделями: `user.links.tls_domains[0].domain`
228
+ и `status.runtime.manager.issuance_enabled` доступны проверке типов после проверки
229
+ nullable-полей на `None`. Модели импортируются из `telemt.models`.
230
+
231
+ ```python
232
+ current = await client.users.get("alice")
233
+ await client.users.update(
234
+ "alice",
235
+ PatchUserRequest(max_tcp_conns=30),
236
+ revision=current.revision,
237
+ )
238
+ ```
239
+
240
+ Аргумент `revision=` передаётся в заголовок `If-Match`. Устаревшая ревизия вызывает
241
+ `ConflictError`. Перечитайте состояние и проверьте, остаётся ли изменение актуальным,
242
+ прежде чем повторять запрос. Клиент не хранит общую ревизию и не подставляет её автоматически,
243
+ поэтому параллельные ответы независимы. WEB-операции используют `runtime_instance`.
244
+
245
+ Новые поля сервера сохраняются в `model_extra`. Для представления, совместимого с JSON,
246
+ используйте `model_dump(mode="json", by_alias=True)`. Разделы конфигурации остаются
247
+ `dict[str, JsonValue]`, поскольку это расширяемые конфигурационные данные;
248
+ известные структуры телеметрии и WEB описаны отдельными моделями.
249
+
250
+ ## Конфигурация и перезагрузка
251
+
252
+ ```python
253
+ from telemt.models import PatchConfigRequest, ReloadRequest
254
+
255
+ current = await client.config.get()
256
+ changed = await client.config.update(
257
+ PatchConfigRequest(censorship={"tls_domain": "front.example.com"}),
258
+ revision=current.revision,
259
+ reload=ReloadRequest(mode="drain", timeout_secs=30, failure_policy="rollback"),
260
+ )
261
+ if changed.data.reload is not None:
262
+ progress = await client.system.reload_status(changed.data.reload.reload_id)
263
+ print(progress.data.state)
264
+ ```
265
+
266
+ Для изменения доступны `general`, `timeouts`, `censorship`, `upstreams`, `dc_overrides`,
267
+ `web` и `server.listeners`. Проверка на стороне сервера определяет, какие вложенные
268
+ параметры можно изменить и каким требуется перезапуск процесса.
269
+
270
+ HTTP `202` означает принятие операции, а не её завершение. Опрашивайте
271
+ `system.reload_status(id)` с интервалом и общим тайм-аутом, подходящими вашему приложению,
272
+ до состояния `succeeded`, `rolled_back` или `failed`. Проверяйте `warnings`,
273
+ `deferred_process_fields` и `error` в результате. Для отдельной перезагрузки вызовите
274
+ `system.reload(ReloadRequest(...))`. Режим `drain` требует `timeout_secs` от 1 до 3600;
275
+ режим `instant` не принимает этот параметр.
276
+
277
+ ## WEB-сессии и жизненный цикл
278
+
279
+ ```python
280
+ from telemt.models import CloseRequest, RefsSelector, SessionQuery
281
+
282
+ status = await client.runtime.web.status()
283
+ if status.data.runtime is not None:
284
+ page = await client.runtime.web.sessions(SessionQuery(user="alice", limit=50))
285
+ if page.data.sessions:
286
+ accepted = await client.runtime.web.close_sessions(
287
+ CloseRequest(
288
+ runtime_instance=status.data.runtime.runtime_instance,
289
+ selector=RefsSelector(session_refs=[row.session_ref for row in page.data.sessions]),
290
+ )
291
+ )
292
+ progress = await client.runtime.web.operation(accepted.data.operation_id)
293
+ print(progress.data.state)
294
+ ```
295
+
296
+ Страница сессий содержит до 200 записей. Для следующей страницы передайте
297
+ `SessionQuery(cursor=page.data.next_cursor, ...)` с теми же фильтрами. Завершайте обход,
298
+ когда `next_cursor` равен `None`. Поля `scan_truncated`, `partial_sessions` и `partial`
299
+ описывают ограничения снимка состояния.
300
+
301
+ Для `pause`, `resume`, `clear_debug` и `reset_carrier_learning` используется
302
+ `RuntimeInstanceRequest`, для `drain` — `DrainRequest`. `FilterSelector` выбирает сессии
303
+ по фильтрам. `AllSelector` требует, чтобы `runtime.manager.issuance_enabled` был равен
304
+ `False`; операторский `pause()` управляет отдельным механизмом допуска. Перед выбором
305
+ всех сессий проверьте состояние runtime. Для управляемого завершения текущей работы
306
+ используйте `drain()`.
307
+
308
+ Ссылки на сессии и операции действуют в пределах текущего процесса сервера.
309
+ Опрашивайте возвращённый идентификатор операции, чтобы узнать результат:
310
+ принятие запроса само по себе не означает завершения.
311
+
312
+ ## Обработка ошибок
313
+
314
+ ```python
315
+ from telemt import APIError, ConflictError, TransportError
316
+
317
+ try:
318
+ await client.users.disable("alice", revision=known_revision)
319
+ except ConflictError as error:
320
+ print(error.code, error.request_id)
321
+ except APIError as error:
322
+ print(error.status_code, error.code, error.message)
323
+ except TransportError:
324
+ # Перечитайте состояние сервера перед решением о повторном изменении.
325
+ raise
326
+ ```
327
+
328
+ | Исключение | Значение |
329
+ | --- | --- |
330
+ | `AuthenticationError` | HTTP 401. |
331
+ | `PermissionDeniedError` | HTTP 403, включая режим read-only. |
332
+ | `NotFoundError` | HTTP 404. |
333
+ | `ConflictError` | HTTP 409, включая конфликт ревизий. |
334
+ | `APIError` | Другие ошибки сервера; доступны `status_code`, `code`, `message`, `request_id`. |
335
+ | `RequestTimeoutError` | Тайм-аут HTTPX; наследуется от `TransportError`. |
336
+ | `TransportError` | Ошибка сети или транспорта; исходное исключение доступно в `__cause__`. |
337
+ | `InvalidResponseError` | Некорректный JSON, формат ответа или структура данных. |
338
+
339
+ Все исключения SDK наследуются от `TelemtError`. Ошибки моделей запросов вызывают
340
+ `pydantic.ValidationError`; недопустимые аргументы маршрутов — `ValueError`, включая
341
+ его подкласс `ValidationError`. Отмена асинхронной задачи распространяется без обёртки.
342
+
343
+ Два HTTP-статуса могут содержать штатный результат: `health.ready()` возвращает данные
344
+ готовности при HTTP 503, а `runtime.web.session()` — `GoneSessionData` при HTTP 410.
345
+ Ответ с ошибкой API на этих маршрутах по-прежнему вызывает исключение. Используйте
346
+ `isinstance(result.data, GoneSessionData)`, чтобы отличить закрытую сессию от `SessionRow`.
347
+
348
+ ## Совместимость
349
+
350
+ SDK следует [проекту Telemt](https://github.com/telemt/telemt) и его
351
+ [Control API](https://github.com/telemt/telemt/blob/main/docs/Architecture/API/API.md).
352
+ Модели сверяются со спецификацией API и типами сериализации в Rust-коде сервера.
353
+ Клиент охватывает 48 основных операций Control API. HTML-страница `/web-status`
354
+ и транспортные WEB-эндпоинты находятся за пределами этого API-клиента.
355
+
356
+ Python 3.13, 3.14 и 3.15 входят в обязательную матрицу CI под Linux и Windows. Необязательные
357
+ возможности Telemt могут возвращать данные об отключённой или недоступной функции:
358
+ проверяйте `enabled`, `reason`, `data` и `partial`, когда они присутствуют. Сохранение
359
+ новых полей помогает при расширении ответов сервера, но не означает гарантированную
360
+ совместимость со всеми прошлыми и будущими изменениями API.
361
+
362
+ Полный перечень методов, типов запросов и ответов доступен в
363
+ [справочнике API](https://github.com/Peakora-VPN/telemt-sdk/blob/main/docs/api-reference.md).
364
+
365
+ ## Участие в разработке и поддержка
366
+
367
+ Сообщения об ошибках и pull request приветствуются. В
368
+ [issue](https://github.com/Peakora-VPN/telemt-sdk/issues) укажите версии Python, SDK и Telemt,
369
+ минимальный пример и тип исключения или код ошибки Telemt. Удалите заголовки авторизации,
370
+ секреты и приватные настройки из публикуемых материалов.
371
+
372
+ Настройка окружения uv, линтер, проверка типов и тесты описаны в
373
+ [CONTRIBUTING.md](https://github.com/Peakora-VPN/telemt-sdk/blob/main/CONTRIBUTING.md).
374
+
375
+ ## Лицензия
376
+
377
+ [MIT](https://github.com/Peakora-VPN/telemt-sdk/blob/main/LICENSE) © 2026 Peakora-VPN.