Show agent history errors without a one-minute wait (#2124)
* fix(client): fail invalid RPC responses immediately Correlated responses that failed schema validation were discarded before request matching, leaving callers blocked until the RPC timeout. Preserve only the raw correlation identity at the boundary so the matching request fails with a protocol error. * test(client): preserve invalid response diagnostics * fix(client): ignore invalid correlated progress events
This commit is contained in:
@@ -4947,9 +4947,13 @@ test("parses canonical fetch_agent_timeline_response payloads without crashing",
|
||||
expect(logger.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("drops invalid fetch_agent_timeline_response tool_call payloads and logs validation warning", async () => {
|
||||
const logger = createMockLogger();
|
||||
test("rejects and logs a correlated response that violates the protocol schema", async () => {
|
||||
const mock = createMockTransport();
|
||||
const warnings: string[] = [];
|
||||
const logger: Logger = {
|
||||
...noopLogger,
|
||||
warn: (_fields, message) => warnings.push(message ?? ""),
|
||||
};
|
||||
|
||||
const client = new DaemonClient({
|
||||
url: "ws://test",
|
||||
@@ -4964,9 +4968,9 @@ test("drops invalid fetch_agent_timeline_response tool_call payloads and logs va
|
||||
mock.triggerOpen();
|
||||
await connectPromise;
|
||||
|
||||
const received: unknown[] = [];
|
||||
const unsubscribe = client.on("fetch_agent_timeline_response", (msg) => {
|
||||
received.push(msg);
|
||||
const response = client.fetchAgentTimeline("agent_cli", {
|
||||
requestId: "req-invalid",
|
||||
timeout: 1,
|
||||
});
|
||||
|
||||
mock.triggerMessage(
|
||||
@@ -5013,10 +5017,56 @@ test("drops invalid fetch_agent_timeline_response tool_call payloads and logs va
|
||||
}),
|
||||
);
|
||||
|
||||
unsubscribe();
|
||||
await expect(response).rejects.toMatchObject({
|
||||
requestId: "req-invalid",
|
||||
message: expect.stringMatching(/validation/i),
|
||||
});
|
||||
expect(warnings).toEqual(["Message validation failed"]);
|
||||
});
|
||||
|
||||
expect(received).toHaveLength(0);
|
||||
expect(logger.warn).toHaveBeenCalled();
|
||||
test("does not reject a request for an invalid correlated progress event", async () => {
|
||||
const mock = createMockTransport();
|
||||
const client = new DaemonClient({
|
||||
url: "ws://test",
|
||||
clientId: "clsk_unit_test",
|
||||
logger: noopLogger,
|
||||
reconnect: { enabled: false },
|
||||
transportFactory: () => mock.transport,
|
||||
});
|
||||
clients.push(client);
|
||||
|
||||
const connectPromise = client.connect();
|
||||
mock.triggerOpen();
|
||||
await connectPromise;
|
||||
|
||||
const response = client.updateDaemon("req-update");
|
||||
|
||||
mock.triggerMessage(
|
||||
wrapSessionMessage({
|
||||
type: "daemon.update.progress",
|
||||
payload: {
|
||||
requestId: "req-update",
|
||||
phase: "verifying",
|
||||
},
|
||||
}),
|
||||
);
|
||||
mock.triggerMessage(
|
||||
wrapSessionMessage({
|
||||
type: "daemon.update.response",
|
||||
payload: {
|
||||
requestId: "req-update",
|
||||
success: true,
|
||||
error: null,
|
||||
previousVersion: "0.1.106",
|
||||
newVersion: "0.1.107",
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
await expect(response).resolves.toMatchObject({
|
||||
requestId: "req-update",
|
||||
success: true,
|
||||
});
|
||||
});
|
||||
|
||||
test("sends subscribe/unsubscribe terminals messages", async () => {
|
||||
|
||||
Reference in New Issue
Block a user