Files
hermes-agent/pm/artifact_mirror.py
teknium1 a31e618e70 fix(pm): download npm-hosted tools through the user's npm registry
pm/lock.json and the Npm/AgentBrowser templates record registry.npmjs.org, and
pinned_source handed that URL straight to the downloader, so ~/.npmrc /
npm_config_registry were ignored and closed networks could not provision npm or
agent-browser. pinned_source now routes public-npm URLs through the configured
registry (npm's own precedence: npm_config_registry, then the user npmrc); the
lock's SHA256 still verifies the bytes and progress keeps the lockfile URL.
npm_dist_tags reads from the same registry.

The E2E cell test_npm_registry_mirror_serves_pm_npm_download drops its gate.

Co-authored-by: funky-xamarin <30426178+Wenfengcheng@users.noreply.github.com>
2026-09-28 02:00:41 -07:00

33 lines
1.1 KiB
Python

"""Public, content-addressed copies of reviewed binary inputs."""
from __future__ import annotations
import json
import os
from pathlib import Path
import re
from pm.downloader import Source
from pm.index_config import npm_registry_url
_LAYOUT = json.loads(Path(__file__).with_name("artifact-mirror.json").read_text(encoding="utf-8-sig"))
KEY_PREFIX = _LAYOUT["prefix"]
PUBLIC_PREFIX = _LAYOUT["origin"] + "/" + KEY_PREFIX
def object_key(sha256: str) -> str:
if not isinstance(sha256, str) or not re.fullmatch(r"[a-f0-9]{64}", sha256):
raise ValueError("A pinned input requires a full lowercase SHA256")
return KEY_PREFIX + sha256
def mirror_url(sha256: str) -> str:
object_key(sha256)
return PUBLIC_PREFIX + sha256
def pinned_source(url: str, dest: Path, sha256: str) -> Source:
archive = mirror_url(sha256)
# The lock records registry.npmjs.org; a user's npm mirror serves the same pinned bytes (#123132).
url = npm_registry_url(url, os.environ)
return Source(url, dest, sha256, fallbacks=() if url == archive else (archive,))