mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:10:44 +00:00
fix(heartbeat): classify untrusted exec completions
This commit is contained in:
@@ -347,7 +347,7 @@ describe("Ghost reminder bug (issue #13317)", () => {
|
||||
reason: "exec-event",
|
||||
target: "none",
|
||||
enqueue: (sessionKey) => {
|
||||
enqueueSystemEvent("exec finished: deploy succeeded", { sessionKey });
|
||||
enqueueSystemEvent("exec finished: deploy succeeded", { sessionKey, trusted: false });
|
||||
},
|
||||
});
|
||||
|
||||
@@ -358,6 +358,23 @@ describe("Ghost reminder bug (issue #13317)", () => {
|
||||
expect(sendTelegram).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("includes untrusted exec completion details in user-relay prompts", async () => {
|
||||
const { result, sendTelegram, calledCtx } = await runHeartbeatCase({
|
||||
tmpPrefix: "openclaw-exec-untrusted-relay-",
|
||||
replyText: "Deploy succeeded",
|
||||
reason: "exec-event",
|
||||
enqueue: (sessionKey) => {
|
||||
enqueueSystemEvent("exec finished: deploy succeeded", { sessionKey, trusted: false });
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.status).toBe("ran");
|
||||
expect(calledCtx?.Provider).toBe("exec-event");
|
||||
expect(calledCtx?.ForceSenderIsOwnerFalse).toBe(true);
|
||||
expect(calledCtx?.Body).toContain("exec finished: deploy succeeded");
|
||||
expect(sendTelegram).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("classifies hook:wake exec completions as exec-event prompts", async () => {
|
||||
const { result, sendTelegram, calledCtx } = await runHeartbeatCase({
|
||||
tmpPrefix: "openclaw-hook-exec-",
|
||||
|
||||
@@ -676,13 +676,12 @@ function resolveHeartbeatRunPrompt(params: {
|
||||
.map((event) => event.text);
|
||||
const execEvents = params.preflight.shouldInspectPendingEvents
|
||||
? pendingEventEntries
|
||||
.filter((event) => event.trusted !== false && isExecCompletionEvent(event.text))
|
||||
.filter((event) => isExecCompletionEvent(event.text))
|
||||
.map((event) => event.text)
|
||||
: [];
|
||||
const hasExecCompletion = execEvents.length > 0;
|
||||
const hasCronEvents = cronEvents.length > 0;
|
||||
|
||||
// If tasks are defined, build a batched prompt with due tasks
|
||||
if (params.preflight.tasks && params.preflight.tasks.length > 0) {
|
||||
const tasks = params.preflight.tasks;
|
||||
const dueTasks = tasks.filter((task) =>
|
||||
@@ -701,7 +700,6 @@ ${taskList}
|
||||
|
||||
After completing all due tasks, reply HEARTBEAT_OK.`;
|
||||
|
||||
// Preserve HEARTBEAT.md directives (non-task content)
|
||||
if (params.heartbeatFileContent) {
|
||||
const directives = params.heartbeatFileContent
|
||||
.replace(/^[\s\S]*?^tasks:[\s\S]*?(?=^[^\s]|^$)/m, "")
|
||||
@@ -712,11 +710,9 @@ After completing all due tasks, reply HEARTBEAT_OK.`;
|
||||
}
|
||||
return { prompt, hasExecCompletion: false, hasCronEvents: false };
|
||||
}
|
||||
// No tasks due - skip this heartbeat to avoid wasteful API calls
|
||||
return { prompt: null, hasExecCompletion: false, hasCronEvents: false };
|
||||
}
|
||||
|
||||
// Fallback to original behavior
|
||||
const basePrompt = hasExecCompletion
|
||||
? buildExecEventPrompt(execEvents, { deliverToUser: params.canRelayToUser })
|
||||
: hasCronEvents
|
||||
|
||||
Reference in New Issue
Block a user