mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 05:30:42 +00:00
fix(active-memory): gracefully degrade on timeout instead of failing entire reply. Fixes #66849
This commit is contained in:
committed by
Peter Steinberger
parent
8a2d7f2541
commit
3f90d92667
@@ -1147,6 +1147,27 @@ describe("active-memory plugin", () => {
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it("returns undefined instead of throwing when an unexpected error escapes the recall path", async () => {
|
||||
runEmbeddedPiAgent.mockRejectedValueOnce(new Error("network reset"));
|
||||
hoisted.updateSessionStore.mockRejectedValueOnce(new Error("store unavailable"));
|
||||
|
||||
const result = await hooks.before_prompt_build(
|
||||
{ prompt: "what should i eat? escape test", messages: [] },
|
||||
{
|
||||
agentId: "main",
|
||||
trigger: "user",
|
||||
sessionKey: "agent:main:escape-test",
|
||||
messageProvider: "webchat",
|
||||
},
|
||||
);
|
||||
|
||||
expect(result).toBeUndefined();
|
||||
const warnLines = vi
|
||||
.mocked(api.logger.warn)
|
||||
.mock.calls.map((call: unknown[]) => String(call[0]));
|
||||
expect(warnLines.some((line: string) => line.includes("before_prompt_build"))).toBe(true);
|
||||
});
|
||||
|
||||
it("honors configured timeoutMs values above the former 60 000 ms ceiling", async () => {
|
||||
api.pluginConfig = {
|
||||
agents: ["main"],
|
||||
|
||||
@@ -1958,83 +1958,93 @@ export default definePluginEntry({
|
||||
});
|
||||
|
||||
api.on("before_prompt_build", async (event, ctx) => {
|
||||
const resolvedAgentId = resolveStatusUpdateAgentId(ctx);
|
||||
const resolvedSessionKey =
|
||||
ctx.sessionKey?.trim() ||
|
||||
(resolvedAgentId
|
||||
? resolveCanonicalSessionKeyFromSessionId({
|
||||
api,
|
||||
agentId: resolvedAgentId,
|
||||
sessionId: ctx.sessionId,
|
||||
})
|
||||
: undefined);
|
||||
const effectiveAgentId =
|
||||
resolvedAgentId || resolveStatusUpdateAgentId({ sessionKey: resolvedSessionKey });
|
||||
if (await isSessionActiveMemoryDisabled({ api, sessionKey: resolvedSessionKey })) {
|
||||
await persistPluginStatusLines({
|
||||
try {
|
||||
const resolvedAgentId = resolveStatusUpdateAgentId(ctx);
|
||||
const resolvedSessionKey =
|
||||
ctx.sessionKey?.trim() ||
|
||||
(resolvedAgentId
|
||||
? resolveCanonicalSessionKeyFromSessionId({
|
||||
api,
|
||||
agentId: resolvedAgentId,
|
||||
sessionId: ctx.sessionId,
|
||||
})
|
||||
: undefined);
|
||||
const effectiveAgentId =
|
||||
resolvedAgentId || resolveStatusUpdateAgentId({ sessionKey: resolvedSessionKey });
|
||||
if (await isSessionActiveMemoryDisabled({ api, sessionKey: resolvedSessionKey })) {
|
||||
await persistPluginStatusLines({
|
||||
api,
|
||||
agentId: effectiveAgentId,
|
||||
sessionKey: resolvedSessionKey,
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
if (!isEnabledForAgent(config, effectiveAgentId)) {
|
||||
await persistPluginStatusLines({
|
||||
api,
|
||||
agentId: effectiveAgentId,
|
||||
sessionKey: resolvedSessionKey,
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
if (!isEligibleInteractiveSession(ctx)) {
|
||||
await persistPluginStatusLines({
|
||||
api,
|
||||
agentId: effectiveAgentId,
|
||||
sessionKey: resolvedSessionKey,
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
if (
|
||||
!isAllowedChatType(config, {
|
||||
...ctx,
|
||||
sessionKey: resolvedSessionKey ?? ctx.sessionKey,
|
||||
mainKey: api.config.session?.mainKey,
|
||||
})
|
||||
) {
|
||||
await persistPluginStatusLines({
|
||||
api,
|
||||
agentId: effectiveAgentId,
|
||||
sessionKey: resolvedSessionKey,
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
const query = buildQuery({
|
||||
latestUserMessage: event.prompt,
|
||||
recentTurns: extractRecentTurns(event.messages),
|
||||
config,
|
||||
});
|
||||
const result = await maybeResolveActiveRecall({
|
||||
api,
|
||||
config,
|
||||
agentId: effectiveAgentId,
|
||||
sessionKey: resolvedSessionKey,
|
||||
sessionId: ctx.sessionId,
|
||||
messageProvider: ctx.messageProvider,
|
||||
channelId: ctx.channelId,
|
||||
query,
|
||||
currentModelProviderId: ctx.modelProviderId,
|
||||
currentModelId: ctx.modelId,
|
||||
});
|
||||
if (!result.summary) {
|
||||
return undefined;
|
||||
}
|
||||
const promptPrefix = buildPromptPrefix(result.summary);
|
||||
if (!promptPrefix) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
prependContext: promptPrefix,
|
||||
};
|
||||
} catch (error) {
|
||||
const message = toSingleLineLogValue(
|
||||
error instanceof Error ? error.message : String(error),
|
||||
);
|
||||
api.logger.warn?.(
|
||||
`active-memory: before_prompt_build failed, skipping memory lookup: ${message}`,
|
||||
);
|
||||
return undefined;
|
||||
}
|
||||
if (!isEnabledForAgent(config, effectiveAgentId)) {
|
||||
await persistPluginStatusLines({
|
||||
api,
|
||||
agentId: effectiveAgentId,
|
||||
sessionKey: resolvedSessionKey,
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
if (!isEligibleInteractiveSession(ctx)) {
|
||||
await persistPluginStatusLines({
|
||||
api,
|
||||
agentId: effectiveAgentId,
|
||||
sessionKey: resolvedSessionKey,
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
if (
|
||||
!isAllowedChatType(config, {
|
||||
...ctx,
|
||||
sessionKey: resolvedSessionKey ?? ctx.sessionKey,
|
||||
mainKey: api.config.session?.mainKey,
|
||||
})
|
||||
) {
|
||||
await persistPluginStatusLines({
|
||||
api,
|
||||
agentId: effectiveAgentId,
|
||||
sessionKey: resolvedSessionKey,
|
||||
});
|
||||
return undefined;
|
||||
}
|
||||
const query = buildQuery({
|
||||
latestUserMessage: event.prompt,
|
||||
recentTurns: extractRecentTurns(event.messages),
|
||||
config,
|
||||
});
|
||||
const result = await maybeResolveActiveRecall({
|
||||
api,
|
||||
config,
|
||||
agentId: effectiveAgentId,
|
||||
sessionKey: resolvedSessionKey,
|
||||
sessionId: ctx.sessionId,
|
||||
messageProvider: ctx.messageProvider,
|
||||
channelId: ctx.channelId,
|
||||
query,
|
||||
currentModelProviderId: ctx.modelProviderId,
|
||||
currentModelId: ctx.modelId,
|
||||
});
|
||||
if (!result.summary) {
|
||||
return undefined;
|
||||
}
|
||||
const promptPrefix = buildPromptPrefix(result.summary);
|
||||
if (!promptPrefix) {
|
||||
return undefined;
|
||||
}
|
||||
return {
|
||||
prependContext: promptPrefix,
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user