Skip to content

Commit a2e8d5e

Browse files
committed
docs: pre-merge sweep — version field, compare link, examples (#45)
Pre-merge cross-doc consistency pass: - AUDIT.md: add `**Version:** 0.4.0` to the new entry to match the format of the prior streaming entry. - CHANGELOG.md: add the `[0.4.0]` compare link at the bottom so the Keep-a-Changelog reference list stays complete. - runcycles/decorator.py: extend the docstring example block with a callable subject/action example so the rendered Sphinx/PyPI docs show the new feature, not just the existing estimate/actual pattern. - examples/decorator_usage.py: add a third decorator demonstrating per-call workspace + action_kind + action_name routing via lambdas. No code or test changes. Coverage 99.38% holds, mypy clean, ruff clean.
1 parent 93fea88 commit a2e8d5e

4 files changed

Lines changed: 30 additions & 0 deletions

File tree

AUDIT.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ Protocol conformance: No new endpoints or protocol changes. All reservation, com
213213
**Issue:** [#45](https://github.com/runcycles/cycles-client-python/issues/45)
214214
**Files:** `runcycles/lifecycle.py`, `runcycles/decorator.py`
215215
**Test files:** `tests/test_lifecycle.py`, `tests/test_decorator.py`
216+
**Version:** 0.4.0
216217

217218
Widened the `@cycles` decorator to accept callables — in addition to constants — for every field that previously had to be static at decoration time. Mirrors the existing `estimate` / `actual` callable contract and re-aligns the Python client with the Java client's `@Cycles(workspace = "#workspaceId")` SpEL behavior shipped in `cycles-spring-boot-starter` 0.2.1 ([java#50](https://github.com/runcycles/cycles-spring-boot-starter/pull/50)).
218219

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ Initial public release.
120120

121121
- Comprehensive error handling and improved API model validation (#1)
122122

123+
[0.4.0]: https://github.com/runcycles/cycles-client-python/compare/v0.3.0...v0.4.0
123124
[0.3.0]: https://github.com/runcycles/cycles-client-python/compare/v0.2.0...v0.3.0
124125
[0.2.0]: https://github.com/runcycles/cycles-client-python/compare/v0.1.3...v0.2.0
125126
[0.1.3]: https://github.com/runcycles/cycles-client-python/compare/v0.1.2...v0.1.3

examples/decorator_usage.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ def call_llm(prompt: str, tokens: int) -> str:
4949
return "Generated response for: " + prompt
5050

5151

52+
# Per-call subject / action routing via callables — resolved at reservation time
53+
# against the wrapped function's *args, **kwargs
54+
@cycles(
55+
estimate=1000,
56+
workspace=lambda req, workspace_id: workspace_id,
57+
action_kind=lambda req, *_: f"llm.{req['provider']}",
58+
action_name=lambda req, *_: req["model"],
59+
client=client,
60+
)
61+
def run_request(req: dict[str, str], workspace_id: str) -> str:
62+
return f"Routed {req['model']} to {workspace_id}"
63+
64+
5265
def main() -> None:
5366
print("Simple call:")
5467
result1 = simple_call()
@@ -58,6 +71,10 @@ def main() -> None:
5871
result2 = call_llm("Tell me a joke", tokens=200)
5972
print(f" Result: {result2}")
6073

74+
print("\nPer-call subject/action routing:")
75+
result3 = run_request({"provider": "openai", "model": "gpt-4"}, workspace_id="ws-42")
76+
print(f" Result: {result3}")
77+
6178

6279
if __name__ == "__main__":
6380
main()

runcycles/decorator.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,17 @@ def call_llm(prompt: str) -> str:
127127
)
128128
def call_llm(prompt: str, tokens: int) -> str:
129129
return openai.complete(prompt, max_tokens=tokens)
130+
131+
# Per-call subject/action routing via callables
132+
@cycles(
133+
estimate=1000,
134+
workspace=lambda req, workspace_id: workspace_id,
135+
action_kind=lambda req, *_: f"llm.{req.provider}",
136+
action_name=lambda req, *_: req.model,
137+
client=my_client,
138+
)
139+
def run_request(req: Request, workspace_id: str) -> Response:
140+
...
130141
"""
131142
unit_str = unit.value if isinstance(unit, Unit) else str(unit)
132143

0 commit comments

Comments
 (0)