





















@@ -56,6 +56,29 @@ type SessionsListResult = Awaited<
5656ReturnType<ReturnType<typeof import("./sessions-list-tool.js").createSessionsListTool>["execute"]>
5757>;
585859+function requireRecord(value: unknown, label: string): Record<string, unknown> {
60+if (!value || typeof value !== "object" || Array.isArray(value)) {
61+throw new Error(`expected ${label}`);
62+}
63+return value as Record<string, unknown>;
64+}
65+66+function requireDetails(result: { details?: unknown }, label = "result details") {
67+return requireRecord(result.details, label);
68+}
69+70+function requireSessions(details: Record<string, unknown>) {
71+const sessions = details.sessions;
72+if (!Array.isArray(sessions)) {
73+throw new Error("expected details.sessions");
74+}
75+return sessions.map((session, index) => requireRecord(session, `session ${index}`));
76+}
77+78+function requireGatewayRequest(index = 0) {
79+return requireRecord(callGatewayMock.mock.calls[index]?.[0], `gateway request ${index}`);
80+}
81+5982beforeAll(async () => {
6083({ createSessionsListTool } = await import("./sessions-list-tool.js"));
6184({ createSessionsSendTool } = await import("./sessions-send-tool.js"));
@@ -167,7 +190,7 @@ function expectWorkerTranscriptPath(
167190params: { containsPath: string; sessionId: string },
168191) {
169192const session = getFirstListedSession(result);
170-expect(session).toMatchObject({ key: "agent:worker:main" });
193+expect(session?.key).toBe("agent:worker:main");
171194const transcriptPath = session?.transcriptPath ?? "";
172195expect(path.normalize(transcriptPath)).toContain(path.normalize(params.containsPath));
173196expect(transcriptPath).toMatch(new RegExp(`${params.sessionId}\\.jsonl$`));
@@ -328,8 +351,7 @@ describe("resolveAnnounceTarget", () => {
328351threadId: "99",
329352});
330353expect(callGatewayMock).toHaveBeenCalledTimes(1);
331-const first = callGatewayMock.mock.calls[0]?.[0] as { method?: string } | undefined;
332-expect(first).toMatchObject({ method: "sessions.list" });
354+expect(requireGatewayRequest().method).toBe("sessions.list");
333355});
334356335357it("falls back to origin provider and accountId from sessions.list when legacy route fields are absent", async () => {
@@ -435,10 +457,9 @@ describe("sessions_list gating", () => {
435457it("filters out other agents when tools.agentToAgent.enabled is false", async () => {
436458const tool = createMainSessionsListTool();
437459const result = await tool.execute("call1", {});
438-expect(result.details).toMatchObject({
439-count: 1,
440-sessions: [{ key: MAIN_AGENT_SESSION_KEY }],
441-});
460+const details = requireDetails(result);
461+expect(details.count).toBe(1);
462+expect(requireSessions(details)[0]?.key).toBe(MAIN_AGENT_SESSION_KEY);
442463});
443464444465it("keeps requester-owned cross-agent rows with tree visibility without a spawned lookup", async () => {
@@ -462,10 +483,11 @@ describe("sessions_list gating", () => {
462483463484const result = await createMainSessionsListTool().execute("call1", {});
464485465-expect(result.details).toMatchObject({
466-count: 1,
467-sessions: [{ key: "agent:codex:acp:child-1", spawnedBy: MAIN_AGENT_SESSION_KEY }],
468-});
486+const details = requireDetails(result);
487+expect(details.count).toBe(1);
488+const session = requireSessions(details)[0];
489+expect(session?.key).toBe("agent:codex:acp:child-1");
490+expect(session?.spawnedBy).toBe(MAIN_AGENT_SESSION_KEY);
469491expect(callGatewayMock).toHaveBeenCalledTimes(1);
470492});
471493@@ -490,10 +512,11 @@ describe("sessions_list gating", () => {
490512491513const result = await createMainSessionsListTool().execute("call1", {});
492514493-expect(result.details).toMatchObject({
494-count: 1,
495-sessions: [{ key: "agent:codex:acp:child-1", parentSessionKey: MAIN_AGENT_SESSION_KEY }],
496-});
515+const details = requireDetails(result);
516+expect(details.count).toBe(1);
517+const session = requireSessions(details)[0];
518+expect(session?.key).toBe("agent:codex:acp:child-1");
519+expect(session?.parentSessionKey).toBe(MAIN_AGENT_SESSION_KEY);
497520expect(callGatewayMock).toHaveBeenCalledTimes(1);
498521});
499522@@ -653,9 +676,10 @@ describe("sessions_list channel derivation", () => {
653676});
654677const result = await executeMainSessionsList();
655678656-expect(result.details).toMatchObject({
657-sessions: [{ key: "agent:main:discord:group:ops", channel: "discord" }],
658-});
679+const details = requireDetails(result);
680+const session = requireSessions(details)[0];
681+expect(session?.key).toBe("agent:main:discord:group:ops");
682+expect(session?.channel).toBe("discord");
659683});
660684});
661685@@ -672,10 +696,9 @@ describe("sessions_send gating", () => {
672696timeoutSeconds: 5,
673697});
674698675-expect(result.details).toMatchObject({
676-status: "error",
677-error: "Either sessionKey or label is required",
678-});
699+const details = requireDetails(result);
700+expect(details.status).toBe("error");
701+expect(details.error).toBe("Either sessionKey or label is required");
679702expect(callGatewayMock).not.toHaveBeenCalled();
680703});
681704@@ -689,14 +712,13 @@ describe("sessions_send gating", () => {
689712timeoutSeconds: 5,
690713});
691714692-expect(result.details).toMatchObject({
693-status: "error",
694-});
715+const details = requireDetails(result);
716+expect(details.status).toBe("error");
695717expect((result.details as { error?: string } | undefined)?.error ?? "").toContain(
696718"No session found with label",
697719);
698720expect(callGatewayMock).toHaveBeenCalledTimes(1);
699-expect(callGatewayMock.mock.calls[0]?.[0]).toMatchObject({ method: "sessions.resolve" });
721+expect(requireGatewayRequest().method).toBe("sessions.resolve");
700722});
701723702724it("blocks cross-agent sends when tools.agentToAgent.enabled is false", async () => {
@@ -709,8 +731,8 @@ describe("sessions_send gating", () => {
709731});
710732711733expect(callGatewayMock).toHaveBeenCalledTimes(1);
712-expect(callGatewayMock.mock.calls[0]?.[0]).toMatchObject({ method: "sessions.list" });
713-expect(result.details).toMatchObject({ status: "forbidden" });
734+expect(requireGatewayRequest().method).toBe("sessions.list");
735+expect(requireDetails(result).status).toBe("forbidden");
714736});
715737716738it("rejects direct thread session targets before dispatching an agent run", async () => {
@@ -730,10 +752,9 @@ describe("sessions_send gating", () => {
730752timeoutSeconds: 0,
731753});
732754733-expect(result.details).toMatchObject({
734-status: "error",
735-sessionKey: threadSessionKey,
736-});
755+const details = requireDetails(result);
756+expect(details.status).toBe("error");
757+expect(details.sessionKey).toBe(threadSessionKey);
737758expect((result.details as { error?: string } | undefined)?.error ?? "").toContain(
738759"cannot target a thread session",
739760);
@@ -758,15 +779,14 @@ describe("sessions_send gating", () => {
758779timeoutSeconds: 0,
759780});
760781761-expect(result.details).toMatchObject({
762-status: "error",
763-sessionKey: threadSessionKey,
764-});
782+const details = requireDetails(result);
783+expect(details.status).toBe("error");
784+expect(details.sessionKey).toBe(threadSessionKey);
765785expect((result.details as { error?: string } | undefined)?.error ?? "").toContain(
766786"cannot target a thread session",
767787);
768788expect(callGatewayMock).toHaveBeenCalledTimes(1);
769-expect(callGatewayMock.mock.calls[0]?.[0]).toMatchObject({ method: "sessions.resolve" });
789+expect(requireGatewayRequest().method).toBe("sessions.resolve");
770790});
771791772792it("does not reuse a stale assistant reply when no new reply appears", async () => {
@@ -806,10 +826,9 @@ describe("sessions_send gating", () => {
806826});
807827808828expect(historyCalls).toBe(2);
809-expect(result.details).toMatchObject({
810-status: "ok",
811-reply: undefined,
812-sessionKey: MAIN_AGENT_SESSION_KEY,
813-});
829+const details = requireDetails(result);
830+expect(details.status).toBe("ok");
831+expect(details.reply).toBeUndefined();
832+expect(details.sessionKey).toBe(MAIN_AGENT_SESSION_KEY);
814833});
815834});
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。