golf-mcp 0.1.12__tar.gz → 0.1.13__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.
Potentially problematic release.
This version of golf-mcp might be problematic. Click here for more details.
- {golf_mcp-0.1.12/src/golf_mcp.egg-info → golf_mcp-0.1.13}/PKG-INFO +1 -1
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/pyproject.toml +2 -2
- golf_mcp-0.1.13/src/golf/__init__.py +1 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/cli/main.py +53 -38
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/commands/run.py +16 -2
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/core/builder.py +17 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/core/telemetry.py +91 -17
- {golf_mcp-0.1.12 → golf_mcp-0.1.13/src/golf_mcp.egg-info}/PKG-INFO +1 -1
- golf_mcp-0.1.12/src/golf/__init__.py +0 -1
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/.docs/docs.md +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/.docs/fast-mcp.md +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/.docs/fastmcp-example-1.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/.docs/fastmcp-example-2.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/.docs/mcp.md +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/.docs/oauth-implementation.md +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/.docs/oauth.md +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/LICENSE +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/MANIFEST.in +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/README.md +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/setup.cfg +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/auth/__init__.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/auth/api_key.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/auth/helpers.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/auth/oauth.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/auth/provider.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/cli/__init__.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/commands/__init__.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/commands/build.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/commands/init.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/core/__init__.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/core/builder_auth.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/core/builder_telemetry.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/core/config.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/core/parser.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/core/transformer.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/__init__.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/api_key/.env +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/api_key/.env.example +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/api_key/README.md +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/api_key/golf.json +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/api_key/pre_build.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/api_key/tools/issues/create.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/api_key/tools/issues/list.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/api_key/tools/repos/list.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/api_key/tools/search/code.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/api_key/tools/users/get.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/.env +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/.env.example +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/README.md +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/golf.json +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/pre_build.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/prompts/welcome.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/resources/current_time.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/resources/info.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/resources/weather/common.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/resources/weather/current.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/resources/weather/forecast.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/tools/github_user.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/tools/hello.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/tools/payments/charge.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/tools/payments/common.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/examples/basic/tools/payments/refund.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/telemetry/__init__.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf/telemetry/instrumentation.py +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf_mcp.egg-info/SOURCES.txt +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf_mcp.egg-info/dependency_links.txt +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf_mcp.egg-info/entry_points.txt +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf_mcp.egg-info/requires.txt +0 -0
- {golf_mcp-0.1.12 → golf_mcp-0.1.13}/src/golf_mcp.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "golf-mcp"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.13"
|
|
8
8
|
description = "Framework for building MCP servers"
|
|
9
9
|
authors = [
|
|
10
10
|
{name = "Antoni Gmitruk", email = "antoni@golf.dev"}
|
|
@@ -64,7 +64,7 @@ golf = ["examples/**/*"]
|
|
|
64
64
|
|
|
65
65
|
[tool.poetry]
|
|
66
66
|
name = "golf-mcp"
|
|
67
|
-
version = "0.1.
|
|
67
|
+
version = "0.1.13"
|
|
68
68
|
description = "Framework for building MCP servers with zero boilerplate"
|
|
69
69
|
authors = ["Antoni Gmitruk <antoni@golf.dev>"]
|
|
70
70
|
license = "Apache-2.0"
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.13"
|
|
@@ -15,6 +15,8 @@ from golf.core.telemetry import (
|
|
|
15
15
|
set_telemetry_enabled,
|
|
16
16
|
shutdown,
|
|
17
17
|
track_event,
|
|
18
|
+
track_detailed_error,
|
|
19
|
+
_detect_execution_environment,
|
|
18
20
|
)
|
|
19
21
|
|
|
20
22
|
# Create console for rich output
|
|
@@ -156,16 +158,12 @@ def build_dev(
|
|
|
156
158
|
# Track successful build with environment
|
|
157
159
|
track_event("cli_build_success", {"success": True, "environment": "dev"})
|
|
158
160
|
except Exception as e:
|
|
159
|
-
|
|
160
|
-
error_message = str(e)
|
|
161
|
-
track_event(
|
|
161
|
+
track_detailed_error(
|
|
162
162
|
"cli_build_failed",
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
"error_message": error_message,
|
|
168
|
-
},
|
|
163
|
+
e,
|
|
164
|
+
context="Development build with environment variables",
|
|
165
|
+
operation="build_dev",
|
|
166
|
+
additional_props={"environment": "dev", "copy_env": True}
|
|
169
167
|
)
|
|
170
168
|
raise
|
|
171
169
|
|
|
@@ -212,16 +210,12 @@ def build_prod(
|
|
|
212
210
|
# Track successful build with environment
|
|
213
211
|
track_event("cli_build_success", {"success": True, "environment": "prod"})
|
|
214
212
|
except Exception as e:
|
|
215
|
-
|
|
216
|
-
error_message = str(e)
|
|
217
|
-
track_event(
|
|
213
|
+
track_detailed_error(
|
|
218
214
|
"cli_build_failed",
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
"error_message": error_message,
|
|
224
|
-
},
|
|
215
|
+
e,
|
|
216
|
+
context="Production build without environment variables",
|
|
217
|
+
operation="build_prod",
|
|
218
|
+
additional_props={"environment": "prod", "copy_env": False}
|
|
225
219
|
)
|
|
226
220
|
raise
|
|
227
221
|
|
|
@@ -282,18 +276,15 @@ def run(
|
|
|
282
276
|
|
|
283
277
|
build_project(project_root, settings, dist_dir)
|
|
284
278
|
except Exception as e:
|
|
285
|
-
error_type = type(e).__name__
|
|
286
|
-
error_message = str(e)
|
|
287
279
|
console.print(
|
|
288
|
-
f"[bold red]Error building project:[/bold red] {
|
|
280
|
+
f"[bold red]Error building project:[/bold red] {str(e)}"
|
|
289
281
|
)
|
|
290
|
-
|
|
282
|
+
track_detailed_error(
|
|
291
283
|
"cli_run_failed",
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
},
|
|
284
|
+
e,
|
|
285
|
+
context="Auto-build before running server",
|
|
286
|
+
operation="auto_build_before_run",
|
|
287
|
+
additional_props={"auto_build": True}
|
|
297
288
|
)
|
|
298
289
|
raise
|
|
299
290
|
else:
|
|
@@ -325,16 +316,43 @@ def run(
|
|
|
325
316
|
port=port,
|
|
326
317
|
)
|
|
327
318
|
|
|
328
|
-
# Track based on return code
|
|
319
|
+
# Track based on return code with better categorization
|
|
329
320
|
if return_code == 0:
|
|
330
321
|
track_event("cli_run_success", {"success": True})
|
|
322
|
+
elif return_code in [130, 143, 137, 2]:
|
|
323
|
+
# Intentional shutdowns (not errors):
|
|
324
|
+
# 130: Ctrl+C (SIGINT)
|
|
325
|
+
# 143: SIGTERM (graceful shutdown, e.g., Kubernetes, Docker)
|
|
326
|
+
# 137: SIGKILL (forced shutdown)
|
|
327
|
+
# 2: General interrupt/graceful shutdown
|
|
328
|
+
shutdown_type = {
|
|
329
|
+
130: "UserInterrupt",
|
|
330
|
+
143: "GracefulShutdown",
|
|
331
|
+
137: "ForcedShutdown",
|
|
332
|
+
2: "Interrupt"
|
|
333
|
+
}.get(return_code, "GracefulShutdown")
|
|
334
|
+
|
|
335
|
+
track_event(
|
|
336
|
+
"cli_run_shutdown",
|
|
337
|
+
{
|
|
338
|
+
"success": True, # Not an error
|
|
339
|
+
"shutdown_type": shutdown_type,
|
|
340
|
+
"exit_code": return_code,
|
|
341
|
+
},
|
|
342
|
+
)
|
|
331
343
|
else:
|
|
344
|
+
# Actual errors (unexpected exit codes)
|
|
332
345
|
track_event(
|
|
333
346
|
"cli_run_failed",
|
|
334
347
|
{
|
|
335
348
|
"success": False,
|
|
336
|
-
"error_type": "
|
|
337
|
-
"error_message": f"Server exited with code {return_code}",
|
|
349
|
+
"error_type": "UnexpectedExit",
|
|
350
|
+
"error_message": f"Server process exited unexpectedly with code {return_code}",
|
|
351
|
+
"exit_code": return_code,
|
|
352
|
+
"operation": "server_process_execution",
|
|
353
|
+
"context": "Server process terminated with unexpected exit code",
|
|
354
|
+
# Add execution environment context
|
|
355
|
+
"execution_env": _detect_execution_environment(),
|
|
338
356
|
},
|
|
339
357
|
)
|
|
340
358
|
|
|
@@ -342,15 +360,12 @@ def run(
|
|
|
342
360
|
if return_code != 0:
|
|
343
361
|
raise typer.Exit(code=return_code)
|
|
344
362
|
except Exception as e:
|
|
345
|
-
|
|
346
|
-
error_message = str(e)
|
|
347
|
-
track_event(
|
|
363
|
+
track_detailed_error(
|
|
348
364
|
"cli_run_failed",
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
},
|
|
365
|
+
e,
|
|
366
|
+
context="Server execution or startup failure",
|
|
367
|
+
operation="run_server_execution",
|
|
368
|
+
additional_props={"has_dist_dir": dist_dir.exists() if dist_dir else False}
|
|
354
369
|
)
|
|
355
370
|
raise
|
|
356
371
|
|
|
@@ -64,10 +64,24 @@ def run_server(
|
|
|
64
64
|
env=env,
|
|
65
65
|
)
|
|
66
66
|
|
|
67
|
+
# Provide more context about the exit
|
|
68
|
+
if process.returncode == 0:
|
|
69
|
+
console.print("[green]Server stopped successfully[/green]")
|
|
70
|
+
elif process.returncode == 130:
|
|
71
|
+
console.print("[yellow]Server stopped by user interrupt (Ctrl+C)[/yellow]")
|
|
72
|
+
elif process.returncode == 143:
|
|
73
|
+
console.print("[yellow]Server stopped by SIGTERM (graceful shutdown)[/yellow]")
|
|
74
|
+
elif process.returncode == 137:
|
|
75
|
+
console.print("[yellow]Server stopped by SIGKILL (forced shutdown)[/yellow]")
|
|
76
|
+
elif process.returncode in [1, 2]:
|
|
77
|
+
console.print(f"[red]Server exited with error code {process.returncode}[/red]")
|
|
78
|
+
else:
|
|
79
|
+
console.print(f"[orange]Server exited with code {process.returncode}[/orange]")
|
|
80
|
+
|
|
67
81
|
return process.returncode
|
|
68
82
|
except KeyboardInterrupt:
|
|
69
|
-
console.print("\n[yellow]Server stopped by user[/yellow]")
|
|
70
|
-
return
|
|
83
|
+
console.print("\n[yellow]Server stopped by user (Ctrl+C)[/yellow]")
|
|
84
|
+
return 130 # Standard exit code for SIGINT
|
|
71
85
|
except Exception as e:
|
|
72
86
|
console.print(f"\n[bold red]Error running server:[/bold red] {e}")
|
|
73
87
|
return 1
|
|
@@ -950,6 +950,23 @@ def build_project(
|
|
|
950
950
|
import traceback
|
|
951
951
|
|
|
952
952
|
console.print(f"[red]{traceback.format_exc()}[/red]")
|
|
953
|
+
|
|
954
|
+
# Track detailed error for pre_build.py execution failures
|
|
955
|
+
try:
|
|
956
|
+
from golf.core.telemetry import track_detailed_error
|
|
957
|
+
track_detailed_error(
|
|
958
|
+
"build_pre_build_failed",
|
|
959
|
+
e,
|
|
960
|
+
context="Executing pre_build.py configuration script",
|
|
961
|
+
operation="pre_build_execution",
|
|
962
|
+
additional_props={
|
|
963
|
+
"file_path": str(pre_build_path.relative_to(project_path)),
|
|
964
|
+
"build_env": build_env,
|
|
965
|
+
}
|
|
966
|
+
)
|
|
967
|
+
except Exception:
|
|
968
|
+
# Don't let telemetry errors break the build
|
|
969
|
+
pass
|
|
953
970
|
|
|
954
971
|
# Clear the output directory if it exists
|
|
955
972
|
if output_dir.exists():
|
|
@@ -189,11 +189,11 @@ def initialize_telemetry() -> None:
|
|
|
189
189
|
"""Initialize PostHog telemetry if enabled."""
|
|
190
190
|
# Ensure PostHog is disabled in test mode
|
|
191
191
|
_ensure_posthog_disabled_in_test_mode()
|
|
192
|
-
|
|
192
|
+
|
|
193
193
|
# Don't initialize if PostHog is disabled (test mode)
|
|
194
194
|
if posthog.disabled:
|
|
195
195
|
return
|
|
196
|
-
|
|
196
|
+
|
|
197
197
|
if not is_telemetry_enabled():
|
|
198
198
|
return
|
|
199
199
|
|
|
@@ -281,6 +281,8 @@ def track_event(event_name: str, properties: dict[str, Any] | None = None) -> No
|
|
|
281
281
|
"command_type",
|
|
282
282
|
"error_type",
|
|
283
283
|
"error_message",
|
|
284
|
+
"shutdown_type",
|
|
285
|
+
"exit_code",
|
|
284
286
|
}
|
|
285
287
|
for key in safe_keys:
|
|
286
288
|
if key in properties:
|
|
@@ -326,26 +328,98 @@ def track_command(
|
|
|
326
328
|
track_event(f"cli_{command}", properties)
|
|
327
329
|
|
|
328
330
|
|
|
329
|
-
def
|
|
330
|
-
|
|
331
|
+
def track_detailed_error(
|
|
332
|
+
event_name: str,
|
|
333
|
+
error: Exception,
|
|
334
|
+
context: str | None = None,
|
|
335
|
+
operation: str | None = None,
|
|
336
|
+
additional_props: dict[str, Any] | None = None,
|
|
337
|
+
) -> None:
|
|
338
|
+
"""Track a detailed error with enhanced debugging information.
|
|
331
339
|
|
|
332
340
|
Args:
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
341
|
+
event_name: Name of the error event (e.g., "cli_run_failed", "cli_build_failed")
|
|
342
|
+
error: The exception that occurred
|
|
343
|
+
context: Additional context about where the error occurred
|
|
344
|
+
operation: The specific operation that failed
|
|
345
|
+
additional_props: Additional properties to include
|
|
337
346
|
"""
|
|
347
|
+
import traceback
|
|
348
|
+
import time
|
|
349
|
+
|
|
350
|
+
properties = {
|
|
351
|
+
"success": False,
|
|
352
|
+
"error_type": type(error).__name__,
|
|
353
|
+
"error_message": _sanitize_error_message(str(error)),
|
|
354
|
+
"timestamp": int(time.time()),
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
# Add operation context
|
|
358
|
+
if operation:
|
|
359
|
+
properties["operation"] = operation
|
|
360
|
+
if context:
|
|
361
|
+
properties["context"] = context
|
|
362
|
+
|
|
363
|
+
# Add sanitized stack trace for debugging
|
|
364
|
+
try:
|
|
365
|
+
tb_lines = traceback.format_exception(type(error), error, error.__traceback__)
|
|
366
|
+
# Get the last few frames (most relevant) and sanitize them
|
|
367
|
+
relevant_frames = tb_lines[-3:] if len(tb_lines) > 3 else tb_lines
|
|
368
|
+
sanitized_trace = []
|
|
369
|
+
|
|
370
|
+
for frame in relevant_frames:
|
|
371
|
+
# Sanitize file paths in stack trace
|
|
372
|
+
sanitized_frame = _sanitize_error_message(frame.strip())
|
|
373
|
+
# Further sanitize common traceback patterns
|
|
374
|
+
sanitized_frame = sanitized_frame.replace('File "[PATH]', 'File "[PATH]')
|
|
375
|
+
sanitized_trace.append(sanitized_frame)
|
|
376
|
+
|
|
377
|
+
properties["stack_trace"] = " | ".join(sanitized_trace)
|
|
378
|
+
|
|
379
|
+
# Add the specific line that caused the error if available
|
|
380
|
+
if hasattr(error, '__traceback__') and error.__traceback__:
|
|
381
|
+
tb = error.__traceback__
|
|
382
|
+
while tb.tb_next:
|
|
383
|
+
tb = tb.tb_next
|
|
384
|
+
properties["error_line"] = tb.tb_lineno
|
|
385
|
+
|
|
386
|
+
except Exception:
|
|
387
|
+
# Don't fail if we can't capture stack trace
|
|
388
|
+
pass
|
|
389
|
+
|
|
390
|
+
# Add system context for debugging
|
|
391
|
+
try:
|
|
392
|
+
properties["python_executable"] = _sanitize_error_message(platform.python_implementation())
|
|
393
|
+
properties["platform_detail"] = platform.platform()[:50] # Limit length
|
|
394
|
+
except Exception:
|
|
395
|
+
pass
|
|
396
|
+
|
|
397
|
+
# Merge additional properties
|
|
398
|
+
if additional_props:
|
|
399
|
+
# Only include safe additional properties
|
|
400
|
+
safe_additional_keys = {
|
|
401
|
+
"exit_code", "shutdown_type", "environment", "template",
|
|
402
|
+
"build_env", "transport", "component_count", "file_path",
|
|
403
|
+
"component_type", "validation_error", "config_error"
|
|
404
|
+
}
|
|
405
|
+
for key, value in additional_props.items():
|
|
406
|
+
if key in safe_additional_keys:
|
|
407
|
+
properties[key] = value
|
|
408
|
+
|
|
409
|
+
track_event(event_name, properties)
|
|
410
|
+
|
|
411
|
+
def _sanitize_error_message(message: str) -> str:
|
|
412
|
+
"""Sanitize error messages to remove sensitive information."""
|
|
338
413
|
import re
|
|
339
414
|
|
|
340
|
-
# Remove
|
|
341
|
-
#
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
message = re.sub(r'(?:^|[\s"])(/[^\s"\']+/)+([^/\s"\']+)', r"\2", message)
|
|
415
|
+
# Remove file paths but preserve filenames
|
|
416
|
+
# Match paths with directories and capture the filename
|
|
417
|
+
# Unix style: /path/to/file.py -> file.py
|
|
418
|
+
message = re.sub(r"(/[^/\s]+)+/([^/\s]+)", r"\2", message)
|
|
419
|
+
# Windows style: C:\path\to\file.py -> file.py
|
|
420
|
+
message = re.sub(r"([A-Za-z]:\\[^\\]+\\)+([^\\]+)", r"\2", message)
|
|
421
|
+
# Remaining absolute paths without filename
|
|
422
|
+
message = re.sub(r"[/\\][^\s]*[/\\]", "[PATH]/", message)
|
|
349
423
|
|
|
350
424
|
# Remove potential API keys or tokens (common patterns)
|
|
351
425
|
# Generic API keys (20+ alphanumeric with underscores/hyphens)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.1.12"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|