@signalcore/ui 1.0.0-beta.0 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/AgentChat.js CHANGED
@@ -709,6 +709,7 @@ function Reply({ message, from, awaiting, current, answers, name, words, classNa
709
709
  /* @__PURE__ */ jsx(Mark, {
710
710
  state: step.state,
711
711
  action: step.action,
712
+ app: step.app ?? null,
712
713
  classNames
713
714
  }),
714
715
  /* @__PURE__ */ jsx("span", { children: words.steps[step.action] ?? actionWords(step.action) }),
@@ -784,6 +785,7 @@ function BuilderStep({ step, words, classNames }) {
784
785
  /* @__PURE__ */ jsx(Mark, {
785
786
  state: step.state,
786
787
  action: step.action,
788
+ app: step.app ?? null,
787
789
  classNames
788
790
  }),
789
791
  /* @__PURE__ */ jsx("span", { children: words.steps[step.action] ?? actionWords(step.action) }),
@@ -799,12 +801,18 @@ function BuilderStep({ step, words, classNames }) {
799
801
  * A step's mark on the list's line: the kind of work it is (its glyph) once it is done, a turning
800
802
  * ring while it runs, a ring while it waits for the person, a warning when it failed.
801
803
  */
802
- function Mark({ state, action, classNames }) {
804
+ function Mark({ state, action, app, classNames }) {
803
805
  const Glyph = stepGlyph(action);
806
+ const logo = app?.icon && /^https:\/\//i.test(app.icon) ? app.icon : null;
804
807
  return /* @__PURE__ */ jsx("span", {
805
808
  "aria-hidden": true,
806
809
  className: classes(classNames, "sc-chat__mark"),
807
- children: state === "done" ? /* @__PURE__ */ jsx(Glyph, {}) : state === "running" ? null : /* @__PURE__ */ jsx("svg", {
810
+ children: state === "done" && logo !== null ? /* @__PURE__ */ jsx("img", {
811
+ src: logo,
812
+ alt: "",
813
+ loading: "lazy",
814
+ draggable: false
815
+ }) : state === "done" ? /* @__PURE__ */ jsx(Glyph, {}) : state === "running" ? null : /* @__PURE__ */ jsx("svg", {
808
816
  viewBox: "0 0 14 14",
809
817
  fill: "none",
810
818
  children: MARKS[state]
@@ -1 +1 @@
1
- {"version":3,"file":"AgentChat.js","names":[],"sources":["../src/AgentChat.tsx"],"sourcesContent":["import {\n ArrowUpIcon,\n CaretRightIcon,\n CheckIcon,\n ChecksIcon,\n ClockIcon,\n MicrophoneIcon,\n PaperclipIcon,\n ShieldWarningIcon,\n StopIcon,\n UploadSimpleIcon,\n WarningCircleIcon,\n} from \"@phosphor-icons/react\";\nimport {\n Fragment,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type KeyboardEvent,\n type ReactNode,\n type RefObject,\n} from \"react\";\n\nimport { actionWords } from \"./about\";\nimport type { Surface as Shown } from \"./blocks\";\nimport {\n BROWSER_MESSAGES,\n BrowserView,\n type BrowserMessages,\n type BrowserPart,\n} from \"./BrowserView\";\nimport { channelParts } from \"./channelParts\";\nimport { classes } from \"./classes\";\nimport { useDictation, type Dictate } from \"./useDictation\";\nimport { useReveal } from \"./reveal\";\nimport type { Client } from \"./client\";\nimport type { Speaker } from \"./credentials\";\nimport { useConversationFiles } from \"./conversationFiles\";\nimport { FILES_PER_MESSAGE } from \"./frames\";\nimport { actionMark } from \"./marks\";\nimport { AudioPlayer } from \"./kit/AudioPlayer\";\nimport { KitProvider, type KitPart } from \"./kit/context\";\nimport { carriesFiles, FileChips, UploadChips, useUploads, type Uploads } from \"./kit/FileField\";\nimport { KIT_MESSAGES, type KitLocale, type KitMessages } from \"./kit/messages\";\nimport type { FileHost } from \"./kit/uploads\";\nimport { stepGlyph } from \"./stepGlyphs\";\nimport { Markdown } from \"./surface/Markdown\";\nimport type { SurfaceComponents, SurfacePart } from \"./surface/scope\";\nimport { framesItself, Surface, usePlayed } from \"./surface/Surface\";\nimport type { SurfaceAction } from \"./surface/values\";\nimport type {\n Action,\n Attachment,\n Decision,\n Delivery,\n Handover,\n Holder,\n Message,\n Request,\n Step,\n StepState,\n} from \"./types\";\nimport {\n NO_TOOL,\n useConversation,\n type LiveConversation,\n type ToolHandler,\n} from \"./useConversation\";\n\n/** The words the chat says; a host gives its own, in its language. */\nexport interface ChatMessages {\n /** The composer's invitation, and the field's name; `fresh` while nothing has been said. */\n placeholder: (name: string, fresh: boolean) => string;\n /** In the composer while the socket is not open. */\n connecting: string;\n /** In the composer while the turn waits for the person to act above. */\n awaiting: string;\n /** Over the composer while a reply is on its way. */\n thinking: (name: string) => string;\n /** Over the composer while a reply is on its way, where the agent's steps are hidden. */\n typing: string;\n /** The builder's line over the composer, while nothing runs and nothing is written yet. */\n working: string;\n /** The builder's line over the composer, while its words come. */\n writing: string;\n /** How long the reply has taken so far, beside it. */\n elapsed: (seconds: number) => string;\n /** At the end of that line: how to stop the reply. */\n escape: string;\n /** Under the log once a reply is in: how long it took. */\n done: (seconds: number) => string;\n /** A conversation with nothing said yet: its title. */\n empty: (name: string) => string;\n /** Under the title, a line on what to say; nothing when empty. */\n intro: (name: string) => string;\n /** The send button's name. */\n send: string;\n /** The button that attaches files, by its name. */\n attach: string;\n /** Over the chat while files are dragged over it. */\n drop: string;\n /** The microphone's name: to dictate, and to stop and have it written. */\n dictate: string;\n dictateStop: string;\n /** Beside the microphone while it listens, writes, or could not. */\n dictation: Readonly<Record<\"listening\" | \"writing\" | \"failed\", string>>;\n /** The stop button's name, in the send button's place while a reply is on its way. */\n stop: string;\n /** The message list's name, for screen readers. */\n log: string;\n /** A step's name, by the action's name as the platform gives it; the name itself otherwise. */\n steps: Readonly<Record<string, string>>;\n /** Beside a step that failed, in the builder's look: the colour is never the whole message. */\n failed: string;\n /** What heads the card of an action that needs the person's leave. */\n approval: string;\n /** The agent wants to run an action that needs the person's leave. */\n request: (name: string, action: string) => string;\n /** An action's input fields, by their name, as the approval card labels them. */\n inputs: Readonly<Record<string, string>>;\n allow: string;\n decline: string;\n /**\n * On a person's page, in place of the approval card: what the agent asked to do waits for the\n * business's yes (`decides: \"business\"`), which its people give from their app.\n */\n confirming: string;\n /** The line across the log where the agent handed the conversation to a person. */\n handedOff: string;\n /**\n * The line across the log where who answers the conversation changed (`handovers`), before\n * why: to whom (`holder`), and who changed it (`by`).\n */\n handover: (holder: Holder, by: HandoverBy, name: string) => string;\n /** Under a person's message the agent let pass this time (a `skip`), before why. */\n skipped: string;\n /**\n * On a call, under a reply the person cut short: the last of what they heard of it (`\"\"`:\n * nothing of it).\n */\n cut: (heard: string) => string;\n /** The composer's invitation when the host takes what is written (`write`): the business's. */\n write: string;\n /** Under what a person of the business wrote on the channel: who it was. */\n business: string;\n /** A voice note's player, by its name. */\n voiceNote: string;\n /** Where what went out on a channel got to, as its mark's name. */\n delivery: Readonly<Record<Delivery, string>>;\n /** Beside a message that never reached the person, with the provider's reason when it gave one. */\n undelivered: (error: string | null) => string;\n /**\n * What the page answers when the agent calls one of the host's tools and the chat was given no\n * `onTool` to run it: read by the agent, never shown.\n */\n noTool: string;\n /** What the kit's controls say on the agent's screens: a form's checks, a calendar, a list. */\n kit: Partial<KitMessages>;\n /** What the browser the agent drives says: who holds it, take it, give it back. */\n browser: BrowserMessages;\n}\n\nexport const CHAT_MESSAGES: ChatMessages = {\n placeholder: (name) => `Write to ${name}…`,\n connecting: \"Connecting…\",\n awaiting: \"Answer above to go on…\",\n thinking: (name) => `${name} is thinking`,\n typing: \"Typing\",\n working: \"Working\",\n writing: \"Writing\",\n elapsed: (seconds) => `${seconds} s`,\n escape: \"esc to stop\",\n done: (seconds) => `Done in ${seconds} s`,\n empty: (name) => `Talk with ${name}`,\n intro: () => \"\",\n send: \"Send\",\n attach: \"Attach files\",\n drop: \"Drop to attach\",\n dictate: \"Dictate\",\n dictateStop: \"Stop and write it\",\n dictation: {\n listening: \"Listening…\",\n writing: \"Writing it down…\",\n failed: \"Couldn't hear you: allow the microphone and try again\",\n },\n stop: \"Stop\",\n log: \"Conversation\",\n steps: { show: \"Shows\", ask_person: \"Asks\" },\n failed: \"failed\",\n approval: \"Needs your approval\",\n request: (name, action) => `${name} wants to ${action}`,\n inputs: {},\n allow: \"Allow\",\n decline: \"Decline\",\n confirming: \"Waiting for the business to confirm\",\n handedOff: \"Handed to a person\",\n handover: (holder, by, name) => {\n const automation = by.kind === \"automation\" ? ` by “${by.title}”` : \"\";\n switch (holder) {\n case \"agent\":\n if (by.kind === \"owner\") return `You gave it back to ${name}`;\n return `Given back to ${name}${automation}`;\n case \"person\":\n if (by.kind === \"owner\") return `You paused ${name}`;\n if (by.kind === \"agent\") return `${name} handed it to a person`;\n return `Handed to a person${automation}`;\n case \"nobody\":\n return `Ignored${automation}`;\n }\n },\n skipped: \"Not answered\",\n cut: (heard) =>\n heard === \"\" ? \"Cut off before a word of it was heard\" : `Cut off after «${heard}»`,\n write: \"Reply as the business…\",\n business: \"You\",\n voiceNote: \"Voice note\",\n delivery: {\n queued: \"Waiting to go\",\n sent: \"Sent\",\n delivered: \"Delivered\",\n read: \"Read\",\n failed: \"Not delivered\",\n },\n undelivered: (error) => (error ? `Not delivered: ${error}` : \"Not delivered\"),\n noTool: NO_TOOL,\n kit: KIT_MESSAGES,\n browser: BROWSER_MESSAGES,\n};\n\n/** The chat's parts, by the class each carries; `classNames` adds a host's own under the same keys. */\nexport type ChatPart =\n | \"sc-chat\"\n | \"sc-chat--builder\"\n | \"sc-chat--console\"\n | \"sc-chat__log\"\n | \"sc-chat__log--channel\"\n | \"sc-chat__message\"\n | \"sc-chat__message--person\"\n | \"sc-chat__message--agent\"\n | \"sc-chat__message--action\"\n | \"sc-chat__message--business\"\n | \"sc-chat__said\"\n | \"sc-chat__business\"\n | \"sc-chat__meta\"\n | \"sc-chat__delivery\"\n | \"sc-chat__text\"\n | \"sc-chat__steps\"\n | \"sc-chat__step\"\n | \"sc-chat__mark\"\n | \"sc-chat__step--running\"\n | \"sc-chat__step--queued\"\n | \"sc-chat__step--waiting\"\n | \"sc-chat__step--done\"\n | \"sc-chat__step--failed\"\n | \"sc-chat__output\"\n | \"sc-chat__request\"\n | \"sc-chat__confirming\"\n | \"sc-chat__screen\"\n | \"sc-chat__screen--bare\"\n | \"sc-chat__handoff\"\n | \"sc-chat__handover\"\n | \"sc-chat__decision\"\n | \"sc-chat__message--heard\"\n | \"sc-chat__message--voice\"\n | \"sc-chat__transcript\"\n | \"sc-chat__cut\"\n | \"sc-chat__reply\"\n | \"sc-chat__status\"\n | \"sc-chat__done\"\n | \"sc-chat__empty\"\n | \"sc-chat__suggestion\"\n | \"sc-chat__composer\"\n | \"sc-chat__files\"\n | \"sc-chat__attach\"\n | \"sc-chat__dictate\"\n | \"sc-chat__typing\"\n | \"sc-chat__dictation\"\n | \"sc-chat__drop\"\n | \"sc-chat__input\"\n | \"sc-chat__actions\"\n | \"sc-chat__send\"\n | \"sc-chat__stop\";\n\ntype ClassNames =\n Partial<Record<ChatPart | SurfacePart | KitPart | BrowserPart, string>> | undefined;\n\n/**\n * How the chat looks. `agent` is an agent's conversation. `builder` is the builder's, v2's: the\n * working line says what it does under the brand's sweeping light, the steps open on what they\n * returned, the send is the brand's; `console` is the same seen as a console beside the work, the\n * person's words as prompt lines.\n */\nexport type ChatLook = \"agent\" | \"builder\" | \"console\";\n\n/**\n * Whether the chat shows the steps the agent took (searching its files, remembering, calling a\n * tool, with what each returned): `shown` for the business, who wants to see the work; `hidden`\n * for the people it serves, who see only what the agent says and shows, and a quiet line while\n * it works.\n */\nexport type ChatSteps = \"shown\" | \"hidden\";\n\n/**\n * Who changed who answers a conversation: one of the business's people (`owner`), the agent itself\n * (its `escalate`), the platform (a release after quiet hours, a contact the owner marked), or an\n * automation, by its title.\n */\nexport type HandoverBy =\n { kind: \"owner\" | \"agent\" | \"platform\" } | { kind: \"automation\"; title: string };\n\n/** Something the host hands the chat from outside it, to say or to leave in the composer. */\nexport interface ChatCompose {\n text: string;\n /** Said at once; otherwise left in the composer for the person to finish. */\n send: boolean;\n /** Tells one request from the last: each new key is taken once. */\n key: number;\n}\n\nexport interface AgentChatProps {\n client: Client;\n conversationId: string;\n /** The agent's name, for the words that address it. */\n name: string;\n messages?: Partial<ChatMessages> | undefined;\n classNames?: ClassNames;\n /** The host's own drawing of a block type, for every surface the agent shows. */\n components?: SurfaceComponents | undefined;\n /** The language of the surfaces' calendars, days, times and numbers; English by default. */\n locale?: KitLocale | undefined;\n /** An error's code, from the socket or `load` for a history that could not be read; the host words it. */\n onError?: ((code: string) => void) | undefined;\n /** The host's own controls, at the composer's left. */\n actions?: ReactNode;\n /** A few things the person might say first, offered while nothing has been said; a click says it. */\n suggestions?: readonly string[] | undefined;\n /**\n * A request from elsewhere on the page (a button beside the chat), taken once each time `key`\n * changes; the one the chat mounts with is not. With `send` it is said, once the socket is open;\n * while a reply is on its way or the turn waits, it goes into the composer instead. Without, it\n * goes into the composer, focused with the caret at its end.\n */\n compose?: ChatCompose | undefined;\n /** An agent's conversation by default; the builder's, or the builder's as a console. */\n look?: ChatLook | undefined;\n /**\n * Whether the agent's steps show: by default as the page speaks (`client.who`): `shown` for the\n * business, `hidden` for a person or a visitor, who see what the agent says and shows (its\n * surfaces, files, a yes it waits for) and `typing` while it works.\n */\n steps?: ChatSteps | undefined;\n /**\n * Whether the person can attach files to what they say (the paperclip, dropping them on the\n * chat, pasting a picture): each uploads to the conversation at once. On in every look, the\n * builder's too; a host turns it off where nobody talks (a transcript read).\n */\n attachments?: boolean | undefined;\n /**\n * Opens a file of the conversation (one the person sent, one sent through a form), as the host\n * shows files (`FileView` in a dialog, its bytes from the API); without it, files only read.\n */\n onOpenFile?: ((file: Attachment) => void) | undefined;\n /**\n * Turns what the person says out loud into words in the composer (the microphone beside the\n * paperclip): the host's speech to text. Without it there is no microphone.\n */\n dictate?: Dictate | undefined;\n /**\n * Where what is written goes instead of the socket: on a conversation on a channel, a person of\n * the business writing to the person there (`POST /conversations/{id}/operator`). The composer\n * then says `write`, takes words and files whatever the agent is doing, and empties once the\n * promise resolves (a rejection leaves them, for the host to say why); what was written comes\n * back on the socket as a message.\n */\n write?: ((text: string, files: readonly string[]) => Promise<unknown>) | undefined;\n /**\n * Whether the log draws who answers the conversation, for a host of the business's (the inbox,\n * the activity): each change (read with the history, then heard live) a quiet line where it\n * fell, with why and when, and under a person's message the agent let pass, that it did. Off,\n * the log draws only where the agent handed it to a person, from its `escalate` step.\n */\n handovers?: boolean | undefined;\n /** Hears each change of who answers the conversation, live: the host's own views of it follow. */\n onHolder?: ((holder: Holder, handover: Handover) => void) | undefined;\n /** Hears each step the agent starts, live, by its action's name: the host's views follow. */\n onStep?: ((action: string) => void) | undefined;\n /**\n * The conversation's last change of who answers it, as the host knows it (one it made itself,\n * as its request answered): drawn at once, whether or not the socket tells it, and kept once.\n */\n handover?: Handover | null | undefined;\n /**\n * Runs one of the host's own tools the agent calls in the page (opening a record in the host's\n * screen, say): what it resolves to goes back to the agent, what it rejects with as why it\n * failed; its step shows as working meanwhile. Without it, each is refused with `noTool`.\n */\n onTool?: ToolHandler | undefined;\n}\n\n/** How close to the foot, in pixels, still counts as being at it (v2's). */\nconst NEAR_FOOT = 80;\n\n/**\n * The conversation with an agent: the person's messages at the right in a bubble, the agent's at\n * the left as text with the steps it took and what they drew, its reply growing as it streams;\n * the composer at the foot. On a channel, the business's side stays at the left: the agent's\n * words with where they got to (a quiet mark), and what a person of the business wrote set apart\n * in a bubble of its own; the surfaces went to the person there, so they only read here, and the\n * reply, which runs on its own time, can't be stopped from here. With `handovers`, each change of\n * who answers it is a quiet line where it fell, the moment it is made, and a person's message the\n * agent let pass says so under it. The host picks the conversation; another id starts the chat\n * afresh.\n */\nexport function AgentChat(props: AgentChatProps) {\n // The last request taken, kept across conversations so another one does not take it again. The\n // one given at mount counts as taken: a chat mounted again never says it twice.\n const taken = useRef<number | null>(props.compose?.key ?? null);\n // The kit's pieces in it (a file's chip, a surface's controls) read the host's words and classes.\n const kit = props.messages?.kit ?? CHAT_MESSAGES.kit;\n return (\n <KitProvider classNames={props.classNames} messages={kit} locale={props.locale}>\n <Chat key={props.conversationId} {...props} taken={taken} />\n </KitProvider>\n );\n}\n\nfunction Chat({\n client,\n conversationId,\n name,\n messages,\n classNames,\n components,\n locale,\n onError,\n actions,\n suggestions,\n compose,\n look = \"agent\",\n steps = client.who === \"person\" ? \"hidden\" : \"shown\",\n attachments = true,\n onOpenFile,\n dictate,\n write,\n handovers = false,\n onHolder,\n onStep,\n handover,\n onTool,\n taken,\n}: AgentChatProps & { taken: RefObject<number | null> }) {\n const words = { ...CHAT_MESSAGES, ...messages };\n const live = useConversation(client, conversationId, {\n onError,\n onHolder,\n onStep,\n handover,\n onTool: onTool ?? (() => Promise.reject(new Error(words.noTool))),\n });\n const files = useConversationFiles(client, conversationId, live.messages, onOpenFile);\n // What the person attaches to their next message: picked, dropped on the chat, or pasted.\n const uploads = useUploads(attachments ? files : undefined, { max: FILES_PER_MESSAGE });\n // Files go with what is said, once the turn waits on nothing; to the host's `write`, at once.\n const attaching = attachments && (write !== undefined || live.awaiting === null);\n const [over, setOver] = useState(false);\n // Whether the messages follow the conversation down: until the person scrolls up to read, and\n // again as soon as they speak.\n const following = useRef(true);\n const fresh = !live.loading && live.messages.length === 0 && !live.pending;\n const took = useTook(live.pending);\n const builder = look !== \"agent\";\n const { pending } = live;\n // A conversation on a channel: its messages say who said them.\n const onChannel = live.messages.some((message) => message.author != null);\n\n // The builder stops on Esc from anywhere on the page, as v2's did; an agent's chat, from inside it.\n const stop = useRef(live.stop);\n useEffect(() => {\n stop.current = live.stop;\n });\n useEffect(() => {\n if (!builder || !pending) return undefined;\n const onKey = (event: globalThis.KeyboardEvent) => {\n if (event.key === \"Escape\" && !event.defaultPrevented) stop.current();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => {\n window.removeEventListener(\"keydown\", onKey);\n };\n }, [builder, pending]);\n\n const looks: ChatPart[] = builder ? [\"sc-chat--builder\"] : [];\n if (look === \"console\") looks.push(\"sc-chat--console\");\n const stepsShown = steps === \"shown\";\n\n return (\n <div\n part=\"chat\"\n className={`sc ${classes(classNames, \"sc-chat\", ...looks)}`}\n onKeyDown={(event) => {\n if (!builder && !onChannel && event.key === \"Escape\" && live.pending) live.stop();\n }}\n // Files dropped anywhere on the chat go with the next message; a form's own drop zone\n // (`data-drop`) takes those dropped on it.\n onDragOver={(event) => {\n if (!attaching || !carriesFiles(event)) return;\n const zone = event.target instanceof Element && event.target.closest(\"[data-drop]\");\n setOver(!zone);\n if (zone) return;\n event.preventDefault();\n event.dataTransfer.dropEffect = \"copy\";\n }}\n onDragLeave={(event) => {\n const to = event.relatedTarget;\n if (!(to instanceof Node && event.currentTarget.contains(to))) setOver(false);\n }}\n onDrop={(event) => {\n setOver(false);\n if (event.defaultPrevented || !attaching || !carriesFiles(event)) return;\n event.preventDefault();\n uploads.add([...event.dataTransfer.files]);\n }}\n >\n {fresh ? (\n <div part=\"empty\" className={classes(classNames, \"sc-chat__empty\")}>\n <h2>{words.empty(name)}</h2>\n {words.intro(name) !== \"\" && <p>{words.intro(name)}</p>}\n {suggestions !== undefined && suggestions.length > 0 && (\n <ul>\n {suggestions.map((text) => (\n <li key={text}>\n <button\n type=\"button\"\n disabled={!live.open}\n onClick={() => {\n if (live.say(text)) following.current = true;\n }}\n part=\"suggestion\"\n className={classes(classNames, \"sc-chat__suggestion\")}\n >\n «{text}»\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n ) : (\n <Log\n live={live}\n name={name}\n words={words}\n classNames={classNames}\n components={components}\n locale={locale}\n following={following}\n took={took}\n builder={builder}\n onChannel={onChannel}\n files={files}\n handovers={handovers ? live.handovers : undefined}\n who={client.who}\n steps={stepsShown}\n />\n )}\n {/* The browser the agent drives, over the composer while the conversation has one. */}\n <BrowserView live={live} name={name} messages={words.browser} classNames={classNames} />\n {live.pending && (\n <Status\n label={\n builder ? workingOn(live, words) : stepsShown ? words.thinking(name) : words.typing\n }\n stoppable={!onChannel}\n timed={stepsShown}\n words={words}\n classNames={classNames}\n />\n )}\n <Composer\n live={live}\n name={name}\n words={words}\n classNames={classNames}\n actions={actions}\n compose={compose}\n taken={taken}\n fresh={fresh}\n builder={builder}\n uploads={attachments ? uploads : undefined}\n files={files}\n dictate={dictate}\n write={write}\n onSent={() => {\n following.current = true;\n }}\n />\n {over && (\n <div aria-hidden className={classes(classNames, \"sc-chat__drop\")}>\n <UploadSimpleIcon weight=\"bold\" />\n {words.drop}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * What the builder is doing right now, v2's way: the step running in this turn, by its name (the\n * first one not settled: the actions of a reply run in its order); its words, while they come; or\n * that it is working.\n */\nexport function workingOn(\n live: Pick<LiveConversation, \"messages\" | \"draft\">,\n words: Pick<ChatMessages, \"steps\" | \"working\" | \"writing\">,\n): string {\n const lastSaid = live.messages.findLastIndex((message) => message.role === \"user\");\n const running = live.messages\n .slice(lastSaid + 1)\n .flatMap((message) => message.steps)\n .find((step) => step.state === \"running\");\n if (running) return words.steps[running.action] ?? running.action;\n return live.draft === \"\" ? words.working : words.writing;\n}\n\ninterface PartProps {\n live: LiveConversation;\n name: string;\n words: ChatMessages;\n classNames: ClassNames;\n}\n\nconst NO_HANDOFFS: ReadonlySet<string> = new Set();\n\n/** Whether a message is the agent's own words: a reply, not what a person of the business wrote. */\nconst agentSaid = (message: Message | undefined): boolean =>\n message?.role === \"assistant\" && message.author !== \"operator\";\n\n/**\n * The replies a handoff line follows: in each turn where the agent handed the conversation to a\n * person (an `escalate` step done), its last reply, so the line closes what the agent said.\n */\nexport function handoffs(messages: readonly Message[]): ReadonlySet<string> {\n const after = new Set<string>();\n let handed = false;\n for (const [index, message] of messages.entries()) {\n handed ||= message.steps.some((step) => step.action === \"escalate\" && step.state === \"done\");\n if (handed && !agentSaid(messages[index + 1])) {\n after.add(message.id);\n handed = false;\n }\n }\n return after;\n}\n\n/** Who changed who answers, from a handover's `by`: anything but these three is an automation's name. */\nexport function handoverBy({ by, title }: Pick<Handover, \"by\" | \"title\">): HandoverBy {\n if (by === \"owner\" || by === \"agent\" || by === \"platform\") return { kind: by };\n return { kind: \"automation\", title: title ?? by };\n}\n\n/** A change of who answers, as its line says it: what changed and who changed it, then why. */\nexport function handoverLine(\n handover: Handover,\n name: string,\n words: Pick<ChatMessages, \"handover\">,\n): string {\n const line = words.handover(handover.holder, handoverBy(handover), name);\n const reason = handover.reason.trim();\n return reason === \"\" ? line : `${line}: ${reason}`;\n}\n\n/**\n * The line under a person's message the agent let pass this time, with why (the owner's words,\n * else the automation that decided); none for any other decision: an answer is the reply itself,\n * and a conversation held or ignored has its line where who answers changed.\n */\nexport function decisionLine(\n decision: Decision | null | undefined,\n words: Pick<ChatMessages, \"skipped\">,\n): string | null {\n if (decision?.kind !== \"skip\") return null;\n const why = decision.reason?.trim() || decision.title;\n return why ? `${words.skipped}: ${why}` : words.skipped;\n}\n\n/**\n * Where each change of who answers falls among the messages, by the index of the message it goes\n * before (`messages.length`: after them all): before the first message said after it, and the\n * agent's own after the last reply of its turn, so its line closes what the agent said.\n */\nexport function handoversAt(\n messages: readonly Message[],\n handovers: readonly Handover[],\n): ReadonlyMap<number, readonly Handover[]> {\n const at = new Map<number, Handover[]>();\n let next = 0;\n for (const [index, message] of messages.entries()) {\n const said = Date.parse(message.created_at);\n const before: Handover[] = [];\n let handover = handovers[next];\n while (\n handover !== undefined &&\n Date.parse(handover.at) < said &&\n !(handover.by === \"agent\" && agentSaid(message))\n ) {\n before.push(handover);\n next += 1;\n handover = handovers[next];\n }\n if (before.length > 0) at.set(index, before);\n }\n if (next < handovers.length) at.set(messages.length, handovers.slice(next));\n return at;\n}\n\n/** When a line across the log happened, as the locale writes it: the time today, else the day too. */\nexport function whenSaid(at: string, now: Date, code: string): string {\n const moment = new Date(at);\n const today = moment.toDateString() === now.toDateString();\n return new Intl.DateTimeFormat(code, {\n ...(today ? {} : { day: \"numeric\", month: \"short\" }),\n hour: \"numeric\",\n minute: \"2-digit\",\n }).format(moment);\n}\n\n/**\n * The messages, read down, and the reply on its way: who is thinking until its first words, then\n * the words as they come with the agent's mark at their end. Where who answers the conversation\n * changed (`handovers`, when the host draws them; else where the agent handed it to a person),\n * one quiet line across the log says so, and under a person's message the agent let pass, that\n * it did. Screen readers hear a reply once, when it is stored.\n */\nfunction Log({\n live,\n name,\n words,\n classNames,\n components,\n locale,\n following,\n took,\n builder,\n onChannel,\n files,\n handovers,\n who,\n steps,\n}: PartProps & {\n components: SurfaceComponents | undefined;\n locale: KitLocale | undefined;\n following: RefObject<boolean>;\n took: number | null;\n builder: boolean;\n onChannel: boolean;\n files: FileHost;\n handovers: readonly Handover[] | undefined;\n who: Speaker;\n /** Whether the agent's steps show, and how long its last reply took. */\n steps: boolean;\n}) {\n const scroller = useRef<HTMLDivElement>(null);\n const said = useRef<HTMLDivElement>(null);\n const { messages, pending, draft, awaiting } = live;\n // The reply as it streams, at a reading pace (`reveal.ts`); when it is stored as a message, the\n // message goes on from where the reveal was, so the words never jump to the end.\n const shown = useRef(0);\n // On a channel the reply being written shows as typing until it is stored; then it shows as\n // the person gets it (its own typing while its parts go).\n const last = messages.at(-1);\n const outgoing =\n last !== undefined &&\n last.role === \"assistant\" &&\n last.delivery != null &&\n last.delivery !== \"failed\";\n const drafted = useReveal(draft, 0, (count) => {\n shown.current = count;\n });\n const lastDraft = useRef(\"\");\n const carried = useRef<{ id: string; from: number } | null>(null);\n const latest = messages.at(-1);\n if (\n latest?.role === \"assistant\" &&\n lastDraft.current !== \"\" &&\n draft === \"\" &&\n carried.current?.id !== latest.id\n ) {\n carried.current = { id: latest.id, from: shown.current };\n }\n lastDraft.current = draft;\n useLayoutEffect(() => {\n const box = scroller.current;\n if (box && following.current) box.scrollTop = box.scrollHeight;\n }, [messages, pending, drafted, following]);\n // What grows by itself (a surface's picture landing, a step opened on its output) keeps the\n // foot in view too, while the person is at it; and so does less room for it (the browser\n // opening large under it).\n useEffect(() => {\n const box = scroller.current;\n const log = said.current;\n if (!box || !log || typeof ResizeObserver === \"undefined\") return undefined;\n const observer = new ResizeObserver(() => {\n if (following.current) box.scrollTop = box.scrollHeight;\n });\n observer.observe(log);\n observer.observe(box);\n return () => {\n observer.disconnect();\n };\n }, [following]);\n\n // A surface takes input while the turn waits on it or, once nothing runs or waits, when the\n // agent showed it since the person last spoke; older ones are read, not used. On a channel the\n // person answered it there: here it only reads.\n const idle = !onChannel && !pending && awaiting === null;\n const lastSaid = messages.findLastIndex((message) => message.role === \"user\");\n // What the person did on each surface, by the surface's id: a surface draws its answer.\n const answers = new Map<string, Action>();\n for (const message of messages) {\n if (message.action) answers.set(message.action.surface, message.action);\n }\n // Drawn, who answers says where the agent handed it over; otherwise its `escalate` step does.\n const handed = handovers === undefined ? handoffs(messages) : NO_HANDOFFS;\n const placed = handoversAt(messages, handovers ?? []);\n const lines = (index: number) =>\n placed\n .get(index)\n ?.map((handover) => (\n <HandoverLine\n key={`${handover.at} ${handover.holder}`}\n handover={handover}\n name={name}\n words={words}\n classNames={classNames}\n code={locale?.code ?? \"en-US\"}\n />\n ));\n\n return (\n <div\n ref={scroller}\n onScroll={(event) => {\n const box = event.currentTarget;\n following.current = box.scrollHeight - box.scrollTop - box.clientHeight < NEAR_FOOT;\n }}\n part=\"transcript\"\n className={classes(\n classNames,\n \"sc-chat__log\",\n ...(onChannel ? ([\"sc-chat__log--channel\"] as const) : []),\n )}\n >\n <div ref={said} role=\"log\" aria-label={words.log}>\n {messages.map((message, index) => (\n <Fragment key={message.id}>\n {lines(index)}\n {message.role === \"user\" ? (\n <>\n <Heard\n message={message}\n after={messages[index - 1]}\n words={words}\n classNames={classNames}\n />\n <Said message={message} words={words} classNames={classNames} files={files} />\n {handovers !== undefined && (\n <Decided decision={message.decision} words={words} classNames={classNames} />\n )}\n </>\n ) : message.author === \"operator\" ? (\n <Business message={message} words={words} classNames={classNames} files={files} />\n ) : (\n <>\n <Reply\n message={message}\n from={carried.current?.id === message.id ? carried.current.from : undefined}\n awaiting={onChannel ? null : awaiting}\n current={idle && index > lastSaid}\n answers={answers}\n name={name}\n words={words}\n classNames={classNames}\n components={components}\n locale={locale}\n onAction={live.act}\n builder={builder}\n files={files}\n who={who}\n steps={steps}\n onChannel={onChannel}\n />\n {handed.has(message.id) && (\n <p className={classes(classNames, \"sc-chat__handoff\")}>\n {actionMark(\"escalate\", \"library\")}\n <span>{words.handedOff}</span>\n </p>\n )}\n </>\n )}\n </Fragment>\n ))}\n {lines(messages.length)}\n </div>\n {steps && !pending && took !== null && (\n <p className={classes(classNames, \"sc-chat__done\")}>{words.done(took)}</p>\n )}\n {pending && onChannel && !outgoing && <Typing label={words.typing} classNames={classNames} />}\n {pending && !onChannel && drafted !== \"\" && (\n <div\n aria-hidden\n part=\"message message-agent\"\n className={classes(classNames, \"sc-chat__text\", \"sc-chat__reply\")}\n >\n <Markdown text={drafted} />\n </div>\n )}\n </div>\n );\n}\n\n/** The channel's \"typing\": three dots in the business's bubble, while a reply or its parts come. */\nfunction Typing({ label, classNames }: { label: string; classNames: ClassNames }) {\n return (\n <p role=\"status\" aria-label={label} className={classes(classNames, \"sc-chat__typing\")}>\n <span />\n <span />\n <span />\n </p>\n );\n}\n\n/** How many of the last words heard a cut line quotes. */\nconst HEARD_WORDS = 8;\n\n/** The last words of what was heard, with an ellipsis before them when there was more. */\nexport function heardTail(heard: string, count = HEARD_WORDS): string {\n const words = heard.trim().split(/\\s+/).filter(Boolean);\n if (words.length <= count) return words.join(\" \");\n return `…${words.slice(-count).join(\" \")}`;\n}\n\n/**\n * On a call, what the person heard of the agent's last words before this message, when it wasn't\n * what was stored. After a reply (the greeting is the first), they cut it short: a quiet line\n * under it quotes the last of what they heard. With no reply before, it was a greeting from before\n * the API kept it: drawn here as the agent's words, where it was said.\n */\nfunction Heard({\n message,\n after,\n words,\n classNames,\n}: {\n message: Message;\n after: Message | undefined;\n words: ChatMessages;\n classNames: ClassNames;\n}) {\n const { heard } = message;\n if (heard == null) return null;\n if (after?.role === \"assistant\") {\n return <p className={classes(classNames, \"sc-chat__cut\")}>{words.cut(heardTail(heard))}</p>;\n }\n if (heard.trim() === \"\") return null;\n return (\n <div\n part=\"message message-agent\"\n className={classes(\n classNames,\n \"sc-chat__message\",\n \"sc-chat__message--agent\",\n \"sc-chat__message--heard\",\n )}\n >\n <div className={classes(classNames, \"sc-chat__text\")}>\n <p>{heard}</p>\n </div>\n </div>\n );\n}\n\n/**\n * The person's message: their words in a bubble (a voice note's player with its words under it);\n * the files they sent with it as chips over it, each opening where the host shows files. An\n * answer on a surface is its words alone: the surface shows its files.\n */\nfunction Said({\n message,\n words,\n classNames,\n files,\n}: {\n message: Message;\n words: ChatMessages;\n classNames: ClassNames;\n files: FileHost;\n}) {\n const sent = message.action ? [] : (message.files ?? []);\n const bubble = message.voice ? (\n <VoiceNote\n file={message.voice}\n text={message.text}\n parts=\"message message-person\"\n kind=\"sc-chat__message--person\"\n words={words}\n classNames={classNames}\n files={files}\n />\n ) : (\n message.text !== \"\" && (\n <p\n part=\"message message-person\"\n className={classes(\n classNames,\n \"sc-chat__message\",\n \"sc-chat__message--person\",\n ...(message.action ? ([\"sc-chat__message--action\"] as const) : []),\n )}\n >\n {message.text}\n </p>\n )\n );\n if (sent.length === 0) return bubble;\n return (\n <div part=\"files\" className={classes(classNames, \"sc-chat__said\")}>\n <FileChips files={sent} onOpen={files.open} />\n {bubble}\n </div>\n );\n}\n\n/**\n * A voice note on a channel, either way: a bubble with the page's own player, streaming from where\n * the file plays (asked again, once, when that ran out), and what was said under it.\n */\nfunction VoiceNote({\n file,\n text,\n parts,\n kind,\n words,\n classNames,\n files,\n}: {\n file: Attachment;\n text: string;\n /** The bubble's parts, a host's to style. */\n parts: string;\n kind: \"sc-chat__message--person\" | \"sc-chat__text\";\n words: ChatMessages;\n classNames: ClassNames;\n files: FileHost;\n}) {\n const played = usePlayed(file, files.play);\n const lost = useRef(false);\n return (\n <div\n part={parts}\n className={classes(\n classNames,\n ...(kind === \"sc-chat__text\" ? [] : ([\"sc-chat__message\"] as const)),\n kind,\n \"sc-chat__message--voice\",\n )}\n >\n <AudioPlayer\n src={played?.url}\n label={words.voiceNote}\n onError={() => {\n if (lost.current || played === null) return;\n lost.current = true;\n played.again();\n }}\n />\n {text !== \"\" && (\n <div className={classes(classNames, \"sc-chat__transcript\")}>\n <Markdown text={text} />\n </div>\n )}\n </div>\n );\n}\n\n/** Under a person's message the agent let pass this time: that it didn't answer it, and why. */\nfunction Decided({\n decision,\n words,\n classNames,\n}: {\n decision: Decision | null | undefined;\n words: ChatMessages;\n classNames: ClassNames;\n}) {\n const line = decisionLine(decision, words);\n if (line === null) return null;\n return <p className={classes(classNames, \"sc-chat__decision\")}>{line}</p>;\n}\n\n/**\n * Where who answers the conversation changed: a quiet line across the log, what changed and who\n * changed it, why, and when.\n */\nfunction HandoverLine({\n handover,\n name,\n words,\n classNames,\n code,\n}: {\n handover: Handover;\n name: string;\n words: ChatMessages;\n classNames: ClassNames;\n /** The locale's, for when. */\n code: string;\n}) {\n return (\n <p className={classes(classNames, \"sc-chat__handover\")}>\n <span>\n {handoverLine(handover, name, words)}\n <time dateTime={handover.at}>{whenSaid(handover.at, new Date(), code)}</time>\n </span>\n </p>\n );\n}\n\n/**\n * What a person of the business wrote on the channel, on the business's side but set apart from\n * the agent's words: a bubble of its own, the files it carried over it, and under it who wrote it\n * and where it got to.\n */\nfunction Business({\n message,\n words,\n classNames,\n files,\n}: {\n message: Message;\n words: ChatMessages;\n classNames: ClassNames;\n files: FileHost;\n}) {\n const sent = message.files ?? [];\n return (\n <div className={classes(classNames, \"sc-chat__business\")}>\n {sent.length > 0 && <FileChips files={sent} onOpen={files.open} />}\n {message.text !== \"\" && (\n <p\n part=\"message message-business\"\n className={classes(classNames, \"sc-chat__message\", \"sc-chat__message--business\")}\n >\n {message.text}\n </p>\n )}\n <p className={classes(classNames, \"sc-chat__meta\")}>\n <span>{words.business}</span>\n <DeliveryMark message={message} words={words} classNames={classNames} />\n </p>\n </div>\n );\n}\n\nconst DELIVERY_MARKS: Readonly<Record<Delivery, ReactNode>> = {\n queued: <ClockIcon aria-hidden />,\n sent: <CheckIcon aria-hidden weight=\"bold\" />,\n delivered: <ChecksIcon aria-hidden weight=\"bold\" />,\n read: <ChecksIcon aria-hidden weight=\"bold\" />,\n failed: <WarningCircleIcon aria-hidden weight=\"fill\" />,\n};\n\n/**\n * Where a message that went out on a channel got to, quietly: a clock while it waits to go, a\n * check once sent, two once delivered, two in the accent once read; one that never got there in\n * the danger tone, with why. Nothing for a message that didn't go out.\n */\nfunction DeliveryMark({\n message,\n words,\n classNames,\n}: {\n message: Message;\n words: ChatMessages;\n classNames: ClassNames;\n}) {\n const { delivery } = message;\n if (delivery == null) return null;\n const failed = delivery === \"failed\";\n return (\n <span\n role={failed ? undefined : \"img\"}\n aria-label={failed ? undefined : words.delivery[delivery]}\n title={failed ? undefined : words.delivery[delivery]}\n data-delivery={delivery}\n className={classes(classNames, \"sc-chat__delivery\")}\n >\n {DELIVERY_MARKS[delivery]}\n {failed && <span>{words.undelivered(message.delivery_error ?? null)}</span>}\n </span>\n );\n}\n\ninterface DrawProps {\n words: ChatMessages;\n classNames: ClassNames;\n components: SurfaceComponents | undefined;\n locale: KitLocale | undefined;\n onAction: (action: Action) => void;\n}\n\n/**\n * The agent's message: its words, then the steps it took as a compact list (a mark for the\n * state, the action's name, its output), then what each step drew (with what the person did on\n * it, from `answers`), and the card for one that waits to be allowed by whoever this page speaks\n * for (on a person's page, one the business allows is a quiet line instead); on a channel, where\n * it got to.\n */\nfunction Reply({\n message,\n from,\n awaiting,\n current,\n answers,\n name,\n words,\n classNames,\n components,\n locale,\n onAction,\n builder,\n files,\n who,\n steps,\n onChannel,\n}: DrawProps & {\n message: Message;\n /** It was streaming: its words go on revealing from here. None: they show whole. */\n from: number | undefined;\n awaiting: string | null;\n current: boolean;\n answers: ReadonlyMap<string, Action>;\n name: string;\n builder: boolean;\n files: FileHost;\n who: Speaker;\n /** Whether the steps it took show, as a list under its words. */\n steps: boolean;\n /** On a channel: its words as the person got them, a bubble for each part, and who sent them. */\n onChannel: boolean;\n}) {\n const text = useReveal(message.text, from ?? message.text.length);\n // On a channel, what the person there has got so far; elsewhere, the words as they come.\n const { shown: said, typing } = onChannel\n ? channelParts(message, text)\n : { shown: [text], typing: false };\n return (\n <div\n part=\"message message-agent\"\n className={classes(classNames, \"sc-chat__message\", \"sc-chat__message--agent\")}\n >\n {/* A voice note shows once it went, as each part does. */}\n {message.voice && said.length > 0 ? (\n <VoiceNote\n file={message.voice}\n text={text}\n parts=\"text\"\n kind=\"sc-chat__text\"\n words={words}\n classNames={classNames}\n files={files}\n />\n ) : (\n text !== \"\" &&\n said.map((words, index) => (\n <div key={index} part=\"text\" className={classes(classNames, \"sc-chat__text\")}>\n <Markdown text={words} />\n </div>\n ))\n )}\n {typing && <Typing label={words.typing} classNames={classNames} />}\n {steps && message.steps.length > 0 && (\n <ol className={classes(classNames, \"sc-chat__steps\")}>\n {message.steps.map((step, index) => (\n <li\n key={step.id}\n className={classes(\n classNames,\n \"sc-chat__step\",\n `sc-chat__step--${shownState(step, message.steps.slice(0, index))}`,\n )}\n >\n {builder ? (\n <BuilderStep step={step} words={words} classNames={classNames} />\n ) : (\n <>\n <Mark state={step.state} action={step.action} classNames={classNames} />\n <span>{words.steps[step.action] ?? actionWords(step.action)}</span>\n {/* What a step answered is the model's, in its words: only why it failed. */}\n {step.state === \"failed\" && step.output !== null && <small>{step.output}</small>}\n </>\n )}\n </li>\n ))}\n </ol>\n )}\n {message.steps.map(\n (step) =>\n step.surface && (\n <div\n key={step.id}\n part=\"surface\"\n className={classes(\n classNames,\n \"sc-chat__screen\",\n ...(framesItself(step.surface) ? ([\"sc-chat__screen--bare\"] as const) : []),\n )}\n >\n <Surface\n surface={step.surface}\n active={step.id === awaiting || current}\n answered={answers.get(step.id)}\n components={components}\n classNames={classNames}\n messages={words.kit}\n locale={locale}\n files={files}\n onAction={(action) => onAction({ surface: step.id, ...action })}\n />\n </div>\n ),\n )}\n {message.steps.map((step) => {\n const { request } = step;\n if (request === null) return null;\n if (request.decides === \"business\" && who === \"person\") {\n return (\n <p\n key={step.id}\n part=\"confirming\"\n className={classes(classNames, \"sc-chat__confirming\")}\n >\n <ClockIcon aria-hidden />\n <span>{words.confirming}</span>\n </p>\n );\n }\n return (\n <Approval\n key={step.id}\n request={request}\n name={name}\n words={words}\n classNames={classNames}\n components={components}\n locale={locale}\n onAction={(action) => onAction({ surface: step.id, ...action })}\n />\n );\n })}\n {message.delivery != null && (\n <p className={classes(classNames, \"sc-chat__meta\")}>\n {onChannel && <span>{name}</span>}\n <DeliveryMark message={message} words={words} classNames={classNames} />\n </p>\n )}\n </div>\n );\n}\n\n/**\n * A step's state as its list shows it, after the steps `before` it in its reply: the actions of\n * one reply run one after another, in its order, so one still `running` after another that runs\n * is only to come (`queued`).\n */\nexport function shownState(step: Step, before: readonly Step[]): StepState | \"queued\" {\n const behind = before.some((earlier) => earlier.state === \"running\");\n return step.state === \"running\" && behind ? \"queued\" : step.state;\n}\n\n/**\n * A step in the builder's look, v2's: its mark and its name, \"failed\" beside it when it did, and\n * what it returned folded under a caret that shows on hover, opened on a click.\n */\nfunction BuilderStep({\n step,\n words,\n classNames,\n}: {\n step: Step;\n words: ChatMessages;\n classNames: ClassNames;\n}) {\n const row = (\n <>\n <Mark state={step.state} action={step.action} classNames={classNames} />\n <span>{words.steps[step.action] ?? actionWords(step.action)}</span>\n {step.state === \"failed\" && <em>{words.failed}</em>}\n </>\n );\n if (!step.output) return row;\n return (\n <details>\n <summary>\n {row}\n <CaretRightIcon aria-hidden />\n </summary>\n <pre className={classes(classNames, \"sc-chat__output\")}>{step.output}</pre>\n </details>\n );\n}\n\n/**\n * A step's mark on the list's line: the kind of work it is (its glyph) once it is done, a turning\n * ring while it runs, a ring while it waits for the person, a warning when it failed.\n */\nfunction Mark({\n state,\n action,\n classNames,\n}: {\n state: StepState;\n action: string;\n classNames: ClassNames;\n}) {\n const Glyph = stepGlyph(action);\n return (\n <span aria-hidden className={classes(classNames, \"sc-chat__mark\")}>\n {state === \"done\" ? (\n <Glyph />\n ) : state === \"running\" ? null : (\n <svg viewBox=\"0 0 14 14\" fill=\"none\">\n {MARKS[state]}\n </svg>\n )}\n </span>\n );\n}\n\nconst STROKE = { stroke: \"currentColor\", strokeWidth: 1.5, strokeLinecap: \"round\" } as const;\nconst MARKS: Record<\"waiting\" | \"failed\", ReactNode> = {\n waiting: <circle cx=\"7\" cy=\"7\" r=\"4.75\" {...STROKE} />,\n failed: (\n <>\n <path d=\"M7 1.9l5.6 9.7H1.4L7 1.9z\" {...STROKE} strokeLinejoin=\"round\" />\n <path d=\"M7 5.6v2.6\" {...STROKE} />\n <circle cx=\"7\" cy=\"10\" r=\"0.8\" fill=\"currentColor\" />\n </>\n ),\n};\n\n/** How long the last reply took, in whole seconds, once it is in; none before the first. */\nfunction useTook(pending: boolean): number | null {\n const [took, setTook] = useState<number | null>(null);\n const started = useRef<number | null>(null);\n useEffect(() => {\n if (pending) {\n started.current = Date.now();\n setTook(null);\n } else if (started.current !== null) {\n setTook(Math.max(1, Math.round((Date.now() - started.current) / 1000)));\n started.current = null;\n }\n }, [pending]);\n return took;\n}\n\n/**\n * What is happening while a reply is on its way, in one quiet line over the composer: a dot that\n * breathes, what goes on (`label`) under a sweeping light, the seconds it has taken, and how to\n * stop it. A new label rises in where the last was.\n */\nfunction Status({\n label,\n stoppable,\n timed,\n words,\n classNames,\n}: {\n label: string;\n /** Whether the reply can be stopped from here: not on a channel, where it runs on its own. */\n stoppable: boolean;\n /** Whether it says the seconds so far and the key that stops it: not where steps are hidden. */\n timed: boolean;\n words: ChatMessages;\n classNames: ClassNames;\n}) {\n const [seconds, setSeconds] = useState(0);\n useEffect(() => {\n const started = Date.now();\n const tick = setInterval(() => {\n setSeconds(Math.floor((Date.now() - started) / 1000));\n }, 1000);\n return () => {\n clearInterval(tick);\n };\n }, []);\n return (\n <p role=\"status\" part=\"status\" className={classes(classNames, \"sc-chat__status\")}>\n <i aria-hidden />\n <span key={label}>{label}…</span>\n {timed && <small>{words.elapsed(seconds)}</small>}\n {timed && stoppable && <kbd>{words.escape}</kbd>}\n </p>\n );\n}\n\n/**\n * An action the platform holds until the person allows it, as v2's card: a head that says it\n * needs their approval, then the sentence, what the action would take, and the two answers,\n * drawn as a surface so the host's blocks and words apply. Drawn from the step, so it is there\n * live and read back alike.\n */\nfunction Approval({\n request,\n name,\n words,\n classNames,\n components,\n locale,\n onAction,\n}: Omit<DrawProps, \"onAction\"> & {\n request: Request;\n name: string;\n onAction: (action: SurfaceAction) => void;\n}) {\n const sentence = words.request(name, request.action);\n const surface: Shown = {\n blocks: [\n {\n type: \"fields\",\n items: Object.entries(request.input).map(([field, value]) => ({\n label: words.inputs[field] ?? field,\n value: typeof value === \"string\" ? value : JSON.stringify(value),\n })),\n },\n {\n type: \"stack\",\n direction: \"row\",\n children: [\n { type: \"button\", label: words.allow, action: \"approve\", tone: \"primary\" },\n { type: \"button\", label: words.decline, action: \"decline\", tone: \"neutral\" },\n ],\n },\n ],\n text: sentence,\n };\n return (\n <div part=\"approval\" className={classes(classNames, \"sc-chat__request\")}>\n <header>\n <ShieldWarningIcon aria-hidden />\n {words.approval}\n </header>\n <div>\n <p>{sentence}</p>\n <Surface\n surface={surface}\n components={components}\n classNames={classNames}\n messages={words.kit}\n locale={locale}\n onAction={onAction}\n />\n </div>\n </div>\n );\n}\n\n/**\n * Where the person writes: a box that grows a few lines with the text. Enter sends, Shift+Enter\n * breaks the line; nothing goes while a reply is on its way or the socket is closed, but the\n * person can keep writing. While the turn waits for them to act above, the box is closed and\n * says so; while a reply is on its way, the send button is a stop button (Esc stops too). The\n * host's `compose` is said from here, or put in the box. With `uploads`, the paperclip attaches\n * files (a picture pasted too): they upload at once, as chips over the words, and go with them\n * (or alone) once every one is in. With `write`, what is written goes to the host instead (a\n * person of the business, on a channel): whatever the turn is doing, emptied once it went.\n */\nfunction Composer({\n live,\n name,\n words,\n classNames,\n actions,\n compose,\n taken,\n fresh,\n builder,\n uploads,\n files,\n dictate,\n write,\n onSent,\n}: PartProps & {\n actions: ReactNode;\n compose: ChatCompose | undefined;\n taken: RefObject<number | null>;\n fresh: boolean;\n builder: boolean;\n uploads: Uploads | undefined;\n files: FileHost;\n dictate: Dictate | undefined;\n write: ((text: string, files: readonly string[]) => Promise<unknown>) | undefined;\n onSent: () => void;\n}) {\n const [text, setText] = useState(\"\");\n // What is written on its way to the host's `write`: nothing more goes until it went.\n const [writing, setWriting] = useState(false);\n const input = useRef<HTMLTextAreaElement>(null);\n const picker = useRef<HTMLInputElement>(null);\n // Counts the host's texts put in the box: each one focuses it, the caret at the text's end.\n const [placed, setPlaced] = useState(0);\n // Waiting for the person to act above holds the composer, unless the words go to the host.\n const held = write === undefined && live.awaiting !== null;\n // What is dictated joins what is written, after it, and the caret goes to its end.\n const dictation = useDictation(dictate, (words) => {\n setText((now) => (now.trim() === \"\" ? words : `${now.trimEnd()} ${words}`));\n setPlaced((count) => count + 1);\n });\n const listening = dictation.state === \"listening\";\n\n // The host's request, once: said when it asks so (waiting for the socket to open), put in the\n // box otherwise, or when it cannot go now (a reply on its way, a turn waiting).\n useEffect(() => {\n if (compose === undefined || taken.current === compose.key) return;\n if (compose.send && !live.open) return;\n taken.current = compose.key;\n if (compose.send && live.say(compose.text)) {\n onSent();\n return;\n }\n setText(compose.text);\n setPlaced((count) => count + 1);\n }, [compose, taken, live, onSent]);\n\n useLayoutEffect(() => {\n const box = input.current;\n if (placed === 0 || box === null) return;\n box.focus();\n box.setSelectionRange(box.value.length, box.value.length);\n }, [placed]);\n\n const attached = uploads?.ids ?? [];\n const settled = uploads === undefined || uploads.waiting === null;\n const said = text.trim() !== \"\" || attached.length > 0;\n const sent = () => {\n setText(\"\");\n uploads?.clear();\n onSent();\n };\n const submit = () => {\n if (!settled) return;\n if (write === undefined) {\n if (live.say(text, attached)) sent();\n return;\n }\n if (writing || !said) return;\n setWriting(true);\n write(text.trim(), attached)\n .then(sent, () => undefined)\n .finally(() => {\n setWriting(false);\n });\n };\n const onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key !== \"Enter\" || event.shiftKey || event.nativeEvent.isComposing) return;\n event.preventDefault();\n submit();\n };\n const ready =\n write === undefined\n ? live.open && !live.pending && !held && settled && said\n : !writing && settled && said;\n const invitation = write === undefined ? words.placeholder(name, fresh) : words.write;\n\n return (\n <form\n onSubmit={(event) => {\n event.preventDefault();\n submit();\n }}\n part=\"composer\"\n className={classes(classNames, \"sc-chat__composer\")}\n >\n {uploads && uploads.items.length > 0 && (\n <div part=\"files\" className={classes(classNames, \"sc-chat__files\")}>\n <UploadChips uploads={uploads} host={files} />\n </div>\n )}\n <textarea\n ref={input}\n rows={1}\n value={text}\n maxLength={20_000}\n disabled={held}\n // The builder takes the keyboard as it opens, as v2's did: it is there to be told things.\n autoFocus={builder}\n aria-label={invitation}\n placeholder={\n held ? words.awaiting : live.open || write !== undefined ? invitation : words.connecting\n }\n onChange={(event) => {\n setText(event.target.value);\n }}\n onKeyDown={onKeyDown}\n part=\"input\"\n // A picture pasted (a screenshot, an image copied) is attached; words pasted stay words.\n onPaste={(event) => {\n const pasted = [...event.clipboardData.files];\n if (!uploads || pasted.length === 0) return;\n if (event.clipboardData.getData(\"text/plain\") !== \"\") return;\n event.preventDefault();\n uploads.add(pasted);\n }}\n className={classes(classNames, \"sc-chat__input\")}\n />\n {uploads && (\n <>\n <button\n type=\"button\"\n aria-label={words.attach}\n title={words.attach}\n disabled={held}\n onClick={() => picker.current?.click()}\n part=\"attach\"\n className={classes(classNames, \"sc-chat__attach\")}\n >\n <PaperclipIcon aria-hidden />\n </button>\n <input\n ref={picker}\n type=\"file\"\n multiple\n hidden\n tabIndex={-1}\n onChange={(event) => {\n uploads.add([...(event.target.files ?? [])]);\n event.target.value = \"\";\n }}\n />\n </>\n )}\n <div part=\"actions\" className={classes(classNames, \"sc-chat__actions\")}>\n {dictation.available && (\n <button\n type=\"button\"\n aria-label={listening ? words.dictateStop : words.dictate}\n title={listening ? words.dictateStop : words.dictate}\n aria-pressed={listening}\n data-state={dictation.state}\n disabled={held || dictation.state === \"writing\"}\n onClick={dictation.toggle}\n part=\"dictate\"\n className={classes(classNames, \"sc-chat__dictate\")}\n >\n <MicrophoneIcon aria-hidden weight={listening ? \"fill\" : \"regular\"} />\n </button>\n )}\n {dictation.state !== \"idle\" && (\n <span\n role=\"status\"\n data-state={dictation.state}\n className={classes(classNames, \"sc-chat__dictation\")}\n >\n {words.dictation[dictation.state]}\n </span>\n )}\n {actions}\n </div>\n {live.pending && write === undefined ? (\n <button\n type=\"button\"\n aria-label={words.stop}\n title={`${words.stop} (Esc)`}\n onClick={() => live.stop()}\n part=\"stop\"\n className={classes(classNames, \"sc-chat__stop\")}\n >\n <StopIcon weight=\"fill\" aria-hidden />\n </button>\n ) : (\n <button\n type=\"submit\"\n aria-label={words.send}\n title={words.send}\n disabled={!ready}\n part=\"send\"\n className={classes(classNames, \"sc-chat__send\")}\n >\n <ArrowUpIcon weight=\"bold\" aria-hidden />\n </button>\n )}\n </form>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"AgentChat.js","names":[],"sources":["../src/AgentChat.tsx"],"sourcesContent":["import {\n ArrowUpIcon,\n CaretRightIcon,\n CheckIcon,\n ChecksIcon,\n ClockIcon,\n MicrophoneIcon,\n PaperclipIcon,\n ShieldWarningIcon,\n StopIcon,\n UploadSimpleIcon,\n WarningCircleIcon,\n} from \"@phosphor-icons/react\";\nimport {\n Fragment,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n type KeyboardEvent,\n type ReactNode,\n type RefObject,\n} from \"react\";\n\nimport { actionWords } from \"./about\";\nimport type { Surface as Shown } from \"./blocks\";\nimport {\n BROWSER_MESSAGES,\n BrowserView,\n type BrowserMessages,\n type BrowserPart,\n} from \"./BrowserView\";\nimport { channelParts } from \"./channelParts\";\nimport { classes } from \"./classes\";\nimport { useDictation, type Dictate } from \"./useDictation\";\nimport { useReveal } from \"./reveal\";\nimport type { Client } from \"./client\";\nimport type { Speaker } from \"./credentials\";\nimport { useConversationFiles } from \"./conversationFiles\";\nimport { FILES_PER_MESSAGE } from \"./frames\";\nimport { actionMark } from \"./marks\";\nimport { AudioPlayer } from \"./kit/AudioPlayer\";\nimport { KitProvider, type KitPart } from \"./kit/context\";\nimport { carriesFiles, FileChips, UploadChips, useUploads, type Uploads } from \"./kit/FileField\";\nimport { KIT_MESSAGES, type KitLocale, type KitMessages } from \"./kit/messages\";\nimport type { FileHost } from \"./kit/uploads\";\nimport { stepGlyph } from \"./stepGlyphs\";\nimport { Markdown } from \"./surface/Markdown\";\nimport type { SurfaceComponents, SurfacePart } from \"./surface/scope\";\nimport { framesItself, Surface, usePlayed } from \"./surface/Surface\";\nimport type { SurfaceAction } from \"./surface/values\";\nimport type {\n Action,\n Attachment,\n Decision,\n Delivery,\n Handover,\n Holder,\n Message,\n Request,\n Step,\n StepApp,\n StepState,\n} from \"./types\";\nimport {\n NO_TOOL,\n useConversation,\n type LiveConversation,\n type ToolHandler,\n} from \"./useConversation\";\n\n/** The words the chat says; a host gives its own, in its language. */\nexport interface ChatMessages {\n /** The composer's invitation, and the field's name; `fresh` while nothing has been said. */\n placeholder: (name: string, fresh: boolean) => string;\n /** In the composer while the socket is not open. */\n connecting: string;\n /** In the composer while the turn waits for the person to act above. */\n awaiting: string;\n /** Over the composer while a reply is on its way. */\n thinking: (name: string) => string;\n /** Over the composer while a reply is on its way, where the agent's steps are hidden. */\n typing: string;\n /** The builder's line over the composer, while nothing runs and nothing is written yet. */\n working: string;\n /** The builder's line over the composer, while its words come. */\n writing: string;\n /** How long the reply has taken so far, beside it. */\n elapsed: (seconds: number) => string;\n /** At the end of that line: how to stop the reply. */\n escape: string;\n /** Under the log once a reply is in: how long it took. */\n done: (seconds: number) => string;\n /** A conversation with nothing said yet: its title. */\n empty: (name: string) => string;\n /** Under the title, a line on what to say; nothing when empty. */\n intro: (name: string) => string;\n /** The send button's name. */\n send: string;\n /** The button that attaches files, by its name. */\n attach: string;\n /** Over the chat while files are dragged over it. */\n drop: string;\n /** The microphone's name: to dictate, and to stop and have it written. */\n dictate: string;\n dictateStop: string;\n /** Beside the microphone while it listens, writes, or could not. */\n dictation: Readonly<Record<\"listening\" | \"writing\" | \"failed\", string>>;\n /** The stop button's name, in the send button's place while a reply is on its way. */\n stop: string;\n /** The message list's name, for screen readers. */\n log: string;\n /** A step's name, by the action's name as the platform gives it; the name itself otherwise. */\n steps: Readonly<Record<string, string>>;\n /** Beside a step that failed, in the builder's look: the colour is never the whole message. */\n failed: string;\n /** What heads the card of an action that needs the person's leave. */\n approval: string;\n /** The agent wants to run an action that needs the person's leave. */\n request: (name: string, action: string) => string;\n /** An action's input fields, by their name, as the approval card labels them. */\n inputs: Readonly<Record<string, string>>;\n allow: string;\n decline: string;\n /**\n * On a person's page, in place of the approval card: what the agent asked to do waits for the\n * business's yes (`decides: \"business\"`), which its people give from their app.\n */\n confirming: string;\n /** The line across the log where the agent handed the conversation to a person. */\n handedOff: string;\n /**\n * The line across the log where who answers the conversation changed (`handovers`), before\n * why: to whom (`holder`), and who changed it (`by`).\n */\n handover: (holder: Holder, by: HandoverBy, name: string) => string;\n /** Under a person's message the agent let pass this time (a `skip`), before why. */\n skipped: string;\n /**\n * On a call, under a reply the person cut short: the last of what they heard of it (`\"\"`:\n * nothing of it).\n */\n cut: (heard: string) => string;\n /** The composer's invitation when the host takes what is written (`write`): the business's. */\n write: string;\n /** Under what a person of the business wrote on the channel: who it was. */\n business: string;\n /** A voice note's player, by its name. */\n voiceNote: string;\n /** Where what went out on a channel got to, as its mark's name. */\n delivery: Readonly<Record<Delivery, string>>;\n /** Beside a message that never reached the person, with the provider's reason when it gave one. */\n undelivered: (error: string | null) => string;\n /**\n * What the page answers when the agent calls one of the host's tools and the chat was given no\n * `onTool` to run it: read by the agent, never shown.\n */\n noTool: string;\n /** What the kit's controls say on the agent's screens: a form's checks, a calendar, a list. */\n kit: Partial<KitMessages>;\n /** What the browser the agent drives says: who holds it, take it, give it back. */\n browser: BrowserMessages;\n}\n\nexport const CHAT_MESSAGES: ChatMessages = {\n placeholder: (name) => `Write to ${name}…`,\n connecting: \"Connecting…\",\n awaiting: \"Answer above to go on…\",\n thinking: (name) => `${name} is thinking`,\n typing: \"Typing\",\n working: \"Working\",\n writing: \"Writing\",\n elapsed: (seconds) => `${seconds} s`,\n escape: \"esc to stop\",\n done: (seconds) => `Done in ${seconds} s`,\n empty: (name) => `Talk with ${name}`,\n intro: () => \"\",\n send: \"Send\",\n attach: \"Attach files\",\n drop: \"Drop to attach\",\n dictate: \"Dictate\",\n dictateStop: \"Stop and write it\",\n dictation: {\n listening: \"Listening…\",\n writing: \"Writing it down…\",\n failed: \"Couldn't hear you: allow the microphone and try again\",\n },\n stop: \"Stop\",\n log: \"Conversation\",\n steps: { show: \"Shows\", ask_person: \"Asks\" },\n failed: \"failed\",\n approval: \"Needs your approval\",\n request: (name, action) => `${name} wants to ${action}`,\n inputs: {},\n allow: \"Allow\",\n decline: \"Decline\",\n confirming: \"Waiting for the business to confirm\",\n handedOff: \"Handed to a person\",\n handover: (holder, by, name) => {\n const automation = by.kind === \"automation\" ? ` by “${by.title}”` : \"\";\n switch (holder) {\n case \"agent\":\n if (by.kind === \"owner\") return `You gave it back to ${name}`;\n return `Given back to ${name}${automation}`;\n case \"person\":\n if (by.kind === \"owner\") return `You paused ${name}`;\n if (by.kind === \"agent\") return `${name} handed it to a person`;\n return `Handed to a person${automation}`;\n case \"nobody\":\n return `Ignored${automation}`;\n }\n },\n skipped: \"Not answered\",\n cut: (heard) =>\n heard === \"\" ? \"Cut off before a word of it was heard\" : `Cut off after «${heard}»`,\n write: \"Reply as the business…\",\n business: \"You\",\n voiceNote: \"Voice note\",\n delivery: {\n queued: \"Waiting to go\",\n sent: \"Sent\",\n delivered: \"Delivered\",\n read: \"Read\",\n failed: \"Not delivered\",\n },\n undelivered: (error) => (error ? `Not delivered: ${error}` : \"Not delivered\"),\n noTool: NO_TOOL,\n kit: KIT_MESSAGES,\n browser: BROWSER_MESSAGES,\n};\n\n/** The chat's parts, by the class each carries; `classNames` adds a host's own under the same keys. */\nexport type ChatPart =\n | \"sc-chat\"\n | \"sc-chat--builder\"\n | \"sc-chat--console\"\n | \"sc-chat__log\"\n | \"sc-chat__log--channel\"\n | \"sc-chat__message\"\n | \"sc-chat__message--person\"\n | \"sc-chat__message--agent\"\n | \"sc-chat__message--action\"\n | \"sc-chat__message--business\"\n | \"sc-chat__said\"\n | \"sc-chat__business\"\n | \"sc-chat__meta\"\n | \"sc-chat__delivery\"\n | \"sc-chat__text\"\n | \"sc-chat__steps\"\n | \"sc-chat__step\"\n | \"sc-chat__mark\"\n | \"sc-chat__step--running\"\n | \"sc-chat__step--queued\"\n | \"sc-chat__step--waiting\"\n | \"sc-chat__step--done\"\n | \"sc-chat__step--failed\"\n | \"sc-chat__output\"\n | \"sc-chat__request\"\n | \"sc-chat__confirming\"\n | \"sc-chat__screen\"\n | \"sc-chat__screen--bare\"\n | \"sc-chat__handoff\"\n | \"sc-chat__handover\"\n | \"sc-chat__decision\"\n | \"sc-chat__message--heard\"\n | \"sc-chat__message--voice\"\n | \"sc-chat__transcript\"\n | \"sc-chat__cut\"\n | \"sc-chat__reply\"\n | \"sc-chat__status\"\n | \"sc-chat__done\"\n | \"sc-chat__empty\"\n | \"sc-chat__suggestion\"\n | \"sc-chat__composer\"\n | \"sc-chat__files\"\n | \"sc-chat__attach\"\n | \"sc-chat__dictate\"\n | \"sc-chat__typing\"\n | \"sc-chat__dictation\"\n | \"sc-chat__drop\"\n | \"sc-chat__input\"\n | \"sc-chat__actions\"\n | \"sc-chat__send\"\n | \"sc-chat__stop\";\n\ntype ClassNames =\n Partial<Record<ChatPart | SurfacePart | KitPart | BrowserPart, string>> | undefined;\n\n/**\n * How the chat looks. `agent` is an agent's conversation. `builder` is the builder's, v2's: the\n * working line says what it does under the brand's sweeping light, the steps open on what they\n * returned, the send is the brand's; `console` is the same seen as a console beside the work, the\n * person's words as prompt lines.\n */\nexport type ChatLook = \"agent\" | \"builder\" | \"console\";\n\n/**\n * Whether the chat shows the steps the agent took (searching its files, remembering, calling a\n * tool, with what each returned): `shown` for the business, who wants to see the work; `hidden`\n * for the people it serves, who see only what the agent says and shows, and a quiet line while\n * it works.\n */\nexport type ChatSteps = \"shown\" | \"hidden\";\n\n/**\n * Who changed who answers a conversation: one of the business's people (`owner`), the agent itself\n * (its `escalate`), the platform (a release after quiet hours, a contact the owner marked), or an\n * automation, by its title.\n */\nexport type HandoverBy =\n { kind: \"owner\" | \"agent\" | \"platform\" } | { kind: \"automation\"; title: string };\n\n/** Something the host hands the chat from outside it, to say or to leave in the composer. */\nexport interface ChatCompose {\n text: string;\n /** Said at once; otherwise left in the composer for the person to finish. */\n send: boolean;\n /** Tells one request from the last: each new key is taken once. */\n key: number;\n}\n\nexport interface AgentChatProps {\n client: Client;\n conversationId: string;\n /** The agent's name, for the words that address it. */\n name: string;\n messages?: Partial<ChatMessages> | undefined;\n classNames?: ClassNames;\n /** The host's own drawing of a block type, for every surface the agent shows. */\n components?: SurfaceComponents | undefined;\n /** The language of the surfaces' calendars, days, times and numbers; English by default. */\n locale?: KitLocale | undefined;\n /** An error's code, from the socket or `load` for a history that could not be read; the host words it. */\n onError?: ((code: string) => void) | undefined;\n /** The host's own controls, at the composer's left. */\n actions?: ReactNode;\n /** A few things the person might say first, offered while nothing has been said; a click says it. */\n suggestions?: readonly string[] | undefined;\n /**\n * A request from elsewhere on the page (a button beside the chat), taken once each time `key`\n * changes; the one the chat mounts with is not. With `send` it is said, once the socket is open;\n * while a reply is on its way or the turn waits, it goes into the composer instead. Without, it\n * goes into the composer, focused with the caret at its end.\n */\n compose?: ChatCompose | undefined;\n /** An agent's conversation by default; the builder's, or the builder's as a console. */\n look?: ChatLook | undefined;\n /**\n * Whether the agent's steps show: by default as the page speaks (`client.who`): `shown` for the\n * business, `hidden` for a person or a visitor, who see what the agent says and shows (its\n * surfaces, files, a yes it waits for) and `typing` while it works.\n */\n steps?: ChatSteps | undefined;\n /**\n * Whether the person can attach files to what they say (the paperclip, dropping them on the\n * chat, pasting a picture): each uploads to the conversation at once. On in every look, the\n * builder's too; a host turns it off where nobody talks (a transcript read).\n */\n attachments?: boolean | undefined;\n /**\n * Opens a file of the conversation (one the person sent, one sent through a form), as the host\n * shows files (`FileView` in a dialog, its bytes from the API); without it, files only read.\n */\n onOpenFile?: ((file: Attachment) => void) | undefined;\n /**\n * Turns what the person says out loud into words in the composer (the microphone beside the\n * paperclip): the host's speech to text. Without it there is no microphone.\n */\n dictate?: Dictate | undefined;\n /**\n * Where what is written goes instead of the socket: on a conversation on a channel, a person of\n * the business writing to the person there (`POST /conversations/{id}/operator`). The composer\n * then says `write`, takes words and files whatever the agent is doing, and empties once the\n * promise resolves (a rejection leaves them, for the host to say why); what was written comes\n * back on the socket as a message.\n */\n write?: ((text: string, files: readonly string[]) => Promise<unknown>) | undefined;\n /**\n * Whether the log draws who answers the conversation, for a host of the business's (the inbox,\n * the activity): each change (read with the history, then heard live) a quiet line where it\n * fell, with why and when, and under a person's message the agent let pass, that it did. Off,\n * the log draws only where the agent handed it to a person, from its `escalate` step.\n */\n handovers?: boolean | undefined;\n /** Hears each change of who answers the conversation, live: the host's own views of it follow. */\n onHolder?: ((holder: Holder, handover: Handover) => void) | undefined;\n /** Hears each step the agent starts, live, by its action's name: the host's views follow. */\n onStep?: ((action: string) => void) | undefined;\n /**\n * The conversation's last change of who answers it, as the host knows it (one it made itself,\n * as its request answered): drawn at once, whether or not the socket tells it, and kept once.\n */\n handover?: Handover | null | undefined;\n /**\n * Runs one of the host's own tools the agent calls in the page (opening a record in the host's\n * screen, say): what it resolves to goes back to the agent, what it rejects with as why it\n * failed; its step shows as working meanwhile. Without it, each is refused with `noTool`.\n */\n onTool?: ToolHandler | undefined;\n}\n\n/** How close to the foot, in pixels, still counts as being at it (v2's). */\nconst NEAR_FOOT = 80;\n\n/**\n * The conversation with an agent: the person's messages at the right in a bubble, the agent's at\n * the left as text with the steps it took and what they drew, its reply growing as it streams;\n * the composer at the foot. On a channel, the business's side stays at the left: the agent's\n * words with where they got to (a quiet mark), and what a person of the business wrote set apart\n * in a bubble of its own; the surfaces went to the person there, so they only read here, and the\n * reply, which runs on its own time, can't be stopped from here. With `handovers`, each change of\n * who answers it is a quiet line where it fell, the moment it is made, and a person's message the\n * agent let pass says so under it. The host picks the conversation; another id starts the chat\n * afresh.\n */\nexport function AgentChat(props: AgentChatProps) {\n // The last request taken, kept across conversations so another one does not take it again. The\n // one given at mount counts as taken: a chat mounted again never says it twice.\n const taken = useRef<number | null>(props.compose?.key ?? null);\n // The kit's pieces in it (a file's chip, a surface's controls) read the host's words and classes.\n const kit = props.messages?.kit ?? CHAT_MESSAGES.kit;\n return (\n <KitProvider classNames={props.classNames} messages={kit} locale={props.locale}>\n <Chat key={props.conversationId} {...props} taken={taken} />\n </KitProvider>\n );\n}\n\nfunction Chat({\n client,\n conversationId,\n name,\n messages,\n classNames,\n components,\n locale,\n onError,\n actions,\n suggestions,\n compose,\n look = \"agent\",\n steps = client.who === \"person\" ? \"hidden\" : \"shown\",\n attachments = true,\n onOpenFile,\n dictate,\n write,\n handovers = false,\n onHolder,\n onStep,\n handover,\n onTool,\n taken,\n}: AgentChatProps & { taken: RefObject<number | null> }) {\n const words = { ...CHAT_MESSAGES, ...messages };\n const live = useConversation(client, conversationId, {\n onError,\n onHolder,\n onStep,\n handover,\n onTool: onTool ?? (() => Promise.reject(new Error(words.noTool))),\n });\n const files = useConversationFiles(client, conversationId, live.messages, onOpenFile);\n // What the person attaches to their next message: picked, dropped on the chat, or pasted.\n const uploads = useUploads(attachments ? files : undefined, { max: FILES_PER_MESSAGE });\n // Files go with what is said, once the turn waits on nothing; to the host's `write`, at once.\n const attaching = attachments && (write !== undefined || live.awaiting === null);\n const [over, setOver] = useState(false);\n // Whether the messages follow the conversation down: until the person scrolls up to read, and\n // again as soon as they speak.\n const following = useRef(true);\n const fresh = !live.loading && live.messages.length === 0 && !live.pending;\n const took = useTook(live.pending);\n const builder = look !== \"agent\";\n const { pending } = live;\n // A conversation on a channel: its messages say who said them.\n const onChannel = live.messages.some((message) => message.author != null);\n\n // The builder stops on Esc from anywhere on the page, as v2's did; an agent's chat, from inside it.\n const stop = useRef(live.stop);\n useEffect(() => {\n stop.current = live.stop;\n });\n useEffect(() => {\n if (!builder || !pending) return undefined;\n const onKey = (event: globalThis.KeyboardEvent) => {\n if (event.key === \"Escape\" && !event.defaultPrevented) stop.current();\n };\n window.addEventListener(\"keydown\", onKey);\n return () => {\n window.removeEventListener(\"keydown\", onKey);\n };\n }, [builder, pending]);\n\n const looks: ChatPart[] = builder ? [\"sc-chat--builder\"] : [];\n if (look === \"console\") looks.push(\"sc-chat--console\");\n const stepsShown = steps === \"shown\";\n\n return (\n <div\n part=\"chat\"\n className={`sc ${classes(classNames, \"sc-chat\", ...looks)}`}\n onKeyDown={(event) => {\n if (!builder && !onChannel && event.key === \"Escape\" && live.pending) live.stop();\n }}\n // Files dropped anywhere on the chat go with the next message; a form's own drop zone\n // (`data-drop`) takes those dropped on it.\n onDragOver={(event) => {\n if (!attaching || !carriesFiles(event)) return;\n const zone = event.target instanceof Element && event.target.closest(\"[data-drop]\");\n setOver(!zone);\n if (zone) return;\n event.preventDefault();\n event.dataTransfer.dropEffect = \"copy\";\n }}\n onDragLeave={(event) => {\n const to = event.relatedTarget;\n if (!(to instanceof Node && event.currentTarget.contains(to))) setOver(false);\n }}\n onDrop={(event) => {\n setOver(false);\n if (event.defaultPrevented || !attaching || !carriesFiles(event)) return;\n event.preventDefault();\n uploads.add([...event.dataTransfer.files]);\n }}\n >\n {fresh ? (\n <div part=\"empty\" className={classes(classNames, \"sc-chat__empty\")}>\n <h2>{words.empty(name)}</h2>\n {words.intro(name) !== \"\" && <p>{words.intro(name)}</p>}\n {suggestions !== undefined && suggestions.length > 0 && (\n <ul>\n {suggestions.map((text) => (\n <li key={text}>\n <button\n type=\"button\"\n disabled={!live.open}\n onClick={() => {\n if (live.say(text)) following.current = true;\n }}\n part=\"suggestion\"\n className={classes(classNames, \"sc-chat__suggestion\")}\n >\n «{text}»\n </button>\n </li>\n ))}\n </ul>\n )}\n </div>\n ) : (\n <Log\n live={live}\n name={name}\n words={words}\n classNames={classNames}\n components={components}\n locale={locale}\n following={following}\n took={took}\n builder={builder}\n onChannel={onChannel}\n files={files}\n handovers={handovers ? live.handovers : undefined}\n who={client.who}\n steps={stepsShown}\n />\n )}\n {/* The browser the agent drives, over the composer while the conversation has one. */}\n <BrowserView live={live} name={name} messages={words.browser} classNames={classNames} />\n {live.pending && (\n <Status\n label={\n builder ? workingOn(live, words) : stepsShown ? words.thinking(name) : words.typing\n }\n stoppable={!onChannel}\n timed={stepsShown}\n words={words}\n classNames={classNames}\n />\n )}\n <Composer\n live={live}\n name={name}\n words={words}\n classNames={classNames}\n actions={actions}\n compose={compose}\n taken={taken}\n fresh={fresh}\n builder={builder}\n uploads={attachments ? uploads : undefined}\n files={files}\n dictate={dictate}\n write={write}\n onSent={() => {\n following.current = true;\n }}\n />\n {over && (\n <div aria-hidden className={classes(classNames, \"sc-chat__drop\")}>\n <UploadSimpleIcon weight=\"bold\" />\n {words.drop}\n </div>\n )}\n </div>\n );\n}\n\n/**\n * What the builder is doing right now, v2's way: the step running in this turn, by its name (the\n * first one not settled: the actions of a reply run in its order); its words, while they come; or\n * that it is working.\n */\nexport function workingOn(\n live: Pick<LiveConversation, \"messages\" | \"draft\">,\n words: Pick<ChatMessages, \"steps\" | \"working\" | \"writing\">,\n): string {\n const lastSaid = live.messages.findLastIndex((message) => message.role === \"user\");\n const running = live.messages\n .slice(lastSaid + 1)\n .flatMap((message) => message.steps)\n .find((step) => step.state === \"running\");\n if (running) return words.steps[running.action] ?? running.action;\n return live.draft === \"\" ? words.working : words.writing;\n}\n\ninterface PartProps {\n live: LiveConversation;\n name: string;\n words: ChatMessages;\n classNames: ClassNames;\n}\n\nconst NO_HANDOFFS: ReadonlySet<string> = new Set();\n\n/** Whether a message is the agent's own words: a reply, not what a person of the business wrote. */\nconst agentSaid = (message: Message | undefined): boolean =>\n message?.role === \"assistant\" && message.author !== \"operator\";\n\n/**\n * The replies a handoff line follows: in each turn where the agent handed the conversation to a\n * person (an `escalate` step done), its last reply, so the line closes what the agent said.\n */\nexport function handoffs(messages: readonly Message[]): ReadonlySet<string> {\n const after = new Set<string>();\n let handed = false;\n for (const [index, message] of messages.entries()) {\n handed ||= message.steps.some((step) => step.action === \"escalate\" && step.state === \"done\");\n if (handed && !agentSaid(messages[index + 1])) {\n after.add(message.id);\n handed = false;\n }\n }\n return after;\n}\n\n/** Who changed who answers, from a handover's `by`: anything but these three is an automation's name. */\nexport function handoverBy({ by, title }: Pick<Handover, \"by\" | \"title\">): HandoverBy {\n if (by === \"owner\" || by === \"agent\" || by === \"platform\") return { kind: by };\n return { kind: \"automation\", title: title ?? by };\n}\n\n/** A change of who answers, as its line says it: what changed and who changed it, then why. */\nexport function handoverLine(\n handover: Handover,\n name: string,\n words: Pick<ChatMessages, \"handover\">,\n): string {\n const line = words.handover(handover.holder, handoverBy(handover), name);\n const reason = handover.reason.trim();\n return reason === \"\" ? line : `${line}: ${reason}`;\n}\n\n/**\n * The line under a person's message the agent let pass this time, with why (the owner's words,\n * else the automation that decided); none for any other decision: an answer is the reply itself,\n * and a conversation held or ignored has its line where who answers changed.\n */\nexport function decisionLine(\n decision: Decision | null | undefined,\n words: Pick<ChatMessages, \"skipped\">,\n): string | null {\n if (decision?.kind !== \"skip\") return null;\n const why = decision.reason?.trim() || decision.title;\n return why ? `${words.skipped}: ${why}` : words.skipped;\n}\n\n/**\n * Where each change of who answers falls among the messages, by the index of the message it goes\n * before (`messages.length`: after them all): before the first message said after it, and the\n * agent's own after the last reply of its turn, so its line closes what the agent said.\n */\nexport function handoversAt(\n messages: readonly Message[],\n handovers: readonly Handover[],\n): ReadonlyMap<number, readonly Handover[]> {\n const at = new Map<number, Handover[]>();\n let next = 0;\n for (const [index, message] of messages.entries()) {\n const said = Date.parse(message.created_at);\n const before: Handover[] = [];\n let handover = handovers[next];\n while (\n handover !== undefined &&\n Date.parse(handover.at) < said &&\n !(handover.by === \"agent\" && agentSaid(message))\n ) {\n before.push(handover);\n next += 1;\n handover = handovers[next];\n }\n if (before.length > 0) at.set(index, before);\n }\n if (next < handovers.length) at.set(messages.length, handovers.slice(next));\n return at;\n}\n\n/** When a line across the log happened, as the locale writes it: the time today, else the day too. */\nexport function whenSaid(at: string, now: Date, code: string): string {\n const moment = new Date(at);\n const today = moment.toDateString() === now.toDateString();\n return new Intl.DateTimeFormat(code, {\n ...(today ? {} : { day: \"numeric\", month: \"short\" }),\n hour: \"numeric\",\n minute: \"2-digit\",\n }).format(moment);\n}\n\n/**\n * The messages, read down, and the reply on its way: who is thinking until its first words, then\n * the words as they come with the agent's mark at their end. Where who answers the conversation\n * changed (`handovers`, when the host draws them; else where the agent handed it to a person),\n * one quiet line across the log says so, and under a person's message the agent let pass, that\n * it did. Screen readers hear a reply once, when it is stored.\n */\nfunction Log({\n live,\n name,\n words,\n classNames,\n components,\n locale,\n following,\n took,\n builder,\n onChannel,\n files,\n handovers,\n who,\n steps,\n}: PartProps & {\n components: SurfaceComponents | undefined;\n locale: KitLocale | undefined;\n following: RefObject<boolean>;\n took: number | null;\n builder: boolean;\n onChannel: boolean;\n files: FileHost;\n handovers: readonly Handover[] | undefined;\n who: Speaker;\n /** Whether the agent's steps show, and how long its last reply took. */\n steps: boolean;\n}) {\n const scroller = useRef<HTMLDivElement>(null);\n const said = useRef<HTMLDivElement>(null);\n const { messages, pending, draft, awaiting } = live;\n // The reply as it streams, at a reading pace (`reveal.ts`); when it is stored as a message, the\n // message goes on from where the reveal was, so the words never jump to the end.\n const shown = useRef(0);\n // On a channel the reply being written shows as typing until it is stored; then it shows as\n // the person gets it (its own typing while its parts go).\n const last = messages.at(-1);\n const outgoing =\n last !== undefined &&\n last.role === \"assistant\" &&\n last.delivery != null &&\n last.delivery !== \"failed\";\n const drafted = useReveal(draft, 0, (count) => {\n shown.current = count;\n });\n const lastDraft = useRef(\"\");\n const carried = useRef<{ id: string; from: number } | null>(null);\n const latest = messages.at(-1);\n if (\n latest?.role === \"assistant\" &&\n lastDraft.current !== \"\" &&\n draft === \"\" &&\n carried.current?.id !== latest.id\n ) {\n carried.current = { id: latest.id, from: shown.current };\n }\n lastDraft.current = draft;\n useLayoutEffect(() => {\n const box = scroller.current;\n if (box && following.current) box.scrollTop = box.scrollHeight;\n }, [messages, pending, drafted, following]);\n // What grows by itself (a surface's picture landing, a step opened on its output) keeps the\n // foot in view too, while the person is at it; and so does less room for it (the browser\n // opening large under it).\n useEffect(() => {\n const box = scroller.current;\n const log = said.current;\n if (!box || !log || typeof ResizeObserver === \"undefined\") return undefined;\n const observer = new ResizeObserver(() => {\n if (following.current) box.scrollTop = box.scrollHeight;\n });\n observer.observe(log);\n observer.observe(box);\n return () => {\n observer.disconnect();\n };\n }, [following]);\n\n // A surface takes input while the turn waits on it or, once nothing runs or waits, when the\n // agent showed it since the person last spoke; older ones are read, not used. On a channel the\n // person answered it there: here it only reads.\n const idle = !onChannel && !pending && awaiting === null;\n const lastSaid = messages.findLastIndex((message) => message.role === \"user\");\n // What the person did on each surface, by the surface's id: a surface draws its answer.\n const answers = new Map<string, Action>();\n for (const message of messages) {\n if (message.action) answers.set(message.action.surface, message.action);\n }\n // Drawn, who answers says where the agent handed it over; otherwise its `escalate` step does.\n const handed = handovers === undefined ? handoffs(messages) : NO_HANDOFFS;\n const placed = handoversAt(messages, handovers ?? []);\n const lines = (index: number) =>\n placed\n .get(index)\n ?.map((handover) => (\n <HandoverLine\n key={`${handover.at} ${handover.holder}`}\n handover={handover}\n name={name}\n words={words}\n classNames={classNames}\n code={locale?.code ?? \"en-US\"}\n />\n ));\n\n return (\n <div\n ref={scroller}\n onScroll={(event) => {\n const box = event.currentTarget;\n following.current = box.scrollHeight - box.scrollTop - box.clientHeight < NEAR_FOOT;\n }}\n part=\"transcript\"\n className={classes(\n classNames,\n \"sc-chat__log\",\n ...(onChannel ? ([\"sc-chat__log--channel\"] as const) : []),\n )}\n >\n <div ref={said} role=\"log\" aria-label={words.log}>\n {messages.map((message, index) => (\n <Fragment key={message.id}>\n {lines(index)}\n {message.role === \"user\" ? (\n <>\n <Heard\n message={message}\n after={messages[index - 1]}\n words={words}\n classNames={classNames}\n />\n <Said message={message} words={words} classNames={classNames} files={files} />\n {handovers !== undefined && (\n <Decided decision={message.decision} words={words} classNames={classNames} />\n )}\n </>\n ) : message.author === \"operator\" ? (\n <Business message={message} words={words} classNames={classNames} files={files} />\n ) : (\n <>\n <Reply\n message={message}\n from={carried.current?.id === message.id ? carried.current.from : undefined}\n awaiting={onChannel ? null : awaiting}\n current={idle && index > lastSaid}\n answers={answers}\n name={name}\n words={words}\n classNames={classNames}\n components={components}\n locale={locale}\n onAction={live.act}\n builder={builder}\n files={files}\n who={who}\n steps={steps}\n onChannel={onChannel}\n />\n {handed.has(message.id) && (\n <p className={classes(classNames, \"sc-chat__handoff\")}>\n {actionMark(\"escalate\", \"library\")}\n <span>{words.handedOff}</span>\n </p>\n )}\n </>\n )}\n </Fragment>\n ))}\n {lines(messages.length)}\n </div>\n {steps && !pending && took !== null && (\n <p className={classes(classNames, \"sc-chat__done\")}>{words.done(took)}</p>\n )}\n {pending && onChannel && !outgoing && <Typing label={words.typing} classNames={classNames} />}\n {pending && !onChannel && drafted !== \"\" && (\n <div\n aria-hidden\n part=\"message message-agent\"\n className={classes(classNames, \"sc-chat__text\", \"sc-chat__reply\")}\n >\n <Markdown text={drafted} />\n </div>\n )}\n </div>\n );\n}\n\n/** The channel's \"typing\": three dots in the business's bubble, while a reply or its parts come. */\nfunction Typing({ label, classNames }: { label: string; classNames: ClassNames }) {\n return (\n <p role=\"status\" aria-label={label} className={classes(classNames, \"sc-chat__typing\")}>\n <span />\n <span />\n <span />\n </p>\n );\n}\n\n/** How many of the last words heard a cut line quotes. */\nconst HEARD_WORDS = 8;\n\n/** The last words of what was heard, with an ellipsis before them when there was more. */\nexport function heardTail(heard: string, count = HEARD_WORDS): string {\n const words = heard.trim().split(/\\s+/).filter(Boolean);\n if (words.length <= count) return words.join(\" \");\n return `…${words.slice(-count).join(\" \")}`;\n}\n\n/**\n * On a call, what the person heard of the agent's last words before this message, when it wasn't\n * what was stored. After a reply (the greeting is the first), they cut it short: a quiet line\n * under it quotes the last of what they heard. With no reply before, it was a greeting from before\n * the API kept it: drawn here as the agent's words, where it was said.\n */\nfunction Heard({\n message,\n after,\n words,\n classNames,\n}: {\n message: Message;\n after: Message | undefined;\n words: ChatMessages;\n classNames: ClassNames;\n}) {\n const { heard } = message;\n if (heard == null) return null;\n if (after?.role === \"assistant\") {\n return <p className={classes(classNames, \"sc-chat__cut\")}>{words.cut(heardTail(heard))}</p>;\n }\n if (heard.trim() === \"\") return null;\n return (\n <div\n part=\"message message-agent\"\n className={classes(\n classNames,\n \"sc-chat__message\",\n \"sc-chat__message--agent\",\n \"sc-chat__message--heard\",\n )}\n >\n <div className={classes(classNames, \"sc-chat__text\")}>\n <p>{heard}</p>\n </div>\n </div>\n );\n}\n\n/**\n * The person's message: their words in a bubble (a voice note's player with its words under it);\n * the files they sent with it as chips over it, each opening where the host shows files. An\n * answer on a surface is its words alone: the surface shows its files.\n */\nfunction Said({\n message,\n words,\n classNames,\n files,\n}: {\n message: Message;\n words: ChatMessages;\n classNames: ClassNames;\n files: FileHost;\n}) {\n const sent = message.action ? [] : (message.files ?? []);\n const bubble = message.voice ? (\n <VoiceNote\n file={message.voice}\n text={message.text}\n parts=\"message message-person\"\n kind=\"sc-chat__message--person\"\n words={words}\n classNames={classNames}\n files={files}\n />\n ) : (\n message.text !== \"\" && (\n <p\n part=\"message message-person\"\n className={classes(\n classNames,\n \"sc-chat__message\",\n \"sc-chat__message--person\",\n ...(message.action ? ([\"sc-chat__message--action\"] as const) : []),\n )}\n >\n {message.text}\n </p>\n )\n );\n if (sent.length === 0) return bubble;\n return (\n <div part=\"files\" className={classes(classNames, \"sc-chat__said\")}>\n <FileChips files={sent} onOpen={files.open} />\n {bubble}\n </div>\n );\n}\n\n/**\n * A voice note on a channel, either way: a bubble with the page's own player, streaming from where\n * the file plays (asked again, once, when that ran out), and what was said under it.\n */\nfunction VoiceNote({\n file,\n text,\n parts,\n kind,\n words,\n classNames,\n files,\n}: {\n file: Attachment;\n text: string;\n /** The bubble's parts, a host's to style. */\n parts: string;\n kind: \"sc-chat__message--person\" | \"sc-chat__text\";\n words: ChatMessages;\n classNames: ClassNames;\n files: FileHost;\n}) {\n const played = usePlayed(file, files.play);\n const lost = useRef(false);\n return (\n <div\n part={parts}\n className={classes(\n classNames,\n ...(kind === \"sc-chat__text\" ? [] : ([\"sc-chat__message\"] as const)),\n kind,\n \"sc-chat__message--voice\",\n )}\n >\n <AudioPlayer\n src={played?.url}\n label={words.voiceNote}\n onError={() => {\n if (lost.current || played === null) return;\n lost.current = true;\n played.again();\n }}\n />\n {text !== \"\" && (\n <div className={classes(classNames, \"sc-chat__transcript\")}>\n <Markdown text={text} />\n </div>\n )}\n </div>\n );\n}\n\n/** Under a person's message the agent let pass this time: that it didn't answer it, and why. */\nfunction Decided({\n decision,\n words,\n classNames,\n}: {\n decision: Decision | null | undefined;\n words: ChatMessages;\n classNames: ClassNames;\n}) {\n const line = decisionLine(decision, words);\n if (line === null) return null;\n return <p className={classes(classNames, \"sc-chat__decision\")}>{line}</p>;\n}\n\n/**\n * Where who answers the conversation changed: a quiet line across the log, what changed and who\n * changed it, why, and when.\n */\nfunction HandoverLine({\n handover,\n name,\n words,\n classNames,\n code,\n}: {\n handover: Handover;\n name: string;\n words: ChatMessages;\n classNames: ClassNames;\n /** The locale's, for when. */\n code: string;\n}) {\n return (\n <p className={classes(classNames, \"sc-chat__handover\")}>\n <span>\n {handoverLine(handover, name, words)}\n <time dateTime={handover.at}>{whenSaid(handover.at, new Date(), code)}</time>\n </span>\n </p>\n );\n}\n\n/**\n * What a person of the business wrote on the channel, on the business's side but set apart from\n * the agent's words: a bubble of its own, the files it carried over it, and under it who wrote it\n * and where it got to.\n */\nfunction Business({\n message,\n words,\n classNames,\n files,\n}: {\n message: Message;\n words: ChatMessages;\n classNames: ClassNames;\n files: FileHost;\n}) {\n const sent = message.files ?? [];\n return (\n <div className={classes(classNames, \"sc-chat__business\")}>\n {sent.length > 0 && <FileChips files={sent} onOpen={files.open} />}\n {message.text !== \"\" && (\n <p\n part=\"message message-business\"\n className={classes(classNames, \"sc-chat__message\", \"sc-chat__message--business\")}\n >\n {message.text}\n </p>\n )}\n <p className={classes(classNames, \"sc-chat__meta\")}>\n <span>{words.business}</span>\n <DeliveryMark message={message} words={words} classNames={classNames} />\n </p>\n </div>\n );\n}\n\nconst DELIVERY_MARKS: Readonly<Record<Delivery, ReactNode>> = {\n queued: <ClockIcon aria-hidden />,\n sent: <CheckIcon aria-hidden weight=\"bold\" />,\n delivered: <ChecksIcon aria-hidden weight=\"bold\" />,\n read: <ChecksIcon aria-hidden weight=\"bold\" />,\n failed: <WarningCircleIcon aria-hidden weight=\"fill\" />,\n};\n\n/**\n * Where a message that went out on a channel got to, quietly: a clock while it waits to go, a\n * check once sent, two once delivered, two in the accent once read; one that never got there in\n * the danger tone, with why. Nothing for a message that didn't go out.\n */\nfunction DeliveryMark({\n message,\n words,\n classNames,\n}: {\n message: Message;\n words: ChatMessages;\n classNames: ClassNames;\n}) {\n const { delivery } = message;\n if (delivery == null) return null;\n const failed = delivery === \"failed\";\n return (\n <span\n role={failed ? undefined : \"img\"}\n aria-label={failed ? undefined : words.delivery[delivery]}\n title={failed ? undefined : words.delivery[delivery]}\n data-delivery={delivery}\n className={classes(classNames, \"sc-chat__delivery\")}\n >\n {DELIVERY_MARKS[delivery]}\n {failed && <span>{words.undelivered(message.delivery_error ?? null)}</span>}\n </span>\n );\n}\n\ninterface DrawProps {\n words: ChatMessages;\n classNames: ClassNames;\n components: SurfaceComponents | undefined;\n locale: KitLocale | undefined;\n onAction: (action: Action) => void;\n}\n\n/**\n * The agent's message: its words, then the steps it took as a compact list (a mark for the\n * state, the action's name, its output), then what each step drew (with what the person did on\n * it, from `answers`), and the card for one that waits to be allowed by whoever this page speaks\n * for (on a person's page, one the business allows is a quiet line instead); on a channel, where\n * it got to.\n */\nfunction Reply({\n message,\n from,\n awaiting,\n current,\n answers,\n name,\n words,\n classNames,\n components,\n locale,\n onAction,\n builder,\n files,\n who,\n steps,\n onChannel,\n}: DrawProps & {\n message: Message;\n /** It was streaming: its words go on revealing from here. None: they show whole. */\n from: number | undefined;\n awaiting: string | null;\n current: boolean;\n answers: ReadonlyMap<string, Action>;\n name: string;\n builder: boolean;\n files: FileHost;\n who: Speaker;\n /** Whether the steps it took show, as a list under its words. */\n steps: boolean;\n /** On a channel: its words as the person got them, a bubble for each part, and who sent them. */\n onChannel: boolean;\n}) {\n const text = useReveal(message.text, from ?? message.text.length);\n // On a channel, what the person there has got so far; elsewhere, the words as they come.\n const { shown: said, typing } = onChannel\n ? channelParts(message, text)\n : { shown: [text], typing: false };\n return (\n <div\n part=\"message message-agent\"\n className={classes(classNames, \"sc-chat__message\", \"sc-chat__message--agent\")}\n >\n {/* A voice note shows once it went, as each part does. */}\n {message.voice && said.length > 0 ? (\n <VoiceNote\n file={message.voice}\n text={text}\n parts=\"text\"\n kind=\"sc-chat__text\"\n words={words}\n classNames={classNames}\n files={files}\n />\n ) : (\n text !== \"\" &&\n said.map((words, index) => (\n <div key={index} part=\"text\" className={classes(classNames, \"sc-chat__text\")}>\n <Markdown text={words} />\n </div>\n ))\n )}\n {typing && <Typing label={words.typing} classNames={classNames} />}\n {steps && message.steps.length > 0 && (\n <ol className={classes(classNames, \"sc-chat__steps\")}>\n {message.steps.map((step, index) => (\n <li\n key={step.id}\n className={classes(\n classNames,\n \"sc-chat__step\",\n `sc-chat__step--${shownState(step, message.steps.slice(0, index))}`,\n )}\n >\n {builder ? (\n <BuilderStep step={step} words={words} classNames={classNames} />\n ) : (\n <>\n <Mark\n state={step.state}\n action={step.action}\n app={step.app ?? null}\n classNames={classNames}\n />\n <span>{words.steps[step.action] ?? actionWords(step.action)}</span>\n {/* What a step answered is the model's, in its words: only why it failed. */}\n {step.state === \"failed\" && step.output !== null && <small>{step.output}</small>}\n </>\n )}\n </li>\n ))}\n </ol>\n )}\n {message.steps.map(\n (step) =>\n step.surface && (\n <div\n key={step.id}\n part=\"surface\"\n className={classes(\n classNames,\n \"sc-chat__screen\",\n ...(framesItself(step.surface) ? ([\"sc-chat__screen--bare\"] as const) : []),\n )}\n >\n <Surface\n surface={step.surface}\n active={step.id === awaiting || current}\n answered={answers.get(step.id)}\n components={components}\n classNames={classNames}\n messages={words.kit}\n locale={locale}\n files={files}\n onAction={(action) => onAction({ surface: step.id, ...action })}\n />\n </div>\n ),\n )}\n {message.steps.map((step) => {\n const { request } = step;\n if (request === null) return null;\n if (request.decides === \"business\" && who === \"person\") {\n return (\n <p\n key={step.id}\n part=\"confirming\"\n className={classes(classNames, \"sc-chat__confirming\")}\n >\n <ClockIcon aria-hidden />\n <span>{words.confirming}</span>\n </p>\n );\n }\n return (\n <Approval\n key={step.id}\n request={request}\n name={name}\n words={words}\n classNames={classNames}\n components={components}\n locale={locale}\n onAction={(action) => onAction({ surface: step.id, ...action })}\n />\n );\n })}\n {message.delivery != null && (\n <p className={classes(classNames, \"sc-chat__meta\")}>\n {onChannel && <span>{name}</span>}\n <DeliveryMark message={message} words={words} classNames={classNames} />\n </p>\n )}\n </div>\n );\n}\n\n/**\n * A step's state as its list shows it, after the steps `before` it in its reply: the actions of\n * one reply run one after another, in its order, so one still `running` after another that runs\n * is only to come (`queued`).\n */\nexport function shownState(step: Step, before: readonly Step[]): StepState | \"queued\" {\n const behind = before.some((earlier) => earlier.state === \"running\");\n return step.state === \"running\" && behind ? \"queued\" : step.state;\n}\n\n/**\n * A step in the builder's look, v2's: its mark and its name, \"failed\" beside it when it did, and\n * what it returned folded under a caret that shows on hover, opened on a click.\n */\nfunction BuilderStep({\n step,\n words,\n classNames,\n}: {\n step: Step;\n words: ChatMessages;\n classNames: ClassNames;\n}) {\n const row = (\n <>\n <Mark\n state={step.state}\n action={step.action}\n app={step.app ?? null}\n classNames={classNames}\n />\n <span>{words.steps[step.action] ?? actionWords(step.action)}</span>\n {step.state === \"failed\" && <em>{words.failed}</em>}\n </>\n );\n if (!step.output) return row;\n return (\n <details>\n <summary>\n {row}\n <CaretRightIcon aria-hidden />\n </summary>\n <pre className={classes(classNames, \"sc-chat__output\")}>{step.output}</pre>\n </details>\n );\n}\n\n/**\n * A step's mark on the list's line: the kind of work it is (its glyph) once it is done, a turning\n * ring while it runs, a ring while it waits for the person, a warning when it failed.\n */\nfunction Mark({\n state,\n action,\n app,\n classNames,\n}: {\n state: StepState;\n action: string;\n app: StepApp | null;\n classNames: ClassNames;\n}) {\n const Glyph = stepGlyph(action);\n // A connected app's step wears the app's logo once done; only an https one is loaded.\n const logo = app?.icon && /^https:\\/\\//i.test(app.icon) ? app.icon : null;\n return (\n <span aria-hidden className={classes(classNames, \"sc-chat__mark\")}>\n {state === \"done\" && logo !== null ? (\n <img src={logo} alt=\"\" loading=\"lazy\" draggable={false} />\n ) : state === \"done\" ? (\n <Glyph />\n ) : state === \"running\" ? null : (\n <svg viewBox=\"0 0 14 14\" fill=\"none\">\n {MARKS[state]}\n </svg>\n )}\n </span>\n );\n}\n\nconst STROKE = { stroke: \"currentColor\", strokeWidth: 1.5, strokeLinecap: \"round\" } as const;\nconst MARKS: Record<\"waiting\" | \"failed\", ReactNode> = {\n waiting: <circle cx=\"7\" cy=\"7\" r=\"4.75\" {...STROKE} />,\n failed: (\n <>\n <path d=\"M7 1.9l5.6 9.7H1.4L7 1.9z\" {...STROKE} strokeLinejoin=\"round\" />\n <path d=\"M7 5.6v2.6\" {...STROKE} />\n <circle cx=\"7\" cy=\"10\" r=\"0.8\" fill=\"currentColor\" />\n </>\n ),\n};\n\n/** How long the last reply took, in whole seconds, once it is in; none before the first. */\nfunction useTook(pending: boolean): number | null {\n const [took, setTook] = useState<number | null>(null);\n const started = useRef<number | null>(null);\n useEffect(() => {\n if (pending) {\n started.current = Date.now();\n setTook(null);\n } else if (started.current !== null) {\n setTook(Math.max(1, Math.round((Date.now() - started.current) / 1000)));\n started.current = null;\n }\n }, [pending]);\n return took;\n}\n\n/**\n * What is happening while a reply is on its way, in one quiet line over the composer: a dot that\n * breathes, what goes on (`label`) under a sweeping light, the seconds it has taken, and how to\n * stop it. A new label rises in where the last was.\n */\nfunction Status({\n label,\n stoppable,\n timed,\n words,\n classNames,\n}: {\n label: string;\n /** Whether the reply can be stopped from here: not on a channel, where it runs on its own. */\n stoppable: boolean;\n /** Whether it says the seconds so far and the key that stops it: not where steps are hidden. */\n timed: boolean;\n words: ChatMessages;\n classNames: ClassNames;\n}) {\n const [seconds, setSeconds] = useState(0);\n useEffect(() => {\n const started = Date.now();\n const tick = setInterval(() => {\n setSeconds(Math.floor((Date.now() - started) / 1000));\n }, 1000);\n return () => {\n clearInterval(tick);\n };\n }, []);\n return (\n <p role=\"status\" part=\"status\" className={classes(classNames, \"sc-chat__status\")}>\n <i aria-hidden />\n <span key={label}>{label}…</span>\n {timed && <small>{words.elapsed(seconds)}</small>}\n {timed && stoppable && <kbd>{words.escape}</kbd>}\n </p>\n );\n}\n\n/**\n * An action the platform holds until the person allows it, as v2's card: a head that says it\n * needs their approval, then the sentence, what the action would take, and the two answers,\n * drawn as a surface so the host's blocks and words apply. Drawn from the step, so it is there\n * live and read back alike.\n */\nfunction Approval({\n request,\n name,\n words,\n classNames,\n components,\n locale,\n onAction,\n}: Omit<DrawProps, \"onAction\"> & {\n request: Request;\n name: string;\n onAction: (action: SurfaceAction) => void;\n}) {\n const sentence = words.request(name, request.action);\n const surface: Shown = {\n blocks: [\n {\n type: \"fields\",\n items: Object.entries(request.input).map(([field, value]) => ({\n label: words.inputs[field] ?? field,\n value: typeof value === \"string\" ? value : JSON.stringify(value),\n })),\n },\n {\n type: \"stack\",\n direction: \"row\",\n children: [\n { type: \"button\", label: words.allow, action: \"approve\", tone: \"primary\" },\n { type: \"button\", label: words.decline, action: \"decline\", tone: \"neutral\" },\n ],\n },\n ],\n text: sentence,\n };\n return (\n <div part=\"approval\" className={classes(classNames, \"sc-chat__request\")}>\n <header>\n <ShieldWarningIcon aria-hidden />\n {words.approval}\n </header>\n <div>\n <p>{sentence}</p>\n <Surface\n surface={surface}\n components={components}\n classNames={classNames}\n messages={words.kit}\n locale={locale}\n onAction={onAction}\n />\n </div>\n </div>\n );\n}\n\n/**\n * Where the person writes: a box that grows a few lines with the text. Enter sends, Shift+Enter\n * breaks the line; nothing goes while a reply is on its way or the socket is closed, but the\n * person can keep writing. While the turn waits for them to act above, the box is closed and\n * says so; while a reply is on its way, the send button is a stop button (Esc stops too). The\n * host's `compose` is said from here, or put in the box. With `uploads`, the paperclip attaches\n * files (a picture pasted too): they upload at once, as chips over the words, and go with them\n * (or alone) once every one is in. With `write`, what is written goes to the host instead (a\n * person of the business, on a channel): whatever the turn is doing, emptied once it went.\n */\nfunction Composer({\n live,\n name,\n words,\n classNames,\n actions,\n compose,\n taken,\n fresh,\n builder,\n uploads,\n files,\n dictate,\n write,\n onSent,\n}: PartProps & {\n actions: ReactNode;\n compose: ChatCompose | undefined;\n taken: RefObject<number | null>;\n fresh: boolean;\n builder: boolean;\n uploads: Uploads | undefined;\n files: FileHost;\n dictate: Dictate | undefined;\n write: ((text: string, files: readonly string[]) => Promise<unknown>) | undefined;\n onSent: () => void;\n}) {\n const [text, setText] = useState(\"\");\n // What is written on its way to the host's `write`: nothing more goes until it went.\n const [writing, setWriting] = useState(false);\n const input = useRef<HTMLTextAreaElement>(null);\n const picker = useRef<HTMLInputElement>(null);\n // Counts the host's texts put in the box: each one focuses it, the caret at the text's end.\n const [placed, setPlaced] = useState(0);\n // Waiting for the person to act above holds the composer, unless the words go to the host.\n const held = write === undefined && live.awaiting !== null;\n // What is dictated joins what is written, after it, and the caret goes to its end.\n const dictation = useDictation(dictate, (words) => {\n setText((now) => (now.trim() === \"\" ? words : `${now.trimEnd()} ${words}`));\n setPlaced((count) => count + 1);\n });\n const listening = dictation.state === \"listening\";\n\n // The host's request, once: said when it asks so (waiting for the socket to open), put in the\n // box otherwise, or when it cannot go now (a reply on its way, a turn waiting).\n useEffect(() => {\n if (compose === undefined || taken.current === compose.key) return;\n if (compose.send && !live.open) return;\n taken.current = compose.key;\n if (compose.send && live.say(compose.text)) {\n onSent();\n return;\n }\n setText(compose.text);\n setPlaced((count) => count + 1);\n }, [compose, taken, live, onSent]);\n\n useLayoutEffect(() => {\n const box = input.current;\n if (placed === 0 || box === null) return;\n box.focus();\n box.setSelectionRange(box.value.length, box.value.length);\n }, [placed]);\n\n const attached = uploads?.ids ?? [];\n const settled = uploads === undefined || uploads.waiting === null;\n const said = text.trim() !== \"\" || attached.length > 0;\n const sent = () => {\n setText(\"\");\n uploads?.clear();\n onSent();\n };\n const submit = () => {\n if (!settled) return;\n if (write === undefined) {\n if (live.say(text, attached)) sent();\n return;\n }\n if (writing || !said) return;\n setWriting(true);\n write(text.trim(), attached)\n .then(sent, () => undefined)\n .finally(() => {\n setWriting(false);\n });\n };\n const onKeyDown = (event: KeyboardEvent<HTMLTextAreaElement>) => {\n if (event.key !== \"Enter\" || event.shiftKey || event.nativeEvent.isComposing) return;\n event.preventDefault();\n submit();\n };\n const ready =\n write === undefined\n ? live.open && !live.pending && !held && settled && said\n : !writing && settled && said;\n const invitation = write === undefined ? words.placeholder(name, fresh) : words.write;\n\n return (\n <form\n onSubmit={(event) => {\n event.preventDefault();\n submit();\n }}\n part=\"composer\"\n className={classes(classNames, \"sc-chat__composer\")}\n >\n {uploads && uploads.items.length > 0 && (\n <div part=\"files\" className={classes(classNames, \"sc-chat__files\")}>\n <UploadChips uploads={uploads} host={files} />\n </div>\n )}\n <textarea\n ref={input}\n rows={1}\n value={text}\n maxLength={20_000}\n disabled={held}\n // The builder takes the keyboard as it opens, as v2's did: it is there to be told things.\n autoFocus={builder}\n aria-label={invitation}\n placeholder={\n held ? words.awaiting : live.open || write !== undefined ? invitation : words.connecting\n }\n onChange={(event) => {\n setText(event.target.value);\n }}\n onKeyDown={onKeyDown}\n part=\"input\"\n // A picture pasted (a screenshot, an image copied) is attached; words pasted stay words.\n onPaste={(event) => {\n const pasted = [...event.clipboardData.files];\n if (!uploads || pasted.length === 0) return;\n if (event.clipboardData.getData(\"text/plain\") !== \"\") return;\n event.preventDefault();\n uploads.add(pasted);\n }}\n className={classes(classNames, \"sc-chat__input\")}\n />\n {uploads && (\n <>\n <button\n type=\"button\"\n aria-label={words.attach}\n title={words.attach}\n disabled={held}\n onClick={() => picker.current?.click()}\n part=\"attach\"\n className={classes(classNames, \"sc-chat__attach\")}\n >\n <PaperclipIcon aria-hidden />\n </button>\n <input\n ref={picker}\n type=\"file\"\n multiple\n hidden\n tabIndex={-1}\n onChange={(event) => {\n uploads.add([...(event.target.files ?? [])]);\n event.target.value = \"\";\n }}\n />\n </>\n )}\n <div part=\"actions\" className={classes(classNames, \"sc-chat__actions\")}>\n {dictation.available && (\n <button\n type=\"button\"\n aria-label={listening ? words.dictateStop : words.dictate}\n title={listening ? words.dictateStop : words.dictate}\n aria-pressed={listening}\n data-state={dictation.state}\n disabled={held || dictation.state === \"writing\"}\n onClick={dictation.toggle}\n part=\"dictate\"\n className={classes(classNames, \"sc-chat__dictate\")}\n >\n <MicrophoneIcon aria-hidden weight={listening ? \"fill\" : \"regular\"} />\n </button>\n )}\n {dictation.state !== \"idle\" && (\n <span\n role=\"status\"\n data-state={dictation.state}\n className={classes(classNames, \"sc-chat__dictation\")}\n >\n {words.dictation[dictation.state]}\n </span>\n )}\n {actions}\n </div>\n {live.pending && write === undefined ? (\n <button\n type=\"button\"\n aria-label={words.stop}\n title={`${words.stop} (Esc)`}\n onClick={() => live.stop()}\n part=\"stop\"\n className={classes(classNames, \"sc-chat__stop\")}\n >\n <StopIcon weight=\"fill\" aria-hidden />\n </button>\n ) : (\n <button\n type=\"submit\"\n aria-label={words.send}\n title={words.send}\n disabled={!ready}\n part=\"send\"\n className={classes(classNames, \"sc-chat__send\")}\n >\n <ArrowUpIcon weight=\"bold\" aria-hidden />\n </button>\n )}\n </form>\n );\n}\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { About, AboutOut, AboutState, ActionFact, AskFact, AutomationFact, Autom
3
3
  import { Automation as Automation$1, AutomationState, AutomationView, Board, Run, RunBy, RunRecord, RunStatus, RunStep, Step, Task, Trigger, Use } from "./automation/types.js";
4
4
  import { Credentials, Speaker, VISITOR_KEY } from "./credentials.js";
5
5
  import { AutomationBlock, Block, ButtonBlock, CardBlock, ChartBlock, ChartPoint, ChoiceBlock, DividerBlock, Entry, FieldKind, FieldValue, FieldsBlock, FormBlock, FormField, ImageBlock, ListBlock, NoteBlock, Option, StackBlock, StatBlock, Surface as Surface$1, TableBlock, TextBlock, Tone } from "./blocks.js";
6
- import { Action, AgentFace, Attachment, Author, BrowserControl, BrowserFrame, BrowserInput, BrowserState, BrowserWhere, CallGlance, CallReason, CallToken, Channel, ChannelGlance, ChannelSettings, ChannelStatus, ChannelWeb, ContactGlance, Conversation, ConversationDetail, ConversationFile, ConversationPerson, Decides, Decision, Delivery, FileAt, FileBlock, FileIndex, FilePreview, Handover, Holder, HoursSpan, Message, Request, Step as Step$1, StepState, StoredFile, ToolCall, WIDGET_FONTS, WeekHours, Weekday, WidgetConfig, WidgetFont, WidgetLook } from "./types.js";
6
+ import { Action, AgentFace, Attachment, Author, BrowserControl, BrowserFrame, BrowserInput, BrowserState, BrowserWhere, CallGlance, CallReason, CallToken, Channel, ChannelGlance, ChannelSettings, ChannelStatus, ChannelWeb, ContactGlance, Conversation, ConversationDetail, ConversationFile, ConversationPerson, Decides, Decision, Delivery, FileAt, FileBlock, FileIndex, FilePreview, Handover, Holder, HoursSpan, Message, Request, Step as Step$1, StepApp, StepState, StoredFile, ToolCall, WIDGET_FONTS, WeekHours, Weekday, WidgetConfig, WidgetFont, WidgetLook } from "./types.js";
7
7
  import { ApiError, Client, ClientOptions, Files, UploadOptions, createClient } from "./client.js";
8
8
  import { AUTOMATION_MESSAGES, AutomationMessages, CallMessages, DayRef, Verb } from "./automation/messages.js";
9
9
  import { KIT_MESSAGES, KitLocale, KitMessages } from "./kit/messages.js";
@@ -60,4 +60,4 @@ import { DateTimeField, DateTimeFieldProps, TimeField, TimeFieldProps } from "./
60
60
  import { Surface, SurfaceProps } from "./surface/Surface.js";
61
61
  import { FaceRead, useAgentFace } from "./useAgentFace.js";
62
62
  import { Live, LiveHandlers, useLive } from "./useLive.js";
63
- export { ABOUT_HOME, ABOUT_MESSAGES, AGENT_ICONS, AUTOMATION_MESSAGES, AUTOMATION_MESSAGES_ES, type About, type AboutControls, type AboutMessages, type AboutOut, type AboutPart, type AboutState, type AboutTools, type AboutView, type Action, type ActionFact, AgentAbout, type AgentAboutProps, type AgentActivity, AgentCard, type AgentCardProps, AgentChat, type AgentChatProps, type AgentFace, type AgentIcon, AgentSpace, type AgentSpaceProps, AgentTasks, type AgentTasksProps, type AgentTint, ApiError, type AppDirectory, type AskFact, type Attachment, AudioPlayer, type AudioPlayerProps, type Author, Automation, type AutomationBlock, type Automation$1 as AutomationData, type AutomationFact, type AutomationKind, type AutomationMessages, type AutomationProps, type AutomationState, type Step as AutomationStep, type AutomationView, BROWSER_MESSAGES, BROWSER_MESSAGES_ES, type Block, type BlockProps, type Board, type BrowserControl, type BrowserFrame, type BrowserInput, type BrowserMessages, type BrowserPart, type BrowserState, BrowserView, type BrowserViewProps, type BrowserWhere, Button, type ButtonBlock, type ButtonProps, CHAT_MESSAGES, CHAT_MESSAGES_ES, type Call, type CallEnd, type CallEndedBy, type CallGlance, type CallJoin, type CallLine, type CallLook, type CallMessages, type CallMeter, type CallProblem, type CallReason, type CallState, type CallToken, Card, type CardBlock, type CardField, type CardPart, type Channel, type ChannelFact, type ChannelGlance, type ChannelKind, type ChannelSettings, type ChannelStatus, type ChannelWeb, type ChartBlock, type ChartPoint, type ChatCompose, type ChatLook, type ChatMessages, type ChatPart, type ChatSteps, Checkbox, Chips, type ChoiceBlock, Choices, type Client, type ClientOptions, Combobox, type ComboboxProps, type ConnectionFact, type ContactGlance, type ControlBase, type Conversation, type ConversationDetail, type ConversationFile, type ConversationPerson, type Credentials, type Cron, type DataFact, DateField, type DateFieldProps, DateTimeField, type DateTimeFieldProps, type DayRef, type Decides, type Decision, type Delivery, type DeviceFact, type DeviceKind, type Dictate, type Dictation, type DividerBlock, type Does, type Entry, FILES_PER_MESSAGE, FILE_MESSAGES, type FaceRead, type Facts, Field, type FieldIds, type FieldKind, type FieldValue, type FieldsBlock, type FileAt, type FileBlock, FileChip, type FileChipProps, FileChips, type FileFact, type FileFamily, FileField, type FileFieldProps, type FileHost, type FileIndex, FileMark, type FileMessages, type FilePart, type FilePreview, FileView, type FileViewProps, type Files, type FormBlock, type FormField, type Frame, type Handover, type HandoverBy, type Holder, type HoursSpan, ICONS, type Icon, type ImageBlock, KIT_MESSAGES, KIT_MESSAGES_ES, type KitClassNames, type KitLocale, type KitMessages, type KitPart, KitProvider, List, type ListBlock, type Live, type LiveConversation, type LiveHandlers, MAX_MB, Mark, type MarkProps, MarkStack, type MemoryFact, type Message, type ModeMessages, type ModePart, NO_TOOL, type Names, Note, type NoteBlock, NumberInput, ORB_STYLES, type Option, Orb, type OrbProps, type OrbState, type OrbStyle, type Preview, type Provider, RangeField, RatingField, type Request, Row, type RowProps, type Run, type RunBy, type RunRecord, type RunStatus, type RunStep, RunView, type RunViewProps, SPACE_MESSAGES, SPACE_MESSAGES_ES, SecretInput, type SpaceLayout, type SpaceMessages, type SpaceMode, type SpacePart, type Speaker, type StackBlock, Stat, type StatBlock, Stats, type StatusTone, type Step$1 as Step, type StepGroup, type StepState, type StoredFile, Surface, type SurfaceAction, type SurfaceComponents, type Surface$1 as SurfaceData, type SurfacePart, type SurfaceProps, Switch, type SwitchProps, TASKS_POLL_MS, TASK_MESSAGES, TASK_MESSAGES_ES, TOOL_ERROR_MAX, TOPICS, type TableBlock, Tag, type Task, type TaskMessages, type TaskPart, TextArea, type TextBlock, TextInput, Tile, type TileProps, Tiles, TimeField, type TimeFieldProps, type Told, type Tone, type ToolCall, type ToolHandler, type ToolResult, type Topic, type Trigger, type UpFrame, type Upload, UploadChips, type UploadOptions, type UploadRules, type Uploader, type Uploads, type Use, VISITOR_KEY, VOICE_CALL_MESSAGES, VOICE_CALL_MESSAGES_ES, type Values, type VaultFact, type Verb, VoiceCall, type VoiceCallMessages, type VoiceCallPart, type VoiceCallProps, WIDGET_FONTS, type Wall, type WeekHours, type Weekday, type When, type WidgetConfig, type WidgetFont, type WidgetLook, aboutBack, aboutState, accepts, actionWords, agentGlyph, agentTint, appOf, appSteps, appTitle, automationsOf, callWords, captionsOf, chosen, cleanDocument, clockOf, countOf, createClient, dayRefOf, durationOf, endedByReason, familyOf, filled, fires, formatSize, generatedName, groupsOf, labelOf, lineOf, lookOf, momentOf, namesOf, namingOf, occurrences, offsetOf, orbOf, parseCron, picked, pressed, previewOf, problemOf, scheduleOf, timeOf, toneOf, tookOf, toolName, toolResultOf, toolTitle, useAgentFace, useCall, useConversation, useDictation, useLive, useTasks, useUploads, verbOf, whenOf };
63
+ export { ABOUT_HOME, ABOUT_MESSAGES, AGENT_ICONS, AUTOMATION_MESSAGES, AUTOMATION_MESSAGES_ES, type About, type AboutControls, type AboutMessages, type AboutOut, type AboutPart, type AboutState, type AboutTools, type AboutView, type Action, type ActionFact, AgentAbout, type AgentAboutProps, type AgentActivity, AgentCard, type AgentCardProps, AgentChat, type AgentChatProps, type AgentFace, type AgentIcon, AgentSpace, type AgentSpaceProps, AgentTasks, type AgentTasksProps, type AgentTint, ApiError, type AppDirectory, type AskFact, type Attachment, AudioPlayer, type AudioPlayerProps, type Author, Automation, type AutomationBlock, type Automation$1 as AutomationData, type AutomationFact, type AutomationKind, type AutomationMessages, type AutomationProps, type AutomationState, type Step as AutomationStep, type AutomationView, BROWSER_MESSAGES, BROWSER_MESSAGES_ES, type Block, type BlockProps, type Board, type BrowserControl, type BrowserFrame, type BrowserInput, type BrowserMessages, type BrowserPart, type BrowserState, BrowserView, type BrowserViewProps, type BrowserWhere, Button, type ButtonBlock, type ButtonProps, CHAT_MESSAGES, CHAT_MESSAGES_ES, type Call, type CallEnd, type CallEndedBy, type CallGlance, type CallJoin, type CallLine, type CallLook, type CallMessages, type CallMeter, type CallProblem, type CallReason, type CallState, type CallToken, Card, type CardBlock, type CardField, type CardPart, type Channel, type ChannelFact, type ChannelGlance, type ChannelKind, type ChannelSettings, type ChannelStatus, type ChannelWeb, type ChartBlock, type ChartPoint, type ChatCompose, type ChatLook, type ChatMessages, type ChatPart, type ChatSteps, Checkbox, Chips, type ChoiceBlock, Choices, type Client, type ClientOptions, Combobox, type ComboboxProps, type ConnectionFact, type ContactGlance, type ControlBase, type Conversation, type ConversationDetail, type ConversationFile, type ConversationPerson, type Credentials, type Cron, type DataFact, DateField, type DateFieldProps, DateTimeField, type DateTimeFieldProps, type DayRef, type Decides, type Decision, type Delivery, type DeviceFact, type DeviceKind, type Dictate, type Dictation, type DividerBlock, type Does, type Entry, FILES_PER_MESSAGE, FILE_MESSAGES, type FaceRead, type Facts, Field, type FieldIds, type FieldKind, type FieldValue, type FieldsBlock, type FileAt, type FileBlock, FileChip, type FileChipProps, FileChips, type FileFact, type FileFamily, FileField, type FileFieldProps, type FileHost, type FileIndex, FileMark, type FileMessages, type FilePart, type FilePreview, FileView, type FileViewProps, type Files, type FormBlock, type FormField, type Frame, type Handover, type HandoverBy, type Holder, type HoursSpan, ICONS, type Icon, type ImageBlock, KIT_MESSAGES, KIT_MESSAGES_ES, type KitClassNames, type KitLocale, type KitMessages, type KitPart, KitProvider, List, type ListBlock, type Live, type LiveConversation, type LiveHandlers, MAX_MB, Mark, type MarkProps, MarkStack, type MemoryFact, type Message, type ModeMessages, type ModePart, NO_TOOL, type Names, Note, type NoteBlock, NumberInput, ORB_STYLES, type Option, Orb, type OrbProps, type OrbState, type OrbStyle, type Preview, type Provider, RangeField, RatingField, type Request, Row, type RowProps, type Run, type RunBy, type RunRecord, type RunStatus, type RunStep, RunView, type RunViewProps, SPACE_MESSAGES, SPACE_MESSAGES_ES, SecretInput, type SpaceLayout, type SpaceMessages, type SpaceMode, type SpacePart, type Speaker, type StackBlock, Stat, type StatBlock, Stats, type StatusTone, type Step$1 as Step, type StepApp, type StepGroup, type StepState, type StoredFile, Surface, type SurfaceAction, type SurfaceComponents, type Surface$1 as SurfaceData, type SurfacePart, type SurfaceProps, Switch, type SwitchProps, TASKS_POLL_MS, TASK_MESSAGES, TASK_MESSAGES_ES, TOOL_ERROR_MAX, TOPICS, type TableBlock, Tag, type Task, type TaskMessages, type TaskPart, TextArea, type TextBlock, TextInput, Tile, type TileProps, Tiles, TimeField, type TimeFieldProps, type Told, type Tone, type ToolCall, type ToolHandler, type ToolResult, type Topic, type Trigger, type UpFrame, type Upload, UploadChips, type UploadOptions, type UploadRules, type Uploader, type Uploads, type Use, VISITOR_KEY, VOICE_CALL_MESSAGES, VOICE_CALL_MESSAGES_ES, type Values, type VaultFact, type Verb, VoiceCall, type VoiceCallMessages, type VoiceCallPart, type VoiceCallProps, WIDGET_FONTS, type Wall, type WeekHours, type Weekday, type When, type WidgetConfig, type WidgetFont, type WidgetLook, aboutBack, aboutState, accepts, actionWords, agentGlyph, agentTint, appOf, appSteps, appTitle, automationsOf, callWords, captionsOf, chosen, cleanDocument, clockOf, countOf, createClient, dayRefOf, durationOf, endedByReason, familyOf, filled, fires, formatSize, generatedName, groupsOf, labelOf, lineOf, lookOf, momentOf, namesOf, namingOf, occurrences, offsetOf, orbOf, parseCron, picked, pressed, previewOf, problemOf, scheduleOf, timeOf, toneOf, tookOf, toolName, toolResultOf, toolTitle, useAgentFace, useCall, useConversation, useDictation, useLive, useTasks, useUploads, verbOf, whenOf };
package/dist/types.d.ts CHANGED
@@ -230,6 +230,13 @@ export interface Step {
230
230
  awaits: boolean;
231
231
  /** Set while it waits to be allowed: by the person (the turn stopped), or by the business. */
232
232
  request: Request | null;
233
+ /** A connected app's action: the app, its logo an https address; absent for the platform's. */
234
+ app?: StepApp | null | undefined;
235
+ }
236
+ /** The connected app a step's action belongs to: its name and logo. */
237
+ export interface StepApp {
238
+ name: string;
239
+ icon: string | null;
233
240
  }
234
241
  /**
235
242
  * What a person did on a surface: `surface` is its id, `name` the block's action, `data` what it