mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 11:28:47 +02:00
Assistant: intercept connect on the single-route transport too
The connect intercept only matched POST …/connect, but CopilotKit talks
to the runtime in single-route mode: everything POSTs to
/api/copilotkit with the operation in the body envelope
({method:"agent/connect"}). So the in-memory runner kept replaying the
BFF process's full event history on every CopilotChat mount — every
conversation since server start, across clears — which is exactly the
stacked resurrected conversations seen in prod after navigating away
and back. Now both transports get the immediately-completed stream.
Verified with the reported repro: three conversations with clears
between, navigate away and back → only the third remains; reload
hydration unaffected.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -384,17 +384,38 @@ 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("", {
|
||||
// CopilotChat fires "connect" on every mount with an explicit threadId,
|
||||
// and the runtime's in-memory runner answers it by replaying THIS
|
||||
// PROCESS's event history — every run since the server started, across
|
||||
// "Nueva conversación" clears (the DB delete can't touch process memory).
|
||||
// That resurrected cleared conversations on navigation. The
|
||||
// empty-messages hydration run against MAF's snapshot store is our single
|
||||
// restore path, so connect gets an immediately-completed stream instead.
|
||||
//
|
||||
// Two transports must be caught: multi-route (POST …/agent/<id>/connect)
|
||||
// and single-route (POST /api/copilotkit with {method:"agent/connect"} in
|
||||
// the body — the one CopilotKit actually uses here; the URL-only check
|
||||
// silently missed it).
|
||||
const emptyStream = () =>
|
||||
new Response("", {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "text/event-stream" },
|
||||
});
|
||||
if (new URL(c.req.url).pathname.endsWith("/connect")) {
|
||||
return emptyStream();
|
||||
}
|
||||
if (
|
||||
c.req.method === "POST" &&
|
||||
(c.req.header("content-type") ?? "").includes("application/json")
|
||||
) {
|
||||
try {
|
||||
const envelope = (await c.req.raw.clone().json()) as { method?: string };
|
||||
if (envelope?.method === "agent/connect") {
|
||||
return emptyStream();
|
||||
}
|
||||
} catch {
|
||||
// not JSON — fall through to the runtime
|
||||
}
|
||||
}
|
||||
|
||||
const cookieHeader = c.req.header("cookie") ?? "";
|
||||
|
||||
Reference in New Issue
Block a user