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:
@@ -6,7 +6,10 @@ export function addAttachOptions(cmd: Command): Command {
|
||||
.argument("<id>", "Agent ID (or prefix)");
|
||||
}
|
||||
import { connectToDaemon, getDaemonHost } from "../../utils/client.js";
|
||||
import { fetchProjectedTimelineItems } from "../../utils/timeline.js";
|
||||
import {
|
||||
fetchProjectedTimelineItems,
|
||||
LIVE_HISTORY_FETCH_TIMEOUT_MS,
|
||||
} from "../../utils/timeline.js";
|
||||
import type { DaemonClient } from "@getpaseo/client/internal/daemon-client";
|
||||
import type { AgentTimelineItem } from "@getpaseo/protocol/agent-types";
|
||||
import type { AgentStreamEventPayload, AgentStreamMessage } from "@getpaseo/protocol/messages";
|
||||
@@ -121,7 +124,7 @@ export async function runAttachCommand(
|
||||
}
|
||||
|
||||
try {
|
||||
const fetchResult = await client.fetchAgent(id);
|
||||
const fetchResult = await client.fetchAgent({ agentId: id });
|
||||
if (!fetchResult) {
|
||||
console.error(`Error: No agent found matching: ${id}`);
|
||||
console.error("Use `paseo ls` to list available agents");
|
||||
@@ -139,6 +142,7 @@ export async function runAttachCommand(
|
||||
const timelineItems = await fetchProjectedTimelineItems({
|
||||
client,
|
||||
agentId: resolvedId,
|
||||
timeoutMs: LIVE_HISTORY_FETCH_TIMEOUT_MS,
|
||||
});
|
||||
for (const item of timelineItems) {
|
||||
printTimelineItem(item);
|
||||
|
||||
@@ -76,7 +76,7 @@ export async function runDeleteCommand(
|
||||
return isSameOrDescendantPath(options.cwd!, a.cwd);
|
||||
});
|
||||
} else if (id) {
|
||||
const fetchResult = await client.fetchAgent(id);
|
||||
const fetchResult = await client.fetchAgent({ agentId: id });
|
||||
if (!fetchResult) {
|
||||
const error: CommandError = {
|
||||
code: "AGENT_NOT_FOUND",
|
||||
|
||||
@@ -243,7 +243,7 @@ export async function runInspectCommand(
|
||||
}
|
||||
|
||||
try {
|
||||
const fetchResult = await client.fetchAgent(agentIdArg);
|
||||
const fetchResult = await client.fetchAgent({ agentId: agentIdArg });
|
||||
if (!fetchResult) {
|
||||
const error: CommandError = {
|
||||
code: "AGENT_NOT_FOUND",
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { Command } from "commander";
|
||||
import { connectToDaemon, getDaemonHost } from "../../utils/client.js";
|
||||
import type { CommandOptions } from "../../output/index.js";
|
||||
import { fetchProjectedTimelineItems } from "../../utils/timeline.js";
|
||||
import {
|
||||
fetchProjectedTimelineItems,
|
||||
LIVE_HISTORY_FETCH_TIMEOUT_MS,
|
||||
} from "../../utils/timeline.js";
|
||||
import type { DaemonClient } from "@getpaseo/client/internal/daemon-client";
|
||||
import type { AgentTimelineItem } from "@getpaseo/protocol/agent-types";
|
||||
import type { AgentStreamMessage } from "@getpaseo/protocol/messages";
|
||||
@@ -32,8 +35,9 @@ export const NO_ACTIVITY_MESSAGE = "No activity to display.";
|
||||
export async function fetchAgentTimelineItems(
|
||||
client: DaemonClient,
|
||||
agentId: string,
|
||||
options?: { timeoutMs?: number },
|
||||
): Promise<AgentTimelineItem[]> {
|
||||
return fetchProjectedTimelineItems({ client, agentId });
|
||||
return fetchProjectedTimelineItems({ client, agentId, timeoutMs: options?.timeoutMs });
|
||||
}
|
||||
|
||||
export function formatAgentActivityTranscript(
|
||||
@@ -107,7 +111,7 @@ export async function runLogsCommand(
|
||||
}
|
||||
|
||||
try {
|
||||
const fetchResult = await client.fetchAgent(id);
|
||||
const fetchResult = await client.fetchAgent({ agentId: id });
|
||||
if (!fetchResult) {
|
||||
console.error(`Error: No agent found matching: ${id}`);
|
||||
console.error("Use `paseo ls` to list available agents");
|
||||
@@ -173,7 +177,14 @@ async function runFollowMode(
|
||||
const tailCount = parseTailCount(options.tail) ?? DEFAULT_FOLLOW_TAIL;
|
||||
|
||||
// First, get existing timeline.
|
||||
let existingItems = await fetchAgentTimelineItems(client, agentId);
|
||||
let existingItems: AgentTimelineItem[] = [];
|
||||
try {
|
||||
existingItems = await fetchAgentTimelineItems(client, agentId, {
|
||||
timeoutMs: LIVE_HISTORY_FETCH_TIMEOUT_MS,
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn("Warning: failed to fetch existing timeline", error);
|
||||
}
|
||||
|
||||
// Apply filter to existing items
|
||||
if (options.filter) {
|
||||
|
||||
@@ -65,7 +65,7 @@ export async function runModeCommand(
|
||||
let client: Awaited<ReturnType<typeof connectToDaemon>> | undefined;
|
||||
try {
|
||||
client = await connectToDaemon({ host: options.host });
|
||||
const fetchResult = await client.fetchAgent(id);
|
||||
const fetchResult = await client.fetchAgent({ agentId: id });
|
||||
if (!fetchResult) {
|
||||
const error: CommandError = {
|
||||
code: "AGENT_NOT_FOUND",
|
||||
|
||||
@@ -83,7 +83,7 @@ export async function runStopCommand(
|
||||
});
|
||||
} else if (id) {
|
||||
// Stop specific agent
|
||||
const fetchResult = await client.fetchAgent(id);
|
||||
const fetchResult = await client.fetchAgent({ agentId: id });
|
||||
if (!fetchResult) {
|
||||
const error: CommandError = {
|
||||
code: "AGENT_NOT_FOUND",
|
||||
|
||||
@@ -132,7 +132,7 @@ export async function runUpdateCommand(
|
||||
}
|
||||
|
||||
try {
|
||||
const fetchResult = await client.fetchAgent(agentIdArg);
|
||||
const fetchResult = await client.fetchAgent({ agentId: agentIdArg });
|
||||
if (!fetchResult) {
|
||||
const error: CommandError = {
|
||||
code: "AGENT_NOT_FOUND",
|
||||
@@ -148,7 +148,7 @@ export async function runUpdateCommand(
|
||||
...(Object.keys(labels).length > 0 ? { labels } : {}),
|
||||
});
|
||||
|
||||
const updatedResult = await client.fetchAgent(agentId);
|
||||
const updatedResult = await client.fetchAgent({ agentId });
|
||||
if (!updatedResult) {
|
||||
throw new Error(`Agent not found after update: ${agentId}`);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ export interface AgentWaitOptions extends CommandOptions {
|
||||
}
|
||||
|
||||
const WAIT_ACTIVITY_PREVIEW_COUNT = 5;
|
||||
const WAIT_ACTIVITY_PREVIEW_TIMEOUT_MS = 2_000;
|
||||
|
||||
function appendRecentActivity(message: string, transcript: string | null): string {
|
||||
if (!transcript || transcript.trim().length === 0) {
|
||||
@@ -46,7 +47,9 @@ async function getRecentActivityTranscript(
|
||||
agentId: string,
|
||||
): Promise<string | null> {
|
||||
try {
|
||||
const timelineItems = await fetchAgentTimelineItems(client, agentId);
|
||||
const timelineItems = await fetchAgentTimelineItems(client, agentId, {
|
||||
timeoutMs: WAIT_ACTIVITY_PREVIEW_TIMEOUT_MS,
|
||||
});
|
||||
return formatAgentActivityTranscript(timelineItems, WAIT_ACTIVITY_PREVIEW_COUNT);
|
||||
} catch {
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user