Metadata-Version: 2.4
Name: hyperneuronai
Version: 0.1.24
Summary: Official Python SDK for HyperNeuron AI services
Author-email: HyperNeuronAI <support@hyperneuron.in>
License: MIT
Project-URL: Homepage, https://www.hyperneuronai.com
Project-URL: Repository, https://github.com/hyperneuronai/hyperneuronai-python
Keywords: ai,tts,voice,telephony,speech
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT 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
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.0.0
Provides-Extra: audio
Requires-Dist: numpy>=1.24.0; extra == "audio"
Requires-Dist: scipy>=1.11.0; extra == "audio"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.23; extra == "dev"
Requires-Dist: respx>=0.21; extra == "dev"

# hyperneuronai
<p align="center">
  <img src="https://i.ibb.co/DHdfV789/logohyperneuronsmall-copy.png" alt="HyperNeuronAI" width="200"/>
</p>

Official Python SDK for [HyperNeuron AI](https://www.hyperneuronai.com) — streaming TTS, one-way voice broadcasts, and full-duplex agentic AI phone calls.

## Install

```bash
pip install hyperneuronai
```

## Client setup

```python
import hyperneuronai

client = hyperneuronai.HyperNeuron(
    api_key="<api-key-from-your-account>",
    base_url="https://ai.hyperneuron.in",
)
```

Available voices: `sanjana`, `divya`, `elina`, `deepraj`, `raju`.

---

## Text-to-Speech

`POST /tts/stream`. Audio is **16-bit little-endian PCM**; `generate(format="wav")` wraps it in a ready-to-save WAV container.

```python
# Save a complete WAV file
audio = client.tts.generate("Hello! How are you today?", voice="deepraj")
with open("hello.wav", "wb") as f:
    f.write(audio)

# Raw 16-bit PCM (no header) — e.g. to pipe into telephony
pcm = client.tts.generate("नमस्ते", voice="sanjana", format="pcm", sample_rate=8000)

# Stream chunks for low-latency playback (each chunk is int16 PCM)
for chunk in client.tts.stream("Hello, world!", voice="elina"):
    your_speaker.write(chunk)

# List voices (served locally by the SDK)
print(client.tts.voices())
```

`text` is capped at 2000 characters. `sample_rate` may be 8000–48000 Hz (default 24000).

---

## One-way outbound call

Synthesizes `text` and plays it to the recipient — the called party cannot speak back.

```python
call = client.telephony.outbound(
    to_number="+919876543210",
    text="Hi! Your order has shipped and arrives tomorrow.",
    voice="sanjana",
    language="en",
    from_number="+14155550100",  # optional caller ID / DID
)
print(call.call_uuid, call.state)
```

---

## Two-way agentic call

A full-duplex AI voice conversation: the recipient speaks and the AI responds in real time. Configure the agent **inline**, or reference a **saved agent** by `agent_id` (see below). Inline fields override the saved config for that call.

```python
# Inline configuration
call = client.telephony.agent_call(
    to_number="+919876543210",
    greeting="Hi! This is HyperNeuron calling. How can I help you today?",
    system="You are a friendly support agent. Keep replies short.",
    voice="deepraj",
    language="hi",
    country_code="IN",
    knowledge_base_id=None,           # optional RAG knowledge base
    barge_in_min_duration_ms=0,       # 0 = caller can interrupt immediately
    speaker_voice_energy_threshold=0.009,
    speaker_silence_threshold_ms=280,
)

# …or use a saved agent
call = client.telephony.agent_call(to_number="+919876543210", agent_id=agent.agent_id)

print(f"Call initiated: {call.call_uuid} ({call.state})")
```

### Poll call status

```python
import time

while True:
    time.sleep(5)
    status = client.telephony.status(call.call_uuid)
    print(f"  → {status.state}")
    if status.is_terminal:
        print(f"Call ended: {status.state}")
        if status.duration_sec:
            print(f"Duration: {status.duration_sec}s ({status.duration_min:.1f} min)")
        break

client.close()
```

---

## Saved agents

Create reusable agent configurations (system prompt, voice, VAD tuning, human-handoff rules) and start calls against them with `agent_id`.

```python
agent = client.agents.create(
    name="Support Bot",
    system_prompt="You are a friendly support agent. Keep replies short.",
    greeting="Hi! Thanks for calling HyperNeuron support.",
    voice="deepraj",
    language="hi",
    speaker_silence_threshold_ms=280,
    human_agent_numbers=[
        {"phone_number": "+919812345678", "priority": 1, "label": "Tier 1"},
    ],
    dtmf_handoff_keys=["0"],
)
print(agent.agent_id)

# List / fetch / update / delete
agents = client.agents.list()
agent = client.agents.get(agent.agent_id)
agent = client.agents.update(agent.agent_id, voice="elina", greeting="नमस्ते!")
client.agents.delete(agent.agent_id)

# Start a call with the saved agent
client.telephony.agent_call(to_number="+919876543210", agent_id=agent.agent_id)
```

Only `name` is required on `create()`; every other field falls back to the server default.

---

## Async

Every method exists on `AsyncHyperNeuron` with the same signature.

```python
import asyncio
import hyperneuronai

async def main():
    async with hyperneuronai.AsyncHyperNeuron(api_key="<api-key>") as client:
        audio = await client.tts.generate("Hello!", voice="deepraj")

        agent = await client.agents.create(name="Sales Bot", voice="sanjana")

        call = await client.telephony.agent_call(
            to_number="+919876543210",
            agent_id=agent.agent_id,
        )

        async for chunk in client.tts.stream("Streaming hello"):
            ...  # each chunk is int16 PCM

asyncio.run(main())
```

---

## Error handling

```python
from hyperneuronai import (
    AuthenticationError, RateLimitError, NotFoundError, APIConnectionError, APIError,
)

try:
    call = client.telephony.agent_call(to_number="+919876543210")
except AuthenticationError:
    ...   # bad / missing API key
except RateLimitError:
    ...   # slow down
except APIError as exc:
    print(exc.status_code, exc)
```

## License

MIT
