26382a7ac6
CI / Clippy (push) Failing after 15m13s
CI / Test (ubuntu-latest) (push) Failing after 16m1s
CI / Test (macos-latest) (push) Has been cancelled
CI / Test (windows-latest) (push) Has been cancelled
CI / Build (no embeddings / no ORT) (push) Has been cancelled
CI / Format (push) Has been cancelled
CI / Cookbook (Node) (push) Has been cancelled
CI / Pi Extension (Node) (push) Has been cancelled
CI / Rust SDK (lean-ctx-client) (push) Has been cancelled
CI / Embed SDK (lean-ctx-sdk) (push) Has been cancelled
CI / Python SDK (leanctx) (push) Has been cancelled
CI / Hermes Plugin (Python) (push) Has been cancelled
CI / SDK Conformance Matrix (push) Has been cancelled
CI / Coverage (push) Has been cancelled
CI / cargo-deny (push) Has been cancelled
CI / Adversarial Safety (push) Has been cancelled
CI / Benchmarks (push) Has been cancelled
CI / Output-Quality Gate (eval A/B) (push) Has been cancelled
CI / Documentation (push) Has been cancelled
CI / CI Green (push) Has been cancelled
JetBrains Plugin / Actionlint (push) Has been cancelled
CodeQL / Analyze (actions) (push) Has been cancelled
CodeQL / Analyze (javascript-typescript) (push) Has been cancelled
CodeQL / Analyze (rust) (push) Has been cancelled
JetBrains Plugin / Validation (push) Has been cancelled
JetBrains Plugin / Build (push) Has been cancelled
JetBrains Plugin / Test (push) Has been cancelled
Security Check / Security Scan (push) Has been cancelled
64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
"""Core client for interacting with the lean-ctx daemon."""
|
|
|
|
import json
|
|
import subprocess
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
|
|
|
|
class LeanCtxClient:
|
|
"""Thin wrapper around the lean-ctx CLI for programmatic access."""
|
|
|
|
def __init__(self, binary: str = "lean-ctx", project_root: Optional[str] = None):
|
|
self.binary = binary
|
|
self.project_root = project_root or str(Path.cwd())
|
|
|
|
def read(self, path: str, mode: str = "auto") -> str:
|
|
return self._run(["read", path, "--mode", mode])
|
|
|
|
def search(self, pattern: str, path: Optional[str] = None) -> str:
|
|
args = ["grep", pattern]
|
|
if path:
|
|
args.append(path)
|
|
return self._run(args)
|
|
|
|
def shell(self, command: str) -> str:
|
|
return self._run(["-c", command])
|
|
|
|
def gain(self) -> dict:
|
|
output = self._run(["gain", "--json"])
|
|
try:
|
|
return json.loads(output)
|
|
except json.JSONDecodeError:
|
|
return {"raw": output}
|
|
|
|
def benchmark(self, path: Optional[str] = None, json_output: bool = True) -> dict:
|
|
args = ["benchmark", "eval"]
|
|
if path:
|
|
args.append(path)
|
|
if json_output:
|
|
args.append("--json")
|
|
output = self._run(args)
|
|
try:
|
|
return json.loads(output)
|
|
except json.JSONDecodeError:
|
|
return {"raw": output}
|
|
|
|
def _run(self, args: list[str]) -> str:
|
|
try:
|
|
result = subprocess.run(
|
|
[self.binary] + args,
|
|
capture_output=True,
|
|
text=True,
|
|
cwd=self.project_root,
|
|
timeout=30,
|
|
)
|
|
return result.stdout.strip()
|
|
except FileNotFoundError:
|
|
raise RuntimeError(
|
|
f"lean-ctx binary not found at '{self.binary}'. "
|
|
"Install: curl -fsSL https://leanctx.com/install.sh | sh"
|
|
)
|
|
except subprocess.TimeoutExpired:
|
|
raise RuntimeError("lean-ctx command timed out after 30s")
|