stresszero 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.
- stresszero-1.0.0/PKG-INFO +105 -0
- stresszero-1.0.0/README.md +77 -0
- stresszero-1.0.0/pyproject.toml +42 -0
- stresszero-1.0.0/stresszero/__init__.py +34 -0
- stresszero-1.0.0/stresszero/client.py +259 -0
- stresszero-1.0.0/stresszero/types.py +156 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stresszero
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Official Python SDK for StressZero Intelligence API — Burnout risk scoring for entrepreneurs
|
|
5
|
+
Project-URL: Homepage, https://stresszeroentrepreneur.fr/intelligence-api
|
|
6
|
+
Project-URL: Documentation, https://stresszeroentrepreneur.fr/docs
|
|
7
|
+
Project-URL: Repository, https://github.com/StressZeroEntrepreneur/stresszero-sdk-python
|
|
8
|
+
Project-URL: Issues, https://github.com/StressZeroEntrepreneur/stresszero-sdk-python/issues
|
|
9
|
+
Author-email: Emmanuel Gomes Soares <hello@stresszeroentrepreneur.fr>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
Keywords: api,burnout,entrepreneur,scoring,sdk,stress,wellness
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Requires-Python: >=3.8
|
|
23
|
+
Requires-Dist: httpx>=0.24.0
|
|
24
|
+
Provides-Extra: dev
|
|
25
|
+
Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
|
|
26
|
+
Requires-Dist: pytest>=7.0; extra == 'dev'
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
|
|
29
|
+
# StressZero Python SDK
|
|
30
|
+
|
|
31
|
+
Official Python SDK for [StressZero Intelligence API](https://stresszeroentrepreneur.fr/intelligence-api) — Burnout risk scoring for entrepreneurs.
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
pip install stresszero
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Quick Start
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from stresszero import StressZero, ResponseItem, AnalysisContext
|
|
43
|
+
|
|
44
|
+
sz = StressZero("sz_live_your_key_here")
|
|
45
|
+
|
|
46
|
+
# Quick 3-score check
|
|
47
|
+
result = sz.quick_check(physical=65, emotional=70, effectiveness=55)
|
|
48
|
+
if result.ok:
|
|
49
|
+
print(f"Score: {result.data['score']['total']}/100")
|
|
50
|
+
print(f"Risk: {result.data['risk']['level']}")
|
|
51
|
+
|
|
52
|
+
# Full analysis
|
|
53
|
+
result = sz.analyze_burnout(
|
|
54
|
+
responses=[
|
|
55
|
+
ResponseItem("physical", "sleep_quality", 65, weight=3),
|
|
56
|
+
ResponseItem("emotional", "motivation", 70, weight=2),
|
|
57
|
+
ResponseItem("effectiveness", "productivity", 55, weight=2),
|
|
58
|
+
],
|
|
59
|
+
context=AnalysisContext(profession="entrepreneur", hours_per_week=55),
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
# Predictive scoring (J+30)
|
|
63
|
+
from stresszero.types import PredictiveContext
|
|
64
|
+
|
|
65
|
+
result = sz.analyze_burnout_with_prediction(
|
|
66
|
+
responses=[
|
|
67
|
+
ResponseItem("physical", "sleep", 65, weight=3),
|
|
68
|
+
ResponseItem("emotional", "stress", 70, weight=2),
|
|
69
|
+
ResponseItem("effectiveness", "focus", 55, weight=2),
|
|
70
|
+
],
|
|
71
|
+
predictive_context=PredictiveContext(
|
|
72
|
+
sleep_hours=6,
|
|
73
|
+
exercise_days_per_week=1,
|
|
74
|
+
has_support_network=False,
|
|
75
|
+
),
|
|
76
|
+
)
|
|
77
|
+
if result.ok:
|
|
78
|
+
pred = result.data["prediction"]
|
|
79
|
+
print(f"Score J+30: {pred['prediction']['score_j30']}")
|
|
80
|
+
print(f"Trajectory: {pred['prediction']['trajectory']}")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Sandbox Testing
|
|
84
|
+
|
|
85
|
+
Use `sz_test_` prefixed keys for sandbox mode (no DB, no quota):
|
|
86
|
+
|
|
87
|
+
```python
|
|
88
|
+
sz = StressZero("sz_test_free") # Free tier sandbox
|
|
89
|
+
sz = StressZero("sz_test_pro") # Pro tier sandbox
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## API Reference
|
|
93
|
+
|
|
94
|
+
| Method | Tier | Description |
|
|
95
|
+
|--------|------|-------------|
|
|
96
|
+
| `analyze_burnout()` | Free+ | Individual burnout scoring |
|
|
97
|
+
| `analyze_burnout_with_prediction()` | Free+ | Scoring + J+30 prediction |
|
|
98
|
+
| `analyze_team()` | Starter+ | Team analysis |
|
|
99
|
+
| `generate_report()` | Starter+ | Detailed report |
|
|
100
|
+
| `quick_check()` | Free+ | Quick 3-score check |
|
|
101
|
+
| `health()` | Public | API health status |
|
|
102
|
+
|
|
103
|
+
## License
|
|
104
|
+
|
|
105
|
+
MIT — [StressZero Entrepreneur](https://stresszeroentrepreneur.fr)
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# StressZero Python SDK
|
|
2
|
+
|
|
3
|
+
Official Python SDK for [StressZero Intelligence API](https://stresszeroentrepreneur.fr/intelligence-api) — Burnout risk scoring for entrepreneurs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install stresszero
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from stresszero import StressZero, ResponseItem, AnalysisContext
|
|
15
|
+
|
|
16
|
+
sz = StressZero("sz_live_your_key_here")
|
|
17
|
+
|
|
18
|
+
# Quick 3-score check
|
|
19
|
+
result = sz.quick_check(physical=65, emotional=70, effectiveness=55)
|
|
20
|
+
if result.ok:
|
|
21
|
+
print(f"Score: {result.data['score']['total']}/100")
|
|
22
|
+
print(f"Risk: {result.data['risk']['level']}")
|
|
23
|
+
|
|
24
|
+
# Full analysis
|
|
25
|
+
result = sz.analyze_burnout(
|
|
26
|
+
responses=[
|
|
27
|
+
ResponseItem("physical", "sleep_quality", 65, weight=3),
|
|
28
|
+
ResponseItem("emotional", "motivation", 70, weight=2),
|
|
29
|
+
ResponseItem("effectiveness", "productivity", 55, weight=2),
|
|
30
|
+
],
|
|
31
|
+
context=AnalysisContext(profession="entrepreneur", hours_per_week=55),
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Predictive scoring (J+30)
|
|
35
|
+
from stresszero.types import PredictiveContext
|
|
36
|
+
|
|
37
|
+
result = sz.analyze_burnout_with_prediction(
|
|
38
|
+
responses=[
|
|
39
|
+
ResponseItem("physical", "sleep", 65, weight=3),
|
|
40
|
+
ResponseItem("emotional", "stress", 70, weight=2),
|
|
41
|
+
ResponseItem("effectiveness", "focus", 55, weight=2),
|
|
42
|
+
],
|
|
43
|
+
predictive_context=PredictiveContext(
|
|
44
|
+
sleep_hours=6,
|
|
45
|
+
exercise_days_per_week=1,
|
|
46
|
+
has_support_network=False,
|
|
47
|
+
),
|
|
48
|
+
)
|
|
49
|
+
if result.ok:
|
|
50
|
+
pred = result.data["prediction"]
|
|
51
|
+
print(f"Score J+30: {pred['prediction']['score_j30']}")
|
|
52
|
+
print(f"Trajectory: {pred['prediction']['trajectory']}")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Sandbox Testing
|
|
56
|
+
|
|
57
|
+
Use `sz_test_` prefixed keys for sandbox mode (no DB, no quota):
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
sz = StressZero("sz_test_free") # Free tier sandbox
|
|
61
|
+
sz = StressZero("sz_test_pro") # Pro tier sandbox
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## API Reference
|
|
65
|
+
|
|
66
|
+
| Method | Tier | Description |
|
|
67
|
+
|--------|------|-------------|
|
|
68
|
+
| `analyze_burnout()` | Free+ | Individual burnout scoring |
|
|
69
|
+
| `analyze_burnout_with_prediction()` | Free+ | Scoring + J+30 prediction |
|
|
70
|
+
| `analyze_team()` | Starter+ | Team analysis |
|
|
71
|
+
| `generate_report()` | Starter+ | Detailed report |
|
|
72
|
+
| `quick_check()` | Free+ | Quick 3-score check |
|
|
73
|
+
| `health()` | Public | API health status |
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
MIT — [StressZero Entrepreneur](https://stresszeroentrepreneur.fr)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "stresszero"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "Official Python SDK for StressZero Intelligence API — Burnout risk scoring for entrepreneurs"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.8"
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Emmanuel Gomes Soares", email = "hello@stresszeroentrepreneur.fr" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["burnout", "stress", "api", "sdk", "wellness", "entrepreneur", "scoring"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.8",
|
|
22
|
+
"Programming Language :: Python :: 3.9",
|
|
23
|
+
"Programming Language :: Python :: 3.10",
|
|
24
|
+
"Programming Language :: Python :: 3.11",
|
|
25
|
+
"Programming Language :: Python :: 3.12",
|
|
26
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
27
|
+
]
|
|
28
|
+
dependencies = [
|
|
29
|
+
"httpx>=0.24.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
dev = [
|
|
34
|
+
"pytest>=7.0",
|
|
35
|
+
"pytest-asyncio>=0.21",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
[project.urls]
|
|
39
|
+
Homepage = "https://stresszeroentrepreneur.fr/intelligence-api"
|
|
40
|
+
Documentation = "https://stresszeroentrepreneur.fr/docs"
|
|
41
|
+
Repository = "https://github.com/StressZeroEntrepreneur/stresszero-sdk-python"
|
|
42
|
+
Issues = "https://github.com/StressZeroEntrepreneur/stresszero-sdk-python/issues"
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"""StressZero SDK — Official Python SDK for StressZero Intelligence API."""
|
|
2
|
+
|
|
3
|
+
from .client import StressZero
|
|
4
|
+
from .types import (
|
|
5
|
+
Dimension,
|
|
6
|
+
RiskLevel,
|
|
7
|
+
Language,
|
|
8
|
+
ResponseItem,
|
|
9
|
+
AnalysisContext,
|
|
10
|
+
AnalysisOptions,
|
|
11
|
+
AnalysisResult,
|
|
12
|
+
ReportResult,
|
|
13
|
+
TeamAnalysisResult,
|
|
14
|
+
PredictiveResult,
|
|
15
|
+
HealthResult,
|
|
16
|
+
ApiResponse,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
__version__ = "1.0.0"
|
|
20
|
+
__all__ = [
|
|
21
|
+
"StressZero",
|
|
22
|
+
"Dimension",
|
|
23
|
+
"RiskLevel",
|
|
24
|
+
"Language",
|
|
25
|
+
"ResponseItem",
|
|
26
|
+
"AnalysisContext",
|
|
27
|
+
"AnalysisOptions",
|
|
28
|
+
"AnalysisResult",
|
|
29
|
+
"ReportResult",
|
|
30
|
+
"TeamAnalysisResult",
|
|
31
|
+
"PredictiveResult",
|
|
32
|
+
"HealthResult",
|
|
33
|
+
"ApiResponse",
|
|
34
|
+
]
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"""StressZero API client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import asdict
|
|
6
|
+
from typing import Any, Dict, List, Optional
|
|
7
|
+
|
|
8
|
+
import httpx
|
|
9
|
+
|
|
10
|
+
from .types import (
|
|
11
|
+
AnalysisContext,
|
|
12
|
+
AnalysisOptions,
|
|
13
|
+
ApiResponse,
|
|
14
|
+
HealthResult,
|
|
15
|
+
Language,
|
|
16
|
+
PredictiveContext,
|
|
17
|
+
PreviousScore,
|
|
18
|
+
ResponseItem,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class StressZero:
|
|
23
|
+
"""Official Python client for StressZero Intelligence API.
|
|
24
|
+
|
|
25
|
+
Example::
|
|
26
|
+
|
|
27
|
+
from stresszero import StressZero, ResponseItem
|
|
28
|
+
|
|
29
|
+
sz = StressZero("sz_live_your_key_here")
|
|
30
|
+
|
|
31
|
+
result = sz.analyze_burnout(
|
|
32
|
+
responses=[
|
|
33
|
+
ResponseItem("physical", "sleep", 65, weight=3),
|
|
34
|
+
ResponseItem("emotional", "motivation", 70, weight=2),
|
|
35
|
+
ResponseItem("effectiveness", "productivity", 55, weight=2),
|
|
36
|
+
],
|
|
37
|
+
context=AnalysisContext(profession="entrepreneur", hours_per_week=55),
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
if result.ok:
|
|
41
|
+
print(result.data["score"]["total"])
|
|
42
|
+
print(result.data["risk"]["level"])
|
|
43
|
+
|
|
44
|
+
Docs: https://stresszeroentrepreneur.fr/intelligence-api
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
BASE_URL = "https://stresszeroentrepreneur.fr"
|
|
48
|
+
VERSION = "1.0.0"
|
|
49
|
+
|
|
50
|
+
def __init__(
|
|
51
|
+
self,
|
|
52
|
+
api_key: str,
|
|
53
|
+
*,
|
|
54
|
+
base_url: Optional[str] = None,
|
|
55
|
+
timeout: float = 30.0,
|
|
56
|
+
):
|
|
57
|
+
if not api_key or not (api_key.startswith("sz_live_") or api_key.startswith("sz_test_")):
|
|
58
|
+
raise ValueError(
|
|
59
|
+
"Invalid API key. Must start with 'sz_live_' or 'sz_test_'. "
|
|
60
|
+
"Get your free key at: https://stresszeroentrepreneur.fr/intelligence-api"
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
self._api_key = api_key
|
|
64
|
+
self._base_url = (base_url or self.BASE_URL).rstrip("/")
|
|
65
|
+
self._client = httpx.Client(
|
|
66
|
+
base_url=self._base_url,
|
|
67
|
+
timeout=timeout,
|
|
68
|
+
headers={
|
|
69
|
+
"Authorization": f"Bearer {api_key}",
|
|
70
|
+
"Content-Type": "application/json",
|
|
71
|
+
"User-Agent": f"stresszero-python/{self.VERSION}",
|
|
72
|
+
},
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
def _request(self, method: str, path: str, json: Optional[Dict[str, Any]] = None) -> ApiResponse:
|
|
76
|
+
try:
|
|
77
|
+
resp = self._client.request(method, path, json=json)
|
|
78
|
+
data = resp.json()
|
|
79
|
+
return ApiResponse(
|
|
80
|
+
success=data.get("success", False),
|
|
81
|
+
data=data.get("data"),
|
|
82
|
+
error=data.get("error"),
|
|
83
|
+
meta=data.get("meta"),
|
|
84
|
+
)
|
|
85
|
+
except httpx.TimeoutException:
|
|
86
|
+
return ApiResponse(success=False, error={"message": "Request timed out"})
|
|
87
|
+
except Exception as e:
|
|
88
|
+
return ApiResponse(success=False, error={"message": str(e)})
|
|
89
|
+
|
|
90
|
+
def analyze_burnout(
|
|
91
|
+
self,
|
|
92
|
+
responses: List[ResponseItem],
|
|
93
|
+
*,
|
|
94
|
+
context: Optional[AnalysisContext] = None,
|
|
95
|
+
options: Optional[AnalysisOptions] = None,
|
|
96
|
+
) -> ApiResponse:
|
|
97
|
+
"""Score burnout risk across 3 dimensions (physical, emotional, effectiveness).
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
responses: List of ResponseItem (min 3, max 20).
|
|
101
|
+
context: Professional context (profession, hours, experience).
|
|
102
|
+
options: Output options (language, recommendations, dimensions).
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
ApiResponse with score, risk, recommendations, suggested product.
|
|
106
|
+
"""
|
|
107
|
+
payload: Dict[str, Any] = {
|
|
108
|
+
"responses": [asdict(r) for r in responses],
|
|
109
|
+
}
|
|
110
|
+
if context:
|
|
111
|
+
payload["context"] = {k: v for k, v in asdict(context).items() if v is not None}
|
|
112
|
+
if options:
|
|
113
|
+
payload["options"] = {k: v for k, v in asdict(options).items() if v is not None}
|
|
114
|
+
|
|
115
|
+
return self._request("POST", "/api/v1/analyze-burnout", json=payload)
|
|
116
|
+
|
|
117
|
+
def analyze_burnout_with_prediction(
|
|
118
|
+
self,
|
|
119
|
+
responses: List[ResponseItem],
|
|
120
|
+
*,
|
|
121
|
+
context: Optional[AnalysisContext] = None,
|
|
122
|
+
predictive_context: Optional[PredictiveContext] = None,
|
|
123
|
+
previous_scores: Optional[List[PreviousScore]] = None,
|
|
124
|
+
language: Language = "fr",
|
|
125
|
+
) -> ApiResponse:
|
|
126
|
+
"""Analyze burnout with J+30 predictive trajectory.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
responses: List of ResponseItem.
|
|
130
|
+
context: Professional context.
|
|
131
|
+
predictive_context: Lifestyle factors for prediction.
|
|
132
|
+
previous_scores: Historical scores for trend detection.
|
|
133
|
+
language: Response language ('fr' or 'en').
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
ApiResponse with score, risk, recommendations + prediction.
|
|
137
|
+
"""
|
|
138
|
+
payload: Dict[str, Any] = {
|
|
139
|
+
"responses": [asdict(r) for r in responses],
|
|
140
|
+
"options": {"include_prediction": True, "language": language},
|
|
141
|
+
}
|
|
142
|
+
if context:
|
|
143
|
+
payload["context"] = {k: v for k, v in asdict(context).items() if v is not None}
|
|
144
|
+
if predictive_context:
|
|
145
|
+
payload["predictive_context"] = {k: v for k, v in asdict(predictive_context).items() if v is not None}
|
|
146
|
+
if previous_scores:
|
|
147
|
+
payload["previous_scores"] = [asdict(s) for s in previous_scores]
|
|
148
|
+
|
|
149
|
+
return self._request("POST", "/api/v1/analyze-burnout", json=payload)
|
|
150
|
+
|
|
151
|
+
def analyze_team(
|
|
152
|
+
self,
|
|
153
|
+
members: List[Dict[str, Any]],
|
|
154
|
+
*,
|
|
155
|
+
team_name: Optional[str] = None,
|
|
156
|
+
anonymize: bool = True,
|
|
157
|
+
language: Language = "fr",
|
|
158
|
+
) -> ApiResponse:
|
|
159
|
+
"""Analyze burnout risk across a team. Requires Starter+ tier.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
members: List of team member data (responses + context).
|
|
163
|
+
team_name: Optional team name.
|
|
164
|
+
anonymize: Anonymize member IDs in response.
|
|
165
|
+
language: Response language.
|
|
166
|
+
|
|
167
|
+
Returns:
|
|
168
|
+
ApiResponse with team stats, distribution, alerts, recommendations.
|
|
169
|
+
"""
|
|
170
|
+
payload: Dict[str, Any] = {
|
|
171
|
+
"members": members,
|
|
172
|
+
"options": {"anonymize": anonymize, "language": language},
|
|
173
|
+
}
|
|
174
|
+
if team_name:
|
|
175
|
+
payload["team_name"] = team_name
|
|
176
|
+
|
|
177
|
+
return self._request("POST", "/api/v1/analyze-team", json=payload)
|
|
178
|
+
|
|
179
|
+
def generate_report(
|
|
180
|
+
self,
|
|
181
|
+
responses: List[ResponseItem],
|
|
182
|
+
*,
|
|
183
|
+
context: Optional[Dict[str, Any]] = None,
|
|
184
|
+
language: Language = "fr",
|
|
185
|
+
format: str = "json",
|
|
186
|
+
) -> ApiResponse:
|
|
187
|
+
"""Generate a detailed burnout report. Requires Starter+ tier.
|
|
188
|
+
|
|
189
|
+
Args:
|
|
190
|
+
responses: List of ResponseItem.
|
|
191
|
+
context: Report context (profession, company, employee name).
|
|
192
|
+
language: Report language.
|
|
193
|
+
format: Output format ('json' or 'html').
|
|
194
|
+
|
|
195
|
+
Returns:
|
|
196
|
+
ApiResponse with full report (summary, dimensions, action plan, resources).
|
|
197
|
+
"""
|
|
198
|
+
payload: Dict[str, Any] = {
|
|
199
|
+
"responses": [asdict(r) for r in responses],
|
|
200
|
+
"language": language,
|
|
201
|
+
"format": format,
|
|
202
|
+
}
|
|
203
|
+
if context:
|
|
204
|
+
payload["context"] = context
|
|
205
|
+
|
|
206
|
+
return self._request("POST", "/api/v1/generate-report", json=payload)
|
|
207
|
+
|
|
208
|
+
def quick_check(
|
|
209
|
+
self,
|
|
210
|
+
physical: int,
|
|
211
|
+
emotional: int,
|
|
212
|
+
effectiveness: int,
|
|
213
|
+
*,
|
|
214
|
+
profession: Optional[str] = None,
|
|
215
|
+
hours_per_week: Optional[int] = None,
|
|
216
|
+
) -> ApiResponse:
|
|
217
|
+
"""Quick 3-score burnout check.
|
|
218
|
+
|
|
219
|
+
Args:
|
|
220
|
+
physical: Physical exhaustion score (0-100).
|
|
221
|
+
emotional: Emotional depletion score (0-100).
|
|
222
|
+
effectiveness: Reduced effectiveness score (0-100).
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
ApiResponse with score, risk level, recommendations.
|
|
226
|
+
"""
|
|
227
|
+
responses = [
|
|
228
|
+
ResponseItem("physical", "overall", physical, weight=2),
|
|
229
|
+
ResponseItem("emotional", "overall", emotional, weight=2),
|
|
230
|
+
ResponseItem("effectiveness", "overall", effectiveness, weight=2),
|
|
231
|
+
]
|
|
232
|
+
context = AnalysisContext(profession=profession, hours_per_week=hours_per_week)
|
|
233
|
+
return self.analyze_burnout(responses, context=context)
|
|
234
|
+
|
|
235
|
+
def health(self) -> HealthResult:
|
|
236
|
+
"""Check API health status (no auth required).
|
|
237
|
+
|
|
238
|
+
Returns:
|
|
239
|
+
HealthResult with status, version, checks.
|
|
240
|
+
"""
|
|
241
|
+
resp = httpx.get(f"{self._base_url}/api/v1/health", timeout=10)
|
|
242
|
+
data = resp.json()
|
|
243
|
+
return HealthResult(
|
|
244
|
+
status=data.get("status", "unknown"),
|
|
245
|
+
version=data.get("version", ""),
|
|
246
|
+
timestamp=data.get("timestamp", ""),
|
|
247
|
+
latency_ms=data.get("latency_ms", 0),
|
|
248
|
+
checks=data.get("checks", {}),
|
|
249
|
+
)
|
|
250
|
+
|
|
251
|
+
def close(self) -> None:
|
|
252
|
+
"""Close the HTTP client."""
|
|
253
|
+
self._client.close()
|
|
254
|
+
|
|
255
|
+
def __enter__(self):
|
|
256
|
+
return self
|
|
257
|
+
|
|
258
|
+
def __exit__(self, *args):
|
|
259
|
+
self.close()
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""Type definitions for StressZero SDK."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
from typing import Any, Dict, List, Literal, Optional, Union
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
Dimension = Literal["physical", "emotional", "effectiveness"]
|
|
10
|
+
RiskLevel = Literal["low", "moderate", "high", "critical"]
|
|
11
|
+
Language = Literal["fr", "en"]
|
|
12
|
+
Trajectory = Literal["improving", "stable", "worsening", "critical_acceleration"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class ResponseItem:
|
|
17
|
+
dimension: Dimension
|
|
18
|
+
question_id: str
|
|
19
|
+
value: int
|
|
20
|
+
weight: int = 1
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass
|
|
24
|
+
class AnalysisContext:
|
|
25
|
+
profession: Optional[str] = None
|
|
26
|
+
hours_per_week: Optional[int] = None
|
|
27
|
+
team_size: Optional[int] = None
|
|
28
|
+
years_experience: Optional[int] = None
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@dataclass
|
|
32
|
+
class AnalysisOptions:
|
|
33
|
+
include_recommendations: bool = True
|
|
34
|
+
include_dimensions: bool = True
|
|
35
|
+
include_prediction: bool = False
|
|
36
|
+
language: Language = "fr"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@dataclass
|
|
40
|
+
class PredictiveContext:
|
|
41
|
+
has_support_network: Optional[bool] = None
|
|
42
|
+
has_morning_routine: Optional[bool] = None
|
|
43
|
+
exercise_days_per_week: Optional[int] = None
|
|
44
|
+
sleep_hours: Optional[float] = None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@dataclass
|
|
48
|
+
class PreviousScore:
|
|
49
|
+
physical: int
|
|
50
|
+
emotional: int
|
|
51
|
+
effectiveness: int
|
|
52
|
+
measured_at: str
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass
|
|
56
|
+
class DimensionScore:
|
|
57
|
+
physical: int
|
|
58
|
+
emotional: int
|
|
59
|
+
effectiveness: int
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@dataclass
|
|
63
|
+
class RiskAssessment:
|
|
64
|
+
level: RiskLevel
|
|
65
|
+
factors: List[str]
|
|
66
|
+
urgency: int
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass
|
|
70
|
+
class SuggestedProduct:
|
|
71
|
+
id: str
|
|
72
|
+
url: str
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@dataclass
|
|
76
|
+
class PredictiveResult:
|
|
77
|
+
prediction: Dict[str, Any]
|
|
78
|
+
risk_factors: List[Dict[str, Any]]
|
|
79
|
+
intervention_urgency: Dict[str, Any]
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass
|
|
83
|
+
class AnalysisResult:
|
|
84
|
+
score: Dict[str, Any]
|
|
85
|
+
risk: Dict[str, Any]
|
|
86
|
+
recommendations: Optional[List[str]] = None
|
|
87
|
+
suggested_product: Optional[Dict[str, str]] = None
|
|
88
|
+
disclaimer: Optional[str] = None
|
|
89
|
+
prediction: Optional[PredictiveResult] = None
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@dataclass
|
|
93
|
+
class ReportResult:
|
|
94
|
+
report: Dict[str, Any]
|
|
95
|
+
summary: Dict[str, Any]
|
|
96
|
+
dimensions: Dict[str, Any]
|
|
97
|
+
action_plan: Dict[str, Any]
|
|
98
|
+
context_factors: Optional[Dict[str, Any]] = None
|
|
99
|
+
resources: Optional[Dict[str, Any]] = None
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@dataclass
|
|
103
|
+
class TeamMember:
|
|
104
|
+
member_id: str
|
|
105
|
+
score: int
|
|
106
|
+
risk_level: RiskLevel
|
|
107
|
+
dimensions: DimensionScore
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@dataclass
|
|
111
|
+
class TeamAnalysisResult:
|
|
112
|
+
team: Dict[str, Any]
|
|
113
|
+
distribution: Optional[Dict[str, int]] = None
|
|
114
|
+
department_breakdown: Optional[Dict[str, Any]] = None
|
|
115
|
+
alerts: List[str] = field(default_factory=list)
|
|
116
|
+
recommendations: List[str] = field(default_factory=list)
|
|
117
|
+
members: List[Dict[str, Any]] = field(default_factory=list)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@dataclass
|
|
121
|
+
class HealthResult:
|
|
122
|
+
status: str
|
|
123
|
+
version: str
|
|
124
|
+
timestamp: str
|
|
125
|
+
latency_ms: float
|
|
126
|
+
checks: Dict[str, Any] = field(default_factory=dict)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
@dataclass
|
|
130
|
+
class ApiMeta:
|
|
131
|
+
api_version: str
|
|
132
|
+
latency_ms: float
|
|
133
|
+
quota: Dict[str, Any] = field(default_factory=dict)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
@dataclass
|
|
137
|
+
class ApiResponse:
|
|
138
|
+
success: bool
|
|
139
|
+
data: Optional[Any] = None
|
|
140
|
+
error: Optional[Dict[str, Any]] = None
|
|
141
|
+
meta: Optional[ApiMeta] = None
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def ok(self) -> bool:
|
|
145
|
+
return self.success
|
|
146
|
+
|
|
147
|
+
def raise_for_error(self) -> None:
|
|
148
|
+
if not self.success and self.error:
|
|
149
|
+
raise StressZeroError(self.error.get("message", "Unknown error"), self.error.get("status"))
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class StressZeroError(Exception):
|
|
153
|
+
def __init__(self, message: str, status: Optional[int] = None):
|
|
154
|
+
self.message = message
|
|
155
|
+
self.status = status
|
|
156
|
+
super().__init__(f"[{status}] {message}" if status else message)
|