@signalcore/ui 1.0.0-beta.3 → 1.0.0-beta.4

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.
Files changed (71) hide show
  1. package/README.md +79 -0
  2. package/dist/AgentChat.d.ts +19 -3
  3. package/dist/AgentChat.js +149 -27
  4. package/dist/AgentChat.js.map +1 -1
  5. package/dist/AgentSpace.d.ts +14 -2
  6. package/dist/AgentSpace.js +3 -1
  7. package/dist/AgentSpace.js.map +1 -1
  8. package/dist/View.d.ts +48 -0
  9. package/dist/View.js +101 -0
  10. package/dist/View.js.map +1 -0
  11. package/dist/blocks.d.ts +83 -2
  12. package/dist/client.d.ts +9 -1
  13. package/dist/client.js +1 -0
  14. package/dist/client.js.map +1 -1
  15. package/dist/es.js +12 -0
  16. package/dist/es.js.map +1 -1
  17. package/dist/index.d.ts +11 -5
  18. package/dist/index.js +7 -1
  19. package/dist/kit/Agenda.d.ts +25 -0
  20. package/dist/kit/Agenda.js +119 -0
  21. package/dist/kit/Agenda.js.map +1 -0
  22. package/dist/kit/Combobox.js +1 -1
  23. package/dist/kit/DateField.js +1 -1
  24. package/dist/kit/Kanban.d.ts +17 -0
  25. package/dist/kit/Kanban.js +157 -0
  26. package/dist/kit/Kanban.js.map +1 -0
  27. package/dist/kit/TimeField.js +1 -1
  28. package/dist/kit/Timeline.d.ts +14 -0
  29. package/dist/kit/Timeline.js +71 -0
  30. package/dist/kit/Timeline.js.map +1 -0
  31. package/dist/kit/context.d.ts +1 -1
  32. package/dist/kit/context.js.map +1 -1
  33. package/dist/kit/messages.d.ts +22 -0
  34. package/dist/kit/messages.js +10 -0
  35. package/dist/kit/messages.js.map +1 -1
  36. package/dist/surface/Placed.d.ts +20 -0
  37. package/dist/surface/Placed.js +70 -0
  38. package/dist/surface/Placed.js.map +1 -0
  39. package/dist/surface/Surface.d.ts +4 -2
  40. package/dist/surface/Surface.js +78 -2
  41. package/dist/surface/Surface.js.map +1 -1
  42. package/dist/surface/places.d.ts +16 -0
  43. package/dist/surface/places.js +15 -0
  44. package/dist/surface/places.js.map +1 -0
  45. package/dist/surface/scope.d.ts +17 -1
  46. package/dist/surface/scope.js +1 -0
  47. package/dist/surface/scope.js.map +1 -1
  48. package/dist/types.d.ts +12 -0
  49. package/dist/types.js.map +1 -1
  50. package/dist/widget.js +17 -17
  51. package/package.json +1 -1
  52. package/src/AgentChat.tsx +215 -34
  53. package/src/AgentSpace.tsx +17 -1
  54. package/src/View.tsx +117 -0
  55. package/src/blocks.ts +100 -2
  56. package/src/client.ts +16 -0
  57. package/src/contract.ts +166 -5
  58. package/src/es.ts +9 -0
  59. package/src/index.ts +27 -2
  60. package/src/kit/Agenda.tsx +161 -0
  61. package/src/kit/Kanban.tsx +182 -0
  62. package/src/kit/Timeline.tsx +58 -0
  63. package/src/kit/context.tsx +45 -1
  64. package/src/kit/messages.ts +31 -0
  65. package/src/styles.css +568 -0
  66. package/src/surface/Placed.tsx +98 -0
  67. package/src/surface/Surface.tsx +92 -1
  68. package/src/surface/places.ts +19 -0
  69. package/src/surface/scope.ts +24 -1
  70. package/src/types.ts +13 -0
  71. package/src/widget/element.tsx +41 -3
@@ -1 +1 @@
1
- {"version":3,"file":"Surface.js","names":["Host"],"sources":["../../src/surface/Surface.tsx"],"sourcesContent":["import { ArrowUpIcon, CheckIcon, PencilSimpleIcon } from \"@phosphor-icons/react\";\nimport { Component, useEffect, useRef, useState, type ComponentType, type ReactNode } from \"react\";\n\nimport { Automation } from \"../automation/Automation\";\nimport type {\n AutomationBlock,\n Block,\n ButtonBlock,\n ChoiceBlock,\n ConnectBlock,\n FieldsBlock,\n ImageBlock,\n ListBlock,\n Surface as Shown,\n TableBlock,\n} from \"../blocks\";\nimport { classes } from \"../classes\";\nimport { Button } from \"../kit/Button\";\nimport { formatSize } from \"../about\";\nimport { baseName } from \"../files\";\nimport { Card } from \"../kit/Card\";\nimport { Chart } from \"../kit/Chart\";\nimport { KitProvider, useKit, useParts } from \"../kit/context\";\nimport { FileMark } from \"../kit/FileMark\";\nimport { List, Row } from \"../kit/List\";\nimport { Mark } from \"../kit/Mark\";\nimport type { KitLocale, KitMessages } from \"../kit/messages\";\nimport type { FileHost } from \"../kit/uploads\";\nimport { AudioPlayer } from \"../kit/AudioPlayer\";\nimport { Note } from \"../kit/Note\";\nimport { Stat } from \"../kit/Stat\";\nimport type { Attachment, FileBlock } from \"../types\";\nimport { FormView } from \"./Form\";\nimport { Markdown } from \"./Markdown\";\nimport {\n ScopeContext,\n useScope,\n useSurfaceParts,\n type Scope,\n type SurfaceClassNames,\n type SurfaceComponents,\n} from \"./scope\";\nimport { answeredIn, chosen, FIELD_KINDS, picked, pressed, type SurfaceAction } from \"./values\";\n\nexport interface SurfaceProps {\n surface: Shown;\n onAction: (action: SurfaceAction) => void;\n /** False draws the inputs disabled: a surface already answered, or one from an older turn. */\n active?: boolean | undefined;\n /** What the person already did on it: the option picked, the button pressed, the form sent. */\n answered?: SurfaceAction | undefined;\n components?: SurfaceComponents | undefined;\n classNames?: SurfaceClassNames;\n /** The words its controls say, in the host's language; English by default. */\n messages?: Partial<KitMessages> | undefined;\n /** The language of its calendar, days, times and numbers; English by default. */\n locale?: KitLocale | undefined;\n /**\n * Where its file fields' files go (uploaded as they are picked) and how the ones sent are found\n * and opened: the conversation's. None: a file field takes no files.\n */\n files?: FileHost | undefined;\n}\n\nconst BLOCKS: ReadonlySet<string> = new Set([\n \"card\",\n \"stack\",\n \"divider\",\n \"text\",\n \"fields\",\n \"table\",\n \"list\",\n \"stat\",\n \"chart\",\n \"note\",\n \"image\",\n \"automation\",\n \"file\",\n \"connect\",\n \"button\",\n \"choice\",\n \"form\",\n]);\n\n/** Whether every block down the tree, and every field of its forms, is one this renderer draws. */\nexport function known(blocks: Block[]): boolean {\n return blocks.every((block) => {\n if (!BLOCKS.has(block.type)) return false;\n if (block.type === \"form\") return block.fields.every((field) => FIELD_KINDS.has(field.kind));\n return \"children\" in block ? known(block.children) : true;\n });\n}\n\n/**\n * Whether a screen draws its own edge: one that is a single card (or an automation, or an app\n * to connect, each a card of its own) needs no panel around it where it is shown.\n */\nexport function framesItself(surface: Shown): boolean {\n const [only, ...more] = surface.blocks;\n return (\n more.length === 0 &&\n (only?.type === \"card\" || only?.type === \"automation\" || only?.type === \"connect\")\n );\n}\n\n/**\n * What the agent showed, drawn block by block with the kit's primitives (a `card` is a `Card`, a\n * `list` a `List` of `Row`s, a form's fields its controls); a block or a field kind the API has\n * grown since this renderer was written leaves the whole surface to its text twin, so nothing\n * is half-drawn. Each block's action comes back through `onAction`; the host wraps it with the\n * surface's id.\n */\nexport function Surface({\n surface,\n onAction,\n active = true,\n answered,\n components,\n classNames,\n messages,\n locale,\n files,\n}: SurfaceProps) {\n const scope: Scope = { active, answered, onAction, components, classNames, files };\n return (\n <KitProvider classNames={classNames} messages={messages} locale={locale}>\n <ScopeContext value={scope}>\n <div className={`sc ${classes(classNames, \"sc-surface\")}`}>\n <Whole twin={<p className={classes(classNames, \"sc-surface__text\")}>{surface.text}</p>}>\n {known(surface.blocks)\n ? surface.blocks.map((block, index) => <Draw key={index} block={block} />)\n : null}\n </Whole>\n </div>\n </ScopeContext>\n </KitProvider>\n );\n}\n\n/**\n * The surface drawn whole or not at all: what it can't draw (blocks it doesn't know, or one that\n * fails as it draws) leaves its text twin in its place, never a broken page.\n */\nclass Whole extends Component<{ twin: ReactNode; children: ReactNode }, { failed: boolean }> {\n override state = { failed: false };\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n override render() {\n return this.state.failed || this.props.children === null\n ? this.props.twin\n : this.props.children;\n }\n}\n\n/** One block: the host's own component for its type when it gave one, else the kit's. */\nfunction Draw({ block }: { block: Block }) {\n const { active, onAction, components } = useScope();\n const part = useSurfaceParts();\n const children =\n \"children\" in block\n ? block.children.map((child, index) => <Draw key={index} block={child} />)\n : undefined;\n const Own = components?.[block.type];\n if (Own) {\n // Found by the block's own type, so its fields are the right props; the union is too wide\n // for the compiler to see that pairing.\n const Host = Own as ComponentType<Record<string, unknown>>;\n return <Host {...block} active={active} onAction={onAction} children={children} />;\n }\n switch (block.type) {\n case \"card\":\n return (\n <Card title={block.title} subtitle={block.subtitle} image={block.image}>\n {children}\n </Card>\n );\n case \"stack\":\n return (\n <div\n part=\"stack\"\n className={part(\n \"sc-surface__stack\",\n ...(block.direction === \"row\" ? ([\"sc-surface__stack--row\"] as const) : []),\n )}\n >\n {children}\n </div>\n );\n case \"divider\":\n return <hr part=\"divider\" className={part(\"sc-surface__divider\")} />;\n case \"text\":\n return (\n <div part=\"text\" className={part(\"sc-surface__text\")}>\n <Markdown text={block.text} />\n </div>\n );\n case \"fields\":\n return <Fields block={block} />;\n case \"table\":\n return <Table block={block} />;\n case \"list\":\n return <Listing block={block} />;\n case \"stat\":\n return <Stat label={block.label} value={block.value} hint={block.hint} tone={block.tone} />;\n case \"chart\":\n return <Chart kind={block.kind} points={block.points} />;\n case \"note\":\n return (\n <Note tone={block.tone}>\n <Markdown text={block.text} />\n </Note>\n );\n case \"image\":\n return <Picture block={block} />;\n case \"automation\":\n return <AutomationShown block={block} />;\n case \"file\":\n return <FileShown block={block} />;\n case \"connect\":\n return <Connect block={block} />;\n case \"button\":\n return <Pressable block={block} />;\n case \"choice\":\n return <Choice block={block} />;\n case \"form\":\n return <FormView block={block} />;\n }\n}\n\n/**\n * A file the agent put in front of the person, compact: its kind's mark, its title (its name\n * under it when the title is another), its size at the right; pressed, it opens whole in the\n * host's viewer (`files.open`), whatever its kind. A picture, a video or a sound plays where it\n * is instead, when the host can play it (`files.play`). Until the API has put it in the\n * conversation it is only named, quietly.\n */\nfunction FileShown({ block }: { block: FileBlock }) {\n const { files } = useScope();\n const { code } = useKit();\n const { file } = block;\n const name = file?.name ?? baseName(block.path);\n const title = block.title ?? name;\n const open = file !== null ? files?.open : undefined;\n const played = file !== null ? playedAs(file.media_type) : null;\n const src = usePlayed(file, played !== null ? files?.play : undefined);\n if (file !== null && played !== null && src !== null) {\n return (\n <Played\n kind={played}\n src={src.url}\n name={name}\n caption={block.title}\n onOpen={open ? () => open(file) : undefined}\n onLost={src.again}\n />\n );\n }\n return (\n <List>\n <Row\n mark={<FileMark name={name} type={file?.media_type} />}\n title={title}\n subtitle={title === name ? undefined : name}\n meta={file === null ? undefined : formatSize(file.size, code)}\n quiet={file === null}\n onPress={open && file !== null ? () => open(file) : undefined}\n />\n </List>\n );\n}\n\ntype PlayedKind = \"image\" | \"video\" | \"audio\";\n\n/** How a file plays in the page: a picture, a video, a sound; null for any other kind. */\nfunction playedAs(mediaType: string): PlayedKind | null {\n const family = mediaType.split(\"/\")[0];\n return family === \"image\" || family === \"video\" || family === \"audio\" ? family : null;\n}\n\n/**\n * Where `file` plays from, asked of the host once (`play`): null until it answers, and when it\n * can't. `again` asks for a new address, for a player whose address ran out.\n */\nexport function usePlayed(\n file: Attachment | null,\n play: ((file: Attachment) => Promise<string>) | undefined,\n): { url: string; again: () => void } | null {\n const [url, setUrl] = useState<string | null>(null);\n const [asked, setAsked] = useState(0);\n // The file and the host's way to play it as they are now: a block drawn again carries the\n // same file anew, and the host its functions; what is asked for changes with the file's id.\n const latest = useRef({ file, play });\n latest.current = { file, play };\n const id = file?.id;\n const playable = play !== undefined;\n useEffect(() => {\n const { file: now, play: player } = latest.current;\n if (now === null || player === undefined) return;\n let current = true;\n player(now).then(\n (address) => current && setUrl(address),\n () => current && setUrl(null),\n );\n return () => {\n current = false;\n };\n }, [id, playable, asked]);\n return url === null ? null : { url, again: () => setAsked((times) => times + 1) };\n}\n\n/**\n * A picture, a video or a sound the agent put in front of the person, where it is: the\n * browser's own player, streaming from the address it plays from; a picture pressed opens whole\n * in the host's viewer. A player whose address ran out asks for a new one, once.\n */\nfunction Played({\n kind,\n src,\n name,\n caption,\n onOpen,\n onLost,\n}: {\n kind: PlayedKind;\n src: string;\n name: string;\n caption: string | undefined;\n onOpen: (() => void) | undefined;\n onLost: () => void;\n}) {\n const part = useSurfaceParts();\n const lost = useRef(false);\n const once = () => {\n if (lost.current) return;\n lost.current = true;\n onLost();\n };\n return (\n <figure part=\"media\" className={part(\"sc-surface__media\")} data-kind={kind}>\n {kind === \"image\" ? (\n onOpen ? (\n <button type=\"button\" onClick={onOpen} aria-label={name}>\n <img src={src} alt={name} loading=\"lazy\" onError={once} />\n </button>\n ) : (\n <img src={src} alt={name} loading=\"lazy\" onError={once} />\n )\n ) : kind === \"video\" ? (\n <video src={src} controls playsInline preload=\"metadata\" aria-label={name} onError={once} />\n ) : (\n <AudioPlayer src={src} label={name} onError={once} />\n )}\n {caption !== undefined && <figcaption>{caption}</figcaption>}\n </figure>\n );\n}\n\n/** Labels and their values, a row each. */\nfunction Fields({ block }: { block: FieldsBlock }) {\n const part = useSurfaceParts();\n return (\n <dl part=\"fields\" className={part(\"sc-surface__fields\")}>\n {block.items.map((item, index) => (\n <div key={index}>\n <dt>{item.label}</dt>\n <dd>{item.value}</dd>\n </div>\n ))}\n </dl>\n );\n}\n\n/** Rows under named columns, scrolling across inside their own box when they are wide. */\nfunction Table({ block }: { block: TableBlock }) {\n const part = useSurfaceParts();\n return (\n <div part=\"table\" className={part(\"sc-surface__table\")}>\n <table>\n <thead>\n <tr>\n {block.columns.map((column, index) => (\n <th key={index} scope=\"col\">\n {column}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {block.rows.map((row, index) => (\n <tr key={index}>\n {block.columns.map((_, at) => (\n <td key={at}>{row[at] ?? \"\"}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\n/** A list block as the kit's `List`: a `Row` each; with an action, rows to pick, the picked checked. */\nfunction Listing({ block }: { block: ListBlock }) {\n const { active, answered, onAction } = useScope();\n const { action } = block;\n const pick = action !== undefined && answered?.name === action ? answered.data.item : undefined;\n return (\n <List>\n {block.items.map((entry) => (\n <Row\n key={entry.id}\n mark={\n entry.image !== undefined && https(entry.image) ? (\n <Mark src={entry.image} photo size={40} />\n ) : undefined\n }\n title={entry.title}\n subtitle={entry.subtitle}\n meta={entry.meta}\n pressed={entry.id === pick}\n disabled={!active}\n onPress={\n action === undefined ? undefined : () => onAction(chosen({ ...block, action }, entry))\n }\n />\n ))}\n </List>\n );\n}\n\n/** A picture from an https address, never sending the page's address along, with its caption. */\nfunction Picture({ block }: { block: ImageBlock }) {\n const part = useSurfaceParts();\n if (!https(block.url)) return null;\n return (\n <figure part=\"image\" className={part(\"sc-surface__image\")}>\n <img src={block.url} alt={block.alt} loading=\"lazy\" referrerPolicy=\"no-referrer\" />\n {block.caption !== undefined && <figcaption>{block.caption}</figcaption>}\n </figure>\n );\n}\n\n/**\n * An automation, read only: the agent's page is where it is switched and its runs opened. One\n * that is not there (removed, renamed since) says so quietly.\n */\nfunction AutomationShown({ block }: { block: AutomationBlock }) {\n const part = useParts();\n const { messages } = useKit();\n // `null`: it is gone; missing: not filled in by the API, which a newer server always does.\n if (block.view == null) {\n return (\n <p className={part(\"sc-automation\", \"sc-automation--gone\")}>{messages.automation.gone}</p>\n );\n }\n return <Automation automation={block.view} runs={block.view.runs} />;\n}\n\n/**\n * An app for the person to connect, as its connection stands: its logo and name over the line\n * the agent wrote of what it will do with it; while it waits for them, the button that opens\n * its consent page apart; once it works, or if it failed, a quiet word in its place. Before\n * the API has asked for it, only the app as the agent named it.\n */\nfunction Connect({ block }: { block: ConnectBlock }) {\n const part = useSurfaceParts();\n const { messages } = useKit();\n const { connection } = block;\n const title = connection?.title ?? block.app;\n const pending = connection?.status === \"pending\" ? connection.url : null;\n const url = pending !== null && https(pending) ? pending : null;\n const working = connection?.status === \"active\";\n const failed = connection !== null && !working && connection.status !== \"pending\";\n return (\n <Card title={title} subtitle={block.purpose} image={connection?.icon ?? undefined}>\n {url !== null ? (\n <Button tone=\"primary\" href={url}>\n {messages.connect.authorize(title)}\n </Button>\n ) : (\n <p\n className={part(\n \"sc-surface__connect\",\n ...(working ? ([\"sc-surface__connect--done\"] as const) : []),\n )}\n >\n {working && <CheckIcon aria-hidden weight=\"bold\" />}\n {connectWords(messages.connect, working, failed)}\n </p>\n )}\n </Card>\n );\n}\n\n/** The quiet word an app's card says where its button isn't: working, failed, or on its way. */\nfunction connectWords(words: KitMessages[\"connect\"], working: boolean, failed: boolean): string {\n if (working) return words.connected;\n return failed ? words.failed : words.preparing;\n}\n\n/**\n * A button that sends its action, marked once it was the one pressed; or a link that opens its\n * page apart (it stays usable on an older turn: it changes nothing here).\n */\nfunction Pressable({ block }: { block: ButtonBlock }) {\n const { active, answered, onAction } = useScope();\n const { action, url, tone, label } = block;\n if (url !== undefined) {\n return https(url) ? (\n <Button tone={tone} href={url}>\n {label}\n </Button>\n ) : null;\n }\n if (action === undefined) return null;\n const done = answered?.name === action && answered.label === label;\n return (\n <Button\n tone={tone}\n icon={done ? CheckIcon : undefined}\n pressed={done}\n disabled={!active}\n onClick={() => onAction(pressed({ ...block, action }))}\n >\n {label}\n </Button>\n );\n}\n\n/** A few options to pick one of at once; the one picked keeps a ring and a check. */\nfunction Choice({ block }: { block: ChoiceBlock }) {\n const { active, answered, onAction } = useScope();\n const part = useSurfaceParts();\n const mine = answered?.name === block.action ? answered.data : undefined;\n const chosenId = mine?.option;\n const listed =\n block.other === true ||\n block.options.length > SHORT_CHOICE ||\n block.options.some((option) => option.hint !== undefined || option.label.length > SHORT_LABEL);\n return (\n <div\n role=\"group\"\n part=\"choice\"\n className={part(\n \"sc-surface__choice\",\n ...(listed ? ([\"sc-surface__choice--list\"] as const) : []),\n )}\n >\n {block.options.map((option) => (\n <button\n key={option.id}\n type=\"button\"\n disabled={!active}\n aria-pressed={option.id === chosenId || undefined}\n onClick={() => onAction(picked(block, option))}\n part=\"option\"\n className={part(\"sc-surface__option\")}\n >\n <span>\n {option.label}\n {option.hint !== undefined && <small>{option.hint}</small>}\n </span>\n {option.id === chosenId && <CheckIcon aria-hidden weight=\"bold\" />}\n </button>\n ))}\n {block.other === true && (\n <Other\n active={active}\n said={typeof mine?.text === \"string\" ? mine.text : undefined}\n onSay={(text) => onAction(answeredIn(block, text))}\n />\n )}\n </div>\n );\n}\n\n/** Pills fit options this few and this short; more, longer or with a hint, they go one a row. */\nconst SHORT_CHOICE = 4;\nconst SHORT_LABEL = 28;\n\n/**\n * A choice's last row, to answer in one's own words: pressed, it turns into a box with its send\n * (Enter sends, Escape folds it back). Once said, the words stand in it, chosen.\n */\nfunction Other({\n active,\n said,\n onSay,\n}: {\n active: boolean;\n said: string | undefined;\n onSay: (text: string) => void;\n}) {\n const part = useSurfaceParts();\n const { messages } = useKit();\n const [writing, setWriting] = useState(false);\n const [text, setText] = useState(\"\");\n if (said !== undefined || !writing) {\n return (\n <button\n type=\"button\"\n disabled={!active}\n aria-pressed={said !== undefined || undefined}\n onClick={() => setWriting(true)}\n part=\"option other\"\n className={part(\"sc-surface__option\", \"sc-surface__option--other\")}\n >\n {said === undefined && <PencilSimpleIcon aria-hidden />}\n <span>{said ?? messages.other}</span>\n {said !== undefined && <CheckIcon aria-hidden weight=\"bold\" />}\n </button>\n );\n }\n const send = () => {\n const words = text.trim();\n if (words !== \"\") onSay(words);\n };\n return (\n <form\n part=\"other\"\n className={part(\"sc-surface__other\")}\n onSubmit={(event) => {\n event.preventDefault();\n send();\n }}\n >\n <input\n // A person who pressed to write wants to write.\n autoFocus\n value={text}\n aria-label={messages.other}\n placeholder={messages.otherPlaceholder}\n onChange={(event) => setText(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.stopPropagation();\n setWriting(false);\n }\n }}\n />\n <button type=\"submit\" aria-label={messages.send} disabled={text.trim() === \"\"}>\n <ArrowUpIcon aria-hidden weight=\"bold\" />\n </button>\n </form>\n );\n}\n\n/** Only an https address is loaded or opened: never a script, never a local file. */\nfunction https(url: string): boolean {\n return /^https:\\/\\//i.test(url);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"Surface.js","names":["Host"],"sources":["../../src/surface/Surface.tsx"],"sourcesContent":["import { ArrowUpIcon, CheckIcon, PencilSimpleIcon } from \"@phosphor-icons/react\";\nimport { Component, useEffect, useRef, useState, type ComponentType, type ReactNode } from \"react\";\n\nimport { Automation } from \"../automation/Automation\";\nimport type {\n AutomationBlock,\n Block,\n BoardBlock,\n ButtonBlock,\n CalendarBlock,\n ChoiceBlock,\n ConnectBlock,\n FieldsBlock,\n HostBlock,\n ImageBlock,\n ListBlock,\n Surface as Shown,\n TableBlock,\n} from \"../blocks\";\nimport { classes } from \"../classes\";\nimport { Button } from \"../kit/Button\";\nimport { formatSize } from \"../about\";\nimport { baseName } from \"../files\";\nimport { Agenda } from \"../kit/Agenda\";\nimport { Kanban } from \"../kit/Kanban\";\nimport { Card } from \"../kit/Card\";\nimport { Chart } from \"../kit/Chart\";\nimport { KitProvider, useKit, useParts } from \"../kit/context\";\nimport { FileMark } from \"../kit/FileMark\";\nimport { List, Row } from \"../kit/List\";\nimport { Mark } from \"../kit/Mark\";\nimport type { KitLocale, KitMessages } from \"../kit/messages\";\nimport type { FileHost } from \"../kit/uploads\";\nimport { AudioPlayer } from \"../kit/AudioPlayer\";\nimport { Note } from \"../kit/Note\";\nimport { Stat } from \"../kit/Stat\";\nimport { Timeline } from \"../kit/Timeline\";\nimport type { Attachment, FileBlock } from \"../types\";\nimport { FormView } from \"./Form\";\nimport { Markdown } from \"./Markdown\";\nimport {\n ScopeContext,\n useScope,\n useSurfaceParts,\n type HostBlockProps,\n type HostBlocks,\n type Scope,\n type SurfaceClassNames,\n type SurfaceComponents,\n} from \"./scope\";\nimport { answeredIn, chosen, FIELD_KINDS, picked, pressed, type SurfaceAction } from \"./values\";\n\nexport interface SurfaceProps {\n surface: Shown;\n onAction: (action: SurfaceAction) => void;\n /** False draws the inputs disabled: a surface already answered, or one from an older turn. */\n active?: boolean | undefined;\n /** What the person already did on it: the option picked, the button pressed, the form sent. */\n answered?: SurfaceAction | undefined;\n components?: SurfaceComponents | undefined;\n /** The host's own blocks, by the name each was declared with. */\n blocks?: HostBlocks | undefined;\n classNames?: SurfaceClassNames;\n /** The words its controls say, in the host's language; English by default. */\n messages?: Partial<KitMessages> | undefined;\n /** The language of its calendar, days, times and numbers; English by default. */\n locale?: KitLocale | undefined;\n /**\n * Where its file fields' files go (uploaded as they are picked) and how the ones sent are found\n * and opened: the conversation's. None: a file field takes no files.\n */\n files?: FileHost | undefined;\n}\n\nconst BLOCKS: ReadonlySet<string> = new Set([\n \"card\",\n \"stack\",\n \"divider\",\n \"text\",\n \"fields\",\n \"table\",\n \"list\",\n \"stat\",\n \"chart\",\n \"note\",\n \"image\",\n \"automation\",\n \"file\",\n \"connect\",\n \"button\",\n \"choice\",\n \"form\",\n \"calendar\",\n \"timeline\",\n \"board\",\n \"host\",\n]);\n\n/** Whether every block down the tree, and every field of its forms, is one this renderer draws. */\nexport function known(blocks: Block[]): boolean {\n return blocks.every((block) => {\n if (!BLOCKS.has(block.type)) return false;\n if (block.type === \"form\") return block.fields.every((field) => FIELD_KINDS.has(field.kind));\n return \"children\" in block ? known(block.children) : true;\n });\n}\n\n/**\n * Whether a screen draws its own edge: one that is a single card (or an automation, or an app\n * to connect, each a card of its own) needs no panel around it where it is shown.\n */\nexport function framesItself(surface: Shown): boolean {\n const [only, ...more] = surface.blocks;\n return (\n more.length === 0 &&\n (only?.type === \"card\" || only?.type === \"automation\" || only?.type === \"connect\")\n );\n}\n\n/**\n * What the agent showed, drawn block by block with the kit's primitives (a `card` is a `Card`, a\n * `list` a `List` of `Row`s, a form's fields its controls); a block or a field kind the API has\n * grown since this renderer was written leaves the whole surface to its text twin, so nothing\n * is half-drawn. Each block's action comes back through `onAction`; the host wraps it with the\n * surface's id.\n */\nexport function Surface({\n surface,\n onAction,\n active = true,\n answered,\n components,\n blocks,\n classNames,\n messages,\n locale,\n files,\n}: SurfaceProps) {\n const scope: Scope = { active, answered, onAction, components, blocks, classNames, files };\n return (\n <KitProvider classNames={classNames} messages={messages} locale={locale}>\n <ScopeContext value={scope}>\n <div className={`sc ${classes(classNames, \"sc-surface\")}`}>\n <Whole twin={<p className={classes(classNames, \"sc-surface__text\")}>{surface.text}</p>}>\n {known(surface.blocks)\n ? surface.blocks.map((block, index) => <Draw key={index} block={block} />)\n : null}\n </Whole>\n </div>\n </ScopeContext>\n </KitProvider>\n );\n}\n\n/**\n * The surface drawn whole or not at all: what it can't draw (blocks it doesn't know, or one that\n * fails as it draws) leaves its text twin in its place, never a broken page.\n */\nclass Whole extends Component<{ twin: ReactNode; children: ReactNode }, { failed: boolean }> {\n override state = { failed: false };\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n override render() {\n return this.state.failed || this.props.children === null\n ? this.props.twin\n : this.props.children;\n }\n}\n\n/** One block: the host's own component for its type when it gave one, else the kit's. */\nfunction Draw({ block }: { block: Block }) {\n const { active, onAction, components } = useScope();\n const part = useSurfaceParts();\n const children =\n \"children\" in block\n ? block.children.map((child, index) => <Draw key={index} block={child} />)\n : undefined;\n const Own = components?.[block.type];\n if (Own) {\n // Found by the block's own type, so its fields are the right props; the union is too wide\n // for the compiler to see that pairing.\n const Host = Own as ComponentType<Record<string, unknown>>;\n return <Host {...block} active={active} onAction={onAction} children={children} />;\n }\n switch (block.type) {\n case \"card\":\n return (\n <Card title={block.title} subtitle={block.subtitle} image={block.image}>\n {children}\n </Card>\n );\n case \"stack\":\n return (\n <div\n part=\"stack\"\n className={part(\n \"sc-surface__stack\",\n ...(block.direction === \"row\" ? ([\"sc-surface__stack--row\"] as const) : []),\n )}\n >\n {children}\n </div>\n );\n case \"divider\":\n return <hr part=\"divider\" className={part(\"sc-surface__divider\")} />;\n case \"text\":\n return (\n <div part=\"text\" className={part(\"sc-surface__text\")}>\n <Markdown text={block.text} />\n </div>\n );\n case \"fields\":\n return <Fields block={block} />;\n case \"table\":\n return <Table block={block} />;\n case \"list\":\n return <Listing block={block} />;\n case \"stat\":\n return <Stat label={block.label} value={block.value} hint={block.hint} tone={block.tone} />;\n case \"chart\":\n return <Chart kind={block.kind} points={block.points} />;\n case \"note\":\n return (\n <Note tone={block.tone}>\n <Markdown text={block.text} />\n </Note>\n );\n case \"image\":\n return <Picture block={block} />;\n case \"automation\":\n return <AutomationShown block={block} />;\n case \"file\":\n return <FileShown block={block} />;\n case \"connect\":\n return <Connect block={block} />;\n case \"button\":\n return <Pressable block={block} />;\n case \"choice\":\n return <Choice block={block} />;\n case \"form\":\n return <FormView block={block} />;\n case \"calendar\":\n return <CalendarShown block={block} />;\n case \"timeline\":\n return <Timeline items={block.items} />;\n case \"board\":\n return <BoardShown block={block} />;\n case \"host\":\n return <Hosted block={block} />;\n }\n}\n\n/** A calendar; with its action, pressing an event sends it (`{event}`). */\nfunction CalendarShown({ block }: { block: CalendarBlock }) {\n const { active, onAction } = useScope();\n const { action } = block;\n return (\n <Agenda\n span={block.span}\n start={block.start}\n events={block.events}\n disabled={!active}\n onEvent={\n action === undefined\n ? undefined\n : (event) => {\n onAction({ name: action, data: { event: event.id }, label: event.title });\n }\n }\n />\n );\n}\n\n/** A board; with its action, a card moved to another column sends it (`{card, column}`). */\nfunction BoardShown({ block }: { block: BoardBlock }) {\n const { active, onAction } = useScope();\n const { messages } = useKit();\n const { action } = block;\n return (\n <Kanban\n columns={block.columns}\n disabled={!active}\n onMove={\n action === undefined\n ? undefined\n : (card, column) => {\n onAction({\n name: action,\n data: { card: card.id, column: column.id },\n label: messages.board.moved(card.title, column.title),\n });\n }\n }\n />\n );\n}\n\n/**\n * One of the host's own blocks, drawn by the component it registered under the block's name; a\n * name it gave none for, or a component that fails as it draws, leaves the block's words in a\n * quiet card in its place, and the rest of the surface draws.\n */\nfunction Hosted({ block }: { block: HostBlock }) {\n const { blocks, active, onAction } = useScope();\n const part = useSurfaceParts();\n const twin = (\n <div part=\"host\" className={part(\"sc-surface__host\")} data-block={block.name}>\n <Markdown text={block.text} />\n </div>\n );\n // Registered under this name, for these props: the API checked them against its schema.\n const Own = blocks?.[block.name] as ComponentType<HostBlockProps> | undefined;\n if (Own === undefined) return twin;\n return (\n <Whole twin={twin}>\n <Own props={block.props} text={block.text} active={active} onAction={onAction} />\n </Whole>\n );\n}\n\n/**\n * A file the agent put in front of the person, compact: its kind's mark, its title (its name\n * under it when the title is another), its size at the right; pressed, it opens whole in the\n * host's viewer (`files.open`), whatever its kind. A picture, a video or a sound plays where it\n * is instead, when the host can play it (`files.play`). Until the API has put it in the\n * conversation it is only named, quietly.\n */\nfunction FileShown({ block }: { block: FileBlock }) {\n const { files } = useScope();\n const { code } = useKit();\n const { file } = block;\n const name = file?.name ?? baseName(block.path);\n const title = block.title ?? name;\n const open = file !== null ? files?.open : undefined;\n const played = file !== null ? playedAs(file.media_type) : null;\n const src = usePlayed(file, played !== null ? files?.play : undefined);\n if (file !== null && played !== null && src !== null) {\n return (\n <Played\n kind={played}\n src={src.url}\n name={name}\n caption={block.title}\n onOpen={open ? () => open(file) : undefined}\n onLost={src.again}\n />\n );\n }\n return (\n <List>\n <Row\n mark={<FileMark name={name} type={file?.media_type} />}\n title={title}\n subtitle={title === name ? undefined : name}\n meta={file === null ? undefined : formatSize(file.size, code)}\n quiet={file === null}\n onPress={open && file !== null ? () => open(file) : undefined}\n />\n </List>\n );\n}\n\ntype PlayedKind = \"image\" | \"video\" | \"audio\";\n\n/** How a file plays in the page: a picture, a video, a sound; null for any other kind. */\nfunction playedAs(mediaType: string): PlayedKind | null {\n const family = mediaType.split(\"/\")[0];\n return family === \"image\" || family === \"video\" || family === \"audio\" ? family : null;\n}\n\n/**\n * Where `file` plays from, asked of the host once (`play`): null until it answers, and when it\n * can't. `again` asks for a new address, for a player whose address ran out.\n */\nexport function usePlayed(\n file: Attachment | null,\n play: ((file: Attachment) => Promise<string>) | undefined,\n): { url: string; again: () => void } | null {\n const [url, setUrl] = useState<string | null>(null);\n const [asked, setAsked] = useState(0);\n // The file and the host's way to play it as they are now: a block drawn again carries the\n // same file anew, and the host its functions; what is asked for changes with the file's id.\n const latest = useRef({ file, play });\n latest.current = { file, play };\n const id = file?.id;\n const playable = play !== undefined;\n useEffect(() => {\n const { file: now, play: player } = latest.current;\n if (now === null || player === undefined) return;\n let current = true;\n player(now).then(\n (address) => current && setUrl(address),\n () => current && setUrl(null),\n );\n return () => {\n current = false;\n };\n }, [id, playable, asked]);\n return url === null ? null : { url, again: () => setAsked((times) => times + 1) };\n}\n\n/**\n * A picture, a video or a sound the agent put in front of the person, where it is: the\n * browser's own player, streaming from the address it plays from; a picture pressed opens whole\n * in the host's viewer. A player whose address ran out asks for a new one, once.\n */\nfunction Played({\n kind,\n src,\n name,\n caption,\n onOpen,\n onLost,\n}: {\n kind: PlayedKind;\n src: string;\n name: string;\n caption: string | undefined;\n onOpen: (() => void) | undefined;\n onLost: () => void;\n}) {\n const part = useSurfaceParts();\n const lost = useRef(false);\n const once = () => {\n if (lost.current) return;\n lost.current = true;\n onLost();\n };\n return (\n <figure part=\"media\" className={part(\"sc-surface__media\")} data-kind={kind}>\n {kind === \"image\" ? (\n onOpen ? (\n <button type=\"button\" onClick={onOpen} aria-label={name}>\n <img src={src} alt={name} loading=\"lazy\" onError={once} />\n </button>\n ) : (\n <img src={src} alt={name} loading=\"lazy\" onError={once} />\n )\n ) : kind === \"video\" ? (\n <video src={src} controls playsInline preload=\"metadata\" aria-label={name} onError={once} />\n ) : (\n <AudioPlayer src={src} label={name} onError={once} />\n )}\n {caption !== undefined && <figcaption>{caption}</figcaption>}\n </figure>\n );\n}\n\n/** Labels and their values, a row each. */\nfunction Fields({ block }: { block: FieldsBlock }) {\n const part = useSurfaceParts();\n return (\n <dl part=\"fields\" className={part(\"sc-surface__fields\")}>\n {block.items.map((item, index) => (\n <div key={index}>\n <dt>{item.label}</dt>\n <dd>{item.value}</dd>\n </div>\n ))}\n </dl>\n );\n}\n\n/** Rows under named columns, scrolling across inside their own box when they are wide. */\nfunction Table({ block }: { block: TableBlock }) {\n const part = useSurfaceParts();\n return (\n <div part=\"table\" className={part(\"sc-surface__table\")}>\n <table>\n <thead>\n <tr>\n {block.columns.map((column, index) => (\n <th key={index} scope=\"col\">\n {column}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {block.rows.map((row, index) => (\n <tr key={index}>\n {block.columns.map((_, at) => (\n <td key={at}>{row[at] ?? \"\"}</td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n\n/** A list block as the kit's `List`: a `Row` each; with an action, rows to pick, the picked checked. */\nfunction Listing({ block }: { block: ListBlock }) {\n const { active, answered, onAction } = useScope();\n const { action } = block;\n const pick = action !== undefined && answered?.name === action ? answered.data.item : undefined;\n return (\n <List>\n {block.items.map((entry) => (\n <Row\n key={entry.id}\n mark={\n entry.image !== undefined && https(entry.image) ? (\n <Mark src={entry.image} photo size={40} />\n ) : undefined\n }\n title={entry.title}\n subtitle={entry.subtitle}\n meta={entry.meta}\n pressed={entry.id === pick}\n disabled={!active}\n onPress={\n action === undefined ? undefined : () => onAction(chosen({ ...block, action }, entry))\n }\n />\n ))}\n </List>\n );\n}\n\n/** A picture from an https address, never sending the page's address along, with its caption. */\nfunction Picture({ block }: { block: ImageBlock }) {\n const part = useSurfaceParts();\n if (!https(block.url)) return null;\n return (\n <figure part=\"image\" className={part(\"sc-surface__image\")}>\n <img src={block.url} alt={block.alt} loading=\"lazy\" referrerPolicy=\"no-referrer\" />\n {block.caption !== undefined && <figcaption>{block.caption}</figcaption>}\n </figure>\n );\n}\n\n/**\n * An automation, read only: the agent's page is where it is switched and its runs opened. One\n * that is not there (removed, renamed since) says so quietly.\n */\nfunction AutomationShown({ block }: { block: AutomationBlock }) {\n const part = useParts();\n const { messages } = useKit();\n // `null`: it is gone; missing: not filled in by the API, which a newer server always does.\n if (block.view == null) {\n return (\n <p className={part(\"sc-automation\", \"sc-automation--gone\")}>{messages.automation.gone}</p>\n );\n }\n return <Automation automation={block.view} runs={block.view.runs} />;\n}\n\n/**\n * An app for the person to connect, as its connection stands: its logo and name over the line\n * the agent wrote of what it will do with it; while it waits for them, the button that opens\n * its consent page apart; once it works, or if it failed, a quiet word in its place. Before\n * the API has asked for it, only the app as the agent named it.\n */\nfunction Connect({ block }: { block: ConnectBlock }) {\n const part = useSurfaceParts();\n const { messages } = useKit();\n const { connection } = block;\n const title = connection?.title ?? block.app;\n const pending = connection?.status === \"pending\" ? connection.url : null;\n const url = pending !== null && https(pending) ? pending : null;\n const working = connection?.status === \"active\";\n const failed = connection !== null && !working && connection.status !== \"pending\";\n return (\n <Card title={title} subtitle={block.purpose} image={connection?.icon ?? undefined}>\n {url !== null ? (\n <Button tone=\"primary\" href={url}>\n {messages.connect.authorize(title)}\n </Button>\n ) : (\n <p\n className={part(\n \"sc-surface__connect\",\n ...(working ? ([\"sc-surface__connect--done\"] as const) : []),\n )}\n >\n {working && <CheckIcon aria-hidden weight=\"bold\" />}\n {connectWords(messages.connect, working, failed)}\n </p>\n )}\n </Card>\n );\n}\n\n/** The quiet word an app's card says where its button isn't: working, failed, or on its way. */\nfunction connectWords(words: KitMessages[\"connect\"], working: boolean, failed: boolean): string {\n if (working) return words.connected;\n return failed ? words.failed : words.preparing;\n}\n\n/**\n * A button that sends its action, marked once it was the one pressed; or a link that opens its\n * page apart (it stays usable on an older turn: it changes nothing here).\n */\nfunction Pressable({ block }: { block: ButtonBlock }) {\n const { active, answered, onAction } = useScope();\n const { action, url, tone, label } = block;\n if (url !== undefined) {\n return https(url) ? (\n <Button tone={tone} href={url}>\n {label}\n </Button>\n ) : null;\n }\n if (action === undefined) return null;\n const done = answered?.name === action && answered.label === label;\n return (\n <Button\n tone={tone}\n icon={done ? CheckIcon : undefined}\n pressed={done}\n disabled={!active}\n onClick={() => onAction(pressed({ ...block, action }))}\n >\n {label}\n </Button>\n );\n}\n\n/** A few options to pick one of at once; the one picked keeps a ring and a check. */\nfunction Choice({ block }: { block: ChoiceBlock }) {\n const { active, answered, onAction } = useScope();\n const part = useSurfaceParts();\n const mine = answered?.name === block.action ? answered.data : undefined;\n const chosenId = mine?.option;\n const listed =\n block.other === true ||\n block.options.length > SHORT_CHOICE ||\n block.options.some((option) => option.hint !== undefined || option.label.length > SHORT_LABEL);\n return (\n <div\n role=\"group\"\n part=\"choice\"\n className={part(\n \"sc-surface__choice\",\n ...(listed ? ([\"sc-surface__choice--list\"] as const) : []),\n )}\n >\n {block.options.map((option) => (\n <button\n key={option.id}\n type=\"button\"\n disabled={!active}\n aria-pressed={option.id === chosenId || undefined}\n onClick={() => onAction(picked(block, option))}\n part=\"option\"\n className={part(\"sc-surface__option\")}\n >\n <span>\n {option.label}\n {option.hint !== undefined && <small>{option.hint}</small>}\n </span>\n {option.id === chosenId && <CheckIcon aria-hidden weight=\"bold\" />}\n </button>\n ))}\n {block.other === true && (\n <Other\n active={active}\n said={typeof mine?.text === \"string\" ? mine.text : undefined}\n onSay={(text) => onAction(answeredIn(block, text))}\n />\n )}\n </div>\n );\n}\n\n/** Pills fit options this few and this short; more, longer or with a hint, they go one a row. */\nconst SHORT_CHOICE = 4;\nconst SHORT_LABEL = 28;\n\n/**\n * A choice's last row, to answer in one's own words: pressed, it turns into a box with its send\n * (Enter sends, Escape folds it back). Once said, the words stand in it, chosen.\n */\nfunction Other({\n active,\n said,\n onSay,\n}: {\n active: boolean;\n said: string | undefined;\n onSay: (text: string) => void;\n}) {\n const part = useSurfaceParts();\n const { messages } = useKit();\n const [writing, setWriting] = useState(false);\n const [text, setText] = useState(\"\");\n if (said !== undefined || !writing) {\n return (\n <button\n type=\"button\"\n disabled={!active}\n aria-pressed={said !== undefined || undefined}\n onClick={() => setWriting(true)}\n part=\"option other\"\n className={part(\"sc-surface__option\", \"sc-surface__option--other\")}\n >\n {said === undefined && <PencilSimpleIcon aria-hidden />}\n <span>{said ?? messages.other}</span>\n {said !== undefined && <CheckIcon aria-hidden weight=\"bold\" />}\n </button>\n );\n }\n const send = () => {\n const words = text.trim();\n if (words !== \"\") onSay(words);\n };\n return (\n <form\n part=\"other\"\n className={part(\"sc-surface__other\")}\n onSubmit={(event) => {\n event.preventDefault();\n send();\n }}\n >\n <input\n // A person who pressed to write wants to write.\n autoFocus\n value={text}\n aria-label={messages.other}\n placeholder={messages.otherPlaceholder}\n onChange={(event) => setText(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === \"Escape\") {\n event.stopPropagation();\n setWriting(false);\n }\n }}\n />\n <button type=\"submit\" aria-label={messages.send} disabled={text.trim() === \"\"}>\n <ArrowUpIcon aria-hidden weight=\"bold\" />\n </button>\n </form>\n );\n}\n\n/** Only an https address is loaded or opened: never a script, never a local file. */\nfunction https(url: string): boolean {\n return /^https:\\/\\//i.test(url);\n}\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { Place, Surface } from "../blocks.js";
2
+ //#region src/surface/places.d.ts
3
+ /**
4
+ * Where a host lets the agent put what it shows besides the conversation: a panel beside it, a
5
+ * modal over the page. A place it doesn't allow shows in the conversation.
6
+ */
7
+ export interface SurfacePlaces {
8
+ panel?: boolean | undefined;
9
+ modal?: boolean | undefined;
10
+ }
11
+ /** Both, unless the host says otherwise. */
12
+ export declare const EVERY_PLACE: SurfacePlaces;
13
+ /** Where a surface shows in this page: the place the agent chose when the host allows it. */
14
+ export declare function placeOf(surface: Surface, places?: SurfacePlaces): Place;
15
+ //#endregion
16
+ //# sourceMappingURL=places.d.ts.map
@@ -0,0 +1,15 @@
1
+ //#region src/surface/places.ts
2
+ /** Both, unless the host says otherwise. */
3
+ const EVERY_PLACE = {
4
+ panel: true,
5
+ modal: true
6
+ };
7
+ /** Where a surface shows in this page: the place the agent chose when the host allows it. */
8
+ function placeOf(surface, places = EVERY_PLACE) {
9
+ const where = surface.where ?? "chat";
10
+ return where !== "chat" && places[where] === true ? where : "chat";
11
+ }
12
+ //#endregion
13
+ export { EVERY_PLACE, placeOf };
14
+
15
+ //# sourceMappingURL=places.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"places.js","names":[],"sources":["../../src/surface/places.ts"],"sourcesContent":["import type { Place, Surface } from \"../blocks\";\n\n/**\n * Where a host lets the agent put what it shows besides the conversation: a panel beside it, a\n * modal over the page. A place it doesn't allow shows in the conversation.\n */\nexport interface SurfacePlaces {\n panel?: boolean | undefined;\n modal?: boolean | undefined;\n}\n\n/** Both, unless the host says otherwise. */\nexport const EVERY_PLACE: SurfacePlaces = { panel: true, modal: true };\n\n/** Where a surface shows in this page: the place the agent chose when the host allows it. */\nexport function placeOf(surface: Surface, places: SurfacePlaces = EVERY_PLACE): Place {\n const where = surface.where ?? \"chat\";\n return where !== \"chat\" && places[where] === true ? where : \"chat\";\n}\n"],"mappings":";;AAYA,MAAa,cAA6B;CAAE,OAAO;CAAM,OAAO;AAAK;;AAGrE,SAAgB,QAAQ,SAAkB,SAAwB,aAAoB;CACpF,MAAM,QAAQ,QAAQ,SAAS;CAC/B,OAAO,UAAU,UAAU,OAAO,WAAW,OAAO,QAAQ;AAC9D"}
@@ -8,7 +8,7 @@ import { ComponentType, ReactNode } from "react";
8
8
  * The surface's own parts, by the class each carries: the blocks that are not a kit primitive,
9
9
  * and the form's layout. `classNames` takes these and the kit's (`KitPart`) under the same keys.
10
10
  */
11
- export type SurfacePart = "sc-surface" | "sc-surface__stack" | "sc-surface__stack--row" | "sc-surface__divider" | "sc-surface__text" | "sc-surface__fields" | "sc-surface__table" | "sc-surface__image" | "sc-surface__media" | "sc-surface__choice" | "sc-surface__choice--list" | "sc-surface__option" | "sc-surface__option--other" | "sc-surface__other" | "sc-surface__form" | "sc-surface__submit" | "sc-surface__foot" | "sc-surface__sent" | "sc-surface__connect" | "sc-surface__connect--done";
11
+ export type SurfacePart = "sc-surface" | "sc-surface__stack" | "sc-surface__stack--row" | "sc-surface__divider" | "sc-surface__text" | "sc-surface__fields" | "sc-surface__table" | "sc-surface__image" | "sc-surface__media" | "sc-surface__choice" | "sc-surface__choice--list" | "sc-surface__option" | "sc-surface__option--other" | "sc-surface__other" | "sc-surface__form" | "sc-surface__submit" | "sc-surface__foot" | "sc-surface__sent" | "sc-surface__connect" | "sc-surface__connect--done" | "sc-surface__host";
12
12
  export type SurfaceClassNames = Partial<Record<SurfacePart | KitPart, string>> | undefined;
13
13
  /**
14
14
  * What a host's component for a block type receives: the block itself, whether the surface still
@@ -28,5 +28,21 @@ export type BlockProps<Type extends Block["type"]> = Omit<Extract<Block, {
28
28
  };
29
29
  /** The host's own drawing of a block type, in place of the package's: `{ table: TheirTable }`. */
30
30
  export type SurfaceComponents = { [Type in Block["type"]]?: ComponentType<BlockProps<Type>>; };
31
+ /**
32
+ * What a host's own block receives (`HostBlocks`): its `props`, as the API checked them against
33
+ * the schema the host declared; `text`, the same in words; whether the surface still takes
34
+ * input, and `onAction` to send what the person did with it, as any block does.
35
+ */
36
+ export interface HostBlockProps<Props = Record<string, unknown>> {
37
+ props: Props;
38
+ text: string;
39
+ active: boolean;
40
+ onAction: (action: SurfaceAction) => void;
41
+ }
42
+ /**
43
+ * The host's own blocks, by the name it declared each with (`PUT /v1/blocks/{name}`):
44
+ * `{ "demoprep.deal-card": DealCard }`. A block of a name it doesn't give shows its words.
45
+ */
46
+ export type HostBlocks = Readonly<Record<string, ComponentType<HostBlockProps<never>>>>;
31
47
  //#endregion
32
48
  //# sourceMappingURL=scope.d.ts.map
@@ -6,6 +6,7 @@ const ScopeContext = createContext({
6
6
  answered: void 0,
7
7
  onAction: () => void 0,
8
8
  components: void 0,
9
+ blocks: void 0,
9
10
  classNames: void 0,
10
11
  files: void 0
11
12
  });
@@ -1 +1 @@
1
- {"version":3,"file":"scope.js","names":[],"sources":["../../src/surface/scope.ts"],"sourcesContent":["import { createContext, useContext, type ComponentType, type ReactNode } from \"react\";\n\nimport type { Block } from \"../blocks\";\nimport { classes } from \"../classes\";\nimport type { KitPart } from \"../kit/context\";\nimport type { FileHost } from \"../kit/uploads\";\nimport type { SurfaceAction } from \"./values\";\n\n/**\n * The surface's own parts, by the class each carries: the blocks that are not a kit primitive,\n * and the form's layout. `classNames` takes these and the kit's (`KitPart`) under the same keys.\n */\nexport type SurfacePart =\n | \"sc-surface\"\n | \"sc-surface__stack\"\n | \"sc-surface__stack--row\"\n | \"sc-surface__divider\"\n | \"sc-surface__text\"\n | \"sc-surface__fields\"\n | \"sc-surface__table\"\n | \"sc-surface__image\"\n | \"sc-surface__media\"\n | \"sc-surface__choice\"\n | \"sc-surface__choice--list\"\n | \"sc-surface__option\"\n | \"sc-surface__option--other\"\n | \"sc-surface__other\"\n | \"sc-surface__form\"\n | \"sc-surface__submit\"\n | \"sc-surface__foot\"\n | \"sc-surface__sent\"\n | \"sc-surface__connect\"\n | \"sc-surface__connect--done\";\n\nexport type SurfaceClassNames = Partial<Record<SurfacePart | KitPart, string>> | undefined;\n\n/**\n * What a host's component for a block type receives: the block itself, whether the surface still\n * takes input, and `onAction` to send what the person did; a container's `children` come drawn.\n */\nexport type BlockProps<Type extends Block[\"type\"]> = Omit<\n Extract<Block, { type: Type }>,\n \"children\"\n> &\n (Extract<Block, { type: Type }> extends { children: Block[] }\n ? { children: ReactNode }\n : unknown) & {\n active: boolean;\n onAction: (action: SurfaceAction) => void;\n };\n\n/** The host's own drawing of a block type, in place of the package's: `{ table: TheirTable }`. */\nexport type SurfaceComponents = { [Type in Block[\"type\"]]?: ComponentType<BlockProps<Type>> };\n\n/** What every block of one surface shares: whether it takes input, what was done on it. */\nexport interface Scope {\n active: boolean;\n /** What the person already did on the surface. */\n answered: SurfaceAction | undefined;\n onAction: (action: SurfaceAction) => void;\n components: SurfaceComponents | undefined;\n classNames: SurfaceClassNames;\n /** Where its file fields' files go and are found; none: they take none. */\n files: FileHost | undefined;\n}\n\nexport const ScopeContext = createContext<Scope>({\n active: false,\n answered: undefined,\n onAction: () => undefined,\n components: undefined,\n classNames: undefined,\n files: undefined,\n});\n\nexport function useScope(): Scope {\n return useContext(ScopeContext);\n}\n\n/** The classes of the surface's own parts, with the host's own under each. */\nexport function useSurfaceParts(): (...parts: SurfacePart[]) => string {\n const { classNames } = useScope();\n return (...parts) => classes(classNames, ...parts);\n}\n"],"mappings":";;;AAkEA,MAAa,eAAe,cAAqB;CAC/C,QAAQ;CACR,UAAU,KAAA;CACV,gBAAgB,KAAA;CAChB,YAAY,KAAA;CACZ,YAAY,KAAA;CACZ,OAAO,KAAA;AACT,CAAC;AAED,SAAgB,WAAkB;CAChC,OAAO,WAAW,YAAY;AAChC;;AAGA,SAAgB,kBAAuD;CACrE,MAAM,EAAE,eAAe,SAAS;CAChC,QAAQ,GAAG,UAAU,QAAQ,YAAY,GAAG,KAAK;AACnD"}
1
+ {"version":3,"file":"scope.js","names":[],"sources":["../../src/surface/scope.ts"],"sourcesContent":["import { createContext, useContext, type ComponentType, type ReactNode } from \"react\";\n\nimport type { Block } from \"../blocks\";\nimport { classes } from \"../classes\";\nimport type { KitPart } from \"../kit/context\";\nimport type { FileHost } from \"../kit/uploads\";\nimport type { SurfaceAction } from \"./values\";\n\n/**\n * The surface's own parts, by the class each carries: the blocks that are not a kit primitive,\n * and the form's layout. `classNames` takes these and the kit's (`KitPart`) under the same keys.\n */\nexport type SurfacePart =\n | \"sc-surface\"\n | \"sc-surface__stack\"\n | \"sc-surface__stack--row\"\n | \"sc-surface__divider\"\n | \"sc-surface__text\"\n | \"sc-surface__fields\"\n | \"sc-surface__table\"\n | \"sc-surface__image\"\n | \"sc-surface__media\"\n | \"sc-surface__choice\"\n | \"sc-surface__choice--list\"\n | \"sc-surface__option\"\n | \"sc-surface__option--other\"\n | \"sc-surface__other\"\n | \"sc-surface__form\"\n | \"sc-surface__submit\"\n | \"sc-surface__foot\"\n | \"sc-surface__sent\"\n | \"sc-surface__connect\"\n | \"sc-surface__connect--done\"\n | \"sc-surface__host\";\n\nexport type SurfaceClassNames = Partial<Record<SurfacePart | KitPart, string>> | undefined;\n\n/**\n * What a host's component for a block type receives: the block itself, whether the surface still\n * takes input, and `onAction` to send what the person did; a container's `children` come drawn.\n */\nexport type BlockProps<Type extends Block[\"type\"]> = Omit<\n Extract<Block, { type: Type }>,\n \"children\"\n> &\n (Extract<Block, { type: Type }> extends { children: Block[] }\n ? { children: ReactNode }\n : unknown) & {\n active: boolean;\n onAction: (action: SurfaceAction) => void;\n };\n\n/** The host's own drawing of a block type, in place of the package's: `{ table: TheirTable }`. */\nexport type SurfaceComponents = { [Type in Block[\"type\"]]?: ComponentType<BlockProps<Type>> };\n\n/**\n * What a host's own block receives (`HostBlocks`): its `props`, as the API checked them against\n * the schema the host declared; `text`, the same in words; whether the surface still takes\n * input, and `onAction` to send what the person did with it, as any block does.\n */\nexport interface HostBlockProps<Props = Record<string, unknown>> {\n props: Props;\n text: string;\n active: boolean;\n onAction: (action: SurfaceAction) => void;\n}\n\n/**\n * The host's own blocks, by the name it declared each with (`PUT /v1/blocks/{name}`):\n * `{ \"demoprep.deal-card\": DealCard }`. A block of a name it doesn't give shows its words.\n */\n// `never`: a component typed for its own props (`HostBlockProps<Deal>`) takes its place.\nexport type HostBlocks = Readonly<Record<string, ComponentType<HostBlockProps<never>>>>;\n\n/** What every block of one surface shares: whether it takes input, what was done on it. */\nexport interface Scope {\n active: boolean;\n /** What the person already did on the surface. */\n answered: SurfaceAction | undefined;\n onAction: (action: SurfaceAction) => void;\n components: SurfaceComponents | undefined;\n /** The host's own blocks, by name. */\n blocks: HostBlocks | undefined;\n classNames: SurfaceClassNames;\n /** Where its file fields' files go and are found; none: they take none. */\n files: FileHost | undefined;\n}\n\nexport const ScopeContext = createContext<Scope>({\n active: false,\n answered: undefined,\n onAction: () => undefined,\n components: undefined,\n blocks: undefined,\n classNames: undefined,\n files: undefined,\n});\n\nexport function useScope(): Scope {\n return useContext(ScopeContext);\n}\n\n/** The classes of the surface's own parts, with the host's own under each. */\nexport function useSurfaceParts(): (...parts: SurfacePart[]) => string {\n const { classNames } = useScope();\n return (...parts) => classes(classNames, ...parts);\n}\n"],"mappings":";;;AAwFA,MAAa,eAAe,cAAqB;CAC/C,QAAQ;CACR,UAAU,KAAA;CACV,gBAAgB,KAAA;CAChB,YAAY,KAAA;CACZ,QAAQ,KAAA;CACR,YAAY,KAAA;CACZ,OAAO,KAAA;AACT,CAAC;AAED,SAAgB,WAAkB;CAChC,OAAO,WAAW,YAAY;AAChC;;AAGA,SAAgB,kBAAuD;CACrE,MAAM,EAAE,eAAe,SAAS;CAChC,QAAQ,GAAG,UAAU,QAAQ,YAAY,GAAG,KAAK;AACnD"}
package/dist/types.d.ts CHANGED
@@ -443,6 +443,18 @@ export interface FileBlock {
443
443
  title?: string;
444
444
  file: Attachment | null;
445
445
  }
446
+ /**
447
+ * An agent's view rendered for one contact (`GET /views/{name}/render`): its blocks as the kit
448
+ * draws them, filled from the rows when it was read, and `text`, the same in words.
449
+ */
450
+ export interface ViewRendered {
451
+ name: string;
452
+ title: string;
453
+ contact_id: string;
454
+ blocks: Surface["blocks"];
455
+ text: string;
456
+ rendered_at: string;
457
+ }
446
458
  /** Who holds the conversation's browser: the agent drives it, or the person does. */
447
459
  export type BrowserControl = "agent" | "person";
448
460
  /** Whose the browser is: a clean one in the cloud, or the owner's own Chrome. */
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","names":[],"sources":["../src/types.ts"],"sourcesContent":["/** The API's objects this package reads (v3/README.md). */\n\nimport type { ChannelKind } from \"./about\";\nimport type { Surface } from \"./blocks\";\n\n/** The channel a conversation is on, as a list draws it. */\nexport interface ChannelGlance {\n id: string;\n kind: ChannelKind;\n /** The number, the @username. */\n name: string;\n}\n\n/** The person a conversation on a channel is with, or a person who signed in to the host's app. */\nexport interface ContactGlance {\n id: string;\n /** As they show it on the channel; null when it doesn't say. */\n name: string | null;\n /** Where they are on it: the number, the Instagram id; their account in the host's app. */\n address: string;\n /** The owner marked them: the agent doesn't answer them; left out by an API from before. */\n muted?: boolean | undefined;\n}\n\n/**\n * Who answers a conversation: its agent; a person of the business (the agent paused in it: it\n * handed it over, or one of them wrote in it); or nobody (it is ignored: what comes is kept, never\n * answered).\n */\nexport type Holder = \"agent\" | \"person\" | \"nobody\";\n\n/** A change of who answers a conversation: to whom, why, who changed it and when. */\nexport interface Handover {\n holder: Holder;\n /** Why, in the words of whoever changed it; \"\" when they said nothing. */\n reason: string;\n /**\n * `owner` (a person of the business), `agent` (its `escalate`), `platform`, or an automation by\n * its file's name.\n */\n by: string;\n /** The automation's title, when one changed it. */\n title: string | null;\n at: string;\n}\n\n/**\n * What was decided of a person's message on a channel before the agent answered it: `deciding`\n * while the automations that decide go; then the agent answers it (`answer`), lets it pass this\n * time (`skip`), or the conversation goes to a person (`hold`) or to nobody (`ignore`).\n */\nexport interface Decision {\n kind: \"deciding\" | \"answer\" | \"skip\" | \"hold\" | \"ignore\";\n /** Why, in the owner's words; null when it says nothing. */\n reason: string | null;\n /** The automation that decided, by its file's name; null when the platform did (a filter, the hours). */\n automation: string | null;\n /** Its title. */\n title: string | null;\n /** Its run that decided. */\n run_id: string | null;\n}\n\n/** A conversation between a person and one agent. */\nexport interface Conversation {\n id: string;\n agent_id: string;\n /** A turn stopped, waiting for the person to answer on a surface. */\n pending: boolean;\n /** Who answers it now: its agent, a person of the business, or nobody. */\n handled_by: Holder;\n /** Its last change of who answers it; null when it never changed, left out by an older API. */\n handover?: Handover | null | undefined;\n /** The owner trying the agent out: no customer sees it, and it is never the agent's activity. */\n test: boolean;\n created_at: string;\n /** Its title in a list: what a person first said in it; null while they've said nothing. */\n title: string | null;\n /** On a channel: which, and the person; null (or left out by an older API) elsewhere. */\n channel?: ChannelGlance | null | undefined;\n contact?: ContactGlance | null | undefined;\n /** On a channel: when the agent's reply is due, once the person has been quiet a moment. */\n reply_due_at?: string | null | undefined;\n /** On a channel: when the person last wrote (WhatsApp's 24 h window counts from it). */\n last_inbound_at?: string | null | undefined;\n /** The call it is, when it is one; null elsewhere, and left out by an API from before calls. */\n call?: CallGlance | null | undefined;\n /**\n * Who it is with, when a person's token or a publishable key started it: a person of the\n * host's app (`host_person`, its `contact` then) or the widget's visitor.\n */\n person?: ConversationPerson | null | undefined;\n /**\n * For the person it is with: how many of the business's messages came since they last read it,\n * and whether it waits on them (a question, their yes); left out by an older API.\n */\n unread?: number | undefined;\n waiting_on_person?: boolean | undefined;\n}\n\n/** Who a person's token or a publishable key started a conversation for. */\nexport interface ConversationPerson {\n kind: \"host_person\" | \"visitor\" | \"contact\" | \"owner\";\n /** The host's id for them, the visitor's id. */\n external_id: string;\n name: string | null;\n email: string | null;\n}\n\n/**\n * Why a call ended, as the API keeps it: the caller hung up, the agent said goodbye, it reached\n * its longest time, it failed, its end never came, or it was never taken.\n */\nexport type CallReason = \"caller\" | \"agent\" | \"max_duration\" | \"error\" | \"lost\" | \"missed\";\n\n/**\n * The call a conversation is (v3/VOICE.md): the owner's in the browser or a phone call, when the\n * agent took it and when it ended, why and how long.\n */\nexport interface CallGlance {\n id: string;\n kind: \"browser\" | \"phone\";\n /** Null while it is on. */\n reason: CallReason | null;\n /** From when the agent took it to when it ended; null while it is on. */\n seconds: number | null;\n started_at: string | null;\n ended_at: string | null;\n /** Whether it was recorded, to play from the conversation; left out by an older API. */\n recording?: boolean | undefined;\n}\n\n/** Who said a message on a channel: the person, the agent, or a person of the business. */\nexport type Author = \"contact\" | \"agent\" | \"operator\";\n\n/** Where a message that goes out on a channel got to: it only moves forward, and `failed` wins. */\nexport type Delivery = \"queued\" | \"sent\" | \"delivered\" | \"read\" | \"failed\";\n\n/** How a channel's account stands, as its provider last said. */\nexport type ChannelStatus = \"pending\" | \"active\" | \"error\" | \"disconnected\";\n\n/** A day of the week, as a channel's hours name it. */\nexport type Weekday = \"mon\" | \"tue\" | \"wed\" | \"thu\" | \"fri\" | \"sat\" | \"sun\";\n\n/** A stretch of a day, from one time to a later one (\"HH:MM\"). */\nexport interface HoursSpan {\n start: string;\n end: string;\n}\n\n/**\n * A week of hours in the agent's time zone: each day's stretches, in order and apart, four at\n * most; a day left out, or empty, is closed.\n */\nexport type WeekHours = Partial<Record<Weekday, HoursSpan[]>>;\n\n/**\n * How the agent behaves on a channel, the same for every text channel (each shows only what its\n * medium can do): when it answers, how what it says goes out, and what it is told there.\n */\nexport interface ChannelSettings {\n /** It answers on this channel; off, everything goes to the inbox for a person. */\n answers: boolean;\n /** Who it answers, in the owner's words; null: everyone. */\n filter: string | null;\n /** Words that, said in a message, have it answer without weighing the filter. */\n filter_keywords: string[];\n /** The week it keeps; null: it answers at any hour. */\n hours: WeekHours | null;\n /** It answers inside the hours, or outside them (the business's people take the hours). */\n answers_when: \"in_hours\" | \"out_of_hours\";\n /** Sent once per conversation while the hours keep it from answering; null: nothing. */\n away_message: string | null;\n /** WhatsApp: it answers in group chats too. */\n groups: boolean;\n /**\n * A conversation a person took over goes back to the agent after this long without them; null:\n * it stays theirs until they give it back.\n */\n auto_release_after_h: number | null;\n /** What it is told on this channel only, besides its own instructions. */\n instructions: string | null;\n /** The quiet period after the person's last message before the agent answers them all. */\n reply_delay_s: number;\n /** A long answer goes in up to three messages as a person writes them, its words as they are. */\n split: boolean;\n /** The channel shows the agent writing between the parts of an answer, where it can. */\n typing: boolean;\n /** WhatsApp, past 24 h since the person last wrote: the template that carries the answer. */\n window_template: string | null;\n /**\n * WhatsApp: the answer as a voice note in the agent's voice, its words kept as what it said;\n * never, when the person's last message was a voice note, or always.\n */\n voice_replies: \"never\" | \"when_voice\" | \"always\";\n}\n\n/**\n * An account on a provider (a WhatsApp number, an Instagram account, an SMS number) and the agent\n * that answers it (`GET /channels?agent=`).\n */\nexport interface Channel {\n id: string;\n agent_id: string;\n kind: \"whatsapp\" | \"instagram\" | \"sms\" | \"phone\" | \"web\";\n /** meta · twilio · livekit · signalcore (the widget) */\n provider: string;\n /** The number, the @username. */\n name: string;\n /** The provider's id for the account. */\n external_id: string;\n /** A phone number's: where its provider sends its calls (a SIP address); null for others. */\n address: string | null;\n /** A phone number's: whether the agent calls out from it (it has the number's SIP login). */\n outbound: boolean;\n status: ChannelStatus;\n /** The provider's word on its status, or what went wrong; null when it said nothing. */\n detail: string | null;\n settings: ChannelSettings;\n /** A web channel's: the widget's publishable key, its sites and its look; null for others. */\n web: ChannelWeb | null;\n created_at: string;\n}\n\n/** The widget a web channel is: the key its line carries, the sites it loads on, its look. */\nexport interface ChannelWeb {\n key: string;\n origins: string[];\n appearance: WidgetLook;\n}\n\nexport type StepState = \"running\" | \"waiting\" | \"done\" | \"failed\";\n\n/**\n * Who gives the yes an action waits for: the person on the screen (the turn stopped for it), or\n * the business (the turn went on; its people allow or decline it from the app, the inbox).\n */\nexport type Decides = \"person\" | \"business\";\n\n/** An action the platform will not run until it is allowed: what, with what input, by whom. */\nexport interface Request {\n action: string;\n input: Record<string, unknown>;\n /** The person's when left out (an API from before it). */\n decides?: Decides | undefined;\n /** The JSON Schema of its input, which an edit given with the yes must fit. */\n schema?: Record<string, unknown> | null | undefined;\n}\n\n/** An action a reply called: what, how it went, and what it drew. */\nexport interface Step {\n id: string;\n action: string;\n state: StepState;\n output: string | null;\n surface: Surface | null;\n /**\n * The turn stopped on it: the person's answer on its surface carries it on. Never a host's tool\n * the page runs, nor a yes the business gives.\n */\n awaits: boolean;\n /** Set while it waits to be allowed: by the person (the turn stopped), or by the business. */\n request: Request | null;\n /** A connected app's action: the app, its logo an https address; absent for the platform's. */\n app?: StepApp | null | undefined;\n}\n\n/** The connected app a step's action belongs to: its name and logo. */\nexport interface StepApp {\n name: string;\n icon: string | null;\n}\n\n/**\n * What a person did on a surface: `surface` is its id, `name` the block's action, `data` what it\n * carries (a pick, a form's values), `label` the words the app shows for it.\n */\nexport interface Action {\n surface: string;\n name: string;\n data: Record<string, unknown>;\n label: string;\n}\n\n/** What is read of a message: who said it, its text, what it did on a surface, its steps. */\nexport interface Message {\n id: string;\n role: \"user\" | \"assistant\";\n text: string;\n /** When the message came from a surface; `text` is then its label. */\n action: Action | null;\n steps: Step[];\n /** The files the person sent with it; an API from before files leaves it out. */\n files?: Attachment[] | undefined;\n /** On a channel, who said it; null elsewhere. A person of the business's is `assistant`. */\n author?: Author | null | undefined;\n /** On a channel, where what goes out got to, and why it failed when it did. */\n delivery?: Delivery | null | undefined;\n delivery_error?: string | null | undefined;\n /** Gone out on a channel in several parts: the words of each, in order; null as one. */\n pieces?: string[] | null | undefined;\n /** Going out on a channel: how many of its parts went so far; null for what doesn't go out. */\n sent_parts?: number | null | undefined;\n /**\n * On a channel, a voice note, the person's or the agent's: its file, played with `text` (what\n * was said) under it; null otherwise, and left out by an API from before voice notes.\n */\n voice?: Attachment | null | undefined;\n /**\n * On a call, a person's message: what they heard of the agent's last words before saying it,\n * when that isn't what was stored (a reply or the greeting they cut short; \"\" for nothing of\n * it); null otherwise, and left out by an API from before calls.\n */\n heard?: string | null | undefined;\n /** On a channel, a person's message: what was decided of it; null otherwise. */\n decision?: Decision | null | undefined;\n /** The agent's words first, without a turn of the person's, and the run whose code sent them. */\n proactive?: boolean | undefined;\n run_id?: string | null | undefined;\n created_at: string;\n}\n\n/**\n * A call with an agent from the browser (the owner's test, `POST /agents/{id}/voice/token`; anyone\n * who may talk to it, a person's as theirs, `POST /agents/{id}/calls`): LiveKit's address, a token\n * to join the call's room (for 10 minutes), and the call and its own conversation, made with it,\n * whose live socket shows what is said.\n */\nexport interface CallToken {\n url: string;\n token: string;\n room: string;\n call_id: string;\n conversation_id: string;\n}\n\n/** A file that arrived in a conversation, as a message carries it. */\nexport interface Attachment {\n id: string;\n name: string;\n media_type: string;\n size: number;\n}\n\n/** Where a file of a conversation plays from, until `expires_at`: a path under the API's root. */\nexport interface FileLink {\n path: string;\n expires_at: string;\n}\n\n/** A conversation's file, as the API stores it (`POST /conversations/{id}/files`). */\nexport interface ConversationFile extends Attachment {\n conversation_id: string;\n created_at: string;\n}\n\n/** A conversation with its messages, in the order they were said. */\nexport interface ConversationDetail extends Conversation {\n messages: Message[];\n /** Every change of who answers it, in order; left out by an API from before them. */\n handovers?: Handover[] | undefined;\n}\n\n/**\n * How far a searchable file's index is: its passages being made, made, or failed; what to know\n * of it (why it failed, what of it can't be searched); its pages without text the model read.\n */\nexport interface FileIndex {\n state: \"indexing\" | \"ready\" | \"failed\";\n detail: string | null;\n scanned: number;\n}\n\n/** A file kept under a name: the organization's, or an agent's own. */\nexport interface StoredFile {\n id: string;\n path: string;\n media_type: string;\n size: number;\n /** Text, Markdown, JSON, YAML or PDF, read by `search_files`; anything else is only kept. */\n searchable: boolean;\n /** Its index, while it is searchable; left out by an API from before it. */\n index?: FileIndex | null | undefined;\n created_at: string;\n}\n\n/**\n * Where a file is, for what reads any of them: the organization's or an agent's own by its path,\n * a conversation's by its id.\n */\nexport type FileAt =\n { path: string } | { agentId: string; path: string } | { conversationId: string; fileId: string };\n\n/** A PDF: the viewer draws the bytes it fetches. Null pages when they can't be counted. */\nexport interface PdfPreview {\n kind: \"pdf\";\n pages: number | null;\n}\n\n/**\n * One sheet: its first row with anything in it as its columns (null for an empty sheet), and the\n * rows under it, the first 500 (an empty row between two as `[]`), each cell as Excel shows it;\n * `total_rows`, every row under its columns.\n */\nexport interface PreviewSheet {\n name: string;\n columns: string[] | null;\n rows: string[][];\n total_rows: number;\n}\n\n/** A spreadsheet's sheets (20 at most), or a CSV as one, named as its file. */\nexport interface SheetPreview {\n kind: \"sheet\";\n sheets: PreviewSheet[];\n /** Rows, columns (50 at most), long cells or sheets were left out. */\n truncated: boolean;\n}\n\n/**\n * A Word file as simple HTML: headings, paragraphs, lists, tables, bold and italic, small\n * pictures as data URLs. Cleaned by the API against an allow-list: nothing in it runs, styles\n * or loads from another address.\n */\nexport interface DocumentPreview {\n kind: \"document\";\n html: string;\n truncated: boolean;\n}\n\n/** A slide: its title (null without one), the words of its other shapes, its notes. */\nexport interface PreviewSlide {\n title: string | null;\n text: string;\n notes: string | null;\n}\n\n/** A deck's slides, in order. */\nexport interface SlidesPreview {\n kind: \"slides\";\n slides: PreviewSlide[];\n truncated: boolean;\n}\n\n/** Words as written: Markdown, plain text, JSON. */\nexport interface TextPreview {\n kind: \"markdown\" | \"text\" | \"json\";\n text: string;\n truncated: boolean;\n}\n\n/** A source as written, never run (HTML too), in the language highlighters name it by. */\nexport interface CodePreview {\n kind: \"code\";\n text: string;\n truncated: boolean;\n language: string;\n}\n\n/** A picture, a video or a sound: the viewer plays the bytes, typed as `media_type`. */\nexport interface MediaPreview {\n kind: \"image\" | \"video\" | \"audio\";\n media_type: string;\n}\n\n/** Nothing to draw: a kind no viewer shows, or a file that can't be read; it is saved. */\nexport interface UnknownPreview {\n kind: \"unknown\";\n}\n\n/**\n * What a viewer draws of a file (`GET …/preview`), by its `kind`. What is too long answers what\n * fits, with `truncated`.\n */\nexport type FilePreview =\n | PdfPreview\n | SheetPreview\n | DocumentPreview\n | SlidesPreview\n | TextPreview\n | CodePreview\n | MediaPreview\n | UnknownPreview;\n\n/**\n * A file the agent shows in a surface (`show`'s `file` block): it names one it may read (`path`:\n * its own or the organization's by path, or the conversation's by id), and the API fills in\n * `file`, the conversation's file it put there (`{conversationId, fileId}` to preview and fetch\n * it); null while there is none (the reply's message before the show ran, or one it refused).\n */\nexport interface FileBlock {\n type: \"file\";\n path: string;\n /** Over it; none: its name. */\n title?: string;\n file: Attachment | null;\n}\n\n/** Who holds the conversation's browser: the agent drives it, or the person does. */\nexport type BrowserControl = \"agent\" | \"person\";\n\n/** Whose the browser is: a clean one in the cloud, or the owner's own Chrome. */\nexport type BrowserWhere = \"hosted\" | \"mine\";\n\n/**\n * The conversation's hosted browser, while it is open: where it is, who holds it, and, when the\n * agent handed it over, why (`reason`) and the step the person's answer carries on (`wait`).\n * `width` and `height` are the page's, the pixels its pointer events are in.\n */\nexport interface BrowserState {\n where: BrowserWhere;\n url: string;\n title: string;\n control: BrowserControl;\n reason: string | null;\n wait: string | null;\n width: number;\n height: number;\n}\n\n/** A picture of the browser's screen: a JPEG in base64, showing the page at this size. */\nexport interface BrowserFrame {\n jpeg: string;\n width: number;\n height: number;\n}\n\n/**\n * What the person does on the browser's screen while they hold it, in the page's pixels: the\n * pointer, the wheel, keys (the DOM's `key`, `code` and `keyCode`; `modifiers` is Alt 1, Ctrl 2,\n * Meta 4, Shift 8) and text pasted.\n */\nexport type BrowserInput =\n | {\n kind: \"mouse\";\n action: \"move\" | \"down\" | \"up\";\n x: number;\n y: number;\n button?: \"left\" | \"middle\" | \"right\";\n clicks?: number;\n }\n | { kind: \"wheel\"; x: number; y: number; dx: number; dy: number }\n | {\n kind: \"key\";\n action: \"down\" | \"up\";\n key: string;\n code: string;\n keyCode: number;\n modifiers: number;\n }\n | { kind: \"paste\"; text: string };\n\n/**\n * What a person may know of the agent they talk to (`GET /agents/{id}/face`): its name, its role\n * in a line, the mark of its work (an `AgentIcon`; null until it picked one) and whether it takes\n * calls.\n */\n/**\n * How a web channel's widget looks (`PUT /channels/{id}/appearance`): each unset field keeps the\n * widget's own default (the page's type and ink, neutral greys). Colours are `#rrggbb`, sizes\n * pixels; `css` is the widget's own stylesheet, drawn inside it after ours.\n */\nexport interface WidgetLook {\n accent?: string | null;\n accent_fg?: string | null;\n font?: WidgetFont | null;\n radius?: number | null;\n theme?: \"auto\" | \"light\" | \"dark\";\n position?: \"right\" | \"left\";\n launcher_size?: number | null;\n panel_width?: number | null;\n panel_height?: number | null;\n header?: boolean;\n css?: string | null;\n}\n\n/** The faces a widget may wear besides the page's own: Google Fonts it loads by name. */\nexport const WIDGET_FONTS = [\n \"Inter\",\n \"Manrope\",\n \"DM Sans\",\n \"Plus Jakarta Sans\",\n \"Poppins\",\n \"Nunito\",\n \"Lora\",\n \"Playfair Display\",\n] as const;\n\nexport type WidgetFont = (typeof WIDGET_FONTS)[number];\n\n/** What the widget reads as it loads, by its publishable key: its agent, and how it looks. */\nexport interface WidgetConfig {\n agent_id: string;\n agent_name: string;\n appearance: WidgetLook;\n}\n\nexport interface AgentFace {\n id: string;\n name: string;\n /** \"\" when it has none. */\n role: string;\n icon: string | null;\n voice: { enabled: boolean };\n}\n\n/**\n * One of the host's own tools the agent called, to run in the page (a tool declared `client` on\n * the agent): the call's id, the tool's name, and what the agent gave it, as its JSON Schema says.\n */\nexport interface ToolCall {\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n"],"mappings":";;AAikBA,MAAa,eAAe;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}
1
+ {"version":3,"file":"types.js","names":[],"sources":["../src/types.ts"],"sourcesContent":["/** The API's objects this package reads (v3/README.md). */\n\nimport type { ChannelKind } from \"./about\";\nimport type { Surface } from \"./blocks\";\n\n/** The channel a conversation is on, as a list draws it. */\nexport interface ChannelGlance {\n id: string;\n kind: ChannelKind;\n /** The number, the @username. */\n name: string;\n}\n\n/** The person a conversation on a channel is with, or a person who signed in to the host's app. */\nexport interface ContactGlance {\n id: string;\n /** As they show it on the channel; null when it doesn't say. */\n name: string | null;\n /** Where they are on it: the number, the Instagram id; their account in the host's app. */\n address: string;\n /** The owner marked them: the agent doesn't answer them; left out by an API from before. */\n muted?: boolean | undefined;\n}\n\n/**\n * Who answers a conversation: its agent; a person of the business (the agent paused in it: it\n * handed it over, or one of them wrote in it); or nobody (it is ignored: what comes is kept, never\n * answered).\n */\nexport type Holder = \"agent\" | \"person\" | \"nobody\";\n\n/** A change of who answers a conversation: to whom, why, who changed it and when. */\nexport interface Handover {\n holder: Holder;\n /** Why, in the words of whoever changed it; \"\" when they said nothing. */\n reason: string;\n /**\n * `owner` (a person of the business), `agent` (its `escalate`), `platform`, or an automation by\n * its file's name.\n */\n by: string;\n /** The automation's title, when one changed it. */\n title: string | null;\n at: string;\n}\n\n/**\n * What was decided of a person's message on a channel before the agent answered it: `deciding`\n * while the automations that decide go; then the agent answers it (`answer`), lets it pass this\n * time (`skip`), or the conversation goes to a person (`hold`) or to nobody (`ignore`).\n */\nexport interface Decision {\n kind: \"deciding\" | \"answer\" | \"skip\" | \"hold\" | \"ignore\";\n /** Why, in the owner's words; null when it says nothing. */\n reason: string | null;\n /** The automation that decided, by its file's name; null when the platform did (a filter, the hours). */\n automation: string | null;\n /** Its title. */\n title: string | null;\n /** Its run that decided. */\n run_id: string | null;\n}\n\n/** A conversation between a person and one agent. */\nexport interface Conversation {\n id: string;\n agent_id: string;\n /** A turn stopped, waiting for the person to answer on a surface. */\n pending: boolean;\n /** Who answers it now: its agent, a person of the business, or nobody. */\n handled_by: Holder;\n /** Its last change of who answers it; null when it never changed, left out by an older API. */\n handover?: Handover | null | undefined;\n /** The owner trying the agent out: no customer sees it, and it is never the agent's activity. */\n test: boolean;\n created_at: string;\n /** Its title in a list: what a person first said in it; null while they've said nothing. */\n title: string | null;\n /** On a channel: which, and the person; null (or left out by an older API) elsewhere. */\n channel?: ChannelGlance | null | undefined;\n contact?: ContactGlance | null | undefined;\n /** On a channel: when the agent's reply is due, once the person has been quiet a moment. */\n reply_due_at?: string | null | undefined;\n /** On a channel: when the person last wrote (WhatsApp's 24 h window counts from it). */\n last_inbound_at?: string | null | undefined;\n /** The call it is, when it is one; null elsewhere, and left out by an API from before calls. */\n call?: CallGlance | null | undefined;\n /**\n * Who it is with, when a person's token or a publishable key started it: a person of the\n * host's app (`host_person`, its `contact` then) or the widget's visitor.\n */\n person?: ConversationPerson | null | undefined;\n /**\n * For the person it is with: how many of the business's messages came since they last read it,\n * and whether it waits on them (a question, their yes); left out by an older API.\n */\n unread?: number | undefined;\n waiting_on_person?: boolean | undefined;\n}\n\n/** Who a person's token or a publishable key started a conversation for. */\nexport interface ConversationPerson {\n kind: \"host_person\" | \"visitor\" | \"contact\" | \"owner\";\n /** The host's id for them, the visitor's id. */\n external_id: string;\n name: string | null;\n email: string | null;\n}\n\n/**\n * Why a call ended, as the API keeps it: the caller hung up, the agent said goodbye, it reached\n * its longest time, it failed, its end never came, or it was never taken.\n */\nexport type CallReason = \"caller\" | \"agent\" | \"max_duration\" | \"error\" | \"lost\" | \"missed\";\n\n/**\n * The call a conversation is (v3/VOICE.md): the owner's in the browser or a phone call, when the\n * agent took it and when it ended, why and how long.\n */\nexport interface CallGlance {\n id: string;\n kind: \"browser\" | \"phone\";\n /** Null while it is on. */\n reason: CallReason | null;\n /** From when the agent took it to when it ended; null while it is on. */\n seconds: number | null;\n started_at: string | null;\n ended_at: string | null;\n /** Whether it was recorded, to play from the conversation; left out by an older API. */\n recording?: boolean | undefined;\n}\n\n/** Who said a message on a channel: the person, the agent, or a person of the business. */\nexport type Author = \"contact\" | \"agent\" | \"operator\";\n\n/** Where a message that goes out on a channel got to: it only moves forward, and `failed` wins. */\nexport type Delivery = \"queued\" | \"sent\" | \"delivered\" | \"read\" | \"failed\";\n\n/** How a channel's account stands, as its provider last said. */\nexport type ChannelStatus = \"pending\" | \"active\" | \"error\" | \"disconnected\";\n\n/** A day of the week, as a channel's hours name it. */\nexport type Weekday = \"mon\" | \"tue\" | \"wed\" | \"thu\" | \"fri\" | \"sat\" | \"sun\";\n\n/** A stretch of a day, from one time to a later one (\"HH:MM\"). */\nexport interface HoursSpan {\n start: string;\n end: string;\n}\n\n/**\n * A week of hours in the agent's time zone: each day's stretches, in order and apart, four at\n * most; a day left out, or empty, is closed.\n */\nexport type WeekHours = Partial<Record<Weekday, HoursSpan[]>>;\n\n/**\n * How the agent behaves on a channel, the same for every text channel (each shows only what its\n * medium can do): when it answers, how what it says goes out, and what it is told there.\n */\nexport interface ChannelSettings {\n /** It answers on this channel; off, everything goes to the inbox for a person. */\n answers: boolean;\n /** Who it answers, in the owner's words; null: everyone. */\n filter: string | null;\n /** Words that, said in a message, have it answer without weighing the filter. */\n filter_keywords: string[];\n /** The week it keeps; null: it answers at any hour. */\n hours: WeekHours | null;\n /** It answers inside the hours, or outside them (the business's people take the hours). */\n answers_when: \"in_hours\" | \"out_of_hours\";\n /** Sent once per conversation while the hours keep it from answering; null: nothing. */\n away_message: string | null;\n /** WhatsApp: it answers in group chats too. */\n groups: boolean;\n /**\n * A conversation a person took over goes back to the agent after this long without them; null:\n * it stays theirs until they give it back.\n */\n auto_release_after_h: number | null;\n /** What it is told on this channel only, besides its own instructions. */\n instructions: string | null;\n /** The quiet period after the person's last message before the agent answers them all. */\n reply_delay_s: number;\n /** A long answer goes in up to three messages as a person writes them, its words as they are. */\n split: boolean;\n /** The channel shows the agent writing between the parts of an answer, where it can. */\n typing: boolean;\n /** WhatsApp, past 24 h since the person last wrote: the template that carries the answer. */\n window_template: string | null;\n /**\n * WhatsApp: the answer as a voice note in the agent's voice, its words kept as what it said;\n * never, when the person's last message was a voice note, or always.\n */\n voice_replies: \"never\" | \"when_voice\" | \"always\";\n}\n\n/**\n * An account on a provider (a WhatsApp number, an Instagram account, an SMS number) and the agent\n * that answers it (`GET /channels?agent=`).\n */\nexport interface Channel {\n id: string;\n agent_id: string;\n kind: \"whatsapp\" | \"instagram\" | \"sms\" | \"phone\" | \"web\";\n /** meta · twilio · livekit · signalcore (the widget) */\n provider: string;\n /** The number, the @username. */\n name: string;\n /** The provider's id for the account. */\n external_id: string;\n /** A phone number's: where its provider sends its calls (a SIP address); null for others. */\n address: string | null;\n /** A phone number's: whether the agent calls out from it (it has the number's SIP login). */\n outbound: boolean;\n status: ChannelStatus;\n /** The provider's word on its status, or what went wrong; null when it said nothing. */\n detail: string | null;\n settings: ChannelSettings;\n /** A web channel's: the widget's publishable key, its sites and its look; null for others. */\n web: ChannelWeb | null;\n created_at: string;\n}\n\n/** The widget a web channel is: the key its line carries, the sites it loads on, its look. */\nexport interface ChannelWeb {\n key: string;\n origins: string[];\n appearance: WidgetLook;\n}\n\nexport type StepState = \"running\" | \"waiting\" | \"done\" | \"failed\";\n\n/**\n * Who gives the yes an action waits for: the person on the screen (the turn stopped for it), or\n * the business (the turn went on; its people allow or decline it from the app, the inbox).\n */\nexport type Decides = \"person\" | \"business\";\n\n/** An action the platform will not run until it is allowed: what, with what input, by whom. */\nexport interface Request {\n action: string;\n input: Record<string, unknown>;\n /** The person's when left out (an API from before it). */\n decides?: Decides | undefined;\n /** The JSON Schema of its input, which an edit given with the yes must fit. */\n schema?: Record<string, unknown> | null | undefined;\n}\n\n/** An action a reply called: what, how it went, and what it drew. */\nexport interface Step {\n id: string;\n action: string;\n state: StepState;\n output: string | null;\n surface: Surface | null;\n /**\n * The turn stopped on it: the person's answer on its surface carries it on. Never a host's tool\n * the page runs, nor a yes the business gives.\n */\n awaits: boolean;\n /** Set while it waits to be allowed: by the person (the turn stopped), or by the business. */\n request: Request | null;\n /** A connected app's action: the app, its logo an https address; absent for the platform's. */\n app?: StepApp | null | undefined;\n}\n\n/** The connected app a step's action belongs to: its name and logo. */\nexport interface StepApp {\n name: string;\n icon: string | null;\n}\n\n/**\n * What a person did on a surface: `surface` is its id, `name` the block's action, `data` what it\n * carries (a pick, a form's values), `label` the words the app shows for it.\n */\nexport interface Action {\n surface: string;\n name: string;\n data: Record<string, unknown>;\n label: string;\n}\n\n/** What is read of a message: who said it, its text, what it did on a surface, its steps. */\nexport interface Message {\n id: string;\n role: \"user\" | \"assistant\";\n text: string;\n /** When the message came from a surface; `text` is then its label. */\n action: Action | null;\n steps: Step[];\n /** The files the person sent with it; an API from before files leaves it out. */\n files?: Attachment[] | undefined;\n /** On a channel, who said it; null elsewhere. A person of the business's is `assistant`. */\n author?: Author | null | undefined;\n /** On a channel, where what goes out got to, and why it failed when it did. */\n delivery?: Delivery | null | undefined;\n delivery_error?: string | null | undefined;\n /** Gone out on a channel in several parts: the words of each, in order; null as one. */\n pieces?: string[] | null | undefined;\n /** Going out on a channel: how many of its parts went so far; null for what doesn't go out. */\n sent_parts?: number | null | undefined;\n /**\n * On a channel, a voice note, the person's or the agent's: its file, played with `text` (what\n * was said) under it; null otherwise, and left out by an API from before voice notes.\n */\n voice?: Attachment | null | undefined;\n /**\n * On a call, a person's message: what they heard of the agent's last words before saying it,\n * when that isn't what was stored (a reply or the greeting they cut short; \"\" for nothing of\n * it); null otherwise, and left out by an API from before calls.\n */\n heard?: string | null | undefined;\n /** On a channel, a person's message: what was decided of it; null otherwise. */\n decision?: Decision | null | undefined;\n /** The agent's words first, without a turn of the person's, and the run whose code sent them. */\n proactive?: boolean | undefined;\n run_id?: string | null | undefined;\n created_at: string;\n}\n\n/**\n * A call with an agent from the browser (the owner's test, `POST /agents/{id}/voice/token`; anyone\n * who may talk to it, a person's as theirs, `POST /agents/{id}/calls`): LiveKit's address, a token\n * to join the call's room (for 10 minutes), and the call and its own conversation, made with it,\n * whose live socket shows what is said.\n */\nexport interface CallToken {\n url: string;\n token: string;\n room: string;\n call_id: string;\n conversation_id: string;\n}\n\n/** A file that arrived in a conversation, as a message carries it. */\nexport interface Attachment {\n id: string;\n name: string;\n media_type: string;\n size: number;\n}\n\n/** Where a file of a conversation plays from, until `expires_at`: a path under the API's root. */\nexport interface FileLink {\n path: string;\n expires_at: string;\n}\n\n/** A conversation's file, as the API stores it (`POST /conversations/{id}/files`). */\nexport interface ConversationFile extends Attachment {\n conversation_id: string;\n created_at: string;\n}\n\n/** A conversation with its messages, in the order they were said. */\nexport interface ConversationDetail extends Conversation {\n messages: Message[];\n /** Every change of who answers it, in order; left out by an API from before them. */\n handovers?: Handover[] | undefined;\n}\n\n/**\n * How far a searchable file's index is: its passages being made, made, or failed; what to know\n * of it (why it failed, what of it can't be searched); its pages without text the model read.\n */\nexport interface FileIndex {\n state: \"indexing\" | \"ready\" | \"failed\";\n detail: string | null;\n scanned: number;\n}\n\n/** A file kept under a name: the organization's, or an agent's own. */\nexport interface StoredFile {\n id: string;\n path: string;\n media_type: string;\n size: number;\n /** Text, Markdown, JSON, YAML or PDF, read by `search_files`; anything else is only kept. */\n searchable: boolean;\n /** Its index, while it is searchable; left out by an API from before it. */\n index?: FileIndex | null | undefined;\n created_at: string;\n}\n\n/**\n * Where a file is, for what reads any of them: the organization's or an agent's own by its path,\n * a conversation's by its id.\n */\nexport type FileAt =\n { path: string } | { agentId: string; path: string } | { conversationId: string; fileId: string };\n\n/** A PDF: the viewer draws the bytes it fetches. Null pages when they can't be counted. */\nexport interface PdfPreview {\n kind: \"pdf\";\n pages: number | null;\n}\n\n/**\n * One sheet: its first row with anything in it as its columns (null for an empty sheet), and the\n * rows under it, the first 500 (an empty row between two as `[]`), each cell as Excel shows it;\n * `total_rows`, every row under its columns.\n */\nexport interface PreviewSheet {\n name: string;\n columns: string[] | null;\n rows: string[][];\n total_rows: number;\n}\n\n/** A spreadsheet's sheets (20 at most), or a CSV as one, named as its file. */\nexport interface SheetPreview {\n kind: \"sheet\";\n sheets: PreviewSheet[];\n /** Rows, columns (50 at most), long cells or sheets were left out. */\n truncated: boolean;\n}\n\n/**\n * A Word file as simple HTML: headings, paragraphs, lists, tables, bold and italic, small\n * pictures as data URLs. Cleaned by the API against an allow-list: nothing in it runs, styles\n * or loads from another address.\n */\nexport interface DocumentPreview {\n kind: \"document\";\n html: string;\n truncated: boolean;\n}\n\n/** A slide: its title (null without one), the words of its other shapes, its notes. */\nexport interface PreviewSlide {\n title: string | null;\n text: string;\n notes: string | null;\n}\n\n/** A deck's slides, in order. */\nexport interface SlidesPreview {\n kind: \"slides\";\n slides: PreviewSlide[];\n truncated: boolean;\n}\n\n/** Words as written: Markdown, plain text, JSON. */\nexport interface TextPreview {\n kind: \"markdown\" | \"text\" | \"json\";\n text: string;\n truncated: boolean;\n}\n\n/** A source as written, never run (HTML too), in the language highlighters name it by. */\nexport interface CodePreview {\n kind: \"code\";\n text: string;\n truncated: boolean;\n language: string;\n}\n\n/** A picture, a video or a sound: the viewer plays the bytes, typed as `media_type`. */\nexport interface MediaPreview {\n kind: \"image\" | \"video\" | \"audio\";\n media_type: string;\n}\n\n/** Nothing to draw: a kind no viewer shows, or a file that can't be read; it is saved. */\nexport interface UnknownPreview {\n kind: \"unknown\";\n}\n\n/**\n * What a viewer draws of a file (`GET …/preview`), by its `kind`. What is too long answers what\n * fits, with `truncated`.\n */\nexport type FilePreview =\n | PdfPreview\n | SheetPreview\n | DocumentPreview\n | SlidesPreview\n | TextPreview\n | CodePreview\n | MediaPreview\n | UnknownPreview;\n\n/**\n * A file the agent shows in a surface (`show`'s `file` block): it names one it may read (`path`:\n * its own or the organization's by path, or the conversation's by id), and the API fills in\n * `file`, the conversation's file it put there (`{conversationId, fileId}` to preview and fetch\n * it); null while there is none (the reply's message before the show ran, or one it refused).\n */\nexport interface FileBlock {\n type: \"file\";\n path: string;\n /** Over it; none: its name. */\n title?: string;\n file: Attachment | null;\n}\n\n/**\n * An agent's view rendered for one contact (`GET /views/{name}/render`): its blocks as the kit\n * draws them, filled from the rows when it was read, and `text`, the same in words.\n */\nexport interface ViewRendered {\n name: string;\n title: string;\n contact_id: string;\n blocks: Surface[\"blocks\"];\n text: string;\n rendered_at: string;\n}\n\n/** Who holds the conversation's browser: the agent drives it, or the person does. */\nexport type BrowserControl = \"agent\" | \"person\";\n\n/** Whose the browser is: a clean one in the cloud, or the owner's own Chrome. */\nexport type BrowserWhere = \"hosted\" | \"mine\";\n\n/**\n * The conversation's hosted browser, while it is open: where it is, who holds it, and, when the\n * agent handed it over, why (`reason`) and the step the person's answer carries on (`wait`).\n * `width` and `height` are the page's, the pixels its pointer events are in.\n */\nexport interface BrowserState {\n where: BrowserWhere;\n url: string;\n title: string;\n control: BrowserControl;\n reason: string | null;\n wait: string | null;\n width: number;\n height: number;\n}\n\n/** A picture of the browser's screen: a JPEG in base64, showing the page at this size. */\nexport interface BrowserFrame {\n jpeg: string;\n width: number;\n height: number;\n}\n\n/**\n * What the person does on the browser's screen while they hold it, in the page's pixels: the\n * pointer, the wheel, keys (the DOM's `key`, `code` and `keyCode`; `modifiers` is Alt 1, Ctrl 2,\n * Meta 4, Shift 8) and text pasted.\n */\nexport type BrowserInput =\n | {\n kind: \"mouse\";\n action: \"move\" | \"down\" | \"up\";\n x: number;\n y: number;\n button?: \"left\" | \"middle\" | \"right\";\n clicks?: number;\n }\n | { kind: \"wheel\"; x: number; y: number; dx: number; dy: number }\n | {\n kind: \"key\";\n action: \"down\" | \"up\";\n key: string;\n code: string;\n keyCode: number;\n modifiers: number;\n }\n | { kind: \"paste\"; text: string };\n\n/**\n * What a person may know of the agent they talk to (`GET /agents/{id}/face`): its name, its role\n * in a line, the mark of its work (an `AgentIcon`; null until it picked one) and whether it takes\n * calls.\n */\n/**\n * How a web channel's widget looks (`PUT /channels/{id}/appearance`): each unset field keeps the\n * widget's own default (the page's type and ink, neutral greys). Colours are `#rrggbb`, sizes\n * pixels; `css` is the widget's own stylesheet, drawn inside it after ours.\n */\nexport interface WidgetLook {\n accent?: string | null;\n accent_fg?: string | null;\n font?: WidgetFont | null;\n radius?: number | null;\n theme?: \"auto\" | \"light\" | \"dark\";\n position?: \"right\" | \"left\";\n launcher_size?: number | null;\n panel_width?: number | null;\n panel_height?: number | null;\n header?: boolean;\n css?: string | null;\n}\n\n/** The faces a widget may wear besides the page's own: Google Fonts it loads by name. */\nexport const WIDGET_FONTS = [\n \"Inter\",\n \"Manrope\",\n \"DM Sans\",\n \"Plus Jakarta Sans\",\n \"Poppins\",\n \"Nunito\",\n \"Lora\",\n \"Playfair Display\",\n] as const;\n\nexport type WidgetFont = (typeof WIDGET_FONTS)[number];\n\n/** What the widget reads as it loads, by its publishable key: its agent, and how it looks. */\nexport interface WidgetConfig {\n agent_id: string;\n agent_name: string;\n appearance: WidgetLook;\n}\n\nexport interface AgentFace {\n id: string;\n name: string;\n /** \"\" when it has none. */\n role: string;\n icon: string | null;\n voice: { enabled: boolean };\n}\n\n/**\n * One of the host's own tools the agent called, to run in the page (a tool declared `client` on\n * the agent): the call's id, the tool's name, and what the agent gave it, as its JSON Schema says.\n */\nexport interface ToolCall {\n id: string;\n name: string;\n input: Record<string, unknown>;\n}\n"],"mappings":";;AA8kBA,MAAa,eAAe;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF"}