harness-evolver 3.0.2 → 3.0.3

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "harness-evolver",
3
- "version": "3.0.2",
3
+ "version": "3.0.3",
4
4
  "description": "LangSmith-native autonomous agent optimization for Claude Code",
5
5
  "author": "Raphael Valdetaro",
6
6
  "license": "MIT",
@@ -11,8 +11,31 @@ Set up the Harness Evolver v3 in a project. Explores the codebase, configures La
11
11
 
12
12
  ## Prerequisites
13
13
 
14
- - `LANGSMITH_API_KEY` must be set. If not: "Set your LangSmith API key: `export LANGSMITH_API_KEY=lsv2_pt_...`"
15
- - Python 3.10+ with `langsmith` and `openevals` packages. If missing:
14
+ Check for LangSmith API key — it can be in the environment, the credentials file, or .env:
15
+
16
+ ```bash
17
+ python3 -c "
18
+ import os, platform
19
+ key = os.environ.get('LANGSMITH_API_KEY', '')
20
+ if not key:
21
+ creds = os.path.expanduser('~/Library/Application Support/langsmith-cli/credentials') if platform.system() == 'Darwin' else os.path.expanduser('~/.config/langsmith-cli/credentials')
22
+ if os.path.exists(creds):
23
+ for line in open(creds):
24
+ if line.strip().startswith('LANGSMITH_API_KEY='):
25
+ key = line.strip().split('=',1)[1].strip()
26
+ if not key and os.path.exists('.env'):
27
+ for line in open('.env'):
28
+ if line.strip().startswith('LANGSMITH_API_KEY=') and not line.strip().startswith('#'):
29
+ key = line.strip().split('=',1)[1].strip().strip('\"').strip(\"'\")
30
+ print('OK' if key else 'MISSING')
31
+ "
32
+ ```
33
+
34
+ If `MISSING`: "Set your LangSmith API key: `export LANGSMITH_API_KEY=lsv2_pt_...` or run `npx harness-evolver@latest` to configure."
35
+
36
+ The tools auto-load the key from the credentials file, but the env var takes precedence.
37
+
38
+ Python 3.10+ with `langsmith` and `openevals` packages must be installed:
16
39
 
17
40
  ```bash
18
41
  pip install langsmith openevals 2>/dev/null || uv pip install langsmith openevals
@@ -21,9 +21,33 @@ Requires: pip install langsmith
21
21
  import argparse
22
22
  import json
23
23
  import os
24
+ import platform
24
25
  import sys
25
26
 
26
27
 
28
+ def ensure_langsmith_api_key():
29
+ """Load LANGSMITH_API_KEY from credentials file if not in env."""
30
+ if os.environ.get("LANGSMITH_API_KEY"):
31
+ return True
32
+ if platform.system() == "Darwin":
33
+ creds_path = os.path.expanduser("~/Library/Application Support/langsmith-cli/credentials")
34
+ else:
35
+ creds_path = os.path.expanduser("~/.config/langsmith-cli/credentials")
36
+ if os.path.exists(creds_path):
37
+ try:
38
+ with open(creds_path) as f:
39
+ for line in f:
40
+ line = line.strip()
41
+ if line.startswith("LANGSMITH_API_KEY="):
42
+ key = line.split("=", 1)[1].strip()
43
+ if key:
44
+ os.environ["LANGSMITH_API_KEY"] = key
45
+ return True
46
+ except OSError:
47
+ pass
48
+ return False
49
+
50
+
27
51
  def read_experiment(client, experiment_name):
28
52
  """Read results from a single LangSmith experiment."""
29
53
  try:
@@ -184,6 +208,7 @@ def main():
184
208
  parser.add_argument("--output", default=None, help="Output JSON path")
185
209
  parser.add_argument("--format", default="json", choices=["json", "markdown"], help="Output format")
186
210
  args = parser.parse_args()
211
+ ensure_langsmith_api_key()
187
212
 
188
213
  from langsmith import Client
189
214
  client = Client()
package/tools/run_eval.py CHANGED
@@ -17,11 +17,47 @@ Requires: pip install langsmith openevals
17
17
  import argparse
18
18
  import json
19
19
  import os
20
+ import platform
20
21
  import subprocess
21
22
  import sys
22
23
  import tempfile
23
24
 
24
25
 
26
+ def ensure_langsmith_api_key():
27
+ """Load LANGSMITH_API_KEY from credentials file if not in env."""
28
+ if os.environ.get("LANGSMITH_API_KEY"):
29
+ return True
30
+ if platform.system() == "Darwin":
31
+ creds_path = os.path.expanduser("~/Library/Application Support/langsmith-cli/credentials")
32
+ else:
33
+ creds_path = os.path.expanduser("~/.config/langsmith-cli/credentials")
34
+ if os.path.exists(creds_path):
35
+ try:
36
+ with open(creds_path) as f:
37
+ for line in f:
38
+ line = line.strip()
39
+ if line.startswith("LANGSMITH_API_KEY="):
40
+ key = line.split("=", 1)[1].strip()
41
+ if key:
42
+ os.environ["LANGSMITH_API_KEY"] = key
43
+ return True
44
+ except OSError:
45
+ pass
46
+ if os.path.exists(".env"):
47
+ try:
48
+ with open(".env") as f:
49
+ for line in f:
50
+ line = line.strip()
51
+ if line.startswith("LANGSMITH_API_KEY=") and not line.startswith("#"):
52
+ key = line.split("=", 1)[1].strip().strip("'\"")
53
+ if key:
54
+ os.environ["LANGSMITH_API_KEY"] = key
55
+ return True
56
+ except OSError:
57
+ pass
58
+ return False
59
+
60
+
25
61
  def make_target(entry_point, cwd):
26
62
  """Create a target function that runs the agent from a specific directory."""
27
63
  def target(inputs):
@@ -132,6 +168,7 @@ def main():
132
168
  config = json.load(f)
133
169
 
134
170
  os.environ["EVAL_TASK_TIMEOUT"] = str(args.timeout)
171
+ ensure_langsmith_api_key()
135
172
 
136
173
  from langsmith import Client
137
174
  client = Client()
package/tools/setup.py CHANGED
@@ -25,12 +25,58 @@ Requires: pip install langsmith openevals
25
25
  import argparse
26
26
  import json
27
27
  import os
28
+ import platform
28
29
  import subprocess
29
30
  import sys
30
31
  import tempfile
31
32
  from datetime import datetime, timezone
32
33
 
33
34
 
35
+ def ensure_langsmith_api_key():
36
+ """Load LANGSMITH_API_KEY from credentials file if not in env.
37
+
38
+ The installer saves the key to the langsmith-cli credentials file,
39
+ but the SDK only reads the env var. This bridges the gap.
40
+ """
41
+ if os.environ.get("LANGSMITH_API_KEY"):
42
+ return True
43
+
44
+ # Platform-specific credentials path (matches langsmith-cli)
45
+ if platform.system() == "Darwin":
46
+ creds_path = os.path.expanduser("~/Library/Application Support/langsmith-cli/credentials")
47
+ else:
48
+ creds_path = os.path.expanduser("~/.config/langsmith-cli/credentials")
49
+
50
+ if os.path.exists(creds_path):
51
+ try:
52
+ with open(creds_path) as f:
53
+ for line in f:
54
+ line = line.strip()
55
+ if line.startswith("LANGSMITH_API_KEY="):
56
+ key = line.split("=", 1)[1].strip()
57
+ if key:
58
+ os.environ["LANGSMITH_API_KEY"] = key
59
+ return True
60
+ except OSError:
61
+ pass
62
+
63
+ # Also check .env in current directory
64
+ if os.path.exists(".env"):
65
+ try:
66
+ with open(".env") as f:
67
+ for line in f:
68
+ line = line.strip()
69
+ if line.startswith("LANGSMITH_API_KEY=") and not line.startswith("#"):
70
+ key = line.split("=", 1)[1].strip().strip("'\"")
71
+ if key:
72
+ os.environ["LANGSMITH_API_KEY"] = key
73
+ return True
74
+ except OSError:
75
+ pass
76
+
77
+ return False
78
+
79
+
34
80
  def check_dependencies():
35
81
  """Verify langsmith and openevals are installed."""
36
82
  missing = []
@@ -294,6 +340,12 @@ def main():
294
340
  print(f"Install with: pip install {' '.join(missing)}", file=sys.stderr)
295
341
  sys.exit(1)
296
342
 
343
+ # Load API key from credentials file if not in env
344
+ if not ensure_langsmith_api_key():
345
+ print("LANGSMITH_API_KEY not found in environment, credentials file, or .env", file=sys.stderr)
346
+ print("Set it with: export LANGSMITH_API_KEY=lsv2_pt_...", file=sys.stderr)
347
+ sys.exit(1)
348
+
297
349
  from langsmith import Client
298
350
  client = Client()
299
351