@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,57 @@
1
+ "use client";
2
+ import { useCallback, useMemo, useState } from "react";
3
+ import { isSkippedQuestion, questionInput } from "../services/types.js";
4
+ const BLANK = { picked: [], other: false, text: "" };
5
+ function answerOf(question, entry) {
6
+ const text = entry.other ? entry.text.trim() : "";
7
+ const values = [...entry.picked, ...text ? [text] : []];
8
+ if (!values.length) return void 0;
9
+ return question.multiple ? values : values[0];
10
+ }
11
+ function applied(entry, question, change) {
12
+ switch (change.type) {
13
+ case "choose":
14
+ if (!question.multiple) return { ...entry, picked: [change.value], other: false };
15
+ return {
16
+ ...entry,
17
+ picked: entry.picked.includes(change.value) ? entry.picked.filter((item) => item !== change.value) : [...entry.picked, change.value]
18
+ };
19
+ case "toggle-other":
20
+ return question.multiple ? { ...entry, other: !entry.other } : { ...entry, picked: [], other: true };
21
+ case "select-other":
22
+ return { ...entry, picked: question.multiple ? entry.picked : [], other: true };
23
+ case "write-other":
24
+ return { ...entry, text: change.text, picked: question.multiple ? entry.picked : [], other: true };
25
+ case "clear":
26
+ return BLANK;
27
+ }
28
+ }
29
+ function useQuestionDraft(input) {
30
+ const [entries, setEntries] = useState({});
31
+ const change = useCallback(
32
+ (name, edit) => {
33
+ const question = input.questions.find((q) => q.name === name);
34
+ if (!question) return;
35
+ setEntries((current) => ({ ...current, [name]: applied(current[name] ?? BLANK, question, edit) }));
36
+ },
37
+ [input]
38
+ );
39
+ return useMemo(() => {
40
+ const answers = {};
41
+ for (const question of input.questions) {
42
+ const answer = answerOf(question, entries[question.name] ?? BLANK);
43
+ if (answer !== void 0) answers[question.name] = answer;
44
+ }
45
+ return {
46
+ answers,
47
+ picked: (name, value) => entries[name]?.picked.includes(value) ?? false,
48
+ other: (name) => ({ on: entries[name]?.other ?? false, text: entries[name]?.text ?? "" }),
49
+ change
50
+ };
51
+ }, [input, entries, change]);
52
+ }
53
+ export {
54
+ isSkippedQuestion,
55
+ questionInput,
56
+ useQuestionDraft
57
+ };
@@ -0,0 +1,18 @@
1
+ import type { Questionnaire } from "../services/types";
2
+ import type { QuestionCheck } from "./use-question-check";
3
+ export type StepMove = "back"
4
+ /** Stays, and says why, while the question being left has no good answer. */
5
+ | "next"
6
+ /** Goes where the first answer to fix is, saying why in each, unless every answer can be sent. */
7
+ | "finish";
8
+ export type QuestionSteps = {
9
+ /** Zero-based; a form of one question is its own last step. */
10
+ index: number;
11
+ count: number;
12
+ /** The person went somewhere, so the arriving question takes focus; the first one never does. */
13
+ moved: boolean;
14
+ active(name: string): boolean;
15
+ /** True when the move went through: for finish, when everything can be sent. */
16
+ move(move: StepMove): boolean;
17
+ };
18
+ export declare function useQuestionSteps(input: Questionnaire, check: QuestionCheck): QuestionSteps;
@@ -0,0 +1,31 @@
1
+ "use client";
2
+ import { useCallback, useMemo, useState } from "react";
3
+ function useQuestionSteps(input, check) {
4
+ const [index, setIndex] = useState(0);
5
+ const [moved, setMoved] = useState(false);
6
+ const count = input.questions.length;
7
+ const move = useCallback(
8
+ (step) => {
9
+ const go = (to) => {
10
+ setIndex(to);
11
+ setMoved(true);
12
+ return true;
13
+ };
14
+ if (step === "back") return index > 0 && go(index - 1);
15
+ if (step === "next")
16
+ return index < count - 1 && !check.reveal([input.questions[index].name]) && go(index + 1);
17
+ const names = input.questions.map((q) => q.name);
18
+ if (!check.reveal(names)) return true;
19
+ go(names.findIndex((name) => check.problem(name) !== null));
20
+ return false;
21
+ },
22
+ [index, count, input, check]
23
+ );
24
+ return useMemo(
25
+ () => ({ index, count, moved, active: (name) => input.questions[index]?.name === name, move }),
26
+ [index, count, moved, input, move]
27
+ );
28
+ }
29
+ export {
30
+ useQuestionSteps
31
+ };
@@ -0,0 +1,8 @@
1
+ import { type QuestionAnswers } from "../services/types";
2
+ import type { AiChat } from "./use-chat-instance";
3
+ export type QuestionWrite = {
4
+ run(answers: QuestionAnswers): Promise<void>;
5
+ pending: boolean;
6
+ error: Error | null;
7
+ };
8
+ export declare function useQuestionWrite(chat: AiChat, id: string): QuestionWrite;
@@ -0,0 +1,25 @@
1
+ "use client";
2
+ import { useCallback, useMemo, useState } from "react";
3
+ import { answerQuestions } from "../services/types.js";
4
+ function useQuestionWrite(chat, id) {
5
+ const [pending, setPending] = useState(false);
6
+ const [error, setError] = useState(null);
7
+ const run = useCallback(
8
+ async (answers) => {
9
+ setPending(true);
10
+ setError(null);
11
+ try {
12
+ await answerQuestions(chat, id, answers);
13
+ } catch (error2) {
14
+ setError(error2 instanceof Error ? error2 : new Error(String(error2)));
15
+ } finally {
16
+ setPending(false);
17
+ }
18
+ },
19
+ [chat, id]
20
+ );
21
+ return useMemo(() => ({ run, pending, error }), [run, pending, error]);
22
+ }
23
+ export {
24
+ useQuestionWrite
25
+ };
@@ -0,0 +1,8 @@
1
+ /** Explicit user playback, one owner at a time; unmount never cancels another message's voice. */
2
+ export declare function useReadAloud(text: string): {
3
+ available: boolean;
4
+ playing: boolean;
5
+ failed: boolean;
6
+ toggle: () => void;
7
+ };
8
+ export type ReadAloud = ReturnType<typeof useReadAloud>;
@@ -0,0 +1,60 @@
1
+ "use client";
2
+ import { useEffect, useState, useSyncExternalStore } from "react";
3
+ let reading = { owner: null, phase: "idle" };
4
+ const listeners = /* @__PURE__ */ new Set();
5
+ const subscribe = (listener) => {
6
+ listeners.add(listener);
7
+ return () => {
8
+ listeners.delete(listener);
9
+ };
10
+ };
11
+ const snapshot = () => reading;
12
+ const server = () => IDLE;
13
+ const IDLE = { owner: null, phase: "idle" };
14
+ const supported = () => typeof window !== "undefined" && "speechSynthesis" in window && "SpeechSynthesisUtterance" in window;
15
+ function publish(next) {
16
+ reading = next;
17
+ listeners.forEach((listener) => listener());
18
+ }
19
+ function stop(owner) {
20
+ if (reading.owner !== owner) return;
21
+ publish(IDLE);
22
+ window.speechSynthesis.cancel();
23
+ }
24
+ function useReadAloud(text) {
25
+ const [owner] = useState(() => ({}));
26
+ const current = useSyncExternalStore(subscribe, snapshot, server);
27
+ const available = useSyncExternalStore(subscribe, supported, () => false);
28
+ useEffect(
29
+ () => () => {
30
+ if (supported()) stop(owner);
31
+ },
32
+ [owner, text]
33
+ );
34
+ const playing = current.owner === owner && current.phase === "playing";
35
+ const failed = current.owner === owner && current.phase === "error";
36
+ const toggle = () => {
37
+ if (!available || !text.trim()) return;
38
+ if (reading.owner === owner && reading.phase === "playing") return stop(owner);
39
+ publish(IDLE);
40
+ window.speechSynthesis.cancel();
41
+ const run = { owner, phase: "playing" };
42
+ publish(run);
43
+ try {
44
+ const utterance = new SpeechSynthesisUtterance(text);
45
+ utterance.onend = () => {
46
+ if (reading === run) publish(IDLE);
47
+ };
48
+ utterance.onerror = () => {
49
+ if (reading === run) publish({ owner, phase: "error" });
50
+ };
51
+ window.speechSynthesis.speak(utterance);
52
+ } catch {
53
+ if (reading === run) publish({ owner, phase: "error" });
54
+ }
55
+ };
56
+ return { available, playing, failed, toggle };
57
+ }
58
+ export {
59
+ useReadAloud
60
+ };
@@ -0,0 +1,8 @@
1
+ export type Reasoning = {
2
+ seconds: number | null;
3
+ streaming: boolean;
4
+ open: boolean;
5
+ setOpen(open: boolean): void;
6
+ };
7
+ /** Historical traces have no measured duration; only a trace observed live gets a timer. */
8
+ export declare function useReasoning(streaming: boolean): Reasoning;
@@ -0,0 +1,32 @@
1
+ "use client";
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ function useReasoning(streaming) {
4
+ const [started] = useState(() => streaming ? Date.now() : null);
5
+ const [seconds, setSeconds] = useState(() => streaming ? 0 : null);
6
+ const [open, set] = useState(streaming);
7
+ const touched = useRef(false);
8
+ const setOpen = useCallback((value) => {
9
+ touched.current = true;
10
+ set(value);
11
+ }, []);
12
+ useEffect(() => {
13
+ if (started === null) return;
14
+ const update = () => setSeconds(Math.max(0, Math.floor((Date.now() - started) / 1e3)));
15
+ if (streaming) {
16
+ const timer = setInterval(update, 1e3);
17
+ return () => clearInterval(timer);
18
+ }
19
+ const finish = setTimeout(update, 0);
20
+ const fold = setTimeout(() => {
21
+ if (!touched.current) set(false);
22
+ }, 1e3);
23
+ return () => {
24
+ clearTimeout(finish);
25
+ clearTimeout(fold);
26
+ };
27
+ }, [streaming, started]);
28
+ return useMemo(() => ({ seconds, streaming, open, setOpen }), [seconds, streaming, open, setOpen]);
29
+ }
30
+ export {
31
+ useReasoning
32
+ };
@@ -0,0 +1,9 @@
1
+ import type { AiChat } from "./use-chat-instance";
2
+ import type { ToolApprovalMemory } from "./use-tool-approval-memory";
3
+ export type ApprovalAutomation = {
4
+ failure: {
5
+ id: string;
6
+ error: Error;
7
+ } | null;
8
+ };
9
+ export declare function useRememberedApprovals(chat: AiChat, policy: ToolApprovalMemory): ApprovalAutomation;
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ import { useChat } from "@ai-sdk/react";
3
+ import { getToolName, isToolUIPart } from "ai";
4
+ import { useEffect, useMemo, useRef, useState } from "react";
5
+ import { respondToApproval } from "../services/types.js";
6
+ function useRememberedApprovals(chat, policy) {
7
+ const { messages } = useChat({ chat });
8
+ const attempts = useRef(/* @__PURE__ */ new WeakMap());
9
+ const mounted = useRef(true);
10
+ useEffect(() => {
11
+ mounted.current = true;
12
+ return () => {
13
+ mounted.current = false;
14
+ };
15
+ }, []);
16
+ const [failure, setFailure] = useState(null);
17
+ useEffect(() => {
18
+ if (!policy.enabled) return;
19
+ let attempted = attempts.current.get(chat);
20
+ if (!attempted) {
21
+ attempted = /* @__PURE__ */ new Set();
22
+ attempts.current.set(chat, attempted);
23
+ }
24
+ for (const message of messages)
25
+ for (const part of message.parts) {
26
+ if (!isToolUIPart(part) || part.state !== "approval-requested" || !policy.tools.includes(getToolName(part)) || attempted.has(part.approval.id))
27
+ continue;
28
+ const id = part.approval.id;
29
+ attempted.add(id);
30
+ void respondToApproval(chat, id, true).catch((error) => {
31
+ if (mounted.current)
32
+ setFailure({ id, error: error instanceof Error ? error : new Error(String(error)) });
33
+ });
34
+ }
35
+ }, [chat, messages, policy]);
36
+ return useMemo(() => ({ failure }), [failure]);
37
+ }
38
+ export {
39
+ useRememberedApprovals
40
+ };
@@ -0,0 +1,3 @@
1
+ import type { AiChat } from "./use-chat-instance";
2
+ /** Sends at once, for a chat with no queue; an open question is skipped, and this is the reply. */
3
+ export declare function useReply(chat: AiChat): (text: string) => void;
@@ -0,0 +1,9 @@
1
+ "use client";
2
+ import { useCallback } from "react";
3
+ import { sendPastQuestions } from "../services/types.js";
4
+ function useReply(chat) {
5
+ return useCallback((text) => void sendPastQuestions(chat, text), [chat]);
6
+ }
7
+ export {
8
+ useReply
9
+ };
@@ -0,0 +1,9 @@
1
+ import { type Chat } from "@ai-sdk/react";
2
+ import type { AiChatMessage } from "../services/types";
3
+ /**
4
+ * Tells the tab when a turn was refused because the server lacks configuration.
5
+ *
6
+ * On the chat whatever made it, because an app that hands the screen its own `Chat` still
7
+ * points it at the installed route, and the route's answer is the same either way.
8
+ */
9
+ export declare function useReportMissingConfiguration(chat: Chat<AiChatMessage>): void;
@@ -0,0 +1,14 @@
1
+ "use client";
2
+ import { useChat } from "@ai-sdk/react";
3
+ import { useEffect } from "react";
4
+ import { reportIfMissingConfiguration } from "@slices.sh/core/configuration";
5
+ import { refusalBody } from "./chat-refusal.js";
6
+ function useReportMissingConfiguration(chat) {
7
+ const { error } = useChat({ chat });
8
+ useEffect(() => {
9
+ if (error) reportIfMissingConfiguration(refusalBody(error));
10
+ }, [error]);
11
+ }
12
+ export {
13
+ useReportMissingConfiguration
14
+ };
@@ -0,0 +1,5 @@
1
+ export declare function useRetryDelay(error: unknown): {
2
+ seconds: number;
3
+ deadline: number | null;
4
+ };
5
+ export type RetryDelay = ReturnType<typeof useRetryDelay>;
@@ -0,0 +1,17 @@
1
+ "use client";
2
+ import { useEffect, useState } from "react";
3
+ import { retryAtOf } from "./chat-refusal.js";
4
+ function useRetryDelay(error) {
5
+ const deadline = retryAtOf(error);
6
+ const [now, setNow] = useState(() => Date.now());
7
+ useEffect(() => {
8
+ if (deadline === null) return;
9
+ const tick = () => setNow(Date.now());
10
+ const timer = setInterval(tick, 250);
11
+ return () => clearInterval(timer);
12
+ }, [deadline]);
13
+ return { seconds: deadline === null ? 0 : Math.max(0, Math.ceil((deadline - now) / 1e3)), deadline };
14
+ }
15
+ export {
16
+ useRetryDelay
17
+ };
@@ -0,0 +1,8 @@
1
+ import type { AiChatMessage } from "../services/types";
2
+ export type SentDraft = {
3
+ value: string | null;
4
+ start: () => void;
5
+ set: (value: string) => void;
6
+ cancel: () => void;
7
+ };
8
+ export declare function useSentDraft(message: AiChatMessage): SentDraft;
@@ -0,0 +1,25 @@
1
+ "use client";
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
+ function useSentDraft(message) {
4
+ const text = message.role === "user" ? message.parts.flatMap((part) => part.type === "text" ? [part.text] : []).join("\n") : "";
5
+ const key = message.id + "\0" + text;
6
+ const [state, setState] = useState({ key, value: null });
7
+ if (state.key !== key) setState({ key, value: null });
8
+ const returnFocus = useRef(null);
9
+ const wasEditing = useRef(false);
10
+ const start = useCallback(() => {
11
+ returnFocus.current = document.activeElement instanceof HTMLElement ? document.activeElement : null;
12
+ setState({ key, value: text });
13
+ }, [key, text]);
14
+ const set = useCallback((value2) => setState({ key, value: value2 }), [key]);
15
+ const cancel = useCallback(() => setState({ key, value: null }), [key]);
16
+ const value = state.key === key ? state.value : null;
17
+ useEffect(() => {
18
+ if (value === null && wasEditing.current && returnFocus.current?.isConnected) returnFocus.current.focus();
19
+ wasEditing.current = value !== null;
20
+ }, [value]);
21
+ return useMemo(() => ({ value, start, set, cancel }), [value, start, set, cancel]);
22
+ }
23
+ export {
24
+ useSentDraft
25
+ };
@@ -0,0 +1,5 @@
1
+ export type SourceDisclosure = {
2
+ open: boolean;
3
+ setOpen(open: boolean): void;
4
+ };
5
+ export declare function useSourceDisclosure(): SourceDisclosure;
@@ -0,0 +1,9 @@
1
+ "use client";
2
+ import { useMemo, useState } from "react";
3
+ function useSourceDisclosure() {
4
+ const [open, setOpen] = useState(false);
5
+ return useMemo(() => ({ open, setOpen }), [open]);
6
+ }
7
+ export {
8
+ useSourceDisclosure
9
+ };
@@ -0,0 +1,3 @@
1
+ import { type AiChatMessage, type ChatSource } from "../services/types";
2
+ export type Sources = readonly ChatSource[];
3
+ export declare function useSources(message: AiChatMessage): Sources;
@@ -0,0 +1,9 @@
1
+ "use client";
2
+ import { useMemo } from "react";
3
+ import { sourcesOf } from "../services/types.js";
4
+ function useSources(message) {
5
+ return useMemo(() => sourcesOf(message), [message]);
6
+ }
7
+ export {
8
+ useSources
9
+ };
@@ -0,0 +1,8 @@
1
+ import type { AiChat } from "./use-chat-instance";
2
+ export type ToolApprovalMemory = {
3
+ enabled: boolean;
4
+ tools: readonly string[];
5
+ remember(tool: string): void;
6
+ forget(tool: string): void;
7
+ };
8
+ export declare function useToolApprovalMemory(chat: AiChat, enabled?: boolean): ToolApprovalMemory;
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { useMemo, useSyncExternalStore } from "react";
3
+ import { toolApprovalMemory } from "../services/types.js";
4
+ const EMPTY = [];
5
+ const server = () => EMPTY;
6
+ function useToolApprovalMemory(chat, enabled = true) {
7
+ const memory = useMemo(() => toolApprovalMemory(chat), [chat]);
8
+ const tools = useSyncExternalStore(memory.watch, memory.snapshot, server);
9
+ return useMemo(
10
+ () => ({ enabled, tools, remember: memory.remember, forget: memory.forget }),
11
+ [enabled, tools, memory]
12
+ );
13
+ }
14
+ export {
15
+ useToolApprovalMemory
16
+ };
@@ -0,0 +1,10 @@
1
+ import type { AiChat } from "./use-chat-instance";
2
+ export type ToolApproval = {
3
+ run(input: {
4
+ approved: boolean;
5
+ }): Promise<void>;
6
+ pending: boolean;
7
+ error: Error | null;
8
+ reset(): void;
9
+ };
10
+ export declare function useToolApproval(chat: AiChat, id: string): ToolApproval;
@@ -0,0 +1,26 @@
1
+ "use client";
2
+ import { useCallback, useMemo, useState } from "react";
3
+ import { respondToApproval } from "../services/types.js";
4
+ function useToolApproval(chat, id) {
5
+ const [pending, setPending] = useState(false);
6
+ const [error, setError] = useState(null);
7
+ const reset = useCallback(() => setError(null), []);
8
+ const run = useCallback(
9
+ async ({ approved }) => {
10
+ setPending(true);
11
+ setError(null);
12
+ try {
13
+ await respondToApproval(chat, id, approved);
14
+ } catch (caught) {
15
+ setError(caught instanceof Error ? caught : new Error(String(caught)));
16
+ } finally {
17
+ setPending(false);
18
+ }
19
+ },
20
+ [chat, id]
21
+ );
22
+ return useMemo(() => ({ run, pending, error, reset }), [run, pending, error, reset]);
23
+ }
24
+ export {
25
+ useToolApproval
26
+ };
@@ -0,0 +1,32 @@
1
+ import type { FileUIPart } from "ai";
2
+ import { type Blocker } from "../services/types";
3
+ import type { AiChat } from "./use-chat-instance";
4
+ export type QueuedTurn = {
5
+ id: string;
6
+ text: string;
7
+ draft: string | null;
8
+ files?: FileUIPart[];
9
+ };
10
+ export type QueueChange = {
11
+ type: "edit";
12
+ id: string;
13
+ text: string;
14
+ } | {
15
+ type: "begin-edit" | "save-edit" | "cancel-edit" | "remove" | "send-now";
16
+ id: string;
17
+ }
18
+ /** Skips the open question of this tool call, and moves the turn on. */
19
+ | {
20
+ type: "skip-question";
21
+ toolCallId: string;
22
+ };
23
+ export type TurnQueue = {
24
+ enqueue(text: string, files?: readonly FileUIPart[]): void;
25
+ waiting: number;
26
+ items: readonly QueuedTurn[];
27
+ change(action: QueueChange): void;
28
+ /** What holds the queue besides a running turn: null when nothing does. */
29
+ blockedBy: Blocker | null;
30
+ };
31
+ /** FIFO by default. Editing holds its place; Send now explicitly stops and reprioritizes. */
32
+ export declare function useTurnQueue(chat: AiChat): TurnQueue;
@@ -0,0 +1,33 @@
1
+ "use client";
2
+ import { useChat } from "@ai-sdk/react";
3
+ import { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from "react";
4
+ import { blockedBy } from "../services/types.js";
5
+ import { createMailbox } from "./turn-mailbox.js";
6
+ const EMPTY = [];
7
+ const server = () => EMPTY;
8
+ function useTurnQueue(chat) {
9
+ const { status, messages } = useChat({ chat });
10
+ const [box] = useState(createMailbox);
11
+ const items = useSyncExternalStore(box.watch, box.snapshot, server);
12
+ useEffect(() => box.open(), [box]);
13
+ useEffect(() => {
14
+ box.drain(chat);
15
+ }, [status, messages, box, chat]);
16
+ const enqueue = useCallback(
17
+ (text, files) => {
18
+ const value = text.trim();
19
+ if (!value && !files?.length) return;
20
+ box.apply({ type: "enqueue", text: value, files }, chat);
21
+ },
22
+ [box, chat]
23
+ );
24
+ const change = useCallback((action) => box.apply(action, chat), [box, chat]);
25
+ const waitingFor = blockedBy(messages, status === "submitted" || status === "streaming");
26
+ return useMemo(
27
+ () => ({ enqueue, items, waiting: items.length, change, blockedBy: waitingFor }),
28
+ [enqueue, items, change, waitingFor]
29
+ );
30
+ }
31
+ export {
32
+ useTurnQueue
33
+ };
@@ -0,0 +1,10 @@
1
+ import type { AiChatClient } from "./services/types";
2
+ export type { AiChatClient };
3
+ /**
4
+ * Configures the ai-chat service: services/ai-chat/<config>.config.ts has
5
+ * `export default aiChat({ provider: … })`. This module is client-safe: it holds a
6
+ * description, and the server half of the provider is loaded lazily.
7
+ */
8
+ export declare const aiChat: <Options extends Record<string, unknown>>(options: {
9
+ provider: import("@slices.sh/core").Provider<AiChatClient>;
10
+ } & Options) => import("@slices.sh/core").ServiceConfig<AiChatClient>;
package/dist/index.js ADDED
@@ -0,0 +1,5 @@
1
+ import { defineService } from "@slices.sh/core";
2
+ const aiChat = defineService("ai-chat");
3
+ export {
4
+ aiChat
5
+ };
package/dist/next.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ import "server-only";
2
+ /** app/api/ai-chat/[config]/[[...path]]/route.ts re-exports these. */
3
+ export declare const GET: (request: Request, context: {
4
+ params: Promise<{
5
+ config?: string;
6
+ path?: string[];
7
+ }> | {
8
+ config?: string;
9
+ path?: string[];
10
+ };
11
+ }) => Promise<Response>, POST: (request: Request, context: {
12
+ params: Promise<{
13
+ config?: string;
14
+ path?: string[];
15
+ }> | {
16
+ config?: string;
17
+ path?: string[];
18
+ };
19
+ }) => Promise<Response>, PUT: (request: Request, context: {
20
+ params: Promise<{
21
+ config?: string;
22
+ path?: string[];
23
+ }> | {
24
+ config?: string;
25
+ path?: string[];
26
+ };
27
+ }) => Promise<Response>, PATCH: (request: Request, context: {
28
+ params: Promise<{
29
+ config?: string;
30
+ path?: string[];
31
+ }> | {
32
+ config?: string;
33
+ path?: string[];
34
+ };
35
+ }) => Promise<Response>, DELETE: (request: Request, context: {
36
+ params: Promise<{
37
+ config?: string;
38
+ path?: string[];
39
+ }> | {
40
+ config?: string;
41
+ path?: string[];
42
+ };
43
+ }) => Promise<Response>;
package/dist/next.js ADDED
@@ -0,0 +1,10 @@
1
+ import "server-only";
2
+ import { serviceRoute } from "@slices.sh/core/server";
3
+ const { GET, POST, PUT, PATCH, DELETE } = serviceRoute("ai-chat");
4
+ export {
5
+ DELETE,
6
+ GET,
7
+ PATCH,
8
+ POST,
9
+ PUT
10
+ };