@slices.sh/ai-chat 0.1.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 (393) hide show
  1. package/LICENSE +21 -0
  2. package/dist/exports.json +794 -0
  3. package/dist/fixture/fixture-approval.d.ts +4 -0
  4. package/dist/fixture/fixture-approval.js +59 -0
  5. package/dist/fixture/fixture-artifacts.d.ts +2 -0
  6. package/dist/fixture/fixture-artifacts.js +48 -0
  7. package/dist/fixture/fixture-question.d.ts +5 -0
  8. package/dist/fixture/fixture-question.js +93 -0
  9. package/dist/fixture/fixture-script.d.ts +35 -0
  10. package/dist/fixture/fixture-script.js +280 -0
  11. package/dist/fixture/fixture-selection.d.ts +5 -0
  12. package/dist/fixture/fixture-selection.js +20 -0
  13. package/dist/fixture/fixture.d.ts +20 -0
  14. package/dist/fixture/fixture.js +75 -0
  15. package/dist/fixture/provider.d.ts +15 -0
  16. package/dist/fixture/provider.js +14 -0
  17. package/dist/headless/always-allow.d.ts +2 -0
  18. package/dist/headless/always-allow.js +24 -0
  19. package/dist/headless/answer.d.ts +6 -0
  20. package/dist/headless/answer.js +29 -0
  21. package/dist/headless/approval-error.d.ts +2 -0
  22. package/dist/headless/approval-error.js +16 -0
  23. package/dist/headless/approval-reason.d.ts +2 -0
  24. package/dist/headless/approval-reason.js +13 -0
  25. package/dist/headless/approval-receipt.d.ts +4 -0
  26. package/dist/headless/approval-receipt.js +13 -0
  27. package/dist/headless/approve.d.ts +4 -0
  28. package/dist/headless/approve.js +15 -0
  29. package/dist/headless/branch-navigation.d.ts +2 -0
  30. package/dist/headless/branch-navigation.js +11 -0
  31. package/dist/headless/branch-next.d.ts +2 -0
  32. package/dist/headless/branch-next.js +21 -0
  33. package/dist/headless/branch-page.d.ts +5 -0
  34. package/dist/headless/branch-page.js +13 -0
  35. package/dist/headless/branch-previous.d.ts +2 -0
  36. package/dist/headless/branch-previous.js +21 -0
  37. package/dist/headless/cancel-edit.d.ts +2 -0
  38. package/dist/headless/cancel-edit.js +10 -0
  39. package/dist/headless/cancel-queue-edit.d.ts +2 -0
  40. package/dist/headless/cancel-queue-edit.js +15 -0
  41. package/dist/headless/cancel-queued.d.ts +2 -0
  42. package/dist/headless/cancel-queued.js +15 -0
  43. package/dist/headless/chat-dictation/confirm.d.ts +2 -0
  44. package/dist/headless/chat-dictation/confirm.js +14 -0
  45. package/dist/headless/chat-dictation/index.d.ts +12 -0
  46. package/dist/headless/chat-dictation/index.js +9 -0
  47. package/dist/headless/chat-dictation/input.d.ts +3 -0
  48. package/dist/headless/chat-dictation/input.js +42 -0
  49. package/dist/headless/chat-dictation/root.d.ts +3 -0
  50. package/dist/headless/chat-dictation/root.js +42 -0
  51. package/dist/headless/chat-dictation/text.d.ts +3 -0
  52. package/dist/headless/chat-dictation/text.js +14 -0
  53. package/dist/headless/chat-dictation/voice.d.ts +3 -0
  54. package/dist/headless/chat-dictation/voice.js +35 -0
  55. package/dist/headless/citation-content.d.ts +3 -0
  56. package/dist/headless/citation-content.js +19 -0
  57. package/dist/headless/citation-description.d.ts +2 -0
  58. package/dist/headless/citation-description.js +12 -0
  59. package/dist/headless/citation-root.d.ts +2 -0
  60. package/dist/headless/citation-root.js +13 -0
  61. package/dist/headless/citation-title.d.ts +2 -0
  62. package/dist/headless/citation-title.js +12 -0
  63. package/dist/headless/citation-trigger.d.ts +2 -0
  64. package/dist/headless/citation-trigger.js +12 -0
  65. package/dist/headless/clear-answer.d.ts +5 -0
  66. package/dist/headless/clear-answer.js +19 -0
  67. package/dist/headless/composer-root.d.ts +14 -0
  68. package/dist/headless/composer-root.js +12 -0
  69. package/dist/headless/composer-standalone.d.ts +3 -0
  70. package/dist/headless/composer-standalone.js +10 -0
  71. package/dist/headless/composer.d.ts +3 -0
  72. package/dist/headless/composer.js +24 -0
  73. package/dist/headless/context-usage.d.ts +3 -0
  74. package/dist/headless/context-usage.js +13 -0
  75. package/dist/headless/contexts.d.ts +77 -0
  76. package/dist/headless/contexts.js +53 -0
  77. package/dist/headless/continue.d.ts +4 -0
  78. package/dist/headless/continue.js +26 -0
  79. package/dist/headless/copy.d.ts +11 -0
  80. package/dist/headless/copy.js +21 -0
  81. package/dist/headless/deny.d.ts +4 -0
  82. package/dist/headless/deny.js +15 -0
  83. package/dist/headless/edit-queued.d.ts +2 -0
  84. package/dist/headless/edit-queued.js +15 -0
  85. package/dist/headless/edit.d.ts +2 -0
  86. package/dist/headless/edit.js +17 -0
  87. package/dist/headless/edited-attachments.d.ts +5 -0
  88. package/dist/headless/edited-attachments.js +11 -0
  89. package/dist/headless/edited-input.d.ts +2 -0
  90. package/dist/headless/edited-input.js +28 -0
  91. package/dist/headless/empty.d.ts +3 -0
  92. package/dist/headless/empty.js +12 -0
  93. package/dist/headless/failed.d.ts +15 -0
  94. package/dist/headless/failed.js +17 -0
  95. package/dist/headless/feedback-error.d.ts +2 -0
  96. package/dist/headless/feedback-error.js +11 -0
  97. package/dist/headless/feedback-root.d.ts +2 -0
  98. package/dist/headless/feedback-root.js +24 -0
  99. package/dist/headless/feedback.d.ts +4 -0
  100. package/dist/headless/feedback.js +18 -0
  101. package/dist/headless/file-audio.d.ts +2 -0
  102. package/dist/headless/file-audio.js +16 -0
  103. package/dist/headless/file-context.d.ts +4 -0
  104. package/dist/headless/file-context.js +7 -0
  105. package/dist/headless/file-img.d.ts +2 -0
  106. package/dist/headless/file-img.js +21 -0
  107. package/dist/headless/file-kind-gate.d.ts +5 -0
  108. package/dist/headless/file-kind-gate.js +11 -0
  109. package/dist/headless/file-link.d.ts +3 -0
  110. package/dist/headless/file-link.js +14 -0
  111. package/dist/headless/file-root.d.ts +5 -0
  112. package/dist/headless/file-root.js +13 -0
  113. package/dist/headless/file-unavailable.d.ts +2 -0
  114. package/dist/headless/file-unavailable.js +12 -0
  115. package/dist/headless/file-video.d.ts +2 -0
  116. package/dist/headless/file-video.js +16 -0
  117. package/dist/headless/follow-ups.d.ts +5 -0
  118. package/dist/headless/follow-ups.js +20 -0
  119. package/dist/headless/forget-approval.d.ts +2 -0
  120. package/dist/headless/forget-approval.js +21 -0
  121. package/dist/headless/gate-content.d.ts +2 -0
  122. package/dist/headless/gate-content.js +6 -0
  123. package/dist/headless/index.d.ts +249 -0
  124. package/dist/headless/index.js +251 -0
  125. package/dist/headless/input.d.ts +11 -0
  126. package/dist/headless/input.js +18 -0
  127. package/dist/headless/jump-to-latest.d.ts +3 -0
  128. package/dist/headless/jump-to-latest.js +14 -0
  129. package/dist/headless/message-edit-root.d.ts +2 -0
  130. package/dist/headless/message-edit-root.js +13 -0
  131. package/dist/headless/message-editing.d.ts +2 -0
  132. package/dist/headless/message-editing.js +10 -0
  133. package/dist/headless/message-editor.d.ts +2 -0
  134. package/dist/headless/message-editor.js +19 -0
  135. package/dist/headless/message-footer.d.ts +3 -0
  136. package/dist/headless/message-footer.js +15 -0
  137. package/dist/headless/message-reading.d.ts +2 -0
  138. package/dist/headless/message-reading.js +10 -0
  139. package/dist/headless/message.d.ts +11 -0
  140. package/dist/headless/message.js +34 -0
  141. package/dist/headless/messages.d.ts +9 -0
  142. package/dist/headless/messages.js +19 -0
  143. package/dist/headless/model-picker.d.ts +2 -0
  144. package/dist/headless/model-picker.js +14 -0
  145. package/dist/headless/model.d.ts +4 -0
  146. package/dist/headless/model.js +13 -0
  147. package/dist/headless/models.d.ts +5 -0
  148. package/dist/headless/models.js +11 -0
  149. package/dist/headless/optional-tools.d.ts +7 -0
  150. package/dist/headless/optional-tools.js +12 -0
  151. package/dist/headless/other-answer.d.ts +5 -0
  152. package/dist/headless/other-answer.js +32 -0
  153. package/dist/headless/part-approval.d.ts +2 -0
  154. package/dist/headless/part-approval.js +33 -0
  155. package/dist/headless/part-file.d.ts +6 -0
  156. package/dist/headless/part-file.js +11 -0
  157. package/dist/headless/part-question.d.ts +2 -0
  158. package/dist/headless/part-question.js +57 -0
  159. package/dist/headless/part-reasoning.d.ts +15 -0
  160. package/dist/headless/part-reasoning.js +26 -0
  161. package/dist/headless/part-source.d.ts +5 -0
  162. package/dist/headless/part-source.js +20 -0
  163. package/dist/headless/part-text.d.ts +16 -0
  164. package/dist/headless/part-text.js +29 -0
  165. package/dist/headless/part-tool.d.ts +16 -0
  166. package/dist/headless/part-tool.js +14 -0
  167. package/dist/headless/parts.d.ts +11 -0
  168. package/dist/headless/parts.js +11 -0
  169. package/dist/headless/question-back.d.ts +2 -0
  170. package/dist/headless/question-back.js +16 -0
  171. package/dist/headless/question-error.d.ts +2 -0
  172. package/dist/headless/question-error.js +14 -0
  173. package/dist/headless/question-invalid.d.ts +8 -0
  174. package/dist/headless/question-invalid.js +18 -0
  175. package/dist/headless/question-item.d.ts +8 -0
  176. package/dist/headless/question-item.js +51 -0
  177. package/dist/headless/question-next.d.ts +3 -0
  178. package/dist/headless/question-next.js +16 -0
  179. package/dist/headless/question-other.d.ts +5 -0
  180. package/dist/headless/question-other.js +22 -0
  181. package/dist/headless/question-progress.d.ts +8 -0
  182. package/dist/headless/question-progress.js +14 -0
  183. package/dist/headless/question-receipt.d.ts +11 -0
  184. package/dist/headless/question-receipt.js +29 -0
  185. package/dist/headless/questions.d.ts +3 -0
  186. package/dist/headless/questions.js +13 -0
  187. package/dist/headless/queue-editing.d.ts +4 -0
  188. package/dist/headless/queue-editing.js +11 -0
  189. package/dist/headless/queue-item.d.ts +2 -0
  190. package/dist/headless/queue-item.js +10 -0
  191. package/dist/headless/queue-items.d.ts +2 -0
  192. package/dist/headless/queue-items.js +11 -0
  193. package/dist/headless/queue-preview.d.ts +6 -0
  194. package/dist/headless/queue-preview.js +11 -0
  195. package/dist/headless/queued-input.d.ts +2 -0
  196. package/dist/headless/queued-input.js +27 -0
  197. package/dist/headless/queued.d.ts +17 -0
  198. package/dist/headless/queued.js +16 -0
  199. package/dist/headless/read-aloud.d.ts +5 -0
  200. package/dist/headless/read-aloud.js +19 -0
  201. package/dist/headless/reasoning-disclosure.d.ts +3 -0
  202. package/dist/headless/reasoning-disclosure.js +17 -0
  203. package/dist/headless/reasoning-timer.d.ts +5 -0
  204. package/dist/headless/reasoning-timer.js +13 -0
  205. package/dist/headless/references.d.ts +6 -0
  206. package/dist/headless/references.js +13 -0
  207. package/dist/headless/regenerate.d.ts +3 -0
  208. package/dist/headless/regenerate.js +22 -0
  209. package/dist/headless/remembered-approval.d.ts +2 -0
  210. package/dist/headless/remembered-approval.js +14 -0
  211. package/dist/headless/root.d.ts +30 -0
  212. package/dist/headless/root.js +99 -0
  213. package/dist/headless/save-edit.d.ts +2 -0
  214. package/dist/headless/save-edit.js +16 -0
  215. package/dist/headless/save-queued.d.ts +2 -0
  216. package/dist/headless/save-queued.js +15 -0
  217. package/dist/headless/send-now.d.ts +2 -0
  218. package/dist/headless/send-now.js +17 -0
  219. package/dist/headless/settings.d.ts +2 -0
  220. package/dist/headless/settings.js +10 -0
  221. package/dist/headless/skip-questions.d.ts +6 -0
  222. package/dist/headless/skip-questions.js +18 -0
  223. package/dist/headless/source-context.d.ts +5 -0
  224. package/dist/headless/source-context.js +9 -0
  225. package/dist/headless/source-link.d.ts +2 -0
  226. package/dist/headless/source-link.js +13 -0
  227. package/dist/headless/source-primitives.d.ts +1 -0
  228. package/dist/headless/source-primitives.js +7 -0
  229. package/dist/headless/source-root.d.ts +5 -0
  230. package/dist/headless/source-root.js +9 -0
  231. package/dist/headless/source-sheet-close.d.ts +2 -0
  232. package/dist/headless/source-sheet-close.js +12 -0
  233. package/dist/headless/source-sheet-content.d.ts +3 -0
  234. package/dist/headless/source-sheet-content.js +16 -0
  235. package/dist/headless/source-sheet-description.d.ts +2 -0
  236. package/dist/headless/source-sheet-description.js +12 -0
  237. package/dist/headless/source-sheet-root.d.ts +2 -0
  238. package/dist/headless/source-sheet-root.js +13 -0
  239. package/dist/headless/source-sheet-title.d.ts +2 -0
  240. package/dist/headless/source-sheet-title.js +12 -0
  241. package/dist/headless/source-sheet-trigger.d.ts +2 -0
  242. package/dist/headless/source-sheet-trigger.js +12 -0
  243. package/dist/headless/source-unavailable.d.ts +2 -0
  244. package/dist/headless/source-unavailable.js +9 -0
  245. package/dist/headless/sources.d.ts +14 -0
  246. package/dist/headless/sources.js +12 -0
  247. package/dist/headless/speaker.d.ts +13 -0
  248. package/dist/headless/speaker.js +10 -0
  249. package/dist/headless/step-boundary.d.ts +4 -0
  250. package/dist/headless/step-boundary.js +16 -0
  251. package/dist/headless/stop.d.ts +10 -0
  252. package/dist/headless/stop.js +18 -0
  253. package/dist/headless/stopped.d.ts +11 -0
  254. package/dist/headless/stopped.js +17 -0
  255. package/dist/headless/submit-answers.d.ts +3 -0
  256. package/dist/headless/submit-answers.js +12 -0
  257. package/dist/headless/submit.d.ts +23 -0
  258. package/dist/headless/submit.js +24 -0
  259. package/dist/headless/suggestion.d.ts +10 -0
  260. package/dist/headless/suggestion.js +14 -0
  261. package/dist/headless/suggestions.d.ts +8 -0
  262. package/dist/headless/suggestions.js +12 -0
  263. package/dist/headless/thread.d.ts +3 -0
  264. package/dist/headless/thread.js +25 -0
  265. package/dist/headless/timing.d.ts +5 -0
  266. package/dist/headless/timing.js +13 -0
  267. package/dist/headless/toggle-tool.d.ts +4 -0
  268. package/dist/headless/toggle-tool.js +15 -0
  269. package/dist/headless/tool-error.d.ts +4 -0
  270. package/dist/headless/tool-error.js +13 -0
  271. package/dist/headless/tool-input.d.ts +4 -0
  272. package/dist/headless/tool-input.js +13 -0
  273. package/dist/headless/tool-output.d.ts +4 -0
  274. package/dist/headless/tool-output.js +13 -0
  275. package/dist/headless/tool-renderer.d.ts +13 -0
  276. package/dist/headless/tool-renderer.js +15 -0
  277. package/dist/headless/transcript.d.ts +23 -0
  278. package/dist/headless/transcript.js +24 -0
  279. package/dist/headless/try-again.d.ts +2 -0
  280. package/dist/headless/try-again.js +24 -0
  281. package/dist/headless/unavailable.d.ts +8 -0
  282. package/dist/headless/unavailable.js +9 -0
  283. package/dist/headless/usage.d.ts +13 -0
  284. package/dist/headless/usage.js +15 -0
  285. package/dist/headless/use-merged-ref.d.ts +2 -0
  286. package/dist/headless/use-merged-ref.js +17 -0
  287. package/dist/headless/use-question.d.ts +3 -0
  288. package/dist/headless/use-question.js +9 -0
  289. package/dist/headless/waiting.d.ts +13 -0
  290. package/dist/headless/waiting.js +12 -0
  291. package/dist/headless/writing.d.ts +13 -0
  292. package/dist/headless/writing.js +12 -0
  293. package/dist/hooks/chat-refusal.d.ts +18 -0
  294. package/dist/hooks/chat-refusal.js +44 -0
  295. package/dist/hooks/turn-mailbox.d.ts +14 -0
  296. package/dist/hooks/turn-mailbox.js +114 -0
  297. package/dist/hooks/use-branches.d.ts +10 -0
  298. package/dist/hooks/use-branches.js +69 -0
  299. package/dist/hooks/use-chat-instance.d.ts +28 -0
  300. package/dist/hooks/use-chat-instance.js +44 -0
  301. package/dist/hooks/use-chat-settings.d.ts +11 -0
  302. package/dist/hooks/use-chat-settings.js +33 -0
  303. package/dist/hooks/use-chat-sink.d.ts +19 -0
  304. package/dist/hooks/use-chat-sink.js +56 -0
  305. package/dist/hooks/use-composer.d.ts +33 -0
  306. package/dist/hooks/use-composer.js +45 -0
  307. package/dist/hooks/use-context-usage.d.ts +8 -0
  308. package/dist/hooks/use-context-usage.js +14 -0
  309. package/dist/hooks/use-copied.d.ts +14 -0
  310. package/dist/hooks/use-copied.js +22 -0
  311. package/dist/hooks/use-draft.d.ts +6 -0
  312. package/dist/hooks/use-draft.js +38 -0
  313. package/dist/hooks/use-feedback.d.ts +8 -0
  314. package/dist/hooks/use-feedback.js +28 -0
  315. package/dist/hooks/use-follow.d.ts +15 -0
  316. package/dist/hooks/use-follow.js +30 -0
  317. package/dist/hooks/use-media-load.d.ts +5 -0
  318. package/dist/hooks/use-media-load.js +12 -0
  319. package/dist/hooks/use-media.d.ts +3 -0
  320. package/dist/hooks/use-media.js +9 -0
  321. package/dist/hooks/use-question-check.d.ts +11 -0
  322. package/dist/hooks/use-question-check.js +29 -0
  323. package/dist/hooks/use-question-draft.d.ts +34 -0
  324. package/dist/hooks/use-question-draft.js +57 -0
  325. package/dist/hooks/use-question-steps.d.ts +18 -0
  326. package/dist/hooks/use-question-steps.js +31 -0
  327. package/dist/hooks/use-question-write.d.ts +8 -0
  328. package/dist/hooks/use-question-write.js +25 -0
  329. package/dist/hooks/use-read-aloud.d.ts +8 -0
  330. package/dist/hooks/use-read-aloud.js +60 -0
  331. package/dist/hooks/use-reasoning.d.ts +8 -0
  332. package/dist/hooks/use-reasoning.js +32 -0
  333. package/dist/hooks/use-remembered-approvals.d.ts +9 -0
  334. package/dist/hooks/use-remembered-approvals.js +40 -0
  335. package/dist/hooks/use-reply.d.ts +3 -0
  336. package/dist/hooks/use-reply.js +9 -0
  337. package/dist/hooks/use-report-missing-configuration.d.ts +9 -0
  338. package/dist/hooks/use-report-missing-configuration.js +14 -0
  339. package/dist/hooks/use-retry-delay.d.ts +5 -0
  340. package/dist/hooks/use-retry-delay.js +17 -0
  341. package/dist/hooks/use-sent-draft.d.ts +8 -0
  342. package/dist/hooks/use-sent-draft.js +25 -0
  343. package/dist/hooks/use-source-disclosure.d.ts +5 -0
  344. package/dist/hooks/use-source-disclosure.js +9 -0
  345. package/dist/hooks/use-sources.d.ts +3 -0
  346. package/dist/hooks/use-sources.js +9 -0
  347. package/dist/hooks/use-tool-approval-memory.d.ts +8 -0
  348. package/dist/hooks/use-tool-approval-memory.js +16 -0
  349. package/dist/hooks/use-tool-approval.d.ts +10 -0
  350. package/dist/hooks/use-tool-approval.js +26 -0
  351. package/dist/hooks/use-turn-queue.d.ts +32 -0
  352. package/dist/hooks/use-turn-queue.js +33 -0
  353. package/dist/index.d.ts +10 -0
  354. package/dist/index.js +5 -0
  355. package/dist/next.d.ts +43 -0
  356. package/dist/next.js +10 -0
  357. package/dist/services/approval-memory.d.ts +9 -0
  358. package/dist/services/approval-memory.js +32 -0
  359. package/dist/services/approval.d.ts +14 -0
  360. package/dist/services/approval.js +37 -0
  361. package/dist/services/branches.d.ts +27 -0
  362. package/dist/services/branches.js +131 -0
  363. package/dist/services/chat-session.d.ts +20 -0
  364. package/dist/services/chat-session.js +61 -0
  365. package/dist/services/choices.d.ts +31 -0
  366. package/dist/services/choices.js +39 -0
  367. package/dist/services/continue.d.ts +8 -0
  368. package/dist/services/continue.js +24 -0
  369. package/dist/services/errors.d.ts +52 -0
  370. package/dist/services/errors.js +54 -0
  371. package/dist/services/media.d.ts +9 -0
  372. package/dist/services/media.js +19 -0
  373. package/dist/services/messages.d.ts +44 -0
  374. package/dist/services/messages.js +0 -0
  375. package/dist/services/optional.d.ts +7 -0
  376. package/dist/services/optional.js +7 -0
  377. package/dist/services/ports.d.ts +31 -0
  378. package/dist/services/ports.js +0 -0
  379. package/dist/services/questions.d.ts +67 -0
  380. package/dist/services/questions.js +119 -0
  381. package/dist/services/request.d.ts +26 -0
  382. package/dist/services/request.js +85 -0
  383. package/dist/services/selection.d.ts +10 -0
  384. package/dist/services/selection.js +49 -0
  385. package/dist/services/sources.d.ts +11 -0
  386. package/dist/services/sources.js +29 -0
  387. package/dist/services/tools.d.ts +11 -0
  388. package/dist/services/tools.js +0 -0
  389. package/dist/services/turn.d.ts +84 -0
  390. package/dist/services/turn.js +0 -0
  391. package/dist/services/types.d.ts +23 -0
  392. package/dist/services/types.js +15 -0
  393. package/package.json +822 -0
@@ -0,0 +1,4 @@
1
+ import { type UIMessageChunk } from "ai";
2
+ import type { AiChatMessage } from "../services/types";
3
+ export declare function approvalHistory(): AiChatMessage[];
4
+ export declare function approvalTurn(messages: AiChatMessage[]): UIMessageChunk[];
@@ -0,0 +1,59 @@
1
+ import { isToolUIPart } from "ai";
2
+ function approvalHistory() {
3
+ return [
4
+ { id: "approval-user", role: "user", parts: [{ type: "text", text: "Count the words in my draft." }] },
5
+ {
6
+ id: "approval-answer",
7
+ role: "assistant",
8
+ parts: [
9
+ {
10
+ type: "tool-count_words",
11
+ toolCallId: "approval-call",
12
+ state: "approval-requested",
13
+ input: { text: "A short draft" },
14
+ approval: { id: "approval-demo", requestReason: "This tool is configured to ask before it runs." }
15
+ }
16
+ ]
17
+ }
18
+ ];
19
+ }
20
+ function approvalTurn(messages) {
21
+ const last = messages.at(-1);
22
+ const decided = last?.parts.find((part) => isToolUIPart(part) && part.state === "approval-responded");
23
+ if (decided && isToolUIPart(decided) && decided.state === "approval-responded") {
24
+ const approved = decided.approval.approved;
25
+ return [
26
+ { type: "start", messageId: last.id },
27
+ approved ? { type: "tool-output-available", toolCallId: decided.toolCallId, output: { words: 3 } } : { type: "tool-output-denied", toolCallId: decided.toolCallId },
28
+ { type: "text-start", id: "decision" },
29
+ {
30
+ type: "text-delta",
31
+ id: "decision",
32
+ delta: approved ? "The tool was allowed and counted 3 words." : "The tool was denied and did not run."
33
+ },
34
+ { type: "text-end", id: "decision" },
35
+ { type: "finish" }
36
+ ];
37
+ }
38
+ const id = last?.id ?? "empty";
39
+ return [
40
+ { type: "start", messageId: "answer-" + id },
41
+ {
42
+ type: "tool-input-available",
43
+ toolCallId: "call-" + id,
44
+ toolName: "count_words",
45
+ input: { text: "A short draft" }
46
+ },
47
+ {
48
+ type: "tool-approval-request",
49
+ approvalId: "approval-" + id,
50
+ toolCallId: "call-" + id,
51
+ reason: "This tool is configured to ask before it runs."
52
+ },
53
+ { type: "finish", finishReason: "tool-calls" }
54
+ ];
55
+ }
56
+ export {
57
+ approvalHistory,
58
+ approvalTurn
59
+ };
@@ -0,0 +1,2 @@
1
+ import type { AiChatMessage } from "../services/types";
2
+ export declare function artifactHistory(): AiChatMessage[];
@@ -0,0 +1,48 @@
1
+ function artifactHistory() {
2
+ return [
3
+ {
4
+ id: "artifact-user",
5
+ role: "user",
6
+ parts: [{ type: "text", text: "Build a counter, then increase its initial value." }]
7
+ },
8
+ {
9
+ id: "artifact-first",
10
+ role: "assistant",
11
+ parts: [
12
+ {
13
+ type: "tool-createArtifact",
14
+ toolCallId: "artifact-v1",
15
+ state: "output-available",
16
+ input: {
17
+ artifactId: "counter",
18
+ title: "Counter",
19
+ code: "import React from 'react'\nexport default function App() { return <button>1</button> }",
20
+ summary: "First version"
21
+ },
22
+ output: { artifactId: "counter", recorded: true }
23
+ }
24
+ ]
25
+ },
26
+ {
27
+ id: "artifact-second",
28
+ role: "assistant",
29
+ parts: [
30
+ {
31
+ type: "tool-updateArtifact",
32
+ toolCallId: "artifact-v2",
33
+ state: "output-available",
34
+ input: {
35
+ artifactId: "counter",
36
+ title: "Counter",
37
+ code: "import React from 'react'\nexport default function App() { return <button>2</button> }",
38
+ summary: "Second version"
39
+ },
40
+ output: { artifactId: "counter", recorded: true }
41
+ }
42
+ ]
43
+ }
44
+ ];
45
+ }
46
+ export {
47
+ artifactHistory
48
+ };
@@ -0,0 +1,5 @@
1
+ import { type UIMessageChunk } from "ai";
2
+ import { type AiChatMessage, type Questionnaire } from "../services/types";
3
+ export declare const QUESTIONS: Questionnaire;
4
+ export declare function questionHistory(): AiChatMessage[];
5
+ export declare function questionTurn(messages: AiChatMessage[]): UIMessageChunk[];
@@ -0,0 +1,93 @@
1
+ import { getToolName, isToolUIPart } from "ai";
2
+ import { isSkippedQuestion } from "../services/types.js";
3
+ const QUESTIONS = {
4
+ title: "Plan your draft",
5
+ questions: [
6
+ {
7
+ name: "tone",
8
+ title: "Which tone?",
9
+ required: true,
10
+ choices: [
11
+ { value: "brief", label: "Brief" },
12
+ { value: "detailed", label: "Detailed" }
13
+ ]
14
+ },
15
+ {
16
+ name: "topics",
17
+ title: "Which topics?",
18
+ multiple: true,
19
+ choices: [
20
+ { value: "design", label: "Design" },
21
+ { value: "engineering", label: "Engineering" }
22
+ ],
23
+ other: "Another topic"
24
+ },
25
+ {
26
+ name: "audience",
27
+ title: "Who is it for?",
28
+ description: "The closest fit is enough.",
29
+ choices: [
30
+ { value: "team", label: "My team", description: "People who know the context" },
31
+ { value: "public", label: "The public", description: "Readers who start from nothing" }
32
+ ],
33
+ other: "Someone else"
34
+ }
35
+ ]
36
+ };
37
+ function questionHistory() {
38
+ return [
39
+ { id: "question-user", role: "user", parts: [{ type: "text", text: "Help me prepare a draft." }] },
40
+ {
41
+ id: "question-answer",
42
+ role: "assistant",
43
+ parts: [
44
+ {
45
+ type: "tool-askQuestions",
46
+ toolCallId: "question-call",
47
+ state: "input-available",
48
+ input: QUESTIONS
49
+ }
50
+ ]
51
+ }
52
+ ];
53
+ }
54
+ function questionTurn(messages) {
55
+ const last = messages.at(-1);
56
+ const answered = last?.parts.find(
57
+ (part) => isToolUIPart(part) && getToolName(part) === "askQuestions" && part.state === "output-available"
58
+ );
59
+ if (messages.some((message) => message.parts.some(isSkippedQuestion)))
60
+ return [
61
+ { type: "start", messageId: last?.role === "assistant" ? last.id : "skipped-" + (last?.id ?? "empty") },
62
+ { type: "start-step" },
63
+ { type: "text-start", id: "answer" },
64
+ { type: "text-delta", id: "answer", delta: "No problem. I will carry on without your answers." },
65
+ { type: "text-end", id: "answer" },
66
+ { type: "finish" }
67
+ ];
68
+ if (answered)
69
+ return [
70
+ { type: "start", messageId: last.id },
71
+ { type: "start-step" },
72
+ { type: "text-start", id: "answer" },
73
+ { type: "text-delta", id: "answer", delta: "Thanks. I will use your answers for the draft." },
74
+ { type: "text-end", id: "answer" },
75
+ { type: "finish" }
76
+ ];
77
+ const id = last?.id ?? "empty";
78
+ return [
79
+ { type: "start", messageId: "answer-" + id },
80
+ {
81
+ type: "tool-input-available",
82
+ toolCallId: "question-" + id,
83
+ toolName: "askQuestions",
84
+ input: QUESTIONS
85
+ },
86
+ { type: "finish", finishReason: "tool-calls" }
87
+ ];
88
+ }
89
+ export {
90
+ QUESTIONS,
91
+ questionHistory,
92
+ questionTurn
93
+ };
@@ -0,0 +1,35 @@
1
+ import type { UIMessageChunk } from "ai";
2
+ import { type MissingConfigurationAnswer } from "@slices.sh/core/configuration";
3
+ import { ChatError, type AiChatMessage } from "../services/types";
4
+ /**
5
+ * What a fixture chat does, per scenario.
6
+ *
7
+ * A scenario is a state the screen can be in, not a story: `failed` is what the error banner
8
+ * looks like, `rate-limited` is the one refusal with a different shape of answer, `slow` is
9
+ * the one where stopping mid-answer is worth trying, `rich` is a turn with everything on it —
10
+ * markdown, a reasoning trace, a tool call, citations and a token count — and `interrupted`
11
+ * is what a reply that was stopped looks like after the fact. `missing-configuration` is a
12
+ * server that has no key for its model, which answers `config/missing` rather than a refusal
13
+ * of its own.
14
+ */
15
+ export declare const CHAT_SCENARIOS: readonly ["ready", "approval", "questions", "empty", "rich", "artifacts", "slow", "interrupted", "failed", "rate-limited", "quota-exceeded", "unknown-chat", "missing-configuration"];
16
+ export type ChatScenario = (typeof CHAT_SCENARIOS)[number];
17
+ export type Script = {
18
+ /** What the transcript already holds when the screen mounts. */
19
+ history: AiChatMessage[];
20
+ /** Milliseconds between words. */
21
+ pace: number;
22
+ refuse: ChatError | MissingConfigurationAnswer | null;
23
+ /** Whether the answer arrives with a trace, a tool call, citations and a count. */
24
+ rich: boolean;
25
+ };
26
+ export declare function scriptFor(scenario: ChatScenario): Script;
27
+ /**
28
+ * The answer a question gets, as the chunks a route streams for it.
29
+ *
30
+ * The same vocabulary a model's turn arrives in, in the same order — a `start`, a trace
31
+ * opened and closed, a tool call's input and then its output under one id, the prose, the
32
+ * citations, and a `finish` carrying what it cost — so the chat state the SDK builds from it
33
+ * is the state it builds from a provider.
34
+ */
35
+ export declare function turnOf(messages: AiChatMessage[], rich: boolean): UIMessageChunk[];
@@ -0,0 +1,280 @@
1
+ import { artifactHistory } from "./fixture-artifacts.js";
2
+ import { questionHistory } from "./fixture-question.js";
3
+ import { approvalHistory } from "./fixture-approval.js";
4
+ import { MISSING_CONFIGURATION } from "@slices.sh/core/configuration";
5
+ import { ChatError } from "../services/types.js";
6
+ const CHAT_SCENARIOS = [
7
+ "ready",
8
+ "approval",
9
+ "questions",
10
+ "empty",
11
+ "rich",
12
+ "artifacts",
13
+ "slow",
14
+ "interrupted",
15
+ "failed",
16
+ "rate-limited",
17
+ "quota-exceeded",
18
+ "unknown-chat",
19
+ "missing-configuration"
20
+ ];
21
+ const CONVERSATION = [
22
+ said("you-1", "user", "What is in this transcript?"),
23
+ said(
24
+ "answer-1",
25
+ "assistant",
26
+ "Two messages, so far: yours and this one. Everything you see is the AI SDK's own chat and the real parts \u2014 only the backend is a fixture, so the stream, the stop button and the error states behave the way they will against a model."
27
+ )
28
+ ];
29
+ const RICH = [
30
+ {
31
+ id: "you-1",
32
+ role: "user",
33
+ parts: [
34
+ {
35
+ type: "file",
36
+ filename: "brief.pdf",
37
+ mediaType: "application/pdf",
38
+ url: "https://example.com/brief.pdf"
39
+ },
40
+ { type: "text", text: "Show me what a turn can carry." }
41
+ ]
42
+ },
43
+ {
44
+ id: "answer-1",
45
+ role: "assistant",
46
+ parts: [
47
+ { type: "step-start" },
48
+ { type: "reasoning", text: "Read the contract, then answer with one of each part.", state: "done" },
49
+ {
50
+ type: "tool-search_docs",
51
+ toolCallId: "search",
52
+ state: "output-available",
53
+ input: { query: "error slugs" },
54
+ output: { found: 3 }
55
+ },
56
+ { type: "step-start" },
57
+ {
58
+ type: "text",
59
+ state: "done",
60
+ text: [
61
+ "A turn carries **more than prose**. This message has all of it:",
62
+ "",
63
+ "| Part | Where it came from |",
64
+ "|---|---|",
65
+ "| reasoning | `reasoning-delta`, collapsed once the answer starts |",
66
+ "| tool | `tool-input-available` then `tool-output-available`, one card either way |",
67
+ "| source | `source-url`, collected into the footer below |",
68
+ "",
69
+ "```ts",
70
+ "const { messages, status, stop } = useChat({ chat })",
71
+ "```",
72
+ "",
73
+ "- markdown renders while it arrives",
74
+ "",
75
+ "An optional formula: $$E = mc^2$$.",
76
+ "",
77
+ "```mermaid",
78
+ "flowchart LR",
79
+ " Draft --> Review --> Publish",
80
+ "```",
81
+ "- a fence the next token would have closed still renders as code"
82
+ ].join("\n")
83
+ },
84
+ {
85
+ type: "source-url",
86
+ sourceId: "s1",
87
+ url: "https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol",
88
+ title: "Stream protocol"
89
+ },
90
+ {
91
+ type: "source-url",
92
+ sourceId: "s2",
93
+ url: "https://ai-sdk.dev/docs/ai-sdk-ui/chatbot-tool-usage",
94
+ title: "Tool usage"
95
+ },
96
+ {
97
+ type: "file",
98
+ filename: "fixture.png",
99
+ mediaType: "image/png",
100
+ url: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mP8/x8AAwMCAO+jRzEAAAAASUVORK5CYII="
101
+ },
102
+ {
103
+ type: "file",
104
+ filename: "guide.pdf",
105
+ mediaType: "application/pdf",
106
+ url: "https://example.com/guide.pdf"
107
+ }
108
+ ],
109
+ metadata: {
110
+ usage: counted(412, 190),
111
+ contextTokens: 412,
112
+ contextWindow: 8192,
113
+ model: "fixture-model",
114
+ followUps: ["Show a concrete example", "Summarize the key points"],
115
+ timing: { firstTokenMs: 250, durationMs: 1500 }
116
+ }
117
+ }
118
+ ];
119
+ const INTERRUPTED = [
120
+ said("you-1", "user", "Write me the whole contract."),
121
+ {
122
+ id: "answer-1",
123
+ role: "assistant",
124
+ parts: [
125
+ {
126
+ type: "text",
127
+ text: "The contract is one operation \u2014 run a turn \u2014 over a chat this app has config",
128
+ state: "streaming"
129
+ }
130
+ ]
131
+ }
132
+ ];
133
+ function scriptFor(scenario) {
134
+ const plain = { refuse: null, rich: false };
135
+ switch (scenario) {
136
+ case "artifacts":
137
+ return { history: artifactHistory(), pace: 5, ...plain };
138
+ case "questions":
139
+ return { history: questionHistory(), pace: 5, ...plain };
140
+ case "approval":
141
+ return { history: approvalHistory(), pace: 5, ...plain };
142
+ case "empty":
143
+ return { history: [], pace: 18, ...plain };
144
+ case "rich":
145
+ return { history: RICH, pace: 24, refuse: null, rich: true };
146
+ case "slow":
147
+ return { history: CONVERSATION, pace: 90, ...plain };
148
+ case "interrupted":
149
+ return { history: INTERRUPTED, pace: 18, ...plain };
150
+ case "failed":
151
+ return {
152
+ history: CONVERSATION,
153
+ pace: 18,
154
+ rich: false,
155
+ refuse: new ChatError("ai-chat/model-unavailable", "The model is not answering right now.")
156
+ };
157
+ case "rate-limited":
158
+ return {
159
+ history: CONVERSATION,
160
+ pace: 18,
161
+ rich: false,
162
+ refuse: new ChatError("ai-chat/rate-limited", "That is a lot of questions. Try again in a minute.")
163
+ };
164
+ case "quota-exceeded":
165
+ return {
166
+ history: CONVERSATION,
167
+ pace: 18,
168
+ rich: false,
169
+ refuse: new ChatError(
170
+ "ai-chat/quota-exceeded",
171
+ "This workspace has used its messages for the month."
172
+ )
173
+ };
174
+ case "unknown-chat":
175
+ return {
176
+ history: [],
177
+ pace: 18,
178
+ rich: false,
179
+ refuse: new ChatError("ai-chat/unknown-chat", "No chat is configured under that name.")
180
+ };
181
+ case "missing-configuration":
182
+ return {
183
+ history: CONVERSATION,
184
+ pace: 18,
185
+ rich: false,
186
+ refuse: {
187
+ error: MISSING_CONFIGURATION,
188
+ scope: "ai-chat",
189
+ message: "This component requires extra server configuration to work properly. If you're the developer, see the logs. If you're a user, please report it!"
190
+ }
191
+ };
192
+ default:
193
+ return { history: CONVERSATION, pace: 18, ...plain };
194
+ }
195
+ }
196
+ function turnOf(messages, rich) {
197
+ const asked = askedIn(messages);
198
+ const chunks = [{ type: "start", messageId: `answer-${messages.length}` }];
199
+ if (rich) {
200
+ chunks.push(
201
+ { type: "reasoning-start", id: "plan" },
202
+ ...pieces("Count the words, then answer in markdown.").map((delta) => ({
203
+ type: "reasoning-delta",
204
+ id: "plan",
205
+ delta
206
+ })),
207
+ { type: "reasoning-end", id: "plan" },
208
+ { type: "tool-input-available", toolCallId: "count", toolName: "count_words", input: { text: asked } },
209
+ { type: "tool-output-available", toolCallId: "count", output: { words: wordsIn(asked) } }
210
+ );
211
+ }
212
+ chunks.push(
213
+ { type: "text-start", id: "answer" },
214
+ ...pieces(answerTo(asked)).map((delta) => ({ type: "text-delta", id: "answer", delta })),
215
+ { type: "text-end", id: "answer" }
216
+ );
217
+ if (rich)
218
+ chunks.push({
219
+ type: "source-url",
220
+ sourceId: "protocol",
221
+ url: "https://ai-sdk.dev/docs/ai-sdk-ui/stream-protocol",
222
+ title: "Stream protocol"
223
+ });
224
+ chunks.push({
225
+ type: "finish",
226
+ finishReason: "stop",
227
+ ...rich ? {
228
+ messageMetadata: {
229
+ usage: counted(412, 190),
230
+ contextTokens: 412,
231
+ contextWindow: 8192,
232
+ model: "fixture-model",
233
+ followUps: ["Show a concrete example", "Summarize the key points"],
234
+ timing: { firstTokenMs: 250, durationMs: 1500 }
235
+ }
236
+ } : {}
237
+ });
238
+ return chunks;
239
+ }
240
+ function answerTo(asked) {
241
+ const words = wordsIn(asked);
242
+ return [
243
+ `You asked ${words} word${words === 1 ? "" : "s"}: **"${asked.trim()}"**`,
244
+ "",
245
+ "This preview has no model behind it. What it does have is the same chat, transcript,",
246
+ "composer, status and error parts the installed component has \u2014 so stopping this",
247
+ "mid-sentence, or typing again before it finishes, does here what it will do in your app."
248
+ ].join("\n");
249
+ }
250
+ function askedIn(messages) {
251
+ const asked = messages.findLast((message) => message.role === "user");
252
+ return (asked?.parts ?? []).map((part) => part.type === "text" ? part.text : "").join("");
253
+ }
254
+ function wordsIn(text) {
255
+ return text.trim().split(/\s+/).filter(Boolean).length;
256
+ }
257
+ function pieces(text) {
258
+ return text.split(/(?<=\s)/);
259
+ }
260
+ function counted(input, output) {
261
+ return {
262
+ inputTokens: input,
263
+ inputTokenDetails: { noCacheTokens: input, cacheReadTokens: void 0, cacheWriteTokens: void 0 },
264
+ outputTokens: output,
265
+ outputTokenDetails: { textTokens: output, reasoningTokens: void 0 },
266
+ totalTokens: input + output
267
+ };
268
+ }
269
+ function said(id, role, text) {
270
+ return {
271
+ id,
272
+ role,
273
+ parts: [{ type: "text", text, ...role === "assistant" ? { state: "done" } : {} }]
274
+ };
275
+ }
276
+ export {
277
+ CHAT_SCENARIOS,
278
+ scriptFor,
279
+ turnOf
280
+ };
@@ -0,0 +1,5 @@
1
+ import type { UIMessageChunk } from "ai";
2
+ import type { ChatChoices, ChatSelection } from "../services/types";
3
+ export declare const fixtureChoices: ChatChoices;
4
+ /** Scripted model variants and actual optional tool chunks, never pretend live inference. */
5
+ export declare function chosenChunks(chunks: UIMessageChunk[], selection?: ChatSelection): UIMessageChunk[];
@@ -0,0 +1,20 @@
1
+ const fixtureChoices = {
2
+ models: [
3
+ { id: "", label: "Standard fixture", contextWindow: 8192 },
4
+ { id: "detailed", label: "Detailed fixture", contextWindow: 8192 }
5
+ ],
6
+ tools: [{ id: "count_words", label: "Word count", defaultEnabled: true }]
7
+ };
8
+ function chosenChunks(chunks, selection) {
9
+ return chunks.flatMap((chunk) => {
10
+ if (selection?.tools && !selection.tools.includes("count_words") && "toolCallId" in chunk && chunk.toolCallId === "count") return [];
11
+ if (selection?.model !== "detailed") return [chunk];
12
+ if (chunk.type === "text-start") return [chunk, { type: "text-delta", id: chunk.id, delta: "Detailed fixture response: " }];
13
+ if (chunk.type === "finish") return [{ ...chunk, messageMetadata: { ...chunk.messageMetadata, model: "fixture-detailed" } }];
14
+ return [chunk];
15
+ });
16
+ }
17
+ export {
18
+ chosenChunks,
19
+ fixtureChoices
20
+ };
@@ -0,0 +1,20 @@
1
+ import type { AiChatClient } from "../services/types";
2
+ import { type ChatTransport } from "ai";
3
+ import { CHAT_SCENARIOS, type ChatScenario } from "./fixture-script";
4
+ import { type AiChatMessage } from "../services/types";
5
+ export { CHAT_SCENARIOS };
6
+ export type { ChatScenario };
7
+ /**
8
+ * A chat backend that answers in the browser, so a preview or a test runs the AI SDK's own
9
+ * `Chat` and the real parts with no route and no key.
10
+ *
11
+ * It is a `ChatTransport` — the SDK's own seam for "something else answers" — rather than a
12
+ * mock of anything above it: the chat state, the stop, the part states and the error branch
13
+ * are the SDK's, and the chunks are the ones a route streams. Hand both to a chat:
14
+ * `new Chat({ transport, messages })`. → docs/concepts/fixtures.md
15
+ */
16
+ export declare function createAiChatFixture(scenario?: ChatScenario): {
17
+ transport: ChatTransport<AiChatMessage>;
18
+ messages: AiChatMessage[];
19
+ client: AiChatClient;
20
+ };
@@ -0,0 +1,75 @@
1
+ import { fixtureChoices, chosenChunks } from "./fixture-selection.js";
2
+ import { questionTurn } from "./fixture-question.js";
3
+ import { approvalTurn } from "./fixture-approval.js";
4
+ import { APICallError } from "ai";
5
+ import { forgetMissingConfiguration } from "@slices.sh/core/configuration";
6
+ import { CHAT_SCENARIOS, scriptFor, turnOf } from "./fixture-script.js";
7
+ import { refusalText, statusForChatError } from "../services/types.js";
8
+ function createAiChatFixture(scenario = "ready") {
9
+ const script = scriptFor(scenario);
10
+ forgetMissingConfiguration();
11
+ const transport = {
12
+ async sendMessages({ messages, abortSignal, body }) {
13
+ await wait(script.pace * 4, abortSignal);
14
+ if (script.refuse) throw refused(script.refuse);
15
+ return paced(
16
+ scenario === "questions" ? questionTurn(messages) : scenario === "approval" ? approvalTurn(messages) : chosenChunks(turnOf(messages, script.rich), body?.selection),
17
+ script.pace,
18
+ abortSignal
19
+ );
20
+ },
21
+ // Nothing outlives a page here, so there is never a stream to go back to.
22
+ async reconnectToStream() {
23
+ return null;
24
+ }
25
+ };
26
+ const client = {
27
+ transportFor: () => transport,
28
+ choicesFor: async () => scenario === "rich" ? fixtureChoices : null
29
+ };
30
+ return { transport, messages: script.history, client };
31
+ }
32
+ function refused(error) {
33
+ const typed = error instanceof Error;
34
+ const body = typed ? refusalText(error) : JSON.stringify(error);
35
+ return new APICallError({
36
+ message: body,
37
+ url: "fixture",
38
+ requestBodyValues: void 0,
39
+ statusCode: typed ? statusForChatError[error.slug] : 503,
40
+ responseBody: body
41
+ });
42
+ }
43
+ function paced(chunks, pace, signal) {
44
+ let next = 0;
45
+ return new ReadableStream({
46
+ async pull(controller) {
47
+ const chunk = chunks[next++];
48
+ if (!chunk) return controller.close();
49
+ try {
50
+ await wait(chunk.type.endsWith("-delta") ? pace : pace * 3, signal);
51
+ } catch {
52
+ return;
53
+ }
54
+ controller.enqueue(chunk);
55
+ }
56
+ });
57
+ }
58
+ function wait(ms, signal) {
59
+ return new Promise((resolve, reject) => {
60
+ if (signal?.aborted) return reject(signal.reason);
61
+ const timer = setTimeout(() => {
62
+ signal?.removeEventListener("abort", onAbort);
63
+ resolve();
64
+ }, ms);
65
+ function onAbort() {
66
+ clearTimeout(timer);
67
+ reject(signal?.reason);
68
+ }
69
+ signal?.addEventListener("abort", onAbort, { once: true });
70
+ });
71
+ }
72
+ export {
73
+ CHAT_SCENARIOS,
74
+ createAiChatFixture
75
+ };
@@ -0,0 +1,15 @@
1
+ import type { AiChatClient } from "../services/types";
2
+ import { type ChatScenario } from "./fixture";
3
+ export type FixtureOptions = {
4
+ /**
5
+ * ready, approval, questions, empty, rich, artifacts, slow, interrupted, failed, rate-limited,
6
+ * quota-exceeded, unknown-chat or missing-configuration. Default "ready".
7
+ */
8
+ scenario?: ChatScenario;
9
+ };
10
+ /**
11
+ * A ChatTransport that emits scripted UI message chunks in the browser, for previews and tests.
12
+ * The parts above it are the shipped ones. No key, no route, no server half:
13
+ * `aiChat({ provider: fixture(), model: "fixture" })`.
14
+ */
15
+ export declare function fixture(options?: FixtureOptions): import("@slices.sh/core").Provider<AiChatClient>;