golf-mcp 0.1.9__py3-none-any.whl → 0.1.11__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 +1 -1
- golf/auth/__init__.py +1 -1
- golf/auth/helpers.py +112 -2
- golf/cli/main.py +27 -14
- golf/commands/init.py +73 -62
- golf/core/builder.py +35 -12
- golf/core/builder_auth.py +31 -91
- golf/core/telemetry.py +57 -4
- golf/telemetry/instrumentation.py +511 -151
- {golf_mcp-0.1.9.dist-info → golf_mcp-0.1.11.dist-info}/METADATA +1 -1
- {golf_mcp-0.1.9.dist-info → golf_mcp-0.1.11.dist-info}/RECORD +15 -15
- {golf_mcp-0.1.9.dist-info → golf_mcp-0.1.11.dist-info}/WHEEL +1 -1
- {golf_mcp-0.1.9.dist-info → golf_mcp-0.1.11.dist-info}/entry_points.txt +0 -0
- {golf_mcp-0.1.9.dist-info → golf_mcp-0.1.11.dist-info}/licenses/LICENSE +0 -0
- {golf_mcp-0.1.9.dist-info → golf_mcp-0.1.11.dist-info}/top_level.txt +0 -0
golf/core/telemetry.py
CHANGED
|
@@ -243,7 +243,7 @@ def track_event(event_name: str, properties: Optional[Dict[str, Any]] = None) ->
|
|
|
243
243
|
# Filter properties to only include safe ones
|
|
244
244
|
if properties:
|
|
245
245
|
# Only include specific safe properties
|
|
246
|
-
safe_keys = {"success", "environment", "template", "command_type"}
|
|
246
|
+
safe_keys = {"success", "environment", "template", "command_type", "error_type", "error_message"}
|
|
247
247
|
for key in safe_keys:
|
|
248
248
|
if key in properties:
|
|
249
249
|
safe_properties[key] = properties[key]
|
|
@@ -260,15 +260,68 @@ def track_event(event_name: str, properties: Optional[Dict[str, Any]] = None) ->
|
|
|
260
260
|
pass
|
|
261
261
|
|
|
262
262
|
|
|
263
|
-
def track_command(command: str, success: bool = True) -> None:
|
|
263
|
+
def track_command(command: str, success: bool = True, error_type: Optional[str] = None, error_message: Optional[str] = None) -> None:
|
|
264
264
|
"""Track a CLI command execution with minimal info.
|
|
265
265
|
|
|
266
266
|
Args:
|
|
267
267
|
command: The command being executed (e.g., "init", "build", "run")
|
|
268
268
|
success: Whether the command was successful
|
|
269
|
+
error_type: Type of error if command failed (e.g., "ValueError", "FileNotFoundError")
|
|
270
|
+
error_message: Sanitized error message (no sensitive data)
|
|
269
271
|
"""
|
|
270
|
-
|
|
271
|
-
|
|
272
|
+
properties = {"success": success}
|
|
273
|
+
|
|
274
|
+
# Add error details if command failed
|
|
275
|
+
if not success and (error_type or error_message):
|
|
276
|
+
if error_type:
|
|
277
|
+
properties["error_type"] = error_type
|
|
278
|
+
if error_message:
|
|
279
|
+
# Sanitize error message - remove file paths and sensitive info
|
|
280
|
+
sanitized_message = _sanitize_error_message(error_message)
|
|
281
|
+
properties["error_message"] = sanitized_message
|
|
282
|
+
|
|
283
|
+
track_event(f"cli_{command}", properties)
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def _sanitize_error_message(message: str) -> str:
|
|
287
|
+
"""Sanitize error message to remove sensitive information.
|
|
288
|
+
|
|
289
|
+
Args:
|
|
290
|
+
message: Raw error message
|
|
291
|
+
|
|
292
|
+
Returns:
|
|
293
|
+
Sanitized error message
|
|
294
|
+
"""
|
|
295
|
+
import re
|
|
296
|
+
|
|
297
|
+
# Remove absolute file paths but keep the filename
|
|
298
|
+
# Unix-style paths
|
|
299
|
+
message = re.sub(r'/(?:Users|home|var|tmp|opt|usr|etc)/[^\s"\']+/([^/\s"\']+)', r'\1', message)
|
|
300
|
+
# Windows-style paths
|
|
301
|
+
message = re.sub(r'[A-Za-z]:\\[^\s"\']+\\([^\\s"\']+)', r'\1', message)
|
|
302
|
+
# Generic path pattern (catches remaining paths)
|
|
303
|
+
message = re.sub(r'(?:^|[\s"])(/[^\s"\']+/)+([^/\s"\']+)', r'\2', message)
|
|
304
|
+
|
|
305
|
+
# Remove potential API keys or tokens (common patterns)
|
|
306
|
+
# Generic API keys (20+ alphanumeric with underscores/hyphens)
|
|
307
|
+
message = re.sub(r'\b[a-zA-Z0-9_-]{32,}\b', '[REDACTED]', message)
|
|
308
|
+
# Bearer tokens
|
|
309
|
+
message = re.sub(r'Bearer\s+[a-zA-Z0-9_.-]+', 'Bearer [REDACTED]', message)
|
|
310
|
+
|
|
311
|
+
# Remove email addresses
|
|
312
|
+
message = re.sub(r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b', '[EMAIL]', message)
|
|
313
|
+
|
|
314
|
+
# Remove IP addresses
|
|
315
|
+
message = re.sub(r'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b', '[IP]', message)
|
|
316
|
+
|
|
317
|
+
# Remove port numbers in URLs
|
|
318
|
+
message = re.sub(r':[0-9]{2,5}(?=/|$|\s)', ':[PORT]', message)
|
|
319
|
+
|
|
320
|
+
# Truncate to reasonable length
|
|
321
|
+
if len(message) > 200:
|
|
322
|
+
message = message[:197] + "..."
|
|
323
|
+
|
|
324
|
+
return message
|
|
272
325
|
|
|
273
326
|
|
|
274
327
|
def flush() -> None:
|