Metadata-Version: 2.4
Name: emotion-machine
Version: 0.0.4
Summary: Infra for AI Companions
Author: Emotion Machine
License: MIT
License-File: LICENSE
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.9
Requires-Dist: httpx>=0.27.0
Description-Content-Type: text/markdown

# Emotion Machine Python SDK

Official Python helper for the Emotion Machine Companion API. It wraps the `/v1` endpoints
documented in `docs/client-companion-api-plan.md` so you can provision companions, ingest
knowledge, and chat/stream with them in just a few lines of code.

## Installation

```bash
pip install emotion-machine
```

The client depends on `httpx` and targets Python 3.9+.

## Quickstart

1. **Export your project API key** (project-scoped):

   ```bash
   export EM_API_KEY="emk_prod_...."
   export EM_API_BASE_URL="https://api.emotionmachine.ai"  # or http://localhost:8100 for local dev
   ```

2. **Bootstrap a companion, ingest curated knowledge, and chat:**

   ```python
   from emotion_machine import EmotionMachine

   client = EmotionMachine()  # reads EM_API_KEY / EM_API_BASE_URL

   # Create a fresh companion
   companion = client.create_companion(
       name="Luteal Support Coach",
       description="Helps users track luteal phase cravings",
       config={
           "system_prompt": {
               "full_system_prompt": "You are an encouraging health coach."
           }
       },
   )
   companion_id = companion["id"]

   # Optionally shape the profile schema for per-user traits
   client.upsert_profile_schema(
       companion_id,
       schema={
           "type": "object",
           "properties": {
               "craving_intensity": {"type": "integer", "minimum": 0, "maximum": 5}
           },
       },
   )

   # Ingest curated luteal-phase knowledge via the built-in key
   job = client.ingest_knowledge(
       companion_id,
       payload_type="json",
       key="pm1_luteal_data_v1",
   )
   job_result = client.wait_for_job(job["id"], timeout=20)
   assert job_result["status"] == "succeeded", job_result

   # Run a synchronous chat completion
   completion = client.chat_completion(
       companion_id,
       message="Hi! I'm feeling intense salt cravings today, what should I know?",
       external_user_id="user-123",
   )
   print(completion["choices"][0]["message"]["content"])

   # Stream responses (Server-Sent Events) and collect message chunks
   stream = client.chat_stream(
       companion_id,
       message="Can you summarise key luteal phase symptoms?",
       external_user_id="user-123",
   )
   for event in stream:
       if event["event"] == "delta":
           chunk = event["data"]["choices"][0]["delta"].get("content", "")
           if chunk:
               print(chunk, end="", flush=True)
       elif event["event"] == "done":
            conversation_id = event["data"]["conversation_id"]

   # Retrieve the full conversation transcript
   transcript = client.get_conversation(conversation_id)
   for message in transcript["messages"]:
       print(f"{message['role']}: {message['content']}")
   ```

3. **Tidy up when finished:**

   ```python
   client.close()
   ```

   or use `with EmotionMachine() as client:` to auto-close the HTTP session.

## API Coverage

| Resource        | Method                                           | SDK helper                                   |
|-----------------|---------------------------------------------------|----------------------------------------------|
| Companions      | `GET /v1/companions`                              | `client.list_companions()`                   |
|                 | `POST /v1/companions`                             | `client.create_companion(...)`               |
|                 | `GET /v1/companions/{id}`                         | `client.get_companion(id)`                   |
|                 | `PATCH /v1/companions/{id}`                       | `client.update_companion(...)`               |
| Profile Schema  | `PUT /v1/companions/{id}/profile-schema`          | `client.upsert_profile_schema(...)`          |
|                 | `GET /v1/companions/{id}/profile-schema`          | `client.get_profile_schema(...)`             |
| Knowledge       | `POST /v1/companions/{id}/knowledge`              | `client.ingest_knowledge(...)`               |
|                 | `GET /v1/knowledge-jobs/{job_id}`                 | `client.knowledge.get_job(job_id)`           |
| Chat            | `POST /v1/companions/{id}/chat`                   | `client.chat_completion(...)`                |
| Chat (stream)   | `POST /v1/companions/{id}/chat/stream`            | `client.chat_stream(...)`                    |
| Conversations   | `GET /v1/conversations/{conversation_id}`         | `client.get_conversation(...)`               |

All helpers raise `emotion_machine.APIError` on non-success HTTP codes. Inspect
`e.status_code` and `e.payload` for diagnostics.

## Development

```bash
cd packages/pip-emotion-machine
pip install -e .[dev]
```

The package ships from `src/emotion_machine`. Update `pyproject.toml` to bump versions.
