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.
@@ -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,4 @@
1
+ exclude tests/*
2
+ recursive-exclude tests *
3
+ global-exclude __pycache__
4
+ global-exclude *.py[cod]
@@ -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,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -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
+ requests<3,>=2.31