stewai 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.
- stewai-0.1.0/.gitignore +132 -0
- stewai-0.1.0/LICENSE.md +27 -0
- stewai-0.1.0/PKG-INFO +77 -0
- stewai-0.1.0/README.md +32 -0
- stewai-0.1.0/pyproject.toml +41 -0
- stewai-0.1.0/src/stewai/__init__.py +10 -0
- stewai-0.1.0/src/stewai/client.py +38 -0
- stewai-0.1.0/src/stewai/errors.py +23 -0
- stewai-0.1.0/src/stewai/py.typed +1 -0
- stewai-0.1.0/src/stewai/resources/__init__.py +1 -0
- stewai-0.1.0/src/stewai/resources/runs.py +52 -0
stewai-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
###############################################################################
|
|
2
|
+
# StewAI — Monorepo .gitignore #
|
|
3
|
+
# Covers: Python (backend), Node (frontend), JetBrains IDE, macOS, CI, etc. #
|
|
4
|
+
###############################################################################
|
|
5
|
+
|
|
6
|
+
###############################################################################
|
|
7
|
+
# 1 · OS / Editor junk #
|
|
8
|
+
###############################################################################
|
|
9
|
+
.DS_Store
|
|
10
|
+
Thumbs.db
|
|
11
|
+
# JetBrains / VS Code
|
|
12
|
+
.idea/
|
|
13
|
+
!.idea/code-style.xml # keep shared code-style only
|
|
14
|
+
.idea/vcs.xml # VCS metadata – tracked only when useful
|
|
15
|
+
*.iml
|
|
16
|
+
.vscode/
|
|
17
|
+
# Swap / temp files
|
|
18
|
+
*.swp
|
|
19
|
+
*~
|
|
20
|
+
*.tmp
|
|
21
|
+
*.xml # generic user-level IDE configs
|
|
22
|
+
.history # VS Code local history
|
|
23
|
+
.quarantine # macOS file attribute after downloads
|
|
24
|
+
|
|
25
|
+
###############################################################################
|
|
26
|
+
# 2 · Python / Poetry #
|
|
27
|
+
###############################################################################
|
|
28
|
+
__pycache__/
|
|
29
|
+
*.py[cod]
|
|
30
|
+
*.pyo
|
|
31
|
+
.env
|
|
32
|
+
.venv/
|
|
33
|
+
venv/
|
|
34
|
+
dist/
|
|
35
|
+
build/
|
|
36
|
+
.eggs/
|
|
37
|
+
*.egg-info/
|
|
38
|
+
pip-wheel-metadata/
|
|
39
|
+
.tox/
|
|
40
|
+
.mypy_cache/
|
|
41
|
+
.pytest_cache/
|
|
42
|
+
.pyre/
|
|
43
|
+
.dmypy.json
|
|
44
|
+
pytestdebug.log
|
|
45
|
+
coverage.*
|
|
46
|
+
coverage.xml
|
|
47
|
+
htmlcov/
|
|
48
|
+
*.cover
|
|
49
|
+
|
|
50
|
+
###############################################################################
|
|
51
|
+
# 3 · Node / Frontend #
|
|
52
|
+
###############################################################################
|
|
53
|
+
node_modules/
|
|
54
|
+
.cache/
|
|
55
|
+
npm-debug.log*
|
|
56
|
+
yarn-debug.log*
|
|
57
|
+
yarn-error.log*
|
|
58
|
+
pnpm-lock.yaml
|
|
59
|
+
+.pnp.* # Yarn Berry Plug-and-Play loader files
|
|
60
|
+
|
|
61
|
+
# ─ Yarn Berry / PnP rules ───────────────────────────────────────────────────
|
|
62
|
+
.yarn/cache/**
|
|
63
|
+
.yarn/**
|
|
64
|
+
!.yarn/patches/**
|
|
65
|
+
!.yarn/plugins/**
|
|
66
|
+
!.yarn/releases/**
|
|
67
|
+
!.yarn/sdks/**
|
|
68
|
+
!**/yarn.lock
|
|
69
|
+
|
|
70
|
+
###############################################################################
|
|
71
|
+
# 4 · Production / dev-build artefacts #
|
|
72
|
+
###############################################################################
|
|
73
|
+
/build/
|
|
74
|
+
dist/
|
|
75
|
+
out/
|
|
76
|
+
.next/
|
|
77
|
+
.svelte-kit/
|
|
78
|
+
vite-cache/
|
|
79
|
+
storybook-static/
|
|
80
|
+
coverage/ # JS code-coverage directory
|
|
81
|
+
|
|
82
|
+
###############################################################################
|
|
83
|
+
# 5 · Docker / Kubernetes #
|
|
84
|
+
###############################################################################
|
|
85
|
+
*.tar
|
|
86
|
+
*.log
|
|
87
|
+
docker-compose.override.yml # local overrides (any depth)
|
|
88
|
+
**/docker-compose.override.yml
|
|
89
|
+
.secrets/ # doppler / sops decrypted files
|
|
90
|
+
#
|
|
91
|
+
# ─ Helm values with live secrets ────────────────────────────────────────────
|
|
92
|
+
# Every real environment gets its *own* values-prod.yaml, values-staging.yaml,
|
|
93
|
+
# etc. They are **never** committed – only the redacted template is tracked.
|
|
94
|
+
stewai-chart/values*.yaml
|
|
95
|
+
!stewai-chart/values-template.yaml
|
|
96
|
+
backend/.env* # runtime-specific env files
|
|
97
|
+
*.envrc # direnv definitions
|
|
98
|
+
.direnv/ # direnv virtual envs
|
|
99
|
+
|
|
100
|
+
###############################################################################
|
|
101
|
+
# 6 · Misc tooling artefacts #
|
|
102
|
+
###############################################################################
|
|
103
|
+
*.sqlite3
|
|
104
|
+
*.db
|
|
105
|
+
*.ipynb_checkpoints/*
|
|
106
|
+
*.ipynb
|
|
107
|
+
*.npy
|
|
108
|
+
*.parquet
|
|
109
|
+
*.csv
|
|
110
|
+
|
|
111
|
+
###############################################################################
|
|
112
|
+
# 7 · macOS & sync service artefacts #
|
|
113
|
+
###############################################################################
|
|
114
|
+
*.zip
|
|
115
|
+
*.tgz
|
|
116
|
+
*.tar.gz
|
|
117
|
+
*.gz
|
|
118
|
+
._* # macOS “resource fork”
|
|
119
|
+
|
|
120
|
+
###############################################################################
|
|
121
|
+
# 8 · End-of-file guard #
|
|
122
|
+
###############################################################################
|
|
123
|
+
# Add new rules above this line – keep the file alphabetised within sections.
|
|
124
|
+
/backend/.coverage
|
|
125
|
+
/.coverage
|
|
126
|
+
/frontend/test-results/.last-run.json
|
|
127
|
+
/frontend/test-results/after-login.png
|
|
128
|
+
/frontend/test-results/before-login.png
|
|
129
|
+
/backend/apps/runner/tests/.coverage
|
|
130
|
+
/backend/.env.bak
|
|
131
|
+
stewai_dump.pgsql
|
|
132
|
+
stewai_dump_20251210_160158.pgsql
|
stewai-0.1.0/LICENSE.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
StewAI Commercial License
|
|
2
|
+
Version 0.0.0 – June 2025
|
|
3
|
+
Copyright © 2025 Christian Mueller. All rights reserved.
|
|
4
|
+
|
|
5
|
+
1. Grant of License
|
|
6
|
+
You are granted a non-exclusive, non-transferable, revocable license to
|
|
7
|
+
(a) view and modify the source code in this repository,
|
|
8
|
+
(b) run the Software for your internal evaluation or development purposes only.
|
|
9
|
+
|
|
10
|
+
2. Restrictions
|
|
11
|
+
• No distribution, sublicensing, or SaaS offering of the Software or
|
|
12
|
+
Derivative Works is permitted without a separate commercial agreement.
|
|
13
|
+
• You may not remove or alter any proprietary notices.
|
|
14
|
+
• Reverse engineering of any binary distribution is prohibited unless
|
|
15
|
+
required by law.
|
|
16
|
+
|
|
17
|
+
3. Termination
|
|
18
|
+
This License terminates automatically if you breach any term. Upon
|
|
19
|
+
termination you must destroy all copies and cease all use.
|
|
20
|
+
|
|
21
|
+
4. DISCLAIMER
|
|
22
|
+
THE SOFTWARE IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND. THE AUTHOR
|
|
23
|
+
DISCLAIMS ALL LIABILITY FOR DAMAGES, DIRECT OR INDIRECT, ARISING FROM USE
|
|
24
|
+
OF THE SOFTWARE.
|
|
25
|
+
|
|
26
|
+
For a production or redistribution license, contact:
|
|
27
|
+
Christian Mueller · christian.mueller@camueller.org
|
stewai-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stewai
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Official StewAI Python SDK
|
|
5
|
+
Author-email: StewAI <dev@stewai.com>
|
|
6
|
+
License: StewAI Commercial License
|
|
7
|
+
Version 0.0.0 – June 2025
|
|
8
|
+
Copyright © 2025 Christian Mueller. All rights reserved.
|
|
9
|
+
|
|
10
|
+
1. Grant of License
|
|
11
|
+
You are granted a non-exclusive, non-transferable, revocable license to
|
|
12
|
+
(a) view and modify the source code in this repository,
|
|
13
|
+
(b) run the Software for your internal evaluation or development purposes only.
|
|
14
|
+
|
|
15
|
+
2. Restrictions
|
|
16
|
+
• No distribution, sublicensing, or SaaS offering of the Software or
|
|
17
|
+
Derivative Works is permitted without a separate commercial agreement.
|
|
18
|
+
• You may not remove or alter any proprietary notices.
|
|
19
|
+
• Reverse engineering of any binary distribution is prohibited unless
|
|
20
|
+
required by law.
|
|
21
|
+
|
|
22
|
+
3. Termination
|
|
23
|
+
This License terminates automatically if you breach any term. Upon
|
|
24
|
+
termination you must destroy all copies and cease all use.
|
|
25
|
+
|
|
26
|
+
4. DISCLAIMER
|
|
27
|
+
THE SOFTWARE IS PROVIDED “AS IS” WITHOUT WARRANTY OF ANY KIND. THE AUTHOR
|
|
28
|
+
DISCLAIMS ALL LIABILITY FOR DAMAGES, DIRECT OR INDIRECT, ARISING FROM USE
|
|
29
|
+
OF THE SOFTWARE.
|
|
30
|
+
|
|
31
|
+
For a production or redistribution license, contact:
|
|
32
|
+
Christian Mueller · christian.mueller@camueller.org
|
|
33
|
+
License-File: LICENSE.md
|
|
34
|
+
Keywords: api,sdk,stewai
|
|
35
|
+
Classifier: Development Status :: 3 - Alpha
|
|
36
|
+
Classifier: License :: Other/Proprietary License
|
|
37
|
+
Classifier: Programming Language :: Python :: 3
|
|
38
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
39
|
+
Classifier: Typing :: Typed
|
|
40
|
+
Requires-Python: >=3.10
|
|
41
|
+
Requires-Dist: httpx<1.0,>=0.27
|
|
42
|
+
Provides-Extra: dev
|
|
43
|
+
Requires-Dist: pytest<9,>=8; extra == 'dev'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
# stewai (Python SDK)
|
|
47
|
+
|
|
48
|
+
Base URL (only): `https://api.stewai.com/v1`
|
|
49
|
+
|
|
50
|
+
## Install
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pip install stewai
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Get an API key
|
|
57
|
+
|
|
58
|
+
1. Log in to `stewai.com`
|
|
59
|
+
2. Go to `Settings → API keys`
|
|
60
|
+
3. Create a key and copy it once (`sk-live-...`)
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from stewai import Stew
|
|
66
|
+
|
|
67
|
+
client = Stew(api_key="sk-live-...")
|
|
68
|
+
|
|
69
|
+
# Use the Input step “API input id” shown in the editor as the inputs key
|
|
70
|
+
run = client.runs.create(
|
|
71
|
+
recipe_id="01K....",
|
|
72
|
+
inputs={"USERQUESTION": "What should I focus on this week?"},
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
run = client.runs.wait(run["id"], timeout=300)
|
|
76
|
+
steps = client.runs.steps(run["id"])
|
|
77
|
+
```
|
stewai-0.1.0/README.md
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# stewai (Python SDK)
|
|
2
|
+
|
|
3
|
+
Base URL (only): `https://api.stewai.com/v1`
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install stewai
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Get an API key
|
|
12
|
+
|
|
13
|
+
1. Log in to `stewai.com`
|
|
14
|
+
2. Go to `Settings → API keys`
|
|
15
|
+
3. Create a key and copy it once (`sk-live-...`)
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from stewai import Stew
|
|
21
|
+
|
|
22
|
+
client = Stew(api_key="sk-live-...")
|
|
23
|
+
|
|
24
|
+
# Use the Input step “API input id” shown in the editor as the inputs key
|
|
25
|
+
run = client.runs.create(
|
|
26
|
+
recipe_id="01K....",
|
|
27
|
+
inputs={"USERQUESTION": "What should I focus on this week?"},
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
run = client.runs.wait(run["id"], timeout=300)
|
|
31
|
+
steps = client.runs.steps(run["id"])
|
|
32
|
+
```
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.25"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "stewai"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Official StewAI Python SDK"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { file = "LICENSE.md" }
|
|
12
|
+
authors = [{ name = "StewAI", email = "dev@stewai.com" }]
|
|
13
|
+
keywords = ["stewai", "sdk", "api"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"License :: Other/Proprietary License",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
19
|
+
"Typing :: Typed",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"httpx>=0.27,<1.0",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.optional-dependencies]
|
|
26
|
+
dev = [
|
|
27
|
+
"pytest>=8,<9",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[tool.hatch.build.targets.wheel]
|
|
31
|
+
packages = ["src/stewai"]
|
|
32
|
+
|
|
33
|
+
[tool.hatch.build]
|
|
34
|
+
include = [
|
|
35
|
+
"src/stewai/**",
|
|
36
|
+
"README.md",
|
|
37
|
+
"LICENSE.md",
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
[tool.pytest.ini_options]
|
|
41
|
+
testpaths = ["tests"]
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
|
|
5
|
+
from .resources.runs import RunsResource
|
|
6
|
+
|
|
7
|
+
DEFAULT_BASE_URL = "https://api.stewai.com/v1"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Stew:
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
api_key: str,
|
|
14
|
+
*,
|
|
15
|
+
base_url: str = DEFAULT_BASE_URL,
|
|
16
|
+
timeout: float = 60.0,
|
|
17
|
+
transport: httpx.BaseTransport | None = None,
|
|
18
|
+
) -> None:
|
|
19
|
+
base_url = base_url.rstrip("/") + "/"
|
|
20
|
+
self._client = httpx.Client(
|
|
21
|
+
base_url=base_url,
|
|
22
|
+
timeout=timeout,
|
|
23
|
+
transport=transport,
|
|
24
|
+
headers={
|
|
25
|
+
"Authorization": f"Bearer {api_key}",
|
|
26
|
+
"User-Agent": "stewai-python/0.1.0",
|
|
27
|
+
},
|
|
28
|
+
)
|
|
29
|
+
self.runs = RunsResource(self._client)
|
|
30
|
+
|
|
31
|
+
def close(self) -> None:
|
|
32
|
+
self._client.close()
|
|
33
|
+
|
|
34
|
+
def __enter__(self) -> "Stew":
|
|
35
|
+
return self
|
|
36
|
+
|
|
37
|
+
def __exit__(self, exc_type, exc, tb) -> None:
|
|
38
|
+
self.close()
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Optional
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class StewError(Exception):
|
|
8
|
+
pass
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass
|
|
12
|
+
class ApiError(StewError):
|
|
13
|
+
status_code: int
|
|
14
|
+
body: Any = None
|
|
15
|
+
message: str = "API request failed"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AuthenticationError(ApiError):
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class RateLimitError(ApiError):
|
|
23
|
+
retry_after: Optional[str] = None
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
import time
|
|
5
|
+
|
|
6
|
+
import httpx
|
|
7
|
+
|
|
8
|
+
from ..errors import ApiError, AuthenticationError, RateLimitError
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class RunsResource:
|
|
12
|
+
def __init__(self, client: httpx.Client) -> None:
|
|
13
|
+
self._client = client
|
|
14
|
+
|
|
15
|
+
def create(self, recipe_id: str, inputs: Optional[Dict[str, str]] = None) -> Dict[str, Any]:
|
|
16
|
+
return self._json(self._client.post("runs/", json={"recipe_id": recipe_id, "inputs": inputs or {}}))
|
|
17
|
+
|
|
18
|
+
def get(self, run_id: str) -> Dict[str, Any]:
|
|
19
|
+
return self._json(self._client.get(f"runs/{run_id}/"))
|
|
20
|
+
|
|
21
|
+
def steps(self, run_id: str) -> Dict[str, Any]:
|
|
22
|
+
return self._json(self._client.get(f"runs/{run_id}/steps/"))
|
|
23
|
+
|
|
24
|
+
def wait(self, run_id: str, *, timeout: float = 300.0, poll_interval: float = 1.0) -> Dict[str, Any]:
|
|
25
|
+
deadline = time.time() + timeout
|
|
26
|
+
while True:
|
|
27
|
+
run = self.get(run_id)
|
|
28
|
+
status = run.get("status")
|
|
29
|
+
if status in {"done", "failed", "abandoned"}:
|
|
30
|
+
return run
|
|
31
|
+
if time.time() > deadline:
|
|
32
|
+
raise ApiError(status_code=408, body=run, message="Timed out waiting for run")
|
|
33
|
+
time.sleep(poll_interval)
|
|
34
|
+
|
|
35
|
+
def _json(self, res: httpx.Response) -> Dict[str, Any]:
|
|
36
|
+
if res.status_code in (401, 403):
|
|
37
|
+
raise AuthenticationError(status_code=res.status_code, body=_safe_json(res), message="Unauthorized")
|
|
38
|
+
if res.status_code == 429:
|
|
39
|
+
err = RateLimitError(status_code=429, body=_safe_json(res), message="Rate limited")
|
|
40
|
+
err.retry_after = res.headers.get("Retry-After")
|
|
41
|
+
raise err
|
|
42
|
+
if res.status_code < 200 or res.status_code >= 300:
|
|
43
|
+
raise ApiError(status_code=res.status_code, body=_safe_json(res))
|
|
44
|
+
data = _safe_json(res)
|
|
45
|
+
return data if isinstance(data, dict) else {"data": data}
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _safe_json(res: httpx.Response) -> Any:
|
|
49
|
+
try:
|
|
50
|
+
return res.json()
|
|
51
|
+
except Exception:
|
|
52
|
+
return res.text
|