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:
Mohamed Boudra
2026-06-29 17:23:18 +02:00
committed by GitHub
parent 57800a0f17
commit b613bea9f6
58 changed files with 1234 additions and 281 deletions
+632 -16
View File
@@ -522,6 +522,520 @@ test("keeps the transport connected when a session RPC ping times out", async ()
expect(client.getConnectionState().status).toBe("connected");
});
test("defaults session RPC waiters to sixty seconds", async () => {
useHeartbeatClock();
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const responsePromise = client.fetchAgent({
agentId: "agent-1",
requestId: "req-agent-1",
});
let settled = false;
void responsePromise.then(
() => {
settled = true;
return undefined;
},
() => {
settled = true;
return undefined;
},
);
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "fetch_agent_request",
requestId: "req-agent-1",
agentId: "agent-1",
});
await vi.advanceTimersByTimeAsync(59_999);
expect(settled).toBe(false);
await vi.advanceTimersByTimeAsync(1);
await expect(responsePromise).rejects.toThrow("Timeout waiting for message (60000ms)");
});
test("honors explicit fetchAgent timeout below the session RPC default", async () => {
useHeartbeatClock();
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const responsePromise = client.fetchAgent({
agentId: "agent-1",
requestId: "req-agent-1",
timeout: 5_000,
});
let settled = false;
void responsePromise.then(
() => {
settled = true;
return undefined;
},
() => {
settled = true;
return undefined;
},
);
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "fetch_agent_request",
requestId: "req-agent-1",
agentId: "agent-1",
});
await vi.advanceTimersByTimeAsync(4_999);
expect(settled).toBe(false);
await vi.advanceTimersByTimeAsync(1);
await expect(responsePromise).rejects.toThrow("Timeout waiting for message (5000ms)");
});
test("preserves legacy fetchAgent id overload", async () => {
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const responsePromise = client.fetchAgent("agent-1", "req-agent-legacy");
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "fetch_agent_request",
requestId: "req-agent-legacy",
agentId: "agent-1",
});
mock.triggerMessage(
wrapSessionMessage({
type: "fetch_agent_response",
payload: {
requestId: "req-agent-legacy",
agent: null,
project: null,
error: "legacy fetch sentinel",
},
}),
);
await expect(responsePromise).rejects.toThrow("legacy fetch sentinel");
});
test("honors explicit fetchAgentTimeline timeout below the session RPC default", async () => {
useHeartbeatClock();
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const responsePromise = client.fetchAgentTimeline("agent-1", {
requestId: "req-timeline-1",
direction: "tail",
limit: 0,
projection: "projected",
timeout: 2_000,
});
let settled = false;
void responsePromise.then(
() => {
settled = true;
return undefined;
},
() => {
settled = true;
return undefined;
},
);
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "fetch_agent_timeline_request",
requestId: "req-timeline-1",
agentId: "agent-1",
direction: "tail",
limit: 0,
projection: "projected",
});
await vi.advanceTimersByTimeAsync(1_999);
expect(settled).toBe(false);
await vi.advanceTimersByTimeAsync(1);
await expect(responsePromise).rejects.toThrow("Timeout waiting for message (2000ms)");
});
test("honors explicit fetchAgents timeout below the session RPC default", async () => {
useHeartbeatClock();
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const responsePromise = client.fetchAgents({
requestId: "req-agents-1",
scope: "active",
timeout: 1_200,
});
let settled = false;
void responsePromise.then(
() => {
settled = true;
return undefined;
},
() => {
settled = true;
return undefined;
},
);
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "fetch_agents_request",
requestId: "req-agents-1",
scope: "active",
});
await vi.advanceTimersByTimeAsync(1_199);
expect(settled).toBe(false);
await vi.advanceTimersByTimeAsync(1);
await expect(responsePromise).rejects.toThrow("Timeout waiting for message (1200ms)");
});
test("honors explicit shutdownServer timeout below the session RPC default", async () => {
useHeartbeatClock();
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const responsePromise = client.shutdownServer({
requestId: "req-shutdown-1",
timeout: 1_500,
});
let settled = false;
void responsePromise.then(
() => {
settled = true;
return undefined;
},
() => {
settled = true;
return undefined;
},
);
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "shutdown_server_request",
requestId: "req-shutdown-1",
});
await vi.advanceTimersByTimeAsync(1_499);
expect(settled).toBe(false);
await vi.advanceTimersByTimeAsync(1);
await expect(responsePromise).rejects.toThrow("Timeout waiting for message (1500ms)");
});
test("honors explicit readChatMessages timeout below the session RPC default", async () => {
useHeartbeatClock();
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const responsePromise = client.readChatMessages({
requestId: "req-chat-read-1",
room: "room-1",
limit: 1,
timeout: 2_500,
});
let settled = false;
void responsePromise.then(
() => {
settled = true;
return undefined;
},
() => {
settled = true;
return undefined;
},
);
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "chat/read",
requestId: "req-chat-read-1",
room: "room-1",
limit: 1,
});
await vi.advanceTimersByTimeAsync(2_499);
expect(settled).toBe(false);
await vi.advanceTimersByTimeAsync(1);
await expect(responsePromise).rejects.toThrow("Timeout waiting for message (2500ms)");
});
test("honors explicit getDaemonStatus timeout below the session RPC default", async () => {
useHeartbeatClock();
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const responsePromise = client.getDaemonStatus({
requestId: "req-daemon-status-1",
timeout: 1_500,
});
let settled = false;
void responsePromise.then(
() => {
settled = true;
return undefined;
},
() => {
settled = true;
return undefined;
},
);
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "daemon.get_status.request",
requestId: "req-daemon-status-1",
});
await vi.advanceTimersByTimeAsync(1_499);
expect(settled).toBe(false);
await vi.advanceTimersByTimeAsync(1);
await expect(responsePromise).rejects.toThrow("Timeout waiting for message (1500ms)");
});
test("honors explicit getDaemonPairingOffer timeout below the session RPC default", async () => {
useHeartbeatClock();
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const responsePromise = client.getDaemonPairingOffer({
requestId: "req-pairing-offer-1",
timeout: 1_500,
});
let settled = false;
void responsePromise.then(
() => {
settled = true;
return undefined;
},
() => {
settled = true;
return undefined;
},
);
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "daemon.get_pairing_offer.request",
requestId: "req-pairing-offer-1",
});
await vi.advanceTimersByTimeAsync(1_499);
expect(settled).toBe(false);
await vi.advanceTimersByTimeAsync(1);
await expect(responsePromise).rejects.toThrow("Timeout waiting for message (1500ms)");
});
test("keeps waitForAgentUpsert initial fetch inside the requested deadline", async () => {
useHeartbeatClock();
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const waitPromise = client.waitForAgentUpsert("agent-1", () => false, 5_000);
let settled = false;
void waitPromise.then(
() => {
settled = true;
return undefined;
},
() => {
settled = true;
return undefined;
},
);
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "fetch_agent_request",
requestId: expect.any(String),
agentId: "agent-1",
});
await vi.advanceTimersByTimeAsync(4_999);
expect(settled).toBe(false);
await vi.advanceTimersByTimeAsync(1);
await expect(waitPromise).rejects.toThrow("Timed out waiting for agent agent-1");
});
test("keeps default connect timeout shorter than session RPC waiters", async () => {
useHeartbeatClock();
try {
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
let settled = false;
const pendingConnect = client.connect().then(
() => {
settled = true;
return { ok: true as const };
},
(error) => {
settled = true;
return { ok: false as const, error };
},
);
await vi.advanceTimersByTimeAsync(14_999);
expect(settled).toBe(false);
expect(client.getConnectionState().status).toBe("connecting");
await vi.advanceTimersByTimeAsync(1);
const result = await pendingConnect;
expect(result.ok).toBe(false);
if (!result.ok) {
expect(result.error).toBeInstanceOf(Error);
if (result.error instanceof Error) {
expect(result.error.message).toContain("Connection timed out");
}
}
expect(client.getConnectionState().status).toBe("disconnected");
} finally {
vi.useRealTimers();
}
});
test("stays online through ten minutes of pongs that arrive five seconds late", async () => {
useHeartbeatClock();
const session = new DaemonClientSession();
@@ -1754,16 +2268,8 @@ test("sends explicit shutdown_server_request via shutdownServer", async () => {
mock.triggerOpen();
await connectPromise;
const lifecycleClient = client as unknown as {
shutdownServer: (requestId?: string) => Promise<{
status: "shutdown_requested";
clientId: string;
requestId: string;
}>;
};
expect(typeof lifecycleClient.shutdownServer).toBe("function");
const promise = lifecycleClient.shutdownServer("req-shutdown-1");
expect(typeof client.shutdownServer).toBe("function");
const promise = client.shutdownServer({ requestId: "req-shutdown-1" });
expect(mock.sent).toHaveLength(1);
const request = parseSentFrame(mock.sent[0]);
@@ -3347,7 +3853,8 @@ test("lists commands with draft config via RPC", async () => {
mock.triggerOpen();
await connectPromise;
const promise = client.listCommands("__new_agent__", {
const promise = client.listCommands({
agentId: "__new_agent__",
draftConfig: {
provider: "codex",
cwd: "/tmp/project",
@@ -3392,7 +3899,7 @@ test("lists commands with draft config via RPC", async () => {
});
});
test("lists commands with legacy requestId signature via RPC", async () => {
test("lists commands with explicit requestId via RPC", async () => {
const logger = createMockLogger();
const mock = createMockTransport();
@@ -3409,13 +3916,16 @@ test("lists commands with legacy requestId signature via RPC", async () => {
mock.triggerOpen();
await connectPromise;
const promise = client.listCommands("agent-1", "req-legacy");
const promise = client.listCommands({
agentId: "agent-1",
requestId: "req-commands",
});
expect(mock.sent).toHaveLength(1);
const request = parseSentFrame(mock.sent[0]);
expect(request.type).toBe("list_commands_request");
expect(request.agentId).toBe("agent-1");
expect(request.requestId).toBe("req-legacy");
expect(request.requestId).toBe("req-commands");
expect(request.draftConfig).toBeUndefined();
mock.triggerMessage(
@@ -3427,7 +3937,7 @@ test("lists commands with legacy requestId signature via RPC", async () => {
agentId: "agent-1",
commands: [],
error: null,
requestId: "req-legacy",
requestId: "req-commands",
},
},
}),
@@ -3437,7 +3947,113 @@ test("lists commands with legacy requestId signature via RPC", async () => {
agentId: "agent-1",
commands: [],
error: null,
requestId: "req-legacy",
requestId: "req-commands",
});
});
test("preserves legacy listCommands id overload", async () => {
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const promise = client.listCommands("agent-1", "req-commands-legacy");
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "list_commands_request",
requestId: "req-commands-legacy",
agentId: "agent-1",
});
mock.triggerMessage(
wrapSessionMessage({
type: "list_commands_response",
payload: {
agentId: "agent-1",
commands: [],
error: null,
requestId: "req-commands-legacy",
},
}),
);
await expect(promise).resolves.toEqual({
agentId: "agent-1",
commands: [],
error: null,
requestId: "req-commands-legacy",
});
});
test("preserves legacy listCommands options overload", async () => {
const logger = createMockLogger();
const mock = createMockTransport();
const client = new DaemonClient({
url: "ws://test",
clientId: "clsk_unit_test",
logger,
reconnect: { enabled: false },
transportFactory: () => mock.transport,
});
clients.push(client);
const connectPromise = client.connect();
mock.triggerOpen();
await connectPromise;
const promise = client.listCommands("__new_agent__", {
requestId: "req-commands-draft-legacy",
draftConfig: {
provider: "codex",
cwd: "/tmp/project",
modeId: "bypassPermissions",
model: "gpt-5",
thinkingOptionId: "off",
},
});
expect(parseSentFrame(mock.sent[0])).toEqual({
type: "list_commands_request",
requestId: "req-commands-draft-legacy",
agentId: "__new_agent__",
draftConfig: {
provider: "codex",
cwd: "/tmp/project",
modeId: "bypassPermissions",
model: "gpt-5",
thinkingOptionId: "off",
},
});
mock.triggerMessage(
wrapSessionMessage({
type: "list_commands_response",
payload: {
agentId: "__new_agent__",
commands: [{ name: "help", description: "Show help", argumentHint: "" }],
error: null,
requestId: "req-commands-draft-legacy",
},
}),
);
await expect(promise).resolves.toEqual({
agentId: "__new_agent__",
commands: [{ name: "help", description: "Show help", argumentHint: "" }],
error: null,
requestId: "req-commands-draft-legacy",
});
});
+111 -136
View File
@@ -374,9 +374,11 @@ export interface WriteProjectConfigInput {
requestId?: string;
}
interface ListCommandsOptions {
agentId: string;
requestId?: string;
draftConfig?: ListCommandsDraftConfig;
}
type LegacyListCommandsOptions = Omit<ListCommandsOptions, "agentId">;
type SetVoiceModePayload = Extract<
SessionOutboundMessage,
{ type: "set_voice_mode_response" }
@@ -458,17 +460,64 @@ export type FetchAgentTimelinePayload = FetchAgentTimelineResponseMessage["paylo
export type FetchAgentTimelineDirection = FetchAgentTimelinePayload["direction"];
export type FetchAgentTimelineProjection = FetchAgentTimelinePayload["projection"];
export type FetchAgentTimelineCursor = NonNullable<FetchAgentTimelinePayload["startCursor"]>;
export interface FetchAgentOptions {
agentId: string;
requestId?: string;
timeout?: number;
}
type LegacyFetchAgentOptions = Omit<FetchAgentOptions, "agentId">;
export interface FetchAgentTimelineOptions {
direction?: FetchAgentTimelineDirection;
cursor?: FetchAgentTimelineCursor;
limit?: number;
projection?: FetchAgentTimelineProjection;
requestId?: string;
timeout?: number;
}
// COMPAT(daemon-client-object-options): added in v0.1.102; remove after
// 2026-12-29 once SDK callers have migrated to object parameters.
function normalizeFetchAgentOptions(
input: FetchAgentOptions | string,
legacyOptions?: LegacyFetchAgentOptions | string,
): FetchAgentOptions {
if (typeof input !== "string") {
return input;
}
if (typeof legacyOptions === "string") {
return { agentId: input, requestId: legacyOptions };
}
return { agentId: input, ...legacyOptions };
}
function normalizeListCommandsOptions(
input: ListCommandsOptions | string,
legacyOptions?: LegacyListCommandsOptions | string,
): ListCommandsOptions {
if (typeof input !== "string") {
return input;
}
if (typeof legacyOptions === "string") {
return { agentId: input, requestId: legacyOptions };
}
return { agentId: input, ...legacyOptions };
}
type AgentRefreshedStatusPayload = z.infer<typeof AgentRefreshedStatusPayloadSchema>;
type RestartRequestedStatusPayload = z.infer<typeof RestartRequestedStatusPayloadSchema>;
type ShutdownRequestedStatusPayload = z.infer<typeof ShutdownRequestedStatusPayloadSchema>;
export interface ShutdownServerOptions {
requestId?: string;
timeout?: number;
}
export interface DaemonStatusOptions {
requestId?: string;
timeout?: number;
}
export interface DaemonPairingOfferOptions {
requestId?: string;
timeout?: number;
}
type DaemonUpdateResponse = z.infer<typeof DaemonUpdateResponseSchema>;
type FetchAgentsPayload = Extract<
SessionOutboundMessage,
@@ -477,6 +526,7 @@ type FetchAgentsPayload = Extract<
type FetchAgentsRequest = Extract<SessionInboundMessage, { type: "fetch_agents_request" }>;
export type FetchAgentsOptions = Omit<FetchAgentsRequest, "type" | "requestId"> & {
requestId?: string;
timeout?: number;
};
export type FetchAgentsEntry = FetchAgentsPayload["entries"][number];
export type FetchAgentsPageInfo = FetchAgentsPayload["pageInfo"];
@@ -544,6 +594,7 @@ export interface ReadChatMessagesOptions {
since?: string;
authorAgentId?: string;
requestId?: string;
timeout?: number;
}
export interface WaitForChatMessagesOptions {
room: string;
@@ -762,15 +813,16 @@ function toTimeoutError(error: unknown, label: string, timeoutMs: number): Error
const DEFAULT_RECONNECT_BASE_DELAY_MS = 1500;
const DEFAULT_RECONNECT_MAX_DELAY_MS = 30000;
const DEFAULT_CONNECT_TIMEOUT_MS = 15000;
const DEFAULT_SESSION_RPC_TIMEOUT_MS = 60_000;
const DEFAULT_CONNECT_TIMEOUT_MS = 15_000;
const DEFAULT_LIVENESS_TIMEOUT_MS = 5000;
const LIVENESS_HEARTBEAT_INTERVAL_MS = 10_000;
const LIVENESS_HEARTBEAT_TIMEOUT_MS = 15_000;
const LIVENESS_FAILURE_RECONNECT_THRESHOLD = 2;
/** Default timeout for waiting for connection before sending queued messages */
const DEFAULT_SEND_QUEUE_TIMEOUT_MS = 10000;
const DEFAULT_DICTATION_FINISH_ACCEPT_TIMEOUT_MS = 15000;
const DEFAULT_SEND_QUEUE_TIMEOUT_MS = DEFAULT_SESSION_RPC_TIMEOUT_MS;
const DEFAULT_DICTATION_FINISH_ACCEPT_TIMEOUT_MS = DEFAULT_SESSION_RPC_TIMEOUT_MS;
const DEFAULT_DICTATION_FINISH_FALLBACK_TIMEOUT_MS = 5 * 60 * 1000;
const DEFAULT_DICTATION_FINISH_TIMEOUT_GRACE_MS = 5000;
@@ -1420,10 +1472,11 @@ export class DaemonClient {
private async sendRequest<T>(params: {
requestId: string;
message: SessionInboundMessage;
timeout: number;
timeout?: number;
select: (msg: SessionOutboundMessage) => T | null;
options?: { skipQueue?: boolean };
}): Promise<T> {
const timeout = params.timeout ?? DEFAULT_SESSION_RPC_TIMEOUT_MS;
const { promise, cancel } = this.waitForWithCancel<RpcWaitResult<T>>(
(msg) => {
if (msg.type === "rpc_error" && msg.payload.requestId === params.requestId) {
@@ -1443,7 +1496,7 @@ export class DaemonClient {
}
return { kind: "ok", value };
},
params.timeout,
timeout,
params.options,
);
@@ -1469,7 +1522,7 @@ export class DaemonClient {
>(params: {
requestId: string;
message: SessionInboundMessage;
timeout: number;
timeout?: number;
responseType: TResponseType;
options?: { skipQueue?: boolean };
selectPayload?: (payload: CorrelatedResponsePayload<TResponseType>) => TResult | null;
@@ -1503,7 +1556,7 @@ export class DaemonClient {
requestId?: string;
message: { type: SessionInboundMessage["type"] } & Record<string, unknown>;
responseType: TResponseType;
timeout: number;
timeout?: number;
selectPayload?: (payload: CorrelatedResponsePayload<TResponseType>) => TResult | null;
}): Promise<TResult> {
const resolvedRequestId = this.createRequestId(params.requestId);
@@ -1530,7 +1583,7 @@ export class DaemonClient {
string,
unknown
>;
timeout: number;
timeout?: number;
selectPayload?: (payload: CorrelatedResponsePayload<TResponseType>) => TResult | null;
}): Promise<TResult> {
const responseType = params.message.type.replace(/\.request$/, ".response") as TResponseType;
@@ -1562,7 +1615,6 @@ export class DaemonClient {
await this.sendRequest({
requestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "clear_agent_attention_response") {
@@ -1586,7 +1638,6 @@ export class DaemonClient {
const response = await this.sendRequest({
requestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "workspace.clear_attention.response") {
@@ -1782,7 +1833,7 @@ export class DaemonClient {
return this.sendRequest({
requestId: resolvedRequestId,
message,
timeout: 10000,
timeout: options?.timeout,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "fetch_agents_response") {
@@ -1808,7 +1859,6 @@ export class DaemonClient {
return this.sendRequest({
requestId: resolvedRequestId,
message,
timeout: 10000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "fetch_agent_history_response") {
@@ -1837,7 +1887,6 @@ export class DaemonClient {
return this.sendRequest({
requestId: resolvedRequestId,
message,
timeout: 10000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "fetch_recent_provider_sessions_response") {
@@ -1864,7 +1913,6 @@ export class DaemonClient {
return this.sendRequest({
requestId: resolvedRequestId,
message,
timeout: 10000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "fetch_workspaces_response") {
@@ -1886,9 +1934,6 @@ export class DaemonClient {
cwd,
},
responseType: "open_project_response",
// Large local repos (e.g. a big monorepo/brain checkout) need >10s for the
// daemon to resolve the path, detect git, and materialize the workspace.
timeout: 60000,
});
}
@@ -1900,7 +1945,6 @@ export class DaemonClient {
cwd,
},
responseType: "project.add.response",
timeout: 10000,
});
}
@@ -1919,7 +1963,6 @@ export class DaemonClient {
scriptName,
},
responseType: "start_workspace_script_response",
timeout: 10000,
});
}
@@ -1934,7 +1977,6 @@ export class DaemonClient {
workspaceId,
},
responseType: "archive_workspace_response",
timeout: 10000,
});
}
@@ -1949,21 +1991,30 @@ export class DaemonClient {
workspaceId,
},
responseType: "workspace_setup_status_response",
timeout: 10000,
});
}
async fetchAgent(agentId: string, requestId?: string): Promise<FetchAgentResult | null> {
const resolvedRequestId = this.createRequestId(requestId);
async fetchAgent(options: FetchAgentOptions): Promise<FetchAgentResult | null>;
async fetchAgent(agentId: string, requestId?: string): Promise<FetchAgentResult | null>;
async fetchAgent(
agentId: string,
options?: LegacyFetchAgentOptions,
): Promise<FetchAgentResult | null>;
async fetchAgent(
input: FetchAgentOptions | string,
legacyOptions?: LegacyFetchAgentOptions | string,
): Promise<FetchAgentResult | null> {
const options = normalizeFetchAgentOptions(input, legacyOptions);
const resolvedRequestId = this.createRequestId(options.requestId);
const message = SessionInboundMessageSchema.parse({
type: "fetch_agent_request",
requestId: resolvedRequestId,
agentId,
agentId: options.agentId,
});
const payload = await this.sendRequest({
requestId: resolvedRequestId,
message,
timeout: 10000,
timeout: options.timeout,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "fetch_agent_response") {
@@ -2048,7 +2099,6 @@ export class DaemonClient {
const status = await this.sendRequest({
requestId,
message,
timeout: 60000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "status") {
@@ -2082,7 +2132,6 @@ export class DaemonClient {
await this.sendRequest({
requestId,
message,
timeout: 10000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "agent_deleted") {
@@ -2106,7 +2155,6 @@ export class DaemonClient {
const result = await this.sendRequest({
requestId,
message,
timeout: 10000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "agent_archived") {
@@ -2127,7 +2175,6 @@ export class DaemonClient {
type: "agent.detach.request",
agentId,
},
timeout: 10000,
});
if (!payload.accepted) {
throw new Error(payload.error ?? "detachAgent rejected");
@@ -2151,7 +2198,6 @@ export class DaemonClient {
const payload = await this.sendRequest({
requestId,
message,
timeout: 10000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "update_agent_response") {
@@ -2181,7 +2227,6 @@ export class DaemonClient {
customName,
},
responseType: "project.rename.response",
timeout: 10000,
});
if (!payload.accepted) {
throw new Error(payload.error ?? "renameProject rejected");
@@ -2199,7 +2244,6 @@ export class DaemonClient {
type: "project.remove.request",
projectId,
},
timeout: 10000,
});
if (!payload.accepted) {
throw new Error(payload.error ?? "removeProject rejected");
@@ -2220,7 +2264,6 @@ export class DaemonClient {
title,
},
responseType: "workspace.title.set.response",
timeout: 10000,
});
if (!payload.accepted) {
throw new Error(payload.error ?? "setWorkspaceTitle rejected");
@@ -2243,7 +2286,6 @@ export class DaemonClient {
const status = await this.sendRequest({
requestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "status") {
@@ -2275,7 +2317,6 @@ export class DaemonClient {
const status = await this.sendRequest({
requestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "status") {
@@ -2312,7 +2353,6 @@ export class DaemonClient {
return this.sendRequest({
requestId: resolvedRequestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "status") {
@@ -2345,7 +2385,7 @@ export class DaemonClient {
const payload = await this.sendRequest({
requestId: resolvedRequestId,
message,
timeout: 15000,
timeout: options.timeout,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "fetch_agent_timeline_response") {
@@ -2388,7 +2428,6 @@ export class DaemonClient {
const payload = await this.sendRequest({
requestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "send_agent_message_response") {
@@ -2425,7 +2464,6 @@ export class DaemonClient {
const payload = await this.sendRequest({
requestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "agent.rewind.response") {
@@ -2453,7 +2491,6 @@ export class DaemonClient {
await this.sendRequest({
requestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "cancel_agent_response") {
@@ -2478,7 +2515,6 @@ export class DaemonClient {
const payload = await this.sendRequest({
requestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "set_agent_mode_response") {
@@ -2507,7 +2543,6 @@ export class DaemonClient {
const payload = await this.sendRequest({
requestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "set_agent_model_response") {
@@ -2536,7 +2571,6 @@ export class DaemonClient {
const payload = await this.sendRequest({
requestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "set_agent_feature_response") {
@@ -2567,7 +2601,6 @@ export class DaemonClient {
const payload = await this.sendRequest({
requestId,
message,
timeout: 15000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "set_agent_thinking_response") {
@@ -2595,7 +2628,6 @@ export class DaemonClient {
return this.sendRequest({
requestId: resolvedRequestId,
message,
timeout: 10000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "status") {
@@ -2613,8 +2645,8 @@ export class DaemonClient {
});
}
async shutdownServer(requestId?: string): Promise<ShutdownRequestedStatusPayload> {
const resolvedRequestId = this.createRequestId(requestId);
async shutdownServer(options?: ShutdownServerOptions): Promise<ShutdownRequestedStatusPayload> {
const resolvedRequestId = this.createRequestId(options?.requestId);
const message = SessionInboundMessageSchema.parse({
type: "shutdown_server_request",
requestId: resolvedRequestId,
@@ -2622,7 +2654,7 @@ export class DaemonClient {
return this.sendRequest({
requestId: resolvedRequestId,
message,
timeout: 10000,
timeout: options?.timeout,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "status") {
@@ -2679,7 +2711,6 @@ export class DaemonClient {
const response = await this.sendRequest({
requestId,
message,
timeout: 10000,
select: (msg) => {
if (msg.type !== "set_voice_mode_response") {
return null;
@@ -2948,7 +2979,6 @@ export class DaemonClient {
const responsePromise = this.sendRequest({
requestId: resolvedRequestId,
message,
timeout: 60000,
options: { skipQueue: true },
select: (msg) => {
if (msg.type !== "checkout_status_response") {
@@ -3049,7 +3079,6 @@ export class DaemonClient {
requestId: resolvedRequestId,
message,
responseType: "subscribe_checkout_diff_response",
timeout: 60000,
options: { skipQueue: true },
selectPayload: (payload) => {
if (payload.subscriptionId !== subscriptionId) {
@@ -3090,7 +3119,6 @@ export class DaemonClient {
addAll: input.addAll,
},
responseType: "checkout_commit_response",
timeout: 60000,
});
}
@@ -3109,7 +3137,6 @@ export class DaemonClient {
requireCleanTarget: input.requireCleanTarget,
},
responseType: "checkout_merge_response",
timeout: 60000,
});
}
@@ -3127,7 +3154,6 @@ export class DaemonClient {
requireCleanTarget: input.requireCleanTarget,
},
responseType: "checkout_merge_from_base_response",
timeout: 60000,
});
}
@@ -3139,7 +3165,6 @@ export class DaemonClient {
cwd,
},
responseType: "checkout_pull_response",
timeout: 60000,
});
}
@@ -3151,7 +3176,6 @@ export class DaemonClient {
cwd,
},
responseType: "checkout_push_response",
timeout: 60000,
});
}
@@ -3163,7 +3187,6 @@ export class DaemonClient {
cwd,
},
responseType: "checkout.refresh.response",
timeout: 60000,
});
}
@@ -3182,7 +3205,6 @@ export class DaemonClient {
baseRef: input.baseRef,
},
responseType: "checkout_pr_create_response",
timeout: 60000,
});
}
@@ -3199,7 +3221,6 @@ export class DaemonClient {
mergeMethod: input.method,
},
responseType: "checkout_pr_merge_response",
timeout: 60000,
});
}
@@ -3216,7 +3237,6 @@ export class DaemonClient {
enabled: input.enabled,
...(input.enabled ? { mergeMethod: input.method } : {}),
},
timeout: 60000,
});
}
@@ -3241,7 +3261,6 @@ export class DaemonClient {
checkRunId: input.checkRunId,
workflowRunId: input.workflowRunId,
},
timeout: 60000,
},
);
}
@@ -3254,7 +3273,6 @@ export class DaemonClient {
cwd,
},
responseType: "checkout_pr_status_response",
timeout: 60000,
});
}
@@ -3272,7 +3290,6 @@ export class DaemonClient {
repoName: input.repoName,
},
responseType: "pull_request_timeline_response",
timeout: 60000,
});
}
@@ -3289,7 +3306,6 @@ export class DaemonClient {
branch,
},
responseType: "checkout_switch_branch_response",
timeout: 30000,
});
}
@@ -3302,7 +3318,6 @@ export class DaemonClient {
branch: input.branch,
},
responseType: "checkout.rename_branch.response",
timeout: 30000,
});
}
@@ -3319,7 +3334,6 @@ export class DaemonClient {
branch: options?.branch,
},
responseType: "stash_save_response",
timeout: 30000,
});
}
@@ -3332,7 +3346,6 @@ export class DaemonClient {
stashIndex,
},
responseType: "stash_pop_response",
timeout: 30000,
});
}
@@ -3349,7 +3362,6 @@ export class DaemonClient {
paseoOnly: options?.paseoOnly,
},
responseType: "stash_list_response",
timeout: 10000,
});
}
@@ -3365,7 +3377,6 @@ export class DaemonClient {
repoRoot: input.repoRoot,
},
responseType: "paseo_worktree_list_response",
timeout: 60000,
});
}
@@ -3390,7 +3401,6 @@ export class DaemonClient {
...(input.scope !== undefined ? { scope: input.scope } : {}),
},
responseType: "paseo_worktree_archive_response",
timeout: 60000,
});
}
@@ -3413,7 +3423,6 @@ export class DaemonClient {
...(input.githubPrNumber !== undefined ? { githubPrNumber: input.githubPrNumber } : {}),
},
responseType: "create_paseo_worktree_response",
timeout: 60000,
});
}
@@ -3436,7 +3445,6 @@ export class DaemonClient {
: {}),
},
responseType: "workspace.create.response",
timeout: 60000,
});
}
@@ -3452,7 +3460,6 @@ export class DaemonClient {
branchName: options.branchName,
},
responseType: "validate_branch_response",
timeout: 10000,
});
}
@@ -3469,7 +3476,6 @@ export class DaemonClient {
limit: options.limit,
},
responseType: "branch_suggestions_response",
timeout: 10000,
});
}
@@ -3487,7 +3493,6 @@ export class DaemonClient {
kinds: options.kinds,
},
responseType: "github_search_response",
timeout: 15000,
});
}
@@ -3516,7 +3521,6 @@ export class DaemonClient {
responseType: "directory_suggestions_response",
// Home-tree scans on large home dirs can take several seconds; don't cut
// the suggestion request off early (it would surface as an empty list).
timeout: 30000,
});
}
@@ -3541,7 +3545,6 @@ export class DaemonClient {
...(acceptBinary ? { acceptBinary: true } : {}),
},
responseType: "file_explorer_response",
timeout: 10000,
});
}
@@ -3601,7 +3604,6 @@ export class DaemonClient {
requestId: resolvedRequestId,
},
responseType: "file.upload.response",
timeout: 60000,
options: { skipQueue: true },
});
@@ -3653,7 +3655,6 @@ export class DaemonClient {
path,
},
responseType: "file_download_token_response",
timeout: 10000,
});
}
@@ -3668,7 +3669,6 @@ export class DaemonClient {
cwd,
},
responseType: "project_icon_response",
timeout: 10000,
});
}
@@ -3733,7 +3733,6 @@ export class DaemonClient {
type: "list_available_providers_request",
},
responseType: "list_available_providers_response",
timeout: 60000,
});
}
@@ -3748,7 +3747,6 @@ export class DaemonClient {
cwd: options?.cwd,
},
responseType: "get_providers_snapshot_response",
timeout: 10000,
});
}
@@ -3761,29 +3759,30 @@ export class DaemonClient {
type: "get_daemon_config_request",
},
responseType: "get_daemon_config_response",
timeout: 10000,
});
}
async getDaemonStatus(requestId?: string): Promise<DaemonStatusPayload> {
async getDaemonStatus(options?: DaemonStatusOptions): Promise<DaemonStatusPayload> {
return this.sendCorrelatedSessionRequest({
requestId,
requestId: options?.requestId,
message: {
type: "daemon.get_status.request",
},
responseType: "daemon.get_status.response",
timeout: 10000,
timeout: options?.timeout,
});
}
async getDaemonPairingOffer(requestId?: string): Promise<DaemonPairingOfferPayload> {
async getDaemonPairingOffer(
options?: DaemonPairingOfferOptions,
): Promise<DaemonPairingOfferPayload> {
return this.sendCorrelatedSessionRequest({
requestId,
requestId: options?.requestId,
message: {
type: "daemon.get_pairing_offer.request",
},
responseType: "daemon.get_pairing_offer.response",
timeout: 10000,
timeout: options?.timeout,
});
}
@@ -3793,7 +3792,6 @@ export class DaemonClient {
message: {
type: "diagnostics.request",
},
timeout: 30000,
});
}
@@ -3808,7 +3806,6 @@ export class DaemonClient {
config,
},
responseType: "set_daemon_config_response",
timeout: 10000,
});
}
@@ -3820,7 +3817,6 @@ export class DaemonClient {
repoRoot,
},
responseType: "read_project_config_response",
timeout: 10000,
});
}
@@ -3834,7 +3830,6 @@ export class DaemonClient {
expectedRevision: input.expectedRevision,
},
responseType: "write_project_config_response",
timeout: 10000,
});
}
@@ -3876,30 +3871,28 @@ export class DaemonClient {
message: {
type: "provider.usage.list.request",
},
timeout: 30000,
});
}
async listCommands(options: ListCommandsOptions): Promise<ListCommandsPayload>;
async listCommands(agentId: string, requestId?: string): Promise<ListCommandsPayload>;
async listCommands(agentId: string, options?: ListCommandsOptions): Promise<ListCommandsPayload>;
async listCommands(
agentId: string,
requestIdOrOptions?: string | ListCommandsOptions,
options?: LegacyListCommandsOptions,
): Promise<ListCommandsPayload>;
async listCommands(
input: ListCommandsOptions | string,
legacyOptions?: LegacyListCommandsOptions | string,
): Promise<ListCommandsPayload> {
const requestId =
typeof requestIdOrOptions === "string" ? requestIdOrOptions : requestIdOrOptions?.requestId;
const draftConfig =
typeof requestIdOrOptions === "string" ? undefined : requestIdOrOptions?.draftConfig;
const options = normalizeListCommandsOptions(input, legacyOptions);
return this.sendCorrelatedSessionRequest({
requestId,
requestId: options.requestId,
message: {
type: "list_commands_request",
agentId,
...(draftConfig ? { draftConfig } : {}),
agentId: options.agentId,
...(options.draftConfig ? { draftConfig: options.draftConfig } : {}),
},
responseType: "list_commands_response",
timeout: 30000,
});
}
@@ -3961,12 +3954,20 @@ export class DaemonClient {
predicate: (snapshot: AgentSnapshotPayload) => boolean,
timeout = 60000,
): Promise<AgentSnapshotPayload> {
const initialResult = await this.fetchAgent(agentId).catch(() => null);
const deadline = Date.now() + timeout;
const remainingTimeoutMs = () => Math.max(1, deadline - Date.now());
const timeoutError = () => new Error(`Timed out waiting for agent ${agentId}`);
const fetchAgentWithinDeadline = () =>
this.fetchAgent({ agentId, timeout: remainingTimeoutMs() }).catch(() => null);
const initialResult = await fetchAgentWithinDeadline();
if (initialResult && predicate(initialResult.agent)) {
return initialResult.agent;
}
if (Date.now() >= deadline) {
throw timeoutError();
}
const deadline = Date.now() + timeout;
return await new Promise<AgentSnapshotPayload>((resolve, reject) => {
let settled = false;
let pollInFlight = false;
@@ -4017,7 +4018,7 @@ export class DaemonClient {
}
pollInFlight = true;
try {
const result = await this.fetchAgent(agentId).catch(() => null);
const result = await fetchAgentWithinDeadline();
maybeResolve(result?.agent ?? null);
} finally {
pollInFlight = false;
@@ -4042,7 +4043,7 @@ export class DaemonClient {
timeoutTimer = setTimeout(() => {
finish({
kind: "error",
error: new Error(`Timed out waiting for agent ${agentId}`),
error: timeoutError(),
});
}, remaining);
@@ -4126,7 +4127,6 @@ export class DaemonClient {
requestId: resolvedRequestId,
message,
responseType: "list_terminals_response",
timeout: 10000,
options: { skipQueue: true },
});
}
@@ -4152,7 +4152,6 @@ export class DaemonClient {
requestId: resolvedRequestId,
message,
responseType: "create_terminal_response",
timeout: 10000,
options: { skipQueue: true },
});
}
@@ -4166,7 +4165,6 @@ export class DaemonClient {
title: input.title,
},
responseType: "terminal.rename.response",
timeout: 10000,
});
}
@@ -4190,7 +4188,6 @@ export class DaemonClient {
requestId: resolvedRequestId,
message,
responseType: "subscribe_terminal_response",
timeout: 10000,
options: { skipQueue: true },
});
if (payload.error === null) {
@@ -4231,7 +4228,6 @@ export class DaemonClient {
requestId: resolvedRequestId,
message,
responseType: "kill_terminal_response",
timeout: 10000,
options: { skipQueue: true },
});
}
@@ -4251,7 +4247,6 @@ export class DaemonClient {
requestId: resolvedRequestId,
message,
responseType: "close_items_response",
timeout: 10000,
options: { skipQueue: true },
});
}
@@ -4274,7 +4269,6 @@ export class DaemonClient {
requestId: resolvedRequestId,
message,
responseType: "capture_terminal_response",
timeout: 10000,
options: { skipQueue: true },
});
}
@@ -4288,7 +4282,6 @@ export class DaemonClient {
...(options.purpose ? { purpose: options.purpose } : {}),
},
responseType: "chat/create/response",
timeout: 10000,
});
}
@@ -4299,7 +4292,6 @@ export class DaemonClient {
type: "chat/list",
},
responseType: "chat/list/response",
timeout: 10000,
});
}
@@ -4311,7 +4303,6 @@ export class DaemonClient {
room: options.room,
},
responseType: "chat/inspect/response",
timeout: 10000,
});
}
@@ -4323,7 +4314,6 @@ export class DaemonClient {
room: options.room,
},
responseType: "chat/delete/response",
timeout: 10000,
});
}
@@ -4338,7 +4328,6 @@ export class DaemonClient {
...(options.replyToMessageId ? { replyToMessageId: options.replyToMessageId } : {}),
},
responseType: "chat/post/response",
timeout: 10000,
});
}
@@ -4353,7 +4342,7 @@ export class DaemonClient {
...(options.authorAgentId ? { authorAgentId: options.authorAgentId } : {}),
},
responseType: "chat/read/response",
timeout: 10000,
timeout: options.timeout,
});
}
@@ -4385,7 +4374,6 @@ export class DaemonClient {
...(typeof options.runOnCreate === "boolean" ? { runOnCreate: options.runOnCreate } : {}),
},
responseType: "schedule/create/response",
timeout: 10000,
});
}
@@ -4396,7 +4384,6 @@ export class DaemonClient {
type: "schedule/list",
},
responseType: "schedule/list/response",
timeout: 10000,
});
}
@@ -4408,7 +4395,6 @@ export class DaemonClient {
scheduleId: options.id,
},
responseType: "schedule/inspect/response",
timeout: 10000,
});
}
@@ -4420,7 +4406,6 @@ export class DaemonClient {
scheduleId: options.id,
},
responseType: "schedule/logs/response",
timeout: 10000,
});
}
@@ -4432,7 +4417,6 @@ export class DaemonClient {
scheduleId: options.id,
},
responseType: "schedule/pause/response",
timeout: 10000,
});
}
@@ -4444,7 +4428,6 @@ export class DaemonClient {
scheduleId: options.id,
},
responseType: "schedule/resume/response",
timeout: 10000,
});
}
@@ -4456,7 +4439,6 @@ export class DaemonClient {
scheduleId: options.id,
},
responseType: "schedule/delete/response",
timeout: 10000,
});
}
@@ -4468,7 +4450,6 @@ export class DaemonClient {
scheduleId: options.id,
},
responseType: "schedule/run-once/response",
timeout: 10000,
});
}
@@ -4486,7 +4467,6 @@ export class DaemonClient {
...(options.expiresAt !== undefined ? { expiresAt: options.expiresAt } : {}),
},
responseType: "schedule/update/response",
timeout: 10000,
});
}
@@ -4515,7 +4495,6 @@ export class DaemonClient {
...(typeof options.maxTimeMs === "number" ? { maxTimeMs: options.maxTimeMs } : {}),
},
responseType: "loop/run/response",
timeout: 15000,
});
}
@@ -4526,7 +4505,6 @@ export class DaemonClient {
type: "loop/list",
},
responseType: "loop/list/response",
timeout: 10000,
});
}
@@ -4539,7 +4517,6 @@ export class DaemonClient {
id: normalized.id,
},
responseType: "loop/inspect/response",
timeout: 10000,
});
}
@@ -4553,7 +4530,6 @@ export class DaemonClient {
...(typeof normalized.afterSeq === "number" ? { afterSeq: normalized.afterSeq } : {}),
},
responseType: "loop/logs/response",
timeout: 10000,
});
}
@@ -4566,7 +4542,6 @@ export class DaemonClient {
id: normalized.id,
},
responseType: "loop/stop/response",
timeout: 10000,
});
}
+1 -1
View File
@@ -472,7 +472,7 @@ function createAgentHandleFactory(daemonClient: DaemonClient): AgentHandleFactor
},
latest: () => latest,
refetch: async (requestId) => {
const result = await daemonClient.fetchAgent(id, requestId);
const result = await daemonClient.fetchAgent({ agentId: id, requestId });
latest = result?.agent ?? null;
return result;
},