revenium-python-sdk 0.1.5__tar.gz → 0.1.6__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.
Files changed (89) hide show
  1. {revenium_python_sdk-0.1.5/revenium_python_sdk.egg-info → revenium_python_sdk-0.1.6}/PKG-INFO +20 -77
  2. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/README.md +19 -76
  3. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/pyproject.toml +1 -1
  4. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/config.py +2 -41
  5. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/fields.py +28 -6
  6. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/anthropic/config.py +0 -3
  7. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/anthropic/middleware.py +0 -75
  8. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/common/__init__.py +0 -14
  9. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/common/trace_fields.py +3 -11
  10. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/common/utils.py +0 -66
  11. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/config.py +0 -1
  12. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/client/config.py +0 -16
  13. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/client/middleware.py +0 -20
  14. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/config.py +0 -3
  15. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/middleware.py +0 -26
  16. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6/revenium_python_sdk.egg-info}/PKG-INFO +20 -77
  17. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_python_sdk.egg-info/SOURCES.txt +0 -4
  18. revenium_python_sdk-0.1.5/revenium_middleware/anthropic/summary_printer.py +0 -286
  19. revenium_python_sdk-0.1.5/revenium_middleware/google/common/summary_printer.py +0 -271
  20. revenium_python_sdk-0.1.5/revenium_middleware/litellm/client/summary_printer.py +0 -314
  21. revenium_python_sdk-0.1.5/revenium_middleware/openai/summary_printer.py +0 -292
  22. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/LICENSE +0 -0
  23. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/__init__.py +0 -0
  24. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/__init__.py +0 -0
  25. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/context.py +0 -0
  26. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/decorators.py +0 -0
  27. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/enforcement.py +0 -0
  28. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/exceptions.py +0 -0
  29. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/metering.py +0 -0
  30. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/patch_registry.py +0 -0
  31. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/prompt_extraction.py +0 -0
  32. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/subscriber.py +0 -0
  33. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/_core/trace_fields.py +0 -0
  34. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/agentic_outcomes.py +0 -0
  35. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/anthropic/__init__.py +0 -0
  36. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/anthropic/bedrock_adapter.py +0 -0
  37. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/anthropic/prompt_extractor.py +0 -0
  38. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/anthropic/provider.py +0 -0
  39. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/anthropic/trace_fields.py +0 -0
  40. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/fal/__init__.py +0 -0
  41. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/fal/_metering.py +0 -0
  42. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/fal/config.py +0 -0
  43. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/fal/middleware.py +0 -0
  44. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/fal/trace_fields.py +0 -0
  45. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/__init__.py +0 -0
  46. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/common/exceptions.py +0 -0
  47. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/common/protocols.py +0 -0
  48. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/common/types.py +0 -0
  49. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/google_ai/__init__.py +0 -0
  50. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/google_ai/middleware.py +0 -0
  51. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/google_ai/provider.py +0 -0
  52. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/prompt_extractor.py +0 -0
  53. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/vertex_ai/__init__.py +0 -0
  54. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/vertex_ai/middleware.py +0 -0
  55. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/google/vertex_ai/provider.py +0 -0
  56. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/__init__.py +0 -0
  57. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/client/__init__.py +0 -0
  58. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/client/context.py +0 -0
  59. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/client/decorators.py +0 -0
  60. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/client/hooks.py +0 -0
  61. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/client/integrations/__init__.py +0 -0
  62. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/client/integrations/crewai.py +0 -0
  63. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/client/trace_fields.py +0 -0
  64. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/client/validation.py +0 -0
  65. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/proxy/__init__.py +0 -0
  66. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/litellm/proxy/middleware.py +0 -0
  67. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/ollama/__init__.py +0 -0
  68. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/ollama/middleware.py +0 -0
  69. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/ollama/trace_fields.py +0 -0
  70. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/__init__.py +0 -0
  71. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/azure_config.py +0 -0
  72. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/azure_model_resolver.py +0 -0
  73. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/exceptions.py +0 -0
  74. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/langchain/__init__.py +0 -0
  75. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/langchain/_utils.py +0 -0
  76. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/langchain/unified_handler.py +0 -0
  77. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/prompt_extractor.py +0 -0
  78. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/provider.py +0 -0
  79. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/openai/trace_fields.py +0 -0
  80. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/perplexity/__init__.py +0 -0
  81. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/perplexity/middleware.py +0 -0
  82. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/perplexity/perplexity_sdk.py +0 -0
  83. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/perplexity/provider.py +0 -0
  84. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_middleware/perplexity/trace_fields.py +0 -0
  85. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_python_sdk.egg-info/dependency_links.txt +0 -0
  86. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_python_sdk.egg-info/requires.txt +0 -0
  87. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/revenium_python_sdk.egg-info/top_level.txt +0 -0
  88. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/setup.cfg +0 -0
  89. {revenium_python_sdk-0.1.5 → revenium_python_sdk-0.1.6}/tests/test_metering.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: revenium-python-sdk
3
- Version: 0.1.5
3
+ Version: 0.1.6
4
4
  Summary: The official Revenium Python SDK — unified AI metering middleware for OpenAI, Anthropic, Google, Ollama, LiteLLM, Perplexity, and fal.ai.
5
5
  Author-email: Revenium <support@revenium.io>
6
6
  License: MIT
@@ -194,7 +194,7 @@ import revenium_middleware_openai # Auto-initializes on import
194
194
 
195
195
  client = openai.OpenAI()
196
196
  response = client.chat.completions.create(
197
- model="gpt-5.5",
197
+ model="gpt-4o-mini",
198
198
  messages=[{"role": "user", "content": "Hello!"}]
199
199
  )
200
200
  print(response.choices[0].message.content)
@@ -244,7 +244,7 @@ client = openai.OpenAI()
244
244
 
245
245
  # Basic chat completion
246
246
  response = client.chat.completions.create(
247
- model="gpt-5.5",
247
+ model="gpt-4o-mini",
248
248
  messages=[{"role": "user", "content": "Hello!"}],
249
249
  usage_metadata={
250
250
  "organizationName": "AcmeCorp",
@@ -256,7 +256,7 @@ response = client.chat.completions.create(
256
256
 
257
257
  # Streaming
258
258
  stream = client.chat.completions.create(
259
- model="gpt-5.5",
259
+ model="gpt-4o-mini",
260
260
  messages=[{"role": "user", "content": "Tell me a story"}],
261
261
  stream=True
262
262
  )
@@ -547,7 +547,7 @@ litellm.api_base = os.getenv("LITELLM_PROXY_URL")
547
547
  litellm.api_key = os.getenv("LITELLM_API_KEY")
548
548
 
549
549
  response = litellm.completion(
550
- model="gpt-5.5",
550
+ model="gpt-4o-mini",
551
551
  messages=[{"role": "user", "content": "Hello!"}],
552
552
  usage_metadata={
553
553
  "organizationName": "AcmeCorp",
@@ -705,7 +705,7 @@ handler = ReveniumCallbackHandler(
705
705
  agent_name="support_agent"
706
706
  )
707
707
 
708
- llm = ChatOpenAI(model="gpt-5.5", callbacks=[handler])
708
+ llm = ChatOpenAI(model="gpt-4o-mini", callbacks=[handler])
709
709
  response = llm.invoke("Hello!")
710
710
  ```
711
711
 
@@ -744,7 +744,7 @@ result = agent.invoke(
744
744
  from revenium_middleware_langchain import AsyncReveniumCallbackHandler
745
745
 
746
746
  handler = AsyncReveniumCallbackHandler(trace_id="async-session")
747
- llm = ChatOpenAI(model="gpt-5.5", callbacks=[handler])
747
+ llm = ChatOpenAI(model="gpt-4o-mini", callbacks=[handler])
748
748
  response = await llm.ainvoke("Hello!")
749
749
  ```
750
750
 
@@ -790,7 +790,7 @@ Add business context to any API call by passing a `usage_metadata` dictionary. A
790
790
 
791
791
  ```python
792
792
  response = client.chat.completions.create(
793
- model="gpt-5.5",
793
+ model="gpt-4o-mini",
794
794
  messages=[{"role": "user", "content": "Hello!"}],
795
795
  usage_metadata={
796
796
  "trace_id": "conv-28a7e9d4",
@@ -812,7 +812,7 @@ response = client.chat.completions.create(
812
812
  )
813
813
  ```
814
814
 
815
- **Deprecation notice:** The old field names `organizationId`, `organization_id`, `productId`, and `product_id` are still supported for backward compatibility but are deprecated. Use `organizationName` and `productName` for new implementations.
815
+ **Deprecation notice:** The legacy field aliases `organizationId`, `organization_id`, `productId`, and `product_id` are accepted by this SDK only as an input-layer convenience and emit a `DeprecationWarning`. The Revenium backend no longer accepts them — they are translated to `organizationName` / `productName` before the wire call. Migrate to `organization_name` / `organizationName` and `product_name` / `productName` now; the input-layer aliases will be removed in the next major release.
816
816
 
817
817
  **API Reference:** [Complete metadata field documentation](https://revenium.readme.io/reference/meter_ai_completion)
818
818
 
@@ -853,7 +853,7 @@ REVENIUM_TRACE_TYPE=customer-support
853
853
 
854
854
  ```python
855
855
  response = client.chat.completions.create(
856
- model="gpt-5.5",
856
+ model="gpt-4o-mini",
857
857
  messages=[{"role": "user", "content": "Hello!"}],
858
858
  usage_metadata={
859
859
  "environment": "production",
@@ -877,7 +877,7 @@ workflow_id = str(uuid.uuid4())
877
877
 
878
878
  # Step 1: Parent operation
879
879
  parent_response = client.chat.completions.create(
880
- model="gpt-5.5",
880
+ model="gpt-4o-mini",
881
881
  messages=[{"role": "user", "content": "Analyze this document"}],
882
882
  usage_metadata={
883
883
  "trace_id": "analysis-session-456",
@@ -888,7 +888,7 @@ parent_response = client.chat.completions.create(
888
888
 
889
889
  # Step 2: Child operation linked to parent
890
890
  child_response = client.chat.completions.create(
891
- model="gpt-5.5",
891
+ model="gpt-4o-mini",
892
892
  messages=[{"role": "user", "content": "Summarize findings"}],
893
893
  usage_metadata={
894
894
  "trace_id": "analysis-session-456",
@@ -919,7 +919,7 @@ from revenium_middleware import revenium_metadata
919
919
  def handle_customer_query(question: str) -> str:
920
920
  # All API calls automatically include the decorator metadata
921
921
  response = client.chat.completions.create(
922
- model="gpt-5.5",
922
+ model="gpt-4o-mini",
923
923
  messages=[{"role": "user", "content": question}]
924
924
  )
925
925
  return response.choices[0].message.content
@@ -958,13 +958,13 @@ def outer_function():
958
958
  def mixed_metadata():
959
959
  # Uses decorator metadata
960
960
  response1 = client.chat.completions.create(
961
- model="gpt-5.5",
961
+ model="gpt-4o-mini",
962
962
  messages=[{"role": "user", "content": "Hello"}]
963
963
  )
964
964
 
965
965
  # API-level metadata overrides decorator's task_type
966
966
  response2 = client.chat.completions.create(
967
- model="gpt-5.5",
967
+ model="gpt-4o-mini",
968
968
  messages=[{"role": "user", "content": "Hello"}],
969
969
  usage_metadata={
970
970
  "task_type": "special-override", # Overrides decorator
@@ -993,7 +993,7 @@ from revenium_middleware import revenium_meter, revenium_metadata
993
993
  def premium_feature(prompt: str) -> str:
994
994
  # This WILL be metered (decorated with @revenium_meter)
995
995
  response = client.chat.completions.create(
996
- model="gpt-5.5",
996
+ model="gpt-4o-mini",
997
997
  messages=[{"role": "user", "content": prompt}]
998
998
  )
999
999
  return response.choices[0].message.content
@@ -1001,7 +1001,7 @@ def premium_feature(prompt: str) -> str:
1001
1001
  def free_feature(prompt: str) -> str:
1002
1002
  # This will NOT be metered (no @revenium_meter decorator)
1003
1003
  response = client.chat.completions.create(
1004
- model="gpt-5.5",
1004
+ model="gpt-4o-mini",
1005
1005
  messages=[{"role": "user", "content": prompt}]
1006
1006
  )
1007
1007
  return response.choices[0].message.content
@@ -1087,7 +1087,7 @@ from openai import OpenAI
1087
1087
 
1088
1088
  client = OpenAI()
1089
1089
  response = client.chat.completions.create(
1090
- model="gpt-5.5",
1090
+ model="gpt-4o-mini",
1091
1091
  messages=[
1092
1092
  {"role": "system", "content": "You are a helpful assistant."},
1093
1093
  {"role": "user", "content": "What is the capital of France?"}
@@ -1109,62 +1109,6 @@ Prompt capture works with both streaming and non-streaming requests, and with mu
1109
1109
 
1110
1110
  ---
1111
1111
 
1112
- ## Terminal Summary Output
1113
-
1114
- Display a cost and usage summary in your terminal after each API request. Useful for development, debugging, and monitoring AI costs in real-time.
1115
-
1116
- ### Configuration
1117
-
1118
- | Environment Variable | Values | Description |
1119
- |---------------------|--------|-------------|
1120
- | `REVENIUM_PRINT_SUMMARY` | `false` (default), `true` or `human`, `json` | Controls output format |
1121
- | `REVENIUM_TEAM_ID` | Your team ID | Required to fetch and display cost information |
1122
-
1123
- ```bash
1124
- # Enable human-readable output
1125
- export REVENIUM_PRINT_SUMMARY=human
1126
-
1127
- # Required for cost display (find in Revenium web app)
1128
- export REVENIUM_TEAM_ID=your-team-id-here
1129
- ```
1130
-
1131
- ### Human-Readable Format
1132
-
1133
- ```
1134
- ============================================================
1135
- REVENIUM USAGE SUMMARY
1136
- ============================================================
1137
- Model: gpt-5.5
1138
- Provider: OPENAI
1139
- Duration: 1.23s
1140
-
1141
- Token Usage:
1142
- Input Tokens: 150
1143
- Output Tokens: 250
1144
- Total Tokens: 400
1145
-
1146
- Cost: $0.000045
1147
-
1148
- Trace ID: abc-123
1149
- ============================================================
1150
- ```
1151
-
1152
- ### JSON Format
1153
-
1154
- ```json
1155
- {"model":"gpt-5.5","provider":"OPENAI","durationSeconds":1.23,"inputTokenCount":150,"outputTokenCount":250,"totalTokenCount":400,"cost":0.000045,"costStatus":"available","traceId":"abc-123"}
1156
- ```
1157
-
1158
- ### Cost Status
1159
-
1160
- | Scenario | Display |
1161
- |----------|---------|
1162
- | Cost available | `$0.000045` |
1163
- | `REVENIUM_TEAM_ID` set, cost pending | `Pending (aggregating... check Revenium dashboard)` |
1164
- | `REVENIUM_TEAM_ID` not set | `Add REVENIUM_TEAM_ID to see pricing` |
1165
-
1166
- ---
1167
-
1168
1112
  ## Cost Controls / Enforcement
1169
1113
 
1170
1114
  Block outbound provider requests client-side when a Revenium cost control trips. When the circuit breaker is enabled, the middleware polls compiled enforcement rules from the Revenium API in a background daemon thread and raises `BudgetExceededError` **before** the upstream call, preventing spend beyond the configured limit.
@@ -1243,7 +1187,7 @@ client = openai.OpenAI()
1243
1187
 
1244
1188
  try:
1245
1189
  response = client.chat.completions.create(
1246
- model="gpt-5.5",
1190
+ model="gpt-4o-mini",
1247
1191
  messages=[{"role": "user", "content": "Summarize the meeting notes"}],
1248
1192
  )
1249
1193
  except BudgetExceededError as exc:
@@ -1282,9 +1226,8 @@ See [`examples/openai/openai_blocking_demo.py`](examples/openai/openai_blocking_
1282
1226
  | `REVENIUM_METERING_BASE_URL` | `https://api.revenium.ai` | Revenium API endpoint |
1283
1227
  | `REVENIUM_LOG_LEVEL` | `INFO` | Log level: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` |
1284
1228
  | `REVENIUM_CAPTURE_PROMPTS` | `false` | Enable prompt capture |
1285
- | `REVENIUM_PRINT_SUMMARY` | `false` | Terminal output: `false`, `true`/`human`, `json` |
1286
1229
  | `REVENIUM_SELECTIVE_METERING` | `false` | Only meter `@revenium_meter` decorated functions |
1287
- | `REVENIUM_TEAM_ID` | - | Team ID for cost display in terminal summary |
1230
+ | `REVENIUM_TEAM_ID` | - | Team ID for cost lookups |
1288
1231
  | `REVENIUM_ENVIRONMENT` | - | Deployment environment (auto-detects from `ENVIRONMENT`, `DEPLOYMENT_ENV`) |
1289
1232
  | `REVENIUM_REGION` | - | Cloud region (auto-detects from `AWS_REGION`, `AZURE_REGION`, `GCP_REGION`) |
1290
1233
  | `REVENIUM_CREDENTIAL_ALIAS` | - | Human-readable API key name |
@@ -106,7 +106,7 @@ import revenium_middleware_openai # Auto-initializes on import
106
106
 
107
107
  client = openai.OpenAI()
108
108
  response = client.chat.completions.create(
109
- model="gpt-5.5",
109
+ model="gpt-4o-mini",
110
110
  messages=[{"role": "user", "content": "Hello!"}]
111
111
  )
112
112
  print(response.choices[0].message.content)
@@ -156,7 +156,7 @@ client = openai.OpenAI()
156
156
 
157
157
  # Basic chat completion
158
158
  response = client.chat.completions.create(
159
- model="gpt-5.5",
159
+ model="gpt-4o-mini",
160
160
  messages=[{"role": "user", "content": "Hello!"}],
161
161
  usage_metadata={
162
162
  "organizationName": "AcmeCorp",
@@ -168,7 +168,7 @@ response = client.chat.completions.create(
168
168
 
169
169
  # Streaming
170
170
  stream = client.chat.completions.create(
171
- model="gpt-5.5",
171
+ model="gpt-4o-mini",
172
172
  messages=[{"role": "user", "content": "Tell me a story"}],
173
173
  stream=True
174
174
  )
@@ -459,7 +459,7 @@ litellm.api_base = os.getenv("LITELLM_PROXY_URL")
459
459
  litellm.api_key = os.getenv("LITELLM_API_KEY")
460
460
 
461
461
  response = litellm.completion(
462
- model="gpt-5.5",
462
+ model="gpt-4o-mini",
463
463
  messages=[{"role": "user", "content": "Hello!"}],
464
464
  usage_metadata={
465
465
  "organizationName": "AcmeCorp",
@@ -617,7 +617,7 @@ handler = ReveniumCallbackHandler(
617
617
  agent_name="support_agent"
618
618
  )
619
619
 
620
- llm = ChatOpenAI(model="gpt-5.5", callbacks=[handler])
620
+ llm = ChatOpenAI(model="gpt-4o-mini", callbacks=[handler])
621
621
  response = llm.invoke("Hello!")
622
622
  ```
623
623
 
@@ -656,7 +656,7 @@ result = agent.invoke(
656
656
  from revenium_middleware_langchain import AsyncReveniumCallbackHandler
657
657
 
658
658
  handler = AsyncReveniumCallbackHandler(trace_id="async-session")
659
- llm = ChatOpenAI(model="gpt-5.5", callbacks=[handler])
659
+ llm = ChatOpenAI(model="gpt-4o-mini", callbacks=[handler])
660
660
  response = await llm.ainvoke("Hello!")
661
661
  ```
662
662
 
@@ -702,7 +702,7 @@ Add business context to any API call by passing a `usage_metadata` dictionary. A
702
702
 
703
703
  ```python
704
704
  response = client.chat.completions.create(
705
- model="gpt-5.5",
705
+ model="gpt-4o-mini",
706
706
  messages=[{"role": "user", "content": "Hello!"}],
707
707
  usage_metadata={
708
708
  "trace_id": "conv-28a7e9d4",
@@ -724,7 +724,7 @@ response = client.chat.completions.create(
724
724
  )
725
725
  ```
726
726
 
727
- **Deprecation notice:** The old field names `organizationId`, `organization_id`, `productId`, and `product_id` are still supported for backward compatibility but are deprecated. Use `organizationName` and `productName` for new implementations.
727
+ **Deprecation notice:** The legacy field aliases `organizationId`, `organization_id`, `productId`, and `product_id` are accepted by this SDK only as an input-layer convenience and emit a `DeprecationWarning`. The Revenium backend no longer accepts them — they are translated to `organizationName` / `productName` before the wire call. Migrate to `organization_name` / `organizationName` and `product_name` / `productName` now; the input-layer aliases will be removed in the next major release.
728
728
 
729
729
  **API Reference:** [Complete metadata field documentation](https://revenium.readme.io/reference/meter_ai_completion)
730
730
 
@@ -765,7 +765,7 @@ REVENIUM_TRACE_TYPE=customer-support
765
765
 
766
766
  ```python
767
767
  response = client.chat.completions.create(
768
- model="gpt-5.5",
768
+ model="gpt-4o-mini",
769
769
  messages=[{"role": "user", "content": "Hello!"}],
770
770
  usage_metadata={
771
771
  "environment": "production",
@@ -789,7 +789,7 @@ workflow_id = str(uuid.uuid4())
789
789
 
790
790
  # Step 1: Parent operation
791
791
  parent_response = client.chat.completions.create(
792
- model="gpt-5.5",
792
+ model="gpt-4o-mini",
793
793
  messages=[{"role": "user", "content": "Analyze this document"}],
794
794
  usage_metadata={
795
795
  "trace_id": "analysis-session-456",
@@ -800,7 +800,7 @@ parent_response = client.chat.completions.create(
800
800
 
801
801
  # Step 2: Child operation linked to parent
802
802
  child_response = client.chat.completions.create(
803
- model="gpt-5.5",
803
+ model="gpt-4o-mini",
804
804
  messages=[{"role": "user", "content": "Summarize findings"}],
805
805
  usage_metadata={
806
806
  "trace_id": "analysis-session-456",
@@ -831,7 +831,7 @@ from revenium_middleware import revenium_metadata
831
831
  def handle_customer_query(question: str) -> str:
832
832
  # All API calls automatically include the decorator metadata
833
833
  response = client.chat.completions.create(
834
- model="gpt-5.5",
834
+ model="gpt-4o-mini",
835
835
  messages=[{"role": "user", "content": question}]
836
836
  )
837
837
  return response.choices[0].message.content
@@ -870,13 +870,13 @@ def outer_function():
870
870
  def mixed_metadata():
871
871
  # Uses decorator metadata
872
872
  response1 = client.chat.completions.create(
873
- model="gpt-5.5",
873
+ model="gpt-4o-mini",
874
874
  messages=[{"role": "user", "content": "Hello"}]
875
875
  )
876
876
 
877
877
  # API-level metadata overrides decorator's task_type
878
878
  response2 = client.chat.completions.create(
879
- model="gpt-5.5",
879
+ model="gpt-4o-mini",
880
880
  messages=[{"role": "user", "content": "Hello"}],
881
881
  usage_metadata={
882
882
  "task_type": "special-override", # Overrides decorator
@@ -905,7 +905,7 @@ from revenium_middleware import revenium_meter, revenium_metadata
905
905
  def premium_feature(prompt: str) -> str:
906
906
  # This WILL be metered (decorated with @revenium_meter)
907
907
  response = client.chat.completions.create(
908
- model="gpt-5.5",
908
+ model="gpt-4o-mini",
909
909
  messages=[{"role": "user", "content": prompt}]
910
910
  )
911
911
  return response.choices[0].message.content
@@ -913,7 +913,7 @@ def premium_feature(prompt: str) -> str:
913
913
  def free_feature(prompt: str) -> str:
914
914
  # This will NOT be metered (no @revenium_meter decorator)
915
915
  response = client.chat.completions.create(
916
- model="gpt-5.5",
916
+ model="gpt-4o-mini",
917
917
  messages=[{"role": "user", "content": prompt}]
918
918
  )
919
919
  return response.choices[0].message.content
@@ -999,7 +999,7 @@ from openai import OpenAI
999
999
 
1000
1000
  client = OpenAI()
1001
1001
  response = client.chat.completions.create(
1002
- model="gpt-5.5",
1002
+ model="gpt-4o-mini",
1003
1003
  messages=[
1004
1004
  {"role": "system", "content": "You are a helpful assistant."},
1005
1005
  {"role": "user", "content": "What is the capital of France?"}
@@ -1021,62 +1021,6 @@ Prompt capture works with both streaming and non-streaming requests, and with mu
1021
1021
 
1022
1022
  ---
1023
1023
 
1024
- ## Terminal Summary Output
1025
-
1026
- Display a cost and usage summary in your terminal after each API request. Useful for development, debugging, and monitoring AI costs in real-time.
1027
-
1028
- ### Configuration
1029
-
1030
- | Environment Variable | Values | Description |
1031
- |---------------------|--------|-------------|
1032
- | `REVENIUM_PRINT_SUMMARY` | `false` (default), `true` or `human`, `json` | Controls output format |
1033
- | `REVENIUM_TEAM_ID` | Your team ID | Required to fetch and display cost information |
1034
-
1035
- ```bash
1036
- # Enable human-readable output
1037
- export REVENIUM_PRINT_SUMMARY=human
1038
-
1039
- # Required for cost display (find in Revenium web app)
1040
- export REVENIUM_TEAM_ID=your-team-id-here
1041
- ```
1042
-
1043
- ### Human-Readable Format
1044
-
1045
- ```
1046
- ============================================================
1047
- REVENIUM USAGE SUMMARY
1048
- ============================================================
1049
- Model: gpt-5.5
1050
- Provider: OPENAI
1051
- Duration: 1.23s
1052
-
1053
- Token Usage:
1054
- Input Tokens: 150
1055
- Output Tokens: 250
1056
- Total Tokens: 400
1057
-
1058
- Cost: $0.000045
1059
-
1060
- Trace ID: abc-123
1061
- ============================================================
1062
- ```
1063
-
1064
- ### JSON Format
1065
-
1066
- ```json
1067
- {"model":"gpt-5.5","provider":"OPENAI","durationSeconds":1.23,"inputTokenCount":150,"outputTokenCount":250,"totalTokenCount":400,"cost":0.000045,"costStatus":"available","traceId":"abc-123"}
1068
- ```
1069
-
1070
- ### Cost Status
1071
-
1072
- | Scenario | Display |
1073
- |----------|---------|
1074
- | Cost available | `$0.000045` |
1075
- | `REVENIUM_TEAM_ID` set, cost pending | `Pending (aggregating... check Revenium dashboard)` |
1076
- | `REVENIUM_TEAM_ID` not set | `Add REVENIUM_TEAM_ID to see pricing` |
1077
-
1078
- ---
1079
-
1080
1024
  ## Cost Controls / Enforcement
1081
1025
 
1082
1026
  Block outbound provider requests client-side when a Revenium cost control trips. When the circuit breaker is enabled, the middleware polls compiled enforcement rules from the Revenium API in a background daemon thread and raises `BudgetExceededError` **before** the upstream call, preventing spend beyond the configured limit.
@@ -1155,7 +1099,7 @@ client = openai.OpenAI()
1155
1099
 
1156
1100
  try:
1157
1101
  response = client.chat.completions.create(
1158
- model="gpt-5.5",
1102
+ model="gpt-4o-mini",
1159
1103
  messages=[{"role": "user", "content": "Summarize the meeting notes"}],
1160
1104
  )
1161
1105
  except BudgetExceededError as exc:
@@ -1194,9 +1138,8 @@ See [`examples/openai/openai_blocking_demo.py`](examples/openai/openai_blocking_
1194
1138
  | `REVENIUM_METERING_BASE_URL` | `https://api.revenium.ai` | Revenium API endpoint |
1195
1139
  | `REVENIUM_LOG_LEVEL` | `INFO` | Log level: `DEBUG`, `INFO`, `WARNING`, `ERROR`, `CRITICAL` |
1196
1140
  | `REVENIUM_CAPTURE_PROMPTS` | `false` | Enable prompt capture |
1197
- | `REVENIUM_PRINT_SUMMARY` | `false` | Terminal output: `false`, `true`/`human`, `json` |
1198
1141
  | `REVENIUM_SELECTIVE_METERING` | `false` | Only meter `@revenium_meter` decorated functions |
1199
- | `REVENIUM_TEAM_ID` | - | Team ID for cost display in terminal summary |
1142
+ | `REVENIUM_TEAM_ID` | - | Team ID for cost lookups |
1200
1143
  | `REVENIUM_ENVIRONMENT` | - | Deployment environment (auto-detects from `ENVIRONMENT`, `DEPLOYMENT_ENV`) |
1201
1144
  | `REVENIUM_REGION` | - | Cloud region (auto-detects from `AWS_REGION`, `AZURE_REGION`, `GCP_REGION`) |
1202
1145
  | `REVENIUM_CREDENTIAL_ALIAS` | - | Human-readable API key name |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "revenium-python-sdk"
7
- version = "0.1.5"
7
+ version = "0.1.6"
8
8
  description = "The official Revenium Python SDK — unified AI metering middleware for OpenAI, Anthropic, Google, Ollama, LiteLLM, Perplexity, and fal.ai."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -8,13 +8,10 @@ this via class inheritance and re-export symbols for backward compatibility.
8
8
 
9
9
  import logging
10
10
  import os
11
- from typing import Set, Literal, Union, Optional
11
+ from typing import Set, Optional
12
12
 
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
- # Type alias for summary format
16
- SummaryFormat = Literal["human", "json"]
17
-
18
15
 
19
16
  class Config:
20
17
  """Shared configuration constants for all Revenium middleware providers."""
@@ -65,13 +62,9 @@ class Config:
65
62
  CAPTURE_PROMPTS: bool = False
66
63
  MAX_PROMPT_LENGTH: int = 50_000 # Maximum characters per prompt field
67
64
 
68
- # Terminal summary settings
69
- ENV_REVENIUM_PRINT_SUMMARY: str = "REVENIUM_PRINT_SUMMARY"
65
+ # Revenium API targeting
70
66
  ENV_REVENIUM_TEAM_ID: str = "REVENIUM_TEAM_ID"
71
67
  ENV_REVENIUM_BASE_URL: str = "REVENIUM_METERING_BASE_URL"
72
- SUMMARY_RETRY_ATTEMPTS: int = 3
73
- SUMMARY_RETRY_DELAY: float = 2.0
74
- SUMMARY_API_TIMEOUT: float = 5.0
75
68
  DEFAULT_BASE_URL: str = "https://api.revenium.ai"
76
69
 
77
70
  # Enforcement / circuit breaker — see _core/enforcement.py.
@@ -139,38 +132,6 @@ def get_timeout_config() -> dict:
139
132
  }
140
133
 
141
134
 
142
- def parse_print_summary_value(value: Optional[str]) -> Union[bool, SummaryFormat]:
143
- """
144
- Parse REVENIUM_PRINT_SUMMARY environment variable value.
145
-
146
- Returns:
147
- False if disabled, 'human' or 'json' if enabled
148
- """
149
- if value is None:
150
- return False
151
-
152
- value_lower = value.lower().strip()
153
-
154
- if value_lower in ('false', '0', 'no', 'off', 'disabled', ''):
155
- return False
156
- elif value_lower in ('true', '1', 'yes', 'on', 'enabled', 'human'):
157
- return 'human'
158
- elif value_lower == 'json':
159
- return 'json'
160
- else:
161
- logger.warning(
162
- f"Invalid REVENIUM_PRINT_SUMMARY value '{value}'. "
163
- f"Expected 'true', 'human', 'json', or 'false'. Defaulting to disabled."
164
- )
165
- return False
166
-
167
-
168
- def get_print_summary_config() -> Union[bool, SummaryFormat]:
169
- """Get print summary configuration from environment."""
170
- value = get_config_value(Config.ENV_REVENIUM_PRINT_SUMMARY)
171
- return parse_print_summary_value(value)
172
-
173
-
174
135
  def get_team_id() -> Optional[str]:
175
136
  """Get Revenium team ID from environment."""
176
137
  return get_config_value(Config.ENV_REVENIUM_TEAM_ID)
@@ -1,5 +1,6 @@
1
1
  import logging
2
- from typing import Any, Dict, Mapping, Optional
2
+ import warnings
3
+ from typing import Any, Dict, Mapping, Optional, Set, Tuple
3
4
 
4
5
  logger = logging.getLogger(__name__)
5
6
 
@@ -10,6 +11,21 @@ AGENTIC_JOB_FIELD_MAP = {
10
11
  "agenticJobVersion": ("agentic_job_version", "agenticJobVersion"),
11
12
  }
12
13
 
14
+ # Tracks (old_field, new_field) pairs already warned about in this process,
15
+ # so high-volume callers don't get a deprecation log flood per call.
16
+ _WARNED_DEPRECATED_FIELDS: Set[Tuple[str, str]] = set()
17
+
18
+
19
+ def _reset_deprecation_warning_cache() -> None:
20
+ """Clear the once-per-key deprecation-warning gate.
21
+
22
+ Intended for test isolation — production callers should not need this.
23
+ Test suites with autouse fixtures call this before each test so that tests
24
+ which assert a warning fires on a specific call do not bleed across each
25
+ other.
26
+ """
27
+ _WARNED_DEPRECATED_FIELDS.clear()
28
+
13
29
 
14
30
  def extract_field_with_fallback(
15
31
  source: Mapping[str, Any],
@@ -29,11 +45,17 @@ def extract_field_with_fallback(
29
45
 
30
46
  if source.get(old_snake) or source.get(old_camel):
31
47
  if not (source.get(new_snake) or source.get(new_camel)):
32
- logger.warning(
33
- "Fields '%s' and '%s' are deprecated. Use '%s' or '%s' instead. "
34
- "The old fields will be removed in a future version.",
35
- old_camel, old_snake, new_camel, new_snake,
36
- )
48
+ key = (old_camel, new_camel)
49
+ if key not in _WARNED_DEPRECATED_FIELDS:
50
+ _WARNED_DEPRECATED_FIELDS.add(key)
51
+ msg = (
52
+ "Fields '%s' and '%s' are deprecated and are no longer "
53
+ "accepted by the Revenium backend. The SDK is translating to "
54
+ "'%s' for this call. Use '%s' or '%s' instead. The "
55
+ "input-layer aliases will be removed in the next major release."
56
+ )
57
+ logger.warning(msg, old_camel, old_snake, new_camel, new_camel, new_snake)
58
+ warnings.warn(msg % (old_camel, old_snake, new_camel, new_camel, new_snake), DeprecationWarning, stacklevel=3)
37
59
 
38
60
  return value
39
61
 
@@ -7,12 +7,9 @@ Extends shared core config with Anthropic-specific settings.
7
7
  from revenium_middleware._core.config import ( # noqa: F401
8
8
  Config as _CoreConfig,
9
9
  SecurityConfig,
10
- SummaryFormat,
11
10
  get_config_value,
12
11
  is_debug_enabled,
13
12
  get_timeout_config,
14
- parse_print_summary_value,
15
- get_print_summary_config,
16
13
  get_team_id,
17
14
  get_base_url,
18
15
  )