

























@@ -658,6 +658,62 @@ describe("sessions_send gating", () => {
658658expect(result.details).toMatchObject({ status: "forbidden" });
659659});
660660661+it("rejects direct thread session targets before dispatching an agent run", async () => {
662+loadConfigMock.mockReturnValue({
663+session: { scope: "per-sender", mainKey: "main" },
664+tools: {
665+agentToAgent: { enabled: false },
666+sessions: { visibility: "all" },
667+},
668+});
669+const threadSessionKey = "agent:main:slack:channel:C123:thread:1710000000.000100";
670+const tool = createMainSessionsSendTool();
671+672+const result = await tool.execute("call-thread-target", {
673+sessionKey: threadSessionKey,
674+message: "hi",
675+timeoutSeconds: 0,
676+});
677+678+expect(result.details).toMatchObject({
679+status: "error",
680+sessionKey: threadSessionKey,
681+});
682+expect((result.details as { error?: string } | undefined)?.error ?? "").toContain(
683+"cannot target a thread session",
684+);
685+expect(callGatewayMock).not.toHaveBeenCalled();
686+});
687+688+it("rejects label targets that resolve to canonical thread sessions", async () => {
689+loadConfigMock.mockReturnValue({
690+session: { scope: "per-sender", mainKey: "main" },
691+tools: {
692+agentToAgent: { enabled: false },
693+sessions: { visibility: "all" },
694+},
695+});
696+const threadSessionKey = "agent:main:discord:channel:123456:thread:987654";
697+callGatewayMock.mockResolvedValueOnce({ key: threadSessionKey });
698+const tool = createMainSessionsSendTool();
699+700+const result = await tool.execute("call-thread-label", {
701+label: "active thread",
702+message: "hi",
703+timeoutSeconds: 0,
704+});
705+706+expect(result.details).toMatchObject({
707+status: "error",
708+sessionKey: threadSessionKey,
709+});
710+expect((result.details as { error?: string } | undefined)?.error ?? "").toContain(
711+"cannot target a thread session",
712+);
713+expect(callGatewayMock).toHaveBeenCalledTimes(1);
714+expect(callGatewayMock.mock.calls[0]?.[0]).toMatchObject({ method: "sessions.resolve" });
715+});
716+661717it("does not reuse a stale assistant reply when no new reply appears", async () => {
662718const tool = createMainSessionsSendTool();
663719let historyCalls = 0;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。