git: 8efc9c28d8b0 - main - misc/hermes-agent: Update to 0.18.0

From: Olivier Cochard <olivier_at_FreeBSD.org>
Date: Sat, 05 Sep 2026 12:18:08 UTC
The branch main has been updated by olivier:

URL: https://cgit.FreeBSD.org/ports/commit/?id=8efc9c28d8b0dea0e6f1fd0e8b2110eccc7633e4

commit 8efc9c28d8b0dea0e6f1fd0e8b2110eccc7633e4
Author:     Olivier Cochard <olivier@FreeBSD.org>
AuthorDate: 2026-09-05 12:11:31 +0000
Commit:     Olivier Cochard <olivier@FreeBSD.org>
CommitDate: 2026-09-05 12:15:39 +0000

    misc/hermes-agent: Update to 0.18.0
---
 misc/hermes-agent/Makefile                         | 38 +++++++++--
 misc/hermes-agent/distinfo                         | 10 +--
 .../files/patch-agent_anthropic__adapter.py        | 75 ++++++++++++++++++++++
 .../files/patch-agent_azure__identity__adapter.py  | 44 +++++++++++++
 .../hermes-agent/files/patch-agent_skill__utils.py |  4 +-
 .../files/patch-hermes__cli_config__defaults.py    |  4 +-
 .../files/patch-hermes__cli_gateway.py             | 28 ++++----
 misc/hermes-agent/files/patch-hermes__cli_main.py  |  4 +-
 misc/hermes-agent/files/patch-hermes__cli_setup.py |  8 +--
 .../files/patch-hermes__cli_uninstall.py           |  4 +-
 misc/hermes-agent/files/patch-tools_lazy__deps.py  |  4 +-
 11 files changed, 183 insertions(+), 40 deletions(-)

diff --git a/misc/hermes-agent/Makefile b/misc/hermes-agent/Makefile
index e7bc2d8babed..98d426f16197 100644
--- a/misc/hermes-agent/Makefile
+++ b/misc/hermes-agent/Makefile
@@ -1,5 +1,5 @@
 PORTNAME=	hermes-agent
-PORTVERSION=	0.17.0
+PORTVERSION=	0.18.0
 CATEGORIES=	misc python
 MASTER_SITES+=	LOCAL/olivier:webdist
 DISTFILES+=	${PORTNAME}-web-dist-${PORTVERSION}${EXTRACT_SUFX}:webdist
@@ -11,8 +11,20 @@ WWW=		https://github.com/NousResearch/hermes-agent
 LICENSE=	MIT
 LICENSE_FILE=	${WRKSRC}/LICENSE
 
+# Upstream splits deps into a small `dependencies` core plus lazy-installed
+# extras (tools/lazy_deps.py).  The port ships the provider-specific extras
+# (anthropic, edge-tts, exa-py, fal-client, firecrawl-py, parallel-web) as
+# hard RUN_DEPENDS because patch-tools_lazy__deps.py turns lazy installs off
+# on FreeBSD -- pkg owns site-packages, so there is no runtime pip fallback.
+#
+# firecrawl-anydoc (upstream core since v2026.8.31) is deliberately NOT
+# listed: no port exists, and tools/read_extract.py guards the import and
+# emits a teaching error naming the pip fallback, so the legacy-Office /
+# ODF / EPUB read_file paths degrade instead of breaking the install.
 RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}anthropic>=0.86.0:misc/py-anthropic@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}certifi>=2026.5.20:security/py-certifi@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}croniter>=6.0.0:sysutils/py-croniter@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}cryptography>=50.0.0:security/py-cryptography@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}edge-tts>=7.2.7:audio/py-edge-tts@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}exa-py>=2.10.2:www/py-exa-py@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}fal-client>=0.13.1:misc/py-fal-client@${PY_FLAVOR} \
@@ -21,27 +33,35 @@ RUN_DEPENDS=	${PYTHON_PKGNAMEPREFIX}anthropic>=0.86.0:misc/py-anthropic@${PY_FLA
 		${PYTHON_PKGNAMEPREFIX}firecrawl-py>=4.17.0:www/py-firecrawl-py@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}httpx>=0.28.1:www/py-httpx@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}Jinja2>=3.1.6:devel/py-Jinja2@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}markdown>=3.10.2:textproc/py-markdown@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}openai>=2.24.0:misc/py-openai@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}packaging>=26.0:devel/py-packaging@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}parallel-web>=0.4.2:www/py-parallel-web@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}pathspec>=1.1.1:devel/py-pathspec@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}pillow>=11.3.0:graphics/py-pillow@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}prompt-toolkit>=3.0.52:devel/py-prompt-toolkit@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}psutil>=7.2.2:sysutils/py-psutil@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}pydantic2>=2.12.5:devel/py-pydantic2@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}pyjwt>=2.12.1:www/py-pyjwt@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}pydantic2>=2.13.4:devel/py-pydantic2@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}pyjwt>=2.13.0:www/py-pyjwt@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}pysocks>0:net/py-pysocks@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}python-dotenv>=1.2.1:www/py-python-dotenv@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}python-dotenv>=1.2.2:www/py-python-dotenv@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}python-multipart>=0.0.9:www/py-python-multipart@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}pyyaml>=6.0.3:devel/py-pyyaml@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}requests>=2.33.0:www/py-requests@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}rich>=14.3.3:textproc/py-rich@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}ruamel.yaml>=0.18.17:devel/py-ruamel.yaml@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}snowballstemmer>=3.1.1:textproc/py-snowballstemmer@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}socksio>0:net/py-socksio@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}tenacity>=9.1.4:devel/py-tenacity@${PY_FLAVOR} \
-		${PYTHON_PKGNAMEPREFIX}uvicorn>=0.41.0:www/py-uvicorn@${PY_FLAVOR}
+		${PYTHON_PKGNAMEPREFIX}urllib3>=2.7.0:net/py-urllib3@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}uvicorn>=0.41.0:www/py-uvicorn@${PY_FLAVOR} \
+		${PYTHON_PKGNAMEPREFIX}websockets>=15.0.1:devel/py-websockets@${PY_FLAVOR}
 
 USES=		python:3.11+,run shebangfix
 USE_GITHUB=	yes
 GH_ACCOUNT=	NousResearch
 GH_PROJECT=	hermes-agent
-GH_TAGNAME=	v2026.8.18
+GH_TAGNAME=	v2026.8.31
 
 USE_RC_SUBR=	hermes_dashboard hermes_gateway
 
@@ -80,9 +100,13 @@ PLIST_SUB+=	HERMES_LIBDIR=${HERMES_LIBDIR:S,^${PREFIX}/,,}
 #        tar xzf ${DISTDIR}/NousResearch-${PORTNAME}-${PORTVERSION}-${GH_TAGNAME}_GH0.tar.gz
 #        cd ${PORTNAME}-*/web
 #   2. Install deps and build the SPA:
-#        npm ci --no-audit --no-fund
+#        npm install --no-audit --no-fund
 #        npm run build
 #      This writes the bundle to ../hermes_cli/web_dist/.
+#      (v2026.8.31 dropped web/package-lock.json, so `npm install` is the
+#      only option -- `npm ci` requires a lockfile.  Earlier releases also
+#      needed --engine-strict=false for a too-narrow npm range in
+#      package.json; the engines gate is gone as of this release.)
 #   3. Repackage with a top-level dir whose name matches the distfile:
 #        cp -a ../hermes_cli/web_dist /tmp/${PORTNAME}-web-dist-${PORTVERSION}
 #        cd /tmp && tar --no-acls --no-xattrs --no-fflags --uid=0 --gid=0 \
diff --git a/misc/hermes-agent/distinfo b/misc/hermes-agent/distinfo
index 942fbbb7ed70..45fd1b39b858 100644
--- a/misc/hermes-agent/distinfo
+++ b/misc/hermes-agent/distinfo
@@ -1,5 +1,5 @@
-TIMESTAMP = 1787258479
-SHA256 (hermes-agent-web-dist-0.17.0.tar.gz) = 8130e8eb8b7529cd4712e549829c500cbbed699c28c29740af3cb3d4efab98a2
-SIZE (hermes-agent-web-dist-0.17.0.tar.gz) = 1490329
-SHA256 (NousResearch-hermes-agent-0.17.0-v2026.8.18_GH0.tar.gz) = 1e3d39d3638ec15fa9d31af262568a953e9272090deb1c50c44cd401175f5b80
-SIZE (NousResearch-hermes-agent-0.17.0-v2026.8.18_GH0.tar.gz) = 66313931
+TIMESTAMP = 1788600397
+SHA256 (hermes-agent-web-dist-0.18.0.tar.gz) = 09b8f000eb69f303869e7e62494f6fad19f9026a1c73dcdc8b94c4425450fc9f
+SIZE (hermes-agent-web-dist-0.18.0.tar.gz) = 1523028
+SHA256 (NousResearch-hermes-agent-0.18.0-v2026.8.31_GH0.tar.gz) = 78fb3ff707ec1d17044b875ecac8bef28aa39d44242824f6871ca40afe7bf217
+SIZE (NousResearch-hermes-agent-0.18.0-v2026.8.31_GH0.tar.gz) = 69421757
diff --git a/misc/hermes-agent/files/patch-agent_anthropic__adapter.py b/misc/hermes-agent/files/patch-agent_anthropic__adapter.py
new file mode 100644
index 000000000000..9b8bb394d9a4
--- /dev/null
+++ b/misc/hermes-agent/files/patch-agent_anthropic__adapter.py
@@ -0,0 +1,75 @@
+--- agent/anthropic_adapter.py.orig	2026-09-05 11:43:11 UTC
++++ agent/anthropic_adapter.py
+@@ -560,6 +560,34 @@ def _common_betas_for_base_url(
+     return betas
+ 
+ 
++_SDK_HTTPX_MOD = None
++
++
++def _sdk_httpx():
++    """Return the httpx module the installed anthropic SDK is built against.
++
++    anthropic 1.x moved its HTTP stack to ``httpx2``; objects crossing the SDK
++    boundary (``Timeout``, ``http_client``) must come from the same module or
++    the SDK rejects them at request time.  Same split as
++    ``tools/mcp_tool.py:sdk_httpx()`` handles for mcp 1.x/2.x.
++    """
++    global _SDK_HTTPX_MOD
++    if _SDK_HTTPX_MOD is not None:
++        return _SDK_HTTPX_MOD
++    try:
++        from anthropic import _base_client as _bc
++        _SDK_HTTPX_MOD = getattr(_bc, "httpx2", None) or getattr(_bc, "httpx", None)
++    except ImportError:
++        _SDK_HTTPX_MOD = None
++    if _SDK_HTTPX_MOD is None:
++        try:
++            import httpx2 as _fallback
++        except ImportError:
++            import httpx as _fallback  # type: ignore[no-redef]
++        _SDK_HTTPX_MOD = _fallback
++    return _SDK_HTTPX_MOD
++
++
+ def _build_anthropic_client_with_bearer_hook(
+     token_provider,
+     base_url: str = None,
+@@ -592,7 +620,7 @@ def _build_anthropic_client_with_bearer_hook(
+ 
+     normalize_proxy_env_vars()
+ 
+-    from httpx import Timeout
++    Timeout = _sdk_httpx().Timeout
+     from agent.azure_identity_adapter import build_bearer_http_client
+ 
+     _read_timeout = timeout if (isinstance(timeout, (int, float)) and timeout > 0) else 900.0
+@@ -604,7 +632,9 @@ def _build_anthropic_client_with_bearer_hook(
+         import re as _re
+         normalized_base_url = _re.sub(r"/v1/?$", "", normalized_base_url.rstrip("/"))
+ 
+-    http_client = build_bearer_http_client(token_provider, timeout=timeout_obj)
++    http_client = build_bearer_http_client(
++        token_provider, httpx_mod=_sdk_httpx(), timeout=timeout_obj
++    )
+ 
+     kwargs = {
+         "timeout": timeout_obj,
+@@ -691,7 +721,7 @@ def build_anthropic_client(
+ 
+     normalize_proxy_env_vars()
+ 
+-    from httpx import Timeout
++    Timeout = _sdk_httpx().Timeout
+ 
+     normalized_base_url = _normalize_base_url_text(base_url)
+     if normalized_base_url:
+@@ -823,7 +853,7 @@ def build_anthropic_bedrock_client(region: str):
+             "anthropic.AnthropicBedrock not available. "
+             "Upgrade with: pip install 'anthropic>=0.39.0'"
+         )
+-    from httpx import Timeout
++    Timeout = _sdk_httpx().Timeout
+ 
+     return _anthropic_sdk.AnthropicBedrock(
+         aws_region=region,
diff --git a/misc/hermes-agent/files/patch-agent_azure__identity__adapter.py b/misc/hermes-agent/files/patch-agent_azure__identity__adapter.py
new file mode 100644
index 000000000000..68b5a695b4f1
--- /dev/null
+++ b/misc/hermes-agent/files/patch-agent_azure__identity__adapter.py
@@ -0,0 +1,44 @@
+--- agent/azure_identity_adapter.py.orig	2026-09-05 11:44:04 UTC
++++ agent/azure_identity_adapter.py
+@@ -475,7 +475,12 @@ def materialize_bearer_for_http(value: Any) -> str:
+     raise ValueError("no usable api_key / token provider")
+ 
+ 
+-def build_bearer_http_client(token_provider: Callable[[], str], **httpx_kwargs: Any) -> Any:
++def build_bearer_http_client(
++    token_provider: Callable[[], str],
++    *,
++    httpx_mod: Any = None,
++    **httpx_kwargs: Any,
++) -> Any:
+     """Return an ``httpx.Client`` that mints a fresh Entra bearer JWT
+     per outbound request.
+ 
+@@ -511,14 +516,19 @@ def build_bearer_http_client(token_provider: Callable[
+             "token provider"
+         )
+ 
+-    try:
+-        import httpx
+-    except ImportError as exc:  # pragma: no cover — httpx ships with openai/anthropic
+-        raise ImportError(
+-            "httpx is required for Entra ID bearer auth on Microsoft Foundry "
+-            "Anthropic-style endpoints. It is normally a transitive "
+-            "dependency of the openai/anthropic SDKs."
+-        ) from exc
++    # ``httpx_mod`` lets the caller pin the flavour its SDK expects: anthropic
++    # 1.x is on httpx2 while openai 2.x is still on httpx.  Defaults to httpx.
++    if httpx_mod is not None:
++        httpx = httpx_mod
++    else:
++        try:
++            import httpx
++        except ImportError as exc:  # pragma: no cover — httpx ships with openai/anthropic
++            raise ImportError(
++                "httpx is required for Entra ID bearer auth on Microsoft Foundry "
++                "Anthropic-style endpoints. It is normally a transitive "
++                "dependency of the openai/anthropic SDKs."
++            ) from exc
+ 
+     def _inject_bearer(request: "httpx.Request") -> None:
+         try:
diff --git a/misc/hermes-agent/files/patch-agent_skill__utils.py b/misc/hermes-agent/files/patch-agent_skill__utils.py
index be1fc31615b3..5dec1122077c 100644
--- a/misc/hermes-agent/files/patch-agent_skill__utils.py
+++ b/misc/hermes-agent/files/patch-agent_skill__utils.py
@@ -1,6 +1,6 @@
---- agent/skill_utils.py.orig	2026-08-03 16:57:23 UTC
+--- agent/skill_utils.py.orig	2026-08-31 19:29:27 UTC
 +++ agent/skill_utils.py
-@@ -236,6 +236,9 @@ def skill_matches_platform_list(platforms: Any) -> boo
+@@ -237,6 +237,9 @@ def skill_matches_platform_list(platforms: Any) -> boo
          mapped = PLATFORM_MAP.get(normalized, normalized)
          if current.startswith(mapped):
              return True
diff --git a/misc/hermes-agent/files/patch-hermes__cli_config__defaults.py b/misc/hermes-agent/files/patch-hermes__cli_config__defaults.py
index 504b7aadcd14..24b97794ef8e 100644
--- a/misc/hermes-agent/files/patch-hermes__cli_config__defaults.py
+++ b/misc/hermes-agent/files/patch-hermes__cli_config__defaults.py
@@ -1,4 +1,4 @@
---- hermes_cli/config_defaults.py.orig	2026-08-04 14:52:16 UTC
+--- hermes_cli/config_defaults.py.orig	2026-08-31 19:29:27 UTC
 +++ hermes_cli/config_defaults.py
 @@ -4,6 +4,8 @@ verbatim from hermes_cli/config.py. Must not import fr
  verbatim from hermes_cli/config.py. Must not import from hermes_cli.config.
@@ -9,7 +9,7 @@
  DEFAULT_CONFIG = {
      "model": "",
      "providers": {},
-@@ -2153,8 +2155,10 @@ DEFAULT_CONFIG = {
+@@ -2700,8 +2702,10 @@ DEFAULT_CONFIG = {
          # their TTS provider). Set to false to require explicit
          # ``pip install`` for everything beyond the base set — appropriate
          # for restricted networks, audited environments, or air-gapped
diff --git a/misc/hermes-agent/files/patch-hermes__cli_gateway.py b/misc/hermes-agent/files/patch-hermes__cli_gateway.py
index 2a8f1e6db94e..b4443397d7a3 100644
--- a/misc/hermes-agent/files/patch-hermes__cli_gateway.py
+++ b/misc/hermes-agent/files/patch-hermes__cli_gateway.py
@@ -1,6 +1,6 @@
---- hermes_cli/gateway.py.orig	2026-08-20 21:23:13 UTC
+--- hermes_cli/gateway.py.orig	2026-08-31 19:29:27 UTC
 +++ hermes_cli/gateway.py
-@@ -1945,6 +1945,45 @@ def supports_systemd_services() -> bool:
+@@ -2608,6 +2608,45 @@ def supports_systemd_services() -> bool:
      return True
  
  
@@ -46,7 +46,7 @@
  def is_macos() -> bool:
      return sys.platform == "darwin"
  
-@@ -2829,7 +2868,8 @@ def ensure_gateway_service(context: str = "setup") -> 
+@@ -3492,7 +3531,8 @@ def ensure_gateway_service(context: str = "setup") -> 
          return False
  
      supports_systemd = supports_systemd_services()
@@ -56,7 +56,7 @@
          print_info("  No supported service manager found on this host.")
          print_info("  Run the gateway in the foreground with: hermes gateway")
          return False
-@@ -2847,6 +2887,8 @@ def ensure_gateway_service(context: str = "setup") -> 
+@@ -3510,6 +3550,8 @@ def ensure_gateway_service(context: str = "setup") -> 
              print_info("  Installing the gateway background service ...")
              if supports_systemd:
                  systemd_install(force=False, non_interactive=True)
@@ -65,7 +65,7 @@
              elif is_macos():
                  launchd_install(force=False)
              else:
-@@ -2859,6 +2901,8 @@ def ensure_gateway_service(context: str = "setup") -> 
+@@ -3522,6 +3564,8 @@ def ensure_gateway_service(context: str = "setup") -> 
  
          if supports_systemd:
              systemd_start()
@@ -74,7 +74,7 @@
          elif is_macos():
              launchd_start()
          else:
-@@ -5287,6 +5331,129 @@ def launchd_status(deep: bool = False):
+@@ -6145,6 +6189,129 @@ def launchd_status(deep: bool = False):
  
  
  # =============================================================================
@@ -204,7 +204,7 @@
  # Gateway Runner
  # =============================================================================
  
-@@ -7560,6 +7727,18 @@ def _gateway_command_inner(args):
+@@ -8449,6 +8616,18 @@ def _gateway_command_inner(args):
              )
              if start_now:
                  systemd_start(system=system)
@@ -223,7 +223,7 @@
          elif is_macos():
              launchd_install(force)
          elif is_windows():
-@@ -7634,6 +7813,8 @@ def _gateway_command_inner(args):
+@@ -8537,6 +8716,8 @@ def _gateway_command_inner(args):
              sys.exit(1)
          if supports_systemd_services():
              systemd_uninstall(system=system)
@@ -232,7 +232,7 @@
          elif is_macos():
              launchd_uninstall()
          elif is_windows():
-@@ -7687,6 +7868,8 @@ def _gateway_command_inner(args):
+@@ -8590,6 +8771,8 @@ def _gateway_command_inner(args):
              sys.exit(1)
          if supports_systemd_services():
              systemd_start(system=system)
@@ -241,7 +241,7 @@
          elif is_macos():
              launchd_start()
          elif is_windows():
-@@ -7764,6 +7947,18 @@ def _gateway_command_inner(args):
+@@ -8673,6 +8856,18 @@ def _gateway_command_inner(args):
                      service_available = True
                  except subprocess.CalledProcessError:
                      pass
@@ -260,7 +260,7 @@
              elif is_macos() and get_launchd_plist_path().exists():
                  try:
                      launchd_stop()
-@@ -7861,6 +8056,12 @@ def _gateway_command_inner(args):
+@@ -8776,6 +8971,12 @@ def _gateway_command_inner(args):
                      service_stopped = True
                  except subprocess.CalledProcessError:
                      pass
@@ -273,7 +273,7 @@
              elif is_macos() and get_launchd_plist_path().exists():
                  try:
                      launchd_stop()
-@@ -7889,6 +8090,8 @@ def _gateway_command_inner(args):
+@@ -8804,6 +9005,8 @@ def _gateway_command_inner(args):
                  or get_systemd_unit_path(system=True).exists()
              ):
                  systemd_start(system=system)
@@ -282,7 +282,7 @@
              elif is_macos() and get_launchd_plist_path().exists():
                  launchd_start()
              elif is_windows():
-@@ -7915,6 +8118,13 @@ def _gateway_command_inner(args):
+@@ -8830,6 +9033,13 @@ def _gateway_command_inner(args):
                  service_available = True
              except subprocess.CalledProcessError:
                  pass
@@ -296,7 +296,7 @@
          elif is_macos() and get_launchd_plist_path().exists():
              service_configured = True
              try:
-@@ -7997,6 +8207,9 @@ def _gateway_command_inner(args):
+@@ -8912,6 +9122,9 @@ def _gateway_command_inner(args):
              or get_systemd_unit_path(system=True).exists()
          ):
              systemd_status(deep, system=system, full=full)
diff --git a/misc/hermes-agent/files/patch-hermes__cli_main.py b/misc/hermes-agent/files/patch-hermes__cli_main.py
index 2cb46e485db8..ed64dd386f8f 100644
--- a/misc/hermes-agent/files/patch-hermes__cli_main.py
+++ b/misc/hermes-agent/files/patch-hermes__cli_main.py
@@ -1,6 +1,6 @@
---- hermes_cli/main.py.orig	2026-08-03 16:57:23 UTC
+--- hermes_cli/main.py.orig	2026-08-31 19:29:27 UTC
 +++ hermes_cli/main.py
-@@ -11112,6 +11112,16 @@ def cmd_skills(args):
+@@ -13019,6 +13019,16 @@ def cmd_skills(args):
  
  
  def cmd_skills(args):
diff --git a/misc/hermes-agent/files/patch-hermes__cli_setup.py b/misc/hermes-agent/files/patch-hermes__cli_setup.py
index 4d6298ef9bdf..f68bf3cb36fd 100644
--- a/misc/hermes-agent/files/patch-hermes__cli_setup.py
+++ b/misc/hermes-agent/files/patch-hermes__cli_setup.py
@@ -1,6 +1,6 @@
---- hermes_cli/setup.py.orig	2026-08-20 21:23:13 UTC
+--- hermes_cli/setup.py.orig	2026-08-31 19:29:27 UTC
 +++ hermes_cli/setup.py
-@@ -2240,9 +2240,11 @@ def setup_gateway(config: dict):
+@@ -2350,9 +2350,11 @@ def setup_gateway(config: dict):
      from hermes_cli.gateway import (
          _is_service_running,
          supports_systemd_services,
@@ -12,7 +12,7 @@
          UserSystemdUnavailableError,
          SystemScopeRequiresRootError,
          _system_scope_wizard_would_need_root,
-@@ -2253,6 +2255,7 @@ def setup_gateway(config: dict):
+@@ -2363,6 +2365,7 @@ def setup_gateway(config: dict):
      _is_macos = _platform.system() == "Darwin"
      _is_windows = _platform.system() == "Windows"
      supports_systemd = supports_systemd_services()
@@ -20,7 +20,7 @@
  
      print()
      if _is_service_running():
-@@ -2267,6 +2270,8 @@ def setup_gateway(config: dict):
+@@ -2377,6 +2380,8 @@ def setup_gateway(config: dict):
              try:
                  if supports_systemd:
                      systemd_restart()
diff --git a/misc/hermes-agent/files/patch-hermes__cli_uninstall.py b/misc/hermes-agent/files/patch-hermes__cli_uninstall.py
index 5c7564199600..8490337642ea 100644
--- a/misc/hermes-agent/files/patch-hermes__cli_uninstall.py
+++ b/misc/hermes-agent/files/patch-hermes__cli_uninstall.py
@@ -1,6 +1,6 @@
---- hermes_cli/uninstall.py.orig	2026-08-03 16:57:23 UTC
+--- hermes_cli/uninstall.py.orig	2026-08-31 19:29:27 UTC
 +++ hermes_cli/uninstall.py
-@@ -265,7 +265,22 @@ def uninstall_gateway_service():
+@@ -278,7 +278,22 @@ def uninstall_gateway_service():
          except Exception as e:
              log_warn(f"Could not remove launchd gateway service: {e}")
  
diff --git a/misc/hermes-agent/files/patch-tools_lazy__deps.py b/misc/hermes-agent/files/patch-tools_lazy__deps.py
index 806ce5257141..cbe9417fcd6e 100644
--- a/misc/hermes-agent/files/patch-tools_lazy__deps.py
+++ b/misc/hermes-agent/files/patch-tools_lazy__deps.py
@@ -1,6 +1,6 @@
---- tools/lazy_deps.py.orig	2026-08-03 16:57:23 UTC
+--- tools/lazy_deps.py.orig	2026-08-31 19:29:27 UTC
 +++ tools/lazy_deps.py
-@@ -514,7 +514,9 @@ def _allow_lazy_installs() -> bool:
+@@ -524,7 +524,9 @@ def _allow_lazy_installs() -> bool:
          cfg = None
      if cfg is not None:
          sec = cfg.get("security") or {}