Metadata-Version: 2.4
Name: aimage-sdk
Version: 0.1.0
Summary: Python SDK for the AI-Mage Search public API
Project-URL: Documentation, https://api.search.ai-mage.jp/docs
Project-URL: Repository, https://github.com/aimagexyz/aimage-monorepo
Author: AI-Mage
License-Expression: MIT
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.12
Requires-Dist: httpx<1,>=0.28
Description-Content-Type: text/markdown

# aimage-sdk

Python SDK for the AI-Mage Search public API (`/v0`). Python 3.12+, `httpx`
is the only dependency.

## Install

The package is not yet published to PyPI. Install from the repository:

```sh
uv add "aimage-sdk @ file:///path/to/aimage-monorepo/sdks/python"
# or: pip install /path/to/aimage-monorepo/sdks/python
```

## Quickstart

```python
import os

from aimage_sdk import AimageClient

client = AimageClient(
    api_key=os.environ["AIMAGE_API_KEY"],  # "aimage_api_..."
    base_url="https://api.search.ai-mage.jp",  # API server origin; the client calls {base_url}/v0/...
)

# Discover accessible projects.
me = client.me()
project_id = me["projects"][0]["id"]

# Upload a video: mints a presigned URL, PUTs the bytes, registers the video.
video = client.upload_video(
    project_id=project_id,
    file="./episode-01.mp4",  # str | pathlib.Path | bytes (bytes need file_name=)
    name="Episode 1",
    season=1,
    episode=1,
    on_progress=print,
)

# Wait until clip extraction and AI tagging finish.
processed = client.wait_for_processing(video["id"], poll_interval_s=10, timeout_s=1800)
if processed["processing_status"] == "failed":
    raise RuntimeError(processed["processing_error"])

# Search clips with a natural-language query.
result = client.search_clips(project_id=project_id, query="two characters arguing in the rain")
for clip in result["clips"]:
    print(clip["start_time"], clip["subtitle"], clip["tags"], clip["characters"])
```

## API surface

- `ping()` / `me()`
- `mint_upload_url(project_id=, file_name=, content_type=)`
- `register_video(project_id=, name=, file_name=|s3_key=, season=, episode=, auto_process=)`
- `get_video(video_id)` / `list_videos(project_id=, page=, page_size=)` / `delete_video(video_id)`
- `search_clips(project_id=, query=, page=, page_size=)`
- `upload_video(project_id=, file=, name=, ...)` — full 3-step upload orchestration
- `wait_for_processing(video_id, poll_interval_s=, timeout_s=)`

Failed API calls raise `AimageApiError` with `code`, `message`, and HTTP
`status` parsed from the `{"error": {"code", "message"}}` envelope.

## Development

```sh
cd sdks/python
uv sync
uv run pytest
uv run ruff check .
```
