diff --git a/src/gateway/server.impl.ts b/src/gateway/server.impl.ts index b5c1b121370..721207df2b0 100644 --- a/src/gateway/server.impl.ts +++ b/src/gateway/server.impl.ts @@ -19,6 +19,7 @@ import { writeConfigFile, } from "../config/config.js"; import { applyPluginAutoEnable } from "../config/plugin-auto-enable.js"; +import { resolveMainSessionKey } from "../config/sessions.js"; import { clearAgentRunContext, onAgentEvent } from "../infra/agent-events.js"; import { ensureControlUiAssetsBuilt, @@ -38,6 +39,7 @@ import { refreshRemoteBinsForConnectedNodes, setSkillsRemoteRegistry, } from "../infra/skills-remote.js"; +import { enqueueSystemEvent } from "../infra/system-events.js"; import { scheduleGatewayUpdateCheck } from "../infra/update-startup.js"; import { startDiagnosticHeartbeat, stopDiagnosticHeartbeat } from "../logging/diagnostic.js"; import { createSubsystemLogger, runtimeForLogger } from "../logging/subsystem.js"; @@ -257,6 +259,16 @@ export async function startGatewayServer( } let secretsDegraded = false; + const emitSecretsStateEvent = ( + code: "SECRETS_RELOADER_DEGRADED" | "SECRETS_RELOADER_RECOVERED", + message: string, + cfg: OpenClawConfig, + ) => { + enqueueSystemEvent(`[${code}] ${message}`, { + sessionKey: resolveMainSessionKey(cfg), + contextKey: code, + }); + }; const activateRuntimeSecrets = async ( config: OpenClawConfig, params: { reason: "startup" | "reload" | "restart-check"; activate: boolean }, @@ -270,9 +282,10 @@ export async function startGatewayServer( logSecrets.warn(`[${warning.code}] ${warning.message}`); } if (secretsDegraded) { - logSecrets.info( - "[SECRETS_RELOADER_RECOVERED] Secret resolution recovered; runtime remained on last-known-good during the outage.", - ); + const recoveredMessage = + "Secret resolution recovered; runtime remained on last-known-good during the outage."; + logSecrets.info(`[SECRETS_RELOADER_RECOVERED] ${recoveredMessage}`); + emitSecretsStateEvent("SECRETS_RELOADER_RECOVERED", recoveredMessage, prepared.config); } secretsDegraded = false; return prepared; @@ -280,6 +293,13 @@ export async function startGatewayServer( const details = String(err); if (!secretsDegraded) { logSecrets.error(`[SECRETS_RELOADER_DEGRADED] ${details}`); + if (params.reason !== "startup") { + emitSecretsStateEvent( + "SECRETS_RELOADER_DEGRADED", + `Secret resolution failed; runtime remains on last-known-good snapshot. ${details}`, + config, + ); + } } else { logSecrets.warn(`[SECRETS_RELOADER_DEGRADED] ${details}`); }