Metadata-Version: 2.4
Name: promptops-sdk
Version: 0.1.0
Summary: Python SDK for PromptOps - AI Prompt Management Platform
Project-URL: Homepage, https://promptsops.com
Project-URL: Repository, https://github.com/promptsops/promptops-python
Project-URL: Bug Tracker, https://github.com/promptsops/promptops-python/issues
License: Apache-2.0
License-File: LICENSE
Keywords: ai,llm,management,prompt,promptops
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
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: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: httpx>=0.24
Provides-Extra: dev
Requires-Dist: pytest-mock>=3.10; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: respx>=0.20; extra == 'dev'
Description-Content-Type: text/markdown

# PromptOps Python SDK

Python SDK for [PromptOps](https://promptsops.com) — AI Prompt Management Platform.

## Installation

```bash
pip install promptops
```

## Quick Start

```python
from promptops import PromptOps

po = PromptOps(api_key="pop_sk_xxx")
config = po.get_prompt("customer-support", label="prod")
print(config.system_prompt)

# Context manager (recommended — ensures cleanup)
with PromptOps(api_key="pop_sk_xxx") as po:
    config = po.get_prompt("customer-support")
    print(config.system_prompt)
```

## Variable Substitution

```python
from promptops import PromptOps

with PromptOps(api_key="pop_sk_xxx") as po:
    config = po.get_prompt("customer-support")

    if config.user_prompt_template:
        message = PromptOps.substitute(
            config.user_prompt_template,
            {"customer_name": "Alice", "issue": "login problem"},
        )
        print(message)
```

## Configuration Options

```python
from promptops import PromptOps, PromptConfig

# Fallback used when API is unreachable and cache is empty
fallback_config = PromptConfig(
    slug="customer-support",
    version=1,
    type="text",
    system_prompt="You are a helpful assistant.",
    user_prompt_template="Help {{customer_name}} with: {{issue}}",
    content=None,
    config={"model": "gpt-4o-mini", "provider": "openai", "temperature": 0.7, "max_tokens": 1024},
    variables=[{"name": "customer_name"}, {"name": "issue"}],
    updated_at="2024-01-01T00:00:00Z",
)

po = PromptOps(
    api_key="pop_sk_xxx",
    base_url="https://promptsops.com",   # default
    refresh_interval=60,                  # seconds, default 60
    fallback={"customer-support": fallback_config},
)
```

## Manual Cache Refresh

```python
with PromptOps(api_key="pop_sk_xxx") as po:
    # Refresh a specific prompt
    po.refresh("customer-support")

    # Refresh all cached prompts
    po.refresh()
```

## PromptConfig Fields

| Field | Type | Description |
|---|---|---|
| `slug` | `str` | Prompt identifier |
| `version` | `int` | Prompt version number |
| `type` | `str` | `"text"` or `"chat"` |
| `system_prompt` | `str \| None` | System prompt text |
| `user_prompt_template` | `str \| None` | User prompt with `{{variable}}` placeholders |
| `content` | `Any` | Chat-type structured content |
| `config` | `dict` | Model config: `model`, `provider`, `temperature`, `max_tokens` |
| `variables` | `list[dict]` | Variable definitions: `name`, optional `description` |
| `updated_at` | `str` | ISO 8601 timestamp of last update |

## Caching Behaviour

The SDK uses a 3-tier fallback strategy on every `get_prompt()` call:

1. **In-memory cache** — returns immediately if the entry is younger than `refresh_interval` seconds.
2. **API fetch** — sends a request with `If-None-Match` (ETag); a `304 Not Modified` response refreshes the timestamp without re-parsing the body.
3. **User-provided fallback** — returned when both the cache and API are unavailable.

A background daemon thread automatically refreshes all cached prompts every `refresh_interval` seconds. The cache is protected by a `threading.Lock` and is safe for concurrent use.

## License

Apache-2.0
