Metadata-Version: 2.4
Name: askfaro
Version: 0.1.0
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: Implementation :: CPython
Requires-Dist: httpx>=0.28.0
Requires-Dist: pytest>=8.0.0 ; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.24.0 ; extra == 'dev'
Requires-Dist: respx>=0.22.0 ; extra == 'dev'
Provides-Extra: dev
License-File: LICENSE
Summary: Faro SDK: run free Faro tools on-device via the bundled Rust core, fall back to the API for the rest. Local and remote results share the identical envelope.
License: MIT
Requires-Python: >=3.9
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# askfaro

The Faro Python SDK. **Local-first**: tools the bundled Rust core can run execute
on-device — no API key, no network, no credits. Everything else falls back to the
Faro backend. Local and remote results share the identical canonical envelope, so
the same code path works whether a tool ran on your machine or in the cloud.

```bash
pip install askfaro
```

```python
from faro import Faro

faro = Faro()                                    # no key needed for on-device tools
r = faro.invoke("calc/evaluate", {"expression": "2 + 2 * 3"})
assert r.ok and r.local and r.data["result"] == 8

faro = Faro(api_key="faro_...")                  # a key enables backend fallback
faro.invoke("weather/current", {"city": "Paris"})    # -> backend (vendor-backed)
```

The Rust core is compiled into this package (`faro._core`), so a single
`pip install askfaro` is all you need — there is no separate core package to
install.

## Routing

`Faro(mode=...)` (per-call override on `invoke(..., mode=...)`):

| mode | behavior |
|------|----------|
| `auto` (default) | run on-device when the core can; otherwise call the backend |
| `local` | on-device only; raise `LocalUnavailableError` if the core can't run it |
| `remote` | always call the backend |

What can run on-device is the bundled core's own capability list
(`Faro.local_namespaces()`), not a pricing flag — it grows as more tools are
ported into the core. A vendor-backed tool (weather, web search, …) physically
needs the backend and always routes remote.

## What's bundled

`faro._core` is the MIT open-source free-tool slice of the Faro core (the
`faro-core-free` Rust crate): calc, units, phone, astronomy, encoding, datetime,
timezone, random — plus the canonical envelope builders. The proprietary parts of
Faro (selection gate, signed continuations, cloud client, billing) are NOT in this
package; vendor-backed tools run server-side via the API.

## Development

This is a [maturin](https://www.maturin.rs) mixed Rust/Python project:

- `python/faro/` — the pure-Python SDK (routing, client, result types)
- `src/lib.rs` — the PyO3 binding that builds the `faro._core` extension from the
  `faro-core-free` crate

```bash
maturin develop        # build faro._core and install faro editable
pytest                 # 16 tests, no network
```

Published wheels are prebuilt (manylinux + macOS universal2), so end users install
with no Rust toolchain.

