golf-mcp 0.1.18__py3-none-any.whl → 0.1.20__py3-none-any.whl

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.

Potentially problematic release.


This version of golf-mcp might be problematic. Click here for more details.

golf/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.18"
1
+ __version__ = "0.1.20"
golf/core/builder.py CHANGED
@@ -1251,14 +1251,17 @@ def build_project(
1251
1251
  try:
1252
1252
  from golf.core.platform import register_project_with_platform
1253
1253
 
1254
- asyncio.run(
1254
+ success = asyncio.run(
1255
1255
  register_project_with_platform(
1256
1256
  project_path=project_path,
1257
1257
  settings=settings,
1258
1258
  components=generator.components,
1259
1259
  )
1260
1260
  )
1261
- console.print("[green]✓ Platform registration completed[/green]")
1261
+
1262
+ if success:
1263
+ console.print("[green]✓ Platform registration completed[/green]")
1264
+ # If success is False, the platform module already printed appropriate warnings
1262
1265
  except ImportError:
1263
1266
  console.print(
1264
1267
  "[yellow]Warning: Platform registration module not available[/yellow]"
golf/core/platform.py CHANGED
@@ -65,7 +65,7 @@ async def register_project_with_platform(
65
65
  try:
66
66
  async with httpx.AsyncClient(timeout=10.0) as client:
67
67
  response = await client.post(
68
- "http://localhost:8000/api/resources",
68
+ "https://golf-backend.golf-auth-1.authed-qukc4.ryvn.run/api/resources",
69
69
  json=metadata,
70
70
  headers={
71
71
  "X-Golf-Key": api_key,
@@ -4,9 +4,11 @@ import asyncio
4
4
  import functools
5
5
  import os
6
6
  import sys
7
+ import time
7
8
  from collections.abc import Callable
8
9
  from contextlib import asynccontextmanager
9
10
  from typing import TypeVar
11
+ from collections import OrderedDict
10
12
 
11
13
  from opentelemetry import baggage, trace
12
14
  from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
@@ -15,6 +17,9 @@ from opentelemetry.sdk.trace import TracerProvider
15
17
  from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
16
18
  from opentelemetry.trace import Status, StatusCode
17
19
 
20
+ from starlette.middleware.base import BaseHTTPMiddleware
21
+ from starlette.requests import Request
22
+
18
23
  T = TypeVar("T")
19
24
 
20
25
  # Global tracer instance
@@ -31,11 +36,27 @@ def init_telemetry(service_name: str = "golf-mcp-server") -> TracerProvider | No
31
36
 
32
37
  # Check for Golf platform integration first
33
38
  golf_api_key = os.environ.get("GOLF_API_KEY")
34
- if golf_api_key and not os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT"):
35
- # Auto-configure for Golf platform
39
+ if golf_api_key:
40
+ # Auto-configure for Golf platform - always use OTLP when Golf API key is present
36
41
  os.environ["OTEL_TRACES_EXPORTER"] = "otlp_http"
37
- os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = "http://localhost:8000/api/v1/otel"
38
- os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"X-Golf-Key={golf_api_key}"
42
+
43
+ # Only set endpoint if not already configured (allow user override)
44
+ if not os.environ.get("OTEL_EXPORTER_OTLP_ENDPOINT"):
45
+ os.environ["OTEL_EXPORTER_OTLP_ENDPOINT"] = (
46
+ "https://golf-backend.golf-auth-1.authed-qukc4.ryvn.run/api/v1/otel"
47
+ )
48
+
49
+ # Set Golf platform headers (append to existing if present)
50
+ existing_headers = os.environ.get("OTEL_EXPORTER_OTLP_HEADERS", "")
51
+ golf_header = f"X-Golf-Key={golf_api_key}"
52
+
53
+ if existing_headers:
54
+ # Check if Golf key is already in headers
55
+ if "X-Golf-Key=" not in existing_headers:
56
+ os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = f"{existing_headers},{golf_header}"
57
+ else:
58
+ os.environ["OTEL_EXPORTER_OTLP_HEADERS"] = golf_header
59
+
39
60
  print("[INFO] Auto-configured OpenTelemetry for Golf platform ingestion")
40
61
 
41
62
  # Check for required environment variables based on exporter type
@@ -821,221 +842,254 @@ def instrument_prompt(func: Callable[..., T], prompt_name: str) -> Callable[...,
821
842
  return sync_wrapper
822
843
 
823
844
 
824
- @asynccontextmanager
825
- async def telemetry_lifespan(mcp_instance):
826
- """Simplified lifespan for telemetry initialization and cleanup."""
827
- global _provider
845
+ # Add the BoundedSessionTracker class before SessionTracingMiddleware
846
+ class BoundedSessionTracker:
847
+ """Memory-safe session tracker with automatic expiration."""
848
+
849
+ def __init__(self, max_sessions: int = 1000, session_ttl: int = 3600):
850
+ self.max_sessions = max_sessions
851
+ self.session_ttl = session_ttl
852
+ self.sessions: OrderedDict[str, float] = OrderedDict()
853
+ self.last_cleanup = time.time()
854
+
855
+ def track_session(self, session_id: str) -> bool:
856
+ """Track a session, returns True if it's new."""
857
+ current_time = time.time()
858
+
859
+ # Periodic cleanup (every 5 minutes)
860
+ if current_time - self.last_cleanup > 300:
861
+ self._cleanup_expired(current_time)
862
+ self.last_cleanup = current_time
863
+
864
+ # Check if session exists and is still valid
865
+ if session_id in self.sessions:
866
+ # Move to end (mark as recently used)
867
+ self.sessions.move_to_end(session_id)
868
+ return False
869
+
870
+ # New session
871
+ self.sessions[session_id] = current_time
872
+
873
+ # Enforce max size
874
+ while len(self.sessions) > self.max_sessions:
875
+ self.sessions.popitem(last=False) # Remove oldest
876
+
877
+ return True
878
+
879
+ def _cleanup_expired(self, current_time: float):
880
+ """Remove expired sessions."""
881
+ expired = [
882
+ sid
883
+ for sid, timestamp in self.sessions.items()
884
+ if current_time - timestamp > self.session_ttl
885
+ ]
886
+ for sid in expired:
887
+ del self.sessions[sid]
888
+
889
+ def get_active_session_count(self) -> int:
890
+ return len(self.sessions)
891
+
892
+
893
+ class SessionTracingMiddleware(BaseHTTPMiddleware):
894
+ def __init__(self, app):
895
+ super().__init__(app)
896
+ # Use memory-safe session tracker instead of unbounded collections
897
+ self.session_tracker = BoundedSessionTracker(
898
+ max_sessions=1000, session_ttl=3600
899
+ )
828
900
 
829
- # Initialize telemetry with the server name
830
- provider = init_telemetry(service_name=mcp_instance.name)
901
+ async def dispatch(self, request: Request, call_next):
902
+ # Record HTTP request timing
903
+ import time
831
904
 
832
- # If provider is None, telemetry is disabled
833
- if provider is None:
834
- # Just yield without any telemetry setup
835
- yield
836
- return
905
+ start_time = time.time()
837
906
 
838
- # Try to add session tracking middleware if possible
839
- try:
840
- from starlette.middleware.base import BaseHTTPMiddleware
841
- from starlette.requests import Request
842
-
843
- class SessionTracingMiddleware(BaseHTTPMiddleware):
844
- def __init__(self, app):
845
- super().__init__(app)
846
- # Track seen sessions to count unique sessions
847
- self.seen_sessions = set()
848
- # Track session start times for duration calculation
849
- self.session_start_times = {}
850
-
851
- async def dispatch(self, request: Request, call_next):
852
- # Record HTTP request timing
853
- import time
854
-
855
- start_time = time.time()
856
-
857
- # Extract session ID from query params or headers
858
- session_id = request.query_params.get("session_id")
859
- if not session_id:
860
- # Check headers as fallback
861
- session_id = request.headers.get("x-session-id")
862
-
863
- # Track session metrics
864
- if session_id:
865
- current_time = time.time()
866
-
867
- # Record new session if we haven't seen this session ID before
868
- if session_id not in self.seen_sessions:
869
- self.seen_sessions.add(session_id)
870
- self.session_start_times[session_id] = current_time
871
- try:
872
- from golf.metrics import get_metrics_collector
873
-
874
- metrics_collector = get_metrics_collector()
875
- metrics_collector.increment_session()
876
- except ImportError:
877
- pass
878
- else:
879
- # Update session duration (time since first request)
880
- if session_id in self.session_start_times:
881
- duration = (
882
- current_time - self.session_start_times[session_id]
883
- )
884
- try:
885
- from golf.metrics import get_metrics_collector
886
-
887
- metrics_collector = get_metrics_collector()
888
- metrics_collector.record_session_duration(duration)
889
- except ImportError:
890
- pass
891
-
892
- # Clean up old session data periodically
893
- if len(self.seen_sessions) > 10000:
894
- # Keep only the most recent 5000 sessions
895
- recent_sessions = list(self.seen_sessions)[-5000:]
896
- self.seen_sessions = set(recent_sessions)
897
- # Clean up start times for removed sessions
898
- for old_session in list(self.session_start_times.keys()):
899
- if old_session not in self.seen_sessions:
900
- self.session_start_times.pop(old_session, None)
901
-
902
- # Create a descriptive span name based on the request
903
- method = request.method
904
- path = request.url.path
905
-
906
- # Determine the operation type from the path
907
- operation_type = "unknown"
908
- if "/mcp" in path:
909
- operation_type = "mcp.request"
910
- elif "/sse" in path:
911
- operation_type = "sse.stream"
912
- elif "/auth" in path:
913
- operation_type = "auth"
914
-
915
- span_name = f"{operation_type}.{method.lower()}"
907
+ # Extract session ID from query params or headers
908
+ session_id = request.query_params.get("session_id")
909
+ if not session_id:
910
+ # Check headers as fallback
911
+ session_id = request.headers.get("x-session-id")
916
912
 
917
- tracer = get_tracer()
918
- with tracer.start_as_current_span(span_name) as span:
919
- # Add comprehensive HTTP attributes
920
- span.set_attribute("http.method", method)
921
- span.set_attribute("http.url", str(request.url))
922
- span.set_attribute("http.scheme", request.url.scheme)
923
- span.set_attribute("http.host", request.url.hostname or "unknown")
924
- span.set_attribute("http.target", path)
925
- span.set_attribute(
926
- "http.user_agent", request.headers.get("user-agent", "unknown")
927
- )
913
+ # Track session metrics using memory-safe tracker
914
+ if session_id:
915
+ is_new_session = self.session_tracker.track_session(session_id)
916
+
917
+ if is_new_session:
918
+ try:
919
+ from golf.metrics import get_metrics_collector
928
920
 
929
- # Add session tracking
930
- if session_id:
931
- span.set_attribute("mcp.session.id", session_id)
932
- # Add to baggage for propagation
933
- ctx = baggage.set_baggage("mcp.session.id", session_id)
934
- from opentelemetry import context
935
-
936
- token = context.attach(ctx)
937
- else:
938
- token = None
939
-
940
- # Add request size if available
941
- content_length = request.headers.get("content-length")
942
- if content_length:
943
- span.set_attribute("http.request.size", int(content_length))
944
-
945
- # Add event for request start
946
- span.add_event(
947
- "http.request.started", {"method": method, "path": path}
921
+ metrics_collector = get_metrics_collector()
922
+ metrics_collector.increment_session()
923
+ except ImportError:
924
+ pass
925
+ else:
926
+ # Record session duration for existing sessions
927
+ try:
928
+ from golf.metrics import get_metrics_collector
929
+
930
+ metrics_collector = get_metrics_collector()
931
+ # Use a default duration since we don't track exact start times anymore
932
+ # This is less precise but memory-safe
933
+ metrics_collector.record_session_duration(300.0) # 5 min default
934
+ except ImportError:
935
+ pass
936
+
937
+ # Create a descriptive span name based on the request
938
+ method = request.method
939
+ path = request.url.path
940
+
941
+ # Determine the operation type from the path
942
+ operation_type = "unknown"
943
+ if "/mcp" in path:
944
+ operation_type = "mcp.request"
945
+ elif "/sse" in path:
946
+ operation_type = "sse.stream"
947
+ elif "/auth" in path:
948
+ operation_type = "auth"
949
+
950
+ span_name = f"{operation_type}.{method.lower()}"
951
+
952
+ tracer = get_tracer()
953
+ with tracer.start_as_current_span(span_name) as span:
954
+ # Add comprehensive HTTP attributes
955
+ span.set_attribute("http.method", method)
956
+ span.set_attribute("http.url", str(request.url))
957
+ span.set_attribute("http.scheme", request.url.scheme)
958
+ span.set_attribute("http.host", request.url.hostname or "unknown")
959
+ span.set_attribute("http.target", path)
960
+ span.set_attribute(
961
+ "http.user_agent", request.headers.get("user-agent", "unknown")
962
+ )
963
+
964
+ # Add session tracking
965
+ if session_id:
966
+ span.set_attribute("mcp.session.id", session_id)
967
+ span.set_attribute(
968
+ "mcp.session.active_count",
969
+ self.session_tracker.get_active_session_count(),
970
+ )
971
+ # Add to baggage for propagation
972
+ ctx = baggage.set_baggage("mcp.session.id", session_id)
973
+ from opentelemetry import context
974
+
975
+ token = context.attach(ctx)
976
+ else:
977
+ token = None
978
+
979
+ # Add request size if available
980
+ content_length = request.headers.get("content-length")
981
+ if content_length:
982
+ span.set_attribute("http.request.size", int(content_length))
983
+
984
+ # Add event for request start
985
+ span.add_event("http.request.started", {"method": method, "path": path})
986
+
987
+ try:
988
+ response = await call_next(request)
989
+
990
+ # Add response attributes
991
+ span.set_attribute("http.status_code", response.status_code)
992
+ span.set_attribute(
993
+ "http.status_class", f"{response.status_code // 100}xx"
994
+ )
995
+
996
+ # Set span status based on HTTP status
997
+ if response.status_code >= 400:
998
+ span.set_status(
999
+ Status(StatusCode.ERROR, f"HTTP {response.status_code}")
948
1000
  )
1001
+ else:
1002
+ span.set_status(Status(StatusCode.OK))
949
1003
 
950
- try:
951
- response = await call_next(request)
1004
+ # Add event for request completion
1005
+ span.add_event(
1006
+ "http.request.completed",
1007
+ {
1008
+ "method": method,
1009
+ "path": path,
1010
+ "status_code": response.status_code,
1011
+ },
1012
+ )
952
1013
 
953
- # Add response attributes
954
- span.set_attribute("http.status_code", response.status_code)
955
- span.set_attribute(
956
- "http.status_class", f"{response.status_code // 100}xx"
957
- )
1014
+ # Record HTTP request metrics
1015
+ try:
1016
+ from golf.metrics import get_metrics_collector
958
1017
 
959
- # Set span status based on HTTP status
960
- if response.status_code >= 400:
961
- span.set_status(
962
- Status(StatusCode.ERROR, f"HTTP {response.status_code}")
963
- )
964
- else:
965
- span.set_status(Status(StatusCode.OK))
966
-
967
- # Add event for request completion
968
- span.add_event(
969
- "http.request.completed",
970
- {
971
- "method": method,
972
- "path": path,
973
- "status_code": response.status_code,
974
- },
975
- )
1018
+ metrics_collector = get_metrics_collector()
976
1019
 
977
- # Record HTTP request metrics
978
- try:
979
- from golf.metrics import get_metrics_collector
1020
+ # Clean up path for metrics (remove query params, normalize)
1021
+ clean_path = path.split("?")[0] # Remove query parameters
1022
+ if clean_path.startswith("/"):
1023
+ clean_path = (
1024
+ clean_path[1:] or "root"
1025
+ ) # Remove leading slash, handle root
980
1026
 
981
- metrics_collector = get_metrics_collector()
1027
+ metrics_collector.increment_http_request(
1028
+ method, response.status_code, clean_path
1029
+ )
1030
+ metrics_collector.record_http_duration(
1031
+ method, clean_path, time.time() - start_time
1032
+ )
1033
+ except ImportError:
1034
+ # Metrics not available, continue without metrics
1035
+ pass
982
1036
 
983
- # Clean up path for metrics (remove query params, normalize)
984
- clean_path = path.split("?")[0] # Remove query parameters
985
- if clean_path.startswith("/"):
986
- clean_path = (
987
- clean_path[1:] or "root"
988
- ) # Remove leading slash, handle root
1037
+ return response
1038
+ except Exception as e:
1039
+ span.record_exception(e)
1040
+ span.set_status(Status(StatusCode.ERROR, str(e)))
989
1041
 
990
- metrics_collector.increment_http_request(
991
- method, response.status_code, clean_path
992
- )
993
- metrics_collector.record_http_duration(
994
- method, clean_path, time.time() - start_time
995
- )
996
- except ImportError:
997
- # Metrics not available, continue without metrics
998
- pass
999
-
1000
- return response
1001
- except Exception as e:
1002
- span.record_exception(e)
1003
- span.set_status(Status(StatusCode.ERROR, str(e)))
1004
-
1005
- # Add event for error
1006
- span.add_event(
1007
- "http.request.error",
1008
- {
1009
- "method": method,
1010
- "path": path,
1011
- "error.type": type(e).__name__,
1012
- "error.message": str(e),
1013
- },
1014
- )
1042
+ # Add event for error
1043
+ span.add_event(
1044
+ "http.request.error",
1045
+ {
1046
+ "method": method,
1047
+ "path": path,
1048
+ "error.type": type(e).__name__,
1049
+ "error.message": str(e),
1050
+ },
1051
+ )
1015
1052
 
1016
- # Record HTTP error metrics
1017
- try:
1018
- from golf.metrics import get_metrics_collector
1053
+ # Record HTTP error metrics
1054
+ try:
1055
+ from golf.metrics import get_metrics_collector
1056
+
1057
+ metrics_collector = get_metrics_collector()
1058
+
1059
+ # Clean up path for metrics
1060
+ clean_path = path.split("?")[0]
1061
+ if clean_path.startswith("/"):
1062
+ clean_path = clean_path[1:] or "root"
1063
+
1064
+ metrics_collector.increment_http_request(
1065
+ method, 500, clean_path
1066
+ ) # Assume 500 for exceptions
1067
+ metrics_collector.increment_error("http", type(e).__name__)
1068
+ except ImportError:
1069
+ pass
1070
+
1071
+ raise
1072
+ finally:
1073
+ if token:
1074
+ context.detach(token)
1019
1075
 
1020
- metrics_collector = get_metrics_collector()
1021
1076
 
1022
- # Clean up path for metrics
1023
- clean_path = path.split("?")[0]
1024
- if clean_path.startswith("/"):
1025
- clean_path = clean_path[1:] or "root"
1077
+ @asynccontextmanager
1078
+ async def telemetry_lifespan(mcp_instance):
1079
+ """Simplified lifespan for telemetry initialization and cleanup."""
1080
+ global _provider
1026
1081
 
1027
- metrics_collector.increment_http_request(
1028
- method, 500, clean_path
1029
- ) # Assume 500 for exceptions
1030
- metrics_collector.increment_error("http", type(e).__name__)
1031
- except ImportError:
1032
- pass
1082
+ # Initialize telemetry with the server name
1083
+ provider = init_telemetry(service_name=mcp_instance.name)
1033
1084
 
1034
- raise
1035
- finally:
1036
- if token:
1037
- context.detach(token)
1085
+ # If provider is None, telemetry is disabled
1086
+ if provider is None:
1087
+ # Just yield without any telemetry setup
1088
+ yield
1089
+ return
1038
1090
 
1091
+ # Try to add session tracking middleware if possible
1092
+ try:
1039
1093
  # Try to add middleware to FastMCP app if it has Starlette app
1040
1094
  if hasattr(mcp_instance, "app") or hasattr(mcp_instance, "_app"):
1041
1095
  app = getattr(mcp_instance, "app", getattr(mcp_instance, "_app", None))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: golf-mcp
3
- Version: 0.1.18
3
+ Version: 0.1.20
4
4
  Summary: Framework for building MCP servers
5
5
  Author-email: Antoni Gmitruk <antoni@golf.dev>
6
6
  License-Expression: Apache-2.0
@@ -28,12 +28,11 @@ Requires-Dist: black>=24.10.0
28
28
  Requires-Dist: pyjwt>=2.0.0
29
29
  Requires-Dist: httpx>=0.28.1
30
30
  Requires-Dist: posthog>=4.1.0
31
- Provides-Extra: telemetry
32
- Requires-Dist: opentelemetry-api>=1.33.1; extra == "telemetry"
33
- Requires-Dist: opentelemetry-sdk>=1.33.1; extra == "telemetry"
34
- Requires-Dist: opentelemetry-instrumentation-asgi>=0.40b0; extra == "telemetry"
35
- Requires-Dist: opentelemetry-exporter-otlp-proto-http>=0.40b0; extra == "telemetry"
36
- Requires-Dist: wrapt>=1.17.0; extra == "telemetry"
31
+ Requires-Dist: opentelemetry-api>=1.33.1
32
+ Requires-Dist: opentelemetry-sdk>=1.33.1
33
+ Requires-Dist: opentelemetry-instrumentation-asgi>=0.40b0
34
+ Requires-Dist: opentelemetry-exporter-otlp-proto-http>=0.40b0
35
+ Requires-Dist: wrapt>=1.17.0
37
36
  Provides-Extra: metrics
38
37
  Requires-Dist: prometheus-client>=0.22.1; extra == "metrics"
39
38
  Dynamic: license-file
@@ -1,4 +1,4 @@
1
- golf/__init__.py,sha256=6BiuMUkhwQp6bzUZSF8np8F1NwCltEtK0sPBF__tepU,23
1
+ golf/__init__.py,sha256=8XalsVoLEfXslFvdtUEmkNOuYShzOzYOcFbgmOz1oSk,23
2
2
  golf/auth/__init__.py,sha256=Rj4yUngJklk6xrDCrxqLTtoDAMzF1HcTvy_l8wREeao,4103
3
3
  golf/auth/api_key.py,sha256=LiIraLiH2v7s3yavidaI6BDlAEfK8XnWF15QmaJn9G4,2378
4
4
  golf/auth/helpers.py,sha256=ZogdcHM7J2PN6cL6F6OLZ3gyoUR3dwAFDxOJQ2DW_bc,6526
@@ -11,13 +11,13 @@ golf/commands/build.py,sha256=jhdxB5EwwCC_8PgqdXLUKuBpnycjh0gft3_7EuTo6ro,2319
11
11
  golf/commands/init.py,sha256=DUAvGqOUapWdF2cgWPscqHRvyOZDiajR0F0Wkn_jm-k,10355
12
12
  golf/commands/run.py,sha256=xsiG5LZw4qVt3cRTTfIoWP4Bf4AxNBBJKx0NNfoua40,2884
13
13
  golf/core/__init__.py,sha256=4bKeskJ2fPaZqkz2xQScSa3phRLLrmrczwSL632jv-o,52
14
- golf/core/builder.py,sha256=flsXnlwOTUhXFMpmZwoxWgnK_oLj4zpSyqcKuDnXezw,59526
14
+ golf/core/builder.py,sha256=06BccMHR6BFMsdyL-3YJJFqLHVLE-NYSQriVyPFzL6s,59657
15
15
  golf/core/builder_auth.py,sha256=nGgyMTiRAqaNfh1FSvoFe6oTVq9RgfMf9JoFGAv2_do,14050
16
16
  golf/core/builder_metrics.py,sha256=j6Gtgd867o46JbDfSNGNsHt1QtV1XHKUJs1z8r4siQM,8830
17
17
  golf/core/builder_telemetry.py,sha256=jobFgRSspLQLuitL4ytk6asSUdTqYcDxGY3sTjkrZd4,2654
18
18
  golf/core/config.py,sha256=6yPtwzVTJauufEnrfUbxsz69H8jC0Ra427oDaRM0-xE,7397
19
19
  golf/core/parser.py,sha256=BQRus1O9zmzSmyavwLVfN8BpYFkbrWUDrgQ7yrYfAKw,42457
20
- golf/core/platform.py,sha256=Z2yEi6ilmQCLC_uAD_oZdVO0WvkL4tsyw7sx0vHhysI,6440
20
+ golf/core/platform.py,sha256=y8-yhRPfvm-Eu44p_kN9wg74n1kB2HweRgRYy-Gu1c4,6473
21
21
  golf/core/telemetry.py,sha256=CjZ7urbizaRjyFiVBjfGW8V4PmNCG1_quk3FvbVTcjw,15772
22
22
  golf/core/transformer.py,sha256=_0nM42M41oM9zw_XxPVVS6MErdBSw2B5lULC7_UFLfU,5287
23
23
  golf/examples/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -51,10 +51,10 @@ golf/metrics/__init__.py,sha256=O91y-hj_E9R06gqV8pDZrzHxOIl-1T415Hj9RvFAp3o,283
51
51
  golf/metrics/collector.py,sha256=iyRszP8TAAigyOsUFTGdKN8Xeob36LhUvXW9tntJrbA,7617
52
52
  golf/metrics/registry.py,sha256=mXQE4Pwf3PopGYjcUu4eGgPDAe085YWcsvcvWk0ny8Q,310
53
53
  golf/telemetry/__init__.py,sha256=ESGCg5HKwTCIfID1e_K7EE0bOWkSzMidlLtdqQgBd0w,396
54
- golf/telemetry/instrumentation.py,sha256=Sn7KBJSCf0Kih9ILEdminR0HggpbOlBKToJhnC4PmZE,44934
55
- golf_mcp-0.1.18.dist-info/licenses/LICENSE,sha256=5_j2f6fTJmvfmUewzElhkpAaXg2grVoxKouOA8ihV6E,11348
56
- golf_mcp-0.1.18.dist-info/METADATA,sha256=w8GR9q2Ln0UzWTXRFG6XdA1EzbAVUsF7D0tq1nEMqd4,12956
57
- golf_mcp-0.1.18.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
58
- golf_mcp-0.1.18.dist-info/entry_points.txt,sha256=5y7rHYM8jGpU-nfwdknCm5XsApLulqsnA37MO6BUTYg,43
59
- golf_mcp-0.1.18.dist-info/top_level.txt,sha256=BQToHcBUufdyhp9ONGMIvPE40jMEtmI20lYaKb4hxOg,5
60
- golf_mcp-0.1.18.dist-info/RECORD,,
54
+ golf/telemetry/instrumentation.py,sha256=t0iuoIuY3mmtcdNAlUvbUgUfpRkH0mZoYg2C6qm8g2s,45320
55
+ golf_mcp-0.1.20.dist-info/licenses/LICENSE,sha256=5_j2f6fTJmvfmUewzElhkpAaXg2grVoxKouOA8ihV6E,11348
56
+ golf_mcp-0.1.20.dist-info/METADATA,sha256=erjB5udWAGp_OQa3MiPhwbpi0R7zZAJeTMpSqnl67Rg,12820
57
+ golf_mcp-0.1.20.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
58
+ golf_mcp-0.1.20.dist-info/entry_points.txt,sha256=5y7rHYM8jGpU-nfwdknCm5XsApLulqsnA37MO6BUTYg,43
59
+ golf_mcp-0.1.20.dist-info/top_level.txt,sha256=BQToHcBUufdyhp9ONGMIvPE40jMEtmI20lYaKb4hxOg,5
60
+ golf_mcp-0.1.20.dist-info/RECORD,,