fix: fast-lane directives bypass queue dedupe

This commit is contained in:
Peter Steinberger
2026-01-12 21:44:09 +00:00
parent 42c17adb5e
commit 99fea64823
3 changed files with 83 additions and 5 deletions

View File

@@ -708,6 +708,9 @@ export async function getReplyFromConfig(
const inlineStatusRequested =
hasInlineStatus && allowTextCommands && command.isAuthorizedSender;
// Inline control directives should apply immediately, even when mixed with text.
let directiveAck: ReplyPayload | undefined;
if (!command.isAuthorizedSender) {
directives = {
...directives,
@@ -851,6 +854,77 @@ export async function getReplyFromConfig(
await opts.onBlockReply(reply);
};
const hasAnyDirective =
directives.hasThinkDirective ||
directives.hasVerboseDirective ||
directives.hasReasoningDirective ||
directives.hasElevatedDirective ||
directives.hasModelDirective ||
directives.hasQueueDirective ||
directives.hasStatusDirective;
if (
hasAnyDirective &&
command.isAuthorizedSender &&
!isDirectiveOnly({
directives,
cleanedBody: directives.cleaned,
ctx,
cfg,
agentId,
isGroup,
})
) {
const resolvedDefaultThinkLevel =
(sessionEntry?.thinkingLevel as ThinkLevel | undefined) ??
(agentCfg?.thinkingDefault as ThinkLevel | undefined) ??
(await modelState.resolveDefaultThinkingLevel());
const currentThinkLevel = resolvedDefaultThinkLevel;
const currentVerboseLevel =
(sessionEntry?.verboseLevel as VerboseLevel | undefined) ??
(agentCfg?.verboseDefault as VerboseLevel | undefined);
const currentReasoningLevel =
(sessionEntry?.reasoningLevel as ReasoningLevel | undefined) ?? "off";
const currentElevatedLevel =
(sessionEntry?.elevatedLevel as ElevatedLevel | undefined) ??
(agentCfg?.elevatedDefault as ElevatedLevel | undefined);
directiveAck = await handleDirectiveOnly({
cfg,
directives,
sessionEntry,
sessionStore,
sessionKey,
storePath,
elevatedEnabled,
elevatedAllowed,
elevatedFailures,
messageProviderKey,
defaultProvider,
defaultModel,
aliasIndex,
allowedModelKeys: modelState.allowedModelKeys,
allowedModelCatalog: modelState.allowedModelCatalog,
resetModelOverride: modelState.resetModelOverride,
provider,
model,
initialModelLabel,
formatModelSwitchEvent,
currentThinkLevel,
currentVerboseLevel,
currentReasoningLevel,
currentElevatedLevel,
});
// Refresh provider/model from session overrides applied by directives.
if (sessionEntry?.providerOverride) {
provider = sessionEntry.providerOverride;
}
if (sessionEntry?.modelOverride) {
model = sessionEntry.modelOverride;
}
}
const inlineCommand =
allowTextCommands && command.isAuthorizedSender
? extractInlineSimpleCommand(cleanedBody)
@@ -930,6 +1004,10 @@ export async function getReplyFromConfig(
}
}
if (directiveAck) {
await sendInlineReply(directiveAck);
}
const isEmptyConfig = Object.keys(cfg).length === 0;
const skipWhenConfigEmpty = command.providerId
? Boolean(

View File

@@ -117,7 +117,7 @@ describe("followup queue deduplication", () => {
);
expect(first).toBe(true);
// Second enqueue with same prompt should be deduplicated
// Second enqueue with same prompt should be allowed (we only dedupe with message id)
const second = enqueueFollowupRun(
key,
createRun({
@@ -127,7 +127,7 @@ describe("followup queue deduplication", () => {
}),
settings,
);
expect(second).toBe(false);
expect(second).toBe(true);
// Third enqueue with different prompt should succeed
const third = enqueueFollowupRun(

View File

@@ -358,9 +358,9 @@ function isRunAlreadyQueued(
(item) => item.messageId?.trim() === messageId && hasSameRouting(item),
);
}
return queue.items.some(
(item) => item.prompt === run.prompt && hasSameRouting(item),
);
// Without a provider message id, avoid prompt-based dedupe to ensure rapid
// directive messages are not dropped.
return false;
}
export function enqueueFollowupRun(