/**
* The chat pane.
*
* Drives the agent, and shows what it is doing. The composer stays live while
* a turn runs — a turn owns the plan, not the conversation — and anything sent
* to the agent meanwhile is queued in order, with its author's name on it, so
* nobody is silenced because a colleague prompted first.
*
* The agent only acts when addressed, so the composer says where a message is
* going before it goes. The failure worth designing out is typing into what
* looks like a prompt and being met with silence.
*/
import { useEffect, useRef, useState } from "react";
import { addressed, MENTION } from "@chopin/protocol/address";
import { Transcript } from "./transcript";
import type { Chat as Wire } from "@chopin/protocol";
import type { Wire as Socket } from "../wire";
export type ChatProps = {
wire: Socket | undefined;
handle: string;
connected: boolean;
/** Brings a questionnaire into view in the decisions pane. */
onReveal?: (widget: string) => void;
/** Open questions, so the pane can point at the one that is blocking. */
waiting?: number;
};
function Queued(
{ handle, onWithdraw, waiting }: {
handle: string;
waiting: Wire.Waiting[];
onWithdraw: (id: string) => void;
},
) {
if (waiting.length === 0) return null;
return (