mirror of
https://github.com/superdesigndev/treg.git
synced 2026-10-02 03:24:35 +08:00
fix(install): Codex cleanup drops hand-wired twins; pip3 fallback explains an out-of-range Python
Two more things the same incident showed. The user's ~/.codex/config.toml held a second table, `treg-to_mcp`, pointing at our MCP url with the token in the env-var-NAME field; the installer now removes any `mcp_servers.*` table whose url is ours before writing the one correct table, so Codex is not left showing a dead server beside the working one. install.sh's pip3 fallback ran on a machine whose pip3 belonged to a Python outside the supported range and died on pip's "Ignored the following versions" wall. pip cannot pick another interpreter, so the script now says which Python pip3 belongs to and prints the uv one-liner instead. Fragment: docs/context/interface/landing-sandbox.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
0727d1d32b
commit
e6b4e219be
@@ -144,7 +144,10 @@ files a skill folder is — `SKILL.md` (agent recipe: call the treg proxy, key i
|
||||
supported interpreter range (`PYREQ`, kept in sync with `requires-python` in `pyproject.toml`): without
|
||||
it uv resolves against its *default* interpreter — its own managed Python first — and a machine whose
|
||||
default falls outside the range fails resolution instead of picking (or auto-downloading) a compatible
|
||||
one. It also installs the official
|
||||
one. The pip3 path cannot pick an interpreter at all, so it checks `pip3 --version` against the range
|
||||
first and, outside it, prints which Python pip3 belongs to plus the uv one-liner instead of letting
|
||||
pip fail with its "Ignored the following versions" wall (a real user hit exactly that). It also
|
||||
installs the official
|
||||
**tools-registry skill** into every detected agent via `treg skill bootstrap` (Claude Code, Cursor, Codex,
|
||||
Gemini, Copilot, OpenCode, Windsurf …), falling back on older CLIs to a Claude-only drop that curls
|
||||
`{BASE}/skill.md` into `~/.claude/skills/treg`. Because the package is public on PyPI,
|
||||
|
||||
+13
-3
@@ -155,12 +155,22 @@ def _write_toml_agent(meta: dict, name: str, url: str, token: str) -> tuple[str,
|
||||
old = path.read_text() if path.exists() else ""
|
||||
tomllib.loads(old) # a config Codex can't read is not ours to edit
|
||||
header = f"[mcp_servers.{name}]"
|
||||
kept = re.sub(rf"(?ms)^\[mcp_servers\.{re.escape(name)}\]\n.*?(?=^\[|\Z)", "", old).rstrip()
|
||||
# Cut our table, and any other table pointing at this same MCP url under another name — an
|
||||
# agent wiring Codex by hand tends to leave a `treg-to_mcp` twin with the token in the wrong
|
||||
# field, which Codex then shows as a dead server beside the working one.
|
||||
stale = {name} | {k for k, v in tomllib.loads(old).get("mcp_servers", {}).items()
|
||||
if isinstance(v, dict) and v.get("url") == url}
|
||||
kept = old
|
||||
for k in stale:
|
||||
kept = re.sub(rf"(?ms)^\[mcp_servers\.{re.escape(k)}\]\n.*?(?=^\[|\Z)", "", kept)
|
||||
kept = kept.rstrip()
|
||||
block = (f"{header}\nurl = {json.dumps(url)}\n"
|
||||
f"http_headers = {{ \"Authorization\" = {json.dumps('Bearer ' + token)} }}\n")
|
||||
new = (kept + "\n\n" if kept else "") + block
|
||||
entry = tomllib.loads(new)["mcp_servers"][name]
|
||||
if entry != {"url": url, "http_headers": {"Authorization": f"Bearer {token}"}}:
|
||||
servers = tomllib.loads(new)["mcp_servers"]
|
||||
if (servers[name] != {"url": url, "http_headers": {"Authorization": f"Bearer {token}"}}
|
||||
or any(k != name and isinstance(v, dict) and v.get("url") == url
|
||||
for k, v in servers.items())):
|
||||
return "error", f"{path}: a sub-table of {header} survived; edit it by hand"
|
||||
_write_private(path, new)
|
||||
return "ok", str(path)
|
||||
|
||||
@@ -52,6 +52,14 @@ elif command -v pipx >/dev/null 2>&1; then
|
||||
pipx install --force "$SRC"
|
||||
fi
|
||||
elif command -v pip3 >/dev/null 2>&1; then
|
||||
# pip can only install into the interpreter it belongs to. Outside PYREQ it prints a wall of
|
||||
# "Ignored the following versions" and dies — say what is wrong and how to fix it instead.
|
||||
if ! pip3 --version 2>/dev/null | grep -qE '\(python 3\.1[23]\)'; then
|
||||
echo "pip3 belongs to $(pip3 --version 2>/dev/null | sed -n 's/.*(python \([0-9.]*\)).*/Python \1/p'), but treg needs Python 3.12 or 3.13." >&2
|
||||
echo "Easiest fix — install uv (it fetches a matching Python by itself), then rerun this command:" >&2
|
||||
echo " curl -LsSf https://astral.sh/uv/install.sh | sh" >&2
|
||||
exit 1
|
||||
fi
|
||||
pip3 install --user --upgrade "$SRC"
|
||||
else
|
||||
echo "Need Python 3.12 or 3.13 and one of: uv (recommended), pipx, or pip3." >&2
|
||||
|
||||
@@ -403,6 +403,8 @@ def test_codex_replaces_a_stale_env_var_table_and_keeps_the_rest(tmp_path, monke
|
||||
import tomllib
|
||||
before = ('model = "gpt-5"\n\n[mcp_servers.figma]\nurl = "https://mcp.figma.com/mcp"\n\n'
|
||||
'[mcp_servers.treg]\nurl = "https://treg.to/mcp/"\nbearer_token_env_var = "TREG_TOKEN"\n\n'
|
||||
# a hand-wired twin under another name, token in the env-var-NAME field (seen in the wild)
|
||||
'[mcp_servers.treg-to_mcp]\nurl = "https://treg.to/mcp/"\nbearer_token_env_var = "eyJ.x"\n\n'
|
||||
'[mcp_servers.node_repl]\ncommand = "node_repl"\n\n[mcp_servers.node_repl.env]\nX = "1"\n')
|
||||
out, cfg = _codex_install(tmp_path, monkeypatch, existing=before, token="NEWKEY")
|
||||
assert out["results"][0][1] == "ok", out
|
||||
@@ -413,6 +415,7 @@ def test_codex_replaces_a_stale_env_var_table_and_keeps_the_rest(tmp_path, monke
|
||||
assert data["mcp_servers"]["treg"] == {
|
||||
"url": "https://treg.to/mcp/", "http_headers": {"Authorization": "Bearer NEWKEY"}}
|
||||
assert cfg.read_text().count("[mcp_servers.treg]") == 1
|
||||
assert "treg-to_mcp" not in cfg.read_text() and "eyJ.x" not in cfg.read_text()
|
||||
# idempotent
|
||||
mcp_install.install_mcp(base_url="https://treg.to", token="NEWKEY", only=["codex"])
|
||||
assert cfg.read_text().count("[mcp_servers.treg]") == 1
|
||||
|
||||
Reference in New Issue
Block a user