feat(gui): generic command flow node and the conversation.chat.commandview keyed slot
The FoldAdapter folds the log-only command/run + command/done pair (paired by commandId) into a CommandNode outside the surface fold and merges the nodes into the flow by seq; cross-window cuts soft-fall like tool pairs (a done-only window builds the node from the done, a run with no done renders as still executing). ChatView renders command nodes through the new keyed 'conversation.chat.commandview' hole (key = command name) with GenericCommandCard — a stripped-down GenericToolCard showing the command line and outcome text — as the render-site fallback, so any slash command renders durably with zero registration and survives refresh, other tabs, and resume via the mux-broadcast events.
This commit is contained in:
@@ -120,6 +120,31 @@ export interface UnknownSurfaceNode {
|
||||
data: unknown
|
||||
}
|
||||
|
||||
/**
|
||||
* One slash-command lifecycle folded from the log-only `command/run` /
|
||||
* `command/done` pair (paired by commandId, mirroring tool call↔result).
|
||||
* Log-only events never enter the surface fold, so the FoldAdapter indexes
|
||||
* them separately and merges the nodes into the flow by seq. A window cut
|
||||
* between the pair soft-falls like tool pairs: a done with no in-window run
|
||||
* still builds a node (name/line null), and a run with no done renders as
|
||||
* still executing.
|
||||
*/
|
||||
export interface CommandNode {
|
||||
kind: 'command'
|
||||
/** Seq of the command/run event; the done event's seq when only the done is in-window. */
|
||||
seq: number
|
||||
/** Unix epoch ms of the anchoring event. */
|
||||
time: number
|
||||
/** Pairing id minted by the host executor. */
|
||||
commandId: string
|
||||
/** Command name (run payload); null when the run fell outside the window. */
|
||||
name: string | null
|
||||
/** Exact dispatched command line (run payload); null when the run fell outside the window. */
|
||||
line: string | null
|
||||
/** Settlement outcome (done payload); null while the command is still executing. */
|
||||
outcome: { kind: 'success' | 'error'; text?: string } | null
|
||||
}
|
||||
|
||||
/** Finalized conversation node union (kind discriminates; seq is the React key). */
|
||||
export type ConversationNode =
|
||||
| UserMessageNode
|
||||
@@ -127,6 +152,7 @@ export type ConversationNode =
|
||||
| SteeringMessageNode
|
||||
| ContextMessageNode
|
||||
| ToolResultNode
|
||||
| CommandNode
|
||||
| UnknownSurfaceNode
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user