@everfur/sdk 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/CHANGELOG.md +213 -0
  2. package/dist/{BookedScreen-BJPbXLCG.d.ts → BookedScreen-DFJcgf1e.d.ts} +12 -2
  3. package/dist/{BookedScreen-Cnld-jB_.d.cts → BookedScreen-R5X_Zrlh.d.cts} +12 -2
  4. package/dist/{Chat-CHqcgMyw.d.ts → Chat-DZpYH8Uh.d.ts} +4 -4
  5. package/dist/{Chat-BoAvCWhI.d.cts → Chat-bATY4atj.d.cts} +4 -4
  6. package/dist/{DepthViews-7Y8Ur058.d.ts → DepthViews-BpHUbjSY.d.cts} +1 -1
  7. package/dist/{DepthViews-B0g83e_N.d.cts → DepthViews-C4DC4Kom.d.cts} +1 -1
  8. package/dist/{DepthViews-Dg2bIon_.d.ts → DepthViews-dLTizxjr.d.ts} +1 -1
  9. package/dist/{DepthViews-CT5mQld9.d.cts → DepthViews-qBIoA48w.d.ts} +1 -1
  10. package/dist/animations/index.cjs +1 -1
  11. package/dist/animations/index.d.cts +3 -3
  12. package/dist/animations/index.d.ts +3 -3
  13. package/dist/animations/index.js +1 -1
  14. package/dist/{attachments-CfxsVg7W.d.ts → attachments-CPRFfoHT.d.ts} +2 -2
  15. package/dist/{attachments-rkox0ewd.d.cts → attachments-CUOGILir.d.cts} +5 -5
  16. package/dist/{attachments-CThFsH4b.d.ts → attachments-CXAnZcEg.d.ts} +5 -5
  17. package/dist/{attachments-C3HJNYQ7.d.cts → attachments-Ce06TWqe.d.cts} +2 -2
  18. package/dist/{bookingCopy-Do3zMeXb.d.cts → bookingCopy-BwVopcoV.d.cts} +451 -50
  19. package/dist/{bookingCopy-Y3OGdoMT.d.ts → bookingCopy-DFTv9w6J.d.ts} +451 -50
  20. package/dist/{bookingTypes-DCs8mmBb.d.cts → bookingTypes-D4pD3tHs.d.cts} +13 -1
  21. package/dist/{bookingTypes-DCs8mmBb.d.ts → bookingTypes-D4pD3tHs.d.ts} +13 -1
  22. package/dist/{branding-DYWma2il.d.ts → branding-Bio5MM6g.d.cts} +3 -3
  23. package/dist/{branding-ChXm8gxI.d.cts → branding-ytH4jJq1.d.ts} +3 -3
  24. package/dist/{callCopy-CPe9mbwG.d.cts → callCopy-DHjem0R-.d.cts} +12 -1
  25. package/dist/{callCopy-CPe9mbwG.d.ts → callCopy-DHjem0R-.d.ts} +12 -1
  26. package/dist/{casesRepository-Jj6t60AY.d.cts → casesRepository-CJchNp3x.d.cts} +1 -1
  27. package/dist/{casesRepository-BbgXYPxa.d.ts → casesRepository-DAVcY3jC.d.ts} +1 -1
  28. package/dist/chat/index.cjs +1 -1
  29. package/dist/chat/index.d.cts +9 -9
  30. package/dist/chat/index.d.ts +9 -9
  31. package/dist/chat/index.js +1 -1
  32. package/dist/client/index.cjs +2 -2
  33. package/dist/client/index.d.cts +10 -10
  34. package/dist/client/index.d.ts +10 -10
  35. package/dist/client/index.js +2 -2
  36. package/dist/{config-Dfbj5mlx.d.ts → config-ZxwCylac.d.ts} +1 -1
  37. package/dist/{config-BZX97FmW.d.cts → config-h5h6TsHL.d.cts} +1 -1
  38. package/dist/consent/index.cjs +1 -1
  39. package/dist/consent/index.d.cts +5 -5
  40. package/dist/consent/index.d.ts +5 -5
  41. package/dist/consent/index.js +1 -1
  42. package/dist/{context-DJXnZ1Mx.d.cts → context-CtsAgJnc.d.cts} +7 -7
  43. package/dist/{context-Cbe0zYym.d.ts → context-DtPIshVA.d.ts} +7 -7
  44. package/dist/{copy-dKK5KoAQ.d.cts → copy-CaWaplQc.d.cts} +2 -2
  45. package/dist/{copy-DHekqSKE.d.ts → copy-Cg89Qoal.d.ts} +2 -2
  46. package/dist/core/index.cjs +7 -7
  47. package/dist/core/index.d.cts +21 -21
  48. package/dist/core/index.d.ts +21 -21
  49. package/dist/core/index.js +7 -7
  50. package/dist/{depth-CrpRjWGB.d.ts → depth-Bo4bAwcn.d.ts} +132 -38
  51. package/dist/{depth-NmWSbvfi.d.cts → depth-EXZYEO70.d.cts} +132 -38
  52. package/dist/{entitlementRepository-iL-9vS1i.d.cts → entitlementRepository-BYtVb1oU.d.cts} +3 -3
  53. package/dist/{entitlementRepository-tVNazi8R.d.ts → entitlementRepository-DcbIx8yV.d.ts} +3 -3
  54. package/dist/{identity-B8rp0L9G.d.ts → identity-EC5-apbY.d.ts} +1 -1
  55. package/dist/{identity-D7PO5s9m.d.cts → identity-b5Vp32Vp.d.cts} +1 -1
  56. package/dist/index.cjs +6 -6
  57. package/dist/index.d.cts +17 -17
  58. package/dist/index.d.ts +17 -17
  59. package/dist/index.js +6 -6
  60. package/dist/notifications/index.d.cts +2 -2
  61. package/dist/notifications/index.d.ts +2 -2
  62. package/dist/{pets-BQbXmICf.d.ts → pets-B_27_agU.d.ts} +1 -1
  63. package/dist/{pets-BWx9BKea.d.cts → pets-DM8QvKLo.d.cts} +1 -1
  64. package/dist/{petsRepository-SqIvEMiT.d.cts → petsRepository-BJsJ4cju.d.cts} +1 -1
  65. package/dist/{petsRepository-0oBVydl6.d.ts → petsRepository-CuYZZaI5.d.ts} +1 -1
  66. package/dist/photo/index.cjs +1 -1
  67. package/dist/photo/index.js +1 -1
  68. package/dist/{ports-ChnzSy4E.d.cts → ports-ZmJYgd5I.d.cts} +10 -9
  69. package/dist/{ports-iXPWd7Vt.d.ts → ports-nXHf50_X.d.ts} +10 -9
  70. package/dist/records/depth/index.cjs +2 -2
  71. package/dist/records/depth/index.d.cts +7 -7
  72. package/dist/records/depth/index.d.ts +7 -7
  73. package/dist/records/depth/index.js +2 -2
  74. package/dist/records/index.cjs +3 -3
  75. package/dist/records/index.d.cts +19 -10
  76. package/dist/records/index.d.ts +19 -10
  77. package/dist/records/index.js +3 -3
  78. package/dist/{requestFunnel-DAwb7haa.d.cts → requestFunnel-C_cZXhIA.d.cts} +2 -2
  79. package/dist/{requestFunnel-CQzz2DIW.d.ts → requestFunnel-Ve9BshTB.d.ts} +2 -2
  80. package/dist/{runtimeTypes-BNOxfmfg.d.ts → runtimeTypes-ByKsp8hm.d.ts} +5 -5
  81. package/dist/{runtimeTypes-DB9-kigO.d.cts → runtimeTypes-D155OlBW.d.cts} +5 -5
  82. package/dist/server/events/index.cjs +1 -1
  83. package/dist/server/events/index.d.cts +2 -2
  84. package/dist/server/events/index.d.ts +2 -2
  85. package/dist/server/events/index.js +1 -1
  86. package/dist/server/index.cjs +1 -1
  87. package/dist/server/index.d.cts +3 -3
  88. package/dist/server/index.d.ts +3 -3
  89. package/dist/server/index.js +1 -1
  90. package/dist/televet/booking/index.cjs +4 -1
  91. package/dist/televet/booking/index.d.cts +116 -29
  92. package/dist/televet/booking/index.d.ts +116 -29
  93. package/dist/televet/booking/index.js +4 -1
  94. package/dist/televet/call/index.cjs +1 -1
  95. package/dist/televet/call/index.d.cts +1 -1
  96. package/dist/televet/call/index.d.ts +1 -1
  97. package/dist/televet/call/index.js +1 -1
  98. package/dist/televet/index.cjs +1 -1
  99. package/dist/televet/index.js +1 -1
  100. package/dist/testing/index.cjs +3 -3
  101. package/dist/testing/index.d.cts +1 -1
  102. package/dist/testing/index.d.ts +1 -1
  103. package/dist/testing/index.js +3 -3
  104. package/dist/testing/rn/index.cjs +1 -1
  105. package/dist/testing/rn/index.d.cts +14 -12
  106. package/dist/testing/rn/index.d.ts +14 -12
  107. package/dist/testing/rn/index.js +1 -1
  108. package/dist/testing/web/index.d.cts +9 -9
  109. package/dist/testing/web/index.d.ts +9 -9
  110. package/dist/{timelineRows-BuNhzDbH.d.cts → timelineRows-BNF43SXK.d.cts} +1 -1
  111. package/dist/{timelineRows-Dll2IGFg.d.ts → timelineRows-DXpjECfA.d.ts} +1 -1
  112. package/dist/{tokens-ARWZtMOU.d.cts → tokens-BYtbKwFh.d.cts} +6 -3
  113. package/dist/{tokens-ARWZtMOU.d.ts → tokens-BYtbKwFh.d.ts} +6 -3
  114. package/dist/{typeStyle-YCS8dt19.d.cts → typeStyle-BqfwxZH4.d.cts} +2 -2
  115. package/dist/{typeStyle-8iEqQmP_.d.ts → typeStyle-DKz02DGU.d.ts} +2 -2
  116. package/dist/{uploadTransport-C1p8FuG8.d.cts → uploadTransport-BM_pnEWj.d.cts} +5 -0
  117. package/dist/{uploadTransport-bZIKBTyK.d.ts → uploadTransport-C6kGP1Kd.d.ts} +5 -0
  118. package/dist/{useRecordsDepth-CNEHZJtj.d.cts → useRecordsDepth-CARTuHKh.d.cts} +1 -1
  119. package/dist/{useRecordsDepth-CuNdne6E.d.ts → useRecordsDepth-fPSv-GXU.d.ts} +1 -1
  120. package/dist/video/index.cjs +1 -1
  121. package/dist/video/index.js +1 -1
  122. package/dist/{view-BhqWlYrZ.d.cts → view-DGPaVno8.d.cts} +47 -5
  123. package/dist/{view-DFy8EDwf.d.ts → view-Dc-JlFkf.d.ts} +47 -5
  124. package/dist/web/consent/index.cjs +1 -1
  125. package/dist/web/consent/index.d.cts +5 -5
  126. package/dist/web/consent/index.d.ts +5 -5
  127. package/dist/web/consent/index.js +1 -1
  128. package/dist/web/index.cjs +7 -7
  129. package/dist/web/index.d.cts +23 -22
  130. package/dist/web/index.d.ts +23 -22
  131. package/dist/web/index.js +7 -7
  132. package/dist/web/notifications/index.d.cts +3 -3
  133. package/dist/web/notifications/index.d.ts +3 -3
  134. package/dist/web/records/depth/index.cjs +2 -2
  135. package/dist/web/records/depth/index.d.cts +7 -7
  136. package/dist/web/records/depth/index.d.ts +7 -7
  137. package/dist/web/records/depth/index.js +2 -2
  138. package/dist/web/records/index.cjs +3 -3
  139. package/dist/web/records/index.d.cts +28 -17
  140. package/dist/web/records/index.d.ts +28 -17
  141. package/dist/web/records/index.js +3 -3
  142. package/dist/web/televet/booking/index.cjs +4 -2
  143. package/dist/web/televet/booking/index.d.cts +228 -90
  144. package/dist/web/televet/booking/index.d.ts +228 -90
  145. package/dist/web/televet/booking/index.js +4 -2
  146. package/dist/web/televet/call/index.cjs +1 -1
  147. package/dist/web/televet/call/index.d.cts +1 -1
  148. package/dist/web/televet/call/index.d.ts +1 -1
  149. package/dist/web/televet/call/index.js +1 -1
  150. package/dist/web/televet/index.cjs +3 -3
  151. package/dist/web/televet/index.d.cts +2 -2
  152. package/dist/web/televet/index.d.ts +2 -2
  153. package/dist/web/televet/index.js +3 -3
  154. package/package.json +1 -1
@@ -1,12 +1,115 @@
1
- import { a as TelevetStatePolicy, b as TelevetBookingEntitlement, c as TelevetCancellationPolicy, d as TelevetClinician, e as TelevetSlot, f as TelevetSlotHold, g as TelevetBookingBody, T as TelevetConsult, h as TelevetCancelReceipt, C as ConsultStatus } from './bookingTypes-DCs8mmBb.js';
1
+ import { n as TelevetStatePolicy, j as TelevetBookingEntitlement, k as TelevetCancellationPolicy, l as TelevetClinician, b as TelevetSlot, m as TelevetSlotHold, i as TelevetBookingBody, T as TelevetConsult, a as TelevetCancelReceipt, o as TelevetTriageVerdict, g as ConsultStatus } from './bookingTypes-D4pD3tHs.js';
2
2
  import { E as EverfurError } from './EverfurError-DmELDpXp.js';
3
3
  import { E as EverfurResult } from './EverfurResult-SGvHKsCB.js';
4
- import { R as RequestFunnel } from './requestFunnel-CQzz2DIW.js';
5
- import { A as AuthContext } from './identity-B8rp0L9G.js';
4
+ import { R as RequestFunnel } from './requestFunnel-Ve9BshTB.js';
5
+ import { A as AuthContext } from './identity-EC5-apbY.js';
6
6
  import { E as ErrorPolicyPort } from './ErrorPolicyPort-D22LUVrK.js';
7
7
  import { T as TelemetryPort } from './TelemetryPort-BDNr00hu.js';
8
8
  import { b as VetCallCredential, c as VetCallJoinRefusal } from './callRoom-7wrE3RP2.js';
9
9
 
10
+ /** What the presign is asked for. The route refuses any other field. */
11
+ interface TelevetAttachmentMeta {
12
+ readonly filename: string;
13
+ readonly contentType: string;
14
+ readonly fileSize: number;
15
+ }
16
+ /**
17
+ * The presigned POST the route answers: the chat presign's shape (so the chat attachment hop posts it), with the
18
+ * key the booking sends in `media_refs`.
19
+ */
20
+ interface TelevetAttachmentPolicy {
21
+ readonly upload_id: string;
22
+ readonly upload_url: string;
23
+ readonly upload_fields: Readonly<Record<string, string>>;
24
+ readonly expires_in_seconds: number;
25
+ readonly max_content_length: number;
26
+ readonly s3_key: string;
27
+ readonly purpose: string | null;
28
+ }
29
+
30
+ /** The member's conversations with the vet, one per pet. */
31
+ declare const TELEVET_MESSAGE_THREADS_PATH = "/widget/v1/televet/messages/threads";
32
+ /** One pet's thread: the page read and the send. `petRef` is the partner's own reference for the pet. */
33
+ declare function televetThreadMessagesCall(petRef: string): string;
34
+ /** One pet's read receipt. */
35
+ declare function televetThreadReadCall(petRef: string): string;
36
+ /** The vet's approved summary of one of the member's visits. */
37
+ declare function televetVisitSummaryCall(consultId: string): string;
38
+ /** The send's bound: `CHAT_BODY_MAX_LENGTH`, the consumer thread's own. */
39
+ declare const VET_MESSAGE_CONTENT_MAX = 4000;
40
+ /** One page of a thread when the caller does not say: the route's default. */
41
+ declare const VET_MESSAGE_PAGE_DEFAULT = 50;
42
+ /** The route's largest page. */
43
+ declare const VET_MESSAGE_PAGE_MAX = 100;
44
+ /** Who wrote a message: the member, a clinician, or Everfur. */
45
+ type VetMessageRole = 'owner' | 'vet' | 'system';
46
+ /** One message in a member's vet thread. */
47
+ interface VetMessage {
48
+ readonly messageId: string;
49
+ /** The partner's reference for the pet the thread is about. */
50
+ readonly petRef: string;
51
+ readonly role: VetMessageRole;
52
+ /** The words. May be empty when the message carries only attachments. */
53
+ readonly content: string;
54
+ readonly createdAt: string;
55
+ /** The clinician's CURRENT display name on a vet row; null on the member's and Everfur's rows, or when gone. */
56
+ readonly senderName: string | null;
57
+ readonly senderSpecialty: string | null;
58
+ /** How many files the message carries. The partner plane serves the count, never the files. */
59
+ readonly attachmentCount: number;
60
+ }
61
+ /** One pet's conversation with the vet, for the member's Messages list. */
62
+ interface VetThread {
63
+ readonly petRef: string;
64
+ readonly lastMessageAt: string;
65
+ /** Vet messages newer than the member's read receipt. */
66
+ readonly unreadCount: number;
67
+ /** False only while Everfur requires a vet to write first and none has: a send then answers 409. */
68
+ readonly ownerCanStart: boolean;
69
+ /** The newest message, for the row's preview line. */
70
+ readonly lastMessage: VetMessage | null;
71
+ }
72
+ /** One medication on an approved summary, as the vet wrote it. Every field but the drug may be absent. */
73
+ interface VisitSummaryMedication {
74
+ readonly drug: string;
75
+ readonly strength: string | null;
76
+ readonly form: string | null;
77
+ /** The directions. */
78
+ readonly sig: string | null;
79
+ readonly quantity: string | null;
80
+ readonly refills: number | null;
81
+ }
82
+ /** The vet's APPROVED summary of one of the member's visits (`OwnerSummaryResponse`). */
83
+ interface VisitSummary {
84
+ readonly consultId: string;
85
+ readonly findingsText: string;
86
+ readonly nextStepsText: string;
87
+ readonly medications: readonly VisitSummaryMedication[];
88
+ readonly productRefs: readonly string[];
89
+ /** The list the member works through, in the vet's words. */
90
+ readonly actionItems: readonly string[];
91
+ readonly approvedAt: string;
92
+ /** The signing clinician's name and credentials line; null only if that registry row was later removed. */
93
+ readonly approvedByName: string | null;
94
+ readonly credentialsText: string | null;
95
+ }
96
+ /** How far back a page reads and how much of it. */
97
+ interface VetMessagePage {
98
+ /** The oldest `createdAt` already shown. Absent, the newest page. */
99
+ readonly before?: string | undefined;
100
+ /** 1 to 100; clamped to the route's bounds. Absent, 50. */
101
+ readonly limit?: number | undefined;
102
+ }
103
+ /**
104
+ * Did the messages plane answer its DARK 404? On the thread list that is the switch being off for this tenant,
105
+ * which a screen reads as the feature being absent (it draws nothing). On a thread, a send or a summary the same
106
+ * status also means "not this member's", "no visit behind the thread" or "not approved yet": the route is opaque
107
+ * on purpose, so only the list read may decide whether the feature exists.
108
+ */
109
+ declare function isVetMessagesDark(error: EverfurError): boolean;
110
+ /** Did a send answer 409: Everfur requires a vet to write first about this pet, and none has? */
111
+ declare function isVetThreadVetFirst(error: EverfurError): boolean;
112
+
10
113
  /** The partner booking surface, relative to the API base. One prefix, so a dark tenant is dark for all of it. */
11
114
  declare const TELEVET_BOOKING_BASE = "/widget/v1/televet";
12
115
  /**
@@ -87,6 +190,30 @@ interface TelevetBookingController {
87
190
  joinConsult?(consultId: string): Promise<EverfurResult<VetCallCredential>>;
88
191
  /** Cancel a visit, answering what it cost. `reason` is the member's own words, 1 to 240 characters. */
89
192
  cancelConsult?(consultId: string, reason: string): Promise<EverfurResult<TelevetCancelReceipt>>;
193
+ /**
194
+ * A presigned POST for one attachment the member adds to the booking; its `s3_key` goes in `media_refs`. A dark
195
+ * route settles its 404 as an error, and a controller without this method is read the same way: nothing the
196
+ * member picked can be sent, and the flow says so.
197
+ */
198
+ initiateAttachment?(file: TelevetAttachmentMeta, signal?: AbortSignal): Promise<EverfurResult<TelevetAttachmentPolicy>>;
199
+ /**
200
+ * Is what the member described an emergency? Asked after Describe, before a vet is chosen.
201
+ *
202
+ * NEVER AN ERROR: every failure (the dark 404, a 403, a spent budget, a fault, an unreadable body) answers
203
+ * null, "no verdict", which the flow reads as "go on". The booking classifies the same words again at Confirm,
204
+ * so a failed early read costs the member the screen's early position, never the check.
205
+ */
206
+ triage?(reasonText: string, signal?: AbortSignal): Promise<EverfurResult<TelevetTriageVerdict | null>>;
207
+ /** The member's conversations with the vet, one per pet. A dark route settles its 404 as an error. */
208
+ listVetThreads?(signal?: AbortSignal): Promise<EverfurResult<readonly VetThread[]>>;
209
+ /** One page of one pet's thread, newest first. */
210
+ listVetMessages?(petRef: string, page?: VetMessagePage, signal?: AbortSignal): Promise<EverfurResult<readonly VetMessage[]>>;
211
+ /** Write to the vet about one pet. ONE attempt: every send alerts a licensed clinician. */
212
+ sendVetMessage?(petRef: string, content: string): Promise<EverfurResult<VetMessage>>;
213
+ /** Advance the member's read receipt for one pet to the instant they rendered it. */
214
+ markVetThreadRead?(petRef: string, readAt: string): Promise<EverfurResult<void>>;
215
+ /** The vet's approved summary of one visit. A 404 is "not approved yet, not this member's, or dark". */
216
+ visitSummary?(consultId: string, signal?: AbortSignal): Promise<EverfurResult<VisitSummary>>;
90
217
  }
91
218
  interface TelevetBookingControllerDeps {
92
219
  readonly auth: AuthContext;
@@ -111,19 +238,6 @@ interface TelevetBookingControllerDeps {
111
238
  declare function validateBookingBody(body: TelevetBookingBody): string | null;
112
239
  declare function createTelevetBookingController(deps: TelevetBookingControllerDeps): Required<TelevetBookingController>;
113
240
 
114
- /**
115
- * The classifier's answer about one piece of free text.
116
- *
117
- * TWO FIELDS, AND `fallback` IS NOT A FAILURE. The consumer treats "the classifier could not give a verdict"
118
- * as an emergency for this purpose, because the booking route refuses it the same way
119
- * (useEarlyTriage.ts:70: `verdict.isEmergency || verdict.fallback`). A read that never completed is a
120
- * different thing and is handled by the absence of a verdict, not by a field on one.
121
- */
122
- interface TelevetTriageVerdict {
123
- readonly isEmergency: boolean;
124
- /** The classifier ran and declined to decide. Refused like an emergency, by the booking route and here. */
125
- readonly fallback: boolean;
126
- }
127
241
  /**
128
242
  * The seam the triage read arrives through.
129
243
  *
@@ -156,6 +270,82 @@ interface TelevetEarlyTriage {
156
270
  */
157
271
  declare function useEarlyTriage(read: TelevetTriageRead | null | undefined): TelevetEarlyTriage;
158
272
 
273
+ /** Whether the vet thread feature exists for this tenant. See the header. */
274
+ type VetMessagesAvailability = 'pending' | 'dark' | 'lit';
275
+ interface VetThreadsState {
276
+ readonly availability: VetMessagesAvailability;
277
+ /** The member's threads, newest first as served. Empty until the list answers. */
278
+ readonly threads: readonly VetThread[];
279
+ readonly isPending: boolean;
280
+ readonly error: EverfurError | null;
281
+ refetch(): void;
282
+ }
283
+ /**
284
+ * The member's conversations with the vet, and whether the feature exists. `revision` is part of the key, so a
285
+ * screen that has just sent a message or read a thread asks again by bumping it.
286
+ */
287
+ declare function useVetThreads(controller: TelevetBookingController | null, revision?: number): VetThreadsState;
288
+ /** Why the last send did not land: the vet must write first (409), or anything else. */
289
+ type VetSendFailure = 'vetWritesFirst' | 'notSent';
290
+ interface VetThreadState {
291
+ readonly status: 'loading' | 'error' | 'ready';
292
+ /** Oldest first, as the thread is read. */
293
+ readonly messages: readonly VetMessage[];
294
+ /** True while the last page read was a full one: there may be older messages to read. */
295
+ readonly hasOlder: boolean;
296
+ readonly loadingOlder: boolean;
297
+ /** Read the page before the oldest message on screen. A no-op while one is in flight or none is left. */
298
+ loadOlder(): void;
299
+ /** False when the member cannot write here: no send on the controller, or Everfur requires the vet first. */
300
+ readonly canWrite: boolean;
301
+ readonly sending: boolean;
302
+ readonly sendFailure: VetSendFailure | null;
303
+ /** How many sends have landed since the thread opened, so a screen can announce each one. */
304
+ readonly sentCount: number;
305
+ /** Send the member's words. Resolves true when the server took them; the screen clears its field only then. */
306
+ send(content: string): Promise<boolean>;
307
+ retry(): void;
308
+ }
309
+ interface UseVetThreadOptions {
310
+ /** What the thread list said (`VetThread.ownerCanStart`). Absent, the route's own default: the member may start. */
311
+ readonly ownerCanStart?: boolean | undefined;
312
+ /** Injected by tests: the instant the read receipt reports. */
313
+ readonly now?: (() => number) | undefined;
314
+ }
315
+ /** One pet's thread with the vet. `petRef` is the partner's own reference for the pet. */
316
+ declare function useVetThread(controller: TelevetBookingController | null, petRef: string, options?: UseVetThreadOptions): VetThreadState;
317
+ interface VisitSummaryState {
318
+ /**
319
+ * `absent` the controller has no summary read (the feature is not wired), `loading`, `ready`, `pending` the
320
+ * route answered 404 (the vet has not approved a summary yet; the route says the same for a dark tenant, which
321
+ * is why a surface opens this only from a visit while the thread list is `lit`), `error` anything else.
322
+ */
323
+ readonly status: 'absent' | 'loading' | 'ready' | 'pending' | 'error';
324
+ readonly summary: VisitSummary | null;
325
+ retry(): void;
326
+ }
327
+ /** The vet's approved summary of one of the member's visits. */
328
+ declare function useVisitSummary(controller: TelevetBookingController | null, consultId: string): VisitSummaryState;
329
+ /** What opening one thread needs: the pet, and what the screen that opened it already knows. */
330
+ interface TelevetVetThreadTarget {
331
+ /** The partner's reference for the pet. */
332
+ readonly petRef: string;
333
+ readonly petName: string | null;
334
+ /** The vet's served name, when known. The thread reads it from its own rows otherwise. */
335
+ readonly vetName: string | null;
336
+ /** What the thread list said; undefined when the pet has no thread yet. */
337
+ readonly ownerCanStart?: boolean | undefined;
338
+ }
339
+ /**
340
+ * The partner's pet reference for a consult's pet. A consult names its pet by the platform id or the partner's
341
+ * reference, so the roster is asked for both (the same match `nameOf` makes). Null when the roster has no such
342
+ * pet, and then no thread can be addressed: the thread routes take the partner's reference only.
343
+ */
344
+ declare function vetThreadPetRef(pets: readonly {
345
+ readonly petRef: string;
346
+ readonly petId: string | null;
347
+ }[], petId: string | null): string | null;
348
+
159
349
  /**
160
350
  * The server's own demand bucket. A CLOSED SET, and callers may not substitute free text.
161
351
  *
@@ -273,11 +463,10 @@ declare function televetMediaShortfallLines(shortfall: TelevetMediaShortfall): r
273
463
  /**
274
464
  * The shortfall THIS SURFACE actually has: every pick the owner made, reported as not sent.
275
465
  *
276
- * WHY THIS FUNCTION EXISTS AT ALL, and why it is not a stub for a future upload. The consumer apps derive
277
- * their shortfall from an upload RESULT. The SDK has no upload: `media_refs` leaves as `[]` whatever the
278
- * owner picked, and that is a decision with a written reason (no confirmed ref format, no read path, no
279
- * attachment purpose on the partner plane), not a gap about to close. So the honest count is knowable
280
- * without a network call: it is the length of the tray.
466
+ * WHY THIS FUNCTION EXISTS AT ALL. The consumer apps derive their shortfall from an upload RESULT, and so
467
+ * does the SDK when the televet presign is served. When it answers its dark 404 (or a host's controller has no
468
+ * presign), `media_refs` leaves as `[]` whatever the owner picked, so the honest count is knowable without an
469
+ * upload: it is the length of the tray.
281
470
  *
282
471
  * `failed`, NOT A REFUSAL BUCKET. The picks passed every local rule - the row accepted them, capped them at
283
472
  * `MEDIA_REFS_MAX` and showed them as thumbnails. Nothing about their size, type or readability is why they
@@ -303,7 +492,7 @@ declare function mediaShortfallFromUnsentPicks(pickCount: number): TelevetMediaS
303
492
  */
304
493
  declare function withUnsentPicks(shortfall: TelevetMediaShortfall, pickCount: number): TelevetMediaShortfall;
305
494
 
306
- type TelevetBookingStep = 'pet' | 'issues' | 'clinician' | 'time' | 'reason' | 'review' | 'booked';
495
+ type TelevetBookingStep = 'pet' | 'where' | 'issues' | 'reason' | 'emergency' | 'clinician' | 'time' | 'review' | 'booked';
307
496
  /**
308
497
  * Ordered for the progress rail. `booked` is terminal and counts toward nothing: the flow is over, and
309
498
  * including it would show a rail at 6/7 on a screen with no next step.
@@ -331,7 +520,10 @@ declare const emptyTelevetDraft: TelevetBookingDraft;
331
520
  interface TelevetBookingContext {
332
521
  /** Skips the picker for a single-pet household. */
333
522
  readonly ownedPetCount: number;
334
- /** Shows the issues step. The web flow sets it, mirroring the consumer web funnel; absent, it is skipped. */
523
+ /**
524
+ * Shows the issues step. Both prebuilt flows set it (both artifacts ask it); absent, it is skipped, which is
525
+ * how a host that drives the reducer itself keeps a flow without it.
526
+ */
335
527
  readonly withIssues?: boolean;
336
528
  }
337
529
  interface TelevetBookingState {
@@ -367,8 +559,8 @@ type TelevetBookingAction = {
367
559
  * Whether a step is skipped for STRUCTURAL reasons rather than user choice.
368
560
  *
369
561
  * NO DRAFT PARAMETER. The consumer's version takes one because an earlier shape skipped a `state` step once
370
- * the draft held a code; that step is gone, so a parameter nothing reads would only invite a future skip rule
371
- * that depends on draft contents without the attestation that made the old one safe.
562
+ * the draft held a code. The `where` step here is never skipped, so a parameter nothing reads would only
563
+ * invite a future skip rule that depends on draft contents without the attestation that made the old one safe.
372
564
  *
373
565
  * A skipped step must still have its value SET. The worst defect a flow of this shape can carry is skipping
374
566
  * the pet picker for a one-pet household and never writing `petId`, which dead-ends the majority case; the
@@ -468,6 +660,75 @@ type TelevetBookingFailure = 'taken' | 'expired' | 'failed' | 'not_entitled'
468
660
  /** The partner booking surface is dark here. No retry can fix it, so the flow says so and offers its exit. */
469
661
  | 'unavailable' | null;
470
662
 
663
+ declare const VET_MESSAGES_COPY: Readonly<{
664
+ /** ARTIFACT (MOBILE `vet`, `vet-upcoming`; WEB `video`): the card's title. */
665
+ messagesTitle: "Messages";
666
+ /** ARTIFACT (MOBILE `vet`, `span.pill--new`): an unread thread. */
667
+ newPillNative: "New";
668
+ /** ARTIFACT (WEB `video`, `span.pill.v-new`): an unread thread. */
669
+ newPillWeb: "New reply";
670
+ /** ARTIFACT (MOBILE `vet-upcoming`; WEB `video`): "You: Booked for Monday. Thank you." `{text}` is DATA. */
671
+ previewOwnerTemplate: "You: {text}";
672
+ /** ARTIFACT (WEB `video`): "Dr. Ellen Russell: Visit notes and Evie’s plan". `{vet}` and `{text}` are DATA. */
673
+ previewVetTemplateWeb: "{vet}: {text}";
674
+ /** ARTIFACT (MOBILE `vet-thread`, `p.screen-meta`): "With Dr. Ellen Russell, DVM". `{vet}` is DATA. */
675
+ threadMetaTemplateNative: "With {vet}";
676
+ /** ARTIFACT (MOBILE `vet-thread`, `ol.chat aria-label`): the thread's name. */
677
+ threadLogTemplate: "Messages with {vet}";
678
+ /** ARTIFACT (MOBILE `vet-thread`, the composer's visually hidden label): "Message Dr. Ellen". */
679
+ composerLabelTemplateNative: "Message {vet}";
680
+ /** ARTIFACT (WEB `vetthread`, `label.sr`). */
681
+ composerLabelWeb: "Message";
682
+ /** ARTIFACT (MOBILE `vet-thread` and WEB `vetthread`, the placeholder): "Message Dr. Ellen…". */
683
+ composerPlaceholderTemplate: "Message {vet}…";
684
+ /** ARTIFACT (MOBILE `vet-thread` and WEB `vetthread`, the send button's `aria-label`). */
685
+ send: "Send";
686
+ /**
687
+ * ARTIFACT (MOBILE `vet-thread`, `p.composer__note`): "Dr. Ellen usually replies within a day. Emergency? Call a
688
+ * vet." Drawn under the composer on BOTH hosts (see the web note under WHAT IS NOT HERE).
689
+ */
690
+ composerNoteTemplate: "{vet} usually replies within a day. Emergency? Call a vet.";
691
+ /** ARTIFACT (WEB `vetthread`, the send's announcement): what the status region says once a message is sent. */
692
+ sent: "Sent";
693
+ /** ARTIFACT (WEB `vetthread`, the head's button): a way to book from the thread. */
694
+ bookVisitWeb: "Book a visit";
695
+ /** chat/copy.ts `CHAT_COPY.empty`, reused: a thread with nothing in it yet. */
696
+ empty: "No messages yet";
697
+ /** chat/copy.ts `CHAT_COPY.loading`, reused: the busy region's name while a thread or a summary loads. */
698
+ loading: "Loading";
699
+ /** bookingCopy.ts `loadFailedTitle` and visitsCopyWeb.ts `retry`, reused: a thread or a summary that failed. */
700
+ loadFailed: "Could not load";
701
+ retry: "Try again";
702
+ /** clinicBatchCopy.ts `notSent`, reused: a send that did not land. The member's words stay in the composer. */
703
+ notSent: "Not sent";
704
+ /** Owner-approved 2026-10-01: the send answered 409, Everfur requires the vet to write first. */
705
+ vetWritesFirst: "Your vet will write first. You can reply once they do.";
706
+ /** Owner-approved 2026-10-01: a message that carries files the partner plane does not serve. `{n}` is DATA. */
707
+ attachmentsTemplate: "{n} attached";
708
+ /** ARTIFACT (MOBILE `vet-visit-waiting`, `a.card__link`; WEB `waiting`): "Running late? Message Dr. Ellen". */
709
+ runningLateTemplate: "Running late? Message {vet}";
710
+ /** ARTIFACT (MOBILE `vet-visit-summary`; WEB `summary`): "What Dr. Ellen saw". `{vet}` is DATA. */
711
+ sawTitleTemplate: "What {vet} saw";
712
+ /** ARTIFACT (MOBILE `vet-visit-summary`; WEB `summary`, `span.label`). */
713
+ summaryLabel: "Summary";
714
+ /** ARTIFACT (MOBILE `vet-visit-summary`; WEB `summary`, the pill): "From Dr. Ellen". */
715
+ fromVetTemplate: "From {vet}";
716
+ /** ARTIFACT (MOBILE `vet-visit-summary`; WEB `summary`): "Evie’s plan". `{pet}` is DATA. */
717
+ planTitleTemplate: "{pet}’s plan";
718
+ /** ARTIFACT (MOBILE `vet-visit-summary`; WEB `summary`, the plan's pill). */
719
+ wordForWord: "Word for word";
720
+ /** ARTIFACT (MOBILE `vet-visit-summary`; WEB `summary`): the card over what the visit produced. */
721
+ fromThisVisitTitle: "From this visit";
722
+ /** ARTIFACT (MOBILE `vet-visit-summary`; WEB `summary`, the vet card's button): "Message Dr. Ellen". */
723
+ messageVetTemplate: "Message {vet}";
724
+ /** ARTIFACT (MOBILE `vet-visit-summary`; WEB `summary`). */
725
+ bookFollowUp: "Book a follow-up";
726
+ /** ARTIFACT (MOBILE `vet-visit-summary`; WEB `summary`, the footnote). `{vet}` is DATA. */
727
+ summaryFootnoteTemplate: "A summary of your video visit, written by {vet}. In an emergency, go to the nearest emergency animal hospital.";
728
+ /** visitsCopyWeb.ts `televetVisitStatusWeb('awaiting_summary')`, reused: a summary the vet has not approved yet. */
729
+ summaryPending: "Summary on its way";
730
+ }>;
731
+
471
732
  /** How early the join arms, in minutes before `scheduled_at`. Both consumer apps: 15. */
472
733
  declare const TELEVET_JOIN_OPENS_MINUTES_BEFORE = 15;
473
734
  /** How late the join stays armed, in minutes after `scheduled_at`: 10 minute consult plus a 4 hour grace. */
@@ -528,6 +789,27 @@ declare function splitTelevetVisits(consults: readonly TelevetConsult[], nowMs:
528
789
  */
529
790
  declare function canManageTelevetVisit(status: ConsultStatus): boolean;
530
791
 
792
+ /** The platform-fixed consult length. */
793
+ declare const CONSULT_MINUTES = 10;
794
+ /**
795
+ * "9:20 PM - 9:30 PM EDT", the visit's bracket, zone-qualified.
796
+ *
797
+ * THE END TIME IS DERIVED, not served: a consult response carries `scheduled_at` only, and the platform fixes
798
+ * the consult at `CONSULT_MINUTES`. Falls back to the bare bracket when the zone cannot be named.
799
+ */
800
+ declare function formatVisitRange(iso: string): string;
801
+ /** "August 20, 9:20 PM EDT". */
802
+ declare function formatWhen(iso: string): string;
803
+ /**
804
+ * "Wed, August 20, 9:20 PM EDT". The booking confirmation only.
805
+ *
806
+ * The weekday is computed from the SAME instant in the SAME zone as the clock beside it, so the two cannot
807
+ * disagree.
808
+ */
809
+ declare function formatWhenWithDay(iso: string): string;
810
+ /** Which of the artifacts' three slot groups a time falls in: before noon, noon to five, five and after. */
811
+ type TelevetDayPeriod = 'morning' | 'afternoon' | 'evening';
812
+
531
813
  /** One read, in the shape the ported screens branch on. */
532
814
  interface TelevetRead<T> {
533
815
  /** False when the question cannot be asked yet. A disabled read is never pending and never errors. */
@@ -678,25 +960,6 @@ type TelevetBookingRefusal =
678
960
  };
679
961
  declare function televetBookingRefusal(error: EverfurError): TelevetBookingRefusal;
680
962
 
681
- /** The platform-fixed consult length. */
682
- declare const CONSULT_MINUTES = 10;
683
- /**
684
- * "9:20 PM - 9:30 PM EDT", the visit's bracket, zone-qualified.
685
- *
686
- * THE END TIME IS DERIVED, not served: a consult response carries `scheduled_at` only, and the platform fixes
687
- * the consult at `CONSULT_MINUTES`. Falls back to the bare bracket when the zone cannot be named.
688
- */
689
- declare function formatVisitRange(iso: string): string;
690
- /** "August 20, 9:20 PM EDT". */
691
- declare function formatWhen(iso: string): string;
692
- /**
693
- * "Wed, August 20, 9:20 PM EDT". The booking confirmation only.
694
- *
695
- * The weekday is computed from the SAME instant in the SAME zone as the clock beside it, so the two cannot
696
- * disagree.
697
- */
698
- declare function formatWhenWithDay(iso: string): string;
699
-
700
963
  declare const TELEVET_BOOKING_COPY: Readonly<{
701
964
  stateBlockedTitle: string;
702
965
  noCliniciansTitle: string;
@@ -704,12 +967,23 @@ declare const TELEVET_BOOKING_COPY: Readonly<{
704
967
  noCliniciansBody: string;
705
968
  noCliniciansRetryCta: string;
706
969
  noCliniciansRegionBody: string;
707
- /** The matched vet, not a roster. */
970
+ /** The matched vet, not a roster. Artifact `vet-book-vet` (mobile) and the web `vet` page, step 6: "Your vet". */
708
971
  yourVetTitle: string;
972
+ /**
973
+ * The vet card's licence pill, `vet-book-vet` ("Licensed in California"). `{state}` is DATA: the NAME of the
974
+ * state the owner picked, drawn only when the clinician's served `licensed_states` carries that state.
975
+ */
976
+ licensedPillTemplate: string;
709
977
  /** Suffix on the star line: "5.0 · 774 reviews". */
710
978
  reviewsLabel: string;
711
979
  rescheduleFromTemplate: string;
712
980
  rescheduleFailed: string;
981
+ rescheduleStepLabel: string;
982
+ rescheduleTitleTemplate: string;
983
+ rescheduleNowLabel: string;
984
+ rescheduleMoveTemplate: string;
985
+ rescheduleMoving: string;
986
+ rescheduleKeepLabel: string;
713
987
  keepExistingCta: string;
714
988
  bookingPausedTitle: string;
715
989
  slotsErrorTitle: string;
@@ -766,10 +1040,9 @@ declare const TELEVET_BOOKING_COPY: Readonly<{
766
1040
  * rather than a pluralisation rule, because that is what both consumer apps do and a rule invented here
767
1041
  * would produce a third grammar for the same sentence.
768
1042
  *
769
- * WHY THIS DECK CARRIES `dropped` AT ALL, given the SDK never uploads. See `mediaShortfall.ts`: the SDK's
770
- * booking sends `media_refs: []` unconditionally, so on this surface EVERY attachment an owner picked is
771
- * dropped, and `dropped` is the sentence for exactly that. It is the most load-bearing line here, not a
772
- * spare one.
1043
+ * `dropped` IS THE LOAD-BEARING LINE HERE. While the televet presign is dark (EFBackend #1806, default OFF)
1044
+ * every attachment an owner picked is dropped, and `dropped` is the sentence for exactly that; served, it
1045
+ * counts the picks whose upload failed or whose key the booking did not keep. See `mediaShortfall.ts`.
773
1046
  */
774
1047
  media: Readonly<{
775
1048
  droppedTemplate: string;
@@ -782,12 +1055,104 @@ declare const TELEVET_BOOKING_COPY: Readonly<{
782
1055
  refusedUnreadablePluralTemplate: string;
783
1056
  }>;
784
1057
  navTitle: string;
1058
+ /** The SDK's own words for an unnamed pet, as in "Have your pet nearby" and "What is going on with your pet?". */
1059
+ petFallback: "your pet";
1060
+ /** `vet-book-where` title, both artifacts. */
1061
+ whereTitleTemplate: string;
1062
+ /**
1063
+ * `vet-book-where` lead, both artifacts; the web page fills the pronoun from the pet (`who-pron`). `{pronoun}`
1064
+ * is DATA. The partner roster carries no sex for a pet, so the call site fills `wherePronounFallback`.
1065
+ */
1066
+ whereLeadTemplate: string;
1067
+ /** The pronoun the lead takes for a pet whose sex the roster does not carry. */
1068
+ wherePronounFallback: "they’ll";
1069
+ /** `vet-book-where` form name ("Where Evie will be") and the hidden legend ("State"). */
1070
+ whereFormLabelTemplate: string;
1071
+ whereLegend: string;
1072
+ /**
1073
+ * The meta line under a state the SERVED policy says prescribes (`prescriptions_available`). Never drawn for a
1074
+ * state the policy has not answered for: it is a statement about what that jurisdiction permits.
1075
+ */
1076
+ wherePrescribeMetaTemplate: string;
1077
+ /** The meta line under a state whose served policy offers a wellness visit and no prescribing. */
1078
+ whereWellnessMeta: string;
1079
+ whereAnotherState: string;
1080
+ whereWhichState: string;
1081
+ /**
1082
+ * The licensure line, `vet-book-where`. `{vet}` is the matched clinician's served name and `{state}` the picked
1083
+ * state's name; drawn ONLY when that clinician's served `licensed_states` says they may prescribe there AND the
1084
+ * state policy says prescriptions are available there.
1085
+ */
1086
+ whereLicensedTemplate: string;
1087
+ /** `vet-book-where`, mobile only: why the question comes back on every booking. */
1088
+ whereAskEveryTime: string;
1089
+ /** `vet-book-issues` title and lead, both artifacts. */
1090
+ issuesTitleTemplate: string;
1091
+ issuesHint: string;
1092
+ /** `vet-book-issues` form name and hidden legend. */
1093
+ issuesFormLabel: string;
1094
+ issuesLegend: string;
1095
+ /** The web page's refusal when nothing is picked. */
1096
+ issuesPickOne: string;
1097
+ /** The last issue chip, both artifacts. */
1098
+ otherIssue: string;
1099
+ /** `vet-book-describe` title once the matched vet is known. `{vet}` is the clinician's served name. */
1100
+ describeHeadingTemplate: string;
1101
+ /** `vet-book-describe` field label, both artifacts. */
1102
+ describeFieldLabel: string;
1103
+ /**
1104
+ * THE EMERGENCY CHECK, `vet-book-emergency` (both artifacts): seven signs, then a yes or no. The signs are
1105
+ * clinical triage copy and are the artifact's words, unedited.
1106
+ */
1107
+ emergencyCheck: Readonly<{
1108
+ titleTemplate: string;
1109
+ lead: string;
1110
+ signs: readonly string[];
1111
+ formLabel: string;
1112
+ legend: string;
1113
+ noneCta: string;
1114
+ someCta: string;
1115
+ }>;
1116
+ /** `vet-book-time` title, both artifacts. */
1117
+ timeHeading: string;
1118
+ /** The slot groups and the hidden legend over them (`Time on Monday, September 28`); `{day}` is DATA. */
1119
+ timeMorning: string;
1120
+ timeAfternoon: string;
1121
+ timeEvening: string;
1122
+ timeLegendTemplate: string;
1123
+ /** The hidden legend over the day strip, `vet-book-time`: "Day". */
1124
+ dayLegend: string;
1125
+ /** `vet-book-review` title, both artifacts. */
1126
+ reviewHeading: string;
1127
+ /** The review's Where row, and the Change link on its When row. */
1128
+ summaryWhere: string;
1129
+ changeCta: string;
1130
+ /**
1131
+ * The jurisdiction attestation, `vet-book-review`: "Evie and I will be in California during the visit."
1132
+ * `{pet}` and `{state}` (the state's NAME) are DATA. Without a pet name the older `stateAttestTemplate` is used.
1133
+ */
1134
+ whereAttestTemplate: string;
1135
+ /** The web page's refusal when Book the visit is pressed with a box unticked. */
1136
+ attestBoth: string;
1137
+ /** The step label over the confirmation, mobile `vet-book-booked`. */
1138
+ bookedStepLabel: string;
1139
+ /** `vet-book-booked` title. `{vet}` is the booked clinician's served name; without one `bookedTitle` stays. */
1140
+ bookedTitleTemplate: string;
1141
+ /** `vet-book-booked` lead: "Monday, September 28 at 6:30 PM PT, for Evie." `{when}` and `{pet}` are DATA. */
1142
+ bookedLeadTemplate: string;
1143
+ /**
1144
+ * THE VET FOOTNOTE, the owner's per-surface one-liner of 2026-09-30 in place of the fixed disclaimer band.
1145
+ * Mobile `vet` and `vet-upcoming`, and the web `video` page, all draw it under the vet home.
1146
+ */
1147
+ footnote: string;
785
1148
  /** The chrome must not say "Book a visit" while the user is moving one they already have. */
786
1149
  rescheduleNavTitle: string;
787
1150
  close: string;
788
1151
  continueCta: string;
789
1152
  petSelectTitle: string;
790
1153
  addPetCta: string;
1154
+ /** The persistent row under the pet list, both artifacts' `vet-book-who`: "Add another pet". */
1155
+ addAnotherPetCta: string;
791
1156
  locationUnknownTitle: string;
792
1157
  locationUnknownBody: string;
793
1158
  locationUnknownCta: string;
@@ -799,17 +1164,28 @@ declare const TELEVET_BOOKING_COPY: Readonly<{
799
1164
  locationUnavailableBody: string;
800
1165
  stateAttestTemplate: string;
801
1166
  describeHeading: string;
1167
+ /** `vet-book-describe` lead, both artifacts. */
802
1168
  describeHelpLong: string;
1169
+ /** `vet-book-describe` attachment row title (MOBILE `vet-book-describe` and web `vet`, 2026-09-30). */
803
1170
  addPhotoCta: string;
1171
+ /**
1172
+ * `vet-book-describe` attachment row meta, verbatim (MOBILE `vet-book-describe`, 2026-09-26 round 7; web `vet`).
1173
+ * Drawn only once the televet presign has answered in this booking (EFBackend #1806), because "a close-up
1174
+ * helps" is true only when a photo can reach the vet; on a dark route it is not drawn.
1175
+ */
1176
+ addPhotoMeta: string;
804
1177
  removePhotoLabel: string;
805
1178
  summaryPet: string;
806
1179
  summaryVet: string;
807
1180
  summaryWhen: string;
808
1181
  summaryLength: string;
1182
+ /** `vet-book-review`'s row for what the visit is about: "About". */
809
1183
  summaryReason: string;
810
1184
  /** "10 minutes" as a DERIVED fact: `{n}` is filled from `CONSULT_MINUTES` so the two cannot drift. */
811
1185
  summaryLengthTemplate: string;
1186
+ /** `vet-book-review`'s button, and the web page's busy label on it. */
812
1187
  confirmCta: string;
1188
+ confirmBusy: string;
813
1189
  bookedTitle: string;
814
1190
  addToCalendarCta: string;
815
1191
  doneCta: string;
@@ -817,6 +1193,20 @@ declare const TELEVET_BOOKING_COPY: Readonly<{
817
1193
  booked: Readonly<{
818
1194
  remindPromise: string;
819
1195
  summaryPromise: string;
1196
+ /**
1197
+ * `vet-book-booked` step 02, the artifact's no-photo form. Drawn only when the owner shared the pet's records
1198
+ * with the vet, because "records go to the vet" is otherwise not true; `{pet}` and `{vet}` are DATA.
1199
+ */
1200
+ recordsPromiseTemplate: string;
1201
+ /**
1202
+ * `vet-book-booked` step 02, the artifact's photo form, verbatim (MOBILE `vet-book-booked`, 2026-09-26 round
1203
+ * 7). Drawn only when the records were shared AND exactly one photo went with the booking and the consult
1204
+ * kept it. The artifact draws no count variant, so two or more attachments, or one that is a video or a
1205
+ * document, keep `recordsPromiseTemplate`, which stays true. `{pet}` and `{vet}` are DATA.
1206
+ */
1207
+ recordsPhotoPromiseTemplate: string;
1208
+ /** The confirmation's list name, `vet-book-booked`. */
1209
+ stepsLabel: string;
820
1210
  joinPromise: string;
821
1211
  backToPet: string;
822
1212
  calendarAdded: string;
@@ -853,13 +1243,24 @@ declare const TELEVET_BOOKING_COPY: Readonly<{
853
1243
  * `src/web/televet/booking/EmergencyExits.tsx`). No number is ever invented for this screen.
854
1244
  */
855
1245
  emergency: Readonly<{
1246
+ /** `vet-book-emergency`'s help panel title, both artifacts. */
856
1247
  bannerTitle: string;
1248
+ /** `vet-book-emergency`'s way on, both artifacts. */
857
1249
  keepBookingCta: string;
858
1250
  lede: string;
1251
+ /**
1252
+ * The first sentence of `lede` alone, for a panel that draws no exit row: "Call one of these first." must not
1253
+ * point at a list that is absent from the screen.
1254
+ */
1255
+ ledeWithoutExits: string;
1256
+ /** `vet-book-emergency`'s third row, both artifacts: "Call Evie’s regular vet". */
859
1257
  exitPrimaryVetTitle: string;
860
1258
  /** everfur-mobile copy.ts:734 `emergency.exitFindErTitle`, the consumer web's `findEmergencyVet` word for word. */
861
1259
  exitFindErTitle: string;
862
1260
  startCallHint: string;
1261
+ poisonControl: string;
1262
+ poisonControlDetail: string;
1263
+ poisonControlTel: "tel:+18884264435";
863
1264
  }>;
864
1265
  /** The calendar entry's own title, from the consumer's `visit` block. */
865
1266
  visit: Readonly<{
@@ -970,4 +1371,4 @@ type TelevetBookingCopy = typeof TELEVET_BOOKING_COPY;
970
1371
  */
971
1372
  declare function isTelevetBookingCopyReady(): boolean;
972
1373
 
973
- export { televetConsultCall as $, type TelevetStateInterestReason as A, type TelevetTriageVerdict as B, CONSULT_MINUTES as C, type TelevetWrite as D, attestation as E, canConfirm as F, canManageTelevetVisit as G, createTelevetBookingController as H, currentStep as I, emptyTelevetDraft as J, formatVisitRange as K, formatWhen as L, formatWhenWithDay as M, NO_MEDIA_SHORTFALL as N, hasPreviousStep as O, initialTelevetBookingState as P, isHoldExpired as Q, isMediaShortfallEmpty as R, isSkipped as S, type TelevetEmptyRosterCause as T, isTelevetBookingCopyReady as U, mediaShortfallFromUnsentPicks as V, splitTelevetVisits as W, televetBookingKey as X, televetBookingReducer as Y, televetBookingRefusal as Z, televetCancelCall as _, type TelevetStateInterestAction as a, televetEmptyRosterCause as a0, televetEmptyRosterView as a1, televetHoldCall as a2, televetJoinCall as a3, televetJoinOpensAtMs as a4, televetJoinReadiness as a5, televetMediaShortfallLines as a6, televetRescheduleCall as a7, useEarlyTriage as a8, useStateInterest as a9, useTelevetBookConsult as aa, useTelevetBookingAvailable as ab, useTelevetBookingController as ac, useTelevetBookingEntitlement as ad, useTelevetCancellationPolicy as ae, useTelevetClinicians as af, useTelevetHoldSlot as ag, useTelevetJoin as ah, useTelevetNextSlot as ai, useTelevetRescheduleConsult as aj, useTelevetSlots as ak, useTelevetStatePolicy as al, validateBookingBody as am, withUnsentPicks as an, type TelevetJoinBlock as ao, type TelevetJoinDecision as ap, televetJoinDecision as aq, type TelevetMediaShortfall as b, type TelevetBookingStep as c, type TelevetBookingController as d, type TelevetTriageRead as e, type TelevetStateInterestWrite as f, TELEVET_BOOKING_BASE as g, TELEVET_BOOKING_COPY as h, TELEVET_BOOKING_STEPS as i, TELEVET_CONSULT_PAGE_LIMIT as j, TELEVET_JOIN_CLOSES_MINUTES_AFTER as k, TELEVET_JOIN_OPENS_MINUTES_BEFORE as l, type TelevetBookingAction as m, type TelevetBookingContext as n, type TelevetBookingControllerDeps as o, type TelevetBookingCopy as p, type TelevetBookingDraft as q, type TelevetBookingFailure as r, type TelevetBookingRefusal as s, type TelevetBookingState as t, type TelevetEarlyTriage as u, type TelevetEmptyRosterView as v, type TelevetJoinReadiness as w, type TelevetJoinState as x, type TelevetMediaRefusal as y, type TelevetRead as z };
1374
+ export { canConfirm as $, type TelevetEmptyRosterView as A, type TelevetJoinReadiness as B, CONSULT_MINUTES as C, type TelevetJoinState as D, type TelevetMediaRefusal as E, type TelevetRead as F, type TelevetStateInterestReason as G, type TelevetWrite as H, VET_MESSAGE_CONTENT_MAX as I, VET_MESSAGE_PAGE_DEFAULT as J, VET_MESSAGE_PAGE_MAX as K, type VetMessage as L, type VetMessagePage as M, NO_MEDIA_SHORTFALL as N, type VetMessageRole as O, type VetMessagesAvailability as P, type VetSendFailure as Q, type VetThread as R, type VetThreadState as S, type TelevetEmptyRosterCause as T, type UseVetThreadOptions as U, VET_MESSAGES_COPY as V, type VetThreadsState as W, type VisitSummary as X, type VisitSummaryMedication as Y, type VisitSummaryState as Z, attestation as _, type TelevetStateInterestAction as a, canManageTelevetVisit as a0, createTelevetBookingController as a1, currentStep as a2, emptyTelevetDraft as a3, formatVisitRange as a4, formatWhen as a5, formatWhenWithDay as a6, hasPreviousStep as a7, initialTelevetBookingState as a8, isHoldExpired as a9, useTelevetBookingAvailable as aA, useTelevetBookingController as aB, useTelevetBookingEntitlement as aC, useTelevetCancellationPolicy as aD, useTelevetClinicians as aE, useTelevetHoldSlot as aF, useTelevetJoin as aG, useTelevetNextSlot as aH, useTelevetRescheduleConsult as aI, useTelevetSlots as aJ, useTelevetStatePolicy as aK, useVetThread as aL, useVetThreads as aM, useVisitSummary as aN, validateBookingBody as aO, vetThreadPetRef as aP, withUnsentPicks as aQ, type TelevetJoinBlock as aR, type TelevetJoinDecision as aS, televetJoinDecision as aT, isMediaShortfallEmpty as aa, isSkipped as ab, isTelevetBookingCopyReady as ac, isVetMessagesDark as ad, isVetThreadVetFirst as ae, mediaShortfallFromUnsentPicks as af, splitTelevetVisits as ag, televetBookingKey as ah, televetBookingReducer as ai, televetBookingRefusal as aj, televetCancelCall as ak, televetConsultCall as al, televetEmptyRosterCause as am, televetEmptyRosterView as an, televetHoldCall as ao, televetJoinCall as ap, televetJoinOpensAtMs as aq, televetJoinReadiness as ar, televetMediaShortfallLines as as, televetRescheduleCall as at, televetThreadMessagesCall as au, televetThreadReadCall as av, televetVisitSummaryCall as aw, useEarlyTriage as ax, useStateInterest as ay, useTelevetBookConsult as az, type TelevetMediaShortfall as b, type TelevetBookingStep as c, type TelevetBookingContext as d, type TelevetBookingController as e, type TelevetTriageRead as f, type TelevetStateInterestWrite as g, type TelevetVetThreadTarget as h, type TelevetDayPeriod as i, TELEVET_BOOKING_BASE as j, TELEVET_BOOKING_COPY as k, TELEVET_BOOKING_STEPS as l, TELEVET_CONSULT_PAGE_LIMIT as m, TELEVET_JOIN_CLOSES_MINUTES_AFTER as n, TELEVET_JOIN_OPENS_MINUTES_BEFORE as o, TELEVET_MESSAGE_THREADS_PATH as p, type TelevetAttachmentMeta as q, type TelevetAttachmentPolicy as r, type TelevetBookingAction as s, type TelevetBookingControllerDeps as t, type TelevetBookingCopy as u, type TelevetBookingDraft as v, type TelevetBookingFailure as w, type TelevetBookingRefusal as x, type TelevetBookingState as y, type TelevetEarlyTriage as z };