




























@@ -167,6 +167,60 @@ const waitForCalls = async (getCount: () => number, count: number, timeoutMs = 2
167167);
168168};
169169170+type GatewayCall = {
171+method?: string;
172+params?: Record<string, unknown>;
173+};
174+175+type AgentCallParams = {
176+message?: string;
177+lane?: string;
178+channel?: string;
179+sessionKey?: string;
180+extraSystemPrompt?: string;
181+inputProvenance?: {
182+kind?: string;
183+sourceSessionKey?: string;
184+};
185+};
186+187+type SessionsSendDetails = {
188+status?: string;
189+runId?: string;
190+reply?: string;
191+error?: string;
192+sessionKey?: string;
193+delivery?: {
194+status?: string;
195+mode?: string;
196+};
197+};
198+199+function requireGatewayCall(call: unknown, method: string): GatewayCall {
200+const request = call as GatewayCall | undefined;
201+if (request?.method !== method) {
202+throw new Error(`expected ${method} gateway call`);
203+}
204+return request;
205+}
206+207+function agentParams(call: { params?: unknown }): AgentCallParams {
208+return (call.params ?? {}) as AgentCallParams;
209+}
210+211+function expectInterSessionAgentCall(call: { params?: unknown }): void {
212+const params = agentParams(call);
213+expect(params.message).toContain("[Inter-session message");
214+expect(params.message).toContain("isUser=false");
215+expect(params.lane).toMatch(/^nested(?::|$)/);
216+expect(params.channel).toBe("webchat");
217+expect(params.inputProvenance?.kind).toBe("inter_session");
218+}
219+220+function sessionsSendDetails(details: unknown): SessionsSendDetails {
221+return details as SessionsSendDetails;
222+}
223+170224describe("sessions tools", () => {
171225beforeEach(() => {
172226callGatewayMock.mockClear();
@@ -450,11 +504,10 @@ describe("sessions tools", () => {
450504}>;
451505};
452506expect(details.sessions).toHaveLength(1);
453-expect(details.sessions?.[0]).toMatchObject({
454-key: "agent:main:main",
455-derivedTitle: "Visible project kickoff",
456-lastMessagePreview: "Visible latest reply",
457-});
507+const visible = details.sessions?.[0];
508+expect(visible?.key).toBe("agent:main:main");
509+expect(visible?.derivedTitle).toBe("Visible project kickoff");
510+expect(visible?.lastMessagePreview).toBe("Visible latest reply");
458511expect(JSON.stringify(details.sessions)).not.toContain("Hidden");
459512} finally {
460513fs.rmSync(tmpDir, { recursive: true, force: true });
@@ -761,10 +814,8 @@ describe("sessions tools", () => {
761814const historyCall = callGatewayMock.mock.calls.find(
762815(call) => (call[0] as { method?: string }).method === "chat.history",
763816);
764-expect(historyCall?.[0]).toMatchObject({
765-method: "chat.history",
766-params: { sessionKey: targetKey },
767-});
817+const request = requireGatewayCall(historyCall?.[0], "chat.history");
818+expect(request.params?.sessionKey).toBe(targetKey);
768819});
769820770821it("sessions_history errors on missing sessionId", async () => {
@@ -864,11 +915,11 @@ describe("sessions tools", () => {
864915message: "ping",
865916timeoutSeconds: 0,
866917});
867-expect(fire.details).toMatchObject({
868- status: "accepted",
869- runId: "run-1",
870- delivery: { status: "pending", mode: "announce" },
871-});
918+const fireDetails = sessionsSendDetails(fire.details);
919+expect(fireDetails.status).toBe("accepted");
920+expect(fireDetails.runId).toBe("run-1");
921+expect(fireDetails.delivery?.status).toBe("pending");
922+expect(fireDetails.delivery?.mode).toBe("announce");
872923await waitForCalls(() => agentCallCount, 3);
873924await waitForCalls(() => waitCallCount, 3);
874925await waitForCalls(() => historyCallCount, 3);
@@ -879,11 +930,11 @@ describe("sessions tools", () => {
879930timeoutSeconds: 1,
880931});
881932const waited = await waitPromise;
882-expect(waited.details).toMatchObject({
883- status: "ok",
884- reply: "done",
885- delivery: { status: "pending", mode: "announce" },
886-});
933+const waitedDetails = sessionsSendDetails(waited.details);
934+expect(waitedDetails.status).toBe("ok");
935+expect(waitedDetails.reply).toBe("done");
936+expect(waitedDetails.delivery?.status).toBe("pending");
937+expect(waitedDetails.delivery?.mode).toBe("announce");
887938expect(typeof (waited.details as { runId?: string }).runId).toBe("string");
888939await waitForCalls(() => agentCallCount, 6);
889940await waitForCalls(() => waitCallCount, 6);
@@ -894,13 +945,7 @@ describe("sessions tools", () => {
894945const historyOnlyCalls = calls.filter((call) => call.method === "chat.history");
895946expect(agentCalls).toHaveLength(6);
896947for (const call of agentCalls) {
897-expect(call.params).toMatchObject({
898-message: expect.stringContaining("[Inter-session message"),
899-lane: expect.stringMatching(/^nested(?::|$)/),
900-channel: "webchat",
901-inputProvenance: { kind: "inter_session" },
902-});
903-expect((call.params as { message?: string }).message).toContain("isUser=false");
948+expectInterSessionAgentCall(call);
904949}
905950expect(
906951agentCalls.some(
@@ -966,10 +1011,8 @@ describe("sessions tools", () => {
9661011const agentCall = callGatewayMock.mock.calls.find(
9671012(call) => (call[0] as { method?: string }).method === "agent",
9681013);
969-expect(agentCall?.[0]).toMatchObject({
970-method: "agent",
971-params: { sessionKey: targetKey },
972-});
1014+const request = requireGatewayCall(agentCall?.[0], "agent");
1015+expect(request.params?.sessionKey).toBe(targetKey);
9731016});
97410179751018it("sessions_send runs ping-pong then announces", async () => {
@@ -1058,10 +1101,9 @@ describe("sessions tools", () => {
10581101message: "ping",
10591102timeoutSeconds: 1,
10601103});
1061-expect(waited.details).toMatchObject({
1062-status: "ok",
1063-reply: "initial",
1064-});
1104+const waitedDetails = sessionsSendDetails(waited.details);
1105+expect(waitedDetails.status).toBe("ok");
1106+expect(waitedDetails.reply).toBe("initial");
10651107await vi.waitFor(
10661108() => {
10671109expect(countMatching(calls, (call) => call.method === "agent")).toBe(3);
@@ -1072,11 +1114,10 @@ describe("sessions tools", () => {
10721114const agentCalls = calls.filter((call) => call.method === "agent");
10731115expect(agentCalls).toHaveLength(3);
10741116for (const call of agentCalls) {
1075-expect(call.params).toMatchObject({
1076-lane: expect.stringMatching(/^nested(?::|$)/),
1077-channel: "webchat",
1078-inputProvenance: { kind: "inter_session" },
1079-});
1117+const params = agentParams(call);
1118+expect(params.lane).toMatch(/^nested(?::|$)/);
1119+expect(params.channel).toBe("webchat");
1120+expect(params.inputProvenance?.kind).toBe("inter_session");
10801121}
1081112210821123const replySteps = calls.filter(
@@ -1088,11 +1129,9 @@ describe("sessions tools", () => {
10881129),
10891130);
10901131expect(replySteps).toHaveLength(2);
1091-expect(sendParams).toMatchObject({
1092-to: "group:target",
1093-channel: "discord",
1094-message: "announce now",
1095-});
1132+expect(sendParams.to).toBe("group:target");
1133+expect(sendParams.channel).toBe("discord");
1134+expect(sendParams.message).toBe("announce now");
10961135});
1097113610981137it("sessions_send keeps delayed requester replies alive after a wait timeout", async () => {
@@ -1173,11 +1212,11 @@ describe("sessions tools", () => {
11731212message: "ping",
11741213timeoutSeconds: 1,
11751214});
1176-expect(result.details).toMatchObject({
1177- status: "accepted",
1178- sessionKey: targetKey,
1179- delivery: { status: "pending", mode: "announce" },
1180-});
1215+const details = sessionsSendDetails(result.details);
1216+expect(details.status).toBe("accepted");
1217+expect(details.sessionKey).toBe(targetKey);
1218+expect(details.delivery?.status).toBe("pending");
1219+expect(details.delivery?.mode).toBe("announce");
1181122011821221await vi.waitFor(
11831222() => {
@@ -1206,10 +1245,8 @@ describe("sessions tools", () => {
12061245sessionKey?: string;
12071246}
12081247| undefined;
1209-expect(replyParams).toMatchObject({
1210-sessionKey: requesterKey,
1211-inputProvenance: { sourceSessionKey: targetKey },
1212-});
1248+expect(replyParams?.sessionKey).toBe(requesterKey);
1249+expect(replyParams?.inputProvenance?.sourceSessionKey).toBe(targetKey);
12131250expect(replyParams?.message).toContain("late director reply");
12141251expect(replyParams?.extraSystemPrompt).toContain("Agent-to-agent reply step");
12151252expect(replyParams?.extraSystemPrompt).toContain("Current agent: Agent 1 (requester)");
@@ -1254,11 +1291,10 @@ describe("sessions tools", () => {
12541291message: "ping",
12551292timeoutSeconds: 1,
12561293});
1257-expect(result.details).toMatchObject({
1258-status: "timeout",
1259-error: "agent run timed out",
1260-sessionKey: targetKey,
1261-});
1294+const details = sessionsSendDetails(result.details);
1295+expect(details.status).toBe("timeout");
1296+expect(details.error).toBe("agent run timed out");
1297+expect(details.sessionKey).toBe(targetKey);
12621298await new Promise((resolve) => setTimeout(resolve, 0));
12631299expect(countMatching(calls, (call) => call.method === "agent")).toBe(1);
12641300});
@@ -1322,11 +1358,11 @@ describe("sessions tools", () => {
13221358timeoutSeconds: 1,
13231359});
132413601325-expect(waited.details).toMatchObject({
1326- status: "ok",
1327- reply: "child reply",
1328- delivery: { status: "skipped", mode: "announce" },
1329-});
1361+const waitedDetails = sessionsSendDetails(waited.details);
1362+expect(waitedDetails.status).toBe("ok");
1363+expect(waitedDetails.reply).toBe("child reply");
1364+expect(waitedDetails.delivery?.status).toBe("skipped");
1365+expect(waitedDetails.delivery?.mode).toBe("announce");
13301366expect(countMatching(calls, (call) => call.method === "agent")).toBe(1);
13311367const replyPromptAgentCalls = calls.filter(
13321368(call) =>
@@ -1455,23 +1491,20 @@ describe("sessions tools", () => {
14551491message: "ping",
14561492timeoutSeconds: 1,
14571493});
1458-expect(waited.details).toMatchObject({
1459-status: "ok",
1460-reply: "initial",
1461-});
1494+const waitedDetails = sessionsSendDetails(waited.details);
1495+expect(waitedDetails.status).toBe("ok");
1496+expect(waitedDetails.reply).toBe("initial");
14621497await vi.waitFor(
14631498() => {
14641499expect(countMatching(calls, (call) => call.method === "send")).toBe(1);
14651500},
14661501{ timeout: 2_000, interval: 5 },
14671502);
146815031469-expect(sendParams).toMatchObject({
1470-to: "123@g.us",
1471-channel: "whatsapp",
1472-accountId: "work",
1473-message: "announce now",
1474-threadId: "99",
1475-});
1504+expect(sendParams.to).toBe("123@g.us");
1505+expect(sendParams.channel).toBe("whatsapp");
1506+expect(sendParams.accountId).toBe("work");
1507+expect(sendParams.message).toBe("announce now");
1508+expect(sendParams.threadId).toBe("99");
14761509});
14771510});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。