From 84fb20aa52105dc861378adfcd773b02a2c2c4bd Mon Sep 17 00:00:00 2001 From: Tak Hoffman <781889+Takhoffman@users.noreply.github.com> Date: Fri, 10 Apr 2026 21:08:02 -0500 Subject: [PATCH] fix: prefer target entry for inline status --- .../reply/get-reply-directives-apply.ts | 5 +- ...ine-actions.skip-when-config-empty.test.ts | 50 +++++++++++++++++++ .../reply/get-reply-inline-actions.ts | 5 +- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/src/auto-reply/reply/get-reply-directives-apply.ts b/src/auto-reply/reply/get-reply-directives-apply.ts index ebeb6e17ce4..568e035abe2 100644 --- a/src/auto-reply/reply/get-reply-directives-apply.ts +++ b/src/auto-reply/reply/get-reply-directives-apply.ts @@ -241,12 +241,13 @@ export async function applyInlineDirectiveOverrides(params: { let statusReply: ReplyPayload | undefined; if (directives.hasStatusDirective && allowTextCommands && command.isAuthorizedSender) { const { buildStatusReply } = await loadCommandsStatus(); + const targetSessionEntry = sessionStore[sessionKey] ?? sessionEntry; statusReply = await buildStatusReply({ cfg, command, - sessionEntry, + sessionEntry: targetSessionEntry, sessionKey, - parentSessionKey: ctx.ParentSessionKey, + parentSessionKey: targetSessionEntry?.parentSessionKey ?? ctx.ParentSessionKey, sessionScope, storePath, provider, diff --git a/src/auto-reply/reply/get-reply-inline-actions.skip-when-config-empty.test.ts b/src/auto-reply/reply/get-reply-inline-actions.skip-when-config-empty.test.ts index d989d62447a..c84067767f3 100644 --- a/src/auto-reply/reply/get-reply-inline-actions.skip-when-config-empty.test.ts +++ b/src/auto-reply/reply/get-reply-inline-actions.skip-when-config-empty.test.ts @@ -259,6 +259,56 @@ describe("handleInlineActions", () => { expect(handleCommandsMock).not.toHaveBeenCalled(); }); + it("prefers the target session entry when routing inline status through the shared status builder", async () => { + const typing = createTypingController(); + const ctx = buildTestCtx({ + Body: "/status", + CommandBody: "/status", + ParentSessionKey: "ctx-parent", + }); + + const result = await handleInlineActions( + createHandleInlineActionsInput({ + ctx, + typing, + cleanedBody: stripInlineStatus("/status").cleaned, + command: { + isAuthorizedSender: true, + rawBodyNormalized: "/status", + commandBodyNormalized: "/status", + }, + overrides: { + allowTextCommands: true, + inlineStatusRequested: true, + sessionEntry: { + sessionId: "wrapper-session", + updatedAt: Date.now(), + parentSessionKey: "wrapper-parent", + } as SessionEntry, + sessionStore: { + "s:main": { + sessionId: "target-session", + updatedAt: Date.now(), + parentSessionKey: "target-parent", + } as SessionEntry, + }, + }, + }), + ); + + expect(result).toEqual({ kind: "reply", reply: undefined }); + expect(buildStatusReplyMock).toHaveBeenCalledWith( + expect.objectContaining({ + sessionEntry: expect.objectContaining({ + sessionId: "target-session", + parentSessionKey: "target-parent", + }), + parentSessionKey: "target-parent", + }), + ); + expect(handleCommandsMock).not.toHaveBeenCalled(); + }); + it("does not continue into the agent after a mention-wrapped inline status-only turn", async () => { const typing = createTypingController(); const ctx = buildTestCtx({ diff --git a/src/auto-reply/reply/get-reply-inline-actions.ts b/src/auto-reply/reply/get-reply-inline-actions.ts index ef6379ef671..034c6f6ee72 100644 --- a/src/auto-reply/reply/get-reply-inline-actions.ts +++ b/src/auto-reply/reply/get-reply-inline-actions.ts @@ -347,12 +347,13 @@ export async function handleInlineActions(params: { let didSendInlineStatus = false; if (handleInlineStatus) { const { buildStatusReply } = await import("./commands.runtime.js"); + const targetSessionEntry = sessionStore?.[sessionKey] ?? sessionEntry; const inlineStatusReply = await buildStatusReply({ cfg, command, - sessionEntry, + sessionEntry: targetSessionEntry, sessionKey, - parentSessionKey: ctx.ParentSessionKey, + parentSessionKey: targetSessionEntry?.parentSessionKey ?? ctx.ParentSessionKey, sessionScope, storePath, provider,