stan-ai-client 0.1.1__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.
- stan_ai_client-0.1.1/LICENSE +22 -0
- stan_ai_client-0.1.1/PKG-INFO +303 -0
- stan_ai_client-0.1.1/README.md +283 -0
- stan_ai_client-0.1.1/pyproject.toml +49 -0
- stan_ai_client-0.1.1/setup.cfg +4 -0
- stan_ai_client-0.1.1/src/stan_ai_client/__init__.py +48 -0
- stan_ai_client-0.1.1/src/stan_ai_client/_version.py +90 -0
- stan_ai_client-0.1.1/src/stan_ai_client/client.py +597 -0
- stan_ai_client-0.1.1/src/stan_ai_client/exceptions.py +105 -0
- stan_ai_client-0.1.1/src/stan_ai_client/parser.py +37 -0
- stan_ai_client-0.1.1/src/stan_ai_client/py.typed +1 -0
- stan_ai_client-0.1.1/src/stan_ai_client/rate_limits.py +167 -0
- stan_ai_client-0.1.1/src/stan_ai_client/schema.py +46 -0
- stan_ai_client-0.1.1/src/stan_ai_client/transport.py +27 -0
- stan_ai_client-0.1.1/src/stan_ai_client/types.py +143 -0
- stan_ai_client-0.1.1/src/stan_ai_client.egg-info/PKG-INFO +303 -0
- stan_ai_client-0.1.1/src/stan_ai_client.egg-info/SOURCES.txt +23 -0
- stan_ai_client-0.1.1/src/stan_ai_client.egg-info/dependency_links.txt +1 -0
- stan_ai_client-0.1.1/src/stan_ai_client.egg-info/requires.txt +7 -0
- stan_ai_client-0.1.1/src/stan_ai_client.egg-info/top_level.txt +1 -0
- stan_ai_client-0.1.1/tests/test_client.py +406 -0
- stan_ai_client-0.1.1/tests/test_parser.py +28 -0
- stan_ai_client-0.1.1/tests/test_rate_limits.py +32 -0
- stan_ai_client-0.1.1/tests/test_schema.py +25 -0
- stan_ai_client-0.1.1/tests/test_versioning.py +55 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Stanislav Kozlovski
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: stan-ai-client
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Thin Python client for running Claude Code via the local claude executable.
|
|
5
|
+
Author: Stanislav Kozlovski
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/stanislavkozlovski/stan_ai_client
|
|
8
|
+
Project-URL: Repository, https://github.com/stanislavkozlovski/stan_ai_client
|
|
9
|
+
Project-URL: Issues, https://github.com/stanislavkozlovski/stan_ai_client/issues
|
|
10
|
+
Requires-Python: >=3.11
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: jsonschema>=4.0
|
|
14
|
+
Provides-Extra: dev
|
|
15
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
16
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
17
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
18
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
19
|
+
Dynamic: license-file
|
|
20
|
+
|
|
21
|
+
# stan_ai_client
|
|
22
|
+
|
|
23
|
+
`stan_ai_client` is a thin Python wrapper around the local `claude` executable.
|
|
24
|
+
|
|
25
|
+
It does not call Anthropic APIs directly. Claude Code must already be installed and authenticated on the machine.
|
|
26
|
+
|
|
27
|
+
The library is intentionally small and pragmatic:
|
|
28
|
+
|
|
29
|
+
- `run_text()` for plain-text Claude output
|
|
30
|
+
- `run_json()` for `--output-format json`
|
|
31
|
+
- `run_structured()` for schema-validated structured output
|
|
32
|
+
- typed results
|
|
33
|
+
- structured exceptions
|
|
34
|
+
- local JSON Schema validation
|
|
35
|
+
- rate-limit parsing helpers
|
|
36
|
+
- stdlib logging
|
|
37
|
+
|
|
38
|
+
## Why Use It
|
|
39
|
+
|
|
40
|
+
Use `stan_ai_client` when you want:
|
|
41
|
+
|
|
42
|
+
- a small Python API on top of Claude Code
|
|
43
|
+
- text mode and JSON mode without hand-rolling subprocess logic
|
|
44
|
+
- strongly guided structured output with local validation
|
|
45
|
+
- command metadata, typed JSON payloads, and normalized exceptions
|
|
46
|
+
- safe-by-default prompt logging behavior
|
|
47
|
+
- local automation that already depends on Claude Code being installed
|
|
48
|
+
|
|
49
|
+
Typical use cases:
|
|
50
|
+
|
|
51
|
+
- article summarization
|
|
52
|
+
- tagging or YAML generation
|
|
53
|
+
- one-shot repository or directory analysis
|
|
54
|
+
- local scripts that need Claude session metadata, cost, or duration
|
|
55
|
+
|
|
56
|
+
It is not a replacement for the Anthropic API SDK, and it is not trying to abstract multiple providers.
|
|
57
|
+
|
|
58
|
+
## Install
|
|
59
|
+
|
|
60
|
+
### From PyPI
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install stan-ai-client
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### From a local checkout
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
python3 -m venv .venv
|
|
70
|
+
source .venv/bin/activate
|
|
71
|
+
pip install -e ".[dev]"
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### From GitHub
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pip install "git+https://github.com/<your-user>/stan_ai_client.git"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Releases
|
|
81
|
+
|
|
82
|
+
- the package version lives in `pyproject.toml`
|
|
83
|
+
- every non-bot push or merge to `main` bumps patch automatically
|
|
84
|
+
- tags use `vX.Y.Z`
|
|
85
|
+
- `main` releases build and publish to PyPI automatically
|
|
86
|
+
- release commits are created by GitHub Actions as `chore: release vX.Y.Z [skip ci]`
|
|
87
|
+
|
|
88
|
+
## Quickstart
|
|
89
|
+
|
|
90
|
+
### 1. Install Claude Code
|
|
91
|
+
|
|
92
|
+
Make sure `claude` is already available on your machine and authenticated:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
claude --version
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 2. Run the smoke test
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
python examples/smoke_test.py
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
That runs one text-mode call and one JSON-mode call.
|
|
105
|
+
|
|
106
|
+
## Minimal Usage
|
|
107
|
+
|
|
108
|
+
### Text mode
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from stan_ai_client import ClaudeCodeClient
|
|
112
|
+
|
|
113
|
+
client = ClaudeCodeClient()
|
|
114
|
+
result = client.run_text("Reply with the single word: ok")
|
|
115
|
+
print(result.text)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### JSON mode
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
from pathlib import Path
|
|
122
|
+
|
|
123
|
+
from stan_ai_client import ClaudeCodeClient, RunOptions
|
|
124
|
+
|
|
125
|
+
client = ClaudeCodeClient(
|
|
126
|
+
default_model="claude-opus-4-6",
|
|
127
|
+
default_effort="max",
|
|
128
|
+
default_timeout_seconds=180,
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
result = client.run_json(
|
|
132
|
+
"Summarize this article.",
|
|
133
|
+
options=RunOptions(
|
|
134
|
+
cwd=Path("."),
|
|
135
|
+
allowed_tools=("Read", "Glob", "Grep", "Bash"),
|
|
136
|
+
),
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
print(result.payload.result)
|
|
140
|
+
print(result.payload.total_cost_usd)
|
|
141
|
+
print(result.payload.session_id)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Structured mode
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
from stan_ai_client import ClaudeCodeClient, StructuredSchema
|
|
148
|
+
|
|
149
|
+
client = ClaudeCodeClient()
|
|
150
|
+
|
|
151
|
+
schema = StructuredSchema.from_dict(
|
|
152
|
+
{
|
|
153
|
+
"type": "object",
|
|
154
|
+
"properties": {
|
|
155
|
+
"summary": {"type": "string"},
|
|
156
|
+
"tags": {"type": "array", "items": {"type": "string"}},
|
|
157
|
+
},
|
|
158
|
+
"required": ["summary", "tags"],
|
|
159
|
+
"additionalProperties": False,
|
|
160
|
+
}
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
result = client.run_structured(
|
|
164
|
+
"Summarize this article and return tags.",
|
|
165
|
+
schema=schema,
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
print(result.structured_output["summary"])
|
|
169
|
+
print(result.payload.session_id)
|
|
170
|
+
print(result.payload.total_cost_usd)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`run_structured()` validates the schema before Claude runs, requires `structured_output` in the response, and validates the returned object locally against the same schema.
|
|
174
|
+
|
|
175
|
+
### Logging
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
import logging
|
|
179
|
+
|
|
180
|
+
from stan_ai_client import ClaudeCodeClient
|
|
181
|
+
|
|
182
|
+
logging.basicConfig(level=logging.INFO)
|
|
183
|
+
logger = logging.getLogger("my_app.claude")
|
|
184
|
+
|
|
185
|
+
client = ClaudeCodeClient(
|
|
186
|
+
logger=logger,
|
|
187
|
+
log_prompts=False,
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
client.run_text("Reply with the single word: ok")
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
By default, logging includes execution metadata, not full prompt text. Set `log_prompts=True` only if you explicitly want prompts written to logs.
|
|
194
|
+
|
|
195
|
+
### Error handling
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
from stan_ai_client import ClaudeCodeClient, ClaudeRateLimitError
|
|
199
|
+
|
|
200
|
+
client = ClaudeCodeClient()
|
|
201
|
+
|
|
202
|
+
try:
|
|
203
|
+
result = client.run_json("Summarize this repository.")
|
|
204
|
+
except ClaudeRateLimitError as exc:
|
|
205
|
+
print(exc.rate_limit.retry_after_seconds)
|
|
206
|
+
print(exc.rate_limit.reset_at)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Public Surface
|
|
210
|
+
|
|
211
|
+
Top-level exports:
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
from stan_ai_client import (
|
|
215
|
+
__version__,
|
|
216
|
+
ClaudeCodeClient,
|
|
217
|
+
RunOptions,
|
|
218
|
+
TextRunResult,
|
|
219
|
+
JsonRunResult,
|
|
220
|
+
StructuredRunResult,
|
|
221
|
+
ClaudeJsonPayload,
|
|
222
|
+
CommandMetadata,
|
|
223
|
+
StructuredSchema,
|
|
224
|
+
ClaudeCodeError,
|
|
225
|
+
ClaudeExecutableNotFoundError,
|
|
226
|
+
ClaudeTimeoutError,
|
|
227
|
+
ClaudeProcessError,
|
|
228
|
+
ClaudeProtocolError,
|
|
229
|
+
ClaudeRateLimitError,
|
|
230
|
+
ClaudeSchemaValidationError,
|
|
231
|
+
ClaudeStructuredOutputMissingError,
|
|
232
|
+
ClaudeStructuredOutputValidationError,
|
|
233
|
+
RateLimitInfo,
|
|
234
|
+
parse_rate_limit_info,
|
|
235
|
+
)
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
## Supported Features
|
|
239
|
+
|
|
240
|
+
- text mode via `run_text()`
|
|
241
|
+
- JSON mode via `run_json()`
|
|
242
|
+
- structured mode via `run_structured()`
|
|
243
|
+
- prompts sent over stdin by default
|
|
244
|
+
- optional argv prompt mode
|
|
245
|
+
- per-call working directory control
|
|
246
|
+
- model, effort, timeout, environment, and session controls
|
|
247
|
+
- support for Claude CLI flags via typed `RunOptions`
|
|
248
|
+
- raw stdout and stderr preserved on results and errors
|
|
249
|
+
- opt-in stdlib logging with safe default prompt handling
|
|
250
|
+
- typed JSON payload parsing with unknown fields preserved in `extras`
|
|
251
|
+
- local input and output validation for structured mode
|
|
252
|
+
- rate-limit detection and reset-time parsing
|
|
253
|
+
|
|
254
|
+
## Examples
|
|
255
|
+
|
|
256
|
+
- [examples/smoke_test.py](./examples/smoke_test.py)
|
|
257
|
+
- [examples/summarize_article.py](./examples/summarize_article.py)
|
|
258
|
+
- [examples/tag_article.py](./examples/tag_article.py)
|
|
259
|
+
- [examples/logging_demo.py](./examples/logging_demo.py)
|
|
260
|
+
|
|
261
|
+
## Documentation
|
|
262
|
+
|
|
263
|
+
See [DOCS.md](./DOCS.md) for:
|
|
264
|
+
|
|
265
|
+
- full `RunOptions` reference
|
|
266
|
+
- logging behavior
|
|
267
|
+
- result types
|
|
268
|
+
- structured output usage
|
|
269
|
+
- exception model
|
|
270
|
+
- rate-limit handling
|
|
271
|
+
- session usage
|
|
272
|
+
- common patterns
|
|
273
|
+
- current limitations
|
|
274
|
+
- maintainer release flow
|
|
275
|
+
|
|
276
|
+
## Notes
|
|
277
|
+
|
|
278
|
+
- prompts default to stdin instead of argv
|
|
279
|
+
- JSON mode always requests `--output-format json`
|
|
280
|
+
- structured mode always requests `--output-format json` and `--json-schema`
|
|
281
|
+
- text mode always requests `--output-format text`
|
|
282
|
+
- logging uses stdlib `logging`
|
|
283
|
+
- prompts are not written to logs unless `log_prompts=True`
|
|
284
|
+
- the library is sync-only in `0.1.x`
|
|
285
|
+
- streaming is intentionally out of scope right now
|
|
286
|
+
|
|
287
|
+
## Current Limitations
|
|
288
|
+
|
|
289
|
+
- no streaming support
|
|
290
|
+
- no async API
|
|
291
|
+
- no built-in retry loop
|
|
292
|
+
- no standalone CLI wrapper command
|
|
293
|
+
- no first-class typed wrapper yet for every Claude Code flag
|
|
294
|
+
- structured mode accepts dict-backed JSON Schema objects only
|
|
295
|
+
|
|
296
|
+
For unsupported Claude Code flags, use `RunOptions(extra_args=...)`.
|
|
297
|
+
|
|
298
|
+
## Development
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
pytest
|
|
302
|
+
mypy src tests
|
|
303
|
+
```
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# stan_ai_client
|
|
2
|
+
|
|
3
|
+
`stan_ai_client` is a thin Python wrapper around the local `claude` executable.
|
|
4
|
+
|
|
5
|
+
It does not call Anthropic APIs directly. Claude Code must already be installed and authenticated on the machine.
|
|
6
|
+
|
|
7
|
+
The library is intentionally small and pragmatic:
|
|
8
|
+
|
|
9
|
+
- `run_text()` for plain-text Claude output
|
|
10
|
+
- `run_json()` for `--output-format json`
|
|
11
|
+
- `run_structured()` for schema-validated structured output
|
|
12
|
+
- typed results
|
|
13
|
+
- structured exceptions
|
|
14
|
+
- local JSON Schema validation
|
|
15
|
+
- rate-limit parsing helpers
|
|
16
|
+
- stdlib logging
|
|
17
|
+
|
|
18
|
+
## Why Use It
|
|
19
|
+
|
|
20
|
+
Use `stan_ai_client` when you want:
|
|
21
|
+
|
|
22
|
+
- a small Python API on top of Claude Code
|
|
23
|
+
- text mode and JSON mode without hand-rolling subprocess logic
|
|
24
|
+
- strongly guided structured output with local validation
|
|
25
|
+
- command metadata, typed JSON payloads, and normalized exceptions
|
|
26
|
+
- safe-by-default prompt logging behavior
|
|
27
|
+
- local automation that already depends on Claude Code being installed
|
|
28
|
+
|
|
29
|
+
Typical use cases:
|
|
30
|
+
|
|
31
|
+
- article summarization
|
|
32
|
+
- tagging or YAML generation
|
|
33
|
+
- one-shot repository or directory analysis
|
|
34
|
+
- local scripts that need Claude session metadata, cost, or duration
|
|
35
|
+
|
|
36
|
+
It is not a replacement for the Anthropic API SDK, and it is not trying to abstract multiple providers.
|
|
37
|
+
|
|
38
|
+
## Install
|
|
39
|
+
|
|
40
|
+
### From PyPI
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install stan-ai-client
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### From a local checkout
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
python3 -m venv .venv
|
|
50
|
+
source .venv/bin/activate
|
|
51
|
+
pip install -e ".[dev]"
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### From GitHub
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
pip install "git+https://github.com/<your-user>/stan_ai_client.git"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Releases
|
|
61
|
+
|
|
62
|
+
- the package version lives in `pyproject.toml`
|
|
63
|
+
- every non-bot push or merge to `main` bumps patch automatically
|
|
64
|
+
- tags use `vX.Y.Z`
|
|
65
|
+
- `main` releases build and publish to PyPI automatically
|
|
66
|
+
- release commits are created by GitHub Actions as `chore: release vX.Y.Z [skip ci]`
|
|
67
|
+
|
|
68
|
+
## Quickstart
|
|
69
|
+
|
|
70
|
+
### 1. Install Claude Code
|
|
71
|
+
|
|
72
|
+
Make sure `claude` is already available on your machine and authenticated:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
claude --version
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 2. Run the smoke test
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
python examples/smoke_test.py
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
That runs one text-mode call and one JSON-mode call.
|
|
85
|
+
|
|
86
|
+
## Minimal Usage
|
|
87
|
+
|
|
88
|
+
### Text mode
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from stan_ai_client import ClaudeCodeClient
|
|
92
|
+
|
|
93
|
+
client = ClaudeCodeClient()
|
|
94
|
+
result = client.run_text("Reply with the single word: ok")
|
|
95
|
+
print(result.text)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### JSON mode
|
|
99
|
+
|
|
100
|
+
```python
|
|
101
|
+
from pathlib import Path
|
|
102
|
+
|
|
103
|
+
from stan_ai_client import ClaudeCodeClient, RunOptions
|
|
104
|
+
|
|
105
|
+
client = ClaudeCodeClient(
|
|
106
|
+
default_model="claude-opus-4-6",
|
|
107
|
+
default_effort="max",
|
|
108
|
+
default_timeout_seconds=180,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
result = client.run_json(
|
|
112
|
+
"Summarize this article.",
|
|
113
|
+
options=RunOptions(
|
|
114
|
+
cwd=Path("."),
|
|
115
|
+
allowed_tools=("Read", "Glob", "Grep", "Bash"),
|
|
116
|
+
),
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
print(result.payload.result)
|
|
120
|
+
print(result.payload.total_cost_usd)
|
|
121
|
+
print(result.payload.session_id)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Structured mode
|
|
125
|
+
|
|
126
|
+
```python
|
|
127
|
+
from stan_ai_client import ClaudeCodeClient, StructuredSchema
|
|
128
|
+
|
|
129
|
+
client = ClaudeCodeClient()
|
|
130
|
+
|
|
131
|
+
schema = StructuredSchema.from_dict(
|
|
132
|
+
{
|
|
133
|
+
"type": "object",
|
|
134
|
+
"properties": {
|
|
135
|
+
"summary": {"type": "string"},
|
|
136
|
+
"tags": {"type": "array", "items": {"type": "string"}},
|
|
137
|
+
},
|
|
138
|
+
"required": ["summary", "tags"],
|
|
139
|
+
"additionalProperties": False,
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
result = client.run_structured(
|
|
144
|
+
"Summarize this article and return tags.",
|
|
145
|
+
schema=schema,
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
print(result.structured_output["summary"])
|
|
149
|
+
print(result.payload.session_id)
|
|
150
|
+
print(result.payload.total_cost_usd)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`run_structured()` validates the schema before Claude runs, requires `structured_output` in the response, and validates the returned object locally against the same schema.
|
|
154
|
+
|
|
155
|
+
### Logging
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
import logging
|
|
159
|
+
|
|
160
|
+
from stan_ai_client import ClaudeCodeClient
|
|
161
|
+
|
|
162
|
+
logging.basicConfig(level=logging.INFO)
|
|
163
|
+
logger = logging.getLogger("my_app.claude")
|
|
164
|
+
|
|
165
|
+
client = ClaudeCodeClient(
|
|
166
|
+
logger=logger,
|
|
167
|
+
log_prompts=False,
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
client.run_text("Reply with the single word: ok")
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
By default, logging includes execution metadata, not full prompt text. Set `log_prompts=True` only if you explicitly want prompts written to logs.
|
|
174
|
+
|
|
175
|
+
### Error handling
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
from stan_ai_client import ClaudeCodeClient, ClaudeRateLimitError
|
|
179
|
+
|
|
180
|
+
client = ClaudeCodeClient()
|
|
181
|
+
|
|
182
|
+
try:
|
|
183
|
+
result = client.run_json("Summarize this repository.")
|
|
184
|
+
except ClaudeRateLimitError as exc:
|
|
185
|
+
print(exc.rate_limit.retry_after_seconds)
|
|
186
|
+
print(exc.rate_limit.reset_at)
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Public Surface
|
|
190
|
+
|
|
191
|
+
Top-level exports:
|
|
192
|
+
|
|
193
|
+
```python
|
|
194
|
+
from stan_ai_client import (
|
|
195
|
+
__version__,
|
|
196
|
+
ClaudeCodeClient,
|
|
197
|
+
RunOptions,
|
|
198
|
+
TextRunResult,
|
|
199
|
+
JsonRunResult,
|
|
200
|
+
StructuredRunResult,
|
|
201
|
+
ClaudeJsonPayload,
|
|
202
|
+
CommandMetadata,
|
|
203
|
+
StructuredSchema,
|
|
204
|
+
ClaudeCodeError,
|
|
205
|
+
ClaudeExecutableNotFoundError,
|
|
206
|
+
ClaudeTimeoutError,
|
|
207
|
+
ClaudeProcessError,
|
|
208
|
+
ClaudeProtocolError,
|
|
209
|
+
ClaudeRateLimitError,
|
|
210
|
+
ClaudeSchemaValidationError,
|
|
211
|
+
ClaudeStructuredOutputMissingError,
|
|
212
|
+
ClaudeStructuredOutputValidationError,
|
|
213
|
+
RateLimitInfo,
|
|
214
|
+
parse_rate_limit_info,
|
|
215
|
+
)
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Supported Features
|
|
219
|
+
|
|
220
|
+
- text mode via `run_text()`
|
|
221
|
+
- JSON mode via `run_json()`
|
|
222
|
+
- structured mode via `run_structured()`
|
|
223
|
+
- prompts sent over stdin by default
|
|
224
|
+
- optional argv prompt mode
|
|
225
|
+
- per-call working directory control
|
|
226
|
+
- model, effort, timeout, environment, and session controls
|
|
227
|
+
- support for Claude CLI flags via typed `RunOptions`
|
|
228
|
+
- raw stdout and stderr preserved on results and errors
|
|
229
|
+
- opt-in stdlib logging with safe default prompt handling
|
|
230
|
+
- typed JSON payload parsing with unknown fields preserved in `extras`
|
|
231
|
+
- local input and output validation for structured mode
|
|
232
|
+
- rate-limit detection and reset-time parsing
|
|
233
|
+
|
|
234
|
+
## Examples
|
|
235
|
+
|
|
236
|
+
- [examples/smoke_test.py](./examples/smoke_test.py)
|
|
237
|
+
- [examples/summarize_article.py](./examples/summarize_article.py)
|
|
238
|
+
- [examples/tag_article.py](./examples/tag_article.py)
|
|
239
|
+
- [examples/logging_demo.py](./examples/logging_demo.py)
|
|
240
|
+
|
|
241
|
+
## Documentation
|
|
242
|
+
|
|
243
|
+
See [DOCS.md](./DOCS.md) for:
|
|
244
|
+
|
|
245
|
+
- full `RunOptions` reference
|
|
246
|
+
- logging behavior
|
|
247
|
+
- result types
|
|
248
|
+
- structured output usage
|
|
249
|
+
- exception model
|
|
250
|
+
- rate-limit handling
|
|
251
|
+
- session usage
|
|
252
|
+
- common patterns
|
|
253
|
+
- current limitations
|
|
254
|
+
- maintainer release flow
|
|
255
|
+
|
|
256
|
+
## Notes
|
|
257
|
+
|
|
258
|
+
- prompts default to stdin instead of argv
|
|
259
|
+
- JSON mode always requests `--output-format json`
|
|
260
|
+
- structured mode always requests `--output-format json` and `--json-schema`
|
|
261
|
+
- text mode always requests `--output-format text`
|
|
262
|
+
- logging uses stdlib `logging`
|
|
263
|
+
- prompts are not written to logs unless `log_prompts=True`
|
|
264
|
+
- the library is sync-only in `0.1.x`
|
|
265
|
+
- streaming is intentionally out of scope right now
|
|
266
|
+
|
|
267
|
+
## Current Limitations
|
|
268
|
+
|
|
269
|
+
- no streaming support
|
|
270
|
+
- no async API
|
|
271
|
+
- no built-in retry loop
|
|
272
|
+
- no standalone CLI wrapper command
|
|
273
|
+
- no first-class typed wrapper yet for every Claude Code flag
|
|
274
|
+
- structured mode accepts dict-backed JSON Schema objects only
|
|
275
|
+
|
|
276
|
+
For unsupported Claude Code flags, use `RunOptions(extra_args=...)`.
|
|
277
|
+
|
|
278
|
+
## Development
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
pytest
|
|
282
|
+
mypy src tests
|
|
283
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "stan-ai-client"
|
|
7
|
+
version = "0.1.1"
|
|
8
|
+
description = "Thin Python client for running Claude Code via the local claude executable."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Stanislav Kozlovski"},
|
|
14
|
+
]
|
|
15
|
+
dependencies = [
|
|
16
|
+
"jsonschema>=4.0",
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[project.urls]
|
|
20
|
+
Homepage = "https://github.com/stanislavkozlovski/stan_ai_client"
|
|
21
|
+
Repository = "https://github.com/stanislavkozlovski/stan_ai_client"
|
|
22
|
+
Issues = "https://github.com/stanislavkozlovski/stan_ai_client/issues"
|
|
23
|
+
|
|
24
|
+
[project.optional-dependencies]
|
|
25
|
+
dev = [
|
|
26
|
+
"build>=1.2",
|
|
27
|
+
"mypy>=1.10",
|
|
28
|
+
"pytest>=8.0",
|
|
29
|
+
"ruff>=0.5",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[tool.setuptools]
|
|
33
|
+
package-dir = {"" = "src"}
|
|
34
|
+
|
|
35
|
+
[tool.setuptools.packages.find]
|
|
36
|
+
where = ["src"]
|
|
37
|
+
|
|
38
|
+
[tool.pytest.ini_options]
|
|
39
|
+
testpaths = ["tests"]
|
|
40
|
+
pythonpath = ["src"]
|
|
41
|
+
|
|
42
|
+
[tool.mypy]
|
|
43
|
+
python_version = "3.11"
|
|
44
|
+
strict = true
|
|
45
|
+
warn_unused_configs = true
|
|
46
|
+
|
|
47
|
+
[[tool.mypy.overrides]]
|
|
48
|
+
module = ["jsonschema", "jsonschema.*"]
|
|
49
|
+
ignore_missing_imports = true
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
from ._version import get_version
|
|
2
|
+
from .client import ClaudeCodeClient
|
|
3
|
+
from .exceptions import (
|
|
4
|
+
ClaudeCodeError,
|
|
5
|
+
ClaudeExecutableNotFoundError,
|
|
6
|
+
ClaudeProcessError,
|
|
7
|
+
ClaudeProtocolError,
|
|
8
|
+
ClaudeRateLimitError,
|
|
9
|
+
ClaudeSchemaValidationError,
|
|
10
|
+
ClaudeStructuredOutputMissingError,
|
|
11
|
+
ClaudeStructuredOutputValidationError,
|
|
12
|
+
ClaudeTimeoutError,
|
|
13
|
+
)
|
|
14
|
+
from .rate_limits import RateLimitInfo, parse_rate_limit_info
|
|
15
|
+
from .schema import StructuredSchema
|
|
16
|
+
from .types import (
|
|
17
|
+
ClaudeJsonPayload,
|
|
18
|
+
CommandMetadata,
|
|
19
|
+
JsonRunResult,
|
|
20
|
+
RunOptions,
|
|
21
|
+
StructuredRunResult,
|
|
22
|
+
TextRunResult,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
__version__ = get_version()
|
|
26
|
+
|
|
27
|
+
__all__ = [
|
|
28
|
+
"__version__",
|
|
29
|
+
"ClaudeCodeClient",
|
|
30
|
+
"ClaudeCodeError",
|
|
31
|
+
"ClaudeExecutableNotFoundError",
|
|
32
|
+
"ClaudeJsonPayload",
|
|
33
|
+
"ClaudeProcessError",
|
|
34
|
+
"ClaudeProtocolError",
|
|
35
|
+
"ClaudeRateLimitError",
|
|
36
|
+
"ClaudeSchemaValidationError",
|
|
37
|
+
"ClaudeStructuredOutputMissingError",
|
|
38
|
+
"ClaudeStructuredOutputValidationError",
|
|
39
|
+
"ClaudeTimeoutError",
|
|
40
|
+
"CommandMetadata",
|
|
41
|
+
"JsonRunResult",
|
|
42
|
+
"RateLimitInfo",
|
|
43
|
+
"RunOptions",
|
|
44
|
+
"StructuredRunResult",
|
|
45
|
+
"StructuredSchema",
|
|
46
|
+
"TextRunResult",
|
|
47
|
+
"parse_rate_limit_info",
|
|
48
|
+
]
|