// HTTP callers must declare the same least-privilege operator scopes they // intend to use over WS so both transport surfaces enforce the same gate. const authResult = await authorizeScopedGatewayHttpRequestOrReply({
req,
res,
auth: opts.auth,
trustedProxies: opts.trustedProxies,
allowRealIpFallback: opts.allowRealIpFallback,
rateLimiter: opts.rateLimiter,
operatorMethod: "chat.history",
resolveOperatorScopes: resolveTrustedHttpOperatorScopes,
}); if (!authResult) { returntrue;
} const { cfg } = authResult;
const target = resolveGatewaySessionStoreTarget({ cfg, key: sessionKey }); const store = loadSessionStore(target.storePath); const entry = resolveFreshestSessionEntryFromStoreKeys(store, target.storeKeys); if (!entry?.sessionId) {
sendJson(res, 404, {
ok: false,
error: {
type: "not_found",
message: `Session not found: ${sessionKey}`,
},
}); returntrue;
} const limit = resolveLimit(req); const cursor = normalizeOptionalString(getRequestUrl(req).searchParams.get("cursor")); const effectiveMaxChars = typeof cfg.gateway?.webchat?.chatHistoryMaxChars === "number"
? cfg.gateway.webchat.chatHistoryMaxChars
: DEFAULT_CHAT_HISTORY_TEXT_MAX_CHARS; // Read the transcript once and derive both sanitized and raw views from the // same snapshot, eliminating the theoretical race window where a concurrent // write between two separate reads could cause seq/content divergence. const rawSnapshot = entry?.sessionId
? readSessionMessages(entry.sessionId, target.storePath, entry.sessionFile)
: []; const historySnapshot = buildSessionHistorySnapshot({
rawMessages: rawSnapshot,
maxChars: effectiveMaxChars,
limit,
cursor,
}); const history = historySnapshot.history;
let cleanedUp = false;
let streamQueue = Promise.resolve(); // Forward-declared so `cleanup` can reference them without relying on // Temporal-Dead-Zone leniency. A future refactor that wires the close event // listeners before the `setInterval` / `onSessionTranscriptUpdate` calls // would otherwise hit a `ReferenceError` on the first cleanup invocation.
let heartbeat: ReturnType<typeof setInterval> | undefined;
let unsubscribe: (() => void) | undefined;
const cleanup = () => { if (cleanedUp) { return;
}
cleanedUp = true; if (heartbeat) {
clearInterval(heartbeat);
} if (unsubscribe) {
unsubscribe();
}
};
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.