evo-cli 0.10.2__tar.gz → 0.10.3__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.
Files changed (45) hide show
  1. {evo_cli-0.10.2 → evo_cli-0.10.3}/PKG-INFO +1 -1
  2. evo_cli-0.10.3/evo_cli/VERSION +1 -0
  3. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/opencode.py +62 -6
  4. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/mcp_registry.py +5 -5
  5. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli.egg-info/PKG-INFO +1 -1
  6. {evo_cli-0.10.2 → evo_cli-0.10.3}/tests/test_opencode.py +26 -3
  7. evo_cli-0.10.2/evo_cli/VERSION +0 -1
  8. {evo_cli-0.10.2 → evo_cli-0.10.3}/Containerfile +0 -0
  9. {evo_cli-0.10.2 → evo_cli-0.10.3}/HISTORY.md +0 -0
  10. {evo_cli-0.10.2 → evo_cli-0.10.3}/LICENSE +0 -0
  11. {evo_cli-0.10.2 → evo_cli-0.10.3}/MANIFEST.in +0 -0
  12. {evo_cli-0.10.2 → evo_cli-0.10.3}/README.md +0 -0
  13. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/__init__.py +0 -0
  14. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/__main__.py +0 -0
  15. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/base.py +0 -0
  16. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/cli.py +0 -0
  17. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/__init__.py +0 -0
  18. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/cloudflare.py +0 -0
  19. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/fix_claude.py +0 -0
  20. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/gdrive.py +0 -0
  21. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/localproxy.py +0 -0
  22. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/mcp.py +0 -0
  23. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/miniconda.py +0 -0
  24. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/netcheck.py +0 -0
  25. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/plantuml.py +0 -0
  26. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/site2s.py +0 -0
  27. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/ssh.py +0 -0
  28. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/sysmon.py +0 -0
  29. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/commands/wifi.py +0 -0
  30. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli/console.py +0 -0
  31. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli.egg-info/SOURCES.txt +0 -0
  32. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli.egg-info/dependency_links.txt +0 -0
  33. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli.egg-info/entry_points.txt +0 -0
  34. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli.egg-info/requires.txt +0 -0
  35. {evo_cli-0.10.2 → evo_cli-0.10.3}/evo_cli.egg-info/top_level.txt +0 -0
  36. {evo_cli-0.10.2 → evo_cli-0.10.3}/pyproject.toml +0 -0
  37. {evo_cli-0.10.2 → evo_cli-0.10.3}/setup.cfg +0 -0
  38. {evo_cli-0.10.2 → evo_cli-0.10.3}/tests/__init__.py +0 -0
  39. {evo_cli-0.10.2 → evo_cli-0.10.3}/tests/test_cli.py +0 -0
  40. {evo_cli-0.10.2 → evo_cli-0.10.3}/tests/test_console.py +0 -0
  41. {evo_cli-0.10.2 → evo_cli-0.10.3}/tests/test_fix_claude.py +0 -0
  42. {evo_cli-0.10.2 → evo_cli-0.10.3}/tests/test_mcp.py +0 -0
  43. {evo_cli-0.10.2 → evo_cli-0.10.3}/tests/test_plantuml.py +0 -0
  44. {evo_cli-0.10.2 → evo_cli-0.10.3}/tests/test_sysmon.py +0 -0
  45. {evo_cli-0.10.2 → evo_cli-0.10.3}/tests/test_wifi.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evo_cli
3
- Version: 0.10.2
3
+ Version: 0.10.3
4
4
  Summary: Evolution CLI - a developer toolbox for setting up dev machines
5
5
  Author: maycuatroi
6
6
  Project-URL: Homepage, https://github.com/maycuatroi/evo-cli
@@ -0,0 +1 @@
1
+ 0.10.3
@@ -1,6 +1,7 @@
1
1
  """Install and configure OpenCode with common MCP servers."""
2
2
 
3
3
  import json
4
+ import os
4
5
  import platform
5
6
  import shutil
6
7
  import subprocess
@@ -22,7 +23,13 @@ EPILOG = Text.from_markup(
22
23
 
23
24
  # Servers bootstrapped by `evo setup opencode`, pulled from the shared library
24
25
  # (evo_cli/mcp_registry.py). Add more servers anytime with `evo mcp add <name>`.
25
- DEFAULT_MCP_SERVERS = opencode_servers("google-search", "playwright")
26
+ # Web search is handled by OpenCode's native Exa-backed `websearch` tool (enabled
27
+ # via OPENCODE_ENABLE_EXA, no API key), not a scraping MCP server.
28
+ DEFAULT_MCP_SERVERS = opencode_servers("playwright")
29
+
30
+ # OpenCode's built-in `websearch` tool only activates for the OpenCode provider or
31
+ # when this env var is truthy, so custom providers need it set explicitly.
32
+ EXA_ENV_VAR = "OPENCODE_ENABLE_EXA"
26
33
 
27
34
 
28
35
  def _local_mcp_commands():
@@ -323,6 +330,51 @@ def verify_mcp_servers():
323
330
  warning(f"Could not verify MCP server [accent]{name}[/accent]: {exc}")
324
331
 
325
332
 
333
+ def get_shell_rc_path():
334
+ """Return the shell rc file to wire env vars into, based on the active shell."""
335
+ shell = os.environ.get("SHELL", "")
336
+ home = Path.home()
337
+ if shell.endswith("zsh"):
338
+ return home / ".zshrc"
339
+ if shell.endswith("bash"):
340
+ # macOS login shells read .bash_profile; Linux reads .bashrc.
341
+ return home / (".bash_profile" if platform.system() == "Darwin" else ".bashrc")
342
+ if shell.endswith("fish"):
343
+ return home / ".config" / "fish" / "config.fish"
344
+ return home / ".profile"
345
+
346
+
347
+ def enable_exa_websearch():
348
+ """Enable OpenCode's built-in Exa web search via the OPENCODE_ENABLE_EXA env var.
349
+
350
+ OpenCode ships a native ``websearch`` tool backed by Exa's hosted MCP service
351
+ (no API key needed), but it is only active when using the OpenCode provider or
352
+ when ``OPENCODE_ENABLE_EXA`` is truthy. Custom providers therefore need the env
353
+ var, so wire it into the shell rc idempotently.
354
+ """
355
+ step("Enabling Exa web search")
356
+ if is_windows():
357
+ info(f"Set the {EXA_ENV_VAR}=1 environment variable to enable web search.")
358
+ info("PowerShell: [accent]setx OPENCODE_ENABLE_EXA 1[/accent]")
359
+ return
360
+
361
+ rc_path = get_shell_rc_path()
362
+ if rc_path.exists() and EXA_ENV_VAR in rc_path.read_text(encoding="utf-8"):
363
+ info(f"{EXA_ENV_VAR} already set in [accent]{rc_path}[/accent]; skipping")
364
+ success("Exa web search already enabled")
365
+ return
366
+
367
+ rc_path.parent.mkdir(parents=True, exist_ok=True)
368
+ block = (
369
+ "\n# opencode web search (Exa native, no API key) - added by evo setup opencode\n"
370
+ f"export {EXA_ENV_VAR}=1\n"
371
+ )
372
+ with rc_path.open("a", encoding="utf-8") as fh:
373
+ fh.write(block)
374
+ success(f"Enabled Exa web search in [accent]{rc_path}[/accent]")
375
+ info(f"Run [accent]source {rc_path}[/accent] or open a new terminal to apply.")
376
+
377
+
326
378
  def run_setup_opencode(global_only, project, skip_install=False):
327
379
  step("evo setup opencode")
328
380
 
@@ -334,6 +386,7 @@ def run_setup_opencode(global_only, project, skip_install=False):
334
386
 
335
387
  if not skip_install:
336
388
  install_opencode(npm_cmd)
389
+ enable_exa_websearch()
337
390
  install_mcp_servers()
338
391
  install_playwright_browsers()
339
392
 
@@ -357,8 +410,9 @@ def run_setup_opencode(global_only, project, skip_install=False):
357
410
  )
358
411
  console.print(
359
412
  Panel(
360
- f"OpenCode configured with google-search and playwright MCP servers.\n\n{paths_text}\n\n"
361
- f"{opencode_note} Restart OpenCode to load the new MCP tools.",
413
+ "OpenCode web search enabled via Exa (native, no API key); "
414
+ f"playwright MCP server configured for browser automation.\n\n{paths_text}\n\n"
415
+ f"{opencode_note} Open a new terminal (or `source` your shell rc), then restart OpenCode.",
362
416
  title="setup opencode complete",
363
417
  border_style="success",
364
418
  expand=False,
@@ -387,9 +441,11 @@ def setup_opencode(global_only, skip_install, project):
387
441
 
388
442
  This command bootstraps a fresh machine with the same OpenCode + MCP setup
389
443
  used across devices. It installs the OpenCode CLI (via npm, unless
390
- --skip-install) and the google-search and playwright MCP servers, downloads
391
- the Playwright Chromium browser, and writes both global
392
- (~/.config/opencode/opencode.jsonc) and project-level (opencode.json) configs.
444
+ --skip-install), enables OpenCode's native Exa-backed web search (via the
445
+ OPENCODE_ENABLE_EXA env var, no API key required), installs the playwright MCP
446
+ server for browser automation, downloads the Playwright Chromium browser, and
447
+ writes both global (~/.config/opencode/opencode.jsonc) and project-level
448
+ (opencode.json) configs.
393
449
 
394
450
  No credentials are bundled; only public MCP server references are added.
395
451
  """
@@ -22,12 +22,12 @@ MCP_REGISTRY = {
22
22
  "homepage": "https://github.com/microsoft/playwright-mcp",
23
23
  "description": "Playwright (Microsoft) - drive a real browser: navigate, click, snapshot.",
24
24
  },
25
- "google-search": {
26
- "transport": "stdio",
27
- "command": ["npx", "-y", "@mcp-server/google-search-mcp@latest"],
25
+ "exa": {
26
+ "transport": "http",
27
+ "url": "https://mcp.exa.ai/mcp",
28
28
  "category": "search",
29
- "homepage": "https://www.npmjs.com/package/@mcp-server/google-search-mcp",
30
- "description": "Google Search - run web searches and fetch result pages.",
29
+ "homepage": "https://exa.ai/docs/reference/exa-mcp",
30
+ "description": "Exa - AI web search (hosted MCP, free tier, no API key).",
31
31
  },
32
32
  "sequential-thinking": {
33
33
  "transport": "stdio",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: evo_cli
3
- Version: 0.10.2
3
+ Version: 0.10.3
4
4
  Summary: Evolution CLI - a developer toolbox for setting up dev machines
5
5
  Author: maycuatroi
6
6
  Project-URL: Homepage, https://github.com/maycuatroi/evo-cli
@@ -7,8 +7,10 @@ from click.testing import CliRunner
7
7
  from evo_cli.cli import cli
8
8
  from evo_cli.commands.opencode import (
9
9
  DEFAULT_MCP_SERVERS,
10
+ EXA_ENV_VAR,
10
11
  configure_opencode_global,
11
12
  configure_opencode_project,
13
+ enable_exa_websearch,
12
14
  install_mcp_servers,
13
15
  install_opencode,
14
16
  load_jsonc,
@@ -55,7 +57,6 @@ def test_merge_mcp_config_preserves_existing():
55
57
  existing = {"mcp": {"playwright": {"enabled": False}}}
56
58
  merged = merge_mcp_config(existing, DEFAULT_MCP_SERVERS)
57
59
  assert merged["mcp"]["playwright"]["enabled"] is False
58
- assert merged["mcp"]["google-search"]["enabled"] is True
59
60
 
60
61
 
61
62
  def test_configure_opencode_global(tmp_path, monkeypatch):
@@ -66,14 +67,33 @@ def test_configure_opencode_global(tmp_path, monkeypatch):
66
67
  path = configure_opencode_global()
67
68
  data = load_jsonc(path)
68
69
  assert "mcp" in data
69
- assert set(data["mcp"].keys()) == {"google-search", "playwright"}
70
+ assert set(data["mcp"].keys()) == {"playwright"}
70
71
 
71
72
 
72
73
  def test_configure_opencode_project(tmp_path):
73
74
  path = configure_opencode_project(tmp_path)
74
75
  data = load_jsonc(path)
75
76
  assert "mcp" in data
76
- assert set(data["mcp"].keys()) == {"google-search", "playwright"}
77
+ assert set(data["mcp"].keys()) == {"playwright"}
78
+
79
+
80
+ def test_enable_exa_websearch_writes_export(tmp_path, monkeypatch):
81
+ rc = tmp_path / ".zshrc"
82
+ monkeypatch.setattr("evo_cli.commands.opencode.is_windows", lambda: False)
83
+ monkeypatch.setattr("evo_cli.commands.opencode.get_shell_rc_path", lambda: rc)
84
+
85
+ enable_exa_websearch()
86
+ assert f"export {EXA_ENV_VAR}=1" in rc.read_text()
87
+
88
+
89
+ def test_enable_exa_websearch_is_idempotent(tmp_path, monkeypatch):
90
+ rc = tmp_path / ".zshrc"
91
+ monkeypatch.setattr("evo_cli.commands.opencode.is_windows", lambda: False)
92
+ monkeypatch.setattr("evo_cli.commands.opencode.get_shell_rc_path", lambda: rc)
93
+
94
+ enable_exa_websearch()
95
+ enable_exa_websearch()
96
+ assert rc.read_text().count(f"export {EXA_ENV_VAR}=1") == 1
77
97
 
78
98
 
79
99
  def test_install_mcp_servers_detaches_stdin_and_sets_timeout(monkeypatch):
@@ -141,6 +161,7 @@ def test_setup_opencode_skip_install(runner, tmp_path, monkeypatch):
141
161
  monkeypatch.setattr("evo_cli.commands.opencode.install_mcp_servers", lambda: None)
142
162
  monkeypatch.setattr("evo_cli.commands.opencode.install_playwright_browsers", lambda: None)
143
163
  monkeypatch.setattr("evo_cli.commands.opencode.verify_mcp_servers", lambda: None)
164
+ monkeypatch.setattr("evo_cli.commands.opencode.enable_exa_websearch", lambda: None)
144
165
 
145
166
  result = runner.invoke(cli, ["setup", "opencode", "--global-only", "--skip-install"])
146
167
  assert result.exit_code == 0
@@ -159,6 +180,7 @@ def test_setup_opencode_writes_global_and_project(runner, tmp_path, monkeypatch)
159
180
  monkeypatch.setattr("evo_cli.commands.opencode.install_mcp_servers", lambda: None)
160
181
  monkeypatch.setattr("evo_cli.commands.opencode.install_playwright_browsers", lambda: None)
161
182
  monkeypatch.setattr("evo_cli.commands.opencode.verify_mcp_servers", lambda: None)
183
+ monkeypatch.setattr("evo_cli.commands.opencode.enable_exa_websearch", lambda: None)
162
184
 
163
185
  result = runner.invoke(cli, ["setup", "opencode", "--project", str(tmp_path)])
164
186
  assert result.exit_code == 0
@@ -180,6 +202,7 @@ def test_setup_opencode_global_only(runner, tmp_path, monkeypatch):
180
202
  monkeypatch.setattr("evo_cli.commands.opencode.install_mcp_servers", lambda: None)
181
203
  monkeypatch.setattr("evo_cli.commands.opencode.install_playwright_browsers", lambda: None)
182
204
  monkeypatch.setattr("evo_cli.commands.opencode.verify_mcp_servers", lambda: None)
205
+ monkeypatch.setattr("evo_cli.commands.opencode.enable_exa_websearch", lambda: None)
183
206
 
184
207
  project = tmp_path / "project"
185
208
  project.mkdir()
@@ -1 +0,0 @@
1
- 0.10.2
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