Merge cf7c6cb94b75b4ec34b63d1d14ae8ca61de1f32b into 598f1826d8b2bc969aace2c6459824737667218c
This commit is contained in:
commit
65b2fe294a
@ -217,7 +217,7 @@ export function createSessionsSendTool(opts?: {
|
||||
const timeoutSeconds =
|
||||
typeof params.timeoutSeconds === "number" && Number.isFinite(params.timeoutSeconds)
|
||||
? Math.max(0, Math.floor(params.timeoutSeconds))
|
||||
: 30;
|
||||
: 90;
|
||||
const timeoutMs = timeoutSeconds * 1000;
|
||||
const announceTimeoutMs = timeoutSeconds === 0 ? 30_000 : timeoutMs;
|
||||
const idempotencyKey = crypto.randomUUID();
|
||||
@ -321,15 +321,21 @@ export function createSessionsSendTool(opts?: {
|
||||
} catch (err) {
|
||||
const messageText =
|
||||
err instanceof Error ? err.message : typeof err === "string" ? err : "error";
|
||||
const isTimeout = messageText.includes("gateway timeout");
|
||||
if (isTimeout) {
|
||||
// Same late-reply fix: deliver via A2A when gateway-level timeout fires
|
||||
startA2AFlow(undefined, runId);
|
||||
}
|
||||
return jsonResult({
|
||||
runId,
|
||||
status: messageText.includes("gateway timeout") ? "timeout" : "error",
|
||||
status: isTimeout ? "timeout" : "error",
|
||||
error: messageText,
|
||||
sessionKey: displayKey,
|
||||
});
|
||||
}
|
||||
|
||||
if (waitStatus === "timeout") {
|
||||
startA2AFlow(undefined, runId);
|
||||
return jsonResult({
|
||||
runId,
|
||||
status: "timeout",
|
||||
|
||||
@ -9,6 +9,11 @@ vi.mock("../../gateway/call.js", () => ({
|
||||
callGateway: (opts: unknown) => callGatewayMock(opts),
|
||||
}));
|
||||
|
||||
const runSessionsSendA2AFlowMock = vi.fn();
|
||||
vi.mock("./sessions-send-tool.a2a.js", () => ({
|
||||
runSessionsSendA2AFlow: (opts: unknown) => runSessionsSendA2AFlowMock(opts),
|
||||
}));
|
||||
|
||||
type SessionsToolTestConfig = {
|
||||
session: { scope: "per-sender"; mainKey: string };
|
||||
tools: {
|
||||
@ -399,6 +404,7 @@ describe("sessions_list transcriptPath resolution", () => {
|
||||
describe("sessions_send gating", () => {
|
||||
beforeEach(() => {
|
||||
callGatewayMock.mockClear();
|
||||
runSessionsSendA2AFlowMock.mockClear();
|
||||
});
|
||||
|
||||
it("returns an error when neither sessionKey nor label is provided", async () => {
|
||||
@ -449,4 +455,54 @@ describe("sessions_send gating", () => {
|
||||
expect(callGatewayMock.mock.calls[0]?.[0]).toMatchObject({ method: "sessions.list" });
|
||||
expect(result.details).toMatchObject({ status: "forbidden" });
|
||||
});
|
||||
|
||||
it("sessions_send delivers reply via A2A when wait times out", async () => {
|
||||
loadConfigMock.mockReturnValue({
|
||||
session: { scope: "per-sender", mainKey: "main" },
|
||||
tools: {
|
||||
agentToAgent: { enabled: true },
|
||||
sessions: { visibility: "all" },
|
||||
},
|
||||
});
|
||||
|
||||
const targetKey = "agent:main:discord:dm:user1";
|
||||
const fakeRunId = "run-timeout-123";
|
||||
|
||||
// sessions.list for visibility check
|
||||
callGatewayMock.mockImplementation((opts: { method: string }) => {
|
||||
if (opts.method === "sessions.list") {
|
||||
return Promise.resolve({
|
||||
path: "/tmp/sessions.json",
|
||||
sessions: [
|
||||
{ key: targetKey, kind: "direct" },
|
||||
{ key: MAIN_AGENT_SESSION_KEY, kind: "direct" },
|
||||
],
|
||||
});
|
||||
}
|
||||
if (opts.method === "agent") {
|
||||
return Promise.resolve({ runId: fakeRunId });
|
||||
}
|
||||
if (opts.method === "agent.wait") {
|
||||
return Promise.resolve({ status: "timeout", error: "timed out" });
|
||||
}
|
||||
return Promise.resolve({});
|
||||
});
|
||||
|
||||
const tool = createMainSessionsSendTool();
|
||||
const result = await tool.execute("call-timeout", {
|
||||
sessionKey: targetKey,
|
||||
message: "ping",
|
||||
timeoutSeconds: 5,
|
||||
});
|
||||
|
||||
expect(result.details).toMatchObject({
|
||||
status: "timeout",
|
||||
runId: fakeRunId,
|
||||
});
|
||||
|
||||
expect(runSessionsSendA2AFlowMock).toHaveBeenCalledTimes(1);
|
||||
const a2aArgs = runSessionsSendA2AFlowMock.mock.calls[0]?.[0] as Record<string, unknown>;
|
||||
expect(a2aArgs.waitRunId).toBe(fakeRunId);
|
||||
expect(a2aArgs.roundOneReply).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user