Metadata-Version: 2.4
Name: powerailabs-core
Version: 0.1.4
Summary: Foundation for the PowerAI Labs stack: shared types, token counting, prices, instrument(), event bus, OTel.
Author: Raghav Mishra
License-Expression: MIT
Requires-Python: >=3.11
Provides-Extra: anthropic
Requires-Dist: anthropic>=0.30; extra == 'anthropic'
Provides-Extra: openai
Requires-Dist: openai>=1.0; extra == 'openai'
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.25; extra == 'otel'
Requires-Dist: opentelemetry-sdk>=1.25; extra == 'otel'
Provides-Extra: tiktoken
Requires-Dist: tiktoken>=0.7; extra == 'tiktoken'
Description-Content-Type: text/markdown

# powerailabs-core

The shared foundation for the PowerAI Labs stack: canonical types, provider-aware token
counting, an offline price table, one `instrument()` interception point, an in-process event
bus, and OpenTelemetry GenAI emitters. Tiny on purpose — it's the blast radius for every other tool.

**One `instrument()` call, every sibling tool observes the stream — no per-call wiring, offline by default.**

![status](https://img.shields.io/badge/status-building-yellow) ![license](https://img.shields.io/badge/license-MIT-blue)

🚧 building · usually installed transitively · `import powerailabs.core`

```python
from powerailabs.core import tokens, prices, instrument, bus

# Count tokens and price a call — fully offline, no API key, no network:
n = tokens.count([{"role": "user", "content": "Summarize the attached report in 3 bullets."}],
                 model="claude-opus-4-8")
cost = prices.estimate("claude-opus-4-8", input_tokens=n, output_tokens=200)
print(n, cost)                       # -> 20  0.0051000 USD

# Instrument any client once; tools subscribe to the normalized event stream:
@bus.subscribe
def on_call(call):                   # receives a normalized LLMCall with usage + cost
    print(call.provider, call.model, call.cost)

client = instrument(openai_or_anthropic_client)   # idempotent, additive, sync + async
```

Install `powerailabs-core[tiktoken]` for exact OpenAI token counts (a documented heuristic is
used otherwise), or `[otel]` to emit `gen_ai.*` spans. Provider SDKs are always optional extras.

See [`docs/core.md`](../../docs/core.md). *Part of the PowerAI Labs stack — github.com/PowerAI-Labs/powerailabs.*
