Metadata-Version: 2.5
Name: frootai-orchard
Version: 1.0.0
Summary: Programmatic SDK for the FrootAI Orchard catalog — type-safe list/search/show/bushel surface for partner apps, CI pipelines, and BI integrations. Reads the same ~/.frootai/.token + ~/.frootai/cache as the frootai CLI for transparent shared auth.
Project-URL: Homepage, https://frootai.dev/orchard
Project-URL: Repository, https://github.com/frootai/frootai-core
Project-URL: Issues, https://github.com/frootai/frootai-core/issues
Project-URL: Changelog, https://github.com/frootai/frootai-core/blob/main/python-sdk/orchard/CHANGELOG.md
Author-email: FrootAI <hello@frootai.dev>
License: MIT
Keywords: accelerators,ai-agents,catalog,frootai,orchard,sdk,solution-plays
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown

# frootai-orchard

Programmatic Python SDK for the FrootAI Orchard catalog — type-safe `list` / `search` / `show` / `bushel` surface for partner apps, CI pipelines, and BI integrations.

Byte-equal contract with the npm `@frootai/orchard` v1.0.0 SDK: same enums, same filter expression language, same HMAC-signed pagination cursors, same retry semantics, same shared `~/.frootai/.token` auth file. A query that returns 12 results in JS returns the same 12 results in Python.

## Install

```bash
pip install frootai-orchard
```

Zero runtime dependencies. Python 3.10+. Stdlib only (`urllib`, `hmac`, `base64`, `json`, `hashlib`, `pathlib`).

## Quickstart

```python
from frootai_orchard import create_client

client = create_client()

# Anonymous catalog reads — no auth required
for fruit in client.list(variety="azure", where="ripeness:Mature OR ripeness:Bearing"):
    print(fruit["name"], "—", fruit.get("tagline", ""))

# Search with scoring
for hit in client.search("rag", limit=10):
    print(f'{hit["_score"]:>2}  {hit["name"]}')

# Single fruit detail
detail = client.show("ms-azure-openai-rag")

# Authenticated — bushel sync (Team tier+)
client.bushel.add("ms-azure-openai-rag")
print(client.bushel.list()["ids"])

# Never-raises auth probe
print(client.whoami())
# → {"signed_in": True, "anonymous": False, "redacted": "…a3f9", ...}
```

## Auth priority

1. `token=` keyword argument
2. `FROOTAI_TOKEN` environment variable
3. `~/.frootai/.token` shared file (same as the `frootai` CLI)

A `frootai login` in your terminal transparently authorizes Python SDK calls.

## Typed errors

Every public surface raises only `FrootaiOrchardError` subclasses — partners catch by type, never by string match:

```python
from frootai_orchard import errors as fai_err

try:
    client.bushel.add("some-fruit")
except fai_err.NotSignedInError:
    print("Run `frootai login` first")
except fai_err.EntitlementRequiredError as e:
    print(f'Upgrade required: {e.context["entitlement"]}')
except fai_err.RateLimitError as e:
    print(f"Slow down — retry after {e.retry_after_ms} ms")
```

## Filter expression language

Identical grammar to the npm SDK:

```python
client.list(where="tier_class:paid AND variety:azure")
client.list(where="ripeness:Mature OR (variety:gcp AND category:rag)")
client.list(where='NOT category:eval')
```

## License

MIT
