megflow-observability 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,97 @@
1
+ Metadata-Version: 2.4
2
+ Name: megflow-observability
3
+ Version: 0.1.0
4
+ Summary: Megflow AI API observability SDK — auto-instrument OpenAI and Anthropic calls
5
+ License: MIT
6
+ Project-URL: Homepage, https://observability.megflow.com
7
+ Project-URL: Repository, https://github.com/saleem-megflow/megflow-observe
8
+ Keywords: llm,observability,openai,anthropic,monitoring
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ Provides-Extra: openai
20
+ Requires-Dist: openai>=1.0.0; extra == "openai"
21
+ Provides-Extra: anthropic
22
+ Requires-Dist: anthropic>=0.20.0; extra == "anthropic"
23
+ Provides-Extra: all
24
+ Requires-Dist: openai>=1.0.0; extra == "all"
25
+ Requires-Dist: anthropic>=0.20.0; extra == "all"
26
+
27
+ # megflow-observability
28
+
29
+ Python SDK for [Megflow AI Observability](https://observability.megflow.com) — track tokens, cost, latency and errors across OpenAI, Anthropic, Gemini and more.
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ pip install megflow-observability
35
+ ```
36
+
37
+ ## Quick start
38
+
39
+ ```python
40
+ from megflow_observability import MegflowObserve
41
+
42
+ observe = MegflowObserve(api_key="obs_your_key_here")
43
+
44
+ observe.track(
45
+ provider="openai",
46
+ model="gpt-4o",
47
+ input_tokens=100,
48
+ output_tokens=50,
49
+ total_tokens=150,
50
+ cost_usd=0.00075,
51
+ latency_ms=320,
52
+ status_code=200,
53
+ )
54
+ ```
55
+
56
+ ## Auto-instrument OpenAI
57
+
58
+ ```python
59
+ from openai import OpenAI
60
+ from megflow_observability import MegflowObserve, wrap_openai
61
+
62
+ client = wrap_openai(OpenAI(), MegflowObserve(api_key="obs_your_key_here"))
63
+
64
+ # All calls are tracked automatically
65
+ response = client.chat.completions.create(
66
+ model="gpt-4o",
67
+ messages=[{"role": "user", "content": "Hello"}],
68
+ )
69
+ ```
70
+
71
+ ## Auto-instrument Anthropic
72
+
73
+ ```python
74
+ import anthropic
75
+ from megflow_observability import MegflowObserve, wrap_anthropic
76
+
77
+ client = wrap_anthropic(anthropic.Anthropic(), MegflowObserve(api_key="obs_your_key_here"))
78
+
79
+ response = client.messages.create(
80
+ model="claude-sonnet-4-6",
81
+ max_tokens=1024,
82
+ messages=[{"role": "user", "content": "Hello"}],
83
+ )
84
+ ```
85
+
86
+ ## Optional dependencies
87
+
88
+ ```bash
89
+ pip install megflow-observability[openai] # includes openai
90
+ pip install megflow-observability[anthropic] # includes anthropic
91
+ pip install megflow-observability[all] # includes both
92
+ ```
93
+
94
+ ## Links
95
+
96
+ - Dashboard: [observability.megflow.com](https://observability.megflow.com)
97
+ - JS SDK: [npmjs.com/package/megflow-observability](https://www.npmjs.com/package/megflow-observability)
@@ -0,0 +1,71 @@
1
+ # megflow-observability
2
+
3
+ Python SDK for [Megflow AI Observability](https://observability.megflow.com) — track tokens, cost, latency and errors across OpenAI, Anthropic, Gemini and more.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install megflow-observability
9
+ ```
10
+
11
+ ## Quick start
12
+
13
+ ```python
14
+ from megflow_observability import MegflowObserve
15
+
16
+ observe = MegflowObserve(api_key="obs_your_key_here")
17
+
18
+ observe.track(
19
+ provider="openai",
20
+ model="gpt-4o",
21
+ input_tokens=100,
22
+ output_tokens=50,
23
+ total_tokens=150,
24
+ cost_usd=0.00075,
25
+ latency_ms=320,
26
+ status_code=200,
27
+ )
28
+ ```
29
+
30
+ ## Auto-instrument OpenAI
31
+
32
+ ```python
33
+ from openai import OpenAI
34
+ from megflow_observability import MegflowObserve, wrap_openai
35
+
36
+ client = wrap_openai(OpenAI(), MegflowObserve(api_key="obs_your_key_here"))
37
+
38
+ # All calls are tracked automatically
39
+ response = client.chat.completions.create(
40
+ model="gpt-4o",
41
+ messages=[{"role": "user", "content": "Hello"}],
42
+ )
43
+ ```
44
+
45
+ ## Auto-instrument Anthropic
46
+
47
+ ```python
48
+ import anthropic
49
+ from megflow_observability import MegflowObserve, wrap_anthropic
50
+
51
+ client = wrap_anthropic(anthropic.Anthropic(), MegflowObserve(api_key="obs_your_key_here"))
52
+
53
+ response = client.messages.create(
54
+ model="claude-sonnet-4-6",
55
+ max_tokens=1024,
56
+ messages=[{"role": "user", "content": "Hello"}],
57
+ )
58
+ ```
59
+
60
+ ## Optional dependencies
61
+
62
+ ```bash
63
+ pip install megflow-observability[openai] # includes openai
64
+ pip install megflow-observability[anthropic] # includes anthropic
65
+ pip install megflow-observability[all] # includes both
66
+ ```
67
+
68
+ ## Links
69
+
70
+ - Dashboard: [observability.megflow.com](https://observability.megflow.com)
71
+ - JS SDK: [npmjs.com/package/megflow-observability](https://www.npmjs.com/package/megflow-observability)
@@ -0,0 +1,7 @@
1
+ from .client import MegflowObserve
2
+ from .openai_wrapper import wrap_openai
3
+ from .anthropic_wrapper import wrap_anthropic
4
+
5
+ __version__ = "0.1.0"
6
+
7
+ __all__ = ["MegflowObserve", "wrap_openai", "wrap_anthropic", "__version__"]
@@ -0,0 +1,74 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+ from datetime import datetime, timezone
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ from .pricing import calc_cost
8
+
9
+ if TYPE_CHECKING:
10
+ import anthropic
11
+ from .client import MegflowObserve
12
+
13
+
14
+ def wrap_anthropic(client: "anthropic.Anthropic", observe: "MegflowObserve") -> "anthropic.Anthropic":
15
+ original_create = client.messages.create
16
+
17
+ def patched_create(*args: Any, **kwargs: Any) -> Any:
18
+ start = time.monotonic()
19
+ model: str = kwargs.get("model", "")
20
+
21
+ try:
22
+ response: Any = original_create(*args, **kwargs)
23
+
24
+ # Don't track streaming responses
25
+ if hasattr(response, "__iter__") and not hasattr(response, "usage"):
26
+ return response
27
+
28
+ latency_ms = int((time.monotonic() - start) * 1000)
29
+ usage = getattr(response, "usage", None)
30
+ input_tokens: int = getattr(usage, "input_tokens", 0) or 0
31
+ output_tokens: int = getattr(usage, "output_tokens", 0) or 0
32
+ cached_tokens: int = getattr(usage, "cache_read_input_tokens", 0) or 0
33
+ finish_reason: str = getattr(response, "stop_reason", "") or ""
34
+
35
+ observe.track(
36
+ provider="anthropic",
37
+ model=model,
38
+ input_tokens=input_tokens,
39
+ output_tokens=output_tokens,
40
+ total_tokens=input_tokens + output_tokens,
41
+ cached_tokens=cached_tokens,
42
+ cost_usd=calc_cost("anthropic", model, input_tokens, output_tokens),
43
+ latency_ms=latency_ms,
44
+ status_code=200,
45
+ error="",
46
+ finish_reason=finish_reason,
47
+ request_id=getattr(response, "id", "") or "",
48
+ timestamp=datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
49
+ )
50
+
51
+ return response
52
+
53
+ except Exception as exc:
54
+ latency_ms = int((time.monotonic() - start) * 1000)
55
+ status_code: int = getattr(exc, "status_code", None) or getattr(exc, "status", 500) or 500
56
+
57
+ observe.track(
58
+ provider="anthropic",
59
+ model=model,
60
+ input_tokens=0,
61
+ output_tokens=0,
62
+ total_tokens=0,
63
+ cost_usd=0.0,
64
+ latency_ms=latency_ms,
65
+ status_code=status_code,
66
+ error=str(exc),
67
+ rate_limit_remaining=0 if status_code == 429 else -1,
68
+ timestamp=datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
69
+ )
70
+
71
+ raise
72
+
73
+ client.messages.create = patched_create # type: ignore[method-assign]
74
+ return client
@@ -0,0 +1,84 @@
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ import threading
5
+ import urllib.request
6
+ import urllib.error
7
+ from datetime import datetime, timezone
8
+ from typing import Any, Dict, Optional
9
+
10
+ SDK_VERSION = "0.1.0"
11
+ DEFAULT_ENDPOINT = "https://api.observability.megflow.com"
12
+
13
+
14
+ class MegflowObserve:
15
+ def __init__(self, api_key: str, endpoint: str = DEFAULT_ENDPOINT) -> None:
16
+ self._api_key = api_key
17
+ self._endpoint = endpoint.rstrip("/")
18
+
19
+ def track(
20
+ self,
21
+ provider: str,
22
+ model: str,
23
+ input_tokens: int,
24
+ output_tokens: int,
25
+ total_tokens: int,
26
+ cost_usd: float,
27
+ latency_ms: int,
28
+ status_code: int,
29
+ error: str = "",
30
+ finish_reason: str = "",
31
+ environment: str = "",
32
+ user_id: str = "",
33
+ cached_tokens: int = 0,
34
+ rate_limit_remaining: int = -1,
35
+ retry_count: int = 0,
36
+ request_id: str = "",
37
+ timestamp: Optional[str] = None,
38
+ metadata: Optional[Dict[str, str]] = None,
39
+ ) -> None:
40
+ payload: Dict[str, Any] = {
41
+ "provider": provider,
42
+ "model": model,
43
+ "input_tokens": input_tokens,
44
+ "output_tokens": output_tokens,
45
+ "total_tokens": total_tokens,
46
+ "cached_tokens": cached_tokens,
47
+ "cost_usd": cost_usd,
48
+ "latency_ms": latency_ms,
49
+ "status_code": status_code,
50
+ "error": error,
51
+ "finish_reason": finish_reason,
52
+ "environment": environment,
53
+ "user_id": user_id,
54
+ "rate_limit_remaining": rate_limit_remaining,
55
+ "retry_count": retry_count,
56
+ "request_id": request_id,
57
+ "timestamp": timestamp or datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
58
+ "metadata": {
59
+ **(metadata or {}),
60
+ "sdk_version": SDK_VERSION,
61
+ "sdk_language": "python",
62
+ },
63
+ }
64
+
65
+ thread = threading.Thread(target=self._send, args=(payload,), daemon=True)
66
+ thread.start()
67
+
68
+ def _send(self, payload: Dict[str, Any]) -> None:
69
+ try:
70
+ body = json.dumps(payload).encode()
71
+ req = urllib.request.Request(
72
+ url=f"{self._endpoint}/v1/events",
73
+ data=body,
74
+ headers={
75
+ "Content-Type": "application/json",
76
+ "X-API-Key": self._api_key,
77
+ "Content-Length": str(len(body)),
78
+ },
79
+ method="POST",
80
+ )
81
+ with urllib.request.urlopen(req, timeout=5):
82
+ pass
83
+ except Exception:
84
+ pass # observability must never break customer code
@@ -0,0 +1,82 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+ from datetime import datetime, timezone
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ from .pricing import calc_cost
8
+
9
+ if TYPE_CHECKING:
10
+ from openai import OpenAI
11
+ from .client import MegflowObserve
12
+
13
+
14
+ def wrap_openai(client: "OpenAI", observe: "MegflowObserve") -> "OpenAI":
15
+ original_create = client.chat.completions.create
16
+
17
+ def patched_create(*args: Any, **kwargs: Any) -> Any:
18
+ start = time.monotonic()
19
+ model: str = kwargs.get("model", "")
20
+
21
+ try:
22
+ response: Any = original_create(*args, **kwargs)
23
+
24
+ # Don't track streaming responses — chunks have no usage data
25
+ if hasattr(response, "__iter__") and not hasattr(response, "usage"):
26
+ return response
27
+
28
+ latency_ms = int((time.monotonic() - start) * 1000)
29
+ input_tokens: int = getattr(getattr(response, "usage", None), "prompt_tokens", 0) or 0
30
+ output_tokens: int = getattr(getattr(response, "usage", None), "completion_tokens", 0) or 0
31
+ total_tokens: int = getattr(getattr(response, "usage", None), "total_tokens", 0) or input_tokens + output_tokens
32
+
33
+ # Cached tokens (OpenAI prompt_tokens_details)
34
+ details = getattr(getattr(response, "usage", None), "prompt_tokens_details", None)
35
+ cached_tokens: int = getattr(details, "cached_tokens", 0) or 0
36
+
37
+ # Finish reason
38
+ choices = getattr(response, "choices", None)
39
+ finish_reason: str = ""
40
+ if choices:
41
+ finish_reason = getattr(choices[0], "finish_reason", "") or ""
42
+
43
+ observe.track(
44
+ provider="openai",
45
+ model=model,
46
+ input_tokens=input_tokens,
47
+ output_tokens=output_tokens,
48
+ total_tokens=total_tokens,
49
+ cached_tokens=cached_tokens,
50
+ cost_usd=calc_cost("openai", model, input_tokens, output_tokens),
51
+ latency_ms=latency_ms,
52
+ status_code=200,
53
+ error="",
54
+ finish_reason=finish_reason,
55
+ request_id=getattr(response, "id", "") or "",
56
+ timestamp=datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
57
+ )
58
+
59
+ return response
60
+
61
+ except Exception as exc:
62
+ latency_ms = int((time.monotonic() - start) * 1000)
63
+ status_code: int = getattr(exc, "status_code", None) or getattr(exc, "status", 500) or 500
64
+
65
+ observe.track(
66
+ provider="openai",
67
+ model=model,
68
+ input_tokens=0,
69
+ output_tokens=0,
70
+ total_tokens=0,
71
+ cost_usd=0.0,
72
+ latency_ms=latency_ms,
73
+ status_code=status_code,
74
+ error=str(exc),
75
+ rate_limit_remaining=0 if status_code == 429 else -1,
76
+ timestamp=datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
77
+ )
78
+
79
+ raise
80
+
81
+ client.chat.completions.create = patched_create # type: ignore[method-assign]
82
+ return client
@@ -0,0 +1,69 @@
1
+ from __future__ import annotations
2
+ from typing import Dict, Optional, Tuple
3
+
4
+ # Cost per 1M tokens [input, output] in USD
5
+ _PRICING: Dict[str, Dict[str, Tuple[float, float]]] = {
6
+ "openai": {
7
+ "gpt-4o": (2.50, 10.00),
8
+ "gpt-4o-mini": (0.15, 0.60),
9
+ "gpt-4-turbo": (10.00, 30.00),
10
+ "gpt-4-turbo-preview": (10.00, 30.00),
11
+ "gpt-4": (30.00, 60.00),
12
+ "gpt-3.5-turbo": (0.50, 1.50),
13
+ "o1": (15.00, 60.00),
14
+ "o1-mini": (3.00, 12.00),
15
+ "o3-mini": (1.10, 4.40),
16
+ },
17
+ "anthropic": {
18
+ "claude-3-5-sonnet-20241022": (3.00, 15.00),
19
+ "claude-3-5-sonnet-20240620": (3.00, 15.00),
20
+ "claude-3-5-haiku-20241022": (0.80, 4.00),
21
+ "claude-3-opus-20240229": (15.00, 75.00),
22
+ "claude-3-sonnet-20240229": (3.00, 15.00),
23
+ "claude-3-haiku-20240307": (0.25, 1.25),
24
+ "claude-sonnet-4-6": (3.00, 15.00),
25
+ "claude-opus-4-8": (15.00, 75.00),
26
+ "claude-haiku-4-5-20251001": (0.80, 4.00),
27
+ },
28
+ "gemini": {
29
+ "gemini-1.5-pro": (1.25, 5.00),
30
+ "gemini-1.5-flash": (0.075, 0.30),
31
+ "gemini-2.0-flash": (0.10, 0.40),
32
+ "gemini-2.5-pro": (1.25, 10.00),
33
+ "gemini-2.5-flash": (0.15, 0.60),
34
+ },
35
+ "mistral": {
36
+ "mistral-large-latest": (2.00, 6.00),
37
+ "mistral-small-latest": (0.20, 0.60),
38
+ "mistral-7b-instruct": (0.25, 0.25),
39
+ },
40
+ "groq": {
41
+ "llama3-8b-8192": (0.05, 0.10),
42
+ "llama3-70b-8192": (0.59, 0.79),
43
+ "mixtral-8x7b-32768": (0.24, 0.24),
44
+ },
45
+ "cohere": {
46
+ "command-r-plus": (3.00, 15.00),
47
+ "command-r": (0.50, 1.50),
48
+ },
49
+ }
50
+
51
+
52
+ def calc_cost(provider: str, model: str, input_tokens: int, output_tokens: int) -> float:
53
+ provider_pricing = _PRICING.get(provider.lower())
54
+ if not provider_pricing:
55
+ return 0.0
56
+
57
+ rates: Optional[Tuple[float, float]] = provider_pricing.get(model)
58
+ if rates is None:
59
+ # prefix match for versioned model names
60
+ for k, v in provider_pricing.items():
61
+ if model.startswith(k) or k.startswith(model):
62
+ rates = v
63
+ break
64
+
65
+ if rates is None:
66
+ return 0.0
67
+
68
+ input_rate, output_rate = rates
69
+ return (input_tokens * input_rate + output_tokens * output_rate) / 1_000_000
@@ -0,0 +1,97 @@
1
+ Metadata-Version: 2.4
2
+ Name: megflow-observability
3
+ Version: 0.1.0
4
+ Summary: Megflow AI API observability SDK — auto-instrument OpenAI and Anthropic calls
5
+ License: MIT
6
+ Project-URL: Homepage, https://observability.megflow.com
7
+ Project-URL: Repository, https://github.com/saleem-megflow/megflow-observe
8
+ Keywords: llm,observability,openai,anthropic,monitoring
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Requires-Python: >=3.8
18
+ Description-Content-Type: text/markdown
19
+ Provides-Extra: openai
20
+ Requires-Dist: openai>=1.0.0; extra == "openai"
21
+ Provides-Extra: anthropic
22
+ Requires-Dist: anthropic>=0.20.0; extra == "anthropic"
23
+ Provides-Extra: all
24
+ Requires-Dist: openai>=1.0.0; extra == "all"
25
+ Requires-Dist: anthropic>=0.20.0; extra == "all"
26
+
27
+ # megflow-observability
28
+
29
+ Python SDK for [Megflow AI Observability](https://observability.megflow.com) — track tokens, cost, latency and errors across OpenAI, Anthropic, Gemini and more.
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ pip install megflow-observability
35
+ ```
36
+
37
+ ## Quick start
38
+
39
+ ```python
40
+ from megflow_observability import MegflowObserve
41
+
42
+ observe = MegflowObserve(api_key="obs_your_key_here")
43
+
44
+ observe.track(
45
+ provider="openai",
46
+ model="gpt-4o",
47
+ input_tokens=100,
48
+ output_tokens=50,
49
+ total_tokens=150,
50
+ cost_usd=0.00075,
51
+ latency_ms=320,
52
+ status_code=200,
53
+ )
54
+ ```
55
+
56
+ ## Auto-instrument OpenAI
57
+
58
+ ```python
59
+ from openai import OpenAI
60
+ from megflow_observability import MegflowObserve, wrap_openai
61
+
62
+ client = wrap_openai(OpenAI(), MegflowObserve(api_key="obs_your_key_here"))
63
+
64
+ # All calls are tracked automatically
65
+ response = client.chat.completions.create(
66
+ model="gpt-4o",
67
+ messages=[{"role": "user", "content": "Hello"}],
68
+ )
69
+ ```
70
+
71
+ ## Auto-instrument Anthropic
72
+
73
+ ```python
74
+ import anthropic
75
+ from megflow_observability import MegflowObserve, wrap_anthropic
76
+
77
+ client = wrap_anthropic(anthropic.Anthropic(), MegflowObserve(api_key="obs_your_key_here"))
78
+
79
+ response = client.messages.create(
80
+ model="claude-sonnet-4-6",
81
+ max_tokens=1024,
82
+ messages=[{"role": "user", "content": "Hello"}],
83
+ )
84
+ ```
85
+
86
+ ## Optional dependencies
87
+
88
+ ```bash
89
+ pip install megflow-observability[openai] # includes openai
90
+ pip install megflow-observability[anthropic] # includes anthropic
91
+ pip install megflow-observability[all] # includes both
92
+ ```
93
+
94
+ ## Links
95
+
96
+ - Dashboard: [observability.megflow.com](https://observability.megflow.com)
97
+ - JS SDK: [npmjs.com/package/megflow-observability](https://www.npmjs.com/package/megflow-observability)
@@ -0,0 +1,12 @@
1
+ README.md
2
+ pyproject.toml
3
+ megflow_observability/__init__.py
4
+ megflow_observability/anthropic_wrapper.py
5
+ megflow_observability/client.py
6
+ megflow_observability/openai_wrapper.py
7
+ megflow_observability/pricing.py
8
+ megflow_observability.egg-info/PKG-INFO
9
+ megflow_observability.egg-info/SOURCES.txt
10
+ megflow_observability.egg-info/dependency_links.txt
11
+ megflow_observability.egg-info/requires.txt
12
+ megflow_observability.egg-info/top_level.txt
@@ -0,0 +1,10 @@
1
+
2
+ [all]
3
+ openai>=1.0.0
4
+ anthropic>=0.20.0
5
+
6
+ [anthropic]
7
+ anthropic>=0.20.0
8
+
9
+ [openai]
10
+ openai>=1.0.0
@@ -0,0 +1 @@
1
+ megflow_observability
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "megflow-observability"
7
+ version = "0.1.0"
8
+ description = "Megflow AI API observability SDK — auto-instrument OpenAI and Anthropic calls"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = { text = "MIT" }
12
+ keywords = ["llm", "observability", "openai", "anthropic", "monitoring"]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Intended Audience :: Developers",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.8",
18
+ "Programming Language :: Python :: 3.9",
19
+ "Programming Language :: Python :: 3.10",
20
+ "Programming Language :: Python :: 3.11",
21
+ "Programming Language :: Python :: 3.12",
22
+ ]
23
+
24
+ [project.optional-dependencies]
25
+ openai = ["openai>=1.0.0"]
26
+ anthropic = ["anthropic>=0.20.0"]
27
+ all = ["openai>=1.0.0", "anthropic>=0.20.0"]
28
+
29
+ [project.urls]
30
+ Homepage = "https://observability.megflow.com"
31
+ Repository = "https://github.com/saleem-megflow/megflow-observe"
32
+
33
+ [tool.setuptools.packages.find]
34
+ where = ["."]
35
+ include = ["megflow_observability*"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+