mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-21 09:34:59 +00:00
Agents/Subagents: preserve threadId in nested announce injections
This commit is contained in:
@@ -31,6 +31,7 @@ Docs: https://docs.openclaw.ai
|
||||
|
||||
### Fixes
|
||||
|
||||
- Agents/Subagents: preserve `threadId` on internal nested subagent announce injections (`deliver: false`) so parent orchestrators keep root thread context when relaying completion updates. (#22118)
|
||||
- Slack/Threading: sessions: keep parent-session forking and thread-history context active beyond first turn by removing first-turn-only gates in session init, thread-history fetch, and reply prompt context injection. (#23843, #23090) Thanks @vincentkoc and @Taskle.
|
||||
- Slack/Threading: respect `replyToMode` when Slack auto-populates top-level `thread_ts`, and ignore inline `replyToId` directive tags when `replyToMode` is `off` so thread forcing stays disabled unless explicitly configured. (#23839, #23320, #23513) Thanks @vincentkoc and @dorukardahan.
|
||||
- Slack/Extension: forward `message read` `threadId` to `readMessages` and use delivery-context `threadId` as outbound `thread_ts` fallback so extension replies/reads stay in the correct Slack thread. (#22216, #22485, #23836) Thanks @vincentkoc, @lan17 and @dorukardahan.
|
||||
|
||||
@@ -1130,7 +1130,7 @@ describe("subagent announce formatting", () => {
|
||||
childRunId: "run-worker-queued",
|
||||
requesterSessionKey: "agent:main:subagent:orchestrator",
|
||||
requesterDisplayKey: "agent:main:subagent:orchestrator",
|
||||
requesterOrigin: { channel: "whatsapp", to: "+1555", accountId: "acct" },
|
||||
requesterOrigin: { channel: "whatsapp", to: "+1555", accountId: "acct", threadId: "777" },
|
||||
...defaultOutcomeAnnounce,
|
||||
});
|
||||
|
||||
@@ -1142,6 +1142,7 @@ describe("subagent announce formatting", () => {
|
||||
expect(call?.params?.deliver).toBe(false);
|
||||
expect(call?.params?.channel).toBeUndefined();
|
||||
expect(call?.params?.to).toBeUndefined();
|
||||
expect(call?.params?.threadId).toBe("777");
|
||||
});
|
||||
|
||||
it.each([
|
||||
@@ -1278,7 +1279,12 @@ describe("subagent announce formatting", () => {
|
||||
childSessionKey: "agent:main:subagent:worker",
|
||||
childRunId: "run-worker",
|
||||
requesterSessionKey: "agent:main:subagent:orchestrator",
|
||||
requesterOrigin: { channel: "whatsapp", accountId: "acct-123", to: "+1555" },
|
||||
requesterOrigin: {
|
||||
channel: "whatsapp",
|
||||
accountId: "acct-123",
|
||||
to: "+1555",
|
||||
threadId: "thread-1",
|
||||
},
|
||||
requesterDisplayKey: "agent:main:subagent:orchestrator",
|
||||
...defaultOutcomeAnnounce,
|
||||
});
|
||||
@@ -1289,6 +1295,7 @@ describe("subagent announce formatting", () => {
|
||||
expect(call?.params?.deliver).toBe(false);
|
||||
expect(call?.params?.channel).toBeUndefined();
|
||||
expect(call?.params?.to).toBeUndefined();
|
||||
expect(call?.params?.threadId).toBe("thread-1");
|
||||
});
|
||||
|
||||
it("keeps completion-mode announce internal for nested requester subagent sessions", async () => {
|
||||
@@ -1299,7 +1306,12 @@ describe("subagent announce formatting", () => {
|
||||
childSessionKey: "agent:main:subagent:orchestrator:subagent:worker",
|
||||
childRunId: "run-worker-nested-completion",
|
||||
requesterSessionKey: "agent:main:subagent:orchestrator",
|
||||
requesterOrigin: { channel: "whatsapp", accountId: "acct-123", to: "+1555" },
|
||||
requesterOrigin: {
|
||||
channel: "whatsapp",
|
||||
accountId: "acct-123",
|
||||
to: "+1555",
|
||||
threadId: "thread-2",
|
||||
},
|
||||
requesterDisplayKey: "agent:main:subagent:orchestrator",
|
||||
expectsCompletionMessage: true,
|
||||
...defaultOutcomeAnnounce,
|
||||
@@ -1312,6 +1324,7 @@ describe("subagent announce formatting", () => {
|
||||
expect(call?.params?.deliver).toBe(false);
|
||||
expect(call?.params?.channel).toBeUndefined();
|
||||
expect(call?.params?.to).toBeUndefined();
|
||||
expect(call?.params?.threadId).toBe("thread-2");
|
||||
const message = typeof call?.params?.message === "string" ? call.params.message : "";
|
||||
expect(message).toContain(
|
||||
"Convert this completion into a concise internal orchestration update for your parent agent",
|
||||
|
||||
@@ -490,7 +490,9 @@ async function sendAnnounce(item: AnnounceQueueItem) {
|
||||
channel: requesterIsSubagent ? undefined : origin?.channel,
|
||||
accountId: requesterIsSubagent ? undefined : origin?.accountId,
|
||||
to: requesterIsSubagent ? undefined : origin?.to,
|
||||
threadId: requesterIsSubagent ? undefined : threadId,
|
||||
// Keep thread context on internal nested announce injections so parent
|
||||
// orchestrators can continue thread-aware delivery after processing.
|
||||
threadId,
|
||||
deliver: !requesterIsSubagent,
|
||||
idempotencyKey,
|
||||
},
|
||||
@@ -713,7 +715,9 @@ async function sendSubagentAnnounceDirectly(params: {
|
||||
channel: params.requesterIsSubagent ? undefined : directOrigin?.channel,
|
||||
accountId: params.requesterIsSubagent ? undefined : directOrigin?.accountId,
|
||||
to: params.requesterIsSubagent ? undefined : directOrigin?.to,
|
||||
threadId: params.requesterIsSubagent ? undefined : threadId,
|
||||
// Preserve root thread context even when we intentionally keep nested
|
||||
// announce delivery internal (`deliver=false`).
|
||||
threadId,
|
||||
idempotencyKey: params.directIdempotencyKey,
|
||||
},
|
||||
expectFinal: true,
|
||||
|
||||
Reference in New Issue
Block a user