fix: keep reset authorization through delivery

This commit is contained in:
Shakker
2026-08-02 14:56:44 +01:00
parent 82a5368bbc
commit dc5e877d20
3 changed files with 26 additions and 18 deletions
+14 -15
View File
@@ -305,6 +305,10 @@ async function drainStoredChatOutbox(
}
syncVisibleChatQueueProjection(host);
if (item.localCommandName === "reset") {
if ((item.sendAttempts ?? 0) > 0 || item.sendRequestStartedAtMs !== undefined) {
setCommandState("unconfirmed", UNCONFIRMED_CHAT_SEND_ERROR);
return "blocked";
}
const resetTarget = captureChatCommandTarget(host);
if (!resetTarget) {
setCommandState("failed", "The Gateway connection changed. Retry the command.");
@@ -316,25 +320,12 @@ async function drainStoredChatOutbox(
dependencies.setChatError(host, initialAccess.reason);
return "blocked";
}
const resetText = item.localCommandArgs ? `/reset ${item.localCommandArgs}` : "/reset";
const convertResetToMessage = (sendState?: ChatQueueItem["sendState"]) =>
updateQueuedMessageForSession(host, outbox.sessionKey, item.id, (entry) => ({
...entry,
localCommandArgs: undefined,
localCommandName: undefined,
refreshSessions: true,
text: resetText,
...(sendState ? { sendState } : {}),
}));
const confirmation = await confirmConversationResetForCurrentSession(host, {
sessionKey: outbox.sessionKey,
...(outbox.agentId ? { agentId: outbox.agentId } : {}),
});
if (confirmation === "deferred") {
const approvedDuringRun =
visibleSessionMatches(host, outbox.sessionKey, outbox.agentId) && host.chatRunId;
const deferCommand = approvedDuringRun ? convertResetToMessage : setCommandState;
deferCommand("waiting-idle");
setCommandState("waiting-idle");
return "blocked";
}
if (confirmation === "cancelled") {
@@ -353,7 +344,15 @@ async function drainStoredChatOutbox(
...lane.pendingOptions.get(item.id),
target: resetTarget,
});
if (!convertResetToMessage()) {
const result = await dependencies.sendQueuedChatMessage(
host,
item.id,
lane.pendingOptions.get(item.id),
outbox.sessionKey,
);
lane.outcomes.set(item.id, result);
lane.pendingOptions.delete(item.id);
if (result !== "sent") {
return "blocked";
}
continue;
+10 -1
View File
@@ -186,7 +186,8 @@ async function sendQueuedChatMessage(
): Promise<QueuedChatSendResult> {
const storageMode = options?.storageMode ?? "durable";
const queued = readQueuedMessageById(host, id);
if (!queued || queued.pendingRunId || queued.localCommandName) {
const approvedReset = queued?.localCommandName === "reset" && Boolean(options?.target);
if (!queued || queued.pendingRunId || (queued.localCommandName && !approvedReset)) {
return "failed";
}
const queueSessionKey = queued.sessionKey ?? queuedSessionKey;
@@ -248,6 +249,13 @@ async function sendQueuedChatMessage(
setChatError(host, OFFLINE_QUEUE_STORAGE_ERROR);
return prepared;
}
if (approvedReset) {
prepared = {
...prepared,
refreshSessions: true,
text: prepared.localCommandArgs ? `/reset ${prepared.localCommandArgs}` : "/reset",
};
}
const message = prepared.text.trim();
const attachments = prepared.attachments ?? [];
if (!message && attachments.length === 0) {
@@ -717,6 +725,7 @@ async function sendResetSlashCommand(
previousDraft: options.previousDraft,
restoreDraft: options.restoreDraft,
routingSessionKey: host.sessionKey,
target: options.target,
});
}
+2 -2
View File
@@ -4317,16 +4317,16 @@ describe("handleSendChat", () => {
expect(approvedReset).toEqual(
expect.objectContaining({
id: item.id,
localCommandName: "reset",
sendState: "waiting-idle",
text: "/reset",
}),
);
expect(approvedReset).not.toHaveProperty("localCommandName");
host.chatRunId = null;
await retryReconnectableQueuedChatSends(host);
expect(confirmConversationReset).toHaveBeenCalledOnce();
expect(confirmConversationReset).toHaveBeenCalledTimes(2);
expect(sendPayloads.map((payload) => payload.message)).toEqual(["/reset"]);
expect(listStoredChatOutboxes(host)).toStrictEqual([]);
});