mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 10:40:43 +00:00
fix(channels): clear stale terminal status reactions
This commit is contained in:
@@ -16,6 +16,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Compaction: use the active session model fallback chain for implicit summarization failures without persisting fallback model selection, so Azure content-filter 400s can recover. Fixes #64960. (#74470) Thanks @jalehman and @OpenCodeEngineer.
|
||||
- Gateway/config: allow `gateway config.patch` to update documented subagent thinking defaults. Fixes #75764. (#75802) Thanks @kAIborg24.
|
||||
- Plugins/CLI: keep git plugin install paths credential-free, preserve existing git checkouts until replacement succeeds, honor duplicate npm install mode, and remove managed git repos on uninstall. Thanks @vincentkoc.
|
||||
- Channels/status reactions: remove stale non-terminal lifecycle reactions when a run reaches done or error, so Discord does not leave a permanent thinking emoji after completion. Fixes #75458. Thanks @davelutztx.
|
||||
|
||||
## 2026.4.30
|
||||
|
||||
|
||||
@@ -65,7 +65,8 @@ describe("Slack status reaction lifecycle", () => {
|
||||
|
||||
await ctrl.setDone();
|
||||
expect(active.has(DEFAULT_EMOJIS.done)).toBe(true);
|
||||
expect(active.has(DEFAULT_EMOJIS.web)).toBe(true);
|
||||
expect(active.has(DEFAULT_EMOJIS.web)).toBe(false);
|
||||
expect(active.has(DEFAULT_EMOJIS.thinking)).toBe(false);
|
||||
|
||||
await ctrl.clear();
|
||||
expect(active.size).toBe(0);
|
||||
@@ -87,7 +88,7 @@ describe("Slack status reaction lifecycle", () => {
|
||||
|
||||
await ctrl.setError();
|
||||
expect(active.has(DEFAULT_EMOJIS.error)).toBe(true);
|
||||
expect(active.has("eyes")).toBe(true);
|
||||
expect(active.has("eyes")).toBe(false);
|
||||
|
||||
await ctrl.restoreInitial();
|
||||
expect(active.has("eyes")).toBe(true);
|
||||
@@ -156,7 +157,8 @@ describe("Slack status reaction lifecycle", () => {
|
||||
|
||||
expect(active.has("eyes")).toBe(true);
|
||||
expect(active.has(DEFAULT_EMOJIS.done)).toBe(false);
|
||||
expect(adapter.removeReaction).toHaveBeenCalledTimes(1);
|
||||
expect(adapter.removeReaction).toHaveBeenCalledTimes(2);
|
||||
expect(adapter.removeReaction).toHaveBeenCalledWith("eyes");
|
||||
expect(adapter.removeReaction).toHaveBeenCalledWith(DEFAULT_EMOJIS.done);
|
||||
expect(adapter.removeReaction).not.toHaveBeenCalledWith(DEFAULT_EMOJIS.thinking);
|
||||
});
|
||||
|
||||
@@ -294,6 +294,39 @@ describe("createStatusReactionController", () => {
|
||||
expect(calls).toContainEqual({ method: "remove", emoji: DEFAULT_EMOJIS.thinking });
|
||||
});
|
||||
|
||||
it("should remove tracked non-terminal emojis when setting done", async () => {
|
||||
const { calls, controller } = createEnabledController();
|
||||
|
||||
void controller.setQueued();
|
||||
await vi.runAllTimersAsync();
|
||||
void controller.setThinking();
|
||||
await vi.advanceTimersByTimeAsync(DEFAULT_TIMING.debounceMs);
|
||||
void controller.setTool("exec");
|
||||
await vi.advanceTimersByTimeAsync(DEFAULT_TIMING.debounceMs);
|
||||
|
||||
await controller.setDone();
|
||||
|
||||
const removeEmojis = calls.filter((call) => call.method === "remove").map((call) => call.emoji);
|
||||
expect(removeEmojis).toEqual(
|
||||
expect.arrayContaining(["👀", DEFAULT_EMOJIS.thinking, DEFAULT_EMOJIS.coding]),
|
||||
);
|
||||
expect(removeEmojis).not.toContain(DEFAULT_EMOJIS.done);
|
||||
});
|
||||
|
||||
it("should not remove reactions on terminal state when adapter lacks removeReaction", async () => {
|
||||
const { calls, controller } = createSetOnlyController();
|
||||
|
||||
void controller.setThinking();
|
||||
await vi.advanceTimersByTimeAsync(DEFAULT_TIMING.debounceMs);
|
||||
|
||||
await controller.setDone();
|
||||
|
||||
expect(calls).toEqual([
|
||||
{ method: "set", emoji: DEFAULT_EMOJIS.thinking },
|
||||
{ method: "set", emoji: DEFAULT_EMOJIS.done },
|
||||
]);
|
||||
});
|
||||
|
||||
it("should not re-add an already active reaction when returning to it", async () => {
|
||||
const { calls, controller } = createEnabledController();
|
||||
|
||||
|
||||
@@ -341,6 +341,7 @@ export function createStatusReactionController(params: {
|
||||
// Directly enqueue to ensure we return the updated promise
|
||||
return enqueue(async () => {
|
||||
await applyEmoji(emoji);
|
||||
await removeActiveEmojis({ keepEmoji: emoji });
|
||||
pendingEmoji = "";
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user