leanback 0.1.1__tar.gz → 0.1.2__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: leanback
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: MCP server for Lean 4 theorem proving — check, prove, goals, eval, search
5
5
  Author: Stefan Szeider
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "leanback"
7
- version = "0.1.1"
7
+ version = "0.1.2"
8
8
  description = "MCP server for Lean 4 theorem proving — check, prove, goals, eval, search"
9
9
  readme = "README.md"
10
10
  license = { text = "Apache-2.0" }
@@ -1,3 +1,3 @@
1
1
  """LeanBack - Lean 4 development tools for Claude Code."""
2
2
 
3
- __version__ = "0.3.0"
3
+ __version__ = "0.1.2"
@@ -295,8 +295,8 @@ def check_project(
295
295
  lean_files = list(project_path.glob("**/*.lean"))
296
296
 
297
297
  for file_path in lean_files:
298
- # Skip files in .lake directory
299
- if ".lake" in file_path.parts:
298
+ # Skip files in .lake directory and lakefile.lean (uses Lake DSL, not standard Lean)
299
+ if ".lake" in file_path.parts or file_path.name == "lakefile.lean":
300
300
  continue
301
301
 
302
302
  console.print(f"Checking {file_path.relative_to(project_path)}...")
@@ -170,11 +170,26 @@ def _clean_lean_message(message: str) -> str:
170
170
  return message
171
171
 
172
172
 
173
- def _serialize_errors(errors: list, sanitize_paths: bool = False) -> list[dict]:
174
- """Serialize LeanError objects to dicts for JSON output."""
173
+ def _serialize_errors(
174
+ errors: list, sanitize_paths: bool = False, source_file: str | None = None
175
+ ) -> list[dict]:
176
+ """Serialize LeanError objects to dicts for JSON output.
177
+
178
+ If source_file is provided, temp file paths are replaced with it
179
+ instead of the generic '<inline>' label.
180
+ """
181
+
182
+ def _resolve_path(file_name: str) -> str:
183
+ if not sanitize_paths:
184
+ return file_name
185
+ sanitized = _sanitize_file_path(file_name)
186
+ if sanitized == "<inline>" and source_file:
187
+ return source_file
188
+ return sanitized
189
+
175
190
  return [
176
191
  {
177
- "file": _sanitize_file_path(e.file_name) if sanitize_paths else e.file_name,
192
+ "file": _resolve_path(e.file_name),
178
193
  "line": e.line,
179
194
  "column": e.column,
180
195
  "end_line": e.end_line,
@@ -413,7 +428,7 @@ def check(
413
428
  - file: Path to a .lean file within the project (e.g., "Basic.lean", "src/Logic.lean")
414
429
  - check_all: Check each file individually for detailed error reporting (slower but more thorough)
415
430
  - expr: A Lean expression or command to check (e.g., "2 + 2 = 4", "Nat.add", "#eval 1 + 1"). Bare expressions are auto-wrapped in #check.
416
- - imports: List of modules to import when checking expressions (e.g., ["Mathlib.Tactic"])
431
+ - imports: List of modules to import when checking expressions (e.g., ["Mathlib.Tactic"]). First Mathlib import takes ~20-30s.
417
432
 
418
433
  Returns JSON with 'success' boolean. The 'messages' array contains objects with:
419
434
  - file: Path to the file (or "<inline>" for expressions)
@@ -565,6 +580,12 @@ def check(
565
580
  "files_checked": 1,
566
581
  },
567
582
  }
583
+ if file_path.name == "lakefile.lean" and not success:
584
+ result["note"] = (
585
+ "lakefile.lean uses Lake DSL which may produce errors "
586
+ "when checked outside the build system. "
587
+ "These errors are typically not actionable."
588
+ )
568
589
  return _json(result)
569
590
 
570
591
  # Case 3: Check entire project
@@ -620,7 +641,7 @@ def prove(
620
641
  - tactics: List of proof tactics to apply in order (e.g., ["intro n", "rfl"])
621
642
  - file: Path to a .lean file containing complete proofs to verify
622
643
  - imports: Additional modules to import (e.g., ["Mathlib.Data.Nat.Basic"])
623
- - mathlib: Import Mathlib.Tactic for all standard tactics (simp, ring, omega, linarith, norm_num, decide, aesop, etc.)
644
+ - mathlib: Import Mathlib.Tactic for all standard tactics (simp, ring, omega, linarith, norm_num, decide, aesop, etc.). First call takes ~8-11s for import.
624
645
 
625
646
  Use either (theorem + tactics) OR (file), not both. When using theorem + tactics,
626
647
  the tool constructs and verifies the proof. When using file, it verifies existing proofs.
@@ -798,7 +819,7 @@ def goals(
798
819
  - theorem: Theorem statement to prove (e.g., "2 + 2 = 4", "∀ n : Nat, n + 0 = n")
799
820
  - tactics: List of tactics applied so far (e.g., ["intro n"]). Omit or pass [] to see the initial goal.
800
821
  - imports: Additional modules to import (e.g., ["Mathlib.Data.Nat.Basic"])
801
- - mathlib: Import Mathlib.Tactic for standard tactics (simp, ring, omega, linarith, norm_num, decide, aesop, etc.)
822
+ - mathlib: Import Mathlib.Tactic for standard tactics (simp, ring, omega, linarith, norm_num, decide, aesop, etc.). First call takes ~8-11s for import.
802
823
 
803
824
  Returns JSON with:
804
825
  - success: Whether the tool ran without internal errors
@@ -884,7 +905,7 @@ def eval(
884
905
  - code: Lean code to execute (e.g., "#eval 2 + 2", "#check Nat.add", "def f := 5")
885
906
  - file: Path to a .lean file to execute instead of inline code
886
907
  - imports: Additional modules to import (e.g., ["Mathlib.Data.Finset.Basic"])
887
- - mathlib: Import Mathlib.Tactic for all standard tactics (simp, ring, omega, linarith, norm_num, decide, aesop, etc.)
908
+ - mathlib: Import Mathlib.Tactic for all standard tactics (simp, ring, omega, linarith, norm_num, decide, aesop, etc.). First call takes ~8-11s for import.
888
909
 
889
910
  Use either 'code' OR 'file', not both. The tool can handle multi-line code.
890
911
 
@@ -984,7 +1005,9 @@ def eval(
984
1005
  "type": "code_execution",
985
1006
  "code": code_to_execute,
986
1007
  "imports": resolved_imports,
987
- "messages": _serialize_errors(errors, sanitize_paths=True),
1008
+ "messages": _serialize_errors(
1009
+ errors, sanitize_paths=True, source_file=file
1010
+ ),
988
1011
  }
989
1012
  )
990
1013
 
@@ -1089,6 +1112,12 @@ def search(
1089
1112
  )
1090
1113
 
1091
1114
  results = batch_search_declarations(patterns, project_path, **search_params)
1115
+ if isinstance(results, dict):
1116
+ results["note"] = (
1117
+ "Search covers Mathlib declarations only, "
1118
+ "not core Lean (e.g., Nat.add_comm, List.map). "
1119
+ "Use eval with #check to inspect core declarations."
1120
+ )
1092
1121
  return _json(results)
1093
1122
  else:
1094
1123
  try:
@@ -1122,6 +1151,11 @@ def search(
1122
1151
  "results": serializable_results,
1123
1152
  "metadata": metadata,
1124
1153
  }
1154
+ result["note"] = (
1155
+ "Search covers Mathlib declarations only, "
1156
+ "not core Lean (e.g., Nat.add_comm, List.map). "
1157
+ "Use eval with #check to inspect core declarations."
1158
+ )
1125
1159
  if len(serializable_results) == 0:
1126
1160
  if filter_namespace and total_found > 0:
1127
1161
  result["note"] = (
@@ -1133,7 +1167,7 @@ def search(
1133
1167
  result["note"] = (
1134
1168
  "No matches found. This search covers Mathlib declarations only, "
1135
1169
  "not core Lean (e.g., Nat.add_comm, List.map). "
1136
- "Try a broader pattern or check the declaration name."
1170
+ "Try a broader pattern, or use eval with #check to inspect core declarations."
1137
1171
  )
1138
1172
  return _json(result)
1139
1173
  except SearchError as e:
File without changes
File without changes
File without changes
File without changes
File without changes