





















@@ -4854,6 +4854,95 @@ describe("runAgentTurnWithFallback", () => {
48544854},
48554855);
485648564857+it.each(["group", "channel"] as const)(
4858+"keeps classified non-transient failures visible in Discord %s chats",
4859+async (chatType) => {
4860+state.runEmbeddedPiAgentMock.mockRejectedValueOnce(
4861+new Error('No API key found for provider "openai"'),
4862+);
4863+4864+const runAgentTurnWithFallback = await getRunAgentTurnWithFallback();
4865+const result = await runAgentTurnWithFallback(
4866+createMinimalRunAgentTurnParams({
4867+sessionCtx: {
4868+Provider: "discord",
4869+Surface: "discord",
4870+ChatType: chatType,
4871+GroupSubject: "agent group",
4872+GroupChannel: "#general",
4873+MessageSid: "msg",
4874+} as unknown as TemplateContext,
4875+}),
4876+);
4877+4878+expect(result.kind).toBe("final");
4879+if (result.kind === "final") {
4880+expect(result.payload.text).not.toBe(SILENT_REPLY_TOKEN);
4881+expect(result.payload.text).toContain('Missing API key for provider "openai"');
4882+}
4883+},
4884+);
4885+4886+it.each(["group", "channel"] as const)(
4887+"keeps rate-limit fallback copy out of Discord %s chats",
4888+async (chatType) => {
4889+state.runEmbeddedPiAgentMock.mockRejectedValueOnce(new Error("429 rate limit exceeded"));
4890+4891+const runAgentTurnWithFallback = await getRunAgentTurnWithFallback();
4892+const result = await runAgentTurnWithFallback(
4893+createMinimalRunAgentTurnParams({
4894+sessionCtx: {
4895+Provider: "discord",
4896+Surface: "discord",
4897+ChatType: chatType,
4898+GroupSubject: "agent group",
4899+GroupChannel: "#general",
4900+MessageSid: "msg",
4901+} as unknown as TemplateContext,
4902+}),
4903+);
4904+4905+expect(result.kind).toBe("final");
4906+if (result.kind === "final") {
4907+expect(result.payload.text).toBe(SILENT_REPLY_TOKEN);
4908+}
4909+},
4910+);
4911+4912+it("surfaces rate-limit fallback copy in Discord group chats when silentReply.group is disallow", async () => {
4913+state.runEmbeddedPiAgentMock.mockRejectedValueOnce(new Error("429 rate limit exceeded"));
4914+4915+const followupRun = createFollowupRun();
4916+followupRun.run.config = {
4917+agents: {
4918+defaults: {
4919+silentReply: { group: "disallow" },
4920+},
4921+},
4922+};
4923+4924+const runAgentTurnWithFallback = await getRunAgentTurnWithFallback();
4925+const result = await runAgentTurnWithFallback(
4926+createMinimalRunAgentTurnParams({
4927+ followupRun,
4928+sessionCtx: {
4929+Provider: "discord",
4930+Surface: "discord",
4931+ChatType: "group",
4932+GroupSubject: "agent group",
4933+GroupChannel: "#general",
4934+MessageSid: "msg",
4935+} as unknown as TemplateContext,
4936+}),
4937+);
4938+4939+expect(result.kind).toBe("final");
4940+if (result.kind === "final") {
4941+expect(result.payload.text).not.toBe(SILENT_REPLY_TOKEN);
4942+expect(result.payload.text).toContain("rate-limited");
4943+}
4944+});
4945+48574946it("uses compact generic copy for raw runner failures in normal Discord direct chats", async () => {
48584947state.runEmbeddedPiAgentMock.mockRejectedValueOnce(
48594948new Error("openai-codex/gpt-5.5 ended with an incomplete terminal response"),
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。