Files
paseo/packages/app/src/utils/agent-initialization.ts
Mohamed Boudra a134132418 Fix app stream/timeline ordering desync and init lifecycle race (#73)
* fix(app): enforce canonical stream sequencing and init resolution

* refactor: extract timeline and stream reducers to pure functions
2026-02-23 19:30:48 +07:00

74 lines
1.7 KiB
TypeScript

export interface DeferredInit {
promise: Promise<void>;
resolve: () => void;
reject: (error: Error) => void;
timeoutId: ReturnType<typeof setTimeout> | null;
requestDirection: "tail" | "after";
}
const initPromises = new Map<string, DeferredInit>();
export function getInitKey(serverId: string, agentId: string): string {
return `${serverId}:${agentId}`;
}
export function getInitDeferred(key: string): DeferredInit | undefined {
return initPromises.get(key);
}
export function createInitDeferred(
key: string,
requestDirection: "tail" | "after"
): DeferredInit {
let resolve!: () => void;
let reject!: (error: Error) => void;
const promise = new Promise<void>((res, rej) => {
resolve = res;
reject = rej;
});
const deferred: DeferredInit = {
promise,
resolve,
reject,
timeoutId: null,
requestDirection,
};
initPromises.set(key, deferred);
return deferred;
}
export function attachInitTimeout(key: string, timeoutId: ReturnType<typeof setTimeout>): void {
const deferred = initPromises.get(key);
if (!deferred) {
clearTimeout(timeoutId);
return;
}
deferred.timeoutId = timeoutId;
}
export function resolveInitDeferred(key: string): void {
const deferred = initPromises.get(key);
if (!deferred) {
return;
}
if (deferred.timeoutId) {
clearTimeout(deferred.timeoutId);
}
initPromises.delete(key);
deferred.resolve();
}
export function rejectInitDeferred(key: string, error: Error): void {
const deferred = initPromises.get(key);
if (!deferred) {
return;
}
if (deferred.timeoutId) {
clearTimeout(deferred.timeoutId);
}
initPromises.delete(key);
deferred.reject(error);
}