@everfur/sdk 0.1.1 → 0.4.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 (219) hide show
  1. package/CHANGELOG.md +703 -4
  2. package/README.md +63 -23
  3. package/consent/package.json +8 -0
  4. package/dist/Chat-BZZ-Py5l.d.ts +128 -0
  5. package/dist/Chat-Dq4fffIO.d.cts +128 -0
  6. package/dist/DepthViews-BG3E25MD.d.ts +16 -0
  7. package/dist/DepthViews-B_hIypI6.d.cts +19 -0
  8. package/dist/DepthViews-CL75jyRA.d.cts +16 -0
  9. package/dist/DepthViews-CkYri51q.d.ts +19 -0
  10. package/dist/ErrorPolicyPort-CNf4uQZP.d.cts +22 -0
  11. package/dist/ErrorPolicyPort-CwbfmxzJ.d.ts +22 -0
  12. package/dist/{EverfurResult-D92-uL82.d.cts → EverfurResult-DN9pL2Ab.d.cts} +11 -10
  13. package/dist/{EverfurResult-D92-uL82.d.ts → EverfurResult-DN9pL2Ab.d.ts} +11 -10
  14. package/dist/{PhotoController-BItt5M7u.d.cts → PhotoController-3l7MT9jA.d.cts} +1 -1
  15. package/dist/{PhotoController-D8zMTdcW.d.ts → PhotoController-vzY5bfY_.d.ts} +1 -1
  16. package/dist/animations/index.cjs +1 -1997
  17. package/dist/animations/index.d.cts +35 -35
  18. package/dist/animations/index.d.ts +35 -35
  19. package/dist/animations/index.js +1 -1972
  20. package/dist/attachments-BorG422I.d.cts +146 -0
  21. package/dist/attachments-BrUWQYNK.d.ts +257 -0
  22. package/dist/attachments-D_SECjr1.d.cts +257 -0
  23. package/dist/attachments-DpldrvIW.d.ts +146 -0
  24. package/dist/bookingCopy-CqtDYvCR.d.ts +732 -0
  25. package/dist/bookingCopy-SREvkG19.d.cts +732 -0
  26. package/dist/branding-CsRdeNwK.d.cts +566 -0
  27. package/dist/branding-CsRdeNwK.d.ts +566 -0
  28. package/dist/callCopy-DoQKG3-L.d.cts +40 -0
  29. package/dist/callCopy-DoQKG3-L.d.ts +40 -0
  30. package/dist/casesRepository-DwtZVsbj.d.cts +51 -0
  31. package/dist/casesRepository-v6QczS9N.d.ts +51 -0
  32. package/dist/chat/index.cjs +1 -1170
  33. package/dist/chat/index.d.cts +32 -53
  34. package/dist/chat/index.d.ts +32 -53
  35. package/dist/chat/index.js +1 -1167
  36. package/dist/client/index.cjs +9 -2315
  37. package/dist/client/index.d.cts +80 -16
  38. package/dist/client/index.d.ts +80 -16
  39. package/dist/client/index.js +9 -2215
  40. package/dist/{config-CiJ0PVBB.d.ts → config--Wu1Umhd.d.cts} +64 -26
  41. package/dist/{config-BSjBdxrZ.d.cts → config-C7eb_IMD.d.ts} +64 -26
  42. package/dist/consent/index.cjs +1 -0
  43. package/dist/consent/index.d.cts +33 -0
  44. package/dist/consent/index.d.ts +33 -0
  45. package/dist/consent/index.js +1 -0
  46. package/dist/context-CL3lyuy1.d.cts +159 -0
  47. package/dist/context-CahAEha8.d.ts +159 -0
  48. package/dist/copy-DdVFDL01.d.ts +198 -0
  49. package/dist/copy-UeUJVk8X.d.cts +198 -0
  50. package/dist/core/index.cjs +13 -3178
  51. package/dist/core/index.d.cts +164 -29
  52. package/dist/core/index.d.ts +164 -29
  53. package/dist/core/index.js +13 -3166
  54. package/dist/depth-D5HwcvKC.d.cts +533 -0
  55. package/dist/depth-DvPwPuT_.d.ts +533 -0
  56. package/dist/entitlementRepository-B7egEdW6.d.ts +43 -0
  57. package/dist/entitlementRepository-BpJ7tiwl.d.cts +43 -0
  58. package/dist/{identity-Brl-lDd6.d.cts → identity-C2-08BZW.d.cts} +20 -7
  59. package/dist/{identity-DK9zORrG.d.ts → identity-CEi9GRFZ.d.ts} +20 -7
  60. package/dist/{ids-CJ1S6adf.d.cts → ids-B2GAAifq.d.cts} +1 -1
  61. package/dist/{ids-CJ1S6adf.d.ts → ids-B2GAAifq.d.ts} +1 -1
  62. package/dist/index.cjs +12 -4494
  63. package/dist/index.d.cts +30 -121
  64. package/dist/index.d.ts +30 -121
  65. package/dist/index.js +12 -4470
  66. package/dist/models-B-Uh2LTf.d.ts +214 -0
  67. package/dist/models-D2EUxPZY.d.cts +214 -0
  68. package/dist/notifications/index.cjs +2 -0
  69. package/dist/notifications/index.d.cts +17 -0
  70. package/dist/notifications/index.d.ts +17 -0
  71. package/dist/notifications/index.js +2 -0
  72. package/dist/optionalModule-DbJmsq5f.d.cts +21 -0
  73. package/dist/optionalModule-DbJmsq5f.d.ts +21 -0
  74. package/dist/pets-DJv2sj2H.d.ts +92 -0
  75. package/dist/pets-JVCXgRgR.d.cts +92 -0
  76. package/dist/petsRepository-B_gKbAzJ.d.cts +142 -0
  77. package/dist/petsRepository-Bk6GDwLs.d.ts +142 -0
  78. package/dist/photo/index.cjs +1 -2189
  79. package/dist/photo/index.d.cts +6 -6
  80. package/dist/photo/index.d.ts +6 -6
  81. package/dist/photo/index.js +1 -2186
  82. package/dist/ports-BN6RHF9W.d.cts +48 -0
  83. package/dist/ports-BN6RHF9W.d.ts +48 -0
  84. package/dist/ports-BY2ph0_y.d.cts +376 -0
  85. package/dist/ports-D7YW8qz9.d.ts +376 -0
  86. package/dist/profile-CSs1wlXT.d.cts +93 -0
  87. package/dist/profile-CSs1wlXT.d.ts +93 -0
  88. package/dist/records/depth/index.cjs +2 -0
  89. package/dist/records/depth/index.d.cts +13 -0
  90. package/dist/records/depth/index.d.ts +13 -0
  91. package/dist/records/depth/index.js +2 -0
  92. package/dist/records/index.cjs +3 -2839
  93. package/dist/records/index.d.cts +137 -203
  94. package/dist/records/index.d.ts +137 -203
  95. package/dist/records/index.js +3 -2833
  96. package/dist/requestFunnel-BjDpqqvm.d.cts +110 -0
  97. package/dist/requestFunnel-DFMGcluw.d.ts +110 -0
  98. package/dist/{resolve-Dq_4_agU.d.ts → resolve-D4Ywz5OS.d.cts} +10 -4
  99. package/dist/{resolve-Dq_4_agU.d.cts → resolve-D4Ywz5OS.d.ts} +10 -4
  100. package/dist/{runtime-Bvr8yqXm.d.cts → runtimeTypes-gZEJu-da.d.cts} +104 -132
  101. package/dist/{runtime-BIYzf9cK.d.ts → runtimeTypes-w5KqBMcs.d.ts} +104 -132
  102. package/dist/server/events/index.cjs +2 -0
  103. package/dist/server/events/index.d.cts +550 -0
  104. package/dist/server/events/index.d.ts +550 -0
  105. package/dist/server/events/index.js +2 -0
  106. package/dist/server/index.cjs +2 -533
  107. package/dist/server/index.d.cts +73 -18
  108. package/dist/server/index.d.ts +73 -18
  109. package/dist/server/index.js +2 -530
  110. package/dist/species-BXAIMh7I.d.cts +9 -0
  111. package/dist/species-BXAIMh7I.d.ts +9 -0
  112. package/dist/televet/booking/index.cjs +1 -0
  113. package/dist/televet/booking/index.d.cts +294 -0
  114. package/dist/televet/booking/index.d.ts +294 -0
  115. package/dist/televet/booking/index.js +1 -0
  116. package/dist/televet/call/index.cjs +1 -0
  117. package/dist/televet/call/index.d.cts +141 -0
  118. package/dist/televet/call/index.d.ts +141 -0
  119. package/dist/televet/call/index.js +1 -0
  120. package/dist/televet/index.cjs +1 -0
  121. package/dist/televet/index.d.cts +142 -0
  122. package/dist/televet/index.d.ts +142 -0
  123. package/dist/televet/index.js +1 -0
  124. package/dist/testing/index.cjs +5 -823
  125. package/dist/testing/index.d.cts +18 -4
  126. package/dist/testing/index.d.ts +18 -4
  127. package/dist/testing/index.js +5 -820
  128. package/dist/testing/rn/index.cjs +1 -449
  129. package/dist/testing/rn/index.d.cts +18 -29
  130. package/dist/testing/rn/index.d.ts +18 -29
  131. package/dist/testing/rn/index.js +1 -444
  132. package/dist/testing/web/index.cjs +1 -0
  133. package/dist/testing/web/index.d.cts +132 -0
  134. package/dist/testing/web/index.d.ts +132 -0
  135. package/dist/testing/web/index.js +1 -0
  136. package/dist/timelineRows-C15jxFFH.d.ts +19 -0
  137. package/dist/timelineRows-odO8g9r2.d.cts +19 -0
  138. package/dist/typeStyle-CKqVYD6L.d.cts +111 -0
  139. package/dist/typeStyle-DmoyacDG.d.ts +111 -0
  140. package/dist/uploadTransport-D0M0T4hN.d.ts +38 -0
  141. package/dist/uploadTransport-DKJHs3Yj.d.cts +38 -0
  142. package/dist/useRecordsDepth-C6rjEaLn.d.cts +237 -0
  143. package/dist/useRecordsDepth-crhBllQK.d.ts +237 -0
  144. package/dist/useVetVisit-Bc84hWUU.d.cts +187 -0
  145. package/dist/useVetVisit-CjmMa896.d.ts +187 -0
  146. package/dist/video/index.cjs +1 -1941
  147. package/dist/video/index.d.cts +4 -4
  148. package/dist/video/index.d.ts +4 -4
  149. package/dist/video/index.js +1 -1938
  150. package/dist/view-Bxwxp4xD.d.ts +310 -0
  151. package/dist/view-DyitEO0m.d.cts +310 -0
  152. package/dist/visitIntent-D7_yVp1I.d.cts +8 -0
  153. package/dist/visitIntent-D7_yVp1I.d.ts +8 -0
  154. package/dist/web/consent/index.cjs +1 -0
  155. package/dist/web/consent/index.d.cts +34 -0
  156. package/dist/web/consent/index.d.ts +34 -0
  157. package/dist/web/consent/index.js +1 -0
  158. package/dist/web/index.cjs +14 -0
  159. package/dist/web/index.d.cts +218 -0
  160. package/dist/web/index.d.ts +218 -0
  161. package/dist/web/index.js +14 -0
  162. package/dist/web/notifications/index.cjs +2 -0
  163. package/dist/web/notifications/index.d.cts +213 -0
  164. package/dist/web/notifications/index.d.ts +213 -0
  165. package/dist/web/notifications/index.js +2 -0
  166. package/dist/web/records/depth/index.cjs +2 -0
  167. package/dist/web/records/depth/index.d.cts +12 -0
  168. package/dist/web/records/depth/index.d.ts +12 -0
  169. package/dist/web/records/depth/index.js +2 -0
  170. package/dist/web/records/index.cjs +4 -0
  171. package/dist/web/records/index.d.cts +285 -0
  172. package/dist/web/records/index.d.ts +285 -0
  173. package/dist/web/records/index.js +4 -0
  174. package/dist/web/televet/booking/index.cjs +1 -0
  175. package/dist/web/televet/booking/index.d.cts +349 -0
  176. package/dist/web/televet/booking/index.d.ts +349 -0
  177. package/dist/web/televet/booking/index.js +1 -0
  178. package/dist/web/televet/call/index.cjs +1 -0
  179. package/dist/web/televet/call/index.d.cts +142 -0
  180. package/dist/web/televet/call/index.d.ts +142 -0
  181. package/dist/web/televet/call/index.js +1 -0
  182. package/dist/web/televet/index.cjs +1 -0
  183. package/dist/web/televet/index.d.cts +136 -0
  184. package/dist/web/televet/index.d.ts +136 -0
  185. package/dist/web/televet/index.js +1 -0
  186. package/notifications/package.json +8 -0
  187. package/package.json +266 -10
  188. package/records/depth/package.json +8 -0
  189. package/server/events/device-blocked.cjs +15 -0
  190. package/server/events/package.json +9 -0
  191. package/televet/booking/package.json +8 -0
  192. package/televet/call/package.json +8 -0
  193. package/televet/package.json +8 -0
  194. package/testing/web/native-blocked.cjs +12 -0
  195. package/testing/web/package.json +8 -0
  196. package/web/consent/native-blocked.cjs +12 -0
  197. package/web/consent/package.json +8 -0
  198. package/web/native-blocked.cjs +12 -0
  199. package/web/notifications/native-blocked.cjs +12 -0
  200. package/web/notifications/package.json +8 -0
  201. package/web/package.json +8 -0
  202. package/web/records/depth/native-blocked.cjs +12 -0
  203. package/web/records/depth/package.json +8 -0
  204. package/web/records/native-blocked.cjs +12 -0
  205. package/web/records/package.json +8 -0
  206. package/web/televet/booking/native-blocked.cjs +12 -0
  207. package/web/televet/booking/package.json +8 -0
  208. package/web/televet/call/native-blocked.cjs +12 -0
  209. package/web/televet/call/package.json +8 -0
  210. package/web/televet/native-blocked.cjs +12 -0
  211. package/web/televet/package.json +8 -0
  212. package/dist/ChatController-CKdBvPj2.d.ts +0 -146
  213. package/dist/ChatController-CpUMvvZf.d.cts +0 -146
  214. package/dist/FilePort-BabWrv7I.d.cts +0 -22
  215. package/dist/FilePort-BabWrv7I.d.ts +0 -22
  216. package/dist/petsRepository-BEGb97M9.d.cts +0 -326
  217. package/dist/petsRepository-Bu18r2kK.d.ts +0 -326
  218. package/dist/requestFunnel-DuUH-kAe.d.cts +0 -28
  219. package/dist/requestFunnel-dio5OmR9.d.ts +0 -28
@@ -0,0 +1,146 @@
1
+ import { E as EverfurError } from './EverfurResult-DN9pL2Ab.cjs';
2
+ import { R as RequestFunnel } from './requestFunnel-BjDpqqvm.cjs';
3
+ import { F as FileHandle, U as UploadTransport, a as UploadPolicyWire } from './ports-BN6RHF9W.cjs';
4
+ import { R as ReadableStore, T as Timers } from './ports-BY2ph0_y.cjs';
5
+
6
+ /** The image MIME types the chat accepts (the server's `CHAT_ATTACHMENT` rule, plus the `image/jpg` alias). */
7
+ declare const ATTACHMENT_MIME_TYPES: readonly string[];
8
+ /** The `accept` list of a web file input: the MIME types and their extensions. */
9
+ declare const ATTACHMENT_ACCEPT = "image/jpeg,image/png,image/webp,image/heic,image/heif,.jpg,.jpeg,.png,.webp,.heic,.heif";
10
+ /** The server's cap on one attachment (`max_content_length: 10485760`). */
11
+ declare const MAX_ATTACHMENT_BYTES: number;
12
+ /** The server's cap on attachments per message (`image_s3_keys`). */
13
+ declare const MAX_ATTACHMENTS_PER_MESSAGE = 5;
14
+ /** The filename cap after sanitising. */
15
+ declare const MAX_FILENAME_LENGTH = 120;
16
+ /** The route the initiate step posts to. */
17
+ declare const ATTACHMENT_INITIATE_PATH = "/widget/v1/uploads/initiate";
18
+ /** True when `mime` is an accepted image type (case-insensitive). */
19
+ declare function isAttachmentMime(mime: string | undefined): boolean;
20
+ /**
21
+ * Sanitise a user-supplied filename so it can sit in a request body, a label or a log line: path separators
22
+ * become spaces, control characters and quotes are dropped, whitespace collapses, and the result is capped at
23
+ * `MAX_FILENAME_LENGTH` keeping the extension. Empty in, `attachment` out.
24
+ */
25
+ declare function sanitizeFilename(input: string | undefined): string;
26
+ /** `512 B`, `12.3 KB`, `10.0 MB`: the app's byte formatter, for the size copy. */
27
+ declare function formatBytes(bytes: number): string;
28
+ /** The closed set of attachment failures; the React layer maps each to the app's copy. */
29
+ type AttachmentErrorCode = 'too_large' | 'too_many' | 'unsupported_type' | 'network' | 'server' | 'cancelled' | 'rate_limited' | 'quota_exceeded' | 'idempotency_conflict' | 'unknown';
30
+ /** One attachment failure, typed; `retryable` says whether a retry control is honest. */
31
+ interface AttachmentError {
32
+ readonly code: AttachmentErrorCode;
33
+ readonly retryable: boolean;
34
+ /** The sanitised filename the failure is about. */
35
+ readonly filename: string;
36
+ /** For `too_large`: the file's size. */
37
+ readonly sizeBytes?: number;
38
+ /** For `server`: the HTTP status when one is known. */
39
+ readonly httpStatus?: number;
40
+ /** The settled SDK error behind a wire failure, when there is one (`displayMessage` is safe). */
41
+ readonly cause?: EverfurError;
42
+ }
43
+ /** The settle-shaped outcome of every attachment step: `AttachmentError` on the failure branch, never a throw. */
44
+ type AttachmentOutcome<T> = {
45
+ readonly ok: true;
46
+ readonly value: T;
47
+ } | {
48
+ readonly ok: false;
49
+ readonly error: AttachmentError;
50
+ };
51
+ /** A validated file: what the queue uploads. */
52
+ interface ValidatedAttachment {
53
+ readonly file: FileHandle;
54
+ readonly filename: string;
55
+ readonly contentType: string;
56
+ readonly sizeBytes: number;
57
+ }
58
+ /** The byte size of a handle: its `sizeBytes`, else its in-memory `blob`'s size; null when unknown. */
59
+ declare function attachmentSize(file: FileHandle): number | null;
60
+ /**
61
+ * The picker-boundary check: an accepted image type, at most `MAX_ATTACHMENT_BYTES`, a known size (the initiate
62
+ * body needs it), and a sanitised filename. Settles; never throws.
63
+ */
64
+ declare function validateAttachment(file: FileHandle): AttachmentOutcome<ValidatedAttachment>;
65
+ /** The presigned policy `POST /widget/v1/uploads/initiate` returns, plus the key the send names. */
66
+ interface AttachmentUploadPolicy extends UploadPolicyWire {
67
+ readonly s3_key: string;
68
+ readonly purpose: string | null;
69
+ }
70
+ /**
71
+ * Step 2: ask for the presigned policy. Settles `ok(policy)` or a typed failure; a malformed policy is a
72
+ * non-retryable `server` failure (retrying cannot change the shape).
73
+ */
74
+ declare function initiateAttachmentUpload(funnel: RequestFunnel, attachment: ValidatedAttachment, opts?: {
75
+ readonly signal?: AbortSignal;
76
+ }): Promise<AttachmentOutcome<AttachmentUploadPolicy>>;
77
+ /**
78
+ * Step 3: stage the bytes on S3 through the injected transport (the policy fields first, `file` last). A
79
+ * rejection is a retryable `server` failure, an abort a `cancelled` one; nothing here throws.
80
+ */
81
+ declare function uploadAttachmentBytes(transport: UploadTransport, policy: AttachmentUploadPolicy, attachment: ValidatedAttachment, opts?: {
82
+ readonly signal?: AbortSignal;
83
+ readonly onProgress?: (fraction: number) => void;
84
+ }): Promise<AttachmentOutcome<void>>;
85
+ declare const ATTACHMENT_QUEUE_CONCURRENCY = 2;
86
+ declare const ATTACHMENT_MAX_ATTEMPTS = 3;
87
+ declare const ATTACHMENT_BACKOFF_MS: readonly number[];
88
+ type AttachmentStatus = 'uploading' | 'uploaded' | 'failed';
89
+ /** One attachment as a composer renders it. `s3Key` is set once `status === 'uploaded'`. */
90
+ interface AttachmentState {
91
+ readonly id: string;
92
+ readonly filename: string;
93
+ /** What the thumbnail shows: the handle's `uri` (an object URL on the web, the local file on native). */
94
+ readonly previewUri: string;
95
+ readonly contentType: string;
96
+ readonly sizeBytes: number;
97
+ readonly status: AttachmentStatus;
98
+ readonly s3Key: string | null;
99
+ readonly error: AttachmentError | null;
100
+ /** 0..1 while uploading (the transport may report completion only). */
101
+ readonly progress: number;
102
+ }
103
+ /** The queue's frozen snapshot: the attachments in the order they were added. */
104
+ interface AttachmentQueueSnapshot {
105
+ readonly attachments: readonly AttachmentState[];
106
+ }
107
+ interface AttachmentQueueDeps {
108
+ /** The request funnel of the current scope (the initiate hop). */
109
+ readonly funnel: RequestFunnel;
110
+ /** The host's upload transport (`EverfurConfig.uploadTransport`); the absent sentinel means uploads cannot run. */
111
+ readonly transport: UploadTransport;
112
+ /** The cap on attachments in the queue (the composer's slots); default `MAX_ATTACHMENTS_PER_MESSAGE`. */
113
+ readonly maxPerMessage?: number;
114
+ readonly concurrency?: number;
115
+ readonly maxAttempts?: number;
116
+ readonly backoffMs?: readonly number[];
117
+ /** Injected clock for deterministic backoff in tests. */
118
+ readonly timers?: Timers;
119
+ /** Injected id factory for deterministic tests. */
120
+ readonly newId?: () => string;
121
+ }
122
+ interface AttachmentQueue extends ReadableStore<AttachmentQueueSnapshot> {
123
+ /** True when the host wired an upload transport; a surface hides its attach control otherwise. */
124
+ readonly available: boolean;
125
+ /**
126
+ * Validate and enqueue one picked file. Settles `ok(state)` (the row, already `uploading`) or the typed
127
+ * failure that kept it out (`too_many`, `unsupported_type`, `too_large`, ...). Never throws.
128
+ */
129
+ add(file: FileHandle): AttachmentOutcome<AttachmentState>;
130
+ /** Re-run a failed row from the start (a fresh initiate; the same 3-attempt budget). A no-op otherwise. */
131
+ retry(id: string): void;
132
+ /** Drop a row: cancels it when in flight. */
133
+ remove(id: string): void;
134
+ /** Drop every row (after a send, or on unmount). */
135
+ clear(): void;
136
+ /** True while any row is still uploading (the send is blocked meanwhile). */
137
+ readonly uploading: boolean;
138
+ /** The S3 keys of every uploaded row, in order: what `SendOptions.imageS3Keys` takes. */
139
+ readonly s3Keys: readonly string[];
140
+ /** Stop everything and drop every listener. */
141
+ dispose(): void;
142
+ }
143
+ /** Build a queue. Framework-free; a React surface binds it through `useSyncExternalStore`. */
144
+ declare function createAttachmentQueue(deps: AttachmentQueueDeps): AttachmentQueue;
145
+
146
+ export { type AttachmentError as A, MAX_ATTACHMENTS_PER_MESSAGE as M, type ValidatedAttachment as V, type AttachmentErrorCode as a, type AttachmentOutcome as b, type AttachmentQueue as c, type AttachmentState as d, type AttachmentStatus as e, ATTACHMENT_ACCEPT as f, ATTACHMENT_BACKOFF_MS as g, ATTACHMENT_INITIATE_PATH as h, ATTACHMENT_MAX_ATTEMPTS as i, ATTACHMENT_MIME_TYPES as j, ATTACHMENT_QUEUE_CONCURRENCY as k, type AttachmentQueueDeps as l, type AttachmentQueueSnapshot as m, type AttachmentUploadPolicy as n, MAX_ATTACHMENT_BYTES as o, MAX_FILENAME_LENGTH as p, attachmentSize as q, createAttachmentQueue as r, formatBytes as s, initiateAttachmentUpload as t, isAttachmentMime as u, sanitizeFilename as v, uploadAttachmentBytes as w, validateAttachment as x };
@@ -0,0 +1,257 @@
1
+ import { E as EverfurError, c as EverfurResult } from './EverfurResult-DN9pL2Ab.js';
2
+ import { C as ConversationId, P as PetRef, b as ResponseId } from './ids-B2GAAifq.js';
3
+ import { f as ChatFeedbackType, j as ChatStatus, i as ChatMessage, c as ChatConversationListOptions, d as ChatConversationPage, g as ChatHistoryOptions, h as ChatMessagePage, a as ChatCheckinTarget, e as ChatFeedbackReceipt } from './ports-D7YW8qz9.js';
4
+ import { C as CheckinAnswer, a as CheckinOutcome } from './casesRepository-v6QczS9N.js';
5
+ import { i as UrgencyLevel } from './config-C7eb_IMD.js';
6
+ import { W as WidgetPet } from './petsRepository-Bk6GDwLs.js';
7
+ import { U as UploadTransport, F as FileHandle } from './ports-BN6RHF9W.js';
8
+ import { c as AttachmentQueue, d as AttachmentState, A as AttachmentError, b as AttachmentOutcome } from './attachments-DpldrvIW.js';
9
+
10
+ /** The three thumbs. `'neutral'` is the app's rotated thumbs-down glyph. */
11
+ type ChatSentiment = 'up' | 'neutral' | 'down';
12
+ /** The reason keys of the not-helpful sheet, in the app's order. */
13
+ type ChatFeedbackReason = 'inaccurate' | 'outdated' | 'unsafe' | 'unclear' | 'other';
14
+ interface ChatFeedbackReasonOption {
15
+ readonly key: ChatFeedbackReason;
16
+ /** The chip label, verbatim from the app. */
17
+ readonly label: string;
18
+ /** The `feedback_type` the chip records. */
19
+ readonly feedbackType: ChatFeedbackType;
20
+ }
21
+
22
+ /**
23
+ * Headless chat state. `isBootstrapping` is a deliberate superset of the SPEC-10 §7.4 minimum: the
24
+ * controller snapshot carries it (§7.1) and the prebuilt component maps it to the Loading state.
25
+ */
26
+ interface UseEverfurChatState {
27
+ readonly status: ChatStatus;
28
+ readonly messages: ReadonlyArray<ChatMessage>;
29
+ readonly conversationId: ConversationId | null;
30
+ /** The pet this surface is scoped to (the option, else the provider's active pet); null when unscoped. */
31
+ readonly petRef: PetRef | null;
32
+ readonly error: EverfurError | null;
33
+ readonly isStreaming: boolean;
34
+ readonly isBootstrapping: boolean;
35
+ readonly historyCursor: string | null;
36
+ readonly isLoadingHistory: boolean;
37
+ /**
38
+ * The last turn was stopped before its first token: the question is on screen with no answer under it. The
39
+ * prebuilt surface renders the app's `Response stopped` notice with a retry; a fresh send, a retry or a
40
+ * thread change clears it.
41
+ *
42
+ * OPTIONAL on the type, always present from the hook. It was added to a shipped interface that partners and
43
+ * suites already build doubles of, and a required field would have made every one of those a type error for
44
+ * a flag they have no opinion about; absent reads the same as `false` everywhere it is consumed.
45
+ */
46
+ readonly stopped?: boolean;
47
+ listConversations(opts?: ChatConversationListOptions): Promise<EverfurResult<ChatConversationPage>>;
48
+ getMessages(id: ConversationId, opts?: ChatHistoryOptions): Promise<EverfurResult<ChatMessagePage>>;
49
+ resumeConversation(id: ConversationId): Promise<EverfurResult<void>>;
50
+ loadOlderMessages(): Promise<EverfurResult<void>>;
51
+ /**
52
+ * Backend-owned suggested-prompt strings (flattened + de-duplicated) from the chat bootstrap. Empty until the
53
+ * bootstrap resolves and empty when the backend returns none; the prebuilt component renders them as the
54
+ * tappable "Follow up questions" list, each string a ready-to-send message.
55
+ */
56
+ readonly suggestedPrompts: ReadonlyArray<string>;
57
+ /** Unread assistant messages in the active thread (see `ChatSnapshot.unreadCount`); null while unknown. */
58
+ readonly unreadCount: number | null;
59
+ /**
60
+ * Does any thread the SDK has listed still carry unread assistant content? The header dot, answerable from
61
+ * the chat bootstrap's own head read, so it never waits on the history drawer being opened.
62
+ *
63
+ * OPTIONAL on the type, always present from the hook, for the same reason `stopped` is: it was added to a
64
+ * shipped interface that partners and suites already build doubles of, and absent reads as `false`.
65
+ */
66
+ readonly hasUnreadThreads?: boolean;
67
+ /**
68
+ * Open the thread a follow-up check-in landed in: the conversation an Everfur push named, or, with only a
69
+ * pet, the head of that pet's list (the read that also materializes a check-in the member is owed).
70
+ * Settles to the conversation opened, `ok(null)` when there is no thread yet; never throws.
71
+ *
72
+ * OPTIONAL on the type, always present from the hook, for the same reason `stopped` is: it was added to a
73
+ * shipped interface that partners and suites already build doubles of, and a required member would have
74
+ * made every one of those a type error. A double that omits it simply opens nothing.
75
+ */
76
+ openCheckin?(target?: ChatCheckinTarget): Promise<EverfurResult<ConversationId | null>>;
77
+ /** Mark the active thread read and zero `unreadCount`. Settles; a no-op without an active thread. */
78
+ markRead(): Promise<EverfurResult<void>>;
79
+ /**
80
+ * CRN-16. The turn in flight is being re-attempted by the SDK with nothing asked of the reader. The
81
+ * prebuilt surfaces render the app's `Reconnecting` caption for it.
82
+ *
83
+ * OPTIONAL on the type, always present from the hook, for the same reason `stopped` is.
84
+ */
85
+ readonly reconnecting?: boolean;
86
+ /**
87
+ * CRN-16. Re-read the active thread's newest window and the limit-1 list, merging in anything the platform
88
+ * wrote while the host was away. Settles; a no-op without a thread and while a turn is in flight.
89
+ *
90
+ * OPTIONAL on the type, always present from the hook, for the same reason `stopped` is.
91
+ */
92
+ refreshActiveThread?(): Promise<EverfurResult<void>>;
93
+ /**
94
+ * Record the owner's answer to a follow-up check-in against the scoped pet and reflect it on the message
95
+ * (`message.checkin`). Settles; without a pet in scope it is `validationFailed` before any I/O.
96
+ */
97
+ answerCheckin(caseId: string, answer: CheckinAnswer): Promise<EverfurResult<CheckinOutcome>>;
98
+ /**
99
+ * Leave the active thread for a fresh, empty one (the history drawer's "New conversation"): the transcript
100
+ * clears and the next `send` creates the conversation. Nothing is fetched or deleted.
101
+ */
102
+ newConversation(): void;
103
+ /**
104
+ * The reader's rating per assistant message (keyed by the message id), for the thumbs: what was last recorded
105
+ * this session. A message with no entry is unrated. Local state; the server keeps its own copy.
106
+ */
107
+ readonly sentimentByMessage: Readonly<Record<string, ChatSentiment>>;
108
+ /**
109
+ * Rate an assistant reply (`POST /widget/v1/messages/{message_id}/feedback`). Only a message with a server
110
+ * `responseId` is eligible (a local or pending id settles to `validationFailed` before any I/O). A tap on the
111
+ * sentiment already recorded CLEARS it locally and sends nothing (the consumer app's behaviour); a different
112
+ * one replaces it. `reason` upgrades a thumbs-down to the specific `feedback_type` the not-helpful sheet
113
+ * picks, `notes` (<= 4000 characters) rides with it. Settles `ok({ feedbackId })` (an empty id on a local
114
+ * clear); never throws.
115
+ */
116
+ feedback(responseId: ResponseId, sentiment: ChatSentiment, reason?: ChatFeedbackReason | null, notes?: string | null): Promise<EverfurResult<ChatFeedbackReceipt>>;
117
+ /**
118
+ * Optimistic; the blank user bubble is removed on a pre-first-delta failure (controller-owned). Drives the
119
+ * controller stream to completion and settles: `ok(responseId)` on a completed turn (the id is null when
120
+ * the terminal `done` frame carried no message id), or `err` with the terminal EverfurError. `imageS3Keys`
121
+ * are the keys of images staged through the attachments queue (at most 5).
122
+ */
123
+ send(text: string, opts?: {
124
+ readonly imageS3Keys?: readonly string[];
125
+ }): Promise<EverfurResult<ResponseId | null>>;
126
+ /**
127
+ * CRN-06. Ask a grounded question in a FRESH conversation: the thread on screen is left and `prompt` is
128
+ * the first turn of a new one (the consumer's "Ask Everfur" handoff from a records card). Settles like
129
+ * `send`.
130
+ *
131
+ * OPTIONAL on the type, always present from the hook, for the same reason `stopped` is.
132
+ */
133
+ askEverfur?(prompt: string): Promise<EverfurResult<ResponseId | null>>;
134
+ /** Re-sends the last turn with the SAME idempotency key; no duplicate user bubble (§7.4). */
135
+ retryLast(): Promise<EverfurResult<ResponseId | null>>;
136
+ /** Aborts the in-flight stream; not an error. */
137
+ stop(): void;
138
+ }
139
+ /**
140
+ * @throws {EverfurConfigError} kind 'not-initialized' if called outside an EverfurProvider.
141
+ * Auto-disposes its controller reference on unmount.
142
+ */
143
+ declare function useEverfurChat(opts?: {
144
+ readonly petRef?: PetRef;
145
+ readonly conversationId?: ConversationId;
146
+ }): UseEverfurChatState;
147
+
148
+ /**
149
+ * The host's lifecycle and connectivity signals. Each subscribe returns its own unsubscribe, which the SDK
150
+ * calls on unmount; a listener that throws is contained by the caller, never by the host.
151
+ */
152
+ interface LifecyclePort {
153
+ /**
154
+ * The host came back to the foreground. Only the real blur-to-focus edge, please: a platform that flips
155
+ * through an inactive state constantly (iOS control centre, a call banner) would otherwise turn a
156
+ * notification-shade pull into a request.
157
+ */
158
+ onForeground(listener: () => void): () => void;
159
+ /** Connectivity returned. Omit it and a deferred refresh waits for the next foreground instead. */
160
+ onOnline?(listener: () => void): () => void;
161
+ /**
162
+ * Something told the host THIS member's thread changed: the push that carried the message. Announced
163
+ * triggers are never coalesced, because that is the one case where the reader is waiting on new content.
164
+ */
165
+ onAnnounced?(listener: () => void): () => void;
166
+ /** Is the host unambiguously offline? Absent reads as online, which is exactly today's behaviour. */
167
+ isOffline?(): boolean;
168
+ }
169
+
170
+ /**
171
+ * CRN-16. The host's own storage for an unsent draft. The SDK ships NO persistence of its own: a draft is
172
+ * memory-only unless a host passes this, because a question half-typed on a health surface is the reader's
173
+ * own text and where it may be written down is the host's decision, not the SDK's. `conversationId` is null
174
+ * for the not-yet-created thread, so a host that keys on it can scope per thread.
175
+ */
176
+ interface EverfurChatDraftStore {
177
+ /** The draft you last stored for this thread, or null. May be async. */
178
+ read(conversationId: string | null): string | null | Promise<string | null>;
179
+ /** Store the unsent draft for this thread; an empty string means the reader cleared it. May be async. */
180
+ write(conversationId: string | null, text: string): void | Promise<void>;
181
+ }
182
+
183
+ /** The three server tiers plus the app's calm `general` tier for an informational turn. */
184
+ type UrgencyDisplayLevel = UrgencyLevel | 'general';
185
+
186
+ /** The pet list state a header or switcher renders from. */
187
+ interface UseEverfurPetsState {
188
+ /** The registered pets, newest first as the server lists them; empty until the first fetch settles. */
189
+ readonly pets: readonly WidgetPet[];
190
+ /** The provider's active pet (`activePet` prop or `handle.setActivePet`), resolved against the list; null when unscoped or not listed. */
191
+ readonly activePet: WidgetPet | null;
192
+ /** True while a fetch is in flight (the first one too, so a header can hold its disc until the name is known). */
193
+ readonly loading: boolean;
194
+ /** The last fetch's settled error (`error.displayMessage` is safe to show), or null. */
195
+ readonly error: EverfurError | null;
196
+ /** Fetch the list again (after `registerPet`, or a retry). Settles; never throws. */
197
+ refresh(): Promise<void>;
198
+ }
199
+ /**
200
+ * @throws {EverfurConfigError} kind 'not-initialized' if called outside an EverfurProvider.
201
+ */
202
+ declare function useEverfurPets(): UseEverfurPetsState;
203
+
204
+ /** What a composer renders and calls. */
205
+ interface UseChatAttachmentsState {
206
+ /** True when the host wired an upload transport; the attach control is hidden otherwise. */
207
+ readonly available: boolean;
208
+ /** The rows, in the order they were added. */
209
+ readonly attachments: readonly AttachmentState[];
210
+ /** The composer's slots. */
211
+ readonly maxPerMessage: number;
212
+ /** True while any row is still uploading: the send is blocked meanwhile. */
213
+ readonly uploading: boolean;
214
+ /**
215
+ * True while any row FAILED to upload. The send is blocked on this too, because the alternative is the
216
+ * silent drop: `s3Keys` names only the rows that landed and the strip is cleared on dispatch, so a send here
217
+ * would post the message without the photo the owner picked and leave nothing behind to say so. The consumer
218
+ * app blocks the same way (everfur-mobile `useAuthenticatedReportChat.ts`, the `blockingAttachment` guard).
219
+ */
220
+ readonly failed: boolean;
221
+ /**
222
+ * True while the composer must refuse the send: a row is uploading or a row failed. `failed` says which of
223
+ * the two needs a sentence (the spinner already speaks for the other).
224
+ */
225
+ readonly blocked: boolean;
226
+ /** The S3 keys of every uploaded row, for `send(text, { imageS3Keys })`. */
227
+ readonly s3Keys: readonly string[];
228
+ /** The last failure that kept a pick out of the queue (`too_large`, `unsupported_type`, `too_many`), or null. */
229
+ readonly rejected: AttachmentError | null;
230
+ /** Validate and enqueue one or more picked files; returns each outcome. Never throws. */
231
+ add(files: FileHandle | readonly FileHandle[]): readonly AttachmentOutcome<AttachmentState>[];
232
+ retry(id: string): void;
233
+ remove(id: string): void;
234
+ /** Drop every row (after a successful send). */
235
+ clear(): void;
236
+ /** Forget the last rejection (the composer showed it). */
237
+ dismissRejected(): void;
238
+ }
239
+ interface UseChatAttachmentsOptions {
240
+ /** The composer's slots; default `MAX_ATTACHMENTS_PER_MESSAGE` (5). */
241
+ readonly maxPerMessage?: number;
242
+ /** Test seam: a queue to bind instead of building one from the provider. */
243
+ readonly queue?: AttachmentQueue;
244
+ /**
245
+ * The upload transport to bind instead of the provider's `uploadTransport`: the web surface passes its own
246
+ * fetch-based one, since a browser needs no host adapter to post a multipart form. Absent, the host's.
247
+ */
248
+ readonly transport?: UploadTransport;
249
+ }
250
+ /**
251
+ * The attachment rows of the composer. The queue lives for the scope (user, session epoch) and is disposed on
252
+ * unmount or re-scope, so a previous user's thumbnails never survive a switch.
253
+ * @throws {EverfurConfigError} kind 'not-initialized' if called outside an EverfurProvider.
254
+ */
255
+ declare function useChatAttachments(options?: UseChatAttachmentsOptions): UseChatAttachmentsState;
256
+
257
+ export { type ChatFeedbackReason as C, type EverfurChatDraftStore as E, type LifecyclePort as L, type UrgencyDisplayLevel as U, type ChatFeedbackReasonOption as a, type ChatSentiment as b, type UseChatAttachmentsOptions as c, type UseChatAttachmentsState as d, type UseEverfurChatState as e, type UseEverfurPetsState as f, useEverfurChat as g, useEverfurPets as h, useChatAttachments as u };
@@ -0,0 +1,257 @@
1
+ import { E as EverfurError, c as EverfurResult } from './EverfurResult-DN9pL2Ab.cjs';
2
+ import { C as ConversationId, P as PetRef, b as ResponseId } from './ids-B2GAAifq.cjs';
3
+ import { f as ChatFeedbackType, j as ChatStatus, i as ChatMessage, c as ChatConversationListOptions, d as ChatConversationPage, g as ChatHistoryOptions, h as ChatMessagePage, a as ChatCheckinTarget, e as ChatFeedbackReceipt } from './ports-BY2ph0_y.cjs';
4
+ import { C as CheckinAnswer, a as CheckinOutcome } from './casesRepository-DwtZVsbj.cjs';
5
+ import { i as UrgencyLevel } from './config--Wu1Umhd.cjs';
6
+ import { W as WidgetPet } from './petsRepository-B_gKbAzJ.cjs';
7
+ import { U as UploadTransport, F as FileHandle } from './ports-BN6RHF9W.cjs';
8
+ import { c as AttachmentQueue, d as AttachmentState, A as AttachmentError, b as AttachmentOutcome } from './attachments-BorG422I.cjs';
9
+
10
+ /** The three thumbs. `'neutral'` is the app's rotated thumbs-down glyph. */
11
+ type ChatSentiment = 'up' | 'neutral' | 'down';
12
+ /** The reason keys of the not-helpful sheet, in the app's order. */
13
+ type ChatFeedbackReason = 'inaccurate' | 'outdated' | 'unsafe' | 'unclear' | 'other';
14
+ interface ChatFeedbackReasonOption {
15
+ readonly key: ChatFeedbackReason;
16
+ /** The chip label, verbatim from the app. */
17
+ readonly label: string;
18
+ /** The `feedback_type` the chip records. */
19
+ readonly feedbackType: ChatFeedbackType;
20
+ }
21
+
22
+ /**
23
+ * Headless chat state. `isBootstrapping` is a deliberate superset of the SPEC-10 §7.4 minimum: the
24
+ * controller snapshot carries it (§7.1) and the prebuilt component maps it to the Loading state.
25
+ */
26
+ interface UseEverfurChatState {
27
+ readonly status: ChatStatus;
28
+ readonly messages: ReadonlyArray<ChatMessage>;
29
+ readonly conversationId: ConversationId | null;
30
+ /** The pet this surface is scoped to (the option, else the provider's active pet); null when unscoped. */
31
+ readonly petRef: PetRef | null;
32
+ readonly error: EverfurError | null;
33
+ readonly isStreaming: boolean;
34
+ readonly isBootstrapping: boolean;
35
+ readonly historyCursor: string | null;
36
+ readonly isLoadingHistory: boolean;
37
+ /**
38
+ * The last turn was stopped before its first token: the question is on screen with no answer under it. The
39
+ * prebuilt surface renders the app's `Response stopped` notice with a retry; a fresh send, a retry or a
40
+ * thread change clears it.
41
+ *
42
+ * OPTIONAL on the type, always present from the hook. It was added to a shipped interface that partners and
43
+ * suites already build doubles of, and a required field would have made every one of those a type error for
44
+ * a flag they have no opinion about; absent reads the same as `false` everywhere it is consumed.
45
+ */
46
+ readonly stopped?: boolean;
47
+ listConversations(opts?: ChatConversationListOptions): Promise<EverfurResult<ChatConversationPage>>;
48
+ getMessages(id: ConversationId, opts?: ChatHistoryOptions): Promise<EverfurResult<ChatMessagePage>>;
49
+ resumeConversation(id: ConversationId): Promise<EverfurResult<void>>;
50
+ loadOlderMessages(): Promise<EverfurResult<void>>;
51
+ /**
52
+ * Backend-owned suggested-prompt strings (flattened + de-duplicated) from the chat bootstrap. Empty until the
53
+ * bootstrap resolves and empty when the backend returns none; the prebuilt component renders them as the
54
+ * tappable "Follow up questions" list, each string a ready-to-send message.
55
+ */
56
+ readonly suggestedPrompts: ReadonlyArray<string>;
57
+ /** Unread assistant messages in the active thread (see `ChatSnapshot.unreadCount`); null while unknown. */
58
+ readonly unreadCount: number | null;
59
+ /**
60
+ * Does any thread the SDK has listed still carry unread assistant content? The header dot, answerable from
61
+ * the chat bootstrap's own head read, so it never waits on the history drawer being opened.
62
+ *
63
+ * OPTIONAL on the type, always present from the hook, for the same reason `stopped` is: it was added to a
64
+ * shipped interface that partners and suites already build doubles of, and absent reads as `false`.
65
+ */
66
+ readonly hasUnreadThreads?: boolean;
67
+ /**
68
+ * Open the thread a follow-up check-in landed in: the conversation an Everfur push named, or, with only a
69
+ * pet, the head of that pet's list (the read that also materializes a check-in the member is owed).
70
+ * Settles to the conversation opened, `ok(null)` when there is no thread yet; never throws.
71
+ *
72
+ * OPTIONAL on the type, always present from the hook, for the same reason `stopped` is: it was added to a
73
+ * shipped interface that partners and suites already build doubles of, and a required member would have
74
+ * made every one of those a type error. A double that omits it simply opens nothing.
75
+ */
76
+ openCheckin?(target?: ChatCheckinTarget): Promise<EverfurResult<ConversationId | null>>;
77
+ /** Mark the active thread read and zero `unreadCount`. Settles; a no-op without an active thread. */
78
+ markRead(): Promise<EverfurResult<void>>;
79
+ /**
80
+ * CRN-16. The turn in flight is being re-attempted by the SDK with nothing asked of the reader. The
81
+ * prebuilt surfaces render the app's `Reconnecting` caption for it.
82
+ *
83
+ * OPTIONAL on the type, always present from the hook, for the same reason `stopped` is.
84
+ */
85
+ readonly reconnecting?: boolean;
86
+ /**
87
+ * CRN-16. Re-read the active thread's newest window and the limit-1 list, merging in anything the platform
88
+ * wrote while the host was away. Settles; a no-op without a thread and while a turn is in flight.
89
+ *
90
+ * OPTIONAL on the type, always present from the hook, for the same reason `stopped` is.
91
+ */
92
+ refreshActiveThread?(): Promise<EverfurResult<void>>;
93
+ /**
94
+ * Record the owner's answer to a follow-up check-in against the scoped pet and reflect it on the message
95
+ * (`message.checkin`). Settles; without a pet in scope it is `validationFailed` before any I/O.
96
+ */
97
+ answerCheckin(caseId: string, answer: CheckinAnswer): Promise<EverfurResult<CheckinOutcome>>;
98
+ /**
99
+ * Leave the active thread for a fresh, empty one (the history drawer's "New conversation"): the transcript
100
+ * clears and the next `send` creates the conversation. Nothing is fetched or deleted.
101
+ */
102
+ newConversation(): void;
103
+ /**
104
+ * The reader's rating per assistant message (keyed by the message id), for the thumbs: what was last recorded
105
+ * this session. A message with no entry is unrated. Local state; the server keeps its own copy.
106
+ */
107
+ readonly sentimentByMessage: Readonly<Record<string, ChatSentiment>>;
108
+ /**
109
+ * Rate an assistant reply (`POST /widget/v1/messages/{message_id}/feedback`). Only a message with a server
110
+ * `responseId` is eligible (a local or pending id settles to `validationFailed` before any I/O). A tap on the
111
+ * sentiment already recorded CLEARS it locally and sends nothing (the consumer app's behaviour); a different
112
+ * one replaces it. `reason` upgrades a thumbs-down to the specific `feedback_type` the not-helpful sheet
113
+ * picks, `notes` (<= 4000 characters) rides with it. Settles `ok({ feedbackId })` (an empty id on a local
114
+ * clear); never throws.
115
+ */
116
+ feedback(responseId: ResponseId, sentiment: ChatSentiment, reason?: ChatFeedbackReason | null, notes?: string | null): Promise<EverfurResult<ChatFeedbackReceipt>>;
117
+ /**
118
+ * Optimistic; the blank user bubble is removed on a pre-first-delta failure (controller-owned). Drives the
119
+ * controller stream to completion and settles: `ok(responseId)` on a completed turn (the id is null when
120
+ * the terminal `done` frame carried no message id), or `err` with the terminal EverfurError. `imageS3Keys`
121
+ * are the keys of images staged through the attachments queue (at most 5).
122
+ */
123
+ send(text: string, opts?: {
124
+ readonly imageS3Keys?: readonly string[];
125
+ }): Promise<EverfurResult<ResponseId | null>>;
126
+ /**
127
+ * CRN-06. Ask a grounded question in a FRESH conversation: the thread on screen is left and `prompt` is
128
+ * the first turn of a new one (the consumer's "Ask Everfur" handoff from a records card). Settles like
129
+ * `send`.
130
+ *
131
+ * OPTIONAL on the type, always present from the hook, for the same reason `stopped` is.
132
+ */
133
+ askEverfur?(prompt: string): Promise<EverfurResult<ResponseId | null>>;
134
+ /** Re-sends the last turn with the SAME idempotency key; no duplicate user bubble (§7.4). */
135
+ retryLast(): Promise<EverfurResult<ResponseId | null>>;
136
+ /** Aborts the in-flight stream; not an error. */
137
+ stop(): void;
138
+ }
139
+ /**
140
+ * @throws {EverfurConfigError} kind 'not-initialized' if called outside an EverfurProvider.
141
+ * Auto-disposes its controller reference on unmount.
142
+ */
143
+ declare function useEverfurChat(opts?: {
144
+ readonly petRef?: PetRef;
145
+ readonly conversationId?: ConversationId;
146
+ }): UseEverfurChatState;
147
+
148
+ /**
149
+ * The host's lifecycle and connectivity signals. Each subscribe returns its own unsubscribe, which the SDK
150
+ * calls on unmount; a listener that throws is contained by the caller, never by the host.
151
+ */
152
+ interface LifecyclePort {
153
+ /**
154
+ * The host came back to the foreground. Only the real blur-to-focus edge, please: a platform that flips
155
+ * through an inactive state constantly (iOS control centre, a call banner) would otherwise turn a
156
+ * notification-shade pull into a request.
157
+ */
158
+ onForeground(listener: () => void): () => void;
159
+ /** Connectivity returned. Omit it and a deferred refresh waits for the next foreground instead. */
160
+ onOnline?(listener: () => void): () => void;
161
+ /**
162
+ * Something told the host THIS member's thread changed: the push that carried the message. Announced
163
+ * triggers are never coalesced, because that is the one case where the reader is waiting on new content.
164
+ */
165
+ onAnnounced?(listener: () => void): () => void;
166
+ /** Is the host unambiguously offline? Absent reads as online, which is exactly today's behaviour. */
167
+ isOffline?(): boolean;
168
+ }
169
+
170
+ /**
171
+ * CRN-16. The host's own storage for an unsent draft. The SDK ships NO persistence of its own: a draft is
172
+ * memory-only unless a host passes this, because a question half-typed on a health surface is the reader's
173
+ * own text and where it may be written down is the host's decision, not the SDK's. `conversationId` is null
174
+ * for the not-yet-created thread, so a host that keys on it can scope per thread.
175
+ */
176
+ interface EverfurChatDraftStore {
177
+ /** The draft you last stored for this thread, or null. May be async. */
178
+ read(conversationId: string | null): string | null | Promise<string | null>;
179
+ /** Store the unsent draft for this thread; an empty string means the reader cleared it. May be async. */
180
+ write(conversationId: string | null, text: string): void | Promise<void>;
181
+ }
182
+
183
+ /** The three server tiers plus the app's calm `general` tier for an informational turn. */
184
+ type UrgencyDisplayLevel = UrgencyLevel | 'general';
185
+
186
+ /** The pet list state a header or switcher renders from. */
187
+ interface UseEverfurPetsState {
188
+ /** The registered pets, newest first as the server lists them; empty until the first fetch settles. */
189
+ readonly pets: readonly WidgetPet[];
190
+ /** The provider's active pet (`activePet` prop or `handle.setActivePet`), resolved against the list; null when unscoped or not listed. */
191
+ readonly activePet: WidgetPet | null;
192
+ /** True while a fetch is in flight (the first one too, so a header can hold its disc until the name is known). */
193
+ readonly loading: boolean;
194
+ /** The last fetch's settled error (`error.displayMessage` is safe to show), or null. */
195
+ readonly error: EverfurError | null;
196
+ /** Fetch the list again (after `registerPet`, or a retry). Settles; never throws. */
197
+ refresh(): Promise<void>;
198
+ }
199
+ /**
200
+ * @throws {EverfurConfigError} kind 'not-initialized' if called outside an EverfurProvider.
201
+ */
202
+ declare function useEverfurPets(): UseEverfurPetsState;
203
+
204
+ /** What a composer renders and calls. */
205
+ interface UseChatAttachmentsState {
206
+ /** True when the host wired an upload transport; the attach control is hidden otherwise. */
207
+ readonly available: boolean;
208
+ /** The rows, in the order they were added. */
209
+ readonly attachments: readonly AttachmentState[];
210
+ /** The composer's slots. */
211
+ readonly maxPerMessage: number;
212
+ /** True while any row is still uploading: the send is blocked meanwhile. */
213
+ readonly uploading: boolean;
214
+ /**
215
+ * True while any row FAILED to upload. The send is blocked on this too, because the alternative is the
216
+ * silent drop: `s3Keys` names only the rows that landed and the strip is cleared on dispatch, so a send here
217
+ * would post the message without the photo the owner picked and leave nothing behind to say so. The consumer
218
+ * app blocks the same way (everfur-mobile `useAuthenticatedReportChat.ts`, the `blockingAttachment` guard).
219
+ */
220
+ readonly failed: boolean;
221
+ /**
222
+ * True while the composer must refuse the send: a row is uploading or a row failed. `failed` says which of
223
+ * the two needs a sentence (the spinner already speaks for the other).
224
+ */
225
+ readonly blocked: boolean;
226
+ /** The S3 keys of every uploaded row, for `send(text, { imageS3Keys })`. */
227
+ readonly s3Keys: readonly string[];
228
+ /** The last failure that kept a pick out of the queue (`too_large`, `unsupported_type`, `too_many`), or null. */
229
+ readonly rejected: AttachmentError | null;
230
+ /** Validate and enqueue one or more picked files; returns each outcome. Never throws. */
231
+ add(files: FileHandle | readonly FileHandle[]): readonly AttachmentOutcome<AttachmentState>[];
232
+ retry(id: string): void;
233
+ remove(id: string): void;
234
+ /** Drop every row (after a successful send). */
235
+ clear(): void;
236
+ /** Forget the last rejection (the composer showed it). */
237
+ dismissRejected(): void;
238
+ }
239
+ interface UseChatAttachmentsOptions {
240
+ /** The composer's slots; default `MAX_ATTACHMENTS_PER_MESSAGE` (5). */
241
+ readonly maxPerMessage?: number;
242
+ /** Test seam: a queue to bind instead of building one from the provider. */
243
+ readonly queue?: AttachmentQueue;
244
+ /**
245
+ * The upload transport to bind instead of the provider's `uploadTransport`: the web surface passes its own
246
+ * fetch-based one, since a browser needs no host adapter to post a multipart form. Absent, the host's.
247
+ */
248
+ readonly transport?: UploadTransport;
249
+ }
250
+ /**
251
+ * The attachment rows of the composer. The queue lives for the scope (user, session epoch) and is disposed on
252
+ * unmount or re-scope, so a previous user's thumbnails never survive a switch.
253
+ * @throws {EverfurConfigError} kind 'not-initialized' if called outside an EverfurProvider.
254
+ */
255
+ declare function useChatAttachments(options?: UseChatAttachmentsOptions): UseChatAttachmentsState;
256
+
257
+ export { type ChatFeedbackReason as C, type EverfurChatDraftStore as E, type LifecyclePort as L, type UrgencyDisplayLevel as U, type ChatFeedbackReasonOption as a, type ChatSentiment as b, type UseChatAttachmentsOptions as c, type UseChatAttachmentsState as d, type UseEverfurChatState as e, type UseEverfurPetsState as f, useEverfurChat as g, useEverfurPets as h, useChatAttachments as u };