mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 21:07:01 -06:00
fix(agents): log warnings instead of swallowing subagent errors (#82943)
* fix: log subagent swallowed errors in hook emission and restore paths
Wire createSubsystemLogger into the two silent catch blocks that
discard errors during subagent lifecycle:
1. emitSubagentEndedHookOnce (subagent-registry-completion.ts):
catch { return false } -> catch (err) { log.warn(...); return false }
2. restoreSubagentRunsOnce (subagent-registry.ts):
catch { /* ignore */ } -> catch (err) { log.warn(...) }
Both paths now log the error message before continuing, providing
a diagnostic trail when hook emission or disk restore fails silently.
Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
* test(agents): keep provider test mocks current
---------
Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
This commit is contained in:
@@ -28,8 +28,42 @@ vi.mock("./provider-model-normalization.runtime.js", () => ({
|
||||
}));
|
||||
|
||||
const emptyPluginMetadataSnapshot = vi.hoisted(() => ({
|
||||
policyHash: "model-fallback-probe-test-empty-plugin-policy",
|
||||
configFingerprint: "model-fallback-probe-test-empty-plugin-metadata",
|
||||
index: {
|
||||
hostContractVersion: "test",
|
||||
compatRegistryVersion: "test",
|
||||
migrationVersion: 1,
|
||||
policyHash: "model-fallback-probe-test-empty-plugin-policy",
|
||||
generatedAtMs: 0,
|
||||
installRecords: {},
|
||||
plugins: [],
|
||||
diagnostics: [],
|
||||
},
|
||||
registryDiagnostics: [],
|
||||
manifestRegistry: { plugins: [], diagnostics: [] },
|
||||
plugins: [],
|
||||
diagnostics: [],
|
||||
byPluginId: new Map(),
|
||||
normalizePluginId: (pluginId: string) => pluginId,
|
||||
owners: {
|
||||
channels: new Map(),
|
||||
channelConfigs: new Map(),
|
||||
providers: new Map(),
|
||||
modelCatalogProviders: new Map(),
|
||||
cliBackends: new Map(),
|
||||
setupProviders: new Map(),
|
||||
commandAliases: new Map(),
|
||||
contracts: new Map(),
|
||||
},
|
||||
metrics: {
|
||||
registrySnapshotMs: 0,
|
||||
manifestRegistryMs: 0,
|
||||
ownerMapsMs: 0,
|
||||
totalMs: 0,
|
||||
indexPluginCount: 0,
|
||||
manifestPluginCount: 0,
|
||||
},
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/current-plugin-metadata-snapshot.js", () => ({
|
||||
|
||||
@@ -5,6 +5,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { testing as extraParamsTesting } from "./pi-embedded-runner/extra-params.js";
|
||||
|
||||
vi.mock("../plugins/provider-hook-runtime.js", () => ({
|
||||
clearProviderRuntimePluginCacheForTest: vi.fn(),
|
||||
testing: {
|
||||
buildHookProviderCacheKey: () => "test-provider-hook-cache-key",
|
||||
},
|
||||
|
||||
@@ -88,6 +88,7 @@ export function createSanitizeSessionHistoryProviderHookRuntimeMock(
|
||||
extra: Record<string, unknown> = {},
|
||||
) {
|
||||
return {
|
||||
clearProviderRuntimePluginCacheForTest: vi.fn(),
|
||||
resolveProviderRuntimePlugin: vi.fn(() => undefined),
|
||||
resolveProviderHookPlugin: vi.fn(() => undefined),
|
||||
resolveProviderPluginsForHooks: vi.fn(() => []),
|
||||
|
||||
@@ -29,6 +29,7 @@ vi.mock("./pi-embedded-helpers.js", async () => ({
|
||||
}));
|
||||
|
||||
vi.mock("../plugins/provider-hook-runtime.js", async () => ({
|
||||
clearProviderRuntimePluginCacheForTest: vi.fn(),
|
||||
testing: {},
|
||||
prepareProviderExtraParams: vi.fn(() => undefined),
|
||||
resolveProviderHookPlugin: vi.fn(() => undefined),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { getGlobalHookRunner } from "../plugins/hook-runner-global.js";
|
||||
import type { SubagentRunOutcome } from "./subagent-announce-output.js";
|
||||
import {
|
||||
@@ -10,6 +11,8 @@ import {
|
||||
} from "./subagent-lifecycle-events.js";
|
||||
import type { SubagentRunRecord } from "./subagent-registry.types.js";
|
||||
|
||||
const log = createSubsystemLogger("agents/subagent-registry-completion");
|
||||
|
||||
export function runOutcomesEqual(
|
||||
a: SubagentRunOutcome | undefined,
|
||||
b: SubagentRunOutcome | undefined,
|
||||
@@ -113,7 +116,10 @@ export async function emitSubagentEndedHookOnce(params: {
|
||||
params.entry.endedHookEmittedAt = Date.now();
|
||||
params.persist();
|
||||
return true;
|
||||
} catch {
|
||||
} catch (err) {
|
||||
log.warn(
|
||||
`failed to emit subagent_ended hook for run ${runId}: ${err instanceof Error ? err.message : String(err)}`,
|
||||
);
|
||||
return false;
|
||||
} finally {
|
||||
params.inFlightRunIds.delete(runId);
|
||||
|
||||
@@ -646,8 +646,10 @@ function restoreSubagentRunsOnce() {
|
||||
// Cold-start restore path: queue the same recovery pass that restart
|
||||
// startup also uses so resumed children are handled through one seam.
|
||||
scheduleSubagentOrphanRecovery();
|
||||
} catch {
|
||||
// ignore restore failures
|
||||
} catch (err) {
|
||||
log.warn(
|
||||
`failed to restore subagent runs from disk: ${err instanceof Error ? err.message : String(err)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user