Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
f078fe3
refactor(hermes): centralize managed policy
jyaunches Jul 31, 2026
3e17fdb
test(hermes): keep policy fixture linear
jyaunches Jul 31, 2026
858977d
fix(hermes): seal runtime managed policy
jyaunches Jul 31, 2026
f722092
docs(hermes): align policy references
jyaunches Jul 31, 2026
7d31337
fix(security): classify config integrity digest
jyaunches Jul 31, 2026
c1b913e
fix(security): name Hermes proxy sentinel accurately
jyaunches Jul 31, 2026
e0a6f10
docs(hermes): align proxy sentinel terminology
jyaunches Jul 31, 2026
0f5a217
fix(hermes): keep image probe discovery standalone
jyaunches Jul 31, 2026
3534e25
fix(hermes): refresh image probe integrity pin
jyaunches Jul 31, 2026
39edc96
docs(hermes): define profile patch removal
jyaunches Jul 31, 2026
eb37107
merge: sync main for Hermes policy E2E
jyaunches Aug 3, 2026
fe18a14
docs(hermes): map managed policy lifecycle
jyaunches Aug 3, 2026
c16cf2d
test(hermes): cover policy cleanup drift
jyaunches Aug 3, 2026
936de32
test(hermes): keep drift setup linear
jyaunches Aug 3, 2026
7672ce8
fix(hermes): probe reset policy at gateway boundary
jyaunches Aug 3, 2026
5a68f82
chore(ci): retry trusted E2E gate
jyaunches Aug 3, 2026
fac55ec
chore(ci): retry cold onboard timing
jyaunches Aug 3, 2026
d61075c
merge(main): refresh PR base
jyaunches Aug 3, 2026
e07f7cb
fix(hermes): preserve managed inference contracts
jyaunches Aug 3, 2026
0aeaf3f
test(hermes): keep credential denial setup linear
jyaunches Aug 3, 2026
b7c7510
fix(hermes): document credential cleanup safety
jyaunches Aug 3, 2026
5873788
merge(main): refresh PR base
jyaunches Aug 3, 2026
1243598
merge(main): refresh Hermes E2E base
jyaunches Aug 3, 2026
b462e8a
test(e2e): retry unreachable Hermes MCP discovery
jyaunches Aug 3, 2026
5689c62
merge(hermes): refresh policy model onto main
jyaunches Aug 5, 2026
cdfb9ce
merge(main): sync latest upstream changes
jyaunches Aug 5, 2026
29831fb
fix(hermes): run neutral platform probe after patch
jyaunches Aug 5, 2026
ede6bca
fix(hermes): refresh patched gateway hashes
jyaunches Aug 5, 2026
233e08b
fix(hermes): validate managed rewrite sentinel
jyaunches Aug 5, 2026
f9137f0
fix(hermes): name OpenShell rewrite boundary
jyaunches Aug 5, 2026
6a04784
fix(hermes): refresh wrapper integrity hash
jyaunches Aug 5, 2026
24f2b7b
test(e2e): cover bounded MCP discovery restart
jyaunches Aug 5, 2026
7ff7bd2
Merge remote-tracking branch 'origin/main' into codex/pr-8026-refresh
jyaunches Aug 5, 2026
cd93a2c
Merge remote-tracking branch 'origin/main' into codex/pr-8026-refresh
jyaunches Aug 5, 2026
b725489
Merge remote-tracking branch 'origin/main' into codex/pr-8026-refresh
jyaunches Aug 6, 2026
15d731c
Merge remote-tracking branch 'origin/main' into codex/pr-8026-refresh
jyaunches Aug 6, 2026
c2d7f83
merge(main): refresh PR 8026
jyaunches Aug 6, 2026
1093420
merge(main): refresh PR 8026
jyaunches Aug 6, 2026
4754802
test(e2e): retry concurrent MCP removal
jyaunches Aug 6, 2026
371c6e5
merge(main): refresh PR 8026
jyaunches Aug 6, 2026
5f06bc5
merge(main): refresh PR 8026
jyaunches Aug 6, 2026
a24f6db
merge(main): refresh PR 8026
jyaunches Aug 6, 2026
b9aed79
merge(main): refresh PR 8026
jyaunches Aug 6, 2026
2a9784d
test(e2e): keep MCP retry helper linear
jyaunches Aug 6, 2026
35f2091
merge(main): refresh PR 8026
jyaunches Aug 6, 2026
6fc2763
fix(inference): resolve readiness comparator merge
jyaunches Aug 6, 2026
e2d7962
merge(main): refresh PR 8026
jyaunches Aug 6, 2026
7c5efdd
merge(main): refresh PR 8026
jyaunches Aug 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 71 additions & 57 deletions agents/hermes/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ COPY agents/hermes/patch-cron-execution-runtime.py /opt/nemoclaw-hermes-config/p
COPY agents/hermes/patch-cron-restore-drain.py /opt/nemoclaw-hermes-config/patch-cron-restore-drain.py
COPY agents/hermes/patch-neutral-platform-env-activation.py /opt/nemoclaw-hermes-config/patch-neutral-platform-env-activation.py
COPY agents/hermes/host/managed-tool-gateway-matrix.json /opt/nemoclaw-hermes-config/managed-tool-gateway-matrix.json
COPY src/lib/hermes-managed-route.ts /src/lib/hermes-managed-route.ts
COPY src/lib/tool-disclosure.ts /src/lib/tool-disclosure.ts
COPY src/lib/messaging/ /src/lib/messaging/
COPY scripts/lib/openclaw-npm-remediation.mts /scripts/lib/openclaw-npm-remediation.mts
Expand All @@ -128,6 +129,7 @@ COPY agents/hermes/validate-env-secret-boundary.py /usr/local/lib/nemoclaw/valid
COPY agents/hermes/patch-session-list-preview.py /usr/local/lib/nemoclaw/patch-hermes-session-list-preview.py
COPY agents/hermes/patch-discord-recovery-permissions.py /usr/local/lib/nemoclaw/patch-hermes-discord-recovery-permissions.py
COPY agents/hermes/patch-profile-policy-defaults.py /usr/local/lib/nemoclaw/patch-hermes-profile-policy-defaults.py
COPY agents/hermes/managed_policy.py /usr/local/lib/nemoclaw/managed_policy.py
COPY agents/hermes/patch-langfuse-credentials.mts /usr/local/lib/nemoclaw/patch-hermes-langfuse-credentials.mts
COPY agents/hermes/seed-dashboard-config.py /usr/local/lib/nemoclaw/seed-hermes-dashboard-config.py
COPY agents/hermes/runtime-config-guard.py /usr/local/lib/nemoclaw/hermes-runtime-config-guard.py
Expand Down Expand Up @@ -318,13 +320,13 @@ RUN chmod -R a+rX /opt/nemoclaw-hermes-plugin/
# read-only.
RUN find /opt/nemoclaw-hermes-config -type d -exec chmod 755 {} + \
&& find /opt/nemoclaw-hermes-config -type f -exec chmod 444 {} + \
&& chmod 444 /src/lib/tool-disclosure.ts \
&& chmod 444 /src/lib/hermes-managed-route.ts /src/lib/tool-disclosure.ts \
&& chmod 444 /scripts/lib/reviewed-npm-archive.mts /scripts/lib/openclaw-npm-remediation.mts \
/scripts/patch-bundled-npm-brace-expansion.mts /scripts/lib/patch-bundled-npm-ip-address.mts \
/scripts/patch-bundled-npm-tar.mts \
&& chmod -R a+rX /src/lib/messaging

ARG NEMOCLAW_HERMES_IMAGE_BUILD_PROBES_SHA256=284e2bf46c82f25967b86f73fbefcd97315a1284a4b079bd6f13e6153bece4b6
ARG NEMOCLAW_HERMES_IMAGE_BUILD_PROBES_SHA256=61fec509d9c0229650f71d1fc53d103a39fd830976213dbdef0d222592981d03
# hadolint ignore=DL4006
RUN printf '%s %s\n' \
"$NEMOCLAW_HERMES_IMAGE_BUILD_PROBES_SHA256" /opt/nemoclaw-hermes-config/image-build-probes.py \
Expand Down Expand Up @@ -363,7 +365,7 @@ RUN chmod 755 /usr/local/bin/nemoclaw-start /usr/local/bin/nemoclaw-managed-star
&& chown root:root /usr/local/bin/nemoclaw-gateway-control /usr/local/lib/nemoclaw/gateway-supervisor.sh /usr/local/lib/nemoclaw/state-dir-guard.py /usr/local/share/nemoclaw/state-lock-plan.json /usr/local/lib/nemoclaw/managed-gateway-control.py /usr/local/lib/nemoclaw/build-hermes-mcp-digest.py /usr/local/lib/nemoclaw/hermes-cron-restore-control.py /usr/local/lib/nemoclaw/openshell-child-visible-credentials.v0.0.85.json \
&& chmod 700 /usr/local/bin/nemoclaw-gateway-control /usr/local/lib/nemoclaw/hermes-cron-restore-control.py \
&& chmod 500 /usr/local/lib/nemoclaw/state-dir-guard.py /usr/local/lib/nemoclaw/managed-gateway-control.py \
&& chmod 444 /usr/local/lib/nemoclaw/entrypoint-env-wrapper.sh /usr/local/share/nemoclaw/state-lock-plan.json /usr/local/lib/nemoclaw/gateway-supervisor.sh /usr/local/lib/nemoclaw/build-hermes-mcp-digest.py \
&& chmod 444 /usr/local/lib/nemoclaw/entrypoint-env-wrapper.sh /usr/local/share/nemoclaw/state-lock-plan.json /usr/local/lib/nemoclaw/gateway-supervisor.sh /usr/local/lib/nemoclaw/build-hermes-mcp-digest.py /usr/local/lib/nemoclaw/managed_policy.py \
&& chmod 444 /usr/local/lib/nemoclaw/patch-hermes-langfuse-credentials.mts \
&& chmod 444 /usr/local/lib/nemoclaw/openshell-child-visible-credentials.v0.0.85.json \
&& if [ -d /usr/local/lib/nemoclaw/preloads ]; then \
Expand Down Expand Up @@ -424,57 +426,6 @@ RUN /usr/bin/python3 -I \
"$NEMOCLAW_HERMES_GATEWAY_RUN_DRAIN_PATCHED_SHA256" /opt/hermes/gateway/run.py \
| sha256sum -c -

# Fresh named profiles do not receive config.yaml, so pin the reviewed
# NemoClaw policy at Hermes' source defaults as well as in generated default
# and dashboard homes. The patcher binds all seven input modules to the exact
# upstream v2026.7.20 source hashes before editing them.
ARG NEMOCLAW_HERMES_PROFILE_POLICY_PATCHER_SHA256=0a05a28e39194016edc3b41448e5ec40abf759c8a445ad2083eb6e6705766599
# hadolint ignore=DL4006
RUN printf '%s %s\n' \
"$NEMOCLAW_HERMES_PROFILE_POLICY_PATCHER_SHA256" /usr/local/lib/nemoclaw/patch-hermes-profile-policy-defaults.py \
| sha256sum -c - \
|| { echo "ERROR: patch-hermes-profile-policy-defaults.py hash mismatch (update NEMOCLAW_HERMES_PROFILE_POLICY_PATCHER_SHA256)" >&2; exit 1; }
RUN /usr/bin/python3 -I /usr/local/lib/nemoclaw/patch-hermes-profile-policy-defaults.py

# Hermes v0.19.0 has several built-in environment override paths that can
# re-enable an explicitly disabled platform when ambient credentials exist.
# Apply this after the profile-policy patch above, then bind both its exact
# output module and this narrow patcher before preserving explicit disables
# across environment processing.
ARG NEMOCLAW_HERMES_NEUTRAL_PLATFORM_PATCHER_SHA256=29769d0ae10646dd0a66b32dbefd5f85540544172d57cac96bb4f0941e260948
ARG NEMOCLAW_HERMES_POST_PROFILE_GATEWAY_CONFIG_SHA256=2084c652a07614761d85703787f8697fc29560fe447f23362aa0bda5179dffa7
ARG NEMOCLAW_HERMES_NEUTRAL_PLATFORM_OUTPUT_SHA256=5a1375664d1451b2fe9c3f2325f673149a90b9035588dfd4eb6618f785ecd6a2
# hadolint ignore=DL4006
RUN printf '%s %s\n' \
"$NEMOCLAW_HERMES_NEUTRAL_PLATFORM_PATCHER_SHA256" /opt/nemoclaw-hermes-config/patch-neutral-platform-env-activation.py \
"$NEMOCLAW_HERMES_POST_PROFILE_GATEWAY_CONFIG_SHA256" /opt/hermes/gateway/config.py \
| sha256sum -c - \
|| { echo "ERROR: Hermes neutral platform environment source identity mismatch" >&2; exit 1; }
# hadolint ignore=DL4006
RUN /usr/bin/python3 -I \
/opt/nemoclaw-hermes-config/patch-neutral-platform-env-activation.py \
/opt/hermes/gateway/config.py \
&& printf '%s %s\n' \
"$NEMOCLAW_HERMES_NEUTRAL_PLATFORM_OUTPUT_SHA256" /opt/hermes/gateway/config.py \
| sha256sum -c -

# Prove the source-level fallback on the real installed runtime through the
# user-facing profile creation path. The new home must remain config-less while
# all security, privacy, update, browser, and session defaults fail safe.
RUN set -eu; \
profile_probe_root="$(mktemp -d)"; \
trap 'rm -rf "$profile_probe_root"' EXIT; \
profile_probe_default="$profile_probe_root/.hermes"; \
HOME="$profile_probe_root" HERMES_HOME="$profile_probe_default" \
/usr/local/bin/hermes profile create nemoclaw-policy-probe \
--no-alias --no-skills; \
profile_probe_home="$profile_probe_default/profiles/nemoclaw-policy-probe"; \
test -d "$profile_probe_home"; \
test ! -e "$profile_probe_home/config.yaml"; \
HOME="$profile_probe_root" HERMES_HOME="$profile_probe_home" \
/opt/hermes/.venv/bin/python -I \
/opt/nemoclaw-hermes-config/image-build-probes.py profile-policy

# Hermes v0.19.0 writes gateway lifecycle metadata directly below HERMES_HOME.
# Shields-up deliberately makes that config root root-owned and non-writable,
# so managed stop/start recovery cannot remove the old PID file and exits with
Expand Down Expand Up @@ -591,7 +542,7 @@ RUN node --experimental-strip-types \
# silent supply-chain tampering of the build context (an attacker rewriting a
# file has to also rewrite the Dockerfile-committed hash, which reviewers gate).
# Regenerate with `sha256sum agents/hermes/{hermes-wrapper.py,hermes-cli-adapter-v1.json,validate-cli-adapter.py,validate-env-secret-boundary.py,finalize-tirith-marker.py,cron-restore-control.py}`.
ARG NEMOCLAW_HERMES_WRAPPER_SHA256=a841a3673cd2543dd53559e513741dd66929361b8ca94b9196b72badf7827d3c
ARG NEMOCLAW_HERMES_WRAPPER_SHA256=f4276e9833638b7a620176c88bd329d6b6d4948538a3227b727a1397146a0e0e
ARG NEMOCLAW_HERMES_CLI_ADAPTER_SHA256=989edf54a8c09c6efb348600a8aa2f264c0b71408eb9d7bcd579b92cbeccf9b1
ARG NEMOCLAW_HERMES_CLI_ADAPTER_VALIDATOR_SHA256=db4046e79e513eab67b069a8eda20167b8b65529cf26842531d2ad673c670330
ARG NEMOCLAW_HERMES_VALIDATOR_SHA256=822c7e63d068c5d09f3291350771c1a42c9686f51bfa9bc9a1f41fbe15d163b1
Expand Down Expand Up @@ -774,15 +725,74 @@ RUN HERMES_HOME=/sandbox/.hermes /usr/local/bin/hermes doctor --fix \
&& node --experimental-strip-types /opt/nemoclaw-hermes-config/generate-config.ts \
&& if [ "$NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION" = "1" ]; then \
/opt/hermes/.venv/bin/python -I -c 'import importlib.metadata as m, pathlib, yaml; config=yaml.safe_load(pathlib.Path("/sandbox/.hermes/config.yaml").read_text()); neutral={name: value for name, value in config["platforms"].items() if name != "api_server"}; assert len(neutral) == 30; assert all(value == {"enabled": False} for value in neutral.values()); assert m.version("microsoft-teams-apps") == "2.0.13.4"; assert m.version("aiohttp") == "3.14.3"'; \
fi \
&& rm -rf /sandbox/.cache

USER root

# Install the generated policy manifest outside the mutable Hermes home. Python
# consumers read this versioned artifact instead of embedding managed defaults.
RUN install -o root -g root -m 0444 \
/sandbox/.hermes/managed-policy.json \
/usr/local/share/nemoclaw/hermes-managed-policy.json \
&& rm -f /sandbox/.hermes/managed-policy.json

# Fresh named profiles do not receive config.yaml. Patch the pinned Hermes
# fallback readers from the generated manifest, then validate a real profile.
ARG NEMOCLAW_HERMES_PROFILE_POLICY_PATCHER_SHA256=7468555c7596b3b95732fb98aec6152537778d8519a4409c3da8aa6a76c9a3f7
# hadolint ignore=DL4006
RUN printf '%s %s\n' \
"$NEMOCLAW_HERMES_PROFILE_POLICY_PATCHER_SHA256" /usr/local/lib/nemoclaw/patch-hermes-profile-policy-defaults.py \
| sha256sum -c - \
|| { echo "ERROR: patch-hermes-profile-policy-defaults.py hash mismatch (update NEMOCLAW_HERMES_PROFILE_POLICY_PATCHER_SHA256)" >&2; exit 1; }
RUN /usr/bin/python3 -I /usr/local/lib/nemoclaw/patch-hermes-profile-policy-defaults.py
# Hermes v0.19.0 has several built-in environment override paths that can
# re-enable an explicitly disabled platform when ambient credentials exist.
# Apply this after the profile-policy patch above, then bind both its exact
# output module and this narrow patcher before preserving explicit disables
# across environment processing.
ARG NEMOCLAW_HERMES_NEUTRAL_PLATFORM_PATCHER_SHA256=29769d0ae10646dd0a66b32dbefd5f85540544172d57cac96bb4f0941e260948
ARG NEMOCLAW_HERMES_POST_PROFILE_GATEWAY_CONFIG_SHA256=b50a8390311c828fa9e13084e9af0caadafe2380ae161ef36dd4bdf792b22ee6
ARG NEMOCLAW_HERMES_NEUTRAL_PLATFORM_OUTPUT_SHA256=77ad342af30d59a5b863d9f5f817247d816fd582fb12d38e074243f88d85b9f4
# hadolint ignore=DL4006
RUN printf '%s %s\n' \
"$NEMOCLAW_HERMES_NEUTRAL_PLATFORM_PATCHER_SHA256" /opt/nemoclaw-hermes-config/patch-neutral-platform-env-activation.py \
"$NEMOCLAW_HERMES_POST_PROFILE_GATEWAY_CONFIG_SHA256" /opt/hermes/gateway/config.py \
| sha256sum -c - \
|| { echo "ERROR: Hermes neutral platform environment source identity mismatch" >&2; exit 1; }
# hadolint ignore=DL4006
RUN /usr/bin/python3 -I \
/opt/nemoclaw-hermes-config/patch-neutral-platform-env-activation.py \
/opt/hermes/gateway/config.py \
&& printf '%s %s\n' \
"$NEMOCLAW_HERMES_NEUTRAL_PLATFORM_OUTPUT_SHA256" /opt/hermes/gateway/config.py \
| sha256sum -c -

RUN if [ "$NEMOCLAW_MANAGED_IMAGE_CAPABILITY_UNION" = "1" ]; then \
GOOGLE_CHAT_PROJECT_ID=nemoclaw-hostile \
GOOGLE_CHAT_SUBSCRIPTION_NAME=projects/nemoclaw-hostile/subscriptions/nemoclaw-hostile \
GOOGLE_CHAT_SERVICE_ACCOUNT_JSON='{"type":"service_account","project_id":"nemoclaw-hostile"}' \
WHATSAPP_CLOUD_PHONE_NUMBER_ID=nemoclaw-hostile \
WHATSAPP_CLOUD_ACCESS_TOKEN=nemoclaw-hostile \
HERMES_HOME=/sandbox/.hermes /opt/hermes/.venv/bin/python -I \
/opt/nemoclaw-hermes-config/image-build-probes.py neutral-platform-inertness; \
fi \
&& rm -rf /sandbox/.cache
fi

RUN set -eu; \
profile_probe_root="$(mktemp -d)"; \
trap 'rm -rf "$profile_probe_root"' EXIT; \
profile_probe_default="$profile_probe_root/.hermes"; \
HOME="$profile_probe_root" HERMES_HOME="$profile_probe_default" \
/usr/local/bin/hermes profile create nemoclaw-policy-probe \
--no-alias --no-skills; \
profile_probe_home="$profile_probe_default/profiles/nemoclaw-policy-probe"; \
test -d "$profile_probe_home"; \
test ! -e "$profile_probe_home/config.yaml"; \
HOME="$profile_probe_root" HERMES_HOME="$profile_probe_home" \
/opt/hermes/.venv/bin/python -I \
/opt/nemoclaw-hermes-config/image-build-probes.py profile-policy

USER sandbox

# Prove that the installed dashboard seeder carries every reviewed policy value
# from the generated default home into a fresh isolated dashboard home. This is
Expand All @@ -792,6 +802,7 @@ RUN dashboard_probe=/tmp/nemoclaw-dashboard-policy-probe.yaml \
&& rm -f "$dashboard_probe" "$dashboard_probe.nemoclaw.tmp" \
&& /opt/hermes/.venv/bin/python -I \
/usr/local/lib/nemoclaw/seed-hermes-dashboard-config.py \
/usr/local/share/nemoclaw/hermes-managed-policy.json \
/sandbox/.hermes/config.yaml "$dashboard_probe" \
&& /opt/hermes/.venv/bin/python -I \
/opt/nemoclaw-hermes-config/image-build-probes.py \
Expand Down Expand Up @@ -1135,6 +1146,7 @@ RUN check_metadata() { \
&& check_absent /root/.cache/node-gyp \
&& check_absent /root/.cache/uv \
&& check_absent /sandbox/.cache \
&& check_absent /sandbox/.hermes/managed-policy.json \
&& check_absent /sandbox/.nemoclaw/hermes-cron-restore-drain.json \
&& check_metadata /sandbox/.nemoclaw 'root:root 1755' \
&& check_metadata /scripts/patch-bundled-npm-brace-expansion.mts 'root:root 444' \
Expand All @@ -1144,6 +1156,8 @@ RUN check_metadata() { \
&& check_metadata /usr/local/lib/nemoclaw/validate-hermes-env-secret-boundary.py 'root:root 755' \
&& check_metadata /usr/local/lib/nemoclaw/patch-hermes-discord-recovery-permissions.py 'root:root 755' \
&& check_metadata /usr/local/lib/nemoclaw/patch-hermes-profile-policy-defaults.py 'root:root 755' \
&& check_metadata /usr/local/lib/nemoclaw/managed_policy.py 'root:root 444' \
&& check_metadata /usr/local/share/nemoclaw/hermes-managed-policy.json 'root:root 444' \
&& test ! -L /usr/local/bin/nemoclaw-managed-bootstrap \
&& check_metadata /usr/local/bin/nemoclaw-managed-bootstrap 'root:root 755' \
&& test ! -L /usr/local/lib/nemoclaw/managed-bootstrap-trampoline.sh \
Expand Down
18 changes: 12 additions & 6 deletions agents/hermes/config/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@
// SPDX-License-Identifier: Apache-2.0

import { type HermesBuildSettings, readHermesBuildSettings } from "./build-env.ts";
import { buildHermesConfig, finalizeHermesPlatformToolsets } from "./hermes-config.ts";
import { buildHermesEnvLines } from "./hermes-env.ts";
import {
buildHermesManagedPolicy,
finalizeHermesPlatformToolsets,
type HermesManagedPolicyV1,
} from "./managed-policy.ts";
import { discoverModelSpecificSetups } from "./model-specific-setup.ts";
import { type WrittenHermesConfig, writeHermesConfigFiles } from "./write-config.ts";

Expand All @@ -18,6 +21,7 @@ export type GeneratedHermesConfig = {
settings: HermesBuildSettings;
config: Record<string, unknown>;
envLines: string[];
policy: HermesManagedPolicyV1;
written: WrittenHermesConfig;
};

Expand All @@ -40,13 +44,15 @@ export function generateHermesConfig({
{ env, scriptDir },
);

const config = buildHermesConfig(settings, env);
const envLines = buildHermesEnvLines(settings, env);
const policy = buildHermesManagedPolicy(settings, env);
const config = policy.config;
const envLines = policy.env_lines;
finalizeHermesPlatformToolsets(config, settings);
const written = writeHermesConfigFiles(config, envLines, homeDir);
const written = writeHermesConfigFiles(config, envLines, policy, homeDir);

log(`[config] Wrote ${written.configPath} (model=${settings.model}, provider=custom)`);
log(`[config] Wrote ${written.envPath} (${written.envEntryCount} entries)`);
log(`[config] Wrote ${written.policyPath} (schema=${policy.schema_version})`);

return { settings, config, envLines, written };
return { settings, config, envLines, policy, written };
}
Loading
Loading