Merge feat/ui-polish: three-phase session model, plan graph, layout restructure
chat.tsx woven by hand: UI's session-surface layout (transcript column + right sidebar as full-height siblings, h-10 header with PhaseChip) wrapped in sub-agents' JobsContext.Provider; the message map carries both the steer ternary (steers bypass the Message wrapper — the model-facing glue text never renders) and UI's PhaseDivider emission (steers are verified phase-boundary no-ops). Right sidebar = sub-agents' fleet panel column (SubAgentsPanel above TreePanel, xl-only) carried onto UI's skeleton. contracts.ts auto-merged (ChatSummary.phase/pendingQuestion + ChatListItem, additive above the async-protocol section). Smoke-verified on the merged tree: steer renders bare as its artifact badge with no learner bubble, no rendered glue text, and no spurious phase divider at the steer boundary.
This commit is contained in:
+24
-1
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
|
||||
import type { UIMessage } from "ai";
|
||||
import type { Phase3 } from "./phases.ts";
|
||||
|
||||
// ─── Plan tree (vision §2 "formal plan tree") ────────────────────────────────
|
||||
// A session-scoped dependency tree authored by the teacher via plan tools.
|
||||
@@ -257,13 +258,35 @@ export interface ChatRecord {
|
||||
tree?: PlanTree;
|
||||
}
|
||||
|
||||
/** The list view's shape (messageCount instead of full messages). */
|
||||
/** The list view's shape (messageCount instead of full messages) + the
|
||||
* per-session status the picker renders. `phase` and `pendingQuestion`
|
||||
* derive from the stored record (tree + messages); the store computes
|
||||
* them in listChats. Liveness (`busy`) is NOT record-derived — the API
|
||||
* route merges it in (see ChatListItem).
|
||||
*
|
||||
* Phase semantics (three phases, data-only): probe = no plan yet, plan =
|
||||
* tree exists but no node occupied, teach = a node is occupied
|
||||
* (core/phases.ts phaseOfTree).
|
||||
*/
|
||||
export interface ChatSummary {
|
||||
id: string;
|
||||
title: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
messageCount: number;
|
||||
/** The session's current phase, derived from the stored plan tree. */
|
||||
phase: Phase3;
|
||||
/** An unanswered quiz/ask question is waiting for the learner. */
|
||||
pendingQuestion: boolean;
|
||||
}
|
||||
|
||||
/** The sidebar's session row: a summary + live liveness. The chats list
|
||||
* route attaches `busy` from the turn-liveness registry and the job store
|
||||
* (a running turn OR a background job = the session is working). The store
|
||||
* itself can't see liveness (import law: store never imports server),
|
||||
* hence the split at exactly the record/liveness seam. */
|
||||
export interface ChatListItem extends ChatSummary {
|
||||
busy: boolean;
|
||||
}
|
||||
|
||||
// ─── Async sub-agent jobs (vision §2.5; plan.md Wave 0 protocol) ────────────
|
||||
|
||||
Reference in New Issue
Block a user