mirror of
https://github.com/escalante29/WealthySmart.git
synced 2026-07-17 12:08:47 +02:00
Assistant: migrate to v2 runtime handler with Postgres-backed AgentRunner
Replace the deprecated copilotRuntimeNextJSAppRouterEndpoint wrapper (which was already the v2 single-route handler underneath) with createCopilotRuntimeHandler from @copilotkit/runtime/v2, built once at module scope, and plug in a custom PostgresAgentRunner: - run() proxies the agent's event stream untouched — MAF persists every turn in chatthreadsnapshot, so the BFF records nothing - connect() forwards to MAF's snapshot hydration (empty-messages run → RUN_STARTED → MESSAGES_SNAPSHOT → RUN_FINISHED, no LLM call), making the DB the only conversation store — correct across clears, restarts and future instances - stop() aborts via a process-local live-run map (same pattern as the official sqlite-runner); isRunning() has no caller in the v2 SSE path This deletes the whole workaround layer the in-memory runner forced: the connect intercepts (URL + envelope forms) and Asistente's client-side hydration run. The ask-box flow now awaits connectAgent instead. Auth moves to a single Request rewrite (ws_token cookie → Authorization Bearer) before the handler — the v2 path forwards authorization + x-* headers to both run clones and runner.connect. Stays in single-route mode: same envelope protocol the client already auto-detected, no exposure to CopilotKit#4953, /threads* REST not needed. Telemetry disabled via COPILOTKIT_TELEMETRY_DISABLED. Verified full matrix in dev: fresh ask, reload replay via runner, 3 cleared convos + double navigation (only last survives), card renders once and survives follow-up + reload, Inicio ask-box with history, stale-tab persists only its new turn. 126 backend tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -39,39 +39,34 @@ export default function Asistente() {
|
||||
const [confirmClear, setConfirmClear] = useState(false);
|
||||
const [clearing, setClearing] = useState(false);
|
||||
|
||||
// Boot sequence, once per page load: hydrate the persisted thread, then
|
||||
// send any question that arrived from the Inicio ask-box via router state.
|
||||
// Order matters — hydration first keeps the invariant that every normal
|
||||
// run's input carries the full client-known history (the BFF's snapshot
|
||||
// reconciliation relies on it).
|
||||
// Ask-box flow: a question typed on Inicio arrives via router state.
|
||||
// History hydration is no longer done here — CopilotChat's mount connect
|
||||
// replays the persisted thread through the BFF's PostgresAgentRunner. We
|
||||
// still await our own connect before sending so the run's input carries
|
||||
// the full client-known history (idempotent with CopilotChat's connect:
|
||||
// the MESSAGES_SNAPSHOT merge is id-based).
|
||||
const bootRef = useRef(false);
|
||||
useEffect(() => {
|
||||
if (!agent || bootRef.current) return;
|
||||
bootRef.current = true;
|
||||
const ask = (location.state as { ask?: string } | null)?.ask;
|
||||
if (ask) {
|
||||
// Clear the state so back/refresh doesn't re-send the question.
|
||||
navigate(location.pathname, { replace: true, state: null });
|
||||
}
|
||||
if (!ask || !agent || bootRef.current) return;
|
||||
bootRef.current = true;
|
||||
// Clear the state so back/refresh doesn't re-send the question.
|
||||
navigate(location.pathname, { replace: true, state: null });
|
||||
void (async () => {
|
||||
agent.threadId = CHAT_THREAD_ID;
|
||||
if (agent.messages.length === 0) {
|
||||
// Empty-messages run = MAF's hydration trigger: replays the stored
|
||||
// snapshot as MESSAGES_SNAPSHOT without invoking the LLM.
|
||||
try {
|
||||
await copilotkit.runAgent({ agent });
|
||||
await copilotkit.connectAgent({ agent });
|
||||
} catch (err) {
|
||||
console.error("[asistente] thread hydration failed:", err);
|
||||
console.error("[asistente] connect before ask failed:", err);
|
||||
}
|
||||
}
|
||||
if (ask) {
|
||||
agent.addMessage({
|
||||
id: crypto.randomUUID(),
|
||||
role: "user",
|
||||
content: ask,
|
||||
});
|
||||
void copilotkit.runAgent({ agent });
|
||||
}
|
||||
agent.addMessage({
|
||||
id: crypto.randomUUID(),
|
||||
role: "user",
|
||||
content: ask,
|
||||
});
|
||||
void copilotkit.runAgent({ agent });
|
||||
})();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [agent]);
|
||||
|
||||
Reference in New Issue
Block a user