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 61b6f3d91ba0..de59e1d4414c 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 @@ -801,6 +801,40 @@ describe("handleInlineActions", () => { expect(handleCommandsMock).not.toHaveBeenCalled(); }); + it("keeps inline skill markers literal when command interpretation is suppressed", async () => { + const typing = createTypingController(); + const body = "Please use /office_hours: to build me a deployment plan"; + const ctx = buildTestCtx({ + Body: body, + CommandBody: body, + Provider: "webchat", + Surface: "webchat", + CommandInterpretationSuppressed: true, + }); + + const result = await handleInlineActions( + createHandleInlineActionsInput({ + ctx, + typing, + cleanedBody: body, + command: { + isAuthorizedSender: true, + rawBodyNormalized: body, + commandBodyNormalized: body, + }, + overrides: { + allowTextCommands: true, + cfg: { commands: { text: true } }, + skillCommands: officeHoursSkillCommands(), + }, + }), + ); + + expect(result).toMatchObject({ kind: "continue", cleanedBody: body }); + expect(ctx.Body).toBe(body); + expect(handleCommandsMock).not.toHaveBeenCalled(); + }); + it("preserves slash commands inside an inline skill payload", async () => { const typing = createTypingController(); const body = "/office_hours: compare /help and /commands with /status"; diff --git a/src/auto-reply/reply/get-reply-inline-actions.ts b/src/auto-reply/reply/get-reply-inline-actions.ts index 8a860bb15263..a490d9dc3cd2 100644 --- a/src/auto-reply/reply/get-reply-inline-actions.ts +++ b/src/auto-reply/reply/get-reply-inline-actions.ts @@ -338,13 +338,13 @@ export async function handleInlineActions(params: { const canUseInlineSkills = command.isAuthorizedSender && ctx.Surface === INTERNAL_MESSAGE_CHANNEL; const hasInlineSkillCandidate = canUseInlineSkills && + !ctx.CommandInterpretationSuppressed && listColonMarkedInlineSkillNames(command.commandBodyNormalized).some(isPotentialInlineSkillName); const shouldLoadSkillCommands = allowTextCommands && (hasSkillReferences || hasSkillSlashCandidate || hasInlineSkillCandidate); - const canReusePreloadedSkillCommands = execOverrides === undefined; const skillCommands = shouldLoadSkillCommands && - canReusePreloadedSkillCommands && + execOverrides === undefined && params.skillCommands && params.skillCommands.length > 0 ? params.skillCommands @@ -381,7 +381,7 @@ export async function handleInlineActions(params: { skillCommands, }) : null; - if (!skillInvocation && allowTextCommands && canUseInlineSkills && skillCommands.length > 0) { + if (!skillInvocation && allowTextCommands && hasInlineSkillCandidate && skillCommands.length) { skillInvocation = resolveInlineSkillCommandInvocation({ commandBodyNormalized: command.commandBodyNormalized, skillCommands,