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

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 (55) hide show
  1. package/README.md +47 -21
  2. package/dist/AgentAbout.js +6 -2
  3. package/dist/AgentAbout.js.map +1 -1
  4. package/dist/AgentChat.d.ts +7 -1
  5. package/dist/AgentChat.js +154 -2
  6. package/dist/AgentChat.js.map +1 -1
  7. package/dist/AgentSpace.d.ts +12 -3
  8. package/dist/AgentSpace.js +53 -11
  9. package/dist/AgentSpace.js.map +1 -1
  10. package/dist/Threads.d.ts +73 -0
  11. package/dist/Threads.js +140 -0
  12. package/dist/Threads.js.map +1 -0
  13. package/dist/automation/marks.js +7 -3
  14. package/dist/automation/marks.js.map +1 -1
  15. package/dist/automation/messages.d.ts +4 -0
  16. package/dist/automation/messages.js +5 -1
  17. package/dist/automation/messages.js.map +1 -1
  18. package/dist/automation/when.js +8 -0
  19. package/dist/automation/when.js.map +1 -1
  20. package/dist/client.d.ts +14 -4
  21. package/dist/client.js +7 -2
  22. package/dist/client.js.map +1 -1
  23. package/dist/contract.d.ts +9 -4
  24. package/dist/es.d.ts +2 -0
  25. package/dist/es.js +22 -3
  26. package/dist/es.js.map +1 -1
  27. package/dist/frames.d.ts +7 -1
  28. package/dist/frames.js.map +1 -1
  29. package/dist/index.d.ts +5 -4
  30. package/dist/index.js +5 -4
  31. package/dist/surface/Form.js +1 -1
  32. package/dist/types.d.ts +11 -0
  33. package/dist/types.js.map +1 -1
  34. package/dist/useConversation.d.ts +2 -0
  35. package/dist/useConversation.js +16 -0
  36. package/dist/useConversation.js.map +1 -1
  37. package/dist/widget.js +17 -16
  38. package/package.json +1 -1
  39. package/src/AgentAbout.tsx +4 -0
  40. package/src/AgentChat.tsx +203 -1
  41. package/src/AgentSpace.tsx +89 -13
  42. package/src/Threads.tsx +218 -0
  43. package/src/automation/marks.tsx +7 -0
  44. package/src/automation/messages.ts +8 -0
  45. package/src/automation/when.ts +4 -0
  46. package/src/client.ts +26 -10
  47. package/src/contract.ts +240 -26
  48. package/src/es.ts +21 -0
  49. package/src/frames.ts +3 -1
  50. package/src/index.ts +9 -1
  51. package/src/styles.css +191 -0
  52. package/src/types.ts +11 -0
  53. package/src/useConversation.ts +10 -0
  54. package/src/widget/element.tsx +13 -4
  55. package/src/widget/widget.css +13 -0
package/dist/frames.d.ts CHANGED
@@ -70,7 +70,8 @@ export type Frame = {
70
70
  } & BrowserFrame);
71
71
  /**
72
72
  * Up: the person says something (words, files they uploaded to the conversation, or both), acts
73
- * on a surface, or stops the reply on its way; takes the browser or gives it back, and acts on it
73
+ * on a surface (several things at once: a yes or no on each call a reply waits on), or stops
74
+ * the reply on its way; takes the browser or gives it back, and acts on it
74
75
  * while they hold it. And what a tool of the host's answered, run in the page: its output, or
75
76
  * why it failed.
76
77
  */
@@ -81,6 +82,11 @@ export type UpFrame = {
81
82
  } | ({
82
83
  type: "action";
83
84
  } & Action) | {
85
+ type: "actions";
86
+ actions: ({
87
+ type: "action";
88
+ } & Action)[];
89
+ } | {
84
90
  type: "stop";
85
91
  } | {
86
92
  type: "browser.control";
@@ -1 +1 @@
1
- {"version":3,"file":"frames.js","names":[],"sources":["../src/frames.ts"],"sourcesContent":["import type { Surface } from \"./blocks\";\nimport type {\n Action,\n Attachment,\n BrowserControl,\n BrowserFrame,\n BrowserInput,\n BrowserState,\n Decides,\n Decision,\n Handover,\n Holder,\n Message,\n Request,\n Step,\n StepState,\n ToolCall,\n} from \"./types\";\n\n/**\n * The frames of a conversation's socket, as v3/README.md documents them. Down: a message stored;\n * a piece of the reply as it streams; a surface the agent shows (`awaits`: the turn stops until\n * the person acts on it); an action running, told again as its state moves; an action that needs\n * a yes, the person's (the turn stopped) or the business's (`decides`: the turn went on); the\n * conversation handed to a person, and why (the agent stays quiet in it\n * until it is released); the turn over, or stopped by the person; or what went wrong (`code` for\n * the app to word, `detail` for a log). A socket that opens mid-turn is first told the turn so\n * far, from the person's message on. Who answers the conversation, after any change of it (`holder`:\n * who now, and the change); and what was decided of a person's message, when it is stored,\n * settles or is cleared (`decision`, null then). And the conversation's browser: its state, whole, whenever it changes\n * (told at once to a socket that opens), and its screen as it paints. And one of the host's own\n * tools the agent called, for the page to run (`tool`): its step works meanwhile, the turn waits\n * for its `tool_result`, and a person's socket that opens while it waits is told it again.\n */\nexport type Frame =\n | { type: \"working\" }\n | { type: \"message\"; message: Message }\n | { type: \"text\"; delta: string }\n | { type: \"ui\"; id: string; surface: Surface; awaits: boolean }\n | { type: \"step\"; id: string; state: StepState; action?: string; output?: string }\n | ({ type: \"request\"; id: string } & Request)\n | ({ type: \"tool\" } & ToolCall)\n | { type: \"handoff\"; reason: string }\n | { type: \"holder\"; handled_by: Holder; handover: Handover }\n | { type: \"decision\"; message_id: string; decision: Decision | null }\n | { type: \"done\" }\n | { type: \"stopped\" }\n | { type: \"error\"; code: string; detail: string }\n | ({ type: \"browser\"; open: true } & BrowserState)\n | { type: \"browser\"; open: false }\n | ({ type: \"browser.frame\" } & BrowserFrame);\n\n/**\n * Up: the person says something (words, files they uploaded to the conversation, or both), acts\n * on a surface, or stops the reply on its way; takes the browser or gives it back, and acts on it\n * while they hold it. And what a tool of the host's answered, run in the page: its output, or\n * why it failed.\n */\nexport type UpFrame =\n | { type: \"say\"; text: string; files?: string[] }\n | ({ type: \"action\" } & Action)\n | { type: \"stop\" }\n | { type: \"browser.control\"; to: BrowserControl }\n | { type: \"browser.close\" }\n | { type: \"browser.input\"; event: BrowserInput }\n | ToolResult;\n\n/** What a host's tool answered: what it gave back (null for nothing), or why it failed. */\nexport type ToolResult =\n | { type: \"tool_result\"; id: string; output: unknown }\n | { type: \"tool_result\"; id: string; error: string };\n\nconst STATES: ReadonlySet<string> = new Set([\"running\", \"waiting\", \"done\", \"failed\"]);\nconst HOLDERS: ReadonlySet<string> = new Set([\"agent\", \"person\", \"nobody\"]);\nconst DECISIONS: ReadonlySet<string> = new Set([\"deciding\", \"answer\", \"skip\", \"hold\", \"ignore\"]);\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nconst isState = (value: unknown): value is StepState =>\n typeof value === \"string\" && STATES.has(value);\n\n// The blocks inside are the API's, validated at `show`; the renderer draws what it knows.\nconst isSurface = (value: unknown): value is Surface =>\n isRecord(value) && Array.isArray(value.blocks) && typeof value.text === \"string\";\n\nconst isDecides = (value: unknown): value is Decides => value === \"person\" || value === \"business\";\n\nconst isRequest = (value: unknown): value is Request =>\n isRecord(value) &&\n typeof value.action === \"string\" &&\n isRecord(value.input) &&\n (value.decides === undefined || isDecides(value.decides));\n\nconst isStep = (value: unknown): value is Step =>\n isRecord(value) &&\n typeof value.id === \"string\" &&\n typeof value.action === \"string\" &&\n isState(value.state) &&\n (value.output === null || typeof value.output === \"string\") &&\n (value.surface === null || isSurface(value.surface)) &&\n typeof value.awaits === \"boolean\" &&\n (value.request === null || isRequest(value.request));\n\nconst isSize = (value: Record<string, unknown>): boolean =>\n typeof value.width === \"number\" && typeof value.height === \"number\";\n\nconst orNull = (value: unknown): string | null => (typeof value === \"string\" ? value : null);\n\nconst isHolder = (value: unknown): value is Holder =>\n typeof value === \"string\" && HOLDERS.has(value);\n\n/** A change of who answers as told, or null when it is not one: a reason or title left out is none. */\nfunction handoverOf(value: unknown): Handover | null {\n if (!isRecord(value) || !isHolder(value.holder)) return null;\n if (typeof value.by !== \"string\" || typeof value.at !== \"string\") return null;\n const { holder, by, at } = value;\n return { holder, reason: orNull(value.reason) ?? \"\", by, title: orNull(value.title), at };\n}\n\n/** A message's decision as told, or null when it is not one; what it leaves out is none. */\nfunction decisionOf(value: unknown): Decision | null {\n if (!isRecord(value) || typeof value.kind !== \"string\" || !DECISIONS.has(value.kind)) return null;\n return {\n kind: value.kind as Decision[\"kind\"],\n reason: orNull(value.reason),\n automation: orNull(value.automation),\n title: orNull(value.title),\n run_id: orNull(value.run_id),\n };\n}\n\n/** The browser's state as told, or null when it is not one this package can draw. */\nfunction browserOf(frame: Record<string, unknown>): BrowserState | null {\n const { url, title, control } = frame;\n if (typeof url !== \"string\" || typeof title !== \"string\" || !isSize(frame)) return null;\n if (control !== \"agent\" && control !== \"person\") return null;\n return {\n where: frame.where === \"mine\" ? \"mine\" : \"hosted\",\n url,\n title,\n control,\n reason: orNull(frame.reason),\n wait: orNull(frame.wait),\n width: frame.width as number,\n height: frame.height as number,\n };\n}\n\nconst isAction = (value: unknown): value is Action =>\n isRecord(value) &&\n typeof value.surface === \"string\" &&\n typeof value.name === \"string\" &&\n isRecord(value.data) &&\n typeof value.label === \"string\";\n\nconst isAttachment = (value: unknown): value is Attachment =>\n isRecord(value) &&\n typeof value.id === \"string\" &&\n typeof value.name === \"string\" &&\n typeof value.media_type === \"string\" &&\n typeof value.size === \"number\";\n\nconst isMessage = (value: unknown): value is Message =>\n isRecord(value) &&\n typeof value.id === \"string\" &&\n (value.role === \"user\" || value.role === \"assistant\") &&\n typeof value.text === \"string\" &&\n (value.action === null || isAction(value.action)) &&\n Array.isArray(value.steps) &&\n value.steps.every(isStep) &&\n (value.files === undefined || (Array.isArray(value.files) && value.files.every(isAttachment))) &&\n typeof value.created_at === \"string\";\n\n/** The most files one message carries. */\nexport const FILES_PER_MESSAGE = 10;\n\n/**\n * What saying something sends: the words trimmed, and the ids of the files uploaded for it\n * beside them (only when there are); null when there is neither.\n */\nexport function sayOf(text: string, files: readonly string[] = []): UpFrame | null {\n const words = text.trim();\n if (words === \"\" && files.length === 0) return null;\n return files.length === 0\n ? { type: \"say\", text: words }\n : { type: \"say\", text: words, files: [...files] };\n}\n\n/** The most of a tool's error the API takes: the agent reads the rest of it as cut. */\nexport const TOOL_ERROR_MAX = 2000;\n\n/**\n * What a host's tool call answers up, from how its promise settled: what it gave back (`null` for\n * nothing, which JSON would leave out), or the reason it threw in words (an error's message; its\n * kind when it says nothing), as much of it as the API takes.\n */\nexport function toolResultOf(id: string, settled: PromiseSettledResult<unknown>): ToolResult {\n if (settled.status === \"fulfilled\") {\n return { type: \"tool_result\", id, output: settled.value ?? null };\n }\n const reason: unknown = settled.reason;\n const words = (reason instanceof Error ? reason.message : String(reason)).trim();\n const error = words || (reason instanceof Error ? reason.name : \"Error\");\n return { type: \"tool_result\", id, error: error.slice(0, TOOL_ERROR_MAX) };\n}\n\n/**\n * One frame, read without trusting it. Kinds this package does not know yet (more will come:\n * `audio`) and anything malformed are null, to be let pass.\n */\nexport function frameOf(raw: unknown): Frame | null {\n if (typeof raw !== \"string\") return null;\n let frame: unknown;\n try {\n frame = JSON.parse(raw);\n } catch {\n return null;\n }\n if (!isRecord(frame)) return null;\n const { id, action, output } = frame;\n if (frame.type === \"message\" && isMessage(frame.message)) {\n return { type: \"message\", message: frame.message };\n }\n if (frame.type === \"text\" && typeof frame.delta === \"string\") {\n return { type: \"text\", delta: frame.delta };\n }\n if (frame.type === \"ui\" && typeof id === \"string\" && isSurface(frame.surface)) {\n return { type: \"ui\", id, surface: frame.surface, awaits: frame.awaits === true };\n }\n if (frame.type === \"step\" && typeof id === \"string\" && isState(frame.state)) {\n return {\n type: \"step\",\n id,\n state: frame.state,\n ...(typeof action === \"string\" ? { action } : {}),\n ...(typeof output === \"string\" ? { output } : {}),\n };\n }\n if (\n frame.type === \"request\" &&\n typeof id === \"string\" &&\n typeof action === \"string\" &&\n isRecord(frame.input)\n ) {\n // Left out by an API from before it: the person on the screen gave every yes then.\n const decides = isDecides(frame.decides) ? frame.decides : \"person\";\n return { type: \"request\", id, action, input: frame.input, decides };\n }\n if (\n frame.type === \"tool\" &&\n typeof id === \"string\" &&\n typeof frame.name === \"string\" &&\n isRecord(frame.input)\n ) {\n return { type: \"tool\", id, name: frame.name, input: frame.input };\n }\n if (frame.type === \"handoff\" && typeof frame.reason === \"string\") {\n return { type: \"handoff\", reason: frame.reason };\n }\n if (frame.type === \"holder\" && isHolder(frame.handled_by)) {\n const handover = handoverOf(frame.handover);\n return handover && { type: \"holder\", handled_by: frame.handled_by, handover };\n }\n if (frame.type === \"decision\" && typeof frame.message_id === \"string\") {\n const { message_id } = frame;\n if (frame.decision === null) return { type: \"decision\", message_id, decision: null };\n const decision = decisionOf(frame.decision);\n return decision && { type: \"decision\", message_id, decision };\n }\n if (frame.type === \"browser\") {\n if (frame.open === false) return { type: \"browser\", open: false };\n const browser = frame.open === true ? browserOf(frame) : null;\n return browser && { type: \"browser\", open: true, ...browser };\n }\n if (frame.type === \"browser.frame\" && typeof frame.jpeg === \"string\" && isSize(frame)) {\n const { jpeg, width, height } = frame as { jpeg: string; width: number; height: number };\n return { type: \"browser.frame\", jpeg, width, height };\n }\n if (frame.type === \"working\" || frame.type === \"done\" || frame.type === \"stopped\") {\n return { type: frame.type };\n }\n if (\n frame.type === \"error\" &&\n typeof frame.code === \"string\" &&\n typeof frame.detail === \"string\"\n ) {\n return { type: \"error\", code: frame.code, detail: frame.detail };\n }\n return null;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"frames.js","names":[],"sources":["../src/frames.ts"],"sourcesContent":["import type { Surface } from \"./blocks\";\nimport type {\n Action,\n Attachment,\n BrowserControl,\n BrowserFrame,\n BrowserInput,\n BrowserState,\n Decides,\n Decision,\n Handover,\n Holder,\n Message,\n Request,\n Step,\n StepState,\n ToolCall,\n} from \"./types\";\n\n/**\n * The frames of a conversation's socket, as v3/README.md documents them. Down: a message stored;\n * a piece of the reply as it streams; a surface the agent shows (`awaits`: the turn stops until\n * the person acts on it); an action running, told again as its state moves; an action that needs\n * a yes, the person's (the turn stopped) or the business's (`decides`: the turn went on); the\n * conversation handed to a person, and why (the agent stays quiet in it\n * until it is released); the turn over, or stopped by the person; or what went wrong (`code` for\n * the app to word, `detail` for a log). A socket that opens mid-turn is first told the turn so\n * far, from the person's message on. Who answers the conversation, after any change of it (`holder`:\n * who now, and the change); and what was decided of a person's message, when it is stored,\n * settles or is cleared (`decision`, null then). And the conversation's browser: its state, whole, whenever it changes\n * (told at once to a socket that opens), and its screen as it paints. And one of the host's own\n * tools the agent called, for the page to run (`tool`): its step works meanwhile, the turn waits\n * for its `tool_result`, and a person's socket that opens while it waits is told it again.\n */\nexport type Frame =\n | { type: \"working\" }\n | { type: \"message\"; message: Message }\n | { type: \"text\"; delta: string }\n | { type: \"ui\"; id: string; surface: Surface; awaits: boolean }\n | { type: \"step\"; id: string; state: StepState; action?: string; output?: string }\n | ({ type: \"request\"; id: string } & Request)\n | ({ type: \"tool\" } & ToolCall)\n | { type: \"handoff\"; reason: string }\n | { type: \"holder\"; handled_by: Holder; handover: Handover }\n | { type: \"decision\"; message_id: string; decision: Decision | null }\n | { type: \"done\" }\n | { type: \"stopped\" }\n | { type: \"error\"; code: string; detail: string }\n | ({ type: \"browser\"; open: true } & BrowserState)\n | { type: \"browser\"; open: false }\n | ({ type: \"browser.frame\" } & BrowserFrame);\n\n/**\n * Up: the person says something (words, files they uploaded to the conversation, or both), acts\n * on a surface (several things at once: a yes or no on each call a reply waits on), or stops\n * the reply on its way; takes the browser or gives it back, and acts on it\n * while they hold it. And what a tool of the host's answered, run in the page: its output, or\n * why it failed.\n */\nexport type UpFrame =\n | { type: \"say\"; text: string; files?: string[] }\n | ({ type: \"action\" } & Action)\n | { type: \"actions\"; actions: ({ type: \"action\" } & Action)[] }\n | { type: \"stop\" }\n | { type: \"browser.control\"; to: BrowserControl }\n | { type: \"browser.close\" }\n | { type: \"browser.input\"; event: BrowserInput }\n | ToolResult;\n\n/** What a host's tool answered: what it gave back (null for nothing), or why it failed. */\nexport type ToolResult =\n | { type: \"tool_result\"; id: string; output: unknown }\n | { type: \"tool_result\"; id: string; error: string };\n\nconst STATES: ReadonlySet<string> = new Set([\"running\", \"waiting\", \"done\", \"failed\"]);\nconst HOLDERS: ReadonlySet<string> = new Set([\"agent\", \"person\", \"nobody\"]);\nconst DECISIONS: ReadonlySet<string> = new Set([\"deciding\", \"answer\", \"skip\", \"hold\", \"ignore\"]);\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null;\n\nconst isState = (value: unknown): value is StepState =>\n typeof value === \"string\" && STATES.has(value);\n\n// The blocks inside are the API's, validated at `show`; the renderer draws what it knows.\nconst isSurface = (value: unknown): value is Surface =>\n isRecord(value) && Array.isArray(value.blocks) && typeof value.text === \"string\";\n\nconst isDecides = (value: unknown): value is Decides => value === \"person\" || value === \"business\";\n\nconst isRequest = (value: unknown): value is Request =>\n isRecord(value) &&\n typeof value.action === \"string\" &&\n isRecord(value.input) &&\n (value.decides === undefined || isDecides(value.decides));\n\nconst isStep = (value: unknown): value is Step =>\n isRecord(value) &&\n typeof value.id === \"string\" &&\n typeof value.action === \"string\" &&\n isState(value.state) &&\n (value.output === null || typeof value.output === \"string\") &&\n (value.surface === null || isSurface(value.surface)) &&\n typeof value.awaits === \"boolean\" &&\n (value.request === null || isRequest(value.request));\n\nconst isSize = (value: Record<string, unknown>): boolean =>\n typeof value.width === \"number\" && typeof value.height === \"number\";\n\nconst orNull = (value: unknown): string | null => (typeof value === \"string\" ? value : null);\n\nconst isHolder = (value: unknown): value is Holder =>\n typeof value === \"string\" && HOLDERS.has(value);\n\n/** A change of who answers as told, or null when it is not one: a reason or title left out is none. */\nfunction handoverOf(value: unknown): Handover | null {\n if (!isRecord(value) || !isHolder(value.holder)) return null;\n if (typeof value.by !== \"string\" || typeof value.at !== \"string\") return null;\n const { holder, by, at } = value;\n return { holder, reason: orNull(value.reason) ?? \"\", by, title: orNull(value.title), at };\n}\n\n/** A message's decision as told, or null when it is not one; what it leaves out is none. */\nfunction decisionOf(value: unknown): Decision | null {\n if (!isRecord(value) || typeof value.kind !== \"string\" || !DECISIONS.has(value.kind)) return null;\n return {\n kind: value.kind as Decision[\"kind\"],\n reason: orNull(value.reason),\n automation: orNull(value.automation),\n title: orNull(value.title),\n run_id: orNull(value.run_id),\n };\n}\n\n/** The browser's state as told, or null when it is not one this package can draw. */\nfunction browserOf(frame: Record<string, unknown>): BrowserState | null {\n const { url, title, control } = frame;\n if (typeof url !== \"string\" || typeof title !== \"string\" || !isSize(frame)) return null;\n if (control !== \"agent\" && control !== \"person\") return null;\n return {\n where: frame.where === \"mine\" ? \"mine\" : \"hosted\",\n url,\n title,\n control,\n reason: orNull(frame.reason),\n wait: orNull(frame.wait),\n width: frame.width as number,\n height: frame.height as number,\n };\n}\n\nconst isAction = (value: unknown): value is Action =>\n isRecord(value) &&\n typeof value.surface === \"string\" &&\n typeof value.name === \"string\" &&\n isRecord(value.data) &&\n typeof value.label === \"string\";\n\nconst isAttachment = (value: unknown): value is Attachment =>\n isRecord(value) &&\n typeof value.id === \"string\" &&\n typeof value.name === \"string\" &&\n typeof value.media_type === \"string\" &&\n typeof value.size === \"number\";\n\nconst isMessage = (value: unknown): value is Message =>\n isRecord(value) &&\n typeof value.id === \"string\" &&\n (value.role === \"user\" || value.role === \"assistant\") &&\n typeof value.text === \"string\" &&\n (value.action === null || isAction(value.action)) &&\n Array.isArray(value.steps) &&\n value.steps.every(isStep) &&\n (value.files === undefined || (Array.isArray(value.files) && value.files.every(isAttachment))) &&\n typeof value.created_at === \"string\";\n\n/** The most files one message carries. */\nexport const FILES_PER_MESSAGE = 10;\n\n/**\n * What saying something sends: the words trimmed, and the ids of the files uploaded for it\n * beside them (only when there are); null when there is neither.\n */\nexport function sayOf(text: string, files: readonly string[] = []): UpFrame | null {\n const words = text.trim();\n if (words === \"\" && files.length === 0) return null;\n return files.length === 0\n ? { type: \"say\", text: words }\n : { type: \"say\", text: words, files: [...files] };\n}\n\n/** The most of a tool's error the API takes: the agent reads the rest of it as cut. */\nexport const TOOL_ERROR_MAX = 2000;\n\n/**\n * What a host's tool call answers up, from how its promise settled: what it gave back (`null` for\n * nothing, which JSON would leave out), or the reason it threw in words (an error's message; its\n * kind when it says nothing), as much of it as the API takes.\n */\nexport function toolResultOf(id: string, settled: PromiseSettledResult<unknown>): ToolResult {\n if (settled.status === \"fulfilled\") {\n return { type: \"tool_result\", id, output: settled.value ?? null };\n }\n const reason: unknown = settled.reason;\n const words = (reason instanceof Error ? reason.message : String(reason)).trim();\n const error = words || (reason instanceof Error ? reason.name : \"Error\");\n return { type: \"tool_result\", id, error: error.slice(0, TOOL_ERROR_MAX) };\n}\n\n/**\n * One frame, read without trusting it. Kinds this package does not know yet (more will come:\n * `audio`) and anything malformed are null, to be let pass.\n */\nexport function frameOf(raw: unknown): Frame | null {\n if (typeof raw !== \"string\") return null;\n let frame: unknown;\n try {\n frame = JSON.parse(raw);\n } catch {\n return null;\n }\n if (!isRecord(frame)) return null;\n const { id, action, output } = frame;\n if (frame.type === \"message\" && isMessage(frame.message)) {\n return { type: \"message\", message: frame.message };\n }\n if (frame.type === \"text\" && typeof frame.delta === \"string\") {\n return { type: \"text\", delta: frame.delta };\n }\n if (frame.type === \"ui\" && typeof id === \"string\" && isSurface(frame.surface)) {\n return { type: \"ui\", id, surface: frame.surface, awaits: frame.awaits === true };\n }\n if (frame.type === \"step\" && typeof id === \"string\" && isState(frame.state)) {\n return {\n type: \"step\",\n id,\n state: frame.state,\n ...(typeof action === \"string\" ? { action } : {}),\n ...(typeof output === \"string\" ? { output } : {}),\n };\n }\n if (\n frame.type === \"request\" &&\n typeof id === \"string\" &&\n typeof action === \"string\" &&\n isRecord(frame.input)\n ) {\n // Left out by an API from before it: the person on the screen gave every yes then.\n const decides = isDecides(frame.decides) ? frame.decides : \"person\";\n return { type: \"request\", id, action, input: frame.input, decides };\n }\n if (\n frame.type === \"tool\" &&\n typeof id === \"string\" &&\n typeof frame.name === \"string\" &&\n isRecord(frame.input)\n ) {\n return { type: \"tool\", id, name: frame.name, input: frame.input };\n }\n if (frame.type === \"handoff\" && typeof frame.reason === \"string\") {\n return { type: \"handoff\", reason: frame.reason };\n }\n if (frame.type === \"holder\" && isHolder(frame.handled_by)) {\n const handover = handoverOf(frame.handover);\n return handover && { type: \"holder\", handled_by: frame.handled_by, handover };\n }\n if (frame.type === \"decision\" && typeof frame.message_id === \"string\") {\n const { message_id } = frame;\n if (frame.decision === null) return { type: \"decision\", message_id, decision: null };\n const decision = decisionOf(frame.decision);\n return decision && { type: \"decision\", message_id, decision };\n }\n if (frame.type === \"browser\") {\n if (frame.open === false) return { type: \"browser\", open: false };\n const browser = frame.open === true ? browserOf(frame) : null;\n return browser && { type: \"browser\", open: true, ...browser };\n }\n if (frame.type === \"browser.frame\" && typeof frame.jpeg === \"string\" && isSize(frame)) {\n const { jpeg, width, height } = frame as { jpeg: string; width: number; height: number };\n return { type: \"browser.frame\", jpeg, width, height };\n }\n if (frame.type === \"working\" || frame.type === \"done\" || frame.type === \"stopped\") {\n return { type: frame.type };\n }\n if (\n frame.type === \"error\" &&\n typeof frame.code === \"string\" &&\n typeof frame.detail === \"string\"\n ) {\n return { type: \"error\", code: frame.code, detail: frame.detail };\n }\n return null;\n}\n"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { About, AboutOut, AboutState, ActionFact, AskFact, AutomationFact, Autom
3
3
  import { Automation as Automation$1, AutomationState, AutomationView, Board, Run, RunBy, RunRecord, RunStatus, RunStep, Step, Task, Trigger, Use, taskCard } from "./automation/types.js";
4
4
  import { Credentials, Speaker, VISITOR_KEY } from "./credentials.js";
5
5
  import { AutomationBlock, Block, ButtonBlock, CardBlock, ChartBlock, ChartPoint, ChoiceBlock, DividerBlock, Entry, FieldKind, FieldValue, FieldsBlock, FormBlock, FormField, ImageBlock, ListBlock, NoteBlock, Option, StackBlock, StatBlock, Surface as Surface$1, TableBlock, TextBlock, Tone } from "./blocks.js";
6
- import { Action, AgentFace, Attachment, Author, BrowserControl, BrowserFrame, BrowserInput, BrowserState, BrowserWhere, CallGlance, CallReason, CallToken, Channel, ChannelGlance, ChannelSettings, ChannelStatus, ChannelWeb, ContactGlance, Conversation, ConversationDetail, ConversationFile, ConversationPerson, Decides, Decision, Delivery, FileAt, FileBlock, FileIndex, FilePreview, Handover, Holder, HoursSpan, Message, Request, Step as Step$1, StepApp, StepState, StoredFile, ToolCall, WIDGET_FONTS, WeekHours, Weekday, WidgetConfig, WidgetFont, WidgetLook } from "./types.js";
6
+ import { Action, AgentFace, Attachment, Author, BrowserControl, BrowserFrame, BrowserInput, BrowserState, BrowserWhere, CallGlance, CallReason, CallToken, Channel, ChannelGlance, ChannelSettings, ChannelStatus, ChannelWeb, ContactGlance, ConversationDetail, ConversationFile, ConversationPerson, Decides, Decision, Delivery, FileAt, FileBlock, FileIndex, FilePreview, Handover, Holder, HoursSpan, Message, Request, Step as Step$1, StepApp, StepState, StoredFile, ToolCall, WIDGET_FONTS, WeekHours, Weekday, WidgetConfig, WidgetFont, WidgetLook } from "./types.js";
7
7
  import { ApiError, Client, ClientOptions, Files, UploadOptions, createClient } from "./client.js";
8
8
  import { AUTOMATION_MESSAGES, AutomationMessages, CallMessages, DayRef, Verb } from "./automation/messages.js";
9
9
  import { KIT_MESSAGES, KitLocale, KitMessages } from "./kit/messages.js";
@@ -16,7 +16,6 @@ import { Cron, Wall, fires, occurrences, offsetOf, parseCron } from "./automatio
16
16
  import { When, clockOf, dayRefOf, lineOf, momentOf, scheduleOf, timeOf, tookOf, whenOf } from "./automation/when.js";
17
17
  import { CallLine, Names, StepGroup, appOf, callWords, groupsOf, namingOf, verbOf } from "./automation/record.js";
18
18
  import { AgentTasks, AgentTasksProps, TASKS_POLL_MS, TASK_MESSAGES, TaskMessages, TaskPart, useTasks } from "./AgentTasks.js";
19
- import { AgentCard, AgentCardProps, CardField, CardPart } from "./AgentCard.js";
20
19
  import { FILES_PER_MESSAGE, Frame, TOOL_ERROR_MAX, ToolResult, UpFrame, toolResultOf } from "./frames.js";
21
20
  import { LiveConversation, NO_TOOL, ToolHandler, useConversation } from "./useConversation.js";
22
21
  import { BROWSER_MESSAGES, BrowserMessages, BrowserPart, BrowserView, BrowserViewProps } from "./BrowserView.js";
@@ -25,6 +24,8 @@ import { FileFamily, FileHost, MAX_MB, Uploader, accepts, familyOf } from "./kit
25
24
  import { SurfaceAction, Values, chosen, filled, labelOf, picked, pressed, problemOf } from "./surface/values.js";
26
25
  import { BlockProps, SurfaceComponents, SurfacePart } from "./surface/scope.js";
27
26
  import { AgentChat, AgentChatProps, CHAT_MESSAGES, ChatCompose, ChatLook, ChatMessages, ChatPart, ChatSteps, HandoverBy } from "./AgentChat.js";
27
+ import { Conversation, ConversationProps, THREADS_POLL_MS, THREAD_MESSAGES, ThreadMessages, ThreadPart, Threads, ThreadsProps, Unread, useUnread } from "./Threads.js";
28
+ import { AgentCard, AgentCardProps, CardField, CardPart } from "./AgentCard.js";
28
29
  import { ModeMessages, ModePart, SpaceMode } from "./Modes.js";
29
30
  import { AgentTint, agentTint } from "./tint.js";
30
31
  import { ORB_STYLES, OrbProps, OrbState, OrbStyle } from "./voice/orbs.js";
@@ -32,7 +33,7 @@ import { AgentActivity, CallEnd, CallEndedBy, CallLook, CallProblem, CallState,
32
33
  import { Call, CallJoin, CallMeter, useCall } from "./useCall.js";
33
34
  import { VOICE_CALL_MESSAGES, VoiceCall, VoiceCallMessages, VoiceCallPart, VoiceCallProps } from "./VoiceCall.js";
34
35
  import { AgentSpace, AgentSpaceProps, SPACE_MESSAGES, SpaceLayout, SpaceMessages, SpacePart, captionsOf } from "./AgentSpace.js";
35
- import { AUTOMATION_MESSAGES_ES, BROWSER_MESSAGES_ES, CHAT_MESSAGES_ES, KIT_MESSAGES_ES, SPACE_MESSAGES_ES, TASK_MESSAGES_ES, VOICE_CALL_MESSAGES_ES } from "./es.js";
36
+ import { AUTOMATION_MESSAGES_ES, BROWSER_MESSAGES_ES, CHAT_MESSAGES_ES, KIT_MESSAGES_ES, SPACE_MESSAGES_ES, TASK_MESSAGES_ES, THREAD_MESSAGES_ES, VOICE_CALL_MESSAGES_ES } from "./es.js";
36
37
  import { Orb } from "./voice/Orb.js";
37
38
  import { FILE_MESSAGES, FileMessages, FilePart, FileView, FileViewProps } from "./FileView.js";
38
39
  import { Preview, cleanDocument, previewOf } from "./files.js";
@@ -60,4 +61,4 @@ import { DateTimeField, DateTimeFieldProps, TimeField, TimeFieldProps } from "./
60
61
  import { Surface, SurfaceProps } from "./surface/Surface.js";
61
62
  import { FaceRead, useAgentFace } from "./useAgentFace.js";
62
63
  import { Live, LiveHandlers, useLive } from "./useLive.js";
63
- export { ABOUT_HOME, ABOUT_MESSAGES, AGENT_ICONS, AUTOMATION_MESSAGES, AUTOMATION_MESSAGES_ES, type About, type AboutControls, type AboutMessages, type AboutOut, type AboutPart, type AboutState, type AboutTools, type AboutView, type Action, type ActionFact, AgentAbout, type AgentAboutProps, type AgentActivity, AgentCard, type AgentCardProps, AgentChat, type AgentChatProps, type AgentFace, type AgentIcon, AgentSpace, type AgentSpaceProps, AgentTasks, type AgentTasksProps, type AgentTint, ApiError, type AppDirectory, type AskFact, type Attachment, AudioPlayer, type AudioPlayerProps, type Author, Automation, type AutomationBlock, type Automation$1 as AutomationData, type AutomationFact, type AutomationKind, type AutomationMessages, type AutomationProps, type AutomationState, type Step as AutomationStep, type AutomationView, BROWSER_MESSAGES, BROWSER_MESSAGES_ES, type Block, type BlockProps, type Board, type BrowserControl, type BrowserFrame, type BrowserInput, type BrowserMessages, type BrowserPart, type BrowserState, BrowserView, type BrowserViewProps, type BrowserWhere, Button, type ButtonBlock, type ButtonProps, CHAT_MESSAGES, CHAT_MESSAGES_ES, type Call, type CallEnd, type CallEndedBy, type CallGlance, type CallJoin, type CallLine, type CallLook, type CallMessages, type CallMeter, type CallProblem, type CallReason, type CallState, type CallToken, Card, type CardBlock, type CardField, type CardPart, type Channel, type ChannelFact, type ChannelGlance, type ChannelKind, type ChannelSettings, type ChannelStatus, type ChannelWeb, type ChartBlock, type ChartPoint, type ChatCompose, type ChatLook, type ChatMessages, type ChatPart, type ChatSteps, Checkbox, Chips, type ChoiceBlock, Choices, type Client, type ClientOptions, Combobox, type ComboboxProps, type ConnectionFact, type ContactGlance, type ControlBase, type Conversation, type ConversationDetail, type ConversationFile, type ConversationPerson, type Credentials, type Cron, type DataFact, DateField, type DateFieldProps, DateTimeField, type DateTimeFieldProps, type DayRef, type Decides, type Decision, type Delivery, type DeviceFact, type DeviceKind, type Dictate, type Dictation, type DividerBlock, type Does, type Entry, FILES_PER_MESSAGE, FILE_MESSAGES, type FaceRead, type Facts, Field, type FieldIds, type FieldKind, type FieldValue, type FieldsBlock, type FileAt, type FileBlock, FileChip, type FileChipProps, FileChips, type FileFact, type FileFamily, FileField, type FileFieldProps, type FileHost, type FileIndex, FileMark, type FileMessages, type FilePart, type FilePreview, FileView, type FileViewProps, type Files, type FormBlock, type FormField, type Frame, type Handover, type HandoverBy, type Holder, type HoursSpan, ICONS, type Icon, type ImageBlock, KIT_MESSAGES, KIT_MESSAGES_ES, type KitClassNames, type KitLocale, type KitMessages, type KitPart, KitProvider, List, type ListBlock, type Live, type LiveConversation, type LiveHandlers, MAX_MB, Mark, type MarkProps, MarkStack, type MemoryFact, type Message, type ModeMessages, type ModePart, NO_TOOL, type Names, Note, type NoteBlock, NumberInput, ORB_STYLES, type Option, Orb, type OrbProps, type OrbState, type OrbStyle, type Preview, type Provider, RangeField, RatingField, type Request, Row, type RowProps, type Run, type RunBy, type RunRecord, type RunStatus, type RunStep, RunView, type RunViewProps, SPACE_MESSAGES, SPACE_MESSAGES_ES, SecretInput, type SpaceLayout, type SpaceMessages, type SpaceMode, type SpacePart, type Speaker, type StackBlock, Stat, type StatBlock, Stats, type StatusTone, type Step$1 as Step, type StepApp, type StepGroup, type StepState, type StoredFile, Surface, type SurfaceAction, type SurfaceComponents, type Surface$1 as SurfaceData, type SurfacePart, type SurfaceProps, Switch, type SwitchProps, TASKS_POLL_MS, TASK_MESSAGES, TASK_MESSAGES_ES, TOOL_ERROR_MAX, TOPICS, type TableBlock, Tag, type Task, type TaskMessages, type TaskPart, TextArea, type TextBlock, TextInput, Tile, type TileProps, Tiles, TimeField, type TimeFieldProps, type Told, type Tone, type ToolCall, type ToolHandler, type ToolResult, type Topic, type Trigger, type UpFrame, type Upload, UploadChips, type UploadOptions, type UploadRules, type Uploader, type Uploads, type Use, VISITOR_KEY, VOICE_CALL_MESSAGES, VOICE_CALL_MESSAGES_ES, type Values, type VaultFact, type Verb, VoiceCall, type VoiceCallMessages, type VoiceCallPart, type VoiceCallProps, WIDGET_FONTS, type Wall, type WeekHours, type Weekday, type When, type WidgetConfig, type WidgetFont, type WidgetLook, aboutBack, aboutState, accepts, actionWords, agentGlyph, agentTint, appOf, appSteps, appTitle, automationsOf, callWords, captionsOf, chosen, cleanDocument, clockOf, countOf, createClient, dayRefOf, durationOf, endedByReason, familyOf, filled, fires, formatSize, generatedName, groupsOf, labelOf, lineOf, lookOf, momentOf, namesOf, namingOf, occurrences, offsetOf, orbOf, parseCron, picked, pressed, previewOf, problemOf, scheduleOf, taskCard, timeOf, toneOf, tookOf, toolName, toolResultOf, toolTitle, useAgentFace, useCall, useConversation, useDictation, useLive, useTasks, useUploads, verbOf, whenOf };
64
+ export { ABOUT_HOME, ABOUT_MESSAGES, AGENT_ICONS, AUTOMATION_MESSAGES, AUTOMATION_MESSAGES_ES, type About, type AboutControls, type AboutMessages, type AboutOut, type AboutPart, type AboutState, type AboutTools, type AboutView, type Action, type ActionFact, AgentAbout, type AgentAboutProps, type AgentActivity, AgentCard, type AgentCardProps, AgentChat, type AgentChatProps, type AgentFace, type AgentIcon, AgentSpace, type AgentSpaceProps, AgentTasks, type AgentTasksProps, type AgentTint, ApiError, type AppDirectory, type AskFact, type Attachment, AudioPlayer, type AudioPlayerProps, type Author, Automation, type AutomationBlock, type Automation$1 as AutomationData, type AutomationFact, type AutomationKind, type AutomationMessages, type AutomationProps, type AutomationState, type Step as AutomationStep, type AutomationView, BROWSER_MESSAGES, BROWSER_MESSAGES_ES, type Block, type BlockProps, type Board, type BrowserControl, type BrowserFrame, type BrowserInput, type BrowserMessages, type BrowserPart, type BrowserState, BrowserView, type BrowserViewProps, type BrowserWhere, Button, type ButtonBlock, type ButtonProps, CHAT_MESSAGES, CHAT_MESSAGES_ES, type Call, type CallEnd, type CallEndedBy, type CallGlance, type CallJoin, type CallLine, type CallLook, type CallMessages, type CallMeter, type CallProblem, type CallReason, type CallState, type CallToken, Card, type CardBlock, type CardField, type CardPart, type Channel, type ChannelFact, type ChannelGlance, type ChannelKind, type ChannelSettings, type ChannelStatus, type ChannelWeb, type ChartBlock, type ChartPoint, type ChatCompose, type ChatLook, type ChatMessages, type ChatPart, type ChatSteps, Checkbox, Chips, type ChoiceBlock, Choices, type Client, type ClientOptions, Combobox, type ComboboxProps, type ConnectionFact, type ContactGlance, type ControlBase, Conversation, type ConversationDetail, type ConversationFile, type ConversationPerson, type ConversationProps, type Credentials, type Cron, type DataFact, DateField, type DateFieldProps, DateTimeField, type DateTimeFieldProps, type DayRef, type Decides, type Decision, type Delivery, type DeviceFact, type DeviceKind, type Dictate, type Dictation, type DividerBlock, type Does, type Entry, FILES_PER_MESSAGE, FILE_MESSAGES, type FaceRead, type Facts, Field, type FieldIds, type FieldKind, type FieldValue, type FieldsBlock, type FileAt, type FileBlock, FileChip, type FileChipProps, FileChips, type FileFact, type FileFamily, FileField, type FileFieldProps, type FileHost, type FileIndex, FileMark, type FileMessages, type FilePart, type FilePreview, FileView, type FileViewProps, type Files, type FormBlock, type FormField, type Frame, type Handover, type HandoverBy, type Holder, type HoursSpan, ICONS, type Icon, type ImageBlock, KIT_MESSAGES, KIT_MESSAGES_ES, type KitClassNames, type KitLocale, type KitMessages, type KitPart, KitProvider, List, type ListBlock, type Live, type LiveConversation, type LiveHandlers, MAX_MB, Mark, type MarkProps, MarkStack, type MemoryFact, type Message, type ModeMessages, type ModePart, NO_TOOL, type Names, Note, type NoteBlock, NumberInput, ORB_STYLES, type Option, Orb, type OrbProps, type OrbState, type OrbStyle, type Preview, type Provider, RangeField, RatingField, type Request, Row, type RowProps, type Run, type RunBy, type RunRecord, type RunStatus, type RunStep, RunView, type RunViewProps, SPACE_MESSAGES, SPACE_MESSAGES_ES, SecretInput, type SpaceLayout, type SpaceMessages, type SpaceMode, type SpacePart, type Speaker, type StackBlock, Stat, type StatBlock, Stats, type StatusTone, type Step$1 as Step, type StepApp, type StepGroup, type StepState, type StoredFile, Surface, type SurfaceAction, type SurfaceComponents, type Surface$1 as SurfaceData, type SurfacePart, type SurfaceProps, Switch, type SwitchProps, TASKS_POLL_MS, TASK_MESSAGES, TASK_MESSAGES_ES, THREADS_POLL_MS, THREAD_MESSAGES, THREAD_MESSAGES_ES, TOOL_ERROR_MAX, TOPICS, type TableBlock, Tag, type Task, type TaskMessages, type TaskPart, TextArea, type TextBlock, TextInput, type ThreadMessages, type ThreadPart, Threads, type ThreadsProps, Tile, type TileProps, Tiles, TimeField, type TimeFieldProps, type Told, type Tone, type ToolCall, type ToolHandler, type ToolResult, type Topic, type Trigger, type Unread, type UpFrame, type Upload, UploadChips, type UploadOptions, type UploadRules, type Uploader, type Uploads, type Use, VISITOR_KEY, VOICE_CALL_MESSAGES, VOICE_CALL_MESSAGES_ES, type Values, type VaultFact, type Verb, VoiceCall, type VoiceCallMessages, type VoiceCallPart, type VoiceCallProps, WIDGET_FONTS, type Wall, type WeekHours, type Weekday, type When, type WidgetConfig, type WidgetFont, type WidgetLook, aboutBack, aboutState, accepts, actionWords, agentGlyph, agentTint, appOf, appSteps, appTitle, automationsOf, callWords, captionsOf, chosen, cleanDocument, clockOf, countOf, createClient, dayRefOf, durationOf, endedByReason, familyOf, filled, fires, formatSize, generatedName, groupsOf, labelOf, lineOf, lookOf, momentOf, namesOf, namingOf, occurrences, offsetOf, orbOf, parseCron, picked, pressed, previewOf, problemOf, scheduleOf, taskCard, timeOf, toneOf, tookOf, toolName, toolResultOf, toolTitle, useAgentFace, useCall, useConversation, useDictation, useLive, useTasks, useUnread, useUploads, verbOf, whenOf };
package/dist/index.js CHANGED
@@ -26,18 +26,17 @@ import { agentTint } from "./tint.js";
26
26
  import { ABOUT_HOME, ABOUT_MESSAGES, AgentAbout, aboutBack } from "./AgentAbout.js";
27
27
  import { taskCard } from "./automation/types.js";
28
28
  import { AgentTasks, TASKS_POLL_MS, TASK_MESSAGES, useTasks } from "./AgentTasks.js";
29
- import { AgentCard } from "./AgentCard.js";
30
29
  import { BROWSER_MESSAGES, BrowserView } from "./BrowserView.js";
31
30
  import { useDictation } from "./useDictation.js";
32
31
  import { FILES_PER_MESSAGE, TOOL_ERROR_MAX, toolResultOf } from "./frames.js";
33
32
  import { AudioPlayer } from "./kit/AudioPlayer.js";
34
33
  import { Field } from "./kit/Field.js";
34
+ import { Checkbox, NumberInput, SecretInput, TextArea, TextInput } from "./kit/Inputs.js";
35
35
  import { FileChip, FileChips, FileField, UploadChips, useUploads } from "./kit/FileField.js";
36
36
  import { Card } from "./kit/Card.js";
37
37
  import { Chips, Choices } from "./kit/Choices.js";
38
38
  import { Combobox } from "./kit/Combobox.js";
39
39
  import { DateField } from "./kit/DateField.js";
40
- import { Checkbox, NumberInput, SecretInput, TextArea, TextInput } from "./kit/Inputs.js";
41
40
  import { RangeField } from "./kit/RangeField.js";
42
41
  import { RatingField } from "./kit/RatingField.js";
43
42
  import { DateTimeField, TimeField } from "./kit/TimeField.js";
@@ -46,9 +45,11 @@ import { Surface } from "./surface/Surface.js";
46
45
  import { useLive } from "./useLive.js";
47
46
  import { NO_TOOL, useConversation } from "./useConversation.js";
48
47
  import { AgentChat, CHAT_MESSAGES } from "./AgentChat.js";
48
+ import { Conversation, THREADS_POLL_MS, THREAD_MESSAGES, Threads, useUnread } from "./Threads.js";
49
+ import { AgentCard } from "./AgentCard.js";
49
50
  import { useAgentFace } from "./useAgentFace.js";
50
51
  import { AgentSpace, SPACE_MESSAGES, captionsOf } from "./AgentSpace.js";
51
- import { AUTOMATION_MESSAGES_ES, BROWSER_MESSAGES_ES, CHAT_MESSAGES_ES, KIT_MESSAGES_ES, SPACE_MESSAGES_ES, TASK_MESSAGES_ES, VOICE_CALL_MESSAGES_ES } from "./es.js";
52
+ import { AUTOMATION_MESSAGES_ES, BROWSER_MESSAGES_ES, CHAT_MESSAGES_ES, KIT_MESSAGES_ES, SPACE_MESSAGES_ES, TASK_MESSAGES_ES, THREAD_MESSAGES_ES, VOICE_CALL_MESSAGES_ES } from "./es.js";
52
53
  import { durationOf, endedByReason, lookOf, orbOf } from "./call.js";
53
54
  import { useCall } from "./useCall.js";
54
55
  import { ORB_STYLES } from "./voice/orbs.js";
@@ -57,4 +58,4 @@ import { VOICE_CALL_MESSAGES, VoiceCall } from "./VoiceCall.js";
57
58
  import { FILE_MESSAGES, FileView } from "./FileView.js";
58
59
  import { Tile, Tiles } from "./kit/Tile.js";
59
60
  import { WIDGET_FONTS } from "./types.js";
60
- export { ABOUT_HOME, ABOUT_MESSAGES, AGENT_ICONS, AUTOMATION_MESSAGES, AUTOMATION_MESSAGES_ES, AgentAbout, AgentCard, AgentChat, AgentSpace, AgentTasks, ApiError, AudioPlayer, Automation, BROWSER_MESSAGES, BROWSER_MESSAGES_ES, BrowserView, Button, CHAT_MESSAGES, CHAT_MESSAGES_ES, Card, Checkbox, Chips, Choices, Combobox, DateField, DateTimeField, FILES_PER_MESSAGE, FILE_MESSAGES, Field, FileChip, FileChips, FileField, FileMark, FileView, ICONS, KIT_MESSAGES, KIT_MESSAGES_ES, KitProvider, List, MAX_MB, Mark, MarkStack, NO_TOOL, Note, NumberInput, ORB_STYLES, Orb, RangeField, RatingField, Row, RunView, SPACE_MESSAGES, SPACE_MESSAGES_ES, SecretInput, Stat, Stats, Surface, Switch, TASKS_POLL_MS, TASK_MESSAGES, TASK_MESSAGES_ES, TOOL_ERROR_MAX, TOPICS, Tag, TextArea, TextInput, Tile, Tiles, TimeField, UploadChips, VISITOR_KEY, VOICE_CALL_MESSAGES, VOICE_CALL_MESSAGES_ES, VoiceCall, WIDGET_FONTS, aboutBack, aboutState, accepts, actionWords, agentGlyph, agentTint, appOf, appSteps, appTitle, automationsOf, callWords, captionsOf, chosen, cleanDocument, clockOf, countOf, createClient, dayRefOf, durationOf, endedByReason, familyOf, filled, fires, formatSize, generatedName, groupsOf, labelOf, lineOf, lookOf, momentOf, namesOf, namingOf, occurrences, offsetOf, orbOf, parseCron, picked, pressed, previewOf, problemOf, scheduleOf, taskCard, timeOf, toneOf, tookOf, toolName, toolResultOf, toolTitle, useAgentFace, useCall, useConversation, useDictation, useLive, useTasks, useUploads, verbOf, whenOf };
61
+ export { ABOUT_HOME, ABOUT_MESSAGES, AGENT_ICONS, AUTOMATION_MESSAGES, AUTOMATION_MESSAGES_ES, AgentAbout, AgentCard, AgentChat, AgentSpace, AgentTasks, ApiError, AudioPlayer, Automation, BROWSER_MESSAGES, BROWSER_MESSAGES_ES, BrowserView, Button, CHAT_MESSAGES, CHAT_MESSAGES_ES, Card, Checkbox, Chips, Choices, Combobox, Conversation, DateField, DateTimeField, FILES_PER_MESSAGE, FILE_MESSAGES, Field, FileChip, FileChips, FileField, FileMark, FileView, ICONS, KIT_MESSAGES, KIT_MESSAGES_ES, KitProvider, List, MAX_MB, Mark, MarkStack, NO_TOOL, Note, NumberInput, ORB_STYLES, Orb, RangeField, RatingField, Row, RunView, SPACE_MESSAGES, SPACE_MESSAGES_ES, SecretInput, Stat, Stats, Surface, Switch, TASKS_POLL_MS, TASK_MESSAGES, TASK_MESSAGES_ES, THREADS_POLL_MS, THREAD_MESSAGES, THREAD_MESSAGES_ES, TOOL_ERROR_MAX, TOPICS, Tag, TextArea, TextInput, Threads, Tile, Tiles, TimeField, UploadChips, VISITOR_KEY, VOICE_CALL_MESSAGES, VOICE_CALL_MESSAGES_ES, VoiceCall, WIDGET_FONTS, aboutBack, aboutState, accepts, actionWords, agentGlyph, agentTint, appOf, appSteps, appTitle, automationsOf, callWords, captionsOf, chosen, cleanDocument, clockOf, countOf, createClient, dayRefOf, durationOf, endedByReason, familyOf, filled, fires, formatSize, generatedName, groupsOf, labelOf, lineOf, lookOf, momentOf, namesOf, namingOf, occurrences, offsetOf, orbOf, parseCron, picked, pressed, previewOf, problemOf, scheduleOf, taskCard, timeOf, toneOf, tookOf, toolName, toolResultOf, toolTitle, useAgentFace, useCall, useConversation, useDictation, useLive, useTasks, useUnread, useUploads, verbOf, whenOf };
@@ -1,11 +1,11 @@
1
1
  import { useKit } from "../kit/context.js";
2
2
  import { Button } from "../kit/Button.js";
3
3
  import { Field } from "../kit/Field.js";
4
+ import { Checkbox, NumberInput, SecretInput, TextArea, TextInput } from "../kit/Inputs.js";
4
5
  import { FileField } from "../kit/FileField.js";
5
6
  import { Chips, Choices } from "../kit/Choices.js";
6
7
  import { Combobox } from "../kit/Combobox.js";
7
8
  import { DateField } from "../kit/DateField.js";
8
- import { Checkbox, NumberInput, SecretInput, TextArea, TextInput } from "../kit/Inputs.js";
9
9
  import { RangeField } from "../kit/RangeField.js";
10
10
  import { RatingField } from "../kit/RatingField.js";
11
11
  import { DateTimeField, TimeField } from "../kit/TimeField.js";
package/dist/types.d.ts CHANGED
@@ -83,6 +83,12 @@ export interface Conversation {
83
83
  * host's app (`host_person`, its `contact` then) or the widget's visitor.
84
84
  */
85
85
  person?: ConversationPerson | null | undefined;
86
+ /**
87
+ * For the person it is with: how many of the business's messages came since they last read it,
88
+ * and whether it waits on them (a question, their yes); left out by an older API.
89
+ */
90
+ unread?: number | undefined;
91
+ waiting_on_person?: boolean | undefined;
86
92
  }
87
93
  /** Who a person's token or a publishable key started a conversation for. */
88
94
  export interface ConversationPerson {
@@ -215,6 +221,8 @@ export interface Request {
215
221
  input: Record<string, unknown>;
216
222
  /** The person's when left out (an API from before it). */
217
223
  decides?: Decides | undefined;
224
+ /** The JSON Schema of its input, which an edit given with the yes must fit. */
225
+ schema?: Record<string, unknown> | null | undefined;
218
226
  }
219
227
  /** An action a reply called: what, how it went, and what it drew. */
220
228
  export interface Step {
@@ -280,6 +288,9 @@ export interface Message {
280
288
  heard?: string | null | undefined;
281
289
  /** On a channel, a person's message: what was decided of it; null otherwise. */
282
290
  decision?: Decision | null | undefined;
291
+ /** The agent's words first, without a turn of the person's, and the run whose code sent them. */
292
+ proactive?: boolean | undefined;
293
+ run_id?: string | null | undefined;
283
294
  created_at: string;
284
295
  }
285
296
  /**
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\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}\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 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":";;AAsjBA,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/** 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"}
@@ -31,6 +31,8 @@ export interface LiveConversation {
31
31
  say: (text: string, files?: readonly string[]) => boolean;
32
32
  /** What the person did on a surface; false when the socket is closed. */
33
33
  act: (action: Action) => boolean;
34
+ /** Several things done at once (a yes or no on each call a reply waits on), sent together. */
35
+ actAll: (actions: readonly Action[]) => boolean;
34
36
  /** Stops the reply on its way; false when the socket is closed. */
35
37
  stop: () => boolean;
36
38
  /** The conversation's browser while it is open: where it is, who holds it. */
@@ -491,6 +491,21 @@ function useConversation(client, conversationId, { onError, onHolder, onStep, ha
491
491
  });
492
492
  return true;
493
493
  };
494
+ const actAll = (actions) => {
495
+ const sent = actions.map((one) => ({
496
+ type: "action",
497
+ ...one
498
+ }));
499
+ if (!live.send({
500
+ type: "actions",
501
+ actions: sent
502
+ })) return false;
503
+ for (const action of actions) dispatch({
504
+ type: "acted",
505
+ action
506
+ });
507
+ return true;
508
+ };
494
509
  return {
495
510
  messages: state.messages,
496
511
  draft: state.draft,
@@ -501,6 +516,7 @@ function useConversation(client, conversationId, { onError, onHolder, onStep, ha
501
516
  error: state.error,
502
517
  say,
503
518
  act,
519
+ actAll,
504
520
  stop: () => live.send({ type: "stop" }),
505
521
  browser: state.browser,
506
522
  watchScreen: screen.watch,