Metadata-Version: 2.4
Name: missilya-sdk
Version: 0.2.1
Summary: MISSILYA GROUP Core SDK — unified, vault-backed infrastructure for AI, payments, notifications, auth, and monitoring.
Project-URL: Homepage, https://github.com/MISSILYA-GROUP/MISSILYA-CORE-SDK
Project-URL: Documentation, https://github.com/MISSILYA-GROUP/MISSILYA-CORE-SDK/tree/main/docs
Project-URL: Changelog, https://github.com/MISSILYA-GROUP/MISSILYA-CORE-SDK/blob/main/CHANGELOG.md
Author-email: MISSILYA GROUP <dev@missilya.com>
License: MISSILYA GROUP — PROPRIETARY LICENCE (SOURCE-AVAILABLE)
        
        Copyright (c) 2026 MISSILYA GROUP. All rights reserved.
        
        This software and its source code are the proprietary property of MISSILYA GROUP.
        They are published on a public package index for distribution convenience only.
        Publication does not place this software in the public domain, does not make it
        open source, and grants no rights beyond those stated below.
        
        GRANT
          You are granted a non-exclusive, non-transferable, revocable licence to
          download, install and execute unmodified copies of this package for the sole
          purpose of interoperating with MISSILYA GROUP services under a valid
          commercial agreement with MISSILYA GROUP.
        
        RESTRICTIONS
          Without prior written authorisation from MISSILYA GROUP you may not:
            (a) copy, reproduce or redistribute the source code, in whole or in part;
            (b) modify, adapt, translate or create derivative works;
            (c) reverse engineer, decompile or disassemble, except to the extent this
                restriction is unenforceable under applicable law;
            (d) use the source code, its structure, or its interfaces to build a
                competing or substantially similar product;
            (e) remove or alter any proprietary notice.
        
        NO WARRANTY
          THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
          IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
          FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
        
        LIMITATION OF LIABILITY
          IN NO EVENT SHALL MISSILYA GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
          LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR ITS USE.
        
        Licensing enquiries: dev@missilya.com
License-File: LICENSE
Keywords: ai,infisical,missilya,payments,sdk,vault
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Typing :: Typed
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic>=2.0
Requires-Dist: pyjwt>=2.8
Requires-Dist: structlog>=24.0
Provides-Extra: ai
Requires-Dist: deepl>=1.18; extra == 'ai'
Requires-Dist: elevenlabs>=1.0; extra == 'ai'
Requires-Dist: litellm<2.0,>=1.40; extra == 'ai'
Requires-Dist: openai>=1.30; extra == 'ai'
Provides-Extra: all
Requires-Dist: cryptography>=42.0; extra == 'all'
Requires-Dist: deepl>=1.18; extra == 'all'
Requires-Dist: elevenlabs>=1.0; extra == 'all'
Requires-Dist: litellm<2.0,>=1.40; extra == 'all'
Requires-Dist: openai>=1.30; extra == 'all'
Requires-Dist: resend>=2.0; extra == 'all'
Requires-Dist: sentry-sdk>=2.0; extra == 'all'
Requires-Dist: stripe>=10.0; extra == 'all'
Requires-Dist: twilio>=9.0; extra == 'all'
Provides-Extra: auth
Requires-Dist: cryptography>=42.0; extra == 'auth'
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest-cov>=5.0; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Provides-Extra: monitoring
Requires-Dist: sentry-sdk>=2.0; extra == 'monitoring'
Provides-Extra: notifications
Requires-Dist: resend>=2.0; extra == 'notifications'
Requires-Dist: twilio>=9.0; extra == 'notifications'
Provides-Extra: payments
Requires-Dist: stripe>=10.0; extra == 'payments'
Description-Content-Type: text/markdown

# missilya-sdk

**MISSILYA GROUP Core SDK** — one versioned, vault-backed Python package that
replaces the copy-pasted `emergentintegrations` code spread across the MISSILYA
ecosystem. It gives every application a single, provider-agnostic API for **AI,
payments, notifications, auth, secrets, and monitoring**, with credentials sourced
from **MISSILYA VAULT** and no vendor lock-in.

- **Package:** `missilya-sdk`  ·  **Import namespace:** `missilya_sdk`
- **Runtime:** staging & production (routes to real providers using vault keys)
- **Python:** 3.11 – 3.13
- **Sandbox twin:** [`missilya-sdk-sandbox`](https://github.com/MISSILYA-GROUP/MISSILYA-SANDBOX-SDK)
  — API-identical, deterministic, offline (use in development & CI)

> **Status:** private, under review. After approval the package is published to the
> MISSILYA private pip registry so any project can `pip install missilya-sdk`.

---

## Table of contents

1. [Why this exists](#1-why-this-exists)
2. [Install](#2-install)
3. [Quickstart](#3-quickstart)
4. [Core concepts](#4-core-concepts)
5. [Configuration & the vault](#5-configuration--the-vault)
6. [Module reference](#6-module-reference)
7. [The Adapter Engine & failover](#7-the-adapter-engine--failover)
8. [Multi-tenant usage](#8-multi-tenant-usage)
9. [Error handling](#9-error-handling)
10. [Observability](#10-observability)
11. [Security model](#11-security-model)
12. [Governance & CI](#12-governance--ci)
13. [Migration from emergentintegrations](#13-migration-from-emergentintegrations)
14. [Sandbox parity & versioning](#14-sandbox-parity--versioning)
15. [Local development](#15-local-development)
16. [Project layout](#16-project-layout)

---

## 1. Why this exists

`emergentintegrations` was vendored (copy-pasted) into ~35 repositories. Each copy
drifted: no versioning, no tests, no CI, hardcoded API keys. This SDK fixes that:

| Before (`emergentintegrations`) | After (`missilya_sdk`) |
|---|---|
| Copy in every repo, silently diverging | One versioned package, one source of truth |
| OpenAI-only, tightly coupled | 100+ models via the Adapter Engine, swappable |
| Hardcoded keys / `.env` | VAULT-first, fail-closed in production |
| No tests, no CI | Strict typing, tests, parity check, CI gates |
| Direct vendor imports everywhere | Apps import only `missilya_sdk` (CI-enforced) |

---

## 2. Install

Install only the modules a service needs (optional extras keep the dependency
surface small):

```bash
pip install "missilya-sdk[ai]"            # LLM, images, TTS, STT, translation
pip install "missilya-sdk[payments]"      # Stripe
pip install "missilya-sdk[notifications]" # Resend (email), Twilio (SMS/WhatsApp)
pip install "missilya-sdk[auth]"          # Google sign-in (RS256 verification)
pip install "missilya-sdk[monitoring]"    # Sentry
pip install "missilya-sdk[all]"           # everything
```

| Extra | Installs |
|---|---|
| `[ai]` | `litellm`, `openai`, `elevenlabs`, `deepl` |
| `[payments]` | `stripe` |
| `[notifications]` | `resend`, `twilio` |
| `[auth]` | `cryptography` (Google ID-token RS256 verification) |
| `[monitoring]` | `sentry-sdk` |
| `[all]` | all of the above |
| `[dev]` | `pytest`, `ruff`, `mypy`, `build`, `twine`, … |

### Installing into a MISSILYA repo

Until the package is published to the private registry, depend on it directly
from GitHub (pin a tag or commit for reproducibility):

```bash
pip install "missilya-sdk[all] @ git+https://github.com/MISSILYA-GROUP/MISSILYA-CORE-SDK.git@v0.2.0"
```

For development/CI, use the sandbox twin (offline, deterministic, no provider
keys) and swap to core by environment — not by import:

```bash
pip install "missilya-sdk-sandbox @ git+https://github.com/MISSILYA-GROUP/MISSILYA-SANDBOX-SDK.git@v0.2.0"
```

### Production readiness

Every module is type-checked (`mypy --strict`) and has 100% test coverage
(enforced in CI). Unit tests exercise provider **boundaries** with mocks, so
before relying on a provider-backed capability in production, run the live smoke
suite once in an environment that has the real credentials (or vault access):

```bash
MISSILYA_RUN_INTEGRATION=1 pytest tests/integration -m integration --no-cov -v
```

Each smoke test self-skips unless its credentials are present, and makes the
smallest real call that proves the round-trip (vault read, chat completion,
Stripe test session, email/SMS/WhatsApp send, Google ID-token verify).

**One-click in CI:** the `Live Integration Smoke` GitHub Actions workflow
(`.github/workflows/integration.yml`, manual `Run workflow`) runs the same suite
using repository secrets — no local setup. Configure under
*Settings → Secrets and variables → Actions* (each capability self-skips if its
secret is absent, so you can validate incrementally):

| Secret | For |
|---|---|
| `MISSILYA_VAULT_URL`, `MISSILYA_VAULT_CLIENT_ID/SECRET`, `MISSILYA_VAULT_PROJECT_ID` | vault read (requires a reachable `vault.missilya.com`) |
| `OPENAI_API_KEY` | chat completion |
| `STRIPE_TEST_SECRET_KEY` | checkout session (TEST key) |
| `RESEND_API_KEY` + var `MISSILYA_SMOKE_EMAIL_TO` | email |
| `TWILIO_ACCOUNT_SID/AUTH_TOKEN` + vars `TWILIO_SMS_FROM`, `MISSILYA_SMOKE_SMS_TO` | SMS |
| `WHATSAPP_ACCESS_TOKEN` + vars `WHATSAPP_PHONE_NUMBER_ID`, `MISSILYA_SMOKE_WHATSAPP_TO` | WhatsApp |
| `GOOGLE_OAUTH_CLIENT_ID`, `GOOGLE_TEST_ID_TOKEN` | Google sign-in |

> **`ai.generate_video` is a stub.** No cross-provider video API is wired into
> core yet; it raises `ProviderError` by design. The sandbox returns a fixture
> so app code can integrate against the shape. Do not depend on live video until
> a provider adapter is added.

For **development and CI**, install the offline twin instead — same import, no real
calls: `pip install missilya-sdk-sandbox`.

---

## 3. Quickstart

```python
from missilya_sdk.ai.chat import LlmChat, SystemMessage, UserMessage

chat = LlmChat(model="gpt-4o")                       # key resolved from VAULT
chat.add_message(SystemMessage("You are a MISSILYA assistant."))
chat.add_message(UserMessage("Explain our subscription tiers."))

print(chat.chat())                                   # -> str (legacy-compatible)
```

No API keys in code. No `import openai`. The SDK resolves the right credential from
the vault, routes through the Adapter Engine, and returns a normalized result.

---

## 4. Core concepts

| Concept | What it is |
|---|---|
| **Unified API** | `missilya_sdk.<domain>.<capability>` — apps never touch a vendor SDK. |
| **Adapter Engine** | Internal layer that resolves credentials, picks a provider, normalizes responses, and fails over. |
| **VAULT-first config** | Credentials come from MISSILYA VAULT; production fails closed if a secret is missing. |
| **TenantContext** | Scopes every call (vault path, billing, audit) to one tenant. |
| **Typed errors** | Every failure is a `missilya_sdk.exceptions.*` subclass of `MissilyaError`. |
| **Sandbox parity** | The sandbox package mirrors this public API exactly, verified in CI. |

---

## 5. Configuration & the vault

Credentials resolve in this order (`config.get_config`):

1. **MISSILYA VAULT** (Infisical) — required for staging/production
2. **CI/vault-injected** environment variable (deployment bridge)
3. **Local environment variable** (development only)
4. **Non-secret default** (if provided)
5. **Fail closed** → `ConfigurationError`

In **production**, a secret resolved from a plain environment variable is
**rejected** unless `MISSILYA_ALLOW_ENV_SECRETS=1` (an approved CI/vault bridge).

### Runtime environment variables

| Variable | Purpose |
|---|---|
| `MISSILYA_VAULT_URL` | Vault base URL. Defaults to `https://vault.missilya.com`. |
| `MISSILYA_VAULT_CLIENT_ID` / `..._CLIENT_SECRET` | Machine-identity Universal Auth (recommended). |
| `MISSILYA_VAULT_TOKEN` | Static service/access token (alternative to Universal Auth). |
| `MISSILYA_VAULT_PROJECT_ID` | Infisical project for app secrets. |
| `MISSILYA_VAULT_SHARED_PROJECT_ID` | Project holding shared provider keys. |
| `MISSILYA_ENV` | `development` / `staging` / `production`. |
| `MISSILYA_ALLOW_ENV_SECRETS` | Set `1` only for an approved CI/vault bridge in production. |

See [`.env.example`](.env.example) for the full list of secret names
(`OPENAI_API_KEY`, `STRIPE_SECRET_KEY`, `RESEND_API_KEY`, `JWT_SECRET`,
`SENTRY_DSN`, …).

### How the vault call works

`VaultClient` speaks the Infisical REST API:

- **Universal Auth login:** `POST /api/v1/auth/universal-auth/login` → short-lived
  access token (cached in memory until just before expiry).
- **Read secret:** `GET /api/v4/secrets/{name}?projectId=&environment=&secretPath=/`
  → `{ "secret": { "secretValue": "..." } }`.

Provider keys (e.g. `OPENAI_API_KEY`) fall back to the **shared project**;
app-specific secrets come from the **app project**. Values are cached briefly,
never logged, and the client retries transient failures with backoff.

---

## 6. Module reference

### `missilya_sdk.ai.chat` — LLM chat

```python
from missilya_sdk.ai.chat import LlmChat, SystemMessage, UserMessage, AssistantMessage

chat = LlmChat(model="gpt-4o", fallbacks=["claude-sonnet-4-20250514"])
chat.add_message(SystemMessage("Be concise."))
chat.add_message(UserMessage("Summarize Q2 in one sentence."))

text = chat.chat()                 # -> str (emergentintegrations-compatible)
resp = chat.complete()             # -> ChatResponse(content, model, provider, usage, raw)
print(resp.usage.total_tokens)

# Async + streaming
text = await chat.achat()
async for delta in chat.astream():
    print(delta, end="")
```

Model strings follow the LiteLLM convention: `"gpt-4o"`, `"claude-sonnet-4-..."`,
`"gemini/gemini-2.5-pro"`, `"mistral/..."`, `"deepseek/..."`.

### `missilya_sdk.ai.images` — image generation

```python
from missilya_sdk.ai.images import generate_image
img = generate_image("a neon skyline at dusk", model="dall-e-3", size="1024x1024")
print(img.url)
```

### `missilya_sdk.ai.tts` / `.stt` — speech

```python
from missilya_sdk.ai.tts import text_to_speech
from missilya_sdk.ai.stt import speech_to_text

audio = text_to_speech("Hello from MISSILYA", voice_id="JBFqnCBsd6RMkjVDRZzb")
open("hello.mp3", "wb").write(audio.audio)

transcript = speech_to_text(open("hello.mp3", "rb").read())
print(transcript.text)
```

### `missilya_sdk.ai.translation` — translation

```python
from missilya_sdk.ai.translation import translate
print(translate("Bonjour le monde", target_lang="EN-US").text)
```

### `missilya_sdk.payments.stripe` — payments

```python
from missilya_sdk.payments.stripe import StripeCheckout
from missilya_sdk.payments.checkout import CheckoutSessionRequest

checkout = StripeCheckout()
session = checkout.create_session(CheckoutSessionRequest(
    line_items=[{"price": "price_123", "quantity": 1}],
    success_url="https://app.missilya.com/success",
    cancel_url="https://app.missilya.com/cancel",
    customer_email="client@example.com",
))
print(session.url)

# Webhook (signature verified against vault STRIPE_WEBHOOK_SECRET)
event = checkout.handle_webhook(request_body, signature_header)
```

### `missilya_sdk.notifications` — email / SMS / WhatsApp

```python
from missilya_sdk.notifications.email import send_email
from missilya_sdk.notifications.sms import send_sms
from missilya_sdk.notifications.whatsapp import send_whatsapp

send_email(to="user@example.com", subject="Welcome", html="<h1>Hi</h1>")
send_sms(to="+10000000000", body="Your code is 123456")
send_whatsapp(to="+10000000000", body="Your order shipped")
```

### `missilya_sdk.whatsapp` — two-way WhatsApp (Meta Cloud API or Twilio)

```python
from missilya_sdk.whatsapp import WhatsAppClient, parse_inbound, verify_signature

wa = WhatsAppClient()                       # provider from WHATSAPP_PROVIDER (default "meta")
wa.send_text("+10000000000", "Your order shipped")
wa.send_template("+10000000000", "order_update", language="en_US")
wa.send_media("+10000000000", "https://cdn.example.com/receipt.pdf", kind="document")

# Inbound webhook (framework-agnostic):
verify_signature(raw_body, request.headers["X-Hub-Signature-256"])   # fail-closed
for msg in parse_inbound(raw_body):
    print(msg.from_number, msg.text)
    wa.mark_read(msg.message_id)
```

The Meta Cloud API is the default backend; set `WHATSAPP_PROVIDER=twilio` to use
Twilio instead. Credentials (`WHATSAPP_ACCESS_TOKEN`, `WHATSAPP_PHONE_NUMBER_ID`,
`WHATSAPP_APP_SECRET`, `WHATSAPP_VERIFY_TOKEN`) come from MISSILYA VAULT.

### `missilya_sdk.auth.jwt` — JWT helpers

```python
from missilya_sdk.auth.jwt import create_token, verify_token

token = create_token({"sub": "user-1"}, expires_in=3600)   # signed with vault JWT_SECRET
claims = verify_token(token)                                 # raises AuthenticationError if invalid
```

### `missilya_sdk.auth.google` — Google Sign-In (OIDC → Missilya JWT)

```python
from missilya_sdk.auth import sign_in_with_google, verify_google_token

# Verify a Google ID token from the client (validates signature, issuer, aud, exp):
identity = verify_google_token(google_id_token)             # -> GoogleIdentity(sub, email, ...)

# Or verify AND mint a first-party Missilya session token in one step:
session = sign_in_with_google(google_id_token)
session.token       # a Missilya JWT (verify with auth.jwt.verify_token)
session.identity    # the verified GoogleIdentity
```

RS256 verification needs the `[auth]` extra: `pip install "missilya-sdk[auth]"`.
The audience defaults to the vault-resolved `GOOGLE_OAUTH_CLIENT_ID`.

### `missilya_sdk.vault.client` — direct vault access

```python
from missilya_sdk.vault.client import VaultClient
client = VaultClient(url="https://vault.missilya.com",
                     client_id="...", client_secret="...", project_id="...")
value = client.get_secret("SOME_APP_SECRET", environment="production")
```

> Application code rarely calls `VaultClient` directly for provider keys — the
> capability modules resolve their own credentials internally.

### Public import surface (v0.1.0)

```python
from missilya_sdk import MissilyaSDK, TenantContext, get_config
from missilya_sdk.ai.chat import LlmChat, UserMessage, SystemMessage, AssistantMessage, ChatResponse, ChatUsage
from missilya_sdk.ai.images import generate_image, ImageResult
from missilya_sdk.ai.tts import text_to_speech, SpeechResult
from missilya_sdk.ai.stt import speech_to_text, TranscriptResult
from missilya_sdk.ai.translation import translate, TranslationResult
from missilya_sdk.ai.video import generate_video, VideoJob
from missilya_sdk.payments.stripe import StripeCheckout
from missilya_sdk.payments.checkout import CheckoutSessionRequest, CheckoutSession, WebhookEvent
from missilya_sdk.notifications import send_email, send_sms, send_whatsapp, DeliveryResult
from missilya_sdk.auth.jwt import create_token, verify_token, decode_token
from missilya_sdk.monitoring import get_logger, new_correlation_id, track_event, init_sentry, capture_exception, capture_message
from missilya_sdk.exceptions import MissilyaError, ConfigurationError, ProviderError, RateLimitError, VaultError
```

---

## 7. The Adapter Engine & failover

Every LLM call flows through one engine so the application never targets a vendor:

```
App → LlmChat → Adapter Engine
                 ├─ resolve credential from VAULT (per provider)
                 ├─ dispatch via LiteLLM to the chosen model
                 ├─ on failure, fail over to the next model in `fallbacks`
                 └─ normalize response + usage; emit redacted telemetry
```

```python
chat = LlmChat(
    model="gpt-4o",
    fallbacks=["claude-sonnet-4-20250514", "gemini/gemini-2.5-pro"],
)
```

If OpenAI errors, the engine automatically retries with Anthropic, then Gemini —
no application change. Errors are normalized to typed exceptions
(`RateLimitError`, `ProviderTimeoutError`, `ProviderAuthError`, `ProviderError`).

---

## 8. Multi-tenant usage

```python
from missilya_sdk import TenantContext
from missilya_sdk.ai.chat import LlmChat, UserMessage

ctx = TenantContext(tenant_id="civytax", env="production")
chat = LlmChat(model="gpt-4o", context=ctx)
chat.add_message(UserMessage("Calculate taxes for ..."))
answer = chat.chat()   # key resolved from the civytax scope; usage tagged to civytax
```

The context drives the vault project/path, tags telemetry for per-tenant billing,
and adds traceability headers. A convenience facade is also available:

```python
from missilya_sdk import MissilyaSDK
sdk = MissilyaSDK(tenant_id="civytax", environment="production")
chat = sdk.chat(model="gpt-4o")
```

---

## 9. Error handling

All failures are subclasses of `MissilyaError`:

```
MissilyaError
├── ConfigurationError
├── ProviderError
│   ├── RateLimitError
│   ├── ProviderTimeoutError
│   └── ProviderAuthError
├── AuthenticationError
├── VaultError
│   ├── VaultConnectionError
│   └── VaultSecretNotFound
└── ValidationError
```

```python
from missilya_sdk.exceptions import MissilyaError, RateLimitError

try:
    answer = chat.chat()
except RateLimitError:
    ...   # back off / queue
except MissilyaError as exc:
    log.error("sdk_error", error=str(exc))
```

---

## 10. Observability

```python
from missilya_sdk.monitoring import get_logger, new_correlation_id, init_sentry, capture_exception

log = get_logger(__name__)        # structured, secret-redacting logger
init_sentry()                     # DSN from vault SENTRY_DSN; no-op if absent

def handle(req):
    new_correlation_id()          # correlate every log line for this request
    try:
        ...
    except Exception as exc:
        capture_exception(exc)    # report to Sentry if configured
        raise
```

Logs emit structured JSON and automatically redact API keys, bearer tokens,
`sk-…`/`sk_live_…`/`whsec_…` patterns, card data, and other sensitive fields.
`track_event(...)` / `track_latency(...)` record usage and latency.

---

## 11. Security model

- **No plaintext secrets** anywhere in code or `.env` (production fails closed).
- **Secrets never logged** — redaction is applied before anything is emitted.
- **Least privilege** — runtime uses a read-only machine identity scoped to one
  project/environment.
- **Production guards** — `StripeCheckout` requires a live key in production; the
  config layer refuses plain-env secrets in production by default.
- **Provenance** — releases record SHA-256 hashes of build artifacts.

---

## 12. Governance & CI

- **Forbidden-import gate:** `tools/check_forbidden_imports.py` fails CI if app
  code imports `openai`/`stripe`/`twilio`/`anthropic`/`litellm`/`resend`/… directly.
- **Quality gate:** `ruff` (lint) + `mypy --strict` (types) + `pytest` (tests) on
  Python 3.11/3.12/3.13.
- **Secret scan:** gitleaks on every push/PR.
- **Release:** tag → build sdist/wheel → `twine check` → SHA-256 ledger → publish to
  the private registry (manual production approval gate).
- **Container:** `Dockerfile` + GHCR publish workflow.
- **Zone:** classified `A` (foundation) in [`repo.classification.yml`](repo.classification.yml).

---

## 13. Migration from `emergentintegrations`

Mostly a find-and-replace on imports; see [`docs/migration-guide.md`](docs/migration-guide.md).

| Legacy | MISSILYA SDK |
|---|---|
| `from emergentintegrations.llm.chat import LlmChat, UserMessage` | `from missilya_sdk.ai.chat import LlmChat, UserMessage` |
| `from emergentintegrations.payments.stripe.checkout import StripeCheckout` | `from missilya_sdk.payments.stripe import StripeCheckout` |
| `resend.Emails.send(...)` | `from missilya_sdk.notifications.email import send_email` |

The `LlmChat` / `StripeCheckout` APIs are preserved, so most migrations need no
business-logic changes — just the import path and removing hardcoded keys.

---

## 14. Sandbox parity & versioning

- The sandbox package exposes an **identical public API** (same names, signatures,
  return shapes). This is verified statically by `repos/sdk-tools/check_sdk_parity.py`
  and as a test.
- Versions are kept **in lock-step** (`src/missilya_sdk/_version.py`); a feature
  cannot land in core without matching sandbox behavior.
- The package follows **SemVer**. Current version: `0.1.0`.

---

## 15. Local development

```bash
python -m venv .venv
./.venv/Scripts/python -m pip install -e ".[all,dev]"   # Windows
# source .venv/bin/activate && pip install -e ".[all,dev]"   # macOS/Linux

ruff check src tests tools
mypy src/missilya_sdk
pytest -q
python -m build && twine check dist/*
```

---

## 16. Project layout

```
src/missilya_sdk/
├── __init__.py            # public top-level exports
├── config.py              # VAULT-first config resolution
├── context.py             # TenantContext, MissilyaSDK facade
├── exceptions.py          # typed error hierarchy
├── ai/                    # chat (+_engine adapter), images, tts, stt, translation, video
├── payments/              # stripe, checkout models
├── notifications/         # email, sms, whatsapp
├── auth/                  # jwt
├── vault/                 # Infisical client
└── monitoring/            # logging, analytics, sentry
tests/                     # unit + smoke + parity tests
tools/check_forbidden_imports.py
docs/                      # getting-started, migration-guide
.github/workflows/         # test, publish, release, docker-publish
Dockerfile · repo.classification.yml · .env.example
```

---

## License

Proprietary — © 2026 MISSILYA GROUP. See [LICENSE](LICENSE). Private to MISSILYA
GROUP; redistribution requires written authorization from Yvon Kamach (CEO).
