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:
@@ -3,10 +3,8 @@
|
||||
*
|
||||
* Part of the domain-split contracts (src/core/contracts/): each domain file
|
||||
* is owned outright by its stream — cross-domain schema changes go through
|
||||
* master. Pure types + protocol docs + tiny pure helpers; type-only imports
|
||||
* of "ai" (safe everywhere: server, client, tests). See docs/vision.md.
|
||||
* master. Pure types + protocol docs + tiny pure helpers. See docs/vision.md.
|
||||
*/
|
||||
import type { UIMessage } from "ai";
|
||||
import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
||||
import type { LhMessage } from "../native-messages.ts";
|
||||
import type { Phase3 } from "../phases.ts";
|
||||
@@ -20,8 +18,8 @@ import type { EmissionStats, UnderstandingLevel } from "./graph.ts";
|
||||
* agent loop's own shapes, provider/model/usage/thinkingSignature stamped
|
||||
* by pi) — the canonical session record IS the agent state; replay is
|
||||
* `state.messages = record.messages` + continue(). The client-shaped view
|
||||
* is the one-way projection (core/projection.ts) — a pending quiz is an
|
||||
* unanswered question tool call, which is exactly what makes
|
||||
* is the client's own grouping fold (core/view.ts, Wave D) — a pending quiz
|
||||
* is an unanswered question tool call, which is exactly what makes
|
||||
* resume-mid-question free. */
|
||||
export interface ChatRecord {
|
||||
id: string;
|
||||
|
||||
@@ -115,3 +115,28 @@ export interface PlanToolResult {
|
||||
tree: PlanTree;
|
||||
}
|
||||
|
||||
|
||||
// ─── the native fold (Wave D: derivePlanStatuses over LhMessage[]) ───────────
|
||||
|
||||
import type { LhMessage } from "../native-messages.ts";
|
||||
|
||||
/** The same derivation over the NATIVE record: quiz CALLS only (any state —
|
||||
* a dangling call still moves position; results feed nothing). */
|
||||
export function derivePlanStatusesLh(tree: PlanTree, messages: readonly LhMessage[]): DerivedPlanStatuses {
|
||||
const ids = new Set(tree.nodes.map((n) => n.id));
|
||||
const runs: string[] = [];
|
||||
for (const m of messages) {
|
||||
if ((m as { role?: string }).role !== "assistant") continue;
|
||||
const content = (m as { content?: unknown }).content;
|
||||
if (!Array.isArray(content)) continue;
|
||||
for (const block of content as Array<{ type?: string; name?: string; arguments?: unknown }>) {
|
||||
if (block.type !== "toolCall" || block.name !== "quiz") continue;
|
||||
const nodeId = (block.arguments as { nodeId?: unknown } | undefined)?.nodeId;
|
||||
if (typeof nodeId !== "string" || !ids.has(nodeId)) continue;
|
||||
if (runs.at(-1) !== nodeId) runs.push(nodeId);
|
||||
}
|
||||
}
|
||||
const current = runs.at(-1) ?? null;
|
||||
const visited = new Set(runs.slice(0, -1));
|
||||
return { current, visited };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user