@teaflask/assistant 0.6.0 → 0.7.0

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 (318) hide show
  1. package/README.md +1 -1
  2. package/custom-elements.json +264 -0
  3. package/dist/appearance/theme.d.ts +138 -0
  4. package/dist/components/approval-card.js +3 -3
  5. package/dist/components/approval-context.d.ts +20 -0
  6. package/dist/components/assistant-companion.d.ts +15 -0
  7. package/dist/components/assistant-page.d.ts +61 -0
  8. package/dist/components/assistant-palette.d.ts +12 -0
  9. package/dist/components/assistant-palette.js +2 -2
  10. package/dist/components/child-transcript.js +1 -1
  11. package/dist/components/companion-header-disclosure.js +1 -1
  12. package/dist/components/companion-history-menu.js +1 -1
  13. package/dist/components/composer.js +11 -65
  14. package/dist/components/conversation-context.d.ts +6 -0
  15. package/dist/components/conversation-gate-card.js +1 -1
  16. package/dist/components/conversation-view.d.ts +11 -0
  17. package/dist/components/elicitation-context.d.ts +39 -0
  18. package/dist/components/model-picker-chip.js +4 -2
  19. package/dist/components/primitives/button.js +25 -17
  20. package/dist/components/primitives/floating-panel.js +1 -1
  21. package/dist/components/provider-chip.js +8 -1
  22. package/dist/components/question-panel-footer.js +1 -1
  23. package/dist/components/react-tool-view.d.ts +7 -0
  24. package/dist/components/subagent-count-pill.js +2 -2
  25. package/dist/components/subagent-group-row.js +1 -26
  26. package/dist/components/subagent-preview-popover.js +1 -1
  27. package/dist/components/subscription-connect-arms.js +6 -4
  28. package/dist/components/subscription-connect-flow.js +30 -45
  29. package/dist/components/subscription-connected-standing.js +9 -6
  30. package/dist/components/subscription-plan-notice.js +4 -2
  31. package/dist/components/teaflask-assistant-provider.d.ts +99 -0
  32. package/dist/components/teaflask-assistant.d.ts +33 -0
  33. package/dist/components/tool-views/action-view.js +1 -1
  34. package/dist/components/tool-views/parts-classes.d.ts +5 -5
  35. package/dist/components/tool-views/parts-classes.js +5 -5
  36. package/dist/components/tool-views/parts.d.ts +44 -0
  37. package/dist/components/tool-views/questions-view.js +2 -2
  38. package/dist/components/tool-views/view-dom.d.ts +76 -0
  39. package/dist/components/transcript.js +2 -2
  40. package/dist/components/use-assistant-activity.d.ts +5 -0
  41. package/dist/components/use-assistant-conversation.d.ts +99 -2
  42. package/dist/components/use-store-cell.d.ts +5 -0
  43. package/dist/components/use-thread-dispatches.js +8 -366
  44. package/dist/components/use-transcript-folds.js +2 -1
  45. package/dist/components/use-transcript.d.ts +55 -2
  46. package/dist/components/use-transcript.js +7 -2
  47. package/dist/contract/actions-adapter.d.ts +78 -0
  48. package/dist/contract/errors.d.ts +6 -1
  49. package/dist/contract/events.d.ts +1 -3
  50. package/dist/contract/identity.d.ts +1 -1
  51. package/dist/contract/subscriptions.d.ts +2 -2
  52. package/dist/contract/subscriptions.js +1 -1
  53. package/dist/contract/telemetry.d.ts +45 -0
  54. package/dist/contract/threads.d.ts +5 -1
  55. package/dist/core/activity.d.ts +44 -0
  56. package/dist/core/approval-inbox.d.ts +69 -0
  57. package/dist/core/assistant-session-registry.js +15 -0
  58. package/dist/core/composer-attachments.js +82 -0
  59. package/dist/core/composer-input-state.js +1 -0
  60. package/dist/core/composer-policy.d.ts +20 -0
  61. package/dist/core/connection-epoch.d.ts +65 -2
  62. package/dist/core/conversation-adoption.js +3 -0
  63. package/dist/core/conversation-contract.d.ts +112 -1
  64. package/dist/core/conversation-publish.js +1 -0
  65. package/dist/core/conversation-store.d.ts +3 -0
  66. package/dist/core/conversation-store.js +7 -0
  67. package/dist/core/dispatch-poll.js +81 -0
  68. package/dist/core/elicitation-answers.js +12 -0
  69. package/dist/core/elicitation-cards.d.ts +14 -0
  70. package/dist/core/elicitation-pickers.d.ts +16 -0
  71. package/dist/core/memory-provenance-anchors.d.ts +16 -0
  72. package/dist/core/observable-cell.d.ts +12 -0
  73. package/dist/core/pending-decision-gap.d.ts +9 -0
  74. package/dist/core/question-drafts.d.ts +59 -0
  75. package/dist/core/receipt-anchors.d.ts +9 -0
  76. package/dist/core/segment-timing.d.ts +23 -0
  77. package/dist/core/subagent-delivery-anchors.d.ts +7 -0
  78. package/dist/core/subagent-ledger-join.js +176 -0
  79. package/dist/core/subagent-rows.d.ts +68 -0
  80. package/dist/core/thread-dispatch-ledger.js +303 -0
  81. package/dist/core/tool-call-display.d.ts +71 -0
  82. package/dist/core/tool-call-presentation.d.ts +34 -1
  83. package/dist/core/tool-call-presentation.js +0 -1
  84. package/dist/core/tool-schema-anchors.d.ts +6 -0
  85. package/dist/core/tool-view.d.ts +174 -1
  86. package/dist/core/transcript-rows.d.ts +138 -3
  87. package/dist/core/turn-failed-anchors.d.ts +4 -0
  88. package/dist/core/user-turn-ledger.d.ts +3 -0
  89. package/dist/generated/models/apiErrorCode.d.ts +1 -0
  90. package/dist/generated/models/apiErrorCode.js +1 -0
  91. package/dist/generated/models/assistantTurnStatus.d.ts +16 -0
  92. package/dist/generated/models/servingAssistantThreadResponse.d.ts +23 -0
  93. package/dist/generated/models/servingAttachmentResponse.d.ts +29 -0
  94. package/dist/generated/models/servingErrorCode.d.ts +18 -0
  95. package/dist/generated/models/servingTurnAttachmentResponse.d.ts +12 -0
  96. package/dist/generated/models/siteTheme.d.ts +1 -0
  97. package/dist/generated/models/thinkingEffort.d.ts +10 -0
  98. package/dist/generated/models/threadModelPickResponse.d.ts +12 -0
  99. package/dist/headless.d.ts +9 -4
  100. package/dist/index.d.ts +2 -6
  101. package/dist/index.js +0 -3
  102. package/dist/persistence/stored-thread.d.ts +5 -0
  103. package/dist/styles.css +1 -1
  104. package/dist/transport/serving-error.d.ts +21 -0
  105. package/package.json +6 -25
  106. package/dist/affordances/highlight.d.ts +0 -3
  107. package/dist/affordances/prefill.d.ts +0 -14
  108. package/dist/components/activity-rail.d.ts +0 -12
  109. package/dist/components/activity-shelf.d.ts +0 -7
  110. package/dist/components/agent-identity-mark.d.ts +0 -7
  111. package/dist/components/appearance-context.d.ts +0 -14
  112. package/dist/components/approval-card.d.ts +0 -7
  113. package/dist/components/assistant-palette-body.d.ts +0 -3
  114. package/dist/components/assistant-transcript.d.ts +0 -47
  115. package/dist/components/attachment-chips.d.ts +0 -4
  116. package/dist/components/child-transcript.d.ts +0 -22
  117. package/dist/components/companion-drawer-body.d.ts +0 -1
  118. package/dist/components/companion-drawer.d.ts +0 -10
  119. package/dist/components/companion-header-disclosure.d.ts +0 -20
  120. package/dist/components/companion-history-menu.d.ts +0 -15
  121. package/dist/components/companion-mark-image.d.ts +0 -3
  122. package/dist/components/companion-mark-image.js +0 -18
  123. package/dist/components/companion-mark.d.ts +0 -1
  124. package/dist/components/companion-mode-menu.d.ts +0 -15
  125. package/dist/components/composer-attachment-chip.d.ts +0 -7
  126. package/dist/components/composer-banner.d.ts +0 -4
  127. package/dist/components/composer.d.ts +0 -4
  128. package/dist/components/conversation-gate-card.d.ts +0 -8
  129. package/dist/components/conversation-surfaces-provider.d.ts +0 -6
  130. package/dist/components/copy-text-button.d.ts +0 -5
  131. package/dist/components/elicitation-receipt-row.d.ts +0 -4
  132. package/dist/components/human-file-size.d.ts +0 -1
  133. package/dist/components/icons.d.ts +0 -15
  134. package/dist/components/lazy-body.d.ts +0 -4
  135. package/dist/components/markdown/assistant-markdown.d.ts +0 -3
  136. package/dist/components/markdown/code-block.d.ts +0 -4
  137. package/dist/components/markdown/highlight.d.ts +0 -1
  138. package/dist/components/markdown/markdown-structure.d.ts +0 -16
  139. package/dist/components/markdown/memoized-blocks.d.ts +0 -6
  140. package/dist/components/markdown/paced-assistant-markdown.d.ts +0 -4
  141. package/dist/components/markdown/reveal-pacer.d.ts +0 -20
  142. package/dist/components/markdown/shiki-highlighter.d.ts +0 -1
  143. package/dist/components/markdown/streaming-repair.d.ts +0 -1
  144. package/dist/components/markdown/use-highlighted-html.d.ts +0 -1
  145. package/dist/components/markdown/use-paced-reveal.d.ts +0 -5
  146. package/dist/components/memory-updated-footer.d.ts +0 -4
  147. package/dist/components/message-list-row.d.ts +0 -13
  148. package/dist/components/message-list-slots.d.ts +0 -25
  149. package/dist/components/message-list-slots.js +0 -1
  150. package/dist/components/message-list.d.ts +0 -23
  151. package/dist/components/model-picker-chip.d.ts +0 -1
  152. package/dist/components/model-picker-effort.d.ts +0 -4
  153. package/dist/components/model-picker-panels.d.ts +0 -22
  154. package/dist/components/notice-banner.d.ts +0 -8
  155. package/dist/components/operation-icons.d.ts +0 -19
  156. package/dist/components/pretty-print.d.ts +0 -1
  157. package/dist/components/primitives/autofocus.d.ts +0 -1
  158. package/dist/components/primitives/button.d.ts +0 -10
  159. package/dist/components/primitives/cx.d.ts +0 -1
  160. package/dist/components/primitives/dialog.d.ts +0 -7
  161. package/dist/components/primitives/disclosure.d.ts +0 -22
  162. package/dist/components/primitives/file-input.d.ts +0 -5
  163. package/dist/components/primitives/floating-panel.d.ts +0 -15
  164. package/dist/components/primitives/kbd.d.ts +0 -2
  165. package/dist/components/primitives/sheet.d.ts +0 -11
  166. package/dist/components/primitives/sheet.js +0 -18
  167. package/dist/components/primitives/textarea.d.ts +0 -7
  168. package/dist/components/primitives/use-dock-reflow.d.ts +0 -2
  169. package/dist/components/primitives/use-swipe-dismiss.d.ts +0 -17
  170. package/dist/components/provider-chip.d.ts +0 -8
  171. package/dist/components/question-panel-answers.d.ts +0 -29
  172. package/dist/components/question-panel-footer.d.ts +0 -9
  173. package/dist/components/question-panel.d.ts +0 -4
  174. package/dist/components/reasoning-row.d.ts +0 -4
  175. package/dist/components/receipt-rows.d.ts +0 -3
  176. package/dist/components/run-status-announcer.d.ts +0 -5
  177. package/dist/components/scroll-follow-guards.d.ts +0 -1
  178. package/dist/components/served-suggestions.d.ts +0 -3
  179. package/dist/components/slot-boundary.d.ts +0 -11
  180. package/dist/components/standing-poll.d.ts +0 -1
  181. package/dist/components/streaming-states.d.ts +0 -12
  182. package/dist/components/subagent-count-pill.d.ts +0 -8
  183. package/dist/components/subagent-current-work.d.ts +0 -6
  184. package/dist/components/subagent-delegation-surface.d.ts +0 -9
  185. package/dist/components/subagent-delivery-divider.d.ts +0 -5
  186. package/dist/components/subagent-drill-in.d.ts +0 -8
  187. package/dist/components/subagent-execution-work.d.ts +0 -3
  188. package/dist/components/subagent-group-row.d.ts +0 -26
  189. package/dist/components/subagent-preview-popover.d.ts +0 -8
  190. package/dist/components/subscription-connect-arms.d.ts +0 -25
  191. package/dist/components/subscription-connect-flow.d.ts +0 -60
  192. package/dist/components/subscription-connected-standing.d.ts +0 -16
  193. package/dist/components/subscription-plan-notice.d.ts +0 -1
  194. package/dist/components/subscription-recheck.d.ts +0 -10
  195. package/dist/components/surface-boundary.d.ts +0 -8
  196. package/dist/components/suspension-surfaces.d.ts +0 -3
  197. package/dist/components/thread-list.d.ts +0 -16
  198. package/dist/components/tool-arguments-summary.d.ts +0 -2
  199. package/dist/components/tool-call-rows.d.ts +0 -10
  200. package/dist/components/tool-row.d.ts +0 -7
  201. package/dist/components/tool-view-registry-context.d.ts +0 -3
  202. package/dist/components/tool-view-slot.d.ts +0 -11
  203. package/dist/components/tool-views/action-view.d.ts +0 -1
  204. package/dist/components/tool-views/command-view.d.ts +0 -1
  205. package/dist/components/tool-views/docs-search-view.d.ts +0 -10
  206. package/dist/components/tool-views/file-edit-view.d.ts +0 -1
  207. package/dist/components/tool-views/questions-view.d.ts +0 -1
  208. package/dist/components/transcript.d.ts +0 -3
  209. package/dist/components/use-agent-subscriber.d.ts +0 -3
  210. package/dist/components/use-agent-subscriber.js +0 -13
  211. package/dist/components/use-answer-list-fold.d.ts +0 -6
  212. package/dist/components/use-assistant-surface-presence.d.ts +0 -2
  213. package/dist/components/use-child-replay-stream.d.ts +0 -20
  214. package/dist/components/use-latest-ref.d.ts +0 -2
  215. package/dist/components/use-member-toggle-outrank.d.ts +0 -6
  216. package/dist/components/use-perch-clearance.d.ts +0 -2
  217. package/dist/components/use-question-panel-keys.d.ts +0 -32
  218. package/dist/components/use-register-assistant-surface.d.ts +0 -2
  219. package/dist/components/use-resolved-theme-mode.d.ts +0 -3
  220. package/dist/components/use-roster-disclosure.d.ts +0 -20
  221. package/dist/components/use-roster-preview.d.ts +0 -24
  222. package/dist/components/use-thread-dispatches.d.ts +0 -8
  223. package/dist/components/use-transcript-folds.d.ts +0 -26
  224. package/dist/components/user-message.d.ts +0 -6
  225. package/dist/contract/actions-adapter.js +0 -1
  226. package/dist/contract/assistant-config.js +0 -1
  227. package/dist/contract/dispatches.d.ts +0 -15
  228. package/dist/contract/errors.js +0 -1
  229. package/dist/contract/identity.js +0 -1
  230. package/dist/core/activity-title.d.ts +0 -1
  231. package/dist/core/agent-identity.d.ts +0 -2
  232. package/dist/core/approval-decision.d.ts +0 -6
  233. package/dist/core/approval-resolved.d.ts +0 -7
  234. package/dist/core/assistant-prose.d.ts +0 -2
  235. package/dist/core/assistant-session-registry.d.ts +0 -51
  236. package/dist/core/attachment-uploads.d.ts +0 -5
  237. package/dist/core/block-timing-anchors.d.ts +0 -5
  238. package/dist/core/companion-drawer-flag.d.ts +0 -4
  239. package/dist/core/companion-presence.d.ts +0 -7
  240. package/dist/core/composer-input-state.d.ts +0 -8
  241. package/dist/core/connection-driver.d.ts +0 -3
  242. package/dist/core/conversation-adoption.d.ts +0 -13
  243. package/dist/core/conversation-contract.js +0 -1
  244. package/dist/core/conversation-publish.d.ts +0 -8
  245. package/dist/core/conversation-refresh.d.ts +0 -4
  246. package/dist/core/conversation-send.d.ts +0 -6
  247. package/dist/core/disposable-subscriber.d.ts +0 -6
  248. package/dist/core/disposable-subscriber.js +0 -18
  249. package/dist/core/dock-reflow.d.ts +0 -5
  250. package/dist/core/elicitation-answers.d.ts +0 -7
  251. package/dist/core/epoch-sync.d.ts +0 -12
  252. package/dist/core/error-copy.d.ts +0 -3
  253. package/dist/core/execution-driver.d.ts +0 -37
  254. package/dist/core/host-fill.d.ts +0 -1
  255. package/dist/core/hotkey.d.ts +0 -18
  256. package/dist/core/identity-pair.d.ts +0 -14
  257. package/dist/core/idle-recheck.d.ts +0 -3
  258. package/dist/core/messages-cell.d.ts +0 -11
  259. package/dist/core/perch-clearance.d.ts +0 -19
  260. package/dist/core/question-receipt.d.ts +0 -11
  261. package/dist/core/reasoning-copy.d.ts +0 -2
  262. package/dist/core/run-folds.d.ts +0 -43
  263. package/dist/core/run-status.d.ts +0 -4
  264. package/dist/core/settle-refresh.d.ts +0 -9
  265. package/dist/core/step-caption.d.ts +0 -2
  266. package/dist/core/stop-copy.d.ts +0 -1
  267. package/dist/core/stop-settle.d.ts +0 -5
  268. package/dist/core/stream-trouble.d.ts +0 -5
  269. package/dist/core/subagent-brief.d.ts +0 -3
  270. package/dist/core/subagent-presence.d.ts +0 -10
  271. package/dist/core/subagent-roster.d.ts +0 -35
  272. package/dist/core/surface-registry.d.ts +0 -16
  273. package/dist/core/suspension-queue.d.ts +0 -14
  274. package/dist/core/tail-slot-pool.d.ts +0 -13
  275. package/dist/core/time-labels.d.ts +0 -7
  276. package/dist/core/tool-call-display-anchors.d.ts +0 -11
  277. package/dist/core/tool-cancel-anchors.d.ts +0 -5
  278. package/dist/core/tool-decision-anchors.d.ts +0 -6
  279. package/dist/core/tool-error-anchors.d.ts +0 -5
  280. package/dist/core/tool-flag-anchors.d.ts +0 -9
  281. package/dist/core/tool-offload-anchors.d.ts +0 -5
  282. package/dist/core/tool-outcome.d.ts +0 -9
  283. package/dist/core/tool-refusal-anchors.d.ts +0 -5
  284. package/dist/core/tool-result-envelope.d.ts +0 -3
  285. package/dist/core/tool-sentence-anchors.d.ts +0 -11
  286. package/dist/core/transcript-lease.d.ts +0 -2
  287. package/dist/core/turn-failure-copy.d.ts +0 -4
  288. package/dist/core/turns-backfill.d.ts +0 -14
  289. package/dist/core/wire-sentence-cap.d.ts +0 -1
  290. package/dist/generated/serving.d.ts +0 -38
  291. package/dist/markdown.d.ts +0 -4
  292. package/dist/markdown.js +0 -4
  293. package/dist/persistence/execution-ledger.d.ts +0 -7
  294. package/dist/persistence/panel-mode.d.ts +0 -6
  295. package/dist/persistence/plan-notice.d.ts +0 -3
  296. package/dist/reader/accessible-name.d.ts +0 -3
  297. package/dist/reader/interactivity.d.ts +0 -11
  298. package/dist/reader/layout-probe.d.ts +0 -29
  299. package/dist/reader/line-diff.d.ts +0 -1
  300. package/dist/reader/read-page.d.ts +0 -12
  301. package/dist/reader/redaction.d.ts +0 -3
  302. package/dist/reader/render.d.ts +0 -3
  303. package/dist/reader/roles.d.ts +0 -8
  304. package/dist/reader/snapshot-compaction.d.ts +0 -5
  305. package/dist/reader/snapshot-node.d.ts +0 -4
  306. package/dist/reader/snapshot-root.d.ts +0 -15
  307. package/dist/reader/snapshot.d.ts +0 -60
  308. package/dist/reader/visibility.d.ts +0 -8
  309. package/dist/scroll.d.ts +0 -1
  310. package/dist/scroll.js +0 -1
  311. package/dist/transcript-ui.d.ts +0 -15
  312. package/dist/transcript-ui.js +0 -8
  313. package/dist/transcript.d.ts +0 -43
  314. package/dist/transcript.js +0 -38
  315. package/dist/transport/actions-adapter.d.ts +0 -4
  316. package/dist/transport/door-budget.d.ts +0 -4
  317. package/dist/transport/serving-api.d.ts +0 -33
  318. package/dist/transport/serving-fetch.d.ts +0 -11
@@ -1,19 +1,72 @@
1
1
  import type { Message } from "@ag-ui/core";
2
2
  import { type AssistantActivitySnapshot } from "../core/activity.js";
3
- import type { MarkerAnchorsSnapshot } from "../core/connection-epoch.js";
3
+ import type { TranscriptMarkers } from "../core/connection-epoch.js";
4
4
  import { type TranscriptRow } from "../core/transcript-rows.js";
5
5
  import type { UserTurnMeta } from "../core/user-turn-ledger.js";
6
+ /**
7
+ * The transcript as useTranscript returns it: ready-to-render rows, whether the
8
+ * assistant is working, and the raw inputs the rows were built from.
9
+ */
6
10
  export interface TranscriptSurface {
11
+ /**
12
+ * The conversation as an ordered list of rows, without the message the user
13
+ * has just sent and that is still on its way.
14
+ */
7
15
  rows: readonly TranscriptRow[];
16
+ /**
17
+ * The rows to render: `rows` plus the user's just-sent message while it is
18
+ * still being delivered. Don't also draw your own bubble for a sent
19
+ * message, or it will appear twice.
20
+ */
8
21
  displayRows: readonly TranscriptRow[];
22
+ /**
23
+ * True while the assistant is working: its turn is queued or running, or
24
+ * paused with nothing waiting on the user. False while a send is still in
25
+ * flight, so a working indicator should also check pendingSend from
26
+ * useConversation().
27
+ */
9
28
  running: boolean;
29
+ /**
30
+ * True while the newest turn has not finished, including while it is paused
31
+ * waiting for the user's approval or answer.
32
+ */
10
33
  turnOpen: boolean;
34
+ /**
35
+ * True while the turn is waiting on the user: an approval or question
36
+ * awaits their answer, or the server reports one this client has nothing to
37
+ * show for.
38
+ */
11
39
  decisionsPending: boolean;
40
+ /**
41
+ * The raw message list behind the rows (user messages, assistant text,
42
+ * reasoning, tool calls and tool results). Use it with markerAnchors,
43
+ * running and turnMeta to call transcriptRowsOf yourself.
44
+ */
12
45
  messages: readonly Message[];
13
- markerAnchors: MarkerAnchorsSnapshot;
46
+ /**
47
+ * Extra facts the stream reports about messages and tool calls (failures,
48
+ * timing, schemas, memory saves), already joined into the rows; read it
49
+ * directly only for custom rendering.
50
+ */
51
+ markerAnchors: TranscriptMarkers;
52
+ /**
53
+ * The conversation's current run state, such as the newest turn's status
54
+ * and how many approvals are waiting.
55
+ */
14
56
  activity: AssistantActivitySnapshot;
57
+ /**
58
+ * The send time and attachments of each user message, keyed by that
59
+ * message's id.
60
+ */
15
61
  turnMeta: ReadonlyMap<string, UserTurnMeta>;
16
62
  }
63
+ /**
64
+ * Returns everything needed to render the conversation's transcript yourself,
65
+ * as rows plus run state. Call it inside TeaflaskAssistantProvider (it throws
66
+ * otherwise); keep it mounted while the transcript is on screen, because that
67
+ * is what makes the assistant connect and load an existing conversation's
68
+ * history.
69
+ */
17
70
  export declare function useTranscript(options?: {
18
71
  surface?: string;
19
72
  }): TranscriptSurface;
@@ -2,14 +2,18 @@
2
2
  import { useEffect, useMemo } from "react";
3
3
  import { isTerminalTurnStatus, } from "../core/activity.js";
4
4
  import { runReadsAsWorking } from "../core/run-status.js";
5
+ import { withDispatchLedger } from "../core/subagent-ledger-join.js";
5
6
  import { approvalAwaitsMember, elicitationAwaitsMember, } from "../core/suspension-queue.js";
6
7
  import { transcriptRowsOf, withPendingUserEcho, } from "../core/transcript-rows.js";
7
8
  import { useConversation } from "./conversation-context.js";
8
9
  import { useAssistantSession } from "./teaflask-assistant-provider.js";
9
10
  import { useCell } from "./use-store-cell.js";
11
+ import { useThreadDispatches } from "./use-thread-dispatches.js";
10
12
  export function useTranscript(options) {
11
- const { store } = useAssistantSession();
13
+ const { session, store } = useAssistantSession();
12
14
  const { pendingEcho } = useConversation();
15
+ const connection = useCell(store.connection);
16
+ const dispatches = useThreadDispatches(session, connection?.threadId ?? null);
13
17
  const messages = useCell(store.messages);
14
18
  const markerAnchors = useCell(store.markerAnchors);
15
19
  const approvalCards = useCell(store.approvals);
@@ -24,7 +28,8 @@ export function useTranscript(options) {
24
28
  const running = runReadsAsWorking(activity.newestTurnStatus, decisionsPending);
25
29
  const turnOpen = activity.newestTurnStatus !== null &&
26
30
  !isTerminalTurnStatus(activity.newestTurnStatus);
27
- const rows = useMemo(() => transcriptRowsOf(messages, markerAnchors, running, turnMeta), [messages, markerAnchors, running, turnMeta]);
31
+ const wireRows = useMemo(() => transcriptRowsOf(messages, markerAnchors, running, turnMeta), [messages, markerAnchors, running, turnMeta]);
32
+ const rows = useMemo(() => withDispatchLedger(wireRows, dispatches), [wireRows, dispatches]);
28
33
  const displayRows = useMemo(() => withPendingUserEcho(rows, pendingEcho), [pendingEcho, rows]);
29
34
  return {
30
35
  rows,
@@ -1,26 +1,104 @@
1
+ /** The catalog entry an action request comes from. */
1
2
  export interface ActionIntentAction {
3
+ /**
4
+ * The action's identifier in your catalog; the agent calls it as the tool
5
+ * action__<slug>.
6
+ */
2
7
  slug: string;
8
+ /** The action's human-readable title from your catalog. */
3
9
  title: string;
4
10
  }
11
+ /**
12
+ * One action request the assistant asks your page to perform, built by Teaflask
13
+ * from your actions catalog with arguments already validated against the
14
+ * action's schemas. Your actions adapter receives it.
15
+ */
5
16
  export interface ActionIntent {
17
+ /** Which catalog action this request is for. */
6
18
  action: ActionIntentAction;
19
+ /**
20
+ * The HTTP method, in upper case - GET, HEAD, POST, PUT, PATCH or DELETE.
21
+ */
7
22
  method: string;
23
+ /**
24
+ * The path relative to your API, with {name} placeholders, for example
25
+ * "/subscriptions/{subscription_id}". It never includes an origin, so the
26
+ * request always goes where your adapter sends it.
27
+ */
8
28
  pathTemplate: string;
29
+ /**
30
+ * Values for the placeholders in pathTemplate, keyed by name. The cookies
31
+ * and headers adapters substitute them URL-encoded.
32
+ */
9
33
  pathParams: Record<string, unknown>;
34
+ /**
35
+ * Query-string parameters, keyed by name; empty when there are none. The
36
+ * cookies and headers adapters drop null or undefined values and
37
+ * JSON-encode non-scalar ones.
38
+ */
10
39
  query: Record<string, unknown>;
40
+ /**
41
+ * The JSON request body; absent when the action sends none. The cookies and
42
+ * headers adapters send it with Content-Type application/json.
43
+ */
11
44
  body?: unknown;
12
45
  }
46
+ /**
47
+ * For APIs authenticated by session cookies. The package fetches baseUrl plus
48
+ * the action's path with credentials included, so each request runs in the
49
+ * user's own session; an API on another origin must allow credentialed CORS
50
+ * from your page.
51
+ */
13
52
  export interface CookiesActionsAdapter {
53
+ /** Selects the cookies adapter. */
14
54
  kind: "cookies";
55
+ /**
56
+ * The URL your action paths are appended to, such as
57
+ * "https://app.example.com/api"; a trailing slash is ignored.
58
+ */
15
59
  baseUrl: string;
16
60
  }
61
+ /**
62
+ * For APIs authenticated by a token or other headers. The package builds the
63
+ * URL the same way as the cookies adapter and adds the headers getHeaders
64
+ * returns.
65
+ */
17
66
  export interface HeadersActionsAdapter {
67
+ /** Selects the headers adapter. */
18
68
  kind: "headers";
69
+ /**
70
+ * The URL your action paths are appended to, such as
71
+ * "https://api.example.com/v1"; a trailing slash is ignored.
72
+ */
19
73
  baseUrl: string;
74
+ /**
75
+ * Called before every action request with that request; return the headers
76
+ * to send, such as Authorization. It may be async to fetch or refresh a
77
+ * token, its headers override the package's Content-Type, and throwing
78
+ * reports the action as failed.
79
+ */
20
80
  getHeaders: (intent: ActionIntent) => Record<string, string> | Promise<Record<string, string>>;
21
81
  }
82
+ /**
83
+ * Full control - you perform the HTTP request yourself, for example through
84
+ * your existing API client.
85
+ */
22
86
  export interface RequestActionsAdapter {
87
+ /** Selects the request adapter. */
23
88
  kind: "request";
89
+ /**
90
+ * Performs the request and resolves with your API's response body, which
91
+ * the agent receives with status 200. Reject (for example by throwing on a
92
+ * non-2xx response) to report the action as failed.
93
+ */
24
94
  execute: (intent: ActionIntent) => Promise<unknown>;
25
95
  }
96
+ /**
97
+ * How the assistant calls your API as the signed-in user, passed as the
98
+ * provider's actionsAdapter prop; without one the assistant cannot perform
99
+ * actions and tells the user to do them. The response's status and body (parsed
100
+ * as JSON, otherwise text) go back to the agent; a non-2xx status counts as
101
+ * your API's answer, not a failure, and bodies over about 16,000 characters are
102
+ * truncated.
103
+ */
26
104
  export type ActionsAdapter = CookiesActionsAdapter | HeadersActionsAdapter | RequestActionsAdapter;
@@ -1,7 +1,12 @@
1
1
  export type { ServingErrorCode } from "../generated/models/index.js";
2
2
  import type { ServingErrorCode } from "../generated/models/index.js";
3
+ /**
4
+ * An error code: one of the known ServingErrorCode values, or any other string,
5
+ * since new codes may be added. Handle unknown codes by showing the error's
6
+ * message.
7
+ */
3
8
  export type ServingErrorCodeOnTheWire = ServingErrorCode | (string & {});
4
- export interface ServingErrorBody {
9
+ interface ServingErrorBody {
5
10
  code: ServingErrorCodeOnTheWire;
6
11
  message: string;
7
12
  details?: unknown;
@@ -1,7 +1,5 @@
1
- import type { ApprovalRequestedMarker, ApprovalResolvedMarker, InterruptAnswerConsumedMarker, RunResumedMarker, SubagentResultsDeliveredMarker, ToolExecutionRequestedMarker } from "../generated/models/index.js";
2
- export type AssistantStreamEventType = "TEXT_MESSAGE_START" | "TEXT_MESSAGE_CONTENT" | "TEXT_MESSAGE_END" | "REASONING_START" | "REASONING_END" | "REASONING_MESSAGE_START" | "REASONING_MESSAGE_CONTENT" | "REASONING_MESSAGE_END" | "TOOL_CALL_START" | "TOOL_CALL_ARGS" | "TOOL_CALL_END" | "TOOL_CALL_RESULT" | "RUN_STARTED" | "RUN_FINISHED" | "RUN_ERROR" | "CUSTOM";
1
+ import type { ApprovalRequestedMarker, ApprovalResolvedMarker, InterruptAnswerConsumedMarker, SubagentResultsDeliveredMarker, ToolExecutionRequestedMarker } from "../generated/models/index.js";
3
2
  export declare const RUN_RESUMED_EVENT_NAME: "run_resumed";
4
- export type RunResumedPayload = RunResumedMarker;
5
3
  export declare const APPROVAL_REQUESTED_EVENT_NAME: "approval_requested";
6
4
  export type ApprovalRequestedPayload = ApprovalRequestedMarker & Required<Pick<ApprovalRequestedMarker, "tool_args" | "tool_input_schema" | "tool_output_schema" | "round" | "gated" | "trust_available">>;
7
5
  export declare const APPROVAL_RESOLVED_EVENT_NAME: "approval_resolved";
@@ -1 +1 @@
1
- export type { CurrentVisitorResponse as WhoamiResponse, EndUserIdentity, MintVisitorTokenRequest, MintVisitorTokenResponse, PublishableKeyMode, VisitorTier, } from "../generated/models/index.js";
1
+ export type { MintVisitorTokenRequest, MintVisitorTokenResponse, VisitorTier, } from "../generated/models/index.js";
@@ -1,6 +1,6 @@
1
1
  import type { SubscriptionProvider } from "../generated/models/index.js";
2
- export type { BeginSubscriptionAuthorizationResponse as SubscriptionAuthorization, CompleteSubscriptionAuthorizationRequest as SubscriptionAuthorizationCompletionRequest, CompleteSubscriptionAuthorizationResponse as SubscriptionAuthorizationCompletion, ServingSubscriptionStatus as SubscriptionStatus, SubscriptionCredentialState, SubscriptionProvider, } from "../generated/models/index.js";
3
- export declare const SUBSCRIPTION_CONNECT_MESSAGE_TYPE = "teaflask.subscription_connect";
2
+ export type { BeginSubscriptionAuthorizationResponse as SubscriptionAuthorization, CompleteSubscriptionAuthorizationRequest as SubscriptionAuthorizationCompletionRequest, CompleteSubscriptionAuthorizationResponse as SubscriptionAuthorizationCompletion, ServingSubscriptionStatus as SubscriptionStatus, SubscriptionProvider, } from "../generated/models/index.js";
3
+ declare const SUBSCRIPTION_CONNECT_MESSAGE_TYPE = "teaflask.subscription_connect";
4
4
  export type SubscriptionConnectMessage = {
5
5
  type: typeof SUBSCRIPTION_CONNECT_MESSAGE_TYPE;
6
6
  provider: SubscriptionProvider;
@@ -1,4 +1,4 @@
1
- export const SUBSCRIPTION_CONNECT_MESSAGE_TYPE = "teaflask.subscription_connect";
1
+ const SUBSCRIPTION_CONNECT_MESSAGE_TYPE = "teaflask.subscription_connect";
2
2
  export function subscriptionConnectMessageOf(event, serverOrigin, provider) {
3
3
  if (event.origin !== serverOrigin || event.source === null) {
4
4
  return null;
@@ -1,7 +1,30 @@
1
+ /**
2
+ * Why clicking approve or deny sent nothing. "no_active_thread" means no
3
+ * conversation was open; "card_missing" means the request was no longer shown;
4
+ * "already_submitting" is a repeat click while the first answer is sending;
5
+ * "not_actionable_answered" and "not_actionable_stale" mean the request had
6
+ * already been answered or was no longer open; "no_turn_id" means no turn could
7
+ * be found to answer.
8
+ */
1
9
  export type ApprovalSubmitDropReason = "no_active_thread" | "card_missing" | "already_submitting" | "not_actionable_answered" | "not_actionable_stale" | "no_turn_id";
2
10
  type ApprovalCardStatusKind = "actionable" | "submitting" | "answered" | "stale";
11
+ /**
12
+ * Reported to onTelemetry as the user answers an approval, so you can spot
13
+ * answers that never reached the server.
14
+ */
3
15
  export interface ApprovalSubmitTelemetryEvent {
16
+ /**
17
+ * "approval_submit_attempted" when the user clicks approve or deny,
18
+ * "approval_submit_sent" when the answer is posted, and
19
+ * "approval_submit_dropped" when nothing was posted (see drop_reason).
20
+ */
4
21
  name: "approval_submit_attempted" | "approval_submit_sent" | "approval_submit_dropped";
22
+ /**
23
+ * The request's interrupt_id, the conversation's thread_id, whether it was
24
+ * approved and trusted, the request's on-screen status (actionable,
25
+ * submitting, answered or stale), whether its turn had parked, and the
26
+ * drop_reason for a dropped answer.
27
+ */
5
28
  properties: {
6
29
  interrupt_id: string;
7
30
  thread_id: string | null;
@@ -12,9 +35,27 @@ export interface ApprovalSubmitTelemetryEvent {
12
35
  drop_reason?: ApprovalSubmitDropReason;
13
36
  };
14
37
  }
38
+ /**
39
+ * Where a stream connection failed. "network_rejected" means no response
40
+ * arrived (offline, DNS, CORS); "http_error" is a non-2xx response; "no_body"
41
+ * is a 2xx with no readable body; "mid_stream" means the connection dropped
42
+ * after events had arrived; "parse_or_validation" means an event could not be
43
+ * read; "client_abort" is a cancellation by the widget and is not reported.
44
+ */
15
45
  export type StreamFailureClass = "network_rejected" | "http_error" | "no_body" | "mid_stream" | "parse_or_validation" | "client_abort";
46
+ /**
47
+ * Reported to onTelemetry when the conversation's live stream connection fails.
48
+ * Cancellations made by the widget itself are not reported.
49
+ */
16
50
  export interface StreamFailedTelemetryEvent {
51
+ /** Always "assistant_stream_failed". */
17
52
  name: "assistant_stream_failed";
53
+ /**
54
+ * Where the connection failed (failure_class), the HTTP status or null when
55
+ * no response arrived, the conversation's thread_id, and two stream
56
+ * positions, resume_cursor and last_committed_sse_id, that locate the
57
+ * failure in the conversation's event stream.
58
+ */
18
59
  properties: {
19
60
  failure_class: StreamFailureClass;
20
61
  status: number | null;
@@ -23,6 +64,10 @@ export interface StreamFailedTelemetryEvent {
23
64
  last_committed_sse_id: string | null;
24
65
  };
25
66
  }
67
+ /**
68
+ * Any event passed to the provider's onTelemetry callback, for forwarding to
69
+ * your own analytics. None carry message text, tool arguments or prompts.
70
+ */
26
71
  export type AssistantTelemetryEvent = ApprovalSubmitTelemetryEvent | StreamFailedTelemetryEvent;
27
72
  export declare function streamFailureClassOf(error: Error, context: {
28
73
  sawBodyBytes: boolean;
@@ -1,3 +1,7 @@
1
- export type { CreateServingAttachmentUploadResponse as AttachmentUploadIntent, HighlightResult, NavigateResult, PrefillFormResult, ReadPageResult, ResolveServingTurnApprovalRequest as ResolveTurnApprovalRequest, ResolveServingTurnApprovalResponse as ResolveTurnApprovalResponse, ResolveServingTurnToolResultsRequest as ResolveTurnToolResultsRequest, ResolveServingTurnToolResultsResponse as ResolveTurnToolResultsResponse, SendServingAssistantMessageRequest as SendAssistantMessageRequest, SendServingAssistantMessageResponse as SendAssistantMessageResponse, ServingApprovalDelivery as ApprovalDelivery, ServingAssistantThreadDetailResponse as AssistantThreadDetailResponse, ServingAssistantThreadResponse as ServingAssistantThread, ServingAssistantTurnResponse as ServingAssistantTurn, ServingAttachmentResponse as ServingAttachment, ServingTurnApprovalDecision as TurnApprovalDecision, ServingTurnAttachmentResponse as TurnAttachment, StopServingTurnResponse as StopTurnResponse, ThreadModelPickResponse as ThreadModelPick, AssistantTurnStatus as TurnStatus, } from "../generated/models/index.js";
1
+ export type { CreateServingAttachmentUploadResponse as AttachmentUploadIntent, HighlightResult, NavigateResult, PrefillFormResult, ReadPageResult, ResolveServingTurnApprovalRequest as ResolveTurnApprovalRequest, ResolveServingTurnApprovalResponse as ResolveTurnApprovalResponse, ResolveServingTurnToolResultsRequest as ResolveTurnToolResultsRequest, ResolveServingTurnToolResultsResponse as ResolveTurnToolResultsResponse, SendServingAssistantMessageRequest as SendAssistantMessageRequest, SendServingAssistantMessageResponse as SendAssistantMessageResponse, ServingAssistantThreadDetailResponse as AssistantThreadDetailResponse, ServingAssistantThreadResponse as ServingAssistantThread, ServingAssistantTurnResponse as ServingAssistantTurn, ServingAttachmentResponse as ServingAttachment, ServingTurnAttachmentResponse as TurnAttachment, StopServingTurnResponse as StopTurnResponse, ThreadModelPickResponse as ThreadModelPick, AssistantTurnStatus as TurnStatus, } from "../generated/models/index.js";
2
+ /**
3
+ * The longest message a user can send, in characters; the composer stops input
4
+ * at this length and the server rejects longer messages.
5
+ */
2
6
  export declare const ASSISTANT_MESSAGE_MAX_CHARS = 4000;
3
7
  export declare const ASSISTANT_MAX_ATTACHMENTS = 10;
@@ -1,17 +1,61 @@
1
1
  import type { ServingAssistantTurn, TurnStatus } from "../contract/threads.js";
2
2
  import type { ApprovalCardModel } from "./approval-inbox.js";
3
3
  import type { PendingDecisionGap } from "./pending-decision-gap.js";
4
+ /** How the most recent finished turn of the conversation ended. */
4
5
  export interface AssistantActivityResult {
6
+ /**
7
+ * The id of that turn, which tells apart two identical outcomes in a row.
8
+ */
5
9
  turnId: string;
10
+ /**
11
+ * The final status. It is one of `succeeded`, `failed`, `stopped` (the user
12
+ * pressed Stop) or `superseded` (the user sent a new message instead of
13
+ * answering what the turn was waiting on).
14
+ */
6
15
  status: TurnStatus;
16
+ /**
17
+ * The error message recorded for a failed turn. Null when the turn did not
18
+ * fail or no message was recorded.
19
+ */
7
20
  failureSentence: string | null;
8
21
  }
22
+ /**
23
+ * What the assistant is doing right now, for the open conversation. When no
24
+ * conversation is open, every field holds its idle value (false, 0 or null).
25
+ */
9
26
  export interface AssistantActivitySnapshot {
27
+ /**
28
+ * True while a message is being sent or the agent is working on a reply.
29
+ */
10
30
  busy: boolean;
31
+ /**
32
+ * The status of the latest turn (one message and the agent's work on it),
33
+ * or null when there is none. `queued` and `working` mean in progress.
34
+ * `awaiting_input` means it is waiting on the user. `parked` means an
35
+ * approval went unanswered long enough for the run to pause, and answering
36
+ * still resumes it. The other values mean it has finished.
37
+ */
11
38
  newestTurnStatus: TurnStatus | null;
39
+ /**
40
+ * The id of the latest turn, or null. Use it to dismiss a notification for
41
+ * one turn without hiding later ones.
42
+ */
12
43
  newestTurnId: string | null;
44
+ /**
45
+ * How many approvals are waiting for the user to approve or deny, including
46
+ * ones being submitted.
47
+ */
13
48
  pendingApprovalCount: number;
49
+ /**
50
+ * Set when the agent is waiting on the user for something this page has no
51
+ * prompt for, so nothing on screen lets them respond. Null otherwise. The
52
+ * built-in UI then shows an alert with a reload button.
53
+ */
14
54
  pendingDecisionGap: PendingDecisionGap | null;
55
+ /**
56
+ * How the most recent finished turn ended. It stays until another turn
57
+ * finishes, and is null until one has or when you switch conversations.
58
+ */
15
59
  lastResult: AssistantActivityResult | null;
16
60
  }
17
61
  export declare const IDLE_ACTIVITY: AssistantActivitySnapshot;
@@ -22,27 +22,96 @@ export type ApprovalAsker = {
22
22
  ordinal: number;
23
23
  label: string;
24
24
  };
25
+ /**
26
+ * One request for the visitor to approve or deny a tool or action call before
27
+ * it runs.
28
+ */
25
29
  export interface ApprovalCardModel {
30
+ /** Unique id of this request; use it as the React key. */
26
31
  interruptId: string;
32
+ /**
33
+ * Name of the tool waiting for approval (an action's is action__<slug>), or
34
+ * null when the request is not tied to a tool call.
35
+ */
27
36
  toolName: string | null;
37
+ /**
38
+ * What the agent passed to the call, without its short step caption. For an
39
+ * action, an object with path_params, query and body.
40
+ */
28
41
  toolArgs: Record<string, unknown>;
42
+ /** JSON Schema of the tool's input, or null when the tool declares none. */
29
43
  toolInputSchema: Record<string, unknown> | null;
44
+ /**
45
+ * JSON Schema of the tool's output, or null when the tool declares none.
46
+ */
30
47
  toolOutputSchema: Record<string, unknown> | null;
48
+ /**
49
+ * The reason approval is needed, from the approval rules that raised it.
50
+ * May be empty; show a generic line such as "This tool needs your approval"
51
+ * then.
52
+ */
31
53
  prompt: string;
54
+ /**
55
+ * Id of the tool call waiting for approval, matching its row in the
56
+ * transcript, or null when there is none.
57
+ */
32
58
  toolCallId: string | null;
59
+ /**
60
+ * True when the waiting tool call has already appeared in the transcript on
61
+ * this connection, so the request can be shown beside that row.
62
+ */
33
63
  anchored: boolean;
64
+ /** Which step of the agent's run paused for this request. */
34
65
  round: number;
66
+ /** Id of the agent run that paused for this request. */
35
67
  runId: string;
68
+ /**
69
+ * True when the agent has stopped actively waiting for an answer. The
70
+ * request can still be answered, and answering resumes the reply.
71
+ */
36
72
  parked: boolean;
73
+ /**
74
+ * True when this action is set to ask for approval on every call; trust
75
+ * cannot skip it, so don't offer "don't ask again".
76
+ */
37
77
  gated: boolean;
78
+ /**
79
+ * True when you may offer "approve and don't ask again" for this tool (send
80
+ * trust with the approval).
81
+ */
38
82
  trustAvailable: boolean;
83
+ /**
84
+ * Where the request stands. actionable means waiting for a decision (with
85
+ * the last failed submit's error sentence, or null), submitting means
86
+ * sending, answered carries the decision, and stale means it can no longer
87
+ * be answered (expired or answered elsewhere).
88
+ */
39
89
  status: ApprovalCardStatus;
90
+ /**
91
+ * Who is asking, the assistant itself or one of its sub-agents (with its
92
+ * number and a label taken from its task), so the card can name it.
93
+ */
40
94
  asker: ApprovalAsker;
95
+ /**
96
+ * For a sub-agent's request, the turn the decision is sent to; null for the
97
+ * assistant's own requests.
98
+ */
41
99
  turnId: string | null;
42
100
  }
101
+ /** The visitor's answer to one approval request, passed to submitDecision. */
43
102
  export interface ApprovalDecisionInput {
103
+ /** True to let the call run, false to deny it. */
44
104
  approved: boolean;
105
+ /**
106
+ * With an approval, also stop asking about this tool for the rest of the
107
+ * conversation (or, for a sub-agent's request, the rest of its task). Only
108
+ * honored when the card's trustAvailable is true and gated is false.
109
+ */
45
110
  trust?: boolean;
111
+ /**
112
+ * For a denial, optional text telling the agent why; it is passed to the
113
+ * agent along with the refusal.
114
+ */
46
115
  feedback?: string;
47
116
  }
48
117
  export interface ApprovalInboxCapabilities {
@@ -63,6 +63,19 @@ class SessionEntry {
63
63
  });
64
64
  return fetch;
65
65
  }
66
+ async _ensureAttachmentPolicy() {
67
+ this.ensureAssistantConfig();
68
+ let flight = this._assistantConfigFetch;
69
+ while (flight !== null) {
70
+ await flight;
71
+ const current = this._assistantConfigFetch;
72
+ if (current === null || current === flight) {
73
+ break;
74
+ }
75
+ flight = current;
76
+ }
77
+ return this._attachmentPolicyCell.get();
78
+ }
66
79
  ensureSubscriptions = () => {
67
80
  this._subscriptionsFetch ??= this._fetchSubscriptions();
68
81
  };
@@ -171,6 +184,8 @@ class SessionEntry {
171
184
  }
172
185
  },
173
186
  onTurnSettled: this._onTurnSettled,
187
+ attachmentPolicy: this._attachmentPolicyCell,
188
+ ensureAttachmentPolicy: () => this._ensureAttachmentPolicy(),
174
189
  });
175
190
  }
176
191
  _resolveEndUserToken() {
@@ -0,0 +1,82 @@
1
+ import { ASSISTANT_MAX_ATTACHMENTS } from "../contract/threads.js";
2
+ import { humanFileSize } from "../components/human-file-size.js";
3
+ import { capSlotsSpentBy, mintAttachmentDraftId, pickCapOf, } from "./composer-policy.js";
4
+ const ATTACHMENTS_UNAVAILABLE_SENTENCE = "Attachments aren't available right now.";
5
+ const UPLOAD_FAILED_SENTENCE = "The upload failed.";
6
+ export function attachmentRoomOf(policy) {
7
+ return Math.min(policy.max_per_message, ASSISTANT_MAX_ATTACHMENTS);
8
+ }
9
+ function attachmentTooLargeSentence(cap) {
10
+ return `Too large — the limit for ${cap.label} is ${humanFileSize(cap.bytes)}.`;
11
+ }
12
+ function tooManyAttachmentsSentence(room) {
13
+ return `Too many files — the limit is ${String(room)} per message.`;
14
+ }
15
+ export async function addComposerFilesFromStore(store, files) {
16
+ const picked = [...files];
17
+ if (picked.length === 0) {
18
+ return;
19
+ }
20
+ const resets = store._composerInputResets;
21
+ const policy = store.deps.attachmentPolicy.get() ??
22
+ (await store.deps.ensureAttachmentPolicy());
23
+ if (store._composerInputResets !== resets) {
24
+ return;
25
+ }
26
+ if (policy === null) {
27
+ _appendDrafts(store, picked.map((file) => _failedDraft(_uploadingDraftFor(file), ATTACHMENTS_UNAVAILABLE_SENTENCE)));
28
+ return;
29
+ }
30
+ const room = attachmentRoomOf(policy);
31
+ let taken = capSlotsSpentBy(store._composerInput.get().attachments);
32
+ const settling = [];
33
+ for (const file of picked) {
34
+ const entry = _uploadingDraftFor(file);
35
+ if (taken >= room) {
36
+ _appendDrafts(store, [
37
+ _failedDraft(entry, tooManyAttachmentsSentence(room)),
38
+ ]);
39
+ continue;
40
+ }
41
+ const cap = pickCapOf(file, policy.max_bytes_by_kind);
42
+ if (file.size > cap.bytes) {
43
+ _appendDrafts(store, [
44
+ _failedDraft(entry, attachmentTooLargeSentence(cap)),
45
+ ]);
46
+ continue;
47
+ }
48
+ taken += 1;
49
+ _appendDrafts(store, [entry]);
50
+ settling.push(_uploadDraft(store, file, entry.localId));
51
+ }
52
+ await Promise.all(settling);
53
+ }
54
+ function _uploadingDraftFor(file) {
55
+ return {
56
+ localId: mintAttachmentDraftId(),
57
+ filename: file.name !== "" ? file.name : "attachment",
58
+ byteSize: file.size,
59
+ status: "uploading",
60
+ };
61
+ }
62
+ function _failedDraft(entry, error) {
63
+ return { ...entry, status: "failed", error };
64
+ }
65
+ function _appendDrafts(store, drafts) {
66
+ store.setComposerAttachments((current) => [...current, ...drafts]);
67
+ }
68
+ async function _uploadDraft(store, file, localId) {
69
+ try {
70
+ const settled = await store.uploadAttachment(file);
71
+ _settleDraft(store, localId, { status: "ready", attachment: settled });
72
+ }
73
+ catch (error) {
74
+ _settleDraft(store, localId, {
75
+ status: "failed",
76
+ error: error instanceof Error ? error.message : UPLOAD_FAILED_SENTENCE,
77
+ });
78
+ }
79
+ }
80
+ function _settleDraft(store, localId, patch) {
81
+ store.setComposerAttachments((current) => current.map((item) => item.localId === localId ? { ...item, ...patch } : item));
82
+ }
@@ -20,6 +20,7 @@ export function setComposerAttachmentsFromStore(store, next) {
20
20
  }
21
21
  export function resetComposerInput(store, threadId) {
22
22
  store._composerCaretReturnPending = null;
23
+ store._composerInputResets += 1;
23
24
  store._composerInput.set({
24
25
  scope: threadId !== null
25
26
  ? `t:${threadId}`
@@ -1,12 +1,32 @@
1
1
  import { type ServingAttachment } from "../contract/threads.js";
2
2
  import type { AttachmentKind } from "../generated/models/index.js";
3
3
  export declare const CHARACTER_COUNT_VISIBLE_FROM: number;
4
+ /** One file staged in the composer for the next message. */
4
5
  export interface AttachmentDraft<A = ServingAttachment> {
6
+ /**
7
+ * An id for this file that is unique within the page, for React keys and
8
+ * for updating or removing it.
9
+ */
5
10
  localId: number;
11
+ /** The file's name as shown to the visitor. */
6
12
  filename: string;
13
+ /** The file's size in bytes. */
7
14
  byteSize: number;
15
+ /**
16
+ * uploading while the file is being uploaded, ready once it can be sent,
17
+ * failed if it was rejected or the upload failed. The package composer
18
+ * won't send while any file is uploading or failed.
19
+ */
8
20
  status: "uploading" | "ready" | "failed";
21
+ /**
22
+ * The uploaded attachment, set once status is ready; pass its id to
23
+ * sendMessage.
24
+ */
9
25
  attachment?: A;
26
+ /**
27
+ * Why the file failed, as a sentence for the visitor; set only when status
28
+ * is failed.
29
+ */
10
30
  error?: string;
11
31
  }
12
32
  export declare function mintAttachmentDraftId(): number;