lime-sites-sdk 0.1.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.
@@ -0,0 +1,64 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ tags: ["v*"]
7
+ pull_request:
8
+ branches: [main, master]
9
+
10
+ jobs:
11
+ quality:
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ fail-fast: false
15
+ matrix:
16
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
17
+ steps:
18
+ - name: Checkout
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Set up Python ${{ matrix.python-version }}
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: ${{ matrix.python-version }}
25
+
26
+ - name: Install package (dev)
27
+ run: pip install -e ".[dev]"
28
+
29
+ - name: Ruff
30
+ run: ruff check src tests
31
+
32
+ - name: Mypy
33
+ if: matrix.python-version == '3.12'
34
+ run: mypy src/lime_sites
35
+
36
+ - name: Pytest (100% coverage)
37
+ run: pytest --cov=lime_sites --cov-fail-under=100
38
+
39
+ publish:
40
+ needs: quality
41
+ if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
42
+ runs-on: ubuntu-latest
43
+ permissions:
44
+ id-token: write
45
+ steps:
46
+ - name: Checkout
47
+ uses: actions/checkout@v4
48
+
49
+ - name: Set up Python
50
+ uses: actions/setup-python@v5
51
+ with:
52
+ python-version: "3.12"
53
+
54
+ - name: Install build tools
55
+ run: pip install build hatchling
56
+
57
+ - name: Build package
58
+ run: python -m build
59
+
60
+ - name: Publish to PyPI
61
+ uses: pypa/gh-action-pypi-publish@release/v1
62
+ with:
63
+ attestations: false
64
+ skip-existing: true
@@ -0,0 +1,38 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+
7
+ # Virtual environments
8
+ .venv/
9
+ venv/
10
+ env/
11
+
12
+ # Integration test token cache (never commit)
13
+ tests/integration/.tokens.env
14
+
15
+ # Test / type / lint caches
16
+ .pytest_cache/
17
+ .coverage
18
+ htmlcov/
19
+ coverage.xml
20
+ .mypy_cache/
21
+ .ruff_cache/
22
+ .hypothesis/
23
+
24
+ # Build artifacts
25
+ dist/
26
+ build/
27
+ *.egg-info/
28
+ *.egg
29
+
30
+ # IDE
31
+ .idea/
32
+ .vscode/
33
+ *.swp
34
+ *.swo
35
+
36
+ # OS
37
+ .DS_Store
38
+ Thumbs.db
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 LIME
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,201 @@
1
+ Metadata-Version: 2.4
2
+ Name: lime-sites-sdk
3
+ Version: 0.1.0
4
+ Summary: Python SDK for LIME 2.0 site integration. Create login requests, wait for agent approval, verify JWT passports. Async-first, SSE reconnect, JWKS caching.
5
+ Project-URL: Homepage, https://github.com/Mawyxx/lime-sait-sdk
6
+ Project-URL: Repository, https://github.com/Mawyxx/lime-sait-sdk
7
+ Project-URL: Documentation, https://lime.pics/docs
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Requires-Python: >=3.10
11
+ Requires-Dist: cryptography>=41.0.0
12
+ Requires-Dist: httpx<1,>=0.27.0
13
+ Requires-Dist: pyjwt>=2.8.0
14
+ Provides-Extra: dev
15
+ Requires-Dist: mypy>=1.11; extra == 'dev'
16
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
17
+ Requires-Dist: pytest-cov>=5.0; extra == 'dev'
18
+ Requires-Dist: pytest>=8.0; extra == 'dev'
19
+ Requires-Dist: ruff>=0.6; extra == 'dev'
20
+ Description-Content-Type: text/markdown
21
+
22
+ # LIME Sites SDK
23
+
24
+ [![PyPI version](https://img.shields.io/pypi/v/lime-sites-sdk)](https://pypi.org/project/lime-sites-sdk/)
25
+ [![Python versions](https://img.shields.io/pypi/pyversions/lime-sites-sdk)](https://pypi.org/project/lime-sites-sdk/)
26
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
27
+ [![CI](https://github.com/Mawyxx/lime-sait-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/Mawyxx/lime-sait-sdk/actions/workflows/ci.yml)
28
+
29
+ Official Python SDK for [LIME](https://lime.pics) site backends. Async-first client: create login requests, wait for agent approval over SSE (with reconnect), verify JWT passports via JWKS.
30
+
31
+ > **Repository:** [lime-sait-sdk](https://github.com/Mawyxx/lime-sait-sdk) · **PyPI:** `lime-sites-sdk` · **Import:** `from lime_sites import LimeSite`
32
+
33
+ Pair with [lime-agents-sdk](https://github.com/Mawyxx/lime-agents-sdk) on the agent worker side.
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ pip install lime-sites-sdk
39
+ ```
40
+
41
+ Install the latest commit from GitHub:
42
+
43
+ ```bash
44
+ pip install git+https://github.com/Mawyxx/lime-sait-sdk.git
45
+ ```
46
+
47
+ **Requirements:** Python 3.10+
48
+
49
+ ## Quick start
50
+
51
+ ```python
52
+ from lime_sites import LimeSite
53
+
54
+ site = LimeSite() # LIME_SITE_TOKEN
55
+
56
+ req = await site.create_login_request()
57
+ # → pass req.request_id to your agent worker (lime-agents-sdk approve)
58
+
59
+ login = await site.wait_for_login(req.request_id)
60
+ verified = await site.verify_passport(
61
+ login.agent_passport_jwt,
62
+ expected_request_id=req.request_id,
63
+ )
64
+ assert verified.valid
65
+ await site.aclose()
66
+ ```
67
+
68
+ ## Production example
69
+
70
+ ```python
71
+ from lime_sites import (
72
+ LimeSite,
73
+ AuthenticationError,
74
+ RequestExpiredError,
75
+ InvalidPassportError,
76
+ TimeoutError,
77
+ ApiError,
78
+ )
79
+
80
+
81
+ async def handle_agent_login() -> dict | None:
82
+ try:
83
+ async with LimeSite() as site:
84
+ req = await site.create_login_request()
85
+ await notify_agent_worker(req.request_id)
86
+
87
+ login = await site.wait_for_login(req.request_id, timeout=120.0)
88
+ verified = await site.verify_passport(
89
+ login.agent_passport_jwt,
90
+ expected_request_id=req.request_id,
91
+ )
92
+ return verified.claims
93
+ except TimeoutError:
94
+ return None
95
+ except RequestExpiredError:
96
+ return None
97
+ except InvalidPassportError:
98
+ return None
99
+ except ApiError as exc:
100
+ print(f"[{exc.code}] {exc.message}")
101
+ return None
102
+ ```
103
+
104
+ ## Authentication
105
+
106
+ Site HTTP calls use the `X-Site-Token` header.
107
+
108
+ **Resolution order:**
109
+
110
+ 1. Constructor argument `site_token="st_..."`
111
+ 2. Environment variable `LIME_SITE_TOKEN`
112
+
113
+ If neither is set, construction raises `AuthenticationError`.
114
+
115
+ Obtain the site token once when registering a site in the LIME owner portal. Store it as a server-side secret.
116
+
117
+ ## Configuration
118
+
119
+ | Variable | Purpose |
120
+ |----------|---------|
121
+ | `LIME_SITE_TOKEN` | Site integration token (required) |
122
+ | `LIME_API_BASE` | API root including `/api/v1` (default `https://lime.pics/api/v1`) |
123
+
124
+ **SSE / proxy:** nginx (or similar) read timeout should be **≥ 310s** for long-lived event streams. The SDK reconnects automatically; default `wait_for_login` budget is 120s.
125
+
126
+ ## API reference
127
+
128
+ ### `LimeSite`
129
+
130
+ Async client for site-backend operations.
131
+
132
+ #### Constructor
133
+
134
+ All arguments are keyword-only.
135
+
136
+ | Parameter | Type | Default | Description |
137
+ |-----------|------|---------|-------------|
138
+ | `site_token` | `str \| None` | `None` | Site secret. Falls back to `LIME_SITE_TOKEN`. |
139
+ | `base_url` | `str \| None` | `None` | API root. Falls back to `LIME_API_BASE`, then production default. |
140
+ | `timeout` | `float` | `30.0` | Per HTTP request timeout (seconds). |
141
+ | `max_retries` | `int` | `3` | Retries on transient 5xx / transport errors. |
142
+ | `sse_backoff_base` | `float` | `0.5` | Initial SSE reconnect backoff (seconds). |
143
+ | `http_client` | `httpx.AsyncClient \| None` | `None` | Inject for tests. |
144
+
145
+ #### Methods
146
+
147
+ | Method | Returns | Description |
148
+ |--------|---------|-------------|
149
+ | `create_login_request()` | `LoginRequestResult` | `POST /modules/agent-login/requests` |
150
+ | `wait_for_login(request_id, *, timeout=120.0)` | `LoginResult` | SSE until approved or expired |
151
+ | `verify_passport(jwt, *, expected_request_id=None)` | `PassportVerificationResult` | JWKS RS256 verify |
152
+ | `aclose()` | `None` | Close owned HTTP client |
153
+
154
+ Supports `async with LimeSite(...) as site:`.
155
+
156
+ ### Types
157
+
158
+ | Type | Fields |
159
+ |------|--------|
160
+ | `LoginRequestResult` | `request_id`, `status`, `expires_at` |
161
+ | `LoginResult` | `request_id`, `agent_passport_jwt`, `redirect_url?` |
162
+ | `PassportVerificationResult` | `valid`, `claims` |
163
+
164
+ ### Errors
165
+
166
+ | Exception | When |
167
+ |-----------|------|
168
+ | `AuthenticationError` | Missing/invalid site token |
169
+ | `RequestExpiredError` | SSE `expired` for waited request |
170
+ | `InvalidPassportError` | JWT verify failure |
171
+ | `TimeoutError` | `wait_for_login` exceeded timeout |
172
+ | `RateLimitError` | HTTP 429 |
173
+ | `ApiError` | Other API errors |
174
+ | `LimeError` | Base class |
175
+
176
+ ## Integration pattern
177
+
178
+ 1. Site backend calls `create_login_request()`.
179
+ 2. Deliver `request_id` to agent worker (queue, RPC, bot message).
180
+ 3. Agent worker runs `lime-agents-sdk` `approve(request_id)`.
181
+ 4. Site backend calls `wait_for_login(request_id)` then `verify_passport(...)`.
182
+ 5. Create local session from verified claims.
183
+
184
+ ## Development
185
+
186
+ ```bash
187
+ pip install -e ".[dev]"
188
+ ruff check src tests
189
+ mypy src/lime_sites
190
+ pytest --cov=lime_sites --cov-fail-under=100
191
+ ```
192
+
193
+ Live integration (requires tokens):
194
+
195
+ ```bash
196
+ LIME_INTEGRATION=1 pytest tests/integration -v
197
+ ```
198
+
199
+ ## License
200
+
201
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,180 @@
1
+ # LIME Sites SDK
2
+
3
+ [![PyPI version](https://img.shields.io/pypi/v/lime-sites-sdk)](https://pypi.org/project/lime-sites-sdk/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/lime-sites-sdk)](https://pypi.org/project/lime-sites-sdk/)
5
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
6
+ [![CI](https://github.com/Mawyxx/lime-sait-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/Mawyxx/lime-sait-sdk/actions/workflows/ci.yml)
7
+
8
+ Official Python SDK for [LIME](https://lime.pics) site backends. Async-first client: create login requests, wait for agent approval over SSE (with reconnect), verify JWT passports via JWKS.
9
+
10
+ > **Repository:** [lime-sait-sdk](https://github.com/Mawyxx/lime-sait-sdk) · **PyPI:** `lime-sites-sdk` · **Import:** `from lime_sites import LimeSite`
11
+
12
+ Pair with [lime-agents-sdk](https://github.com/Mawyxx/lime-agents-sdk) on the agent worker side.
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pip install lime-sites-sdk
18
+ ```
19
+
20
+ Install the latest commit from GitHub:
21
+
22
+ ```bash
23
+ pip install git+https://github.com/Mawyxx/lime-sait-sdk.git
24
+ ```
25
+
26
+ **Requirements:** Python 3.10+
27
+
28
+ ## Quick start
29
+
30
+ ```python
31
+ from lime_sites import LimeSite
32
+
33
+ site = LimeSite() # LIME_SITE_TOKEN
34
+
35
+ req = await site.create_login_request()
36
+ # → pass req.request_id to your agent worker (lime-agents-sdk approve)
37
+
38
+ login = await site.wait_for_login(req.request_id)
39
+ verified = await site.verify_passport(
40
+ login.agent_passport_jwt,
41
+ expected_request_id=req.request_id,
42
+ )
43
+ assert verified.valid
44
+ await site.aclose()
45
+ ```
46
+
47
+ ## Production example
48
+
49
+ ```python
50
+ from lime_sites import (
51
+ LimeSite,
52
+ AuthenticationError,
53
+ RequestExpiredError,
54
+ InvalidPassportError,
55
+ TimeoutError,
56
+ ApiError,
57
+ )
58
+
59
+
60
+ async def handle_agent_login() -> dict | None:
61
+ try:
62
+ async with LimeSite() as site:
63
+ req = await site.create_login_request()
64
+ await notify_agent_worker(req.request_id)
65
+
66
+ login = await site.wait_for_login(req.request_id, timeout=120.0)
67
+ verified = await site.verify_passport(
68
+ login.agent_passport_jwt,
69
+ expected_request_id=req.request_id,
70
+ )
71
+ return verified.claims
72
+ except TimeoutError:
73
+ return None
74
+ except RequestExpiredError:
75
+ return None
76
+ except InvalidPassportError:
77
+ return None
78
+ except ApiError as exc:
79
+ print(f"[{exc.code}] {exc.message}")
80
+ return None
81
+ ```
82
+
83
+ ## Authentication
84
+
85
+ Site HTTP calls use the `X-Site-Token` header.
86
+
87
+ **Resolution order:**
88
+
89
+ 1. Constructor argument `site_token="st_..."`
90
+ 2. Environment variable `LIME_SITE_TOKEN`
91
+
92
+ If neither is set, construction raises `AuthenticationError`.
93
+
94
+ Obtain the site token once when registering a site in the LIME owner portal. Store it as a server-side secret.
95
+
96
+ ## Configuration
97
+
98
+ | Variable | Purpose |
99
+ |----------|---------|
100
+ | `LIME_SITE_TOKEN` | Site integration token (required) |
101
+ | `LIME_API_BASE` | API root including `/api/v1` (default `https://lime.pics/api/v1`) |
102
+
103
+ **SSE / proxy:** nginx (or similar) read timeout should be **≥ 310s** for long-lived event streams. The SDK reconnects automatically; default `wait_for_login` budget is 120s.
104
+
105
+ ## API reference
106
+
107
+ ### `LimeSite`
108
+
109
+ Async client for site-backend operations.
110
+
111
+ #### Constructor
112
+
113
+ All arguments are keyword-only.
114
+
115
+ | Parameter | Type | Default | Description |
116
+ |-----------|------|---------|-------------|
117
+ | `site_token` | `str \| None` | `None` | Site secret. Falls back to `LIME_SITE_TOKEN`. |
118
+ | `base_url` | `str \| None` | `None` | API root. Falls back to `LIME_API_BASE`, then production default. |
119
+ | `timeout` | `float` | `30.0` | Per HTTP request timeout (seconds). |
120
+ | `max_retries` | `int` | `3` | Retries on transient 5xx / transport errors. |
121
+ | `sse_backoff_base` | `float` | `0.5` | Initial SSE reconnect backoff (seconds). |
122
+ | `http_client` | `httpx.AsyncClient \| None` | `None` | Inject for tests. |
123
+
124
+ #### Methods
125
+
126
+ | Method | Returns | Description |
127
+ |--------|---------|-------------|
128
+ | `create_login_request()` | `LoginRequestResult` | `POST /modules/agent-login/requests` |
129
+ | `wait_for_login(request_id, *, timeout=120.0)` | `LoginResult` | SSE until approved or expired |
130
+ | `verify_passport(jwt, *, expected_request_id=None)` | `PassportVerificationResult` | JWKS RS256 verify |
131
+ | `aclose()` | `None` | Close owned HTTP client |
132
+
133
+ Supports `async with LimeSite(...) as site:`.
134
+
135
+ ### Types
136
+
137
+ | Type | Fields |
138
+ |------|--------|
139
+ | `LoginRequestResult` | `request_id`, `status`, `expires_at` |
140
+ | `LoginResult` | `request_id`, `agent_passport_jwt`, `redirect_url?` |
141
+ | `PassportVerificationResult` | `valid`, `claims` |
142
+
143
+ ### Errors
144
+
145
+ | Exception | When |
146
+ |-----------|------|
147
+ | `AuthenticationError` | Missing/invalid site token |
148
+ | `RequestExpiredError` | SSE `expired` for waited request |
149
+ | `InvalidPassportError` | JWT verify failure |
150
+ | `TimeoutError` | `wait_for_login` exceeded timeout |
151
+ | `RateLimitError` | HTTP 429 |
152
+ | `ApiError` | Other API errors |
153
+ | `LimeError` | Base class |
154
+
155
+ ## Integration pattern
156
+
157
+ 1. Site backend calls `create_login_request()`.
158
+ 2. Deliver `request_id` to agent worker (queue, RPC, bot message).
159
+ 3. Agent worker runs `lime-agents-sdk` `approve(request_id)`.
160
+ 4. Site backend calls `wait_for_login(request_id)` then `verify_passport(...)`.
161
+ 5. Create local session from verified claims.
162
+
163
+ ## Development
164
+
165
+ ```bash
166
+ pip install -e ".[dev]"
167
+ ruff check src tests
168
+ mypy src/lime_sites
169
+ pytest --cov=lime_sites --cov-fail-under=100
170
+ ```
171
+
172
+ Live integration (requires tokens):
173
+
174
+ ```bash
175
+ LIME_INTEGRATION=1 pytest tests/integration -v
176
+ ```
177
+
178
+ ## License
179
+
180
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,60 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "lime-sites-sdk"
7
+ version = "0.1.0"
8
+ description = "Python SDK for LIME 2.0 site integration. Create login requests, wait for agent approval, verify JWT passports. Async-first, SSE reconnect, JWKS caching."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ dependencies = [
13
+ "httpx>=0.27.0,<1",
14
+ "PyJWT>=2.8.0",
15
+ "cryptography>=41.0.0",
16
+ ]
17
+
18
+ [project.optional-dependencies]
19
+ dev = [
20
+ "pytest>=8.0",
21
+ "pytest-asyncio>=0.24",
22
+ "pytest-cov>=5.0",
23
+ "ruff>=0.6",
24
+ "mypy>=1.11",
25
+ ]
26
+
27
+ [project.urls]
28
+ Homepage = "https://github.com/Mawyxx/lime-sait-sdk"
29
+ Repository = "https://github.com/Mawyxx/lime-sait-sdk"
30
+ Documentation = "https://lime.pics/docs"
31
+
32
+ [tool.hatch.build.targets.wheel]
33
+ packages = ["src/lime_sites"]
34
+
35
+ [tool.pytest.ini_options]
36
+ asyncio_mode = "auto"
37
+ testpaths = ["tests"]
38
+ markers = [
39
+ "integration: live HTTP tests against LIME API (requires LIME_INTEGRATION=1)",
40
+ ]
41
+
42
+ [tool.coverage.run]
43
+ source = ["lime_sites"]
44
+
45
+ [tool.coverage.report]
46
+ fail_under = 100
47
+
48
+ [tool.ruff]
49
+ target-version = "py310"
50
+ line-length = 100
51
+ src = ["src", "tests"]
52
+
53
+ [tool.ruff.lint]
54
+ select = ["E", "F", "I", "UP", "B"]
55
+
56
+ [tool.mypy]
57
+ python_version = "3.12"
58
+ strict = true
59
+ packages = ["lime_sites"]
60
+ mypy_path = "src"
@@ -0,0 +1,30 @@
1
+ """Official Python SDK for LIME site backends."""
2
+
3
+ from lime_sites._errors import (
4
+ ApiError,
5
+ AuthenticationError,
6
+ InvalidPassportError,
7
+ LimeError,
8
+ RateLimitError,
9
+ RequestExpiredError,
10
+ TimeoutError,
11
+ )
12
+ from lime_sites._site import LimeSite
13
+ from lime_sites._types import LoginRequestResult, LoginResult, PassportVerificationResult
14
+
15
+ __version__ = "0.1.0"
16
+
17
+ __all__ = [
18
+ "ApiError",
19
+ "AuthenticationError",
20
+ "InvalidPassportError",
21
+ "LimeError",
22
+ "LimeSite",
23
+ "LoginRequestResult",
24
+ "LoginResult",
25
+ "PassportVerificationResult",
26
+ "RateLimitError",
27
+ "RequestExpiredError",
28
+ "TimeoutError",
29
+ "__version__",
30
+ ]