fix: fast-lane directives bypass queue dedupe
This commit is contained in:
@@ -708,6 +708,9 @@ export async function getReplyFromConfig(
|
|||||||
const inlineStatusRequested =
|
const inlineStatusRequested =
|
||||||
hasInlineStatus && allowTextCommands && command.isAuthorizedSender;
|
hasInlineStatus && allowTextCommands && command.isAuthorizedSender;
|
||||||
|
|
||||||
|
// Inline control directives should apply immediately, even when mixed with text.
|
||||||
|
let directiveAck: ReplyPayload | undefined;
|
||||||
|
|
||||||
if (!command.isAuthorizedSender) {
|
if (!command.isAuthorizedSender) {
|
||||||
directives = {
|
directives = {
|
||||||
...directives,
|
...directives,
|
||||||
@@ -851,6 +854,77 @@ export async function getReplyFromConfig(
|
|||||||
await opts.onBlockReply(reply);
|
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 =
|
const inlineCommand =
|
||||||
allowTextCommands && command.isAuthorizedSender
|
allowTextCommands && command.isAuthorizedSender
|
||||||
? extractInlineSimpleCommand(cleanedBody)
|
? extractInlineSimpleCommand(cleanedBody)
|
||||||
@@ -930,6 +1004,10 @@ export async function getReplyFromConfig(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (directiveAck) {
|
||||||
|
await sendInlineReply(directiveAck);
|
||||||
|
}
|
||||||
|
|
||||||
const isEmptyConfig = Object.keys(cfg).length === 0;
|
const isEmptyConfig = Object.keys(cfg).length === 0;
|
||||||
const skipWhenConfigEmpty = command.providerId
|
const skipWhenConfigEmpty = command.providerId
|
||||||
? Boolean(
|
? Boolean(
|
||||||
|
|||||||
@@ -117,7 +117,7 @@ describe("followup queue deduplication", () => {
|
|||||||
);
|
);
|
||||||
expect(first).toBe(true);
|
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(
|
const second = enqueueFollowupRun(
|
||||||
key,
|
key,
|
||||||
createRun({
|
createRun({
|
||||||
@@ -127,7 +127,7 @@ describe("followup queue deduplication", () => {
|
|||||||
}),
|
}),
|
||||||
settings,
|
settings,
|
||||||
);
|
);
|
||||||
expect(second).toBe(false);
|
expect(second).toBe(true);
|
||||||
|
|
||||||
// Third enqueue with different prompt should succeed
|
// Third enqueue with different prompt should succeed
|
||||||
const third = enqueueFollowupRun(
|
const third = enqueueFollowupRun(
|
||||||
|
|||||||
@@ -358,9 +358,9 @@ function isRunAlreadyQueued(
|
|||||||
(item) => item.messageId?.trim() === messageId && hasSameRouting(item),
|
(item) => item.messageId?.trim() === messageId && hasSameRouting(item),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return queue.items.some(
|
// Without a provider message id, avoid prompt-based dedupe to ensure rapid
|
||||||
(item) => item.prompt === run.prompt && hasSameRouting(item),
|
// directive messages are not dropped.
|
||||||
);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function enqueueFollowupRun(
|
export function enqueueFollowupRun(
|
||||||
|
|||||||
Reference in New Issue
Block a user