@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,376 @@
1
+ import { C as CheckinAnswer, a as CheckinOutcome } from './casesRepository-v6QczS9N.js';
2
+ import { A as AuthContext } from './identity-CEi9GRFZ.js';
3
+ import { E as EverfurError, c as EverfurResult } from './EverfurResult-DN9pL2Ab.js';
4
+ import { R as RequestFunnel } from './requestFunnel-DFMGcluw.js';
5
+ import { P as PetRef, C as ConversationId, b as ResponseId } from './ids-B2GAAifq.js';
6
+ import { i as UrgencyLevel, F as Frame } from './config-C7eb_IMD.js';
7
+ import { E as ErrorPolicyPort } from './ErrorPolicyPort-CwbfmxzJ.js';
8
+ import { T as TelemetryPort } from './TelemetryPort-BDNr00hu.js';
9
+ import { F as FileHandle } from './ports-BN6RHF9W.js';
10
+
11
+ /** Injectable timers so the watchdog + deadlines are testable with a fake clock (no direct setTimeout). */
12
+ interface Timers$1 {
13
+ setTimeout(handler: () => void, ms: number): unknown;
14
+ clearTimeout(handle: unknown): void;
15
+ now(): number;
16
+ }
17
+
18
+ /** User-scoped history. Titles are restricted data; keep them out of logs and persistent storage. */
19
+ interface ChatConversation {
20
+ readonly id: ConversationId;
21
+ readonly title: string | null;
22
+ readonly createdAt: string;
23
+ readonly updatedAt: string;
24
+ /**
25
+ * Unread assistant messages for the calling user (`unread_message_count`), for a badge. null when the wire
26
+ * did not carry it, which means the server does not speak unread, never "all read".
27
+ */
28
+ readonly unreadCount: number | null;
29
+ }
30
+ interface ChatHistoryOptions {
31
+ readonly cursor?: string;
32
+ readonly limit?: number;
33
+ readonly signal?: AbortSignal;
34
+ }
35
+ interface ChatConversationListOptions extends ChatHistoryOptions {
36
+ readonly petRef?: PetRef;
37
+ }
38
+ interface ChatConversationPage {
39
+ readonly conversations: readonly ChatConversation[];
40
+ readonly nextCursor: string | null;
41
+ }
42
+ /** Each page is chronological; nextCursor loads the older window, to prepend rather than append. */
43
+ interface ChatMessagePage {
44
+ readonly messages: readonly ChatMessage[];
45
+ readonly nextCursor: string | null;
46
+ }
47
+
48
+ /**
49
+ * The answerable check-in behind an assistant message, derived from its `proactiveOriginRef` and kept up to date
50
+ * by `ChatController.answerCheckin`. `answer` is the answer on record for this session (null while unanswered);
51
+ * `resolutionText` is the server's own post-answer line when it sent one.
52
+ */
53
+ interface ChatCheckin {
54
+ readonly caseId: string;
55
+ readonly answer: CheckinAnswer | null;
56
+ readonly resolutionText: string | null;
57
+ /**
58
+ * The case's lifecycle status as last known (`watching` while open, then `resolved`, `escalated`, `lapsed`),
59
+ * null while UNKNOWN. The server accepts an answer only while the case is watching, so a surface draws no
60
+ * answer row for any other known status: leaving one tappable produced a 404 that reads to the owner as
61
+ * "your answer did not save". Unknown does NOT lock, so a surface that cannot read the status keeps exactly
62
+ * the behaviour it had before this existed.
63
+ */
64
+ readonly status: string | null;
65
+ }
66
+ /** The one status that still takes an answer (the consumer's `ANSWERABLE_STATUS`). */
67
+ declare const CHECKIN_ANSWERABLE_STATUS = "watching";
68
+ /** True when the case will no longer take an answer, so the surface draws no answer row. */
69
+ declare function isCheckinSettled(checkin: ChatCheckin): boolean;
70
+
71
+ type ChatStatus = 'idle' | 'streaming' | 'complete' | 'error';
72
+ /** Opaque citation record (DoneFrame.citations shape). Rendered by the UI layer, never trusted for logic. */
73
+ type Citation = Readonly<Record<string, unknown>>;
74
+ interface ChatMessage {
75
+ /** Stable list key: a client id for a user turn, the responseId for a finalized assistant turn. */
76
+ readonly id: string;
77
+ readonly role: 'user' | 'assistant';
78
+ readonly text: string;
79
+ /**
80
+ * ISO 8601. A history row carries the server's `created_at`; an optimistic user turn and a streamed reply
81
+ * are stamped from the controller clock when the row is created, and the stamp survives the reply's
82
+ * finalize. Rendered by the message footer as the app does (`toLocaleTimeString`, hour and minute).
83
+ */
84
+ readonly createdAt: string;
85
+ readonly citations?: readonly Citation[];
86
+ readonly responseId?: ResponseId;
87
+ /** Optimistic user bubble; removed if the turn fails BEFORE the first delta. */
88
+ readonly pending?: boolean;
89
+ /** Server classification, never inferred by the SDK from message text. */
90
+ readonly urgencyLevel?: UrgencyLevel | null;
91
+ readonly urgencyReason?: string | null;
92
+ /**
93
+ * True when the done frame carried the urgency slot (`DoneFrame.urgencyProvided`): with `urgencyLevel`
94
+ * null it means the server classified the turn as informational, which the surfaces show as the calm
95
+ * "Good to know" tier. Absent on user turns, on history rows and on a turn the server never classified.
96
+ */
97
+ readonly urgencyProvided?: boolean;
98
+ /**
99
+ * The platform's occasion marker on a message it wrote itself (`checkin:<case_id>:<YYYY-MM-DD>` for a
100
+ * follow-up check-in), verbatim from the wire. Absent on ordinary turns.
101
+ */
102
+ readonly proactiveOriginRef?: string;
103
+ /** The answerable check-in behind this message, when `proactiveOriginRef` names one (see `answerCheckin`). */
104
+ readonly checkin?: ChatCheckin;
105
+ }
106
+ interface ChatSnapshot {
107
+ readonly status: ChatStatus;
108
+ /** [] => Empty state; length > 0 => Populated. */
109
+ readonly messages: readonly ChatMessage[];
110
+ /** nulled on a 404 before recreate. */
111
+ readonly conversationId: ConversationId | null;
112
+ /** present iff status === 'error'; NEVER thrown. */
113
+ readonly error: EverfurError | null;
114
+ readonly isStreaming: boolean;
115
+ /** true during the initial conversation prime => Loading. */
116
+ readonly isBootstrapping: boolean;
117
+ /** Opaque cursor for older messages in the active conversation, not a forward-page cursor. */
118
+ readonly historyCursor?: string | null;
119
+ readonly isLoadingHistory?: boolean;
120
+ /**
121
+ * The last turn was STOPPED by the owner before its first delta, so the message they typed is on screen with
122
+ * no answer under it and nothing said about why. Not an error (nothing failed), which is why it is its own
123
+ * flag: a surface renders the consumer app's `Response stopped` notice with a retry, and the next send,
124
+ * retry or thread change clears it.
125
+ */
126
+ readonly stopped?: boolean;
127
+ /**
128
+ * The turn in flight is being RE-ATTEMPTED by the controller with nothing asked of the owner: the mid-stream
129
+ * token refresh replay, or the one recreate-and-resend after the conversation went missing. The consumer app
130
+ * shows its `Reconnecting\u2026` caption for exactly this (`streamStatus === 'reconnecting'`, set from the
131
+ * stream registry's `recovering`). Cleared by the turn settling either way, by `stop()` and by a thread
132
+ * change. Optional on the type for the same reason `stopped` is: it was added to a shipped interface.
133
+ */
134
+ readonly reconnecting?: boolean;
135
+ /**
136
+ * Flattened, de-duplicated suggested-prompt strings (backend-owned copy). After a reply they are THAT reply's
137
+ * `follow_up_questions` from the done frame; a reply that carries none falls back to the bootstrap set
138
+ * (empty until the bootstrap resolves, empty when the backend returns none). The UI renders these as the
139
+ * tappable "Follow up questions" list; each string is a ready-to-send message.
140
+ */
141
+ readonly suggestedPrompts: readonly string[];
142
+ /**
143
+ * Unread assistant messages in the active thread, for a badge: the count the conversation list last
144
+ * reported for it (`unread_message_count`), 0 once `markRead()` settles. null while unknown, which is also
145
+ * what a server that does not speak unread leaves it at; never read null as "all read".
146
+ */
147
+ readonly unreadCount: number | null;
148
+ /**
149
+ * CRN-01. Does ANY thread this controller has listed still carry unread assistant messages? The header's
150
+ * dot, answerable without the history drawer ever being opened, because the chat bootstrap reads the head
151
+ * of the list on mount. False while nothing has been listed and against a server that does not speak
152
+ * unread, which is the same thing the dot already means: nothing to show.
153
+ */
154
+ readonly hasUnreadThreads?: boolean;
155
+ }
156
+ interface SendOptions {
157
+ readonly conversationId?: ConversationId;
158
+ readonly petRef?: PetRef;
159
+ readonly signal?: AbortSignal;
160
+ readonly idempotencyKey?: string;
161
+ /**
162
+ * The S3 keys of images already staged through `core/chat/attachments` (`POST /widget/v1/uploads/initiate`,
163
+ * then the multipart upload), sent as `image_s3_keys`. At most `MAX_IMAGE_KEYS_PER_MESSAGE`; the server
164
+ * checks each key is the caller's own. The message text is still required.
165
+ */
166
+ readonly imageS3Keys?: readonly string[];
167
+ }
168
+ /** The server's cap on `image_s3_keys` per message (`SendWidgetMessageRequest`, mirrored from the consumer send). */
169
+ declare const MAX_IMAGE_KEYS_PER_MESSAGE = 5;
170
+ /**
171
+ * The feedback a reader records on an assistant message (`POST /widget/v1/messages/{message_id}/feedback`,
172
+ * the consumer `MessageFeedbackType` enum): the three sentiments the thumbs record on tap, and the reasons the
173
+ * not-helpful sheet upgrades a thumbs-down to.
174
+ */
175
+ type ChatFeedbackType = 'helpful' | 'neutral' | 'not_helpful' | 'wrong' | 'outdated' | 'dangerous' | 'unclear';
176
+ /** Every `ChatFeedbackType`, for a validator or a picker. */
177
+ declare const CHAT_FEEDBACK_TYPES: readonly ChatFeedbackType[];
178
+ /** The server's cap on the free-text `notes` (`notes: Field(None, max_length=4000)`). */
179
+ declare const FEEDBACK_NOTES_MAX_CHARS = 4000;
180
+ /** What a recorded feedback settles to: the server's row id. */
181
+ interface ChatFeedbackReceipt {
182
+ readonly feedbackId: string;
183
+ }
184
+ /**
185
+ * What a check-in tap is about: the `case` target of an Everfur push
186
+ * (src/core/notifications/parse.ts `EverfurNotificationTarget`), which carries the conversation id when the
187
+ * platform knew it and only the pet when it did not. Both optional, so a host that has just the pet (a
188
+ * deep link, a home-screen card) passes what it has.
189
+ */
190
+ interface ChatCheckinTarget {
191
+ readonly conversationId?: ConversationId | null;
192
+ readonly petRef?: PetRef | null;
193
+ }
194
+ interface ChatHandlers {
195
+ onFrame(frame: Frame): void;
196
+ onDone(responseId: ResponseId | null): void;
197
+ onError(error: EverfurError): void;
198
+ }
199
+ /** A suggested-prompt category returned by the prompts bootstrap endpoint. */
200
+ interface SuggestedPromptCategory {
201
+ readonly category: string;
202
+ readonly prompts: readonly string[];
203
+ }
204
+ interface ChatControllerDeps {
205
+ /** Device auth context (bearer-XOR-pk precedence + lazy token). Carries the TransportPort. */
206
+ readonly auth: AuthContext;
207
+ readonly telemetry?: TelemetryPort;
208
+ readonly errorPolicy?: ErrorPolicyPort;
209
+ readonly timers?: Timers$1;
210
+ /** Injected RNG for deterministic backoff in tests. */
211
+ readonly rng?: () => number;
212
+ /** Injected id factory (client message ids) for deterministic tests. */
213
+ readonly newId?: () => string;
214
+ /** Injected idempotency-key factory for the TURN identity (see `buildSendRequest`). */
215
+ readonly makeIdempotencyKey?: () => string;
216
+ /** The ONE request funnel. Built from `auth` when absent; injected in tests for a deterministic clock. */
217
+ readonly funnel?: RequestFunnel;
218
+ readonly budget?: {
219
+ readonly idleMs?: number;
220
+ readonly overallMs?: number;
221
+ };
222
+ readonly initialConversationId?: ConversationId | null;
223
+ /** The pet this controller is scoped to (the registry's scope key), the pet a check-in answer is recorded against. */
224
+ readonly petRef?: PetRef | null;
225
+ }
226
+ interface ChatController {
227
+ /** useSyncExternalStore subscribe. Returns an unsubscribe. */
228
+ subscribe(listener: () => void): () => void;
229
+ /** A stable frozen snapshot; identity changes only on real change. */
230
+ getSnapshot(): ChatSnapshot;
231
+ /** Stream a reply. The iterable ALWAYS completes cleanly; a failure is a terminal Frame, never a throw. */
232
+ send(text: string, opts?: SendOptions): AsyncIterable<Frame>;
233
+ /** Imperative escape hatch; returns a teardown, also torn down on dispose(). */
234
+ send(text: string, opts: SendOptions, handlers: ChatHandlers): () => void;
235
+ /**
236
+ * CRN-06. Ask a grounded question in a FRESH conversation: the thread on screen is left (its transcript
237
+ * clears and anything in flight is dropped), a new conversation is opened and `prompt` is the first turn
238
+ * in it. This is the consumer app's "Ask Everfur" handoff, whose whole point is that a question about one
239
+ * lab marker does not land in the middle of an unrelated thread
240
+ * (`useConsumerChatRouteHandoffs.ts`: `sendMessage(prompt, { forceFreshConversation: true })`).
241
+ *
242
+ * NOT GROUNDED ON THE WIRE YET. The consumer plane carries a `focus_ref` on conversation create, which
243
+ * orients the SYSTEM PROMPT at the entity the owner is looking at. `CreateWidgetConversationRequest`
244
+ * declares `title`, `pet_ref` and `pet` and nothing else, and it is a plain pydantic v2 model
245
+ * (`extra="ignore"`), so a `focus_ref` sent here would be discarded without a 422 and the SDK would be
246
+ * asserting a grounding that never happened. The prompt the records surfaces build already names the
247
+ * entity in words, which is what actually reaches the model today.
248
+ */
249
+ askEverfur(prompt: string, opts?: SendOptions): AsyncIterable<Frame>;
250
+ /** Re-send the last turn without a duplicate user bubble, reusing its idempotency key. */
251
+ retryLast(): AsyncIterable<Frame>;
252
+ /** Abort in-flight; not an error. Returns to pre-send (idle) and drops a never-answered optimistic bubble. */
253
+ stop(): void;
254
+ /** Idempotent. Aborts in-flight, bumps the epoch, drops listeners + handler subscriptions. */
255
+ dispose(): void;
256
+ /** Re-scope on user/pet switch: aborts in-flight and bumps the epoch so a late write drops. */
257
+ rescope(): void;
258
+ /** Bootstrap helper (§8): create a conversation. Unary, authed, settles. */
259
+ createConversation(opts?: {
260
+ readonly petRef?: PetRef;
261
+ }): Promise<EverfurResult<ConversationId>>;
262
+ /**
263
+ * Bootstrap helper (CRN-01): the whole "which thread does chat open in" decision, made HERE rather than in
264
+ * `bootstrapChat`, because the race guard that stops a send opening a second conversation lives here and
265
+ * has to cover the head read as well as the create. Reads the head of the pet's list (which is also what
266
+ * materializes a follow-up check-in the member is owed), resumes it when it carries unread assistant
267
+ * content, and otherwise creates exactly as `createConversation` did. Settles; never throws.
268
+ */
269
+ primeConversation(opts?: {
270
+ readonly petRef?: PetRef;
271
+ }): Promise<EverfurResult<ConversationId>>;
272
+ /** Bootstrap helper (§8): fetch the session's suggested prompts, optionally personalized to a pet. Settles; never throws. */
273
+ getPrompts(opts?: {
274
+ readonly petRef?: PetRef;
275
+ }): Promise<EverfurResult<readonly SuggestedPromptCategory[]>>;
276
+ /** Adopt (or clear) the active conversation id, e.g. after bootstrap primes one. */
277
+ adoptConversation(id: ConversationId | null): void;
278
+ /** Read a page of this user's conversations; optional petRef filters on the server. */
279
+ listConversations(opts?: ChatConversationListOptions): Promise<EverfurResult<ChatConversationPage>>;
280
+ /**
281
+ * CRN-01. Open the thread a follow-up check-in landed in: the conversation the push named, or, with only a
282
+ * pet, the HEAD of that pet's list. Reading the list is what materializes a check-in the member is owed
283
+ * (`widget_follow_ups_for_list`), so the pet-only form is not a lookup, it is the trigger. Settles to the
284
+ * conversation opened, or `ok(null)` when the member has no thread yet, which is not a failure: the empty
285
+ * chat they are already looking at is the right place for them to be. Never throws.
286
+ */
287
+ openCheckin(target?: ChatCheckinTarget): Promise<EverfurResult<ConversationId | null>>;
288
+ /** Read a chronological message window without changing the active conversation. */
289
+ getMessages(id: ConversationId, opts?: ChatHistoryOptions): Promise<EverfurResult<ChatMessagePage>>;
290
+ /** Switch threads and hydrate the latest message window. Clears the old thread immediately. */
291
+ resumeConversation(id: ConversationId): Promise<EverfurResult<void>>;
292
+ /** Prepend the next older window, preserving any replies sent while the page was loading. */
293
+ loadOlderMessages(): Promise<EverfurResult<void>>;
294
+ /**
295
+ * CRN-16. Re-read the active thread's NEWEST window and the pet's limit-1 conversation list, and merge
296
+ * what is new into the transcript. This is how a message the PLATFORM wrote (a follow-up check-in, a
297
+ * reminder) becomes visible on a plane with no websocket and no polling; the host decides when to call it
298
+ * by wiring a lifecycle port, and `decideChatRefresh` decides whether it may run. Non-destructive: rows
299
+ * already on screen keep their place and any older pages the reader scrolled back to are kept. A no-op
300
+ * without a thread and while a turn is in flight. Settles; never throws.
301
+ */
302
+ refreshActiveThread(): Promise<EverfurResult<void>>;
303
+ /**
304
+ * Adopt the suggested-prompt categories fetched by the bootstrap (§8): flattened + de-duplicated onto the
305
+ * snapshot's `suggestedPrompts` so the prebuilt UI can render the tappable follow-up list. Idempotent; a
306
+ * no-op when the flattened set is empty and none are shown.
307
+ */
308
+ adoptPrompts(categories: readonly SuggestedPromptCategory[]): void;
309
+ /**
310
+ * Record the owner's answer to a follow-up check-in (`POST /widget/v1/pets/{pet_ref}/cases/{case_id}/checkin`)
311
+ * against the scoped pet (or `opts.petRef`), and reflect it on the message carrying that case: `checkin.answer`
312
+ * and the server's `resolutionText`. A stale, closed or foreign case is the ordinary not-found error; without
313
+ * a pet it settles to `validationFailed` before any I/O. Never posts a message into the thread.
314
+ */
315
+ answerCheckin(caseId: string, answer: CheckinAnswer, opts?: {
316
+ readonly petRef?: PetRef;
317
+ readonly signal?: AbortSignal;
318
+ }): Promise<EverfurResult<CheckinOutcome>>;
319
+ /**
320
+ * Advance the caller's read watermark on the active thread (`POST /widget/v1/conversations/{id}/read`,
321
+ * idempotent) and zero `unreadCount`. Called for you when `resumeConversation` opens a thread the list reported
322
+ * unread; call it yourself when you opened the thread another way. A no-op without an active thread.
323
+ */
324
+ markRead(opts?: {
325
+ readonly signal?: AbortSignal;
326
+ }): Promise<EverfurResult<void>>;
327
+ /**
328
+ * Record the reader's feedback on an assistant message (`POST /widget/v1/messages/{message_id}/feedback`,
329
+ * body `{ feedback_type, notes? }`). The server upserts per reader, so a second call replaces the first.
330
+ * Only a message with a server `responseId` can be rated: a local id settles to `validationFailed` before
331
+ * any I/O, as do an unknown `feedbackType` and notes over `FEEDBACK_NOTES_MAX_CHARS`. Clearing a rating is
332
+ * local to the surface (the consumer app sends nothing for it). Settles `ok({ feedbackId })`; never throws.
333
+ */
334
+ submitFeedback(responseId: ResponseId, feedbackType: ChatFeedbackType, notes?: string | null, opts?: {
335
+ readonly signal?: AbortSignal;
336
+ }): Promise<EverfurResult<ChatFeedbackReceipt>>;
337
+ }
338
+
339
+ /** The presigned POST/PUT policy returned by `/uploads/initiate` (SPEC-11b §2.1). */
340
+ interface PresignedPolicy {
341
+ /** Absolute S3 endpoint URL to POST/PUT the bytes at. */
342
+ readonly url: string;
343
+ /** POST-policy form fields to include with the upload (empty for a plain PUT). */
344
+ readonly fields: Readonly<Record<string, string>>;
345
+ /** The owned-uploads-prefixed key the analyze call then references. */
346
+ readonly s3Key: string;
347
+ /** epoch seconds the policy expires; telemetry only. */
348
+ readonly expiresAt: number | null;
349
+ }
350
+ /**
351
+ * The native upload seam. It PUTs `file` at the presigned `target` (SPEC-11b §2.1). `idempotencyKey` is reused
352
+ * on every retry so a re-uploaded identical file dedupes server-side. A network failure REJECTS; the controller
353
+ * normalizes that to a `mediaUploadFailed` and exposes a retake affordance (never auto-retried, SPEC-00 §3.2).
354
+ *
355
+ * NOTE: the spine `FilePort.presignedPut(file, { idempotencyKey, signal })` has no slot for the presigned
356
+ * target; this richer port is the shape it must grow to. See the manifest gap note.
357
+ */
358
+ interface UploadPort {
359
+ presignedPut(file: FileHandle, opts: {
360
+ readonly target: PresignedPolicy;
361
+ readonly idempotencyKey: string;
362
+ readonly signal?: AbortSignal;
363
+ }): Promise<void>;
364
+ }
365
+ interface Timers {
366
+ setTimeout(handler: () => void, ms: number): unknown;
367
+ clearTimeout(handle: unknown): void;
368
+ now(): number;
369
+ }
370
+ /** The useSyncExternalStore contract the rn hooks bind to. */
371
+ interface ReadableStore<S> {
372
+ subscribe(listener: () => void): () => void;
373
+ getSnapshot(): S;
374
+ }
375
+
376
+ export { type ChatCheckin as C, FEEDBACK_NOTES_MAX_CHARS as F, MAX_IMAGE_KEYS_PER_MESSAGE as M, type PresignedPolicy as P, type ReadableStore as R, type SendOptions as S, type Timers as T, type UploadPort as U, type ChatCheckinTarget as a, type ChatConversation as b, type ChatConversationListOptions as c, type ChatConversationPage as d, type ChatFeedbackReceipt as e, type ChatFeedbackType as f, type ChatHistoryOptions as g, type ChatMessagePage as h, type ChatMessage as i, type ChatStatus as j, type Citation as k, type ChatController as l, type ChatControllerDeps as m, type SuggestedPromptCategory as n, CHAT_FEEDBACK_TYPES as o, CHECKIN_ANSWERABLE_STATUS as p, type ChatHandlers as q, type ChatSnapshot as r, type Timers$1 as s, isCheckinSettled as t };
@@ -0,0 +1,93 @@
1
+ /** The consumer profile's sex. */
2
+ type PetSex = 'male' | 'female' | 'unknown';
3
+ /** How exact `birthDate` is. Always sent together with `birthDate`. */
4
+ type PetBirthDatePrecision = 'day' | 'month' | 'year';
5
+ /** The consumer profile's activity level. */
6
+ type PetActivityLevel = 'low' | 'medium' | 'high' | 'athletic';
7
+ /** Where the pet lives. */
8
+ type PetIndoorOutdoor = 'indoor' | 'outdoor' | 'both';
9
+ /** An allergy's severity. */
10
+ type PetAllergySeverity = 'mild' | 'moderate' | 'severe';
11
+ /**
12
+ * One allergy (the consumer allergy fields). `ref` is your own stable id for the item: send it and an edit updates
13
+ * the same row; omit it and the item matches an earlier row of yours by name. Never shown to the member.
14
+ */
15
+ interface PetAllergy {
16
+ readonly ref?: string | null;
17
+ /** 1 to 120 characters. */
18
+ readonly allergen: string;
19
+ readonly severity?: PetAllergySeverity | null;
20
+ /** At most 2000 characters. */
21
+ readonly notes?: string | null;
22
+ }
23
+ /** One medication or supplement (the consumer medication fields). Dates are `YYYY-MM-DD`; the end never precedes the start. */
24
+ interface PetMedication {
25
+ readonly ref?: string | null;
26
+ /** 1 to 120 characters. */
27
+ readonly name: string;
28
+ /** At most 120 characters. */
29
+ readonly dose?: string | null;
30
+ /** At most 120 characters. */
31
+ readonly frequency?: string | null;
32
+ readonly startDate?: string | null;
33
+ readonly endDate?: string | null;
34
+ /** At most 2000 characters. */
35
+ readonly notes?: string | null;
36
+ }
37
+ /** One diagnosed condition (the consumer condition fields). */
38
+ interface PetCondition {
39
+ readonly ref?: string | null;
40
+ /** 1 to 120 characters. */
41
+ readonly conditionName: string;
42
+ /** `YYYY-MM-DD`. */
43
+ readonly diagnosedDate?: string | null;
44
+ /** At most 2000 characters. */
45
+ readonly notes?: string | null;
46
+ }
47
+ /**
48
+ * The health fields of a pet write. Every field is optional; an absent field is unchanged. A scalar set to null is
49
+ * cleared. A list you send is the complete set you hold for that pet (at most 50 items, refs unique within it), and []
50
+ * clears it. Any health field needs a signed session on the device routes and a pet that is a dog or a cat.
51
+ */
52
+ interface PetHealthProfileInput {
53
+ readonly sex?: PetSex | null;
54
+ readonly spayedNeutered?: boolean | null;
55
+ /** `YYYY-MM-DD`. Always sent together with `birthDatePrecision`, including when clearing both to null. */
56
+ readonly birthDate?: string | null;
57
+ readonly birthDatePrecision?: PetBirthDatePrecision | null;
58
+ readonly activityLevel?: PetActivityLevel | null;
59
+ readonly indoorOutdoor?: PetIndoorOutdoor | null;
60
+ /** At most 120 characters. */
61
+ readonly foodBrand?: string | null;
62
+ /** At most 120 characters. */
63
+ readonly foodType?: string | null;
64
+ /** At most 80 characters. */
65
+ readonly microchipId?: string | null;
66
+ readonly allergies?: readonly PetAllergy[];
67
+ readonly medications?: readonly PetMedication[];
68
+ readonly supplements?: readonly PetMedication[];
69
+ readonly conditions?: readonly PetCondition[];
70
+ }
71
+ /**
72
+ * A pet's health profile as Everfur holds it. The scalars are the pet's one shared profile, whoever set them; the
73
+ * lists are the rows YOUR integration wrote, with your refs, and never a row the member entered themselves.
74
+ */
75
+ interface PetHealthProfile {
76
+ /** Moves on every accepted write to the pet from any path. Compare it to tell whether anything changed. */
77
+ readonly profileVersion: number;
78
+ readonly sex: PetSex | null;
79
+ readonly spayedNeutered: boolean | null;
80
+ readonly birthDate: string | null;
81
+ readonly birthDatePrecision: PetBirthDatePrecision | null;
82
+ readonly activityLevel: PetActivityLevel | null;
83
+ readonly indoorOutdoor: PetIndoorOutdoor | null;
84
+ readonly foodBrand: string | null;
85
+ readonly foodType: string | null;
86
+ readonly microchipId: string | null;
87
+ readonly allergies: readonly PetAllergy[];
88
+ readonly medications: readonly PetMedication[];
89
+ readonly supplements: readonly PetMedication[];
90
+ readonly conditions: readonly PetCondition[];
91
+ }
92
+
93
+ export type { PetHealthProfileInput as P, PetHealthProfile as a, PetActivityLevel as b, PetAllergy as c, PetAllergySeverity as d, PetBirthDatePrecision as e, PetCondition as f, PetIndoorOutdoor as g, PetMedication as h, PetSex as i };
@@ -0,0 +1,93 @@
1
+ /** The consumer profile's sex. */
2
+ type PetSex = 'male' | 'female' | 'unknown';
3
+ /** How exact `birthDate` is. Always sent together with `birthDate`. */
4
+ type PetBirthDatePrecision = 'day' | 'month' | 'year';
5
+ /** The consumer profile's activity level. */
6
+ type PetActivityLevel = 'low' | 'medium' | 'high' | 'athletic';
7
+ /** Where the pet lives. */
8
+ type PetIndoorOutdoor = 'indoor' | 'outdoor' | 'both';
9
+ /** An allergy's severity. */
10
+ type PetAllergySeverity = 'mild' | 'moderate' | 'severe';
11
+ /**
12
+ * One allergy (the consumer allergy fields). `ref` is your own stable id for the item: send it and an edit updates
13
+ * the same row; omit it and the item matches an earlier row of yours by name. Never shown to the member.
14
+ */
15
+ interface PetAllergy {
16
+ readonly ref?: string | null;
17
+ /** 1 to 120 characters. */
18
+ readonly allergen: string;
19
+ readonly severity?: PetAllergySeverity | null;
20
+ /** At most 2000 characters. */
21
+ readonly notes?: string | null;
22
+ }
23
+ /** One medication or supplement (the consumer medication fields). Dates are `YYYY-MM-DD`; the end never precedes the start. */
24
+ interface PetMedication {
25
+ readonly ref?: string | null;
26
+ /** 1 to 120 characters. */
27
+ readonly name: string;
28
+ /** At most 120 characters. */
29
+ readonly dose?: string | null;
30
+ /** At most 120 characters. */
31
+ readonly frequency?: string | null;
32
+ readonly startDate?: string | null;
33
+ readonly endDate?: string | null;
34
+ /** At most 2000 characters. */
35
+ readonly notes?: string | null;
36
+ }
37
+ /** One diagnosed condition (the consumer condition fields). */
38
+ interface PetCondition {
39
+ readonly ref?: string | null;
40
+ /** 1 to 120 characters. */
41
+ readonly conditionName: string;
42
+ /** `YYYY-MM-DD`. */
43
+ readonly diagnosedDate?: string | null;
44
+ /** At most 2000 characters. */
45
+ readonly notes?: string | null;
46
+ }
47
+ /**
48
+ * The health fields of a pet write. Every field is optional; an absent field is unchanged. A scalar set to null is
49
+ * cleared. A list you send is the complete set you hold for that pet (at most 50 items, refs unique within it), and []
50
+ * clears it. Any health field needs a signed session on the device routes and a pet that is a dog or a cat.
51
+ */
52
+ interface PetHealthProfileInput {
53
+ readonly sex?: PetSex | null;
54
+ readonly spayedNeutered?: boolean | null;
55
+ /** `YYYY-MM-DD`. Always sent together with `birthDatePrecision`, including when clearing both to null. */
56
+ readonly birthDate?: string | null;
57
+ readonly birthDatePrecision?: PetBirthDatePrecision | null;
58
+ readonly activityLevel?: PetActivityLevel | null;
59
+ readonly indoorOutdoor?: PetIndoorOutdoor | null;
60
+ /** At most 120 characters. */
61
+ readonly foodBrand?: string | null;
62
+ /** At most 120 characters. */
63
+ readonly foodType?: string | null;
64
+ /** At most 80 characters. */
65
+ readonly microchipId?: string | null;
66
+ readonly allergies?: readonly PetAllergy[];
67
+ readonly medications?: readonly PetMedication[];
68
+ readonly supplements?: readonly PetMedication[];
69
+ readonly conditions?: readonly PetCondition[];
70
+ }
71
+ /**
72
+ * A pet's health profile as Everfur holds it. The scalars are the pet's one shared profile, whoever set them; the
73
+ * lists are the rows YOUR integration wrote, with your refs, and never a row the member entered themselves.
74
+ */
75
+ interface PetHealthProfile {
76
+ /** Moves on every accepted write to the pet from any path. Compare it to tell whether anything changed. */
77
+ readonly profileVersion: number;
78
+ readonly sex: PetSex | null;
79
+ readonly spayedNeutered: boolean | null;
80
+ readonly birthDate: string | null;
81
+ readonly birthDatePrecision: PetBirthDatePrecision | null;
82
+ readonly activityLevel: PetActivityLevel | null;
83
+ readonly indoorOutdoor: PetIndoorOutdoor | null;
84
+ readonly foodBrand: string | null;
85
+ readonly foodType: string | null;
86
+ readonly microchipId: string | null;
87
+ readonly allergies: readonly PetAllergy[];
88
+ readonly medications: readonly PetMedication[];
89
+ readonly supplements: readonly PetMedication[];
90
+ readonly conditions: readonly PetCondition[];
91
+ }
92
+
93
+ export type { PetHealthProfileInput as P, PetHealthProfile as a, PetActivityLevel as b, PetAllergy as c, PetAllergySeverity as d, PetBirthDatePrecision as e, PetCondition as f, PetIndoorOutdoor as g, PetMedication as h, PetSex as i };