const replyRunState = resolveGlobalSingleton<ReplyRunState>(REPLY_RUN_STATE_KEY, () => ({
activeRunsByKey: new Map<string, ReplyOperation>(),
activeSessionIdsByKey: new Map<string, string>(),
activeKeysBySessionId: new Map<string, string>(),
waitKeysBySessionId: new Map<string, string>(),
waitersByKey: new Map<string, Set<ReplyRunWaiter>>(),
}));
export class ReplyRunAlreadyActiveError extends Error {
constructor(sessionKey: string) { super(`Reply run already active for ${sessionKey}`); this.name = "ReplyRunAlreadyActiveError";
}
}
function createUserAbortError(): Error { const err = new Error("Reply operation aborted by user");
err.name = "AbortError"; return err;
}
function registerWaitSessionId(sessionKey: string, sessionId: string): void {
replyRunState.waitKeysBySessionId.set(sessionId, sessionKey);
}
function clearWaitSessionIds(sessionKey: string): void { for (const [sessionId, mappedKey] of replyRunState.waitKeysBySessionId) { if (mappedKey === sessionKey) {
replyRunState.waitKeysBySessionId.delete(sessionId);
}
}
}
function notifyReplyRunEnded(sessionKey: string): void { const waiters = replyRunState.waitersByKey.get(sessionKey); if (!waiters || waiters.size === 0) { return;
}
replyRunState.waitersByKey.delete(sessionKey); for (const waiter of waiters) {
clearTimeout(waiter.timer);
waiter.resolve(true);
}
}
function resolveReplyRunForCurrentSessionId(sessionId: string): ReplyOperation | undefined { const normalizedSessionId = normalizeOptionalString(sessionId); if (!normalizedSessionId) { return undefined;
} const sessionKey = replyRunState.activeKeysBySessionId.get(normalizedSessionId); if (!sessionKey) { return undefined;
} return replyRunState.activeRunsByKey.get(sessionKey);
}
export function createReplyOperation(params: {
sessionKey: string;
sessionId: string;
resetTriggered: boolean;
upstreamAbortSignal?: AbortSignal;
}): ReplyOperation { const sessionKey = normalizeOptionalString(params.sessionKey); const sessionId = normalizeOptionalString(params.sessionId); if (!sessionKey) { thrownew Error("Reply operations require a canonical sessionKey");
} if (!sessionId) { thrownew Error("Reply operations require a sessionId");
} if (replyRunState.activeRunsByKey.has(sessionKey)) { thrownew ReplyRunAlreadyActiveError(sessionKey);
}
const controller = new AbortController();
let currentSessionId = sessionId;
let phase: ReplyOperationPhase = "queued";
let result: ReplyOperationResult | null = null;
let stateCleared = false;
export function abortActiveReplyRuns(opts: { mode: "all" | "compacting" }): boolean {
let aborted = false; for (const operation of replyRunState.activeRunsByKey.values()) { if (opts.mode === "compacting" && !isReplyRunCompacting(operation)) { continue;
}
operation.abortForRestart();
aborted = true;
} return aborted;
}
export function getActiveReplyRunCount(): number { return replyRunState.activeRunsByKey.size;
}
export function listActiveReplyRunSessionIds(): string[] { return [...replyRunState.activeSessionIdsByKey.values()];
}
export const __testing = {
resetReplyRunRegistry(): void {
replyRunState.activeRunsByKey.clear();
replyRunState.activeSessionIdsByKey.clear();
replyRunState.activeKeysBySessionId.clear();
replyRunState.waitKeysBySessionId.clear(); for (const waiters of replyRunState.waitersByKey.values()) { for (const waiter of waiters) {
clearTimeout(waiter.timer);
waiter.resolve(false);
}
}
replyRunState.waitersByKey.clear();
},
};
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.24Bemerkung:
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.