Metadata-Version: 2.4
Name: lithora
Version: 0.1.0
Summary: Official Python SDK for the Lithora REST API (teams, projects, tasks, work graph, AI workspace).
Author-email: Lithora <support@lithora.io>
License-Expression: MIT
Project-URL: Homepage, https://lithora.io
Project-URL: Documentation, https://github.com/AADI0009/SaaS-App/tree/main/sdk/python
Project-URL: Repository, https://github.com/AADI0009/SaaS-App
Project-URL: Issues, https://github.com/AADI0009/SaaS-App/issues
Project-URL: API, https://api.lithora.io
Keywords: lithora,sdk,api,project-management,work-graph
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: requests>=2.28
Dynamic: license-file

# lithora

Official Python SDK for the [Lithora](https://lithora.io) REST API — teams,
projects, tasks, the unified work graph, and the confirmation-gated AI
workspace.

- Base URL: `https://api.lithora.io` (local dev: `http://localhost:8000`)
- Auth: JWT bearer (HS256). Get a token with `client.login(...)`.

## Install

```bash
pip install lithora
# or, from this source tree:
pip install -e /path/to/sdk/python
```

Requires Python 3.9+ and `requests>=2.28`.

## Quickstart

```python
from lithora import Lithora, AuthChallengeError

client = Lithora(base_url="https://api.lithora.io")  # or http://localhost:8000

# 1. Authenticate. Token is stored on the client and reused automatically.
try:
    user = client.login("you@example.com", "your-strong-password")
except AuthChallengeError as e:
    # Login asked for a second factor instead of returning a token.
    print("2FA:", e.requires_2fa, " OTP:", e.requires_login_otp)
    raise

# 2. Create a project (needs a team_id; list teams with client.teams.list()).
project = client.projects.create("Apollo", team_id="team_123",
                                 description="Q3 launch", status="active")

# 3. Create a task in that project.
task = client.tasks.create("Write the spec", project_id=project["id"],
                           priority="high", status="todo")
client.tasks.set_status(task["id"], "in_progress")

# 4. Use the AI workspace (confirmation-gated agent over the work graph).
session = client.ai.create_session(title="Planning")
reply = client.ai.chat(session["session_id"], "Break the spec into subtasks")
if reply.get("requires_confirmation"):
    action = reply["action_plan"]["actions"][0]   # shape per server
    client.ai.confirm_action(session["session_id"], action["id"], confirmed=True)
```

Already have a token? Skip `login`: `Lithora(token="eyJ...")`.

## API surface

All methods map 1:1 to verified endpoints. Namespaces on the client:

| Namespace            | Methods |
|----------------------|---------|
| `client` (auth)      | `login`, `register`, `set_token` |
| `client.auth`        | `me` |
| `client.teams`       | `list`, `get`, `create`, `members` |
| `client.projects`    | `list`, `get`, `create`, `update`, `patch`, `delete` |
| `client.tasks`       | `list(project_id)`, `my`, `get`, `create`, `update`, `set_status`, `delete`, `bulk`, `link_github`, `push_to_github` |
| `client.work_items`  | `list`, `get`, `create`, `update`, `delete`, `create_relation`, `relations`, `children`, `parents`, `delete_relation`, `cycle_time` |
| `client.ai`          | `create_session`, `chat`, `link_item`, `search`, `confirm_action` |

## Errors

Every non-2xx response raises a typed exception (all subclass `LithoraError`):

| Exception            | When |
|----------------------|------|
| `AuthError`          | 401 — missing/invalid/expired token |
| `ServerError`        | 5xx — failure on Lithora's side |
| `ApiError`           | any other non-2xx; has `.status` and `.detail` |
| `AuthChallengeError` | login needs a 2FA/OTP code (no token issued); has `.requires_2fa`, `.requires_login_otp` |

```python
from lithora import ApiError

try:
    client.projects.get("does-not-exist")
except ApiError as e:
    print(e.status, e.detail)   # e.g. 404 "Project not found"
```

## Known gaps

- **No API-key / PAT auth.** Lithora only supports JWT bearer tokens today,
  so this SDK authenticates via `login(email, password)`. There is no
  long-lived key mechanism to wrap.
- Some endpoints (`tasks.link_github`, `tasks.push_to_github`,
  `work_items.create`) accept fields the public contract abbreviates; those
  methods pass extra keyword arguments straight through to the request body.
- **`work_items.cycle_time`** targets a newly added analytics endpoint; its
  response shape is provisional and fields may change. It requires a
  `team_id` or `project_id` you have access to.

## License

MIT — see [LICENSE](LICENSE).
