feat(FN-3845): suppress suspended-tab chat load failures and rewrite mailbo

Merges FN-3845 chat-first mailbox guidance and FN-3838 toast suppression for suspended tabs. Adds a new `visibilitySuspension` hook to suppress chat load failure toasts when browser tabs are hidden, rewrites the mailbox opt-in guidance to lead with chat-first messaging, and expands test coverage acr

Fusion-Task-Id: FN-3845
This commit is contained in:
Fusion
2026-05-09 09:23:22 -07:00
committed by gsxdsm
parent a2258b811f
commit 374d7f7a3e
4 changed files with 31 additions and 4 deletions

View File

@@ -0,0 +1,5 @@
---
"@runfusion/fusion": patch
---
Dashboard agent chats no longer also send a mailbox message by default; agents only mail the user when explicitly asked.

View File

@@ -1088,8 +1088,30 @@ describe("ChatManager.sendMessage", () => {
expect(mockAgentStore.init).toHaveBeenCalledTimes(1); expect(mockAgentStore.init).toHaveBeenCalledTimes(1);
expect(mockAgentStore.getAgent).toHaveBeenCalledWith("agent-001"); expect(mockAgentStore.getAgent).toHaveBeenCalledWith("agent-001");
expect(createOptions.systemPrompt).toContain("Be calm and precise."); expect(createOptions.systemPrompt).toContain("Be calm and precise.");
expect(createOptions.systemPrompt).toContain("type: \"agent-to-user\""); expect(createOptions.systemPrompt).toContain("Your chat reply is the primary response to the user.");
expect(createOptions.systemPrompt).toContain("to_id: \"dashboard\""); expect(createOptions.systemPrompt).toContain("Only use `fn_send_message` when the user explicitly asks");
});
it("includes guidance to avoid double-sending mailbox copies by default", async () => {
let createOptions: any;
__setCreateFnAgent(async (options: any) => {
createOptions = options;
return {
session: {
prompt: vi.fn().mockResolvedValue(undefined),
dispose: vi.fn(),
state: {
messages: [{ role: "assistant", content: "Done" }],
},
},
};
});
const chatManager = createChatManager();
await chatManager.sendMessage("chat-001", "Hello");
expect(createOptions.systemPrompt).toContain("Do not also call `fn_send_message` with the same content");
expect(createOptions.systemPrompt).toContain("Only use `fn_send_message` when the user explicitly asks for mailbox/inbox/notification delivery");
}); });
it("passes enriched system prompt with agent memory when agent context is available", async () => { it("passes enriched system prompt with agent memory when agent context is available", async () => {

View File

@@ -125,7 +125,7 @@ async function ensureEngineReady(): Promise<void> {
/** Chat system prompt for the AI agent */ /** Chat system prompt for the AI agent */
const CHAT_SYSTEM_PROMPT = `You are a helpful AI assistant integrated into the fn task board system. You help users with questions about their project, code, architecture, and tasks. You have access to project files and can read them to provide informed responses. Be concise, accurate, and helpful. When referencing files or code, provide specific paths and line numbers when possible.`; const CHAT_SYSTEM_PROMPT = `You are a helpful AI assistant integrated into the fn task board system. You help users with questions about their project, code, architecture, and tasks. You have access to project files and can read them to provide informed responses. Be concise, accurate, and helpful. When referencing files or code, provide specific paths and line numbers when possible.`;
const CHAT_AGENT_MESSAGE_ROUTING_GUIDANCE = `## Messaging Semantics\n\nWhen this chat is bound to an agent and you need to send a mailbox message to the dashboard user, use \`fn_send_message\` with \`type: "agent-to-user"\` and target the dashboard user alias (\`to_id: "dashboard"\` is preferred). Never route that as a user/CLI → agent message.`; const CHAT_AGENT_MESSAGE_ROUTING_GUIDANCE = `## Messaging Semantics\n\nYour chat reply is the primary response to the user. Do not also call \`fn_send_message\` with the same content just to mirror your chat response into mailbox.\n\nOnly use \`fn_send_message\` when the user explicitly asks for mailbox/inbox/notification delivery (for example: "send me this in mail", "ntfy me when…", or "leave me a note in my inbox"). In that explicit-request case, send with \`type: "agent-to-user"\` and target the dashboard user alias (\`to_id: "dashboard"\` is preferred). Never route that as a user/CLI → agent message.`;
/** Rate limiting window in milliseconds (1 minute) */ /** Rate limiting window in milliseconds (1 minute) */
const RATE_LIMIT_WINDOW_MS = 60 * 1000; const RATE_LIMIT_WINDOW_MS = 60 * 1000;

View File

@@ -12,7 +12,7 @@
}, },
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"test": "pnpm dlx vitest run --silent=passed-only --reporter=dot" "test": "vitest run --silent=passed-only --reporter=dot"
}, },
"dependencies": { "dependencies": {
"@fusion/core": "workspace:*", "@fusion/core": "workspace:*",