Files
paseo/packages/app/src/utils/agent-initialization.ts
T
Mohamed BoudraandGitHub b613bea9f6 Default client RPC waits to 60 seconds (#1789)
* fix(client): wait longer for session responses

* fix(client): default RPC waits to sixty seconds

* fix(app): preserve detached stream scroll on delayed history

Code drift: longer client RPC waits let delayed timeline responses arrive after a user scroll-away, so web stream anchoring must not reattach on transient scroll-top resets.

Restore the 15s connect deadline and leave app initialization slack above the default 60s session RPC wait.

* fix(client): keep helper waits within caller deadlines

Review fix: the 60s default session RPC wait leaked into wait previews and waitForAgentUpsert helper fetches. Bound those helper RPCs to the caller deadline or a short best-effort preview timeout, and allow small scroll ranges to reattach at bottom.

* fix(client): respect caller timeout budgets

* fix(cli): keep diagnostic probes responsive

* Refactor daemon client request options

* Preserve daemon client legacy overloads
2026-06-29 17:23:18 +02:00

80 lines
1.9 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 const INIT_TIMEOUT_MS = 65_000;
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 refreshInitTimeout(input: {
key: string;
onTimeout: () => void;
timeoutMs?: number;
}): void {
const timeoutId = setTimeout(input.onTimeout, input.timeoutMs ?? INIT_TIMEOUT_MS);
const deferred = initPromises.get(input.key);
if (!deferred) {
clearTimeout(timeoutId);
return;
}
if (deferred.timeoutId) {
clearTimeout(deferred.timeoutId);
}
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);
}