Assistant: reliable "Nueva conversación" reset
All checks were successful
Deploy to VPS / test (push) Successful in 1m33s
Deploy to VPS / deploy (push) Successful in 29s

Clearing in place (setMessages + remount) left the conversation
rendered — CopilotKit keeps chat state beyond agent.messages — so the
button now reloads the page after deleting the thread: a fresh boot
hydrates from the empty store and shows the welcome screen with
suggestions, which previously only appeared after a manual refresh.

Supporting changes:
- CopilotChat gets an explicit agentId="wealthysmart" (without it, it
  resolves DEFAULT_AGENT_ID and can bind a different client agent
  instance than useAgent's).
- The BFF answers CopilotChat's POST …/connect with an
  immediately-completed stream: the runtime's in-memory runner replays
  this PROCESS's event history, which resurrects cleared conversations
  and double-feeds hydration. The empty-messages hydration run against
  the DB store is the single restore path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Carlos Escalante
2026-07-04 19:33:41 -06:00
parent 7b7c741ba2
commit 0f34a64e51
2 changed files with 26 additions and 3 deletions

View File

@@ -384,12 +384,28 @@ app.use("*", async (c, next) => {
});
app.all("/api/copilotkit/*", async (c) => {
// CopilotChat fires POST …/agent/<id>/connect for explicit threadIds and
// the runtime's in-memory runner replays THIS PROCESS's event history —
// stale relative to the DB store (it resurrects cleared conversations and
// double-feeds page-load hydration). The empty-messages hydration run
// against MAF is our single restore path, so connect gets an
// immediately-completed stream instead.
if (new URL(c.req.url).pathname.endsWith("/connect")) {
return new Response("", {
status: 200,
headers: { "Content-Type": "text/event-stream" },
});
}
const cookieHeader = c.req.header("cookie") ?? "";
const match = cookieHeader.match(/(?:^|;\s*)ws_token=([^;]+)/);
const token = match?.[1];
const agentHeaders: Record<string, string> = token
? { Authorization: `Bearer ${token}` }
: {};
// Note: the browser's X-Client-Timezone header (set in App.tsx) reaches
// the backend without help — CopilotKit's runtime forwards authorization
// and all x-* headers to the agent (extractForwardableHeaders).
const agent = new HttpAgent({ url: AGENT_URL, headers: agentHeaders });
// CK_MIDDLEWARES=off runs the stack bare — used to audit which of these