oridio 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,47 @@
1
+ # Rust build artifacts
2
+ target/
3
+ Cargo.lock
4
+
5
+ # Environment variables
6
+ .env
7
+ .env.local
8
+ .env.*.local
9
+
10
+ # IDEs and editors
11
+ .idea/
12
+ .vscode/
13
+ *.suo
14
+ *.ntvs*
15
+ *.njsproj
16
+ *.sln
17
+ *.sw?
18
+
19
+ # OS files
20
+ .DS_Store
21
+ Thumbs.db
22
+
23
+ # Logs
24
+ *.log
25
+
26
+ # Python
27
+ __pycache__/
28
+ *.py[cod]
29
+ *.class
30
+ *.egg-info/
31
+ .pytest_cache/
32
+ .venv/
33
+ venv/
34
+
35
+ # Node
36
+ node_modules/
37
+ dist/
38
+ .npm/
39
+
40
+ # Oridio specific
41
+ .fastembed_cache/
42
+
43
+ test_results.json
44
+ *.key
45
+ *.pem
46
+ .next/
47
+ demo/
oridio-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,209 @@
1
+ Metadata-Version: 2.5
2
+ Name: oridio
3
+ Version: 0.1.0
4
+ Summary: Official Python SDK for Oridio — AI Control Plane
5
+ Project-URL: Homepage, https://oridio.org
6
+ Project-URL: Repository, https://github.com/Oridio-org/ORIDIO
7
+ Project-URL: Documentation, https://oridio.org/docs
8
+ Author-email: Oridio <team@oridio.org>
9
+ License: Apache-2.0
10
+ Keywords: ai,control-plane,langchain,langgraph,llm,openai,proxy
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Requires-Python: >=3.9
21
+ Requires-Dist: httpx>=0.27.0
22
+ Requires-Dist: opentelemetry-api>=1.20.0
23
+ Requires-Dist: opentelemetry-instrumentation-httpx>=0.45b0
24
+ Requires-Dist: opentelemetry-instrumentation-requests>=0.45b0
25
+ Requires-Dist: pydantic>=2.0.0
26
+ Requires-Dist: typing-extensions>=4.0.0
27
+ Requires-Dist: websockets>=12.0
28
+ Provides-Extra: dev
29
+ Requires-Dist: mypy; extra == 'dev'
30
+ Requires-Dist: pytest-asyncio>=0.21; extra == 'dev'
31
+ Requires-Dist: pytest>=7.0; extra == 'dev'
32
+ Requires-Dist: ruff; extra == 'dev'
33
+ Requires-Dist: types-requests; extra == 'dev'
34
+ Provides-Extra: langchain
35
+ Requires-Dist: langchain-openai>=0.1.0; extra == 'langchain'
36
+ Description-Content-Type: text/markdown
37
+
38
+ # Oridio Python SDK
39
+
40
+ [![PyPI version](https://badge.fury.io/py/oridio.svg)](https://badge.fury.io/py/oridio)
41
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
42
+
43
+ The official Python SDK for [Oridio](https://oridio.org) — the Enterprise AI Control Plane.
44
+
45
+ Oridio is a high-performance, drop-in OpenAI-compatible proxy that provides:
46
+ - 🛡️ **Policy Enforcement:** Set cost limits, redact PII, block toxic content, and detect prompt injections before they reach the LLM.
47
+ - ⚡ **Semantic Caching:** Serve identical or semantically similar requests instantly from cache, saving tokens and reducing latency.
48
+ - 🔀 **Intelligent Routing:** Automatically route requests to fallback models when primary providers experience downtime.
49
+ - 📊 **Observability & Audit:** Full telemetry, usage analytics, and SOC2-compliant audit logs.
50
+ - 🤖 **Agent-Ready:** Native integration with LangGraph, CrewAI, and other agentic frameworks out of the box.
51
+
52
+ ## Installation
53
+
54
+ Install the base package:
55
+ ```bash
56
+ pip install oridio
57
+ ```
58
+
59
+ If you are using LangChain, you can install the optional dependencies:
60
+ ```bash
61
+ pip install "oridio[langchain]"
62
+ ```
63
+
64
+ ## Quick Start
65
+
66
+ ### 1. Drop-in OpenAI Replacement
67
+
68
+ Use the `OridioClient` exactly as you would use the `OpenAI` client. All your existing code will continue to work, but with added security and caching.
69
+
70
+ ```python
71
+ import oridio
72
+
73
+ client = oridio.OridioClient(
74
+ api_key="sk-or-your-key",
75
+ proxy_url="http://localhost:8080", # Point to your Oridio proxy
76
+ )
77
+
78
+ response = client.chat.completions.create(
79
+ model="gpt-4o",
80
+ messages=[{"role": "user", "content": "Explain quantum computing in one sentence."}],
81
+ )
82
+ print(response.choices[0].message.content)
83
+ print(f"Cache hit: {response.cache_hit}") # True on repeated or similar requests
84
+ ```
85
+
86
+ ### 2. LangGraph / LangChain Integration (Zero Code Change)
87
+
88
+ Because Oridio acts as an OpenAI-compatible endpoint, integrating with LangChain is as simple as overriding the `base_url`.
89
+
90
+ ```python
91
+ from langchain_openai import ChatOpenAI
92
+
93
+ llm = ChatOpenAI(
94
+ model="gpt-4o",
95
+ base_url="http://localhost:8080/v1", # Point to your Oridio proxy
96
+ api_key="sk-or-your-key",
97
+ )
98
+ ```
99
+
100
+ ### 3. Asynchronous Usage
101
+
102
+ For high-throughput or asynchronous applications, use the `AsyncOridioClient`.
103
+
104
+ ```python
105
+ import asyncio
106
+ from oridio import AsyncOridioClient
107
+
108
+ async def main():
109
+ async with AsyncOridioClient(api_key="sk-or-your-key") as client:
110
+ response = await client.chat.completions.create(
111
+ model="gpt-4o",
112
+ messages=[{"role": "user", "content": "Hello async!"}],
113
+ )
114
+ print(response.choices[0].message.content)
115
+
116
+ asyncio.run(main())
117
+ ```
118
+
119
+ ## Advanced Policy Management
120
+
121
+ The SDK also allows you to interact with the **Oridio Control Plane** to manage policies programmatically.
122
+
123
+ ```python
124
+ client = oridio.OridioClient(
125
+ admin_token="your-admin-token",
126
+ control_plane_url="http://localhost:3000",
127
+ )
128
+
129
+ # Create an advanced policy for cost optimization and safety
130
+ policy = client.policies.create({
131
+ "name": "strict-production-guardrails",
132
+ "rules": [
133
+ {
134
+ "id": "cost-limit",
135
+ "name": "Daily Cost Limit",
136
+ "action": "block",
137
+ "conditions": {"cost_limit": {"daily_usd": 100}}
138
+ },
139
+ {
140
+ "id": "pii-redaction",
141
+ "name": "Redact Sensitive Info",
142
+ "action": "redact",
143
+ "pii_types": ["EMAIL", "CREDIT_CARD", "SSN"]
144
+ }
145
+ ]
146
+ })
147
+
148
+ # Deploy the policy to all active Data Planes (Proxies)
149
+ client.policies.deploy(policy.id)
150
+ print(f"Deployed policy: {policy.name}")
151
+ ```
152
+
153
+ ## Error Handling
154
+
155
+ Oridio provides strongly-typed exceptions so your applications can react gracefully to policy blocks or rate limits.
156
+
157
+ ```python
158
+ from oridio import OridioPolicyBlockedError, OridioRateLimitError, OridioAuthError
159
+
160
+ try:
161
+ response = client.chat.completions.create(model="gpt-4o", messages=[...])
162
+ except OridioPolicyBlockedError as e:
163
+ # Handle requests blocked by your custom guardrails (e.g., PII detected, cost limit exceeded)
164
+ print(f"🚨 Request Blocked: {e.reason}")
165
+ print(f"Triggered Rules: {e.rules_matched}")
166
+ except OridioRateLimitError as e:
167
+ # Handle Oridio or provider rate limits
168
+ print(f"⏳ Rate limited. Retry after {e.retry_after} seconds.")
169
+ except OridioAuthError:
170
+ print("❌ Invalid API key.")
171
+ ```
172
+
173
+ ## API Key Management & Usage Analytics
174
+
175
+ Manage programmatic access and track spend:
176
+
177
+ ```python
178
+ # Create a scoped key
179
+ key = client.keys.create(name="production-backend-key", spend_limit_usd=50)
180
+ print(f"Secret: {key.secret}") # Store securely! Only shown once.
181
+
182
+ # Track Usage
183
+ records = client.usage.list(limit=100)
184
+ total_cost = sum(r.estimated_cost_usd for r in records)
185
+ cache_hits = sum(1 for r in records if r.cache_hit)
186
+ print(f"Total spend: ${total_cost:.4f} | Cache hits: {cache_hits}/{len(records)}")
187
+ ```
188
+
189
+ ## Examples
190
+
191
+ See [`examples/`](../../examples/) for full working demos:
192
+ - `basic_proxy.py` — Simple script showing basic chat completion via Oridio.
193
+ - `advanced_policy.py` — Demonstrates catching and handling policy enforcement blocks.
194
+ - `langgraph_example.py` — LangGraph ReAct agent with policy enforcement.
195
+ - `crewai_example.py` — Multi-agent CrewAI pipeline with cost tracking.
196
+
197
+ ---
198
+
199
+ ## Known Limitations & Intentional Gaps
200
+
201
+ | Feature | Status | Notes |
202
+ |---|---|---|
203
+ | `keys.create()` response | Fixed in SDK | CP returns `{"status": "success", "data": {"id": ..., "key": ...}}`. The SDK unwraps this and normalises `key` → `secret`. |
204
+ | `keys.list()` response | Handled | CP may return a flat array or `{"data": [...]}` — both are handled. |
205
+ | `estimated_cost_usd` for unknown models | By design | When `estimated_cost_known=False`, cost is `0.0` (not a real zero). Do not aggregate for spend reporting without checking this flag. |
206
+ | `McpServer.sandbox_preference` | Documented | Default is `"process"`. Firecracker requires KVM-capable Linux hosts; will hard-deny when `require_strong_isolation=True` and Firecracker is unavailable. |
207
+ | Async MCP client | Not yet implemented | `AsyncOridioClient` exposes `chat.completions.create` but not the full MCP management API. Use the synchronous `OridioClient` for MCP admin operations. |
208
+ | Admin dashboard | Deferred | No web UI. All operations use this SDK or the REST API directly. |
209
+ | SSO / SAML | Not implemented | Auth is via static admin token or JWT. |
oridio-0.1.0/README.md ADDED
@@ -0,0 +1,172 @@
1
+ # Oridio Python SDK
2
+
3
+ [![PyPI version](https://badge.fury.io/py/oridio.svg)](https://badge.fury.io/py/oridio)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ The official Python SDK for [Oridio](https://oridio.org) — the Enterprise AI Control Plane.
7
+
8
+ Oridio is a high-performance, drop-in OpenAI-compatible proxy that provides:
9
+ - 🛡️ **Policy Enforcement:** Set cost limits, redact PII, block toxic content, and detect prompt injections before they reach the LLM.
10
+ - ⚡ **Semantic Caching:** Serve identical or semantically similar requests instantly from cache, saving tokens and reducing latency.
11
+ - 🔀 **Intelligent Routing:** Automatically route requests to fallback models when primary providers experience downtime.
12
+ - 📊 **Observability & Audit:** Full telemetry, usage analytics, and SOC2-compliant audit logs.
13
+ - 🤖 **Agent-Ready:** Native integration with LangGraph, CrewAI, and other agentic frameworks out of the box.
14
+
15
+ ## Installation
16
+
17
+ Install the base package:
18
+ ```bash
19
+ pip install oridio
20
+ ```
21
+
22
+ If you are using LangChain, you can install the optional dependencies:
23
+ ```bash
24
+ pip install "oridio[langchain]"
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ### 1. Drop-in OpenAI Replacement
30
+
31
+ Use the `OridioClient` exactly as you would use the `OpenAI` client. All your existing code will continue to work, but with added security and caching.
32
+
33
+ ```python
34
+ import oridio
35
+
36
+ client = oridio.OridioClient(
37
+ api_key="sk-or-your-key",
38
+ proxy_url="http://localhost:8080", # Point to your Oridio proxy
39
+ )
40
+
41
+ response = client.chat.completions.create(
42
+ model="gpt-4o",
43
+ messages=[{"role": "user", "content": "Explain quantum computing in one sentence."}],
44
+ )
45
+ print(response.choices[0].message.content)
46
+ print(f"Cache hit: {response.cache_hit}") # True on repeated or similar requests
47
+ ```
48
+
49
+ ### 2. LangGraph / LangChain Integration (Zero Code Change)
50
+
51
+ Because Oridio acts as an OpenAI-compatible endpoint, integrating with LangChain is as simple as overriding the `base_url`.
52
+
53
+ ```python
54
+ from langchain_openai import ChatOpenAI
55
+
56
+ llm = ChatOpenAI(
57
+ model="gpt-4o",
58
+ base_url="http://localhost:8080/v1", # Point to your Oridio proxy
59
+ api_key="sk-or-your-key",
60
+ )
61
+ ```
62
+
63
+ ### 3. Asynchronous Usage
64
+
65
+ For high-throughput or asynchronous applications, use the `AsyncOridioClient`.
66
+
67
+ ```python
68
+ import asyncio
69
+ from oridio import AsyncOridioClient
70
+
71
+ async def main():
72
+ async with AsyncOridioClient(api_key="sk-or-your-key") as client:
73
+ response = await client.chat.completions.create(
74
+ model="gpt-4o",
75
+ messages=[{"role": "user", "content": "Hello async!"}],
76
+ )
77
+ print(response.choices[0].message.content)
78
+
79
+ asyncio.run(main())
80
+ ```
81
+
82
+ ## Advanced Policy Management
83
+
84
+ The SDK also allows you to interact with the **Oridio Control Plane** to manage policies programmatically.
85
+
86
+ ```python
87
+ client = oridio.OridioClient(
88
+ admin_token="your-admin-token",
89
+ control_plane_url="http://localhost:3000",
90
+ )
91
+
92
+ # Create an advanced policy for cost optimization and safety
93
+ policy = client.policies.create({
94
+ "name": "strict-production-guardrails",
95
+ "rules": [
96
+ {
97
+ "id": "cost-limit",
98
+ "name": "Daily Cost Limit",
99
+ "action": "block",
100
+ "conditions": {"cost_limit": {"daily_usd": 100}}
101
+ },
102
+ {
103
+ "id": "pii-redaction",
104
+ "name": "Redact Sensitive Info",
105
+ "action": "redact",
106
+ "pii_types": ["EMAIL", "CREDIT_CARD", "SSN"]
107
+ }
108
+ ]
109
+ })
110
+
111
+ # Deploy the policy to all active Data Planes (Proxies)
112
+ client.policies.deploy(policy.id)
113
+ print(f"Deployed policy: {policy.name}")
114
+ ```
115
+
116
+ ## Error Handling
117
+
118
+ Oridio provides strongly-typed exceptions so your applications can react gracefully to policy blocks or rate limits.
119
+
120
+ ```python
121
+ from oridio import OridioPolicyBlockedError, OridioRateLimitError, OridioAuthError
122
+
123
+ try:
124
+ response = client.chat.completions.create(model="gpt-4o", messages=[...])
125
+ except OridioPolicyBlockedError as e:
126
+ # Handle requests blocked by your custom guardrails (e.g., PII detected, cost limit exceeded)
127
+ print(f"🚨 Request Blocked: {e.reason}")
128
+ print(f"Triggered Rules: {e.rules_matched}")
129
+ except OridioRateLimitError as e:
130
+ # Handle Oridio or provider rate limits
131
+ print(f"⏳ Rate limited. Retry after {e.retry_after} seconds.")
132
+ except OridioAuthError:
133
+ print("❌ Invalid API key.")
134
+ ```
135
+
136
+ ## API Key Management & Usage Analytics
137
+
138
+ Manage programmatic access and track spend:
139
+
140
+ ```python
141
+ # Create a scoped key
142
+ key = client.keys.create(name="production-backend-key", spend_limit_usd=50)
143
+ print(f"Secret: {key.secret}") # Store securely! Only shown once.
144
+
145
+ # Track Usage
146
+ records = client.usage.list(limit=100)
147
+ total_cost = sum(r.estimated_cost_usd for r in records)
148
+ cache_hits = sum(1 for r in records if r.cache_hit)
149
+ print(f"Total spend: ${total_cost:.4f} | Cache hits: {cache_hits}/{len(records)}")
150
+ ```
151
+
152
+ ## Examples
153
+
154
+ See [`examples/`](../../examples/) for full working demos:
155
+ - `basic_proxy.py` — Simple script showing basic chat completion via Oridio.
156
+ - `advanced_policy.py` — Demonstrates catching and handling policy enforcement blocks.
157
+ - `langgraph_example.py` — LangGraph ReAct agent with policy enforcement.
158
+ - `crewai_example.py` — Multi-agent CrewAI pipeline with cost tracking.
159
+
160
+ ---
161
+
162
+ ## Known Limitations & Intentional Gaps
163
+
164
+ | Feature | Status | Notes |
165
+ |---|---|---|
166
+ | `keys.create()` response | Fixed in SDK | CP returns `{"status": "success", "data": {"id": ..., "key": ...}}`. The SDK unwraps this and normalises `key` → `secret`. |
167
+ | `keys.list()` response | Handled | CP may return a flat array or `{"data": [...]}` — both are handled. |
168
+ | `estimated_cost_usd` for unknown models | By design | When `estimated_cost_known=False`, cost is `0.0` (not a real zero). Do not aggregate for spend reporting without checking this flag. |
169
+ | `McpServer.sandbox_preference` | Documented | Default is `"process"`. Firecracker requires KVM-capable Linux hosts; will hard-deny when `require_strong_isolation=True` and Firecracker is unavailable. |
170
+ | Async MCP client | Not yet implemented | `AsyncOridioClient` exposes `chat.completions.create` but not the full MCP management API. Use the synchronous `OridioClient` for MCP admin operations. |
171
+ | Admin dashboard | Deferred | No web UI. All operations use this SDK or the REST API directly. |
172
+ | SSO / SAML | Not implemented | Auth is via static admin token or JWT. |
@@ -0,0 +1,99 @@
1
+ """
2
+ Oridio Python SDK — AI Control Plane
3
+
4
+ Drop-in OpenAI-compatible proxy with policy enforcement,
5
+ semantic caching, cost controls, and observability.
6
+ """
7
+
8
+ __version__ = "0.1.0"
9
+
10
+ from .client import OridioClient, AsyncOridioClient
11
+ from .decorators import oridio_protected
12
+ from .context import (
13
+ set_agent_id, get_agent_id,
14
+ set_session_id, get_session_id,
15
+ set_run_id, get_run_id
16
+ )
17
+ from .bootstrap import init
18
+ from .tools.bridge import wrap_tool, register_autogen_tool
19
+ from .tools.schema import extract_mcp_schema
20
+ from .interceptors import (
21
+ create_openai_client,
22
+ create_async_openai_client,
23
+ create_anthropic_client,
24
+ create_async_anthropic_client,
25
+ spawn_child,
26
+ )
27
+ from .exceptions import (
28
+ OridioError,
29
+ OridioAPIError,
30
+ OridioAuthError,
31
+ OridioRateLimitError,
32
+ OridioPolicyBlockedError,
33
+ OridioTimeoutError,
34
+ OridioHITLPendingError,
35
+ OridioHITLTimeoutError,
36
+ OridioHITLDeniedError,
37
+ )
38
+ from .models import (
39
+ ChatMessage,
40
+ ChatCompletionRequest,
41
+ ChatCompletionResponse,
42
+ McpGrant,
43
+ McpServer,
44
+ McpTool,
45
+ Policy,
46
+ PolicyRule,
47
+ ApiKey,
48
+ UsageRecord,
49
+ AgentStatus,
50
+ AgentIdentity,
51
+ MCPMeta,
52
+ MCPParams,
53
+ MCPPayload,
54
+ FirewallVerdict,
55
+ OridioResponse,
56
+ )
57
+
58
+ __all__ = [
59
+ "__version__",
60
+ # Client
61
+ "OridioClient",
62
+ "AsyncOridioClient",
63
+ "oridio_protected",
64
+ "create_openai_client",
65
+ "create_async_openai_client",
66
+ "create_anthropic_client",
67
+ "create_async_anthropic_client",
68
+ "spawn_child",
69
+ # Exceptions
70
+ "OridioError",
71
+ "OridioAPIError",
72
+ "OridioAuthError",
73
+ "OridioRateLimitError",
74
+ "OridioPolicyBlockedError",
75
+ "OridioTimeoutError",
76
+ "OridioHITLPendingError",
77
+ "OridioHITLTimeoutError",
78
+ "OridioHITLDeniedError",
79
+ "extract_mcp_schema",
80
+ # Models
81
+ "ChatMessage",
82
+ "ChatCompletionRequest",
83
+ "ChatCompletionResponse",
84
+ "McpGrant",
85
+ "McpServer",
86
+ "McpTool",
87
+ "Policy",
88
+ "PolicyRule",
89
+ "ApiKey",
90
+ "UsageRecord",
91
+ "AgentStatus",
92
+ "AgentIdentity",
93
+ "MCPMeta",
94
+ "MCPParams",
95
+ "MCPPayload",
96
+ "FirewallVerdict",
97
+ "OridioResponse",
98
+ ]
99
+
@@ -0,0 +1,45 @@
1
+ import os
2
+ import logging
3
+ from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
4
+ from opentelemetry.instrumentation.requests import RequestsInstrumentor
5
+ from .context import get_agent_id
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ def _request_hook(span, request):
10
+ """Inject Oridio headers into outbound HTTP requests."""
11
+ agent_id = get_agent_id()
12
+ if agent_id:
13
+ request.headers["X-Oridio-Agent-Id"] = agent_id
14
+
15
+ # The JWT is typically already in the environment or set by the user,
16
+ # but if we wanted to auto-inject a known key here we could.
17
+ oridio_api_key = os.environ.get("ORIDIO_API_KEY")
18
+ if oridio_api_key and "Authorization" not in request.headers:
19
+ request.headers["Authorization"] = f"Bearer {oridio_api_key}"
20
+
21
+ def init():
22
+ """
23
+ Initialize global Oridio interception for Python.
24
+
25
+ 1. Sets OPENAI_BASE_URL and ANTHROPIC_BASE_URL to point to the proxy.
26
+ 2. Hooks httpx and requests via OpenTelemetry to inject identity headers.
27
+ """
28
+ proxy_url = os.environ.get("ORIDIO_PROXY_URL", "http://localhost:8080")
29
+
30
+ # Force OpenAI and Anthropic SDKs to use the Oridio proxy
31
+ os.environ.setdefault("OPENAI_BASE_URL", f"{proxy_url}/v1")
32
+ os.environ.setdefault("ANTHROPIC_BASE_URL", f"{proxy_url}/v1")
33
+
34
+ try:
35
+ HTTPXClientInstrumentor().instrument(request_hook=_request_hook)
36
+ logger.info("Successfully instrumented httpx.")
37
+ except Exception as e:
38
+ logger.warning(f"Failed to instrument httpx: {e}")
39
+
40
+ try:
41
+ RequestsInstrumentor().instrument(request_hook=_request_hook)
42
+ logger.info("Successfully instrumented requests.")
43
+ except Exception as e:
44
+ logger.warning(f"Failed to instrument requests: {e}")
45
+