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
This commit is contained in:
@@ -26,6 +26,7 @@ export async function connectChatClient(host?: string) {
|
||||
export async function attachAgentNamesToMessages(
|
||||
client: Awaited<ReturnType<typeof connectToDaemon>>,
|
||||
messages: ChatMessageRow[],
|
||||
options: { timeout?: number; bestEffort?: boolean } = {},
|
||||
): Promise<ChatMessageRow[]> {
|
||||
const agentIds = new Set<string>();
|
||||
for (const message of messages) {
|
||||
@@ -39,9 +40,18 @@ export async function attachAgentNamesToMessages(
|
||||
return messages;
|
||||
}
|
||||
|
||||
const payload = await client.fetchAgents({
|
||||
filter: { includeArchived: true },
|
||||
});
|
||||
let payload: Awaited<ReturnType<typeof client.fetchAgents>>;
|
||||
try {
|
||||
payload = await client.fetchAgents({
|
||||
filter: { includeArchived: true },
|
||||
...(typeof options.timeout === "number" ? { timeout: options.timeout } : {}),
|
||||
});
|
||||
} catch (error) {
|
||||
if (options.bestEffort) {
|
||||
return messages;
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
const agentNames = new Map<string, string>();
|
||||
for (const entry of payload.entries) {
|
||||
const title = entry.agent.title?.trim();
|
||||
|
||||
@@ -13,26 +13,44 @@ export interface ChatWaitOptions extends ChatCommandOptions {
|
||||
timeout?: string;
|
||||
}
|
||||
|
||||
const CHAT_WAIT_PREFLIGHT_TIMEOUT_MS = 2000;
|
||||
|
||||
export async function runWaitCommand(
|
||||
room: string,
|
||||
options: ChatWaitOptions,
|
||||
_command: Command,
|
||||
): Promise<ListResult<ChatMessageRow>> {
|
||||
const timeoutMs = parseTimeoutMs(options.timeout);
|
||||
const { client } = await connectChatClient(options.host);
|
||||
const deadline = typeof timeoutMs === "number" ? Date.now() + timeoutMs : null;
|
||||
const hasExplicitTimeout = deadline !== null;
|
||||
const remainingTimeoutMs = () =>
|
||||
deadline === null ? undefined : Math.max(1, deadline - Date.now());
|
||||
try {
|
||||
const latest = await client.readChatMessages({
|
||||
room,
|
||||
limit: 1,
|
||||
...(hasExplicitTimeout
|
||||
? {
|
||||
timeout: Math.min(remainingTimeoutMs() ?? 1, CHAT_WAIT_PREFLIGHT_TIMEOUT_MS),
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
const afterMessageId = latest.messages[0]?.id;
|
||||
const payload = await client.waitForChatMessages({
|
||||
room,
|
||||
afterMessageId,
|
||||
timeoutMs: parseTimeoutMs(options.timeout),
|
||||
timeoutMs: remainingTimeoutMs() ?? timeoutMs,
|
||||
});
|
||||
const messages = await attachAgentNamesToMessages(
|
||||
client,
|
||||
payload.messages.map(toChatMessageRow),
|
||||
hasExplicitTimeout
|
||||
? {
|
||||
timeout: remainingTimeoutMs(),
|
||||
bestEffort: true,
|
||||
}
|
||||
: {},
|
||||
);
|
||||
return {
|
||||
type: "list",
|
||||
|
||||
Reference in New Issue
Block a user