Skip to content

Add SDK source, config, CI, and documentation#2

Merged
solwyn-ai merged 25 commits intomainfrom
sdk-extraction
Apr 10, 2026
Merged

Add SDK source, config, CI, and documentation#2
solwyn-ai merged 25 commits intomainfrom
sdk-extraction

Conversation

@solwyn-ai
Copy link
Copy Markdown
Owner

@solwyn-ai solwyn-ai commented Apr 9, 2026

Summary

Standalone Python SDK extracted from the Solwyn monorepo, fully configured for independent development, testing, and PyPI publishing.

The Solwyn SDK is a drop-in wrapper for OpenAI, Anthropic, and Google LLM clients that adds budget enforcement, circuit breaking, and usage tracking. It never sees customer prompts — the SDK only reports metadata (token counts, latency, model name) to the Solwyn API after each call. Pricing and budget logic live on the server, so pricing updates never require an SDK release.

What's in this repo

SDK source (src/solwyn/)

  • Solwyn / AsyncSolwyn — drop-in wrappers for sync and async provider clients
  • BudgetEnforcer — cloud budget check with local fallback + fail-open default
  • CircuitBreaker — local-only circuit breaker state machine with failover
  • MetadataReporter — non-blocking background queue (threading for sync, asyncio.create_task for async)
  • Provider adapters for OpenAI, Anthropic, Google — lazy-loaded via a registry
  • Stream wrappers that report usage after the stream completes without blocking the caller
  • Privacy firewall (_privacy.py) — the only module allowed to touch prompt content, enforced by structural tests

Testing (tests/)

  • 297 unit tests in tests/unit/ — all marked @pytest.mark.unit, run in CI with -m unit
  • 10 integration tests in tests/integration/ — auto-bootstraps test credentials via the API (signup → project creation → API key). CI opt-in via run-integration label or workflow_dispatch
  • 5 pytest markers registered: unit, integration, chaos, performance, stress
  • Full async coverage: AsyncBudgetEnforcer, AsyncMetadataReporter lifecycle, AsyncSolwyn non-streaming path
  • Structural tests for privacy (no prompt content logged), no-production-asserts (Python -O safe), and stream non-blocking behavior
  • BudgetCheckResponse.denied_by_period is required (no silent default=None) — contract drift fails loudly

Tooling

  • Makefilemake check, make test, make install-hooks as single entry points
  • scripts/pre-commit — runs make check (ruff + format + mypy strict)
  • GitHub Actions CI on Python 3.11/3.12 with -m unit filtering
  • PyPI publish workflow via OIDC trusted publishing
  • CLAUDE.md files at root, src/solwyn/, and tests/ for development context (excluded from the wheel)
  • Pydantic v2 throughout — ConfigDict, @model_validator, .model_dump()

Developer experience

make install          # install in dev mode
make install-hooks    # install pre-commit hook
make check            # lint + format + typecheck
make test             # run unit tests
make test-integration # run integration tests (needs API at localhost:8080)

Environment variable discovery for credentials (matches openai-python / stripe-python conventions):

export SOLWYN_API_KEY="sk_solwyn_..."
export SOLWYN_PROJECT_ID="proj_abc12345"
client = Solwyn(OpenAI())  # auto-loads from env

Test plan

  • make check passes (ruff + format + mypy strict)
  • uv run pytest tests/ -m unit passes (297 passed)
  • uv run pytest tests/ -m integration passes against local API (10 passed)
  • hatch build produces a clean wheel with no CLAUDE.md, no test files, no solwyn_shared
  • CI passes on this PR (Python 3.11 + 3.12)
  • pip install solwyn from wheel works in clean venv

solwyn-ai and others added 25 commits April 9, 2026 12:58
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copies vendored source (providers, budget, circuit breaker, client,
config, tokenizer, stream, reporter) and full test suite (303 tests).
Fixes mypy strict-mode issues not caught by monorepo config: list[Any]
type arg, cast() for __exit__ returns, tiktoken optional-import ignore,
and an unused type: ignore[override] on the Pydantic model_validator.
Adds mypy overrides for tiktoken (optional dependency, no stubs).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move all tests into tests/unit/ subdirectory following the testing
strategy docs. Add tests/integration/ with credential-bootstrapping
fixtures that auto-create a user/project via the API.

- Reorganize tests into tests/unit/ and tests/integration/
- Register all 5 pytest markers (unit, integration, chaos, perf, stress)
- Add @pytest.mark.unit to 6 unmarked test files
- Add @pytest.mark.unit + @pytest.mark.asyncio (proper order) to async methods
- Standardize anyio -> asyncio markers
- Fix import discipline in conftest (httpx to module top)
- Fix SDK_SRC paths for new directory depth
- Make BudgetCheckResponse.denied_by_period required (no silent default)
- Align all deny-scenario mocks with real API contract
- CI workflows now filter with -m unit; integration job is opt-in

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Cover the three critical async gaps identified in the coverage audit:

- AsyncBudgetEnforcer: check_budget (allow, deny-hard, deny-alert,
  fail-open), confirm_cost (success, error swallowing), close
- AsyncMetadataReporter: start/close lifecycle, batch sending,
  flush correctness, context manager protocol
- AsyncSolwyn: non-streaming call passthrough with confirm_cost

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create three CLAUDE.md files for Claude Code context:
- Root: project overview, commands, architecture, rules
- tests/: marker conventions, integration test setup, mocking patterns
- src/solwyn/: module map, provider notes, thread safety

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
v6 of these actions does not exist as a published release, causing
checkout path errors in the GitHub Actions runner.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Mirror core repo's pre-commit setup: scripts/pre-commit runs
`make check` (lint + format check + typecheck) before each commit.

Also fixes ruff format issues in 4 test files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove stale `# sdks/python/...` path comments from 4 files
left over from the monorepo extraction. Add uv.lock for
reproducible installs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ents

- Normalize SolwynConfig.model_config to use ConfigDict() (was plain dict)
- Remove monorepo provenance comments from docstrings
- Fix stale test path in _privacy.py (tests/unit/ prefix)
- Remove ../core reference from CLAUDE.md architecture diagram
- Move src/solwyn/CLAUDE.md to src/CLAUDE.md (exclude from wheel)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add hatch wheel exclude rule for CLAUDE.md instead of moving
the file out of the package directory. Developers get the
context file; end users don't get it in their install.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove monorepo-specific rule (no solwyn_api imports), add Pydantic v2
rule, switch commands to Makefile targets.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move 8 provider proxy classes from client.py into _proxies.py to
improve readability. client.py drops from 750 to 617 lines, with
the core interception logic now easier to follow.

Add comment in _types.py explaining why TokenDetails lives in a
separate module (circular-import avoidance).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Align with the GitHub account email. Replaces dev@solwyn.io
in pyproject.toml authors and SECURITY.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add badges (CI, PyPI, Python versions, license)
- Fix quickstart to include required api_key/project_id kwargs
- Add provider-specific examples (OpenAI, Anthropic, Google)
- Add async, streaming, and budget enforcement sections
- Add configuration table with all env vars
- Add error handling reference
- Add contributing section with make commands
- Keep data transparency table

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Make api_key and project_id optional on both Solwyn and AsyncSolwyn
constructors. When omitted, SolwynConfig loads them from SOLWYN_API_KEY
and SOLWYN_PROJECT_ID environment variables — matching the convention
used by openai-python and stripe-python.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tie the publish job to a GitHub 'pypi' environment. Required to match
the PyPI trusted publisher config and enables protection rules + a
deployment history page on GitHub.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Not using a GitHub environment for the trusted publisher config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Ties the publish job to a GitHub 'pypi' environment for release
protection. Pair with a 'required reviewer' rule to add a manual
approval gate before any PyPI publish.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@solwyn-ai solwyn-ai merged commit 4502211 into main Apr 10, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant