nees-gp-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_gp_sdk-0.1.0/MANIFEST.in +3 -0
- nees_gp_sdk-0.1.0/PKG-INFO +178 -0
- nees_gp_sdk-0.1.0/README.md +137 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk/__init__.py +57 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk/client.py +277 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk/config.py +76 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk/exceptions.py +99 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk/models.py +220 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk/session.py +123 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk/transport.py +162 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk/utils.py +60 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk.egg-info/PKG-INFO +178 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk.egg-info/SOURCES.txt +19 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk.egg-info/dependency_links.txt +1 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk.egg-info/requires.txt +6 -0
- nees_gp_sdk-0.1.0/nees_gp_sdk.egg-info/top_level.txt +1 -0
- nees_gp_sdk-0.1.0/pyproject.toml +6 -0
- nees_gp_sdk-0.1.0/setup.cfg +4 -0
- nees_gp_sdk-0.1.0/setup.py +50 -0
- nees_gp_sdk-0.1.0/tests/test_live.py +17 -0
- nees_gp_sdk-0.1.0/tests/test_sdk.py +485 -0
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: nees-gp-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for NEES GP — AI Governance Operating System
|
|
5
|
+
Home-page: https://github.com/NEES-Anna
|
|
6
|
+
Author: Nainacore Emotional Tech
|
|
7
|
+
Author-email: anna@nainacore.com
|
|
8
|
+
Project-URL: Documentation, https://nees-gp.onrender.com/docs
|
|
9
|
+
Project-URL: Source, https://github.com/NEES-Anna/NEES_GP_SDK
|
|
10
|
+
Project-URL: Tracker, https://github.com/NEES-Anna/NEES_GP_SDK/issues
|
|
11
|
+
Keywords: ai governance llm safety nees naina
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
22
|
+
Requires-Python: >=3.9
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
Requires-Dist: requests>=2.28.0
|
|
25
|
+
Provides-Extra: dev
|
|
26
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
27
|
+
Requires-Dist: pytest-mock>=3.10; extra == "dev"
|
|
28
|
+
Requires-Dist: responses>=0.23; extra == "dev"
|
|
29
|
+
Dynamic: author
|
|
30
|
+
Dynamic: author-email
|
|
31
|
+
Dynamic: classifier
|
|
32
|
+
Dynamic: description
|
|
33
|
+
Dynamic: description-content-type
|
|
34
|
+
Dynamic: home-page
|
|
35
|
+
Dynamic: keywords
|
|
36
|
+
Dynamic: project-url
|
|
37
|
+
Dynamic: provides-extra
|
|
38
|
+
Dynamic: requires-dist
|
|
39
|
+
Dynamic: requires-python
|
|
40
|
+
Dynamic: summary
|
|
41
|
+
|
|
42
|
+
# NEES GP SDK
|
|
43
|
+
|
|
44
|
+
> AI Governance Operating System (AGOS) — control AI behavior across sessions, not just outputs.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## 🚀 What is NEES GP?
|
|
49
|
+
|
|
50
|
+
NEES GP is an **AI Governance Operating System** that manages AI behavior across time.
|
|
51
|
+
|
|
52
|
+
Unlike traditional AI safety tools that filter single outputs, NEES GP introduces:
|
|
53
|
+
|
|
54
|
+
* 🧠 **Intent-aware reasoning**
|
|
55
|
+
* 🔁 **Session-level governance**
|
|
56
|
+
* 🛡️ **Policy enforcement before generation**
|
|
57
|
+
* 📊 **Structured response metadata**
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
## 📦 Installation
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pip install nees-gp-sdk
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## ⚡ Quickstart (3 lines)
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from nees_gp_sdk import Client
|
|
73
|
+
|
|
74
|
+
client = Client(api_key="your-api-key")
|
|
75
|
+
|
|
76
|
+
res = client.chat("Mujhe kuch samajh nahi aa raha life mein")
|
|
77
|
+
|
|
78
|
+
print(res.text)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 🧠 Response Structure
|
|
84
|
+
|
|
85
|
+
Every response includes both **AI output + governance metadata**:
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
print(res.text) # AI response
|
|
89
|
+
print(res.intent) # e.g. "confusion"
|
|
90
|
+
print(res.framework) # e.g. "confusion_direction"
|
|
91
|
+
print(res.urgency) # "low" | "medium" | "high"
|
|
92
|
+
print(res.governance_clean) # True / False
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## 🎯 Why NEES GP?
|
|
98
|
+
|
|
99
|
+
Traditional AI:
|
|
100
|
+
|
|
101
|
+
* Input → Output filter
|
|
102
|
+
|
|
103
|
+
NEES GP:
|
|
104
|
+
|
|
105
|
+
* Input → Policy → Governance → Response → Session continuity
|
|
106
|
+
|
|
107
|
+
👉 This enables **stateful AI control across conversations**
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 🔧 Configuration
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
client = Client(
|
|
115
|
+
api_key="your-api-key",
|
|
116
|
+
base_url="https://nees-gp.onrender.com",
|
|
117
|
+
timeout=30
|
|
118
|
+
)
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## ⚠️ Error Handling
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from nees_gp_sdk.exceptions import NEESError
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
res = client.chat("Hello")
|
|
130
|
+
except NEESError as e:
|
|
131
|
+
print("Error:", str(e))
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 🛡️ Security & Privacy
|
|
137
|
+
|
|
138
|
+
* API keys are never stored in the SDK
|
|
139
|
+
* No local data persistence beyond session context
|
|
140
|
+
* Governance decisions happen server-side
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 🧪 Example Use Cases
|
|
145
|
+
|
|
146
|
+
* AI copilots with behavioral control
|
|
147
|
+
* Emotion-aware assistants
|
|
148
|
+
* Enterprise AI governance layer
|
|
149
|
+
* Multi-agent coordination systems
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## 🌐 Vision
|
|
154
|
+
|
|
155
|
+
NEES GP defines a new category:
|
|
156
|
+
|
|
157
|
+
> **AI Governance Operating System (AGOS)**
|
|
158
|
+
|
|
159
|
+
A system that governs AI behavior across time, not just at the point of output.
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## 🤝 Contributing
|
|
164
|
+
|
|
165
|
+
Contributions, feedback, and ideas are welcome.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 📄 License
|
|
170
|
+
|
|
171
|
+
MIT License
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 👤 Author
|
|
176
|
+
|
|
177
|
+
Built by Nainacore Emotional Tech
|
|
178
|
+
Founder: Piyush P. Jambhulkar - ANNA
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# NEES GP SDK
|
|
2
|
+
|
|
3
|
+
> AI Governance Operating System (AGOS) — control AI behavior across sessions, not just outputs.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 🚀 What is NEES GP?
|
|
8
|
+
|
|
9
|
+
NEES GP is an **AI Governance Operating System** that manages AI behavior across time.
|
|
10
|
+
|
|
11
|
+
Unlike traditional AI safety tools that filter single outputs, NEES GP introduces:
|
|
12
|
+
|
|
13
|
+
* 🧠 **Intent-aware reasoning**
|
|
14
|
+
* 🔁 **Session-level governance**
|
|
15
|
+
* 🛡️ **Policy enforcement before generation**
|
|
16
|
+
* 📊 **Structured response metadata**
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## 📦 Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install nees-gp-sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## ⚡ Quickstart (3 lines)
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from nees_gp_sdk import Client
|
|
32
|
+
|
|
33
|
+
client = Client(api_key="your-api-key")
|
|
34
|
+
|
|
35
|
+
res = client.chat("Mujhe kuch samajh nahi aa raha life mein")
|
|
36
|
+
|
|
37
|
+
print(res.text)
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## 🧠 Response Structure
|
|
43
|
+
|
|
44
|
+
Every response includes both **AI output + governance metadata**:
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
print(res.text) # AI response
|
|
48
|
+
print(res.intent) # e.g. "confusion"
|
|
49
|
+
print(res.framework) # e.g. "confusion_direction"
|
|
50
|
+
print(res.urgency) # "low" | "medium" | "high"
|
|
51
|
+
print(res.governance_clean) # True / False
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## 🎯 Why NEES GP?
|
|
57
|
+
|
|
58
|
+
Traditional AI:
|
|
59
|
+
|
|
60
|
+
* Input → Output filter
|
|
61
|
+
|
|
62
|
+
NEES GP:
|
|
63
|
+
|
|
64
|
+
* Input → Policy → Governance → Response → Session continuity
|
|
65
|
+
|
|
66
|
+
👉 This enables **stateful AI control across conversations**
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 🔧 Configuration
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
client = Client(
|
|
74
|
+
api_key="your-api-key",
|
|
75
|
+
base_url="https://nees-gp.onrender.com",
|
|
76
|
+
timeout=30
|
|
77
|
+
)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## ⚠️ Error Handling
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
from nees_gp_sdk.exceptions import NEESError
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
res = client.chat("Hello")
|
|
89
|
+
except NEESError as e:
|
|
90
|
+
print("Error:", str(e))
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## 🛡️ Security & Privacy
|
|
96
|
+
|
|
97
|
+
* API keys are never stored in the SDK
|
|
98
|
+
* No local data persistence beyond session context
|
|
99
|
+
* Governance decisions happen server-side
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## 🧪 Example Use Cases
|
|
104
|
+
|
|
105
|
+
* AI copilots with behavioral control
|
|
106
|
+
* Emotion-aware assistants
|
|
107
|
+
* Enterprise AI governance layer
|
|
108
|
+
* Multi-agent coordination systems
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 🌐 Vision
|
|
113
|
+
|
|
114
|
+
NEES GP defines a new category:
|
|
115
|
+
|
|
116
|
+
> **AI Governance Operating System (AGOS)**
|
|
117
|
+
|
|
118
|
+
A system that governs AI behavior across time, not just at the point of output.
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## 🤝 Contributing
|
|
123
|
+
|
|
124
|
+
Contributions, feedback, and ideas are welcome.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## 📄 License
|
|
129
|
+
|
|
130
|
+
MIT License
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 👤 Author
|
|
135
|
+
|
|
136
|
+
Built by Nainacore Emotional Tech
|
|
137
|
+
Founder: Piyush P. Jambhulkar - ANNA
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"""
|
|
2
|
+
nees_gp — NEES GP Python SDK
|
|
3
|
+
=============================
|
|
4
|
+
AI Governance Operating System SDK.
|
|
5
|
+
|
|
6
|
+
Quickstart:
|
|
7
|
+
from nees_gp import Client
|
|
8
|
+
|
|
9
|
+
client = Client(api_key="your-key")
|
|
10
|
+
response = client.chat("Mujhe kuch samajh nahi aa raha")
|
|
11
|
+
print(response.text)
|
|
12
|
+
print(response.intent) # "confusion"
|
|
13
|
+
print(response.governance_clean) # True
|
|
14
|
+
|
|
15
|
+
Or set NEES_API_KEY in your environment and call Client() with no arguments.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from .client import Client
|
|
19
|
+
from .exceptions import (
|
|
20
|
+
AuthError,
|
|
21
|
+
GovernanceError,
|
|
22
|
+
NEESAPIError,
|
|
23
|
+
NEESError,
|
|
24
|
+
RateLimitError,
|
|
25
|
+
TimeoutError,
|
|
26
|
+
ValidationError,
|
|
27
|
+
)
|
|
28
|
+
from .models import (
|
|
29
|
+
ChatResponse,
|
|
30
|
+
DriftReport,
|
|
31
|
+
HealthResponse,
|
|
32
|
+
LatencyInfo,
|
|
33
|
+
ProposalResponse,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
__version__ = "0.1.0"
|
|
37
|
+
__author__ = "Nainacore Emotional Tech"
|
|
38
|
+
__all__ = [
|
|
39
|
+
# Client
|
|
40
|
+
"Client",
|
|
41
|
+
# Models
|
|
42
|
+
"ChatResponse",
|
|
43
|
+
"DriftReport",
|
|
44
|
+
"HealthResponse",
|
|
45
|
+
"LatencyInfo",
|
|
46
|
+
"ProposalResponse",
|
|
47
|
+
# Exceptions
|
|
48
|
+
"NEESError",
|
|
49
|
+
"AuthError",
|
|
50
|
+
"TimeoutError",
|
|
51
|
+
"RateLimitError",
|
|
52
|
+
"GovernanceError",
|
|
53
|
+
"ValidationError",
|
|
54
|
+
"NEESAPIError",
|
|
55
|
+
# Meta
|
|
56
|
+
"__version__",
|
|
57
|
+
]
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"""
|
|
2
|
+
=========================================
|
|
3
|
+
The single class developers interact with.
|
|
4
|
+
|
|
5
|
+
Quickstart
|
|
6
|
+
──────────
|
|
7
|
+
from nees_gp import Client
|
|
8
|
+
|
|
9
|
+
client = Client(api_key="your-key")
|
|
10
|
+
response = client.chat("Mujhe kuch samajh nahi aa raha")
|
|
11
|
+
print(response.text)
|
|
12
|
+
print(response.intent) # "confusion"
|
|
13
|
+
print(response.urgency) # "medium"
|
|
14
|
+
print(response.governance_clean) # True
|
|
15
|
+
|
|
16
|
+
Context manager
|
|
17
|
+
───────────────
|
|
18
|
+
with Client(api_key="your-key") as client:
|
|
19
|
+
response = client.chat("Help me decide")
|
|
20
|
+
print(response.text)
|
|
21
|
+
|
|
22
|
+
Environment variable shortcut
|
|
23
|
+
──────────────────────────────
|
|
24
|
+
export NEES_API_KEY="your-key"
|
|
25
|
+
|
|
26
|
+
from nees_gp import Client
|
|
27
|
+
client = Client() # reads NEES_API_KEY automatically
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
import logging
|
|
33
|
+
from typing import Any, Optional
|
|
34
|
+
|
|
35
|
+
from .config import SDKConfig
|
|
36
|
+
from .exceptions import NEESError
|
|
37
|
+
from .models import (
|
|
38
|
+
ChatResponse, DriftReport, HealthResponse,
|
|
39
|
+
ProposalResponse,
|
|
40
|
+
)
|
|
41
|
+
from .session import Session
|
|
42
|
+
from .transport import Transport
|
|
43
|
+
from .utils import resolve_api_key
|
|
44
|
+
|
|
45
|
+
logger = logging.getLogger("nees_gp_sdk.client")
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class Client:
|
|
49
|
+
"""
|
|
50
|
+
NEES GP SDK client.
|
|
51
|
+
|
|
52
|
+
Parameters
|
|
53
|
+
──────────
|
|
54
|
+
api_key API key (Bearer token). Falls back to NEES_API_KEY env var.
|
|
55
|
+
base_url NEES GP server URL. Default: https://nees-gp.onrender.com
|
|
56
|
+
timeout HTTP timeout in seconds. Default: 30
|
|
57
|
+
max_retries Retries on transient errors. Default: 2
|
|
58
|
+
authority_state Governance authority state A | B | C. Default: B
|
|
59
|
+
session_id Resume a known session by ID. Default: auto-generated UUID.
|
|
60
|
+
verify_ssl Verify SSL certificates. Default: True.
|
|
61
|
+
|
|
62
|
+
All methods raise subclasses of NEESError on failure.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def __init__(
|
|
66
|
+
self,
|
|
67
|
+
api_key: Optional[str] = None,
|
|
68
|
+
base_url: str = "https://nees-gp.onrender.com",
|
|
69
|
+
timeout: float = 30,
|
|
70
|
+
max_retries: int = 2,
|
|
71
|
+
authority_state: str = "B",
|
|
72
|
+
session_id: Optional[str] = None,
|
|
73
|
+
verify_ssl: bool = True,
|
|
74
|
+
) -> None:
|
|
75
|
+
resolved_key = resolve_api_key(api_key)
|
|
76
|
+
self._config = SDKConfig(
|
|
77
|
+
api_key=resolved_key,
|
|
78
|
+
base_url=base_url,
|
|
79
|
+
timeout=timeout,
|
|
80
|
+
max_retries=max_retries,
|
|
81
|
+
authority_state=authority_state,
|
|
82
|
+
verify_ssl=verify_ssl,
|
|
83
|
+
)
|
|
84
|
+
self._transport = Transport(self._config)
|
|
85
|
+
self._session = Session(session_id=session_id)
|
|
86
|
+
logger.debug("Client initialised | base_url=%s session=%s", base_url, self._session)
|
|
87
|
+
|
|
88
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
89
|
+
# Core interface
|
|
90
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
def chat(
|
|
93
|
+
self,
|
|
94
|
+
message: str,
|
|
95
|
+
history: Optional[list[dict[str, str]]] = None,
|
|
96
|
+
session_id: Optional[str] = None,
|
|
97
|
+
) -> ChatResponse:
|
|
98
|
+
"""
|
|
99
|
+
Send a message through the NEES GP governed chat pipeline.
|
|
100
|
+
|
|
101
|
+
The client automatically maintains conversation history across
|
|
102
|
+
calls — you do not need to pass history manually for typical use.
|
|
103
|
+
Pass `history` explicitly only to inject external context.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
message User message text (max 2000 characters).
|
|
107
|
+
history Optional explicit history override.
|
|
108
|
+
List of {"role": "user"|"assistant", "content": "..."}.
|
|
109
|
+
If None, the session's accumulated history is used.
|
|
110
|
+
session_id Override the session ID for this request only.
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
ChatResponse with text, governance metadata, and trace_id.
|
|
114
|
+
|
|
115
|
+
Raises:
|
|
116
|
+
AuthError — invalid API key
|
|
117
|
+
TimeoutError — request exceeded timeout
|
|
118
|
+
GovernanceError — server pipeline not initialised
|
|
119
|
+
ValidationError — bad request payload
|
|
120
|
+
NEESAPIError — other server error
|
|
121
|
+
"""
|
|
122
|
+
payload: dict[str, Any] = {
|
|
123
|
+
"message": message,
|
|
124
|
+
"history": history if history is not None else self._session.history_as_dicts(),
|
|
125
|
+
"session_id": session_id or self._session.session_id,
|
|
126
|
+
}
|
|
127
|
+
raw = self._transport.post("/v1/proxy/chat", json=payload)
|
|
128
|
+
resp = ChatResponse.from_dict(raw)
|
|
129
|
+
|
|
130
|
+
# Record the exchange in session history
|
|
131
|
+
self._session.record(message, resp.text)
|
|
132
|
+
logger.debug("chat: intent=%s urgency=%s clean=%s", resp.intent, resp.urgency, resp.governance_clean)
|
|
133
|
+
return resp
|
|
134
|
+
|
|
135
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
136
|
+
# Governance pipeline operations
|
|
137
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
138
|
+
|
|
139
|
+
def propose(
|
|
140
|
+
self,
|
|
141
|
+
name: str,
|
|
142
|
+
category: str,
|
|
143
|
+
payload: Optional[dict[str, Any]] = None,
|
|
144
|
+
principal: Optional[str] = None,
|
|
145
|
+
) -> ProposalResponse:
|
|
146
|
+
"""
|
|
147
|
+
Create a governance proposal via POST /propose.
|
|
148
|
+
Evaluates the action through G1–G7 gates without executing it.
|
|
149
|
+
|
|
150
|
+
Args:
|
|
151
|
+
name Human-readable action label.
|
|
152
|
+
category ActionCategory: READ | WRITE | EXTERNAL_CALL |
|
|
153
|
+
MEMORY_OP | DELEGATE | SYSTEM_CONFIG |
|
|
154
|
+
IRREVERSIBLE | SAFETY_CHANGE
|
|
155
|
+
payload Arbitrary action parameters dict.
|
|
156
|
+
principal Optional principal identifier.
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
ProposalResponse with verdict, risk_level, and admissibility detail.
|
|
160
|
+
"""
|
|
161
|
+
body: dict[str, Any] = {
|
|
162
|
+
"name": name,
|
|
163
|
+
"category": category.upper(),
|
|
164
|
+
"payload": payload or {},
|
|
165
|
+
}
|
|
166
|
+
if principal:
|
|
167
|
+
body["principal"] = principal
|
|
168
|
+
raw = self._transport.post("/propose", json=body)
|
|
169
|
+
return ProposalResponse.from_dict(raw)
|
|
170
|
+
|
|
171
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
172
|
+
# Monitoring
|
|
173
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
174
|
+
|
|
175
|
+
def health(self) -> HealthResponse:
|
|
176
|
+
"""
|
|
177
|
+
Check NEES GP server liveness via GET /health.
|
|
178
|
+
|
|
179
|
+
Returns:
|
|
180
|
+
HealthResponse with status, uptime, authority_state.
|
|
181
|
+
|
|
182
|
+
Raises:
|
|
183
|
+
GovernanceError — server is unhealthy (503)
|
|
184
|
+
"""
|
|
185
|
+
raw = self._transport.get("/health")
|
|
186
|
+
return HealthResponse.from_dict(raw)
|
|
187
|
+
|
|
188
|
+
def drift(self) -> DriftReport:
|
|
189
|
+
"""
|
|
190
|
+
Get the current drift report via GET /trajectory.
|
|
191
|
+
|
|
192
|
+
Returns:
|
|
193
|
+
DriftReport with status, anomaly_score, drift_magnitude.
|
|
194
|
+
"""
|
|
195
|
+
raw = self._transport.get("/trajectory")
|
|
196
|
+
return DriftReport.from_dict(raw)
|
|
197
|
+
|
|
198
|
+
def ledger(self, n: int = 20) -> list[dict[str, Any]]:
|
|
199
|
+
"""
|
|
200
|
+
Fetch the last N audit entries from the governance ledger.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
n Number of entries to return (max 200).
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
List of raw ledger entry dicts.
|
|
207
|
+
"""
|
|
208
|
+
raw = self._transport.get("/ledger", params={"n": min(n, 200)})
|
|
209
|
+
return raw.get("entries", [])
|
|
210
|
+
|
|
211
|
+
def policies(self) -> list[dict[str, Any]]:
|
|
212
|
+
"""
|
|
213
|
+
List all currently loaded YAML governance policies.
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
List of policy summary dicts.
|
|
217
|
+
"""
|
|
218
|
+
raw = self._transport.get("/policies")
|
|
219
|
+
return raw.get("rules", [])
|
|
220
|
+
|
|
221
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
222
|
+
# Session management
|
|
223
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
224
|
+
|
|
225
|
+
def reset_session(self) -> str:
|
|
226
|
+
"""
|
|
227
|
+
Clear conversation history and generate a new session_id.
|
|
228
|
+
Returns the new session_id.
|
|
229
|
+
"""
|
|
230
|
+
self._session.reset()
|
|
231
|
+
logger.debug("Session reset: new id=%s", self._session.session_id)
|
|
232
|
+
return self._session.session_id
|
|
233
|
+
|
|
234
|
+
def resume_session(
|
|
235
|
+
self,
|
|
236
|
+
session_id: str,
|
|
237
|
+
history: Optional[list[dict[str, str]]] = None,
|
|
238
|
+
) -> None:
|
|
239
|
+
"""
|
|
240
|
+
Resume a previously known session.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
session_id The session_id to resume.
|
|
244
|
+
history Optional history to restore. If None, starts empty.
|
|
245
|
+
"""
|
|
246
|
+
self._session.seed(session_id, history)
|
|
247
|
+
logger.debug("Session resumed: id=%s turns=%d", session_id, self._session.turn_count // 2)
|
|
248
|
+
|
|
249
|
+
@property
|
|
250
|
+
def session_id(self) -> str:
|
|
251
|
+
"""Current session identifier."""
|
|
252
|
+
return self._session.session_id
|
|
253
|
+
|
|
254
|
+
@property
|
|
255
|
+
def history(self) -> list[dict[str, str]]:
|
|
256
|
+
"""Current conversation history as a list of dicts."""
|
|
257
|
+
return self._session.history_as_dicts()
|
|
258
|
+
|
|
259
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
260
|
+
# Context manager support
|
|
261
|
+
# ─────────────────────────────────────────────────────────────────────────
|
|
262
|
+
|
|
263
|
+
def __enter__(self) -> "Client":
|
|
264
|
+
return self
|
|
265
|
+
|
|
266
|
+
def __exit__(self, *_: Any) -> None:
|
|
267
|
+
self.close()
|
|
268
|
+
|
|
269
|
+
def close(self) -> None:
|
|
270
|
+
"""Release the underlying HTTP connections."""
|
|
271
|
+
self._transport.close()
|
|
272
|
+
|
|
273
|
+
def __repr__(self) -> str:
|
|
274
|
+
return (
|
|
275
|
+
f"Client(base_url={self._config.base_url!r}, "
|
|
276
|
+
f"session={self._session!r})"
|
|
277
|
+
)
|