Files
learnharness/app/chat/[id]/page.tsx
T
amosblomqvist f3003d357a Wave D: native AgentEvent wire + client session rewrite (SDK purged)
Server: ui-stream.ts is verbatim pi AgentEvent passthrough (SSE data
lines + [DONE]); only app-level events are the loop-level error and
turn-settled terminal; onError carries raw provider text (owner ruling).

Client: useChat + the AI-SDK transport replaced by components/session-core.ts
(SessionModel: 409 identity-retry, optimistic c_ appends, absorbed()
adoption, needsContinuation, shared consume for POST + reattach) and the
session.ts hook; the golden-master grouping canon moved client-side into
core/view.ts (projectView); scanners read the native record (phaseAt3Lh,
danglingQuestionOf, graph toolParts, plan-blocks, runner, extraction).

Coverage: the native message is the unit (fork 3) with the call+result
inseparability bond rule; view-line-less messages (markers, error
results) are invisible to coverage and never checkpointed.

Deletes: chat-transport, projection, ui-message, their tests (ported to
tests/session-core.test.ts), and the ai + @ai-sdk/react dependencies —
the Vercel SDK is fully out of the tree. Wire pins in chat-flow rewritten
onto the AgentEvent dialect (eventsOf parser).

Gates: tsc clean, 994/994 tests, eslint clean, build green; live smoke
on PORT=3004 (verbatim wire → native record).
2026-09-26 01:52:47 +03:00

39 lines
1.3 KiB
TypeScript

import { notFound } from "next/navigation";
import { Chat } from "@/components/chat";
import { slotsConfigured } from "@/src/core";
import { getChat, isTurnRunning, readSettingsRecord } from "@/src/server";
export const dynamic = "force-dynamic";
export default async function ChatPage({
params,
searchParams,
}: {
params: Promise<{ id: string }>;
searchParams: Promise<{ prompt?: string }>;
}) {
const [{ id }, { prompt }] = await Promise.all([params, searchParams]);
const chat = getChat(id);
if (!chat) notFound();
// The persistent setup CTA's seed (BYOK, owner 2026-09-22): slotsConfigured
// over the settings record, server-read — the same gate home/new read. The
// server's 503 stays the truth; this only decides whether the pill rides.
const record = readSettingsRecord();
return (
<Chat
key={chat.id}
chatId={chat.id}
title={chat.title}
// Wave D: the record IS native agent history — the client view is
// derived app-side (core/view.ts projectView; GET serves the same
// native messages).
initialMessages={chat.messages}
initialConfigured={slotsConfigured(record?.models)}
initialPrompt={prompt}
// A teacher turn that outlived its client: the remounted view must
// attach (busy shimmer + poll), never resurrect the stale record.
initiallyInFlight={isTurnRunning(chat.id)}
/>
);
}