nees-core-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.
- nees_core_sdk-0.1.0/LICENSE +28 -0
- nees_core_sdk-0.1.0/MANIFEST.in +4 -0
- nees_core_sdk-0.1.0/PKG-INFO +86 -0
- nees_core_sdk-0.1.0/README.md +65 -0
- nees_core_sdk-0.1.0/pyproject.toml +46 -0
- nees_core_sdk-0.1.0/setup.cfg +4 -0
- nees_core_sdk-0.1.0/src/nees/__init__.py +38 -0
- nees_core_sdk-0.1.0/src/nees/_http.py +75 -0
- nees_core_sdk-0.1.0/src/nees/client.py +107 -0
- nees_core_sdk-0.1.0/src/nees/errors.py +60 -0
- nees_core_sdk-0.1.0/src/nees/models.py +24 -0
- nees_core_sdk-0.1.0/src/nees_core_sdk.egg-info/PKG-INFO +86 -0
- nees_core_sdk-0.1.0/src/nees_core_sdk.egg-info/SOURCES.txt +14 -0
- nees_core_sdk-0.1.0/src/nees_core_sdk.egg-info/dependency_links.txt +1 -0
- nees_core_sdk-0.1.0/src/nees_core_sdk.egg-info/requires.txt +1 -0
- nees_core_sdk-0.1.0/src/nees_core_sdk.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Nainacore SDK Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Nainacore Emotional Tech. All rights reserved.
|
|
4
|
+
|
|
5
|
+
Permission is granted to download, install, and use the NEES Python SDK solely
|
|
6
|
+
for the purpose of accessing NEES services for which the user has valid
|
|
7
|
+
authorization.
|
|
8
|
+
|
|
9
|
+
This license applies only to the NEES Python SDK distribution. It does not grant
|
|
10
|
+
any license, ownership right, or other right in the NEES Core Engine, NEES
|
|
11
|
+
service-side software, governance implementation, policies, models, data,
|
|
12
|
+
infrastructure, trademarks, patents, or other proprietary technology of
|
|
13
|
+
Nainacore Emotional Tech.
|
|
14
|
+
|
|
15
|
+
Except where applicable law expressly permits otherwise, you may not:
|
|
16
|
+
- use the SDK to bypass authentication, authorization, usage limits, or service
|
|
17
|
+
protections;
|
|
18
|
+
- use the SDK or service interfaces to obtain, reconstruct, or disclose
|
|
19
|
+
non-public service-side implementation details; or
|
|
20
|
+
- represent this SDK or any modified version as an official Nainacore product.
|
|
21
|
+
|
|
22
|
+
THE SDK IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
23
|
+
INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
24
|
+
PARTICULAR PURPOSE, AND NON-INFRINGEMENT. TO THE MAXIMUM EXTENT PERMITTED BY
|
|
25
|
+
LAW, NAINACORE EMOTIONAL TECH SHALL NOT BE LIABLE FOR ANY CLAIM, DAMAGES, OR
|
|
26
|
+
OTHER LIABILITY ARISING FROM USE OF THE SDK.
|
|
27
|
+
|
|
28
|
+
Use of NEES hosted services may also be subject to separate service terms.
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nees-core-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python client for the NEES API.
|
|
5
|
+
Author: Nainacore Emotional Tech
|
|
6
|
+
License-Expression: LicenseRef-Nainacore-SDK-Proprietary
|
|
7
|
+
Project-URL: Homepage, https://nees.cloud
|
|
8
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: requests<3,>=2.31
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# NEES Python SDK
|
|
23
|
+
|
|
24
|
+
The NEES Python SDK is the official Python client for connecting applications to NEES governed AI runtime services.
|
|
25
|
+
SDK v0.1 currently exposes only the authenticated chat capability.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install nees-core-sdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The PyPI distribution is `nees-core-sdk`; the Python import package is `nees`.
|
|
34
|
+
|
|
35
|
+
Python 3.9 or newer is required.
|
|
36
|
+
|
|
37
|
+
## Quickstart
|
|
38
|
+
|
|
39
|
+
Trial API keys are currently issued manually by Nainacore.
|
|
40
|
+
|
|
41
|
+
Windows PowerShell:
|
|
42
|
+
|
|
43
|
+
```powershell
|
|
44
|
+
$env:NEES_API_KEY="..."
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Linux/macOS:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
export NEES_API_KEY="..."
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from nees import NEESClient
|
|
55
|
+
|
|
56
|
+
client = NEESClient()
|
|
57
|
+
result = client.chat("Reply with exactly: NEES SDK connected")
|
|
58
|
+
print(result.reply)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
To configure a different endpoint or timeout:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
client = NEESClient(api_key="...", base_url="https://api.nees.cloud", timeout=30)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The SDK requires HTTPS for remote endpoints. Plain HTTP is accepted only for localhost development.
|
|
68
|
+
|
|
69
|
+
The SDK currently supports only `chat:invoke`.
|
|
70
|
+
|
|
71
|
+
## Response boundary
|
|
72
|
+
|
|
73
|
+
The SDK exposes a deliberately limited public response model: reply/session identifiers,
|
|
74
|
+
request and trace identifiers, and selected public governance fields. Unrecognized API
|
|
75
|
+
response fields are not surfaced by the SDK.
|
|
76
|
+
|
|
77
|
+
## Errors
|
|
78
|
+
|
|
79
|
+
Catch `NEESAPIError` for all API failures, or a specific exported subclass such as
|
|
80
|
+
`NEESAuthenticationError`, `NEESAuthorizationError`, and `NEESRateLimitError`.
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
The SDK is distributed under the Nainacore SDK Proprietary License included with this package.
|
|
85
|
+
This license applies to the SDK only and does not grant rights in the NEES Core Engine or
|
|
86
|
+
other service-side technology.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# NEES Python SDK
|
|
2
|
+
|
|
3
|
+
The NEES Python SDK is the official Python client for connecting applications to NEES governed AI runtime services.
|
|
4
|
+
SDK v0.1 currently exposes only the authenticated chat capability.
|
|
5
|
+
|
|
6
|
+
## Install
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
pip install nees-core-sdk
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
The PyPI distribution is `nees-core-sdk`; the Python import package is `nees`.
|
|
13
|
+
|
|
14
|
+
Python 3.9 or newer is required.
|
|
15
|
+
|
|
16
|
+
## Quickstart
|
|
17
|
+
|
|
18
|
+
Trial API keys are currently issued manually by Nainacore.
|
|
19
|
+
|
|
20
|
+
Windows PowerShell:
|
|
21
|
+
|
|
22
|
+
```powershell
|
|
23
|
+
$env:NEES_API_KEY="..."
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Linux/macOS:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
export NEES_API_KEY="..."
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```python
|
|
33
|
+
from nees import NEESClient
|
|
34
|
+
|
|
35
|
+
client = NEESClient()
|
|
36
|
+
result = client.chat("Reply with exactly: NEES SDK connected")
|
|
37
|
+
print(result.reply)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
To configure a different endpoint or timeout:
|
|
41
|
+
|
|
42
|
+
```python
|
|
43
|
+
client = NEESClient(api_key="...", base_url="https://api.nees.cloud", timeout=30)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The SDK requires HTTPS for remote endpoints. Plain HTTP is accepted only for localhost development.
|
|
47
|
+
|
|
48
|
+
The SDK currently supports only `chat:invoke`.
|
|
49
|
+
|
|
50
|
+
## Response boundary
|
|
51
|
+
|
|
52
|
+
The SDK exposes a deliberately limited public response model: reply/session identifiers,
|
|
53
|
+
request and trace identifiers, and selected public governance fields. Unrecognized API
|
|
54
|
+
response fields are not surfaced by the SDK.
|
|
55
|
+
|
|
56
|
+
## Errors
|
|
57
|
+
|
|
58
|
+
Catch `NEESAPIError` for all API failures, or a specific exported subclass such as
|
|
59
|
+
`NEESAuthenticationError`, `NEESAuthorizationError`, and `NEESRateLimitError`.
|
|
60
|
+
|
|
61
|
+
## License
|
|
62
|
+
|
|
63
|
+
The SDK is distributed under the Nainacore SDK Proprietary License included with this package.
|
|
64
|
+
This license applies to the SDK only and does not grant rights in the NEES Core Engine or
|
|
65
|
+
other service-side technology.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0.3"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "nees-core-sdk"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python client for the NEES API."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
authors = [{ name = "Nainacore Emotional Tech" }]
|
|
12
|
+
dependencies = ["requests>=2.31,<3"]
|
|
13
|
+
license = "LicenseRef-Nainacore-SDK-Proprietary"
|
|
14
|
+
license-files = ["LICENSE"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 2 - Pre-Alpha",
|
|
17
|
+
"Intended Audience :: Developers",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
20
|
+
"Programming Language :: Python :: 3.9",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.urls]
|
|
27
|
+
Homepage = "https://nees.cloud"
|
|
28
|
+
|
|
29
|
+
[tool.setuptools.packages.find]
|
|
30
|
+
where = ["src"]
|
|
31
|
+
|
|
32
|
+
[tool.pytest.ini_options]
|
|
33
|
+
testpaths = ["tests"]
|
|
34
|
+
|
|
35
|
+
[tool.ruff]
|
|
36
|
+
target-version = "py39"
|
|
37
|
+
line-length = 100
|
|
38
|
+
|
|
39
|
+
[tool.ruff.lint]
|
|
40
|
+
select = ["E", "F", "I"]
|
|
41
|
+
|
|
42
|
+
[tool.mypy]
|
|
43
|
+
python_version = "3.9"
|
|
44
|
+
strict = true
|
|
45
|
+
files = ["src"]
|
|
46
|
+
disable_error_code = ["import-untyped"]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"""Public Python client for the NEES API."""
|
|
2
|
+
|
|
3
|
+
from .client import NEESClient
|
|
4
|
+
from .errors import (
|
|
5
|
+
NEESAPIError,
|
|
6
|
+
NEESAuthenticationError,
|
|
7
|
+
NEESAuthorizationError,
|
|
8
|
+
NEESBadRequestError,
|
|
9
|
+
NEESConfigurationError,
|
|
10
|
+
NEESConflictError,
|
|
11
|
+
NEESConnectionError,
|
|
12
|
+
NEESNotFoundError,
|
|
13
|
+
NEESRateLimitError,
|
|
14
|
+
NEESServerError,
|
|
15
|
+
NEESTimeoutError,
|
|
16
|
+
NEESValidationError,
|
|
17
|
+
)
|
|
18
|
+
from .models import NEESChatResponse, NEESGovernanceResult
|
|
19
|
+
|
|
20
|
+
__version__ = "0.1.0"
|
|
21
|
+
|
|
22
|
+
__all__ = [
|
|
23
|
+
"NEESClient",
|
|
24
|
+
"NEESChatResponse",
|
|
25
|
+
"NEESGovernanceResult",
|
|
26
|
+
"NEESAPIError",
|
|
27
|
+
"NEESAuthenticationError",
|
|
28
|
+
"NEESAuthorizationError",
|
|
29
|
+
"NEESBadRequestError",
|
|
30
|
+
"NEESConfigurationError",
|
|
31
|
+
"NEESConflictError",
|
|
32
|
+
"NEESConnectionError",
|
|
33
|
+
"NEESNotFoundError",
|
|
34
|
+
"NEESRateLimitError",
|
|
35
|
+
"NEESServerError",
|
|
36
|
+
"NEESTimeoutError",
|
|
37
|
+
"NEESValidationError",
|
|
38
|
+
]
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""Private HTTP transport for the NEES SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, Dict, Type
|
|
6
|
+
|
|
7
|
+
import requests
|
|
8
|
+
|
|
9
|
+
from .errors import (
|
|
10
|
+
NEESAPIError,
|
|
11
|
+
NEESAuthenticationError,
|
|
12
|
+
NEESAuthorizationError,
|
|
13
|
+
NEESBadRequestError,
|
|
14
|
+
NEESConflictError,
|
|
15
|
+
NEESConnectionError,
|
|
16
|
+
NEESNotFoundError,
|
|
17
|
+
NEESRateLimitError,
|
|
18
|
+
NEESServerError,
|
|
19
|
+
NEESTimeoutError,
|
|
20
|
+
NEESValidationError,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
_STATUS_ERRORS: Dict[int, Type[NEESAPIError]] = {
|
|
24
|
+
400: NEESBadRequestError,
|
|
25
|
+
401: NEESAuthenticationError,
|
|
26
|
+
403: NEESAuthorizationError,
|
|
27
|
+
404: NEESNotFoundError,
|
|
28
|
+
409: NEESConflictError,
|
|
29
|
+
422: NEESValidationError,
|
|
30
|
+
429: NEESRateLimitError,
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def request_json(
|
|
35
|
+
session: requests.Session,
|
|
36
|
+
url: str,
|
|
37
|
+
headers: Dict[str, str],
|
|
38
|
+
payload: Dict[str, Any],
|
|
39
|
+
timeout: float,
|
|
40
|
+
) -> Dict[str, Any]:
|
|
41
|
+
try:
|
|
42
|
+
response = session.post(url, headers=headers, json=payload, timeout=timeout)
|
|
43
|
+
except requests.Timeout as exc:
|
|
44
|
+
raise NEESTimeoutError("Request to NEES timed out.") from exc
|
|
45
|
+
except requests.RequestException as exc:
|
|
46
|
+
raise NEESConnectionError("Could not connect to the NEES API.") from exc
|
|
47
|
+
request_id = response.headers.get("X-Request-ID") or response.headers.get("X-Request-Id")
|
|
48
|
+
try:
|
|
49
|
+
body = response.json()
|
|
50
|
+
except ValueError:
|
|
51
|
+
body = None
|
|
52
|
+
if response.status_code >= 400:
|
|
53
|
+
error_type = _STATUS_ERRORS.get(
|
|
54
|
+
response.status_code, NEESServerError if response.status_code >= 500 else NEESAPIError
|
|
55
|
+
)
|
|
56
|
+
raise error_type(
|
|
57
|
+
_error_message(body, response.reason),
|
|
58
|
+
status_code=response.status_code,
|
|
59
|
+
request_id=request_id,
|
|
60
|
+
)
|
|
61
|
+
if not isinstance(body, dict):
|
|
62
|
+
raise NEESAPIError(
|
|
63
|
+
"NEES API returned malformed JSON.",
|
|
64
|
+
status_code=response.status_code,
|
|
65
|
+
request_id=request_id,
|
|
66
|
+
)
|
|
67
|
+
return body
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _error_message(body: Any, fallback: str) -> str:
|
|
71
|
+
if isinstance(body, dict):
|
|
72
|
+
detail = body.get("detail") or body.get("message") or body.get("error")
|
|
73
|
+
if isinstance(detail, str) and detail.strip():
|
|
74
|
+
return detail.strip()
|
|
75
|
+
return fallback or "NEES API request failed."
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Synchronous NEES API client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from typing import Any, Dict, Optional
|
|
7
|
+
from urllib.parse import urlparse
|
|
8
|
+
|
|
9
|
+
import requests
|
|
10
|
+
|
|
11
|
+
from ._http import request_json
|
|
12
|
+
from .errors import NEESConfigurationError
|
|
13
|
+
from .models import NEESChatResponse, NEESGovernanceResult
|
|
14
|
+
|
|
15
|
+
DEFAULT_BASE_URL = "https://api.nees.cloud"
|
|
16
|
+
DEFAULT_TIMEOUT = 30.0
|
|
17
|
+
_LOCAL_HTTP_HOSTS = {"localhost", "127.0.0.1", "::1"}
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class NEESClient:
|
|
21
|
+
"""Synchronous client for the public NEES chat API."""
|
|
22
|
+
|
|
23
|
+
def __init__(
|
|
24
|
+
self,
|
|
25
|
+
api_key: Optional[str] = None,
|
|
26
|
+
*,
|
|
27
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
28
|
+
timeout: float = DEFAULT_TIMEOUT,
|
|
29
|
+
) -> None:
|
|
30
|
+
key = (api_key if api_key is not None else os.getenv("NEES_API_KEY", "")).strip()
|
|
31
|
+
if not key:
|
|
32
|
+
raise NEESConfigurationError(
|
|
33
|
+
"An API key is required. Set NEES_API_KEY or pass api_key."
|
|
34
|
+
)
|
|
35
|
+
normalized_url = base_url.strip().rstrip("/")
|
|
36
|
+
self._validate_base_url(normalized_url)
|
|
37
|
+
if timeout <= 0:
|
|
38
|
+
raise NEESConfigurationError("timeout must be greater than zero.")
|
|
39
|
+
self._api_key = key
|
|
40
|
+
self.base_url = normalized_url
|
|
41
|
+
self.timeout = float(timeout)
|
|
42
|
+
self._session = requests.Session()
|
|
43
|
+
|
|
44
|
+
def __repr__(self) -> str:
|
|
45
|
+
return f"NEESClient(base_url={self.base_url!r}, timeout={self.timeout!r})"
|
|
46
|
+
|
|
47
|
+
def chat(
|
|
48
|
+
self, prompt: str, *, session_id: Optional[str] = None, user_id: Optional[str] = None
|
|
49
|
+
) -> NEESChatResponse:
|
|
50
|
+
"""Send a prompt to the NEES `/chat` endpoint."""
|
|
51
|
+
payload: Dict[str, Any] = {"prompt": prompt}
|
|
52
|
+
if session_id is not None:
|
|
53
|
+
payload["session_id"] = session_id
|
|
54
|
+
if user_id is not None:
|
|
55
|
+
payload["user_id"] = user_id
|
|
56
|
+
body = request_json(
|
|
57
|
+
self._session, f"{self.base_url}/chat", self._headers(), payload, self.timeout
|
|
58
|
+
)
|
|
59
|
+
return self._parse_chat_response(body)
|
|
60
|
+
|
|
61
|
+
def _headers(self) -> Dict[str, str]:
|
|
62
|
+
return {
|
|
63
|
+
"Authorization": f"Bearer {self._api_key}",
|
|
64
|
+
"User-Agent": "nees-python/0.1.0",
|
|
65
|
+
"Accept": "application/json",
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
@staticmethod
|
|
69
|
+
def _validate_base_url(base_url: str) -> None:
|
|
70
|
+
parsed = urlparse(base_url)
|
|
71
|
+
if parsed.scheme == "https" and parsed.netloc:
|
|
72
|
+
return
|
|
73
|
+
if parsed.scheme == "http" and parsed.hostname in _LOCAL_HTTP_HOSTS:
|
|
74
|
+
return
|
|
75
|
+
raise NEESConfigurationError(
|
|
76
|
+
"base_url must use HTTPS; HTTP is allowed only for localhost development."
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
@staticmethod
|
|
80
|
+
def _parse_chat_response(body: Dict[str, Any]) -> NEESChatResponse:
|
|
81
|
+
required = ("reply", "session_id", "request_id", "governance")
|
|
82
|
+
if any(field not in body for field in required) or not isinstance(body["governance"], dict):
|
|
83
|
+
raise NEESConfigurationError("NEES API returned an invalid chat response.")
|
|
84
|
+
|
|
85
|
+
governance = body["governance"]
|
|
86
|
+
status_value = (
|
|
87
|
+
governance.get("status")
|
|
88
|
+
if "status" in governance
|
|
89
|
+
else governance.get("policy_status")
|
|
90
|
+
)
|
|
91
|
+
return NEESChatResponse(
|
|
92
|
+
reply=str(body["reply"]),
|
|
93
|
+
session_id=str(body["session_id"]),
|
|
94
|
+
request_id=str(body["request_id"]),
|
|
95
|
+
trace_id=str(body["trace_id"]) if body.get("trace_id") is not None else None,
|
|
96
|
+
governance=NEESGovernanceResult(
|
|
97
|
+
decision=_optional_text(governance.get("decision")),
|
|
98
|
+
status=_optional_text(status_value),
|
|
99
|
+
reason=_optional_text(governance.get("reason")),
|
|
100
|
+
),
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def _optional_text(value: Any) -> Optional[str]:
|
|
105
|
+
if value is None:
|
|
106
|
+
return None
|
|
107
|
+
return str(value)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Exceptions raised by the NEES SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class NEESAPIError(Exception):
|
|
9
|
+
"""Base exception for safe API failures."""
|
|
10
|
+
|
|
11
|
+
def __init__(
|
|
12
|
+
self, message: str, *, status_code: Optional[int] = None, request_id: Optional[str] = None
|
|
13
|
+
) -> None:
|
|
14
|
+
super().__init__(message)
|
|
15
|
+
self.status_code = status_code
|
|
16
|
+
self.request_id = request_id
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class NEESConfigurationError(NEESAPIError):
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class NEESBadRequestError(NEESAPIError):
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class NEESAuthenticationError(NEESAPIError):
|
|
28
|
+
pass
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class NEESAuthorizationError(NEESAPIError):
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class NEESNotFoundError(NEESAPIError):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class NEESConflictError(NEESAPIError):
|
|
40
|
+
pass
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class NEESValidationError(NEESAPIError):
|
|
44
|
+
pass
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class NEESRateLimitError(NEESAPIError):
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class NEESServerError(NEESAPIError):
|
|
52
|
+
pass
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class NEESTimeoutError(NEESAPIError):
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class NEESConnectionError(NEESAPIError):
|
|
60
|
+
pass
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Response models for the public NEES API."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class NEESGovernanceResult:
|
|
11
|
+
"""Public governance result safe for SDK consumers."""
|
|
12
|
+
|
|
13
|
+
decision: Optional[str] = None
|
|
14
|
+
status: Optional[str] = None
|
|
15
|
+
reason: Optional[str] = None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@dataclass(frozen=True)
|
|
19
|
+
class NEESChatResponse:
|
|
20
|
+
reply: str
|
|
21
|
+
session_id: str
|
|
22
|
+
request_id: str
|
|
23
|
+
trace_id: Optional[str]
|
|
24
|
+
governance: NEESGovernanceResult
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nees-core-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python client for the NEES API.
|
|
5
|
+
Author: Nainacore Emotional Tech
|
|
6
|
+
License-Expression: LicenseRef-Nainacore-SDK-Proprietary
|
|
7
|
+
Project-URL: Homepage, https://nees.cloud
|
|
8
|
+
Classifier: Development Status :: 2 - Pre-Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Requires-Python: >=3.9
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Requires-Dist: requests<3,>=2.31
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
# NEES Python SDK
|
|
23
|
+
|
|
24
|
+
The NEES Python SDK is the official Python client for connecting applications to NEES governed AI runtime services.
|
|
25
|
+
SDK v0.1 currently exposes only the authenticated chat capability.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install nees-core-sdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The PyPI distribution is `nees-core-sdk`; the Python import package is `nees`.
|
|
34
|
+
|
|
35
|
+
Python 3.9 or newer is required.
|
|
36
|
+
|
|
37
|
+
## Quickstart
|
|
38
|
+
|
|
39
|
+
Trial API keys are currently issued manually by Nainacore.
|
|
40
|
+
|
|
41
|
+
Windows PowerShell:
|
|
42
|
+
|
|
43
|
+
```powershell
|
|
44
|
+
$env:NEES_API_KEY="..."
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Linux/macOS:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
export NEES_API_KEY="..."
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from nees import NEESClient
|
|
55
|
+
|
|
56
|
+
client = NEESClient()
|
|
57
|
+
result = client.chat("Reply with exactly: NEES SDK connected")
|
|
58
|
+
print(result.reply)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
To configure a different endpoint or timeout:
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
client = NEESClient(api_key="...", base_url="https://api.nees.cloud", timeout=30)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The SDK requires HTTPS for remote endpoints. Plain HTTP is accepted only for localhost development.
|
|
68
|
+
|
|
69
|
+
The SDK currently supports only `chat:invoke`.
|
|
70
|
+
|
|
71
|
+
## Response boundary
|
|
72
|
+
|
|
73
|
+
The SDK exposes a deliberately limited public response model: reply/session identifiers,
|
|
74
|
+
request and trace identifiers, and selected public governance fields. Unrecognized API
|
|
75
|
+
response fields are not surfaced by the SDK.
|
|
76
|
+
|
|
77
|
+
## Errors
|
|
78
|
+
|
|
79
|
+
Catch `NEESAPIError` for all API failures, or a specific exported subclass such as
|
|
80
|
+
`NEESAuthenticationError`, `NEESAuthorizationError`, and `NEESRateLimitError`.
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
The SDK is distributed under the Nainacore SDK Proprietary License included with this package.
|
|
85
|
+
This license applies to the SDK only and does not grant rights in the NEES Core Engine or
|
|
86
|
+
other service-side technology.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
MANIFEST.in
|
|
3
|
+
README.md
|
|
4
|
+
pyproject.toml
|
|
5
|
+
src/nees/__init__.py
|
|
6
|
+
src/nees/_http.py
|
|
7
|
+
src/nees/client.py
|
|
8
|
+
src/nees/errors.py
|
|
9
|
+
src/nees/models.py
|
|
10
|
+
src/nees_core_sdk.egg-info/PKG-INFO
|
|
11
|
+
src/nees_core_sdk.egg-info/SOURCES.txt
|
|
12
|
+
src/nees_core_sdk.egg-info/dependency_links.txt
|
|
13
|
+
src/nees_core_sdk.egg-info/requires.txt
|
|
14
|
+
src/nees_core_sdk.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests<3,>=2.31
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
nees
|