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).
This commit is contained in:
+10
-11
@@ -13,9 +13,8 @@ import { PATHS } from "../../config.ts";
|
||||
import type { ChatStore } from "../core/ports.ts";
|
||||
import type { ChatRecord, ChatSettings, ChatSummary, ExtractionRunUsage, PlanTree, TurnUsage } from "../core/contracts.ts";
|
||||
import type { LhMessage } from "../core/native-messages.ts";
|
||||
import { findPendingToolCall } from "../core/pending.ts";
|
||||
import { phaseAt3 } from "../core/phases.ts";
|
||||
import { projectNative } from "../core/projection.ts";
|
||||
import { danglingQuestionOf } from "../core/native-messages.ts";
|
||||
import { phaseAt3Lh } from "../core/phases.ts";
|
||||
|
||||
function chatFile(id: string): string {
|
||||
if (!/^[A-Za-z0-9_-]+$/.test(id)) throw new Error(`Invalid chat id: ${id}`);
|
||||
@@ -58,7 +57,6 @@ function listChats(): ChatSummary[] {
|
||||
// zero-back-compat wipe makes these "corrupt") must not blank the
|
||||
// whole sidebar — same isolation getChat's per-file catch gives.
|
||||
try {
|
||||
const projected = projectNative(messages);
|
||||
return {
|
||||
// turns and extractions stay out of the list payload (list =
|
||||
// summaries; usage aggregates ride the full record, the picker
|
||||
@@ -66,13 +64,14 @@ function listChats(): ChatSummary[] {
|
||||
...summary,
|
||||
messageCount: messages.length,
|
||||
// Record-derived status for the session picker: phase from the
|
||||
// transcript's explicit markers (probe_done / plan_init — the
|
||||
// event-driven phases, docs/probe-teach-split.md §4), pending
|
||||
// question from the last unanswered quiz/ask part — both read
|
||||
// through the one-way projection. Liveness (busy) is NOT
|
||||
// record-derived — the API route merges it (ChatListItem).
|
||||
phase: phaseAt3(projected),
|
||||
pendingQuestion: findPendingToolCall(projected) !== null,
|
||||
// transcript's explicit events (probe_done concluded / verdict
|
||||
// accepted — docs/probe-teach-split.md §4), pending question
|
||||
// from the native dangling-call scan. Wave D: both folds read
|
||||
// the NATIVE record (core/phases.ts phaseAt3Lh +
|
||||
// native-messages.ts danglingQuestionOf). Liveness (busy) is
|
||||
// NOT record-derived — the API route merges it (ChatListItem).
|
||||
phase: phaseAt3Lh(messages),
|
||||
pendingQuestion: danglingQuestionOf(messages) !== null,
|
||||
};
|
||||
} catch (err) {
|
||||
console.error(`[chat ${summary.id}] summary projection failed:`, err);
|
||||
|
||||
Reference in New Issue
Block a user