@everfur/sdk 0.15.1 → 0.16.1
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.
- package/CHANGELOG.md +138 -0
- package/README.md +3 -1
- package/chat/lite/package.json +8 -0
- package/dist/Chat.d-CzI2228d.d.ts +11 -0
- package/dist/Chat.d-D3ScVQ22.d.cts +11 -0
- package/dist/{DepthViews.d-PuBGdAYk.d.cts → DepthViews.d-6U4QqaW3.d.cts} +1 -1
- package/dist/{DepthViews.d--1daZblh.d.cts → DepthViews.d-BLx_ZTwa.d.cts} +1 -1
- package/dist/{DepthViews.d-CKTnEeUo.d.ts → DepthViews.d-Cwbel5o4.d.ts} +1 -1
- package/dist/{DepthViews.d-BuEWI6Ln.d.ts → DepthViews.d-DVIydPLt.d.ts} +1 -1
- package/dist/{RecordsPage.d-CBB8sfoY.d.ts → RecordsPage.d-Bwalb0wU.d.ts} +1 -1
- package/dist/{RecordsPage.d-Dq5gpQG0.d.cts → RecordsPage.d-Do7T8Fns.d.cts} +1 -1
- package/dist/animations/index.d.cts +5 -5
- package/dist/animations/index.d.ts +5 -5
- package/dist/{Chat.d-BlsnQwCQ.d.ts → appStateLifecycle.d-Bd-rNy6K.d.ts} +62 -144
- package/dist/{Chat.d-BO5iJsR2.d.cts → appStateLifecycle.d-_mh4CEAq.d.cts} +62 -144
- package/dist/attachmentTransport.d-Syrvv5zH.d.ts +41 -0
- package/dist/attachmentTransport.d-r1XCCdUB.d.cts +41 -0
- package/dist/{attachments.d-DFP9yvz9.d.ts → attachments.d-BiBGBE4o.d.ts} +24 -6
- package/dist/{attachments.d-C2nkIyDB.d.ts → attachments.d-CyB8hzDo.d.ts} +2 -2
- package/dist/{attachments.d-DRHsJkni.d.cts → attachments.d-GlO5UP7H.d.cts} +24 -6
- package/dist/{attachments.d-DRUC35Ti.d.cts → attachments.d-Y-qvSHVU.d.cts} +2 -2
- package/dist/{bookingCopy.d-bF_QknDC.d.cts → bookingCopy.d-BIaCiRuW.d.cts} +2 -2
- package/dist/{bookingCopy.d-CFL-1Be2.d.ts → bookingCopy.d-DgWvNKD5.d.ts} +2 -2
- package/dist/{casesRepository.d-C__BnffJ.d.ts → casesRepository.d-BW8DTYeN.d.ts} +1 -1
- package/dist/{casesRepository.d-BMOnT1fg.d.cts → casesRepository.d-_0AO2YrL.d.cts} +1 -1
- package/dist/chat/index.cjs +246 -231
- package/dist/chat/index.d.cts +16 -49
- package/dist/chat/index.d.ts +16 -49
- package/dist/chat/index.js +246 -231
- package/dist/chat/lite/index.cjs +430 -0
- package/dist/chat/lite/index.d.cts +35 -0
- package/dist/chat/lite/index.d.ts +35 -0
- package/dist/chat/lite/index.js +430 -0
- package/dist/client/index.cjs +4 -4
- package/dist/client/index.d.cts +6 -6
- package/dist/client/index.d.ts +6 -6
- package/dist/client/index.js +4 -4
- package/dist/{clinicBatch.d-D68RYvc3.d.ts → clinicBatch.d-BXwATY3-.d.ts} +2 -2
- package/dist/{clinicBatch.d-C5deJ4xY.d.cts → clinicBatch.d-BcuSaOkv.d.cts} +2 -2
- package/dist/{config.d-BQgrIDdu.d.cts → config.d-D1xcxALX.d.cts} +1 -1
- package/dist/{config.d-XSMThgVj.d.ts → config.d-jTVsAeky.d.ts} +1 -1
- package/dist/consent/index.d.cts +5 -5
- package/dist/consent/index.d.ts +5 -5
- package/dist/{context.d-Ba8YyJpk.d.cts → context.d-C3x-z665.d.cts} +5 -5
- package/dist/{context.d-xoh5vmxS.d.ts → context.d-goZeZO2I.d.ts} +5 -5
- package/dist/{copy.d-Cq-s-UUv.d.cts → copy.d-DPwFY4r5.d.cts} +2 -2
- package/dist/{copy.d-HV9fU5kh.d.ts → copy.d-yfJv7fl6.d.ts} +2 -2
- package/dist/core/index.cjs +10 -10
- package/dist/core/index.d.cts +13 -13
- package/dist/core/index.d.ts +13 -13
- package/dist/core/index.js +10 -10
- package/dist/{depth.d-D7kKiYl7.d.ts → depth.d-SJzknw_P.d.ts} +2 -2
- package/dist/{depth.d-DYnkz8Re.d.cts → depth.d-e_8_icip.d.cts} +2 -2
- package/dist/{entitlementRepository.d-DmnUZLl_.d.ts → entitlementRepository.d-BNgZhwoE.d.ts} +2 -2
- package/dist/{entitlementRepository.d-B_kEPLhz.d.cts → entitlementRepository.d-C_LdzINM.d.cts} +2 -2
- package/dist/{focus.d-BHm_QtQ9.d.cts → focus.d-CXpIkIuU.d.cts} +3 -3
- package/dist/{focus.d-CjL6Cj0m.d.ts → focus.d-DzIgOqNB.d.ts} +3 -3
- package/dist/health-plan/index.cjs +136 -133
- package/dist/health-plan/index.d.cts +77 -24
- package/dist/health-plan/index.d.ts +77 -24
- package/dist/health-plan/index.js +136 -133
- package/dist/{idempotency.d-BSRK8od4.d.cts → idempotency.d-0biUa_Vw.d.cts} +1 -1
- package/dist/{idempotency.d-CFc4CCc9.d.ts → idempotency.d-DcqIqmf9.d.ts} +1 -1
- package/dist/{identity.d-Be2Es9Td.d.ts → identity.d-BEJcHY-5.d.ts} +1 -1
- package/dist/{identity.d-HbwYQ4-z.d.cts → identity.d-COcNGuCJ.d.cts} +1 -1
- package/dist/index.cjs +245 -230
- package/dist/index.d.cts +15 -12
- package/dist/index.d.ts +15 -12
- package/dist/index.js +246 -231
- package/dist/{introEvents.d-Dr34KIaD.d.cts → introEvents.d-D8N9bbGO.d.cts} +1 -1
- package/dist/{introEvents.d-DflJ6J9H.d.ts → introEvents.d-GCdyQyUG.d.ts} +1 -1
- package/dist/notifications/index.d.cts +4 -4
- package/dist/notifications/index.d.ts +4 -4
- package/dist/{optInView.d-3mbj1mR6.d.ts → optInView.d-CY2IueSZ.d.ts} +2 -2
- package/dist/{optInView.d-D23o1gtT.d.cts → optInView.d-DVuuWDRw.d.cts} +2 -2
- package/dist/{parse.d-BERabxHw.d.ts → parse.d--ztmWIIP.d.ts} +1 -1
- package/dist/{parse.d-4lUXdmvY.d.cts → parse.d-B-WrkW2C.d.cts} +1 -1
- package/dist/{pets.d-CHU0UbXt.d.cts → pets.d-BSW0oEYx.d.cts} +1 -1
- package/dist/{pets.d-D_ayuqjp.d.ts → pets.d-DwsImaHU.d.ts} +1 -1
- package/dist/{petsRepository.d-Bwfe8yuR.d.cts → petsRepository.d-BQfWC3d4.d.cts} +1 -1
- package/dist/{petsRepository.d-DUaAWoTv.d.ts → petsRepository.d-BudLFHVe.d.ts} +1 -1
- package/dist/photo/index.cjs +2 -2
- package/dist/photo/index.js +2 -2
- package/dist/{ports.d-DzEJMVRs.d.ts → ports.d-B6kDPKF7.d.ts} +4 -4
- package/dist/{ports.d-ClbPRUtx.d.cts → ports.d-DzPbmiDT.d.cts} +4 -4
- package/dist/records/depth/index.cjs +10 -10
- package/dist/records/depth/index.d.cts +9 -9
- package/dist/records/depth/index.d.ts +9 -9
- package/dist/records/depth/index.js +10 -10
- package/dist/records/index.cjs +253 -211
- package/dist/records/index.d.cts +169 -73
- package/dist/records/index.d.ts +169 -73
- package/dist/records/index.js +254 -212
- package/dist/{requestFunnel.d-YabU6G-Z.d.ts → requestFunnel.d-BPsCHJWf.d.ts} +2 -2
- package/dist/{requestFunnel.d-JoqddYSx.d.cts → requestFunnel.d-BdpL7gwg.d.cts} +2 -2
- package/dist/{runtimeTypes.d-DQTBJAbk.d.ts → runtimeTypes.d-C_Pcxn-n.d.ts} +4 -4
- package/dist/{runtimeTypes.d-Cv38YuzP.d.cts → runtimeTypes.d-Cfq3IrZG.d.cts} +4 -4
- package/dist/{screenProps.d-C-AuHoyF.d.cts → screenProps.d-BJMn1kTR.d.cts} +2 -2
- package/dist/{screenProps.d-BuJLzFkN.d.ts → screenProps.d-DGrfO17l.d.ts} +2 -2
- package/dist/server/events/index.cjs +3 -3
- package/dist/server/events/index.d.cts +48 -6
- package/dist/server/events/index.d.ts +48 -6
- package/dist/server/events/index.js +3 -3
- package/dist/server/index.cjs +2 -2
- package/dist/server/index.d.cts +3 -3
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.js +2 -2
- package/dist/shop/index.cjs +16 -16
- package/dist/shop/index.d.cts +12 -3
- package/dist/shop/index.d.ts +12 -3
- package/dist/shop/index.js +16 -16
- package/dist/tabs/index.cjs +4 -4
- package/dist/tabs/index.d.cts +34 -15
- package/dist/tabs/index.d.ts +34 -15
- package/dist/tabs/index.js +5 -5
- package/dist/{tabsModel.d-BfIQg6yS.d.ts → tabsModel.d-B7QMug1u.d.cts} +1 -17
- package/dist/{tabsModel.d-BfIQg6yS.d.cts → tabsModel.d-B7QMug1u.d.ts} +1 -17
- package/dist/televet/booking/index.cjs +2 -2
- package/dist/televet/booking/index.d.cts +6 -6
- package/dist/televet/booking/index.d.ts +6 -6
- package/dist/televet/booking/index.js +2 -2
- package/dist/televet/call/index.cjs +1 -1
- package/dist/televet/call/index.js +1 -1
- package/dist/televet/index.cjs +4 -3
- package/dist/televet/index.d.cts +1 -0
- package/dist/televet/index.d.ts +1 -0
- package/dist/televet/index.js +5 -4
- package/dist/testing/index.d.cts +1 -1
- package/dist/testing/index.d.ts +1 -1
- package/dist/testing/rn/index.cjs +1 -1
- package/dist/testing/rn/index.d.cts +7 -7
- package/dist/testing/rn/index.d.ts +7 -7
- package/dist/testing/rn/index.js +1 -1
- package/dist/testing/web/index.d.cts +7 -7
- package/dist/testing/web/index.d.ts +7 -7
- package/dist/texting/index.cjs +21 -16
- package/dist/texting/index.d.cts +5 -5
- package/dist/texting/index.d.ts +5 -5
- package/dist/texting/index.js +22 -17
- package/dist/threadOptions.d-B0folrKm.d.cts +147 -0
- package/dist/{threadOptions.d-DBrmOwmb.d.cts → threadOptions.d-B8HTJa9A.d.cts} +6 -40
- package/dist/{threadOptions.d-8x_1evAr.d.ts → threadOptions.d-BnhE7T8Y.d.ts} +6 -40
- package/dist/threadOptions.d-DTsJFkL-.d.ts +147 -0
- package/dist/threadOptions.d-GPJPprkn.d.cts +55 -0
- package/dist/threadOptions.d-GPJPprkn.d.ts +55 -0
- package/dist/{timelineRows.d-B6lLC8Ud.d.cts → timelineRows.d-BTcUdNeI.d.cts} +1 -1
- package/dist/{timelineRows.d-Brlkti-G.d.ts → timelineRows.d-kmBms1W5.d.ts} +1 -1
- package/dist/{planSignals.d-Dha2CMDF.d.cts → useHealthPlanSubscription.d-B_cth_iF.d.cts} +81 -3
- package/dist/{planSignals.d-CON9gTvJ.d.ts → useHealthPlanSubscription.d-BzNaVl89.d.ts} +81 -3
- package/dist/{usePresentation.d-Bne14SlX.d.ts → usePresentation.d-B7Uf44Ax.d.ts} +40 -40
- package/dist/{usePresentation.d-BcdCIuEU.d.cts → usePresentation.d-BkAMOfb5.d.cts} +40 -40
- package/dist/{useRecordsDepth.d-Cd6J03o5.d.ts → useRecordsDepth.d-BHkZi0tM.d.ts} +1 -1
- package/dist/{useRecordsDepth.d-DAa169VY.d.cts → useRecordsDepth.d-BxHpKipf.d.cts} +1 -1
- package/dist/video/index.cjs +2 -2
- package/dist/video/index.js +2 -2
- package/dist/{view.d-DkGM8GNA.d.ts → view.d-2BYMRnWj.d.ts} +3 -3
- package/dist/{view.d-3d5_O7Xk.d.cts → view.d-CoDbnv0f.d.cts} +3 -3
- package/dist/web/consent/index.d.cts +5 -5
- package/dist/web/consent/index.d.ts +5 -5
- package/dist/web/health-plan/index.cjs +5 -5
- package/dist/web/health-plan/index.d.cts +15 -69
- package/dist/web/health-plan/index.d.ts +15 -69
- package/dist/web/health-plan/index.js +5 -5
- package/dist/web/index.cjs +8 -8
- package/dist/web/index.d.cts +26 -43
- package/dist/web/index.d.ts +26 -43
- package/dist/web/index.js +8 -8
- package/dist/web/intro/index.d.cts +6 -6
- package/dist/web/intro/index.d.ts +6 -6
- package/dist/web/notifications/index.d.cts +3 -3
- package/dist/web/notifications/index.d.ts +3 -3
- package/dist/web/records/depth/index.cjs +9 -9
- package/dist/web/records/depth/index.d.cts +9 -9
- package/dist/web/records/depth/index.d.ts +9 -9
- package/dist/web/records/depth/index.js +9 -9
- package/dist/web/records/index.cjs +12 -12
- package/dist/web/records/index.d.cts +11 -11
- package/dist/web/records/index.d.ts +11 -11
- package/dist/web/records/index.js +12 -12
- package/dist/web/records-sheet/index.cjs +17 -17
- package/dist/web/records-sheet/index.js +17 -17
- package/dist/web/shop/index.cjs +12 -12
- package/dist/web/shop/index.d.cts +3 -3
- package/dist/web/shop/index.d.ts +3 -3
- package/dist/web/shop/index.js +12 -12
- package/dist/web/televet/booking/index.cjs +2 -2
- package/dist/web/televet/booking/index.d.cts +6 -6
- package/dist/web/televet/booking/index.d.ts +6 -6
- package/dist/web/televet/booking/index.js +2 -2
- package/dist/web/televet/call/index.cjs +1 -1
- package/dist/web/televet/call/index.js +1 -1
- package/dist/web/texting/index.d.cts +5 -5
- package/dist/web/texting/index.d.ts +5 -5
- package/package.json +22 -27
|
@@ -1,10 +1,51 @@
|
|
|
1
1
|
/*! @everfur/sdk. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { n as HealthPlanPagePet, b as HealthPlanFocusDesign, H as HealthPlanPage, q as HealthPlan, j as HealthPlanPageRepository, P as HealthPlanRepository, i as HealthPlanSubscriptionRepository, S as HealthPlanSubscriptionQuote, g as HealthPlanSubscription, h as HealthPlanOneBoxOrder } from './focus.d-CXpIkIuU.cjs';
|
|
4
|
+
import { a as EverfurChatTopCard } from './threadOptions.d-GPJPprkn.cjs';
|
|
4
5
|
import { P as PetRef } from './ids.d-B2GAAifq.cjs';
|
|
5
|
-
import {
|
|
6
|
+
import { g as HealthPlanCart } from './usePresentation.d-BkAMOfb5.cjs';
|
|
6
7
|
import { E as EverfurError } from './EverfurError.d-8NHtlgzA.cjs';
|
|
7
8
|
import { L as LifecyclePort } from './LifecyclePort.d-Cr1p33a7.cjs';
|
|
9
|
+
import { E as EverfurResult } from './EverfurResult.d-BFH-3s6E.cjs';
|
|
10
|
+
|
|
11
|
+
/** The page's focus, as the copy functions receive it. */
|
|
12
|
+
type HealthPlanTopCardFocus = NonNullable<HealthPlanFocusDesign['focus']>;
|
|
13
|
+
/** Who the card is about: the page's pet and the possessive its words use ("her", "his", "Georgia's"), or null. */
|
|
14
|
+
interface HealthPlanTopCardPet {
|
|
15
|
+
readonly pet: HealthPlanPagePet;
|
|
16
|
+
readonly possessive: string | null;
|
|
17
|
+
}
|
|
18
|
+
/** The card's own words. Defaults: Raph's v3 design (`HEALTH_PLAN_TOP_CARD_COPY`). */
|
|
19
|
+
interface HealthPlanTopCardCopy {
|
|
20
|
+
/** The plan button ("See her Health Plan"); null draws none. */
|
|
21
|
+
readonly action: (who: HealthPlanTopCardPet) => string | null;
|
|
22
|
+
/** The question link ("What does it mean?"). */
|
|
23
|
+
readonly ask: string;
|
|
24
|
+
/** What the link sends to the chat: the risk line's lead, then the link's words. */
|
|
25
|
+
readonly askPrompt: (focus: HealthPlanTopCardFocus, ask: string) => string;
|
|
26
|
+
/** The close control's accessible name ("Close her focus"); null or blank names it with the chat's plain "Close". */
|
|
27
|
+
readonly close: (who: HealthPlanTopCardPet) => string | null;
|
|
28
|
+
}
|
|
29
|
+
declare const HEALTH_PLAN_TOP_CARD_COPY: HealthPlanTopCardCopy;
|
|
30
|
+
/** The pet facts the possessive reads: its name and sex (a plan page's pet, or the focus words' pet). */
|
|
31
|
+
interface HealthPlanPossessivePet {
|
|
32
|
+
readonly name?: string | null;
|
|
33
|
+
readonly sex?: string | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* "her" for a female, "his" for a male, "Georgia's" for a named pet of unknown sex, else null. The sex is read
|
|
37
|
+
* leniently (any case, surrounding spaces), so a host-shaped page that says "Female" still reads as her.
|
|
38
|
+
*/
|
|
39
|
+
declare function healthPlanPossessive(pet: HealthPlanPossessivePet): string | null;
|
|
40
|
+
interface HealthPlanTopCardOptions {
|
|
41
|
+
/** Opens the pet's Health Plan (your tab or screen). Absent, the card has no plan button. */
|
|
42
|
+
readonly onOpenPlan?: (() => void) | undefined;
|
|
43
|
+
readonly copy?: Partial<HealthPlanTopCardCopy>;
|
|
44
|
+
/** Draw the close icon your way. */
|
|
45
|
+
readonly renderIcon?: (icon: 'close') => ReactNode;
|
|
46
|
+
}
|
|
47
|
+
/** The top card for a page, or undefined when the page has no focus to show. Pure. */
|
|
48
|
+
declare function healthPlanTopCard(page: HealthPlanPage | null, options?: HealthPlanTopCardOptions): EverfurChatTopCard | undefined;
|
|
8
49
|
|
|
9
50
|
/** What a docked bar needs, as the plan page last published it. */
|
|
10
51
|
interface HealthPlanCartDock {
|
|
@@ -124,4 +165,41 @@ declare function healthPlanNoVet(petRef: PetRef): boolean;
|
|
|
124
165
|
/** Listens for `setHealthPlanNoVet`. Returns the unsubscribe. */
|
|
125
166
|
declare function onHealthPlanNoVet(listener: HealthPlanNoVetListener): () => void;
|
|
126
167
|
|
|
127
|
-
|
|
168
|
+
type HealthPlanSubscriptionPhase = 'idle' | 'loading' | 'unavailable' | 'failed' | 'ready';
|
|
169
|
+
interface HealthPlanSubscriptionOptions {
|
|
170
|
+
readonly petRef: PetRef | null;
|
|
171
|
+
readonly productId: string | null;
|
|
172
|
+
/** False skips every read (a host that has not opted in). Defaults to true. */
|
|
173
|
+
readonly enabled?: boolean;
|
|
174
|
+
/** A repository of your own (tests, a stub backend). Defaults to the one over the provider's runtime. */
|
|
175
|
+
readonly repository?: HealthPlanSubscriptionRepository;
|
|
176
|
+
/** Coming back to the foreground re-reads a quote shown for more than a minute, quietly. Absent, it does not. */
|
|
177
|
+
readonly lifecycle?: LifecyclePort | null;
|
|
178
|
+
/** Change it to re-read the quote now, quietly (for example after your checkout completed). */
|
|
179
|
+
readonly refreshKey?: string | number;
|
|
180
|
+
}
|
|
181
|
+
interface HealthPlanSubscriptionState {
|
|
182
|
+
readonly phase: HealthPlanSubscriptionPhase;
|
|
183
|
+
readonly quote: HealthPlanSubscriptionQuote | null;
|
|
184
|
+
/** The member's row for this pet and product (active or cancelled), or null. */
|
|
185
|
+
readonly subscription: HealthPlanSubscription | null;
|
|
186
|
+
/** A write is in flight. */
|
|
187
|
+
readonly busy: boolean;
|
|
188
|
+
/** The last refused read or write, or null. */
|
|
189
|
+
readonly error: EverfurError | null;
|
|
190
|
+
/** Each write settles the server's new state, or the refusal (a write before the quote is ready is refused). */
|
|
191
|
+
subscribe(intervalDays: number): Promise<EverfurResult<HealthPlanSubscription>>;
|
|
192
|
+
changeInterval(intervalDays: number): Promise<EverfurResult<HealthPlanSubscription>>;
|
|
193
|
+
skip(): Promise<EverfurResult<HealthPlanSubscription>>;
|
|
194
|
+
cancel(): Promise<EverfurResult<HealthPlanSubscription>>;
|
|
195
|
+
restart(intervalDays?: number): Promise<EverfurResult<HealthPlanSubscription>>;
|
|
196
|
+
/** Buy one box (no renewal), then re-read the quote: a one-box order spends the first-box offer. */
|
|
197
|
+
buyOneBox(tapKey?: string): Promise<EverfurResult<HealthPlanOneBoxOrder>>;
|
|
198
|
+
refresh(): Promise<void>;
|
|
199
|
+
}
|
|
200
|
+
/** The subscription repository bound to the runtime under your provider. */
|
|
201
|
+
declare function useHealthPlanSubscriptionRepository(): HealthPlanSubscriptionRepository;
|
|
202
|
+
/** One product's subscription for one pet. `EverfurHealthPlan` with `layout="focus"` paints it. */
|
|
203
|
+
declare function useHealthPlanSubscription(options: HealthPlanSubscriptionOptions): HealthPlanSubscriptionState;
|
|
204
|
+
|
|
205
|
+
export { useHealthPlanSubscription as A, useHealthPlanSubscriptionRepository as B, type HealthPlanTopCardOptions as C, type HealthPlanPossessivePet as D, healthPlanPossessive as E, healthPlanTopCard as F, type HealthPlanTopCardCopy as H, HEALTH_PLAN_TOP_CARD_COPY as a, type HealthPlanCartDock as b, HealthPlanCartScope as c, type HealthPlanCartScopeProps as d, HealthPlanController as e, type HealthPlanNoVetListener as f, type HealthPlanPageOptions as g, type HealthPlanPagePhase as h, type HealthPlanPageState as i, type HealthPlanPhase as j, type HealthPlanRecordsLandedListener as k, type HealthPlanRecordsLandedSource as l, type HealthPlanSnapshot as m, type HealthPlanSubscriptionOptions as n, type HealthPlanSubscriptionPhase as o, type HealthPlanSubscriptionState as p, type HealthPlanTopCardFocus as q, type HealthPlanTopCardPet as r, healthPlanNoVet as s, notifyHealthPlanRecordsLanded as t, onHealthPlanNoVet as u, onHealthPlanRecordsLanded as v, setHealthPlanNoVet as w, useHealthPlanCartDock as x, useHealthPlanPage as y, useHealthPlanPageRepository as z };
|
|
@@ -1,10 +1,51 @@
|
|
|
1
1
|
/*! @everfur/sdk. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
2
2
|
import { ReactNode } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { n as HealthPlanPagePet, b as HealthPlanFocusDesign, H as HealthPlanPage, q as HealthPlan, j as HealthPlanPageRepository, P as HealthPlanRepository, i as HealthPlanSubscriptionRepository, S as HealthPlanSubscriptionQuote, g as HealthPlanSubscription, h as HealthPlanOneBoxOrder } from './focus.d-DzIgOqNB.js';
|
|
4
|
+
import { a as EverfurChatTopCard } from './threadOptions.d-GPJPprkn.js';
|
|
4
5
|
import { P as PetRef } from './ids.d-B2GAAifq.js';
|
|
5
|
-
import {
|
|
6
|
+
import { g as HealthPlanCart } from './usePresentation.d-B7Uf44Ax.js';
|
|
6
7
|
import { E as EverfurError } from './EverfurError.d-8NHtlgzA.js';
|
|
7
8
|
import { L as LifecyclePort } from './LifecyclePort.d-Cr1p33a7.js';
|
|
9
|
+
import { E as EverfurResult } from './EverfurResult.d-D_-254ZY.js';
|
|
10
|
+
|
|
11
|
+
/** The page's focus, as the copy functions receive it. */
|
|
12
|
+
type HealthPlanTopCardFocus = NonNullable<HealthPlanFocusDesign['focus']>;
|
|
13
|
+
/** Who the card is about: the page's pet and the possessive its words use ("her", "his", "Georgia's"), or null. */
|
|
14
|
+
interface HealthPlanTopCardPet {
|
|
15
|
+
readonly pet: HealthPlanPagePet;
|
|
16
|
+
readonly possessive: string | null;
|
|
17
|
+
}
|
|
18
|
+
/** The card's own words. Defaults: Raph's v3 design (`HEALTH_PLAN_TOP_CARD_COPY`). */
|
|
19
|
+
interface HealthPlanTopCardCopy {
|
|
20
|
+
/** The plan button ("See her Health Plan"); null draws none. */
|
|
21
|
+
readonly action: (who: HealthPlanTopCardPet) => string | null;
|
|
22
|
+
/** The question link ("What does it mean?"). */
|
|
23
|
+
readonly ask: string;
|
|
24
|
+
/** What the link sends to the chat: the risk line's lead, then the link's words. */
|
|
25
|
+
readonly askPrompt: (focus: HealthPlanTopCardFocus, ask: string) => string;
|
|
26
|
+
/** The close control's accessible name ("Close her focus"); null or blank names it with the chat's plain "Close". */
|
|
27
|
+
readonly close: (who: HealthPlanTopCardPet) => string | null;
|
|
28
|
+
}
|
|
29
|
+
declare const HEALTH_PLAN_TOP_CARD_COPY: HealthPlanTopCardCopy;
|
|
30
|
+
/** The pet facts the possessive reads: its name and sex (a plan page's pet, or the focus words' pet). */
|
|
31
|
+
interface HealthPlanPossessivePet {
|
|
32
|
+
readonly name?: string | null;
|
|
33
|
+
readonly sex?: string | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* "her" for a female, "his" for a male, "Georgia's" for a named pet of unknown sex, else null. The sex is read
|
|
37
|
+
* leniently (any case, surrounding spaces), so a host-shaped page that says "Female" still reads as her.
|
|
38
|
+
*/
|
|
39
|
+
declare function healthPlanPossessive(pet: HealthPlanPossessivePet): string | null;
|
|
40
|
+
interface HealthPlanTopCardOptions {
|
|
41
|
+
/** Opens the pet's Health Plan (your tab or screen). Absent, the card has no plan button. */
|
|
42
|
+
readonly onOpenPlan?: (() => void) | undefined;
|
|
43
|
+
readonly copy?: Partial<HealthPlanTopCardCopy>;
|
|
44
|
+
/** Draw the close icon your way. */
|
|
45
|
+
readonly renderIcon?: (icon: 'close') => ReactNode;
|
|
46
|
+
}
|
|
47
|
+
/** The top card for a page, or undefined when the page has no focus to show. Pure. */
|
|
48
|
+
declare function healthPlanTopCard(page: HealthPlanPage | null, options?: HealthPlanTopCardOptions): EverfurChatTopCard | undefined;
|
|
8
49
|
|
|
9
50
|
/** What a docked bar needs, as the plan page last published it. */
|
|
10
51
|
interface HealthPlanCartDock {
|
|
@@ -124,4 +165,41 @@ declare function healthPlanNoVet(petRef: PetRef): boolean;
|
|
|
124
165
|
/** Listens for `setHealthPlanNoVet`. Returns the unsubscribe. */
|
|
125
166
|
declare function onHealthPlanNoVet(listener: HealthPlanNoVetListener): () => void;
|
|
126
167
|
|
|
127
|
-
|
|
168
|
+
type HealthPlanSubscriptionPhase = 'idle' | 'loading' | 'unavailable' | 'failed' | 'ready';
|
|
169
|
+
interface HealthPlanSubscriptionOptions {
|
|
170
|
+
readonly petRef: PetRef | null;
|
|
171
|
+
readonly productId: string | null;
|
|
172
|
+
/** False skips every read (a host that has not opted in). Defaults to true. */
|
|
173
|
+
readonly enabled?: boolean;
|
|
174
|
+
/** A repository of your own (tests, a stub backend). Defaults to the one over the provider's runtime. */
|
|
175
|
+
readonly repository?: HealthPlanSubscriptionRepository;
|
|
176
|
+
/** Coming back to the foreground re-reads a quote shown for more than a minute, quietly. Absent, it does not. */
|
|
177
|
+
readonly lifecycle?: LifecyclePort | null;
|
|
178
|
+
/** Change it to re-read the quote now, quietly (for example after your checkout completed). */
|
|
179
|
+
readonly refreshKey?: string | number;
|
|
180
|
+
}
|
|
181
|
+
interface HealthPlanSubscriptionState {
|
|
182
|
+
readonly phase: HealthPlanSubscriptionPhase;
|
|
183
|
+
readonly quote: HealthPlanSubscriptionQuote | null;
|
|
184
|
+
/** The member's row for this pet and product (active or cancelled), or null. */
|
|
185
|
+
readonly subscription: HealthPlanSubscription | null;
|
|
186
|
+
/** A write is in flight. */
|
|
187
|
+
readonly busy: boolean;
|
|
188
|
+
/** The last refused read or write, or null. */
|
|
189
|
+
readonly error: EverfurError | null;
|
|
190
|
+
/** Each write settles the server's new state, or the refusal (a write before the quote is ready is refused). */
|
|
191
|
+
subscribe(intervalDays: number): Promise<EverfurResult<HealthPlanSubscription>>;
|
|
192
|
+
changeInterval(intervalDays: number): Promise<EverfurResult<HealthPlanSubscription>>;
|
|
193
|
+
skip(): Promise<EverfurResult<HealthPlanSubscription>>;
|
|
194
|
+
cancel(): Promise<EverfurResult<HealthPlanSubscription>>;
|
|
195
|
+
restart(intervalDays?: number): Promise<EverfurResult<HealthPlanSubscription>>;
|
|
196
|
+
/** Buy one box (no renewal), then re-read the quote: a one-box order spends the first-box offer. */
|
|
197
|
+
buyOneBox(tapKey?: string): Promise<EverfurResult<HealthPlanOneBoxOrder>>;
|
|
198
|
+
refresh(): Promise<void>;
|
|
199
|
+
}
|
|
200
|
+
/** The subscription repository bound to the runtime under your provider. */
|
|
201
|
+
declare function useHealthPlanSubscriptionRepository(): HealthPlanSubscriptionRepository;
|
|
202
|
+
/** One product's subscription for one pet. `EverfurHealthPlan` with `layout="focus"` paints it. */
|
|
203
|
+
declare function useHealthPlanSubscription(options: HealthPlanSubscriptionOptions): HealthPlanSubscriptionState;
|
|
204
|
+
|
|
205
|
+
export { useHealthPlanSubscription as A, useHealthPlanSubscriptionRepository as B, type HealthPlanTopCardOptions as C, type HealthPlanPossessivePet as D, healthPlanPossessive as E, healthPlanTopCard as F, type HealthPlanTopCardCopy as H, HEALTH_PLAN_TOP_CARD_COPY as a, type HealthPlanCartDock as b, HealthPlanCartScope as c, type HealthPlanCartScopeProps as d, HealthPlanController as e, type HealthPlanNoVetListener as f, type HealthPlanPageOptions as g, type HealthPlanPagePhase as h, type HealthPlanPageState as i, type HealthPlanPhase as j, type HealthPlanRecordsLandedListener as k, type HealthPlanRecordsLandedSource as l, type HealthPlanSnapshot as m, type HealthPlanSubscriptionOptions as n, type HealthPlanSubscriptionPhase as o, type HealthPlanSubscriptionState as p, type HealthPlanTopCardFocus as q, type HealthPlanTopCardPet as r, healthPlanNoVet as s, notifyHealthPlanRecordsLanded as t, onHealthPlanNoVet as u, onHealthPlanRecordsLanded as v, setHealthPlanNoVet as w, useHealthPlanCartDock as x, useHealthPlanPage as y, useHealthPlanPageRepository as z };
|
|
@@ -1,12 +1,50 @@
|
|
|
1
1
|
/*! @everfur/sdk. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
2
|
+
import { O as HealthPlanReasonKind, f as HealthPlanItem, q as HealthPlan, P as HealthPlanRepository } from './focus.d-DzIgOqNB.js';
|
|
2
3
|
import { ReactNode } from 'react';
|
|
3
4
|
import { E as EverfurError } from './EverfurError.d-8NHtlgzA.js';
|
|
4
5
|
import { P as PetRef } from './ids.d-B2GAAifq.js';
|
|
5
|
-
import { f as HealthPlanItem, m as HealthPlan, n as HealthPlanRepository, o as HealthPlanReasonKind } from './focus.d-CjL6Cj0m.js';
|
|
6
6
|
import { L as LifecyclePort } from './LifecyclePort.d-Cr1p33a7.js';
|
|
7
7
|
import { d as RecordsRequestView, f as RecordsView } from './models.d-DOwnr8fi.js';
|
|
8
8
|
import { i as EverfurPresentationInput, h as EverfurPresentation } from './presentation.d-vy8kTGfR.js';
|
|
9
9
|
|
|
10
|
+
declare const HEALTH_PLAN_COPY: Readonly<{
|
|
11
|
+
loading: "Loading";
|
|
12
|
+
retry: "Try again";
|
|
13
|
+
signedOut: "Sign in required";
|
|
14
|
+
addToCart: "Add to cart";
|
|
15
|
+
added: "Added";
|
|
16
|
+
remove: "Remove";
|
|
17
|
+
checkout: "Checkout";
|
|
18
|
+
subtotal: "Subtotal";
|
|
19
|
+
sample: "Sample";
|
|
20
|
+
cartEmpty: "Your cart is empty.";
|
|
21
|
+
choosePet: "Choose a pet";
|
|
22
|
+
emptyTitle: "";
|
|
23
|
+
emptyBody: "";
|
|
24
|
+
emptyAsk: "";
|
|
25
|
+
}>;
|
|
26
|
+
/** The Health Plan's empty state words (Q1). Each is '' by default: an empty title and body draw nothing. */
|
|
27
|
+
interface HealthPlanEmptyCopy {
|
|
28
|
+
readonly emptyTitle: string;
|
|
29
|
+
readonly emptyBody: string;
|
|
30
|
+
/** The empty state's Ask button. */
|
|
31
|
+
readonly emptyAsk: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The reason labels, one per kind. An empty label is not drawn (the reason's text still is). `profile` (a pet profile
|
|
35
|
+
* fact) has no source yet; `dna` names one partner's product, so the SDK leaves it to that partner (Q3).
|
|
36
|
+
*/
|
|
37
|
+
declare const HEALTH_PLAN_REASON_LABELS: Readonly<Record<HealthPlanReasonKind, string>>;
|
|
38
|
+
/** ADAPTED from Raph. Listed for approval. */
|
|
39
|
+
declare const HEALTH_PLAN_TEMPLATES: Readonly<{
|
|
40
|
+
/** Raph: "Georgia's care plan". Used only when the plan carries no `headline` of the tenant's own. */
|
|
41
|
+
planTitle: (petName: string) => string;
|
|
42
|
+
/** Raph: "<brand> cart" (his demo named the partner). */
|
|
43
|
+
cartLabel: (brand: string) => string;
|
|
44
|
+
}>;
|
|
45
|
+
/** Every key still waiting on Raph's words (empty, so not drawn), so the list a reviewer approves cannot drift from the file. */
|
|
46
|
+
declare const HEALTH_PLAN_COPY_PLACEHOLDERS: readonly string[];
|
|
47
|
+
|
|
10
48
|
type EverfurHealthPlanStatus = 'signedOut' | 'noPet' | 'loading' | 'failed' | 'empty' | 'ready';
|
|
11
49
|
/** The member's cart: the items in the plan, and their total when one can honestly be given. */
|
|
12
50
|
interface HealthPlanCart {
|
|
@@ -239,48 +277,10 @@ declare function healthPlanBlanksFacts(input: {
|
|
|
239
277
|
readonly record: RecordsView | null;
|
|
240
278
|
}, now: number): HealthPlanBlanksFacts | null;
|
|
241
279
|
|
|
242
|
-
declare const HEALTH_PLAN_COPY: Readonly<{
|
|
243
|
-
loading: "Loading";
|
|
244
|
-
retry: "Try again";
|
|
245
|
-
signedOut: "Sign in required";
|
|
246
|
-
addToCart: "Add to cart";
|
|
247
|
-
added: "Added";
|
|
248
|
-
remove: "Remove";
|
|
249
|
-
checkout: "Checkout";
|
|
250
|
-
subtotal: "Subtotal";
|
|
251
|
-
sample: "Sample";
|
|
252
|
-
cartEmpty: "Your cart is empty.";
|
|
253
|
-
choosePet: "Choose a pet";
|
|
254
|
-
emptyTitle: "";
|
|
255
|
-
emptyBody: "";
|
|
256
|
-
emptyAsk: "";
|
|
257
|
-
}>;
|
|
258
|
-
/** The Health Plan's empty state words (Q1). Each is '' by default: an empty title and body draw nothing. */
|
|
259
|
-
interface HealthPlanEmptyCopy {
|
|
260
|
-
readonly emptyTitle: string;
|
|
261
|
-
readonly emptyBody: string;
|
|
262
|
-
/** The empty state's Ask button. */
|
|
263
|
-
readonly emptyAsk: string;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* The reason labels, one per kind. An empty label is not drawn (the reason's text still is). `profile` (a pet profile
|
|
267
|
-
* fact) has no source yet; `dna` names one partner's product, so the SDK leaves it to that partner (Q3).
|
|
268
|
-
*/
|
|
269
|
-
declare const HEALTH_PLAN_REASON_LABELS: Readonly<Record<HealthPlanReasonKind, string>>;
|
|
270
|
-
/** ADAPTED from Raph. Listed for approval. */
|
|
271
|
-
declare const HEALTH_PLAN_TEMPLATES: Readonly<{
|
|
272
|
-
/** Raph: "Georgia's care plan". Used only when the plan carries no `headline` of the tenant's own. */
|
|
273
|
-
planTitle: (petName: string) => string;
|
|
274
|
-
/** Raph: "<brand> cart" (his demo named the partner). */
|
|
275
|
-
cartLabel: (brand: string) => string;
|
|
276
|
-
}>;
|
|
277
|
-
/** Every key still waiting on Raph's words (empty, so not drawn), so the list a reviewer approves cannot drift from the file. */
|
|
278
|
-
declare const HEALTH_PLAN_COPY_PLACEHOLDERS: readonly string[];
|
|
279
|
-
|
|
280
280
|
/**
|
|
281
281
|
* The tenant's presentation settings resolved against `client` (the explicit props; leave a field undefined to
|
|
282
282
|
* take the console value). Total: always every field.
|
|
283
283
|
*/
|
|
284
284
|
declare function useEverfurPresentation(client?: EverfurPresentationInput | null): EverfurPresentation;
|
|
285
285
|
|
|
286
|
-
export { formatHealthPlanPriceWith as A, healthPlanBlanksFacts as B, healthPlanCart as C, healthPlanNextShotsAt as D, type EverfurHealthPlanOptions as E, healthPlanRecordsWeightKg as F, isHealthPlanSessionRequired as G, type HealthPlanBlanksFacts as H, showHealthPlanCartBar as I, useEverfurHealthPlan as J, useEverfurHealthPlanRepository as K, useEverfurPresentation as L, type HealthPlanPriceFormat as a, type HealthPlanLayoutProps as b, type HealthPlanEmptyCopy as c, type
|
|
286
|
+
export { formatHealthPlanPriceWith as A, healthPlanBlanksFacts as B, healthPlanCart as C, healthPlanNextShotsAt as D, type EverfurHealthPlanOptions as E, healthPlanRecordsWeightKg as F, isHealthPlanSessionRequired as G, type HealthPlanBlanksFacts as H, showHealthPlanCartBar as I, useEverfurHealthPlan as J, useEverfurHealthPlanRepository as K, useEverfurPresentation as L, type HealthPlanPriceFormat as a, type HealthPlanLayoutProps as b, type HealthPlanEmptyCopy as c, type HealthPlanCardOptions as d, type HealthPlanImageVariant as e, type HealthPlanReasonVariant as f, type HealthPlanCart as g, type EverfurHealthPlanState as h, type EverfurHealthPlanStatus as i, HEALTH_PLAN_COPY as j, HEALTH_PLAN_COPY_PLACEHOLDERS as k, HEALTH_PLAN_LAYOUT_DEFAULTS as l, HEALTH_PLAN_REASON_LABELS as m, HEALTH_PLAN_TEMPLATES as n, type HealthPlanAddButtonSize as o, type HealthPlanAddedVariant as p, type HealthPlanBlanksPhase as q, type HealthPlanCardShadow as r, type HealthPlanCartBarPlacement as s, type HealthPlanCartBarVisibility as t, type HealthPlanCategoryVariant as u, type HealthPlanFontWeight as v, type HealthPlanHeaderContext as w, type HealthPlanPageContext as x, type HealthPlanShadow as y, formatHealthPlanPrice as z };
|
|
@@ -1,12 +1,50 @@
|
|
|
1
1
|
/*! @everfur/sdk. Copyright (c) 2026 Strand Health Inc. dba Everfur. All rights reserved. Use is subject to the Everfur SDK License: https://docs.everfur.com/license */
|
|
2
|
+
import { O as HealthPlanReasonKind, f as HealthPlanItem, q as HealthPlan, P as HealthPlanRepository } from './focus.d-CXpIkIuU.cjs';
|
|
2
3
|
import { ReactNode } from 'react';
|
|
3
4
|
import { E as EverfurError } from './EverfurError.d-8NHtlgzA.cjs';
|
|
4
5
|
import { P as PetRef } from './ids.d-B2GAAifq.cjs';
|
|
5
|
-
import { f as HealthPlanItem, m as HealthPlan, n as HealthPlanRepository, o as HealthPlanReasonKind } from './focus.d-BHm_QtQ9.cjs';
|
|
6
6
|
import { L as LifecyclePort } from './LifecyclePort.d-Cr1p33a7.cjs';
|
|
7
7
|
import { d as RecordsRequestView, f as RecordsView } from './models.d-BSqvbTE1.cjs';
|
|
8
8
|
import { i as EverfurPresentationInput, h as EverfurPresentation } from './presentation.d-vy8kTGfR.cjs';
|
|
9
9
|
|
|
10
|
+
declare const HEALTH_PLAN_COPY: Readonly<{
|
|
11
|
+
loading: "Loading";
|
|
12
|
+
retry: "Try again";
|
|
13
|
+
signedOut: "Sign in required";
|
|
14
|
+
addToCart: "Add to cart";
|
|
15
|
+
added: "Added";
|
|
16
|
+
remove: "Remove";
|
|
17
|
+
checkout: "Checkout";
|
|
18
|
+
subtotal: "Subtotal";
|
|
19
|
+
sample: "Sample";
|
|
20
|
+
cartEmpty: "Your cart is empty.";
|
|
21
|
+
choosePet: "Choose a pet";
|
|
22
|
+
emptyTitle: "";
|
|
23
|
+
emptyBody: "";
|
|
24
|
+
emptyAsk: "";
|
|
25
|
+
}>;
|
|
26
|
+
/** The Health Plan's empty state words (Q1). Each is '' by default: an empty title and body draw nothing. */
|
|
27
|
+
interface HealthPlanEmptyCopy {
|
|
28
|
+
readonly emptyTitle: string;
|
|
29
|
+
readonly emptyBody: string;
|
|
30
|
+
/** The empty state's Ask button. */
|
|
31
|
+
readonly emptyAsk: string;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The reason labels, one per kind. An empty label is not drawn (the reason's text still is). `profile` (a pet profile
|
|
35
|
+
* fact) has no source yet; `dna` names one partner's product, so the SDK leaves it to that partner (Q3).
|
|
36
|
+
*/
|
|
37
|
+
declare const HEALTH_PLAN_REASON_LABELS: Readonly<Record<HealthPlanReasonKind, string>>;
|
|
38
|
+
/** ADAPTED from Raph. Listed for approval. */
|
|
39
|
+
declare const HEALTH_PLAN_TEMPLATES: Readonly<{
|
|
40
|
+
/** Raph: "Georgia's care plan". Used only when the plan carries no `headline` of the tenant's own. */
|
|
41
|
+
planTitle: (petName: string) => string;
|
|
42
|
+
/** Raph: "<brand> cart" (his demo named the partner). */
|
|
43
|
+
cartLabel: (brand: string) => string;
|
|
44
|
+
}>;
|
|
45
|
+
/** Every key still waiting on Raph's words (empty, so not drawn), so the list a reviewer approves cannot drift from the file. */
|
|
46
|
+
declare const HEALTH_PLAN_COPY_PLACEHOLDERS: readonly string[];
|
|
47
|
+
|
|
10
48
|
type EverfurHealthPlanStatus = 'signedOut' | 'noPet' | 'loading' | 'failed' | 'empty' | 'ready';
|
|
11
49
|
/** The member's cart: the items in the plan, and their total when one can honestly be given. */
|
|
12
50
|
interface HealthPlanCart {
|
|
@@ -239,48 +277,10 @@ declare function healthPlanBlanksFacts(input: {
|
|
|
239
277
|
readonly record: RecordsView | null;
|
|
240
278
|
}, now: number): HealthPlanBlanksFacts | null;
|
|
241
279
|
|
|
242
|
-
declare const HEALTH_PLAN_COPY: Readonly<{
|
|
243
|
-
loading: "Loading";
|
|
244
|
-
retry: "Try again";
|
|
245
|
-
signedOut: "Sign in required";
|
|
246
|
-
addToCart: "Add to cart";
|
|
247
|
-
added: "Added";
|
|
248
|
-
remove: "Remove";
|
|
249
|
-
checkout: "Checkout";
|
|
250
|
-
subtotal: "Subtotal";
|
|
251
|
-
sample: "Sample";
|
|
252
|
-
cartEmpty: "Your cart is empty.";
|
|
253
|
-
choosePet: "Choose a pet";
|
|
254
|
-
emptyTitle: "";
|
|
255
|
-
emptyBody: "";
|
|
256
|
-
emptyAsk: "";
|
|
257
|
-
}>;
|
|
258
|
-
/** The Health Plan's empty state words (Q1). Each is '' by default: an empty title and body draw nothing. */
|
|
259
|
-
interface HealthPlanEmptyCopy {
|
|
260
|
-
readonly emptyTitle: string;
|
|
261
|
-
readonly emptyBody: string;
|
|
262
|
-
/** The empty state's Ask button. */
|
|
263
|
-
readonly emptyAsk: string;
|
|
264
|
-
}
|
|
265
|
-
/**
|
|
266
|
-
* The reason labels, one per kind. An empty label is not drawn (the reason's text still is). `profile` (a pet profile
|
|
267
|
-
* fact) has no source yet; `dna` names one partner's product, so the SDK leaves it to that partner (Q3).
|
|
268
|
-
*/
|
|
269
|
-
declare const HEALTH_PLAN_REASON_LABELS: Readonly<Record<HealthPlanReasonKind, string>>;
|
|
270
|
-
/** ADAPTED from Raph. Listed for approval. */
|
|
271
|
-
declare const HEALTH_PLAN_TEMPLATES: Readonly<{
|
|
272
|
-
/** Raph: "Georgia's care plan". Used only when the plan carries no `headline` of the tenant's own. */
|
|
273
|
-
planTitle: (petName: string) => string;
|
|
274
|
-
/** Raph: "<brand> cart" (his demo named the partner). */
|
|
275
|
-
cartLabel: (brand: string) => string;
|
|
276
|
-
}>;
|
|
277
|
-
/** Every key still waiting on Raph's words (empty, so not drawn), so the list a reviewer approves cannot drift from the file. */
|
|
278
|
-
declare const HEALTH_PLAN_COPY_PLACEHOLDERS: readonly string[];
|
|
279
|
-
|
|
280
280
|
/**
|
|
281
281
|
* The tenant's presentation settings resolved against `client` (the explicit props; leave a field undefined to
|
|
282
282
|
* take the console value). Total: always every field.
|
|
283
283
|
*/
|
|
284
284
|
declare function useEverfurPresentation(client?: EverfurPresentationInput | null): EverfurPresentation;
|
|
285
285
|
|
|
286
|
-
export { formatHealthPlanPriceWith as A, healthPlanBlanksFacts as B, healthPlanCart as C, healthPlanNextShotsAt as D, type EverfurHealthPlanOptions as E, healthPlanRecordsWeightKg as F, isHealthPlanSessionRequired as G, type HealthPlanBlanksFacts as H, showHealthPlanCartBar as I, useEverfurHealthPlan as J, useEverfurHealthPlanRepository as K, useEverfurPresentation as L, type HealthPlanPriceFormat as a, type HealthPlanLayoutProps as b, type HealthPlanEmptyCopy as c, type
|
|
286
|
+
export { formatHealthPlanPriceWith as A, healthPlanBlanksFacts as B, healthPlanCart as C, healthPlanNextShotsAt as D, type EverfurHealthPlanOptions as E, healthPlanRecordsWeightKg as F, isHealthPlanSessionRequired as G, type HealthPlanBlanksFacts as H, showHealthPlanCartBar as I, useEverfurHealthPlan as J, useEverfurHealthPlanRepository as K, useEverfurPresentation as L, type HealthPlanPriceFormat as a, type HealthPlanLayoutProps as b, type HealthPlanEmptyCopy as c, type HealthPlanCardOptions as d, type HealthPlanImageVariant as e, type HealthPlanReasonVariant as f, type HealthPlanCart as g, type EverfurHealthPlanState as h, type EverfurHealthPlanStatus as i, HEALTH_PLAN_COPY as j, HEALTH_PLAN_COPY_PLACEHOLDERS as k, HEALTH_PLAN_LAYOUT_DEFAULTS as l, HEALTH_PLAN_REASON_LABELS as m, HEALTH_PLAN_TEMPLATES as n, type HealthPlanAddButtonSize as o, type HealthPlanAddedVariant as p, type HealthPlanBlanksPhase as q, type HealthPlanCardShadow as r, type HealthPlanCartBarPlacement as s, type HealthPlanCartBarVisibility as t, type HealthPlanCategoryVariant as u, type HealthPlanFontWeight as v, type HealthPlanHeaderContext as w, type HealthPlanPageContext as x, type HealthPlanShadow as y, formatHealthPlanPrice as z };
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { E as EverfurError } from './EverfurError.d-8NHtlgzA.js';
|
|
3
3
|
import { E as EverfurResult } from './EverfurResult.d-D_-254ZY.js';
|
|
4
4
|
import { P as PetRef } from './ids.d-B2GAAifq.js';
|
|
5
|
-
import { l as RecordsDepthClient } from './depth.d-
|
|
5
|
+
import { l as RecordsDepthClient } from './depth.d-SJzknw_P.js';
|
|
6
6
|
|
|
7
7
|
type RecordsDepthStatus = 'loading' | 'empty' | 'error' | 'populated';
|
|
8
8
|
/** One depth read as a render state. `withheld` (no consent, or a fail-closed parse) renders nothing. */
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { E as EverfurError } from './EverfurError.d-8NHtlgzA.cjs';
|
|
3
3
|
import { E as EverfurResult } from './EverfurResult.d-BFH-3s6E.cjs';
|
|
4
4
|
import { P as PetRef } from './ids.d-B2GAAifq.cjs';
|
|
5
|
-
import { l as RecordsDepthClient } from './depth.d-
|
|
5
|
+
import { l as RecordsDepthClient } from './depth.d-e_8_icip.cjs';
|
|
6
6
|
|
|
7
7
|
type RecordsDepthStatus = 'loading' | 'empty' | 'error' | 'populated';
|
|
8
8
|
/** One depth read as a render state. `withheld` (no consent, or a fail-closed parse) renders nothing. */
|
package/dist/video/index.cjs
CHANGED
|
@@ -98,8 +98,8 @@ return Object.freeze({ok:false,error:error})}var EverfurConfigError=class _Everf
|
|
|
98
98
|
return Object.freeze({kind:"error",terminal:true,code:fields.code,retryable:fields.retryable,wireMessage:fields.wireMessage,synthesized:fields.synthesized,lastEventId:fields.lastEventId,serverRequestId:null})}function mintFailedError(cause,refusal){let message=cause instanceof Error?cause.message:typeof cause=="string"?cause:null;return makeEverfurError("authRejected",{retryable:false,...refusal?.wireCode?{wireCode:refusal.wireCode}:{},...refusal?.requestId?{requestId:refusal.requestId}:{},...message?{wireMessage:message}:{},...cause!=null?{raw:cause}:{}})}function authHeaders(auth){let headers={};return auth.mode==="personalized"?headers.authorization=`Bearer ${auth.token}`:headers["x-everfur-partner-key"]=auth.publishableKey,auth.userRef&&(headers["x-everfur-user-ref"]=auth.userRef),auth.sessionId&&(headers["x-everfur-session-id"]=auth.sessionId),headers}function withAuthHeaders(req,auth){return{...req,headers:{...stripAuthHeaders(req.headers),...authHeaders(auth)}}}function stripAuthHeaders(headers){if(!headers)return{};let out={};for(let[key,value]of Object.entries(headers)){let lower=key.toLowerCase();lower==="authorization"||lower==="x-everfur-partner-key"||(out[key]=value)}return out}async function authedSend(req,ctx){if(ctx.mode==="anonymous")return ctx.transport.request(withAuthHeaders(req,{mode:"anonymous",publishableKey:ctx.publishableKey,userRef:ctx.userRef,...ctx.sessionId?{sessionId:ctx.sessionId}:{}}));let token;try{token=await ctx.identity.currentToken()}catch(cause){return ctx.identity.reportRejected?.(),err(mintFailedError(cause))}let first=await ctx.transport.request(withAuthHeaders(req,{mode:"personalized",token:token,userRef:ctx.userRef,...ctx.sessionId?{sessionId:ctx.sessionId}:{}}));if(first.ok||first.error.httpStatus!==401)return first;let refreshed;try{refreshed=await ctx.identity.currentToken({forceRefresh:!0})}catch(cause){return ctx.identity.reportRejected?.(),err(mintFailedError(cause,{wireCode:wireCodeOf(first.error.raw),requestId:first.error.requestId}))}let retry=await ctx.transport.request(withAuthHeaders(req,{mode:"personalized",token:refreshed,userRef:ctx.userRef,...ctx.sessionId?{sessionId:ctx.sessionId}:{}}));return!retry.ok&&retry.error.httpStatus===401?(ctx.identity.reportRejected?.(),err(refusedAfterRemintError(retry.error))):retry}function refusedAfterRemintError(refusal){let raw=refusal.raw,wireCode=wireCodeOf(raw);return makeEverfurError("authRejected",{retryable:false,...refusal.httpStatus!==void 0?{httpStatus:refusal.httpStatus}:{},...refusal.requestId?{requestId:refusal.requestId}:{},...wireCode?{wireCode:wireCode}:{},...refusal.reasonCode?{reasonCode:refusal.reasonCode}:{},...refusal.wireMessage?{wireMessage:refusal.wireMessage}:{},...raw!=null?{raw:raw}:{}})}function wireCodeOf(body){if(typeof body!="object"||body===null)return null;let b=body,code=(typeof b.error=="object"&&b.error!==null?b.error.code:void 0)??b.code;return typeof code=="string"&&code.length>0?code:null}function networkError(cause){return makeEverfurError("internalError",{retryable:true,wireMessage:describeCause(cause)})}function describeCause(cause){return cause instanceof Error?cause.message:typeof cause=="string"?cause:"network request failed"}var FUNNEL_UNARY_TIMEOUT_MS=3e4,RETRY_OVERRIDE_MAX_MS=BACKOFF_CAP_MS*2,IDEMPOTENCY_HEADER="idempotency-key",MUTATING_METHODS=/* @__PURE__ */new Set(["POST","PUT","PATCH","DELETE"]),NOOP_OBSERVER=/* @__PURE__ */Object.freeze({onEvent(){}}),defaultFunnelTimers=/* @__PURE__ */Object.freeze({setTimeout:(handler,ms)=>setTimeout(handler,ms),clearTimeout:handle=>clearTimeout(handle),now:()=>Date.now()});function seededIdempotencyKey(seed){let safe=seed.trim().replace(/[^A-Za-z0-9_.:-]/g,"-");return safe.length===0?null:`efs_${safe}`.slice(0,128)}function createRequestFunnel(deps){let observer=deps.observer??NOOP_OBSERVER,timers=deps.timers??defaultFunnelTimers,rng=deps.rng??Math.random,sleep=deps.sleep??((ms,signal)=>delayAbortable(ms,timers,signal)),ceiling=deps.maxAttempts??MAX_RETRY_ATTEMPTS,timeoutMs=deps.unaryTimeoutMs??FUNNEL_UNARY_TIMEOUT_MS,mintKey=deps.newIdempotencyKey??defaultIdempotencyKeyFactory(),emit=event=>{try{observer.onEvent(event)}catch{}};async function send(call,req,opts){let perCallMaxAttempts=opts?.maxAttempts,maxAttempts=Math.max(1,perCallMaxAttempts??ceiling),idempotent=opts?.idempotent??MUTATING_METHODS.has(req.method),seeded=opts?.idempotencyKey===void 0?null:seededIdempotencyKey(opts.idempotencyKey),idempotencyKey=idempotent?seeded??mintKey():null,base=assembleHeaders(req,idempotencyKey),attempt=0;for(;;){let stamp=extra=>/* @__PURE__ */Object.freeze({call:call,method:req.method,path:req.path,attempt:attempt,...idempotencyKey?{idempotencyKey:idempotencyKey}:{},...extra});emit(stamp({phase:"attempt"}));let deadline=boundedSignal(timeoutMs,timers),merged=mergeSignals(deadline.signal,req.signal),settled;try{settled=await authedSend({...base,signal:merged.signal},deps.auth)}catch(cause){settled=err(networkError(cause))}finally{merged.dispose(),deadline.cancel()}if(settled.ok)return emit(stamp({phase:"settled",ok:true,reason:"ok"})),settled;let error=settled.error,decision=decideRetry(error,attempt,{maxAttempts:maxAttempts,rng:rng,now:timers.now(),aborted:req.signal?.aborted===true,...perCallMaxAttempts!==void 0?{perCallMaxAttempts:perCallMaxAttempts}:{},...deps.errorPolicy!==void 0?{policy:deps.errorPolicy}:{}}),settledEvent={ok:false,code:error.code,reason:decision.reason,...error.httpStatus!==void 0?{httpStatus:error.httpStatus}:{},...error.requestId!==void 0?{requestId:error.requestId}:{}};if(!decision.retry)return emit(stamp({phase:"settled",...settledEvent})),err(error);if(emit(stamp({phase:"retry",...settledEvent,delayMs:decision.delayMs})),await sleep(decision.delayMs,req.signal),req.signal?.aborted===true)return emit(stamp({phase:"settled",...settledEvent,reason:"aborted"})),err(error);attempt+=1}}async function authorize(req){return withAuthHeaders(req,await resolveDeviceAuth(deps.auth))}async function*stream(call,req,signal){emit(
|
|
99
99
|
/* @__PURE__ */Object.freeze({call:call,phase:"stream.open",method:req.method,path:req.path,attempt:0}));try{yield*deps.auth.transport.stream(req,signal)}catch{yield errorFrame({code:"internal_error",retryable:true,wireMessage:null,synthesized:true,lastEventId:null})}}/* @__PURE__ */
|
|
100
100
|
return Object.freeze({send:send,authorize:authorize,stream:stream})}function assembleHeaders(req,idempotencyKey){let headers={};for(let[key,value]of Object.entries(req.headers??{}))key.toLowerCase()!==IDEMPOTENCY_HEADER&&(headers[key]=value);return idempotencyKey!==null&&(headers["Idempotency-Key"]=idempotencyKey),{...req,headers:headers}}function defaultIdempotencyKeyFactory(){let counter=0;return()=>`efk_${Date.now().toString(36)}_${(counter++).toString(36)}_${Math.random().toString(36).slice(2,12)}`}var POLICY_MAX_ATTEMPTS_CAP=10;function decideRetry(error,attempt,ctx){if(ctx.aborted)return{retry:false,reason:"aborted"};let throttle=throttleKind(error);if(throttle==="quota")return{retry:false,reason:"daily-quota-exhausted"};if(throttle!=="burst"&&!isAutoRetryable(error.code))return{retry:false,reason:"terminal-code"};let reason=throttle==="burst"?"burst-throttle":"retryable-code";if((()=>{if(ctx.policy===void 0)return false;try{return!ctx.policy.shouldRetry(error.code,attempt)}catch{return false}})())return{retry:false,reason:"terminal-code"};let policyCeiling=()=>{if(ctx.policy===void 0)return null;let raw;try{raw=ctx.policy.maxAttempts(error.code)}catch{return null}return typeof raw!="number"||!Number.isFinite(raw)?null:Math.max(1,Math.min(POLICY_MAX_ATTEMPTS_CAP,Math.floor(raw)))},ceiling=ctx.perCallMaxAttempts??policyCeiling()??ctx.maxAttempts;if(attempt+1>=ceiling)return{retry:false,reason:"attempts-exhausted"};let override=retryOverrideMs(error,ctx.now);return override!==null?override>RETRY_OVERRIDE_MAX_MS?{retry:false,reason:"server-reset-beyond-budget"}:{retry:true,reason:reason,delayMs:override}:{retry:true,reason:reason,delayMs:backoffDelayMs(attempt,ctx.rng)}}function throttleKind(error){let code=error.code==="unknown"?fromWire(rawWireCode(error.raw)):error.code;return code==="quotaExceeded"?"quota":code==="rateLimited"||error.httpStatus===429?"burst":null}function retryOverrideMs(error,now){let at=findResetsAt(error.raw);if(at!==null){let delta=at-now;return delta>0?delta:0}let wait=findRetryAfterSeconds(error.raw);return wait===null?null:Math.round(wait*1e3)}function findRetryAfterSeconds(raw){for(let scope of candidateScopes(raw)){let value=scope.retry_after_seconds;if(typeof value=="number"&&Number.isFinite(value)&&value>=0)return value}return null}function findResetsAt(raw){for(let scope of candidateScopes(raw)){let value=scope.resets_at,parsed=parseInstantMs(value);if(parsed!==null)return parsed}return null}function candidateScopes(raw){if(!isRecord(raw))return[];let out=[raw];for(let nested of["error","detail"]){let value=raw[nested];isRecord(value)&&out.push(value)}return out}function parseInstantMs(value){if(typeof value=="number"&&Number.isFinite(value))return value<1e11?Math.round(value*1e3):Math.round(value);if(typeof value=="string"&&value.trim().length>0){let parsed=Date.parse(value);return Number.isFinite(parsed)?parsed:null}return null}function rawWireCode(raw){for(let scope of candidateScopes(raw)){let code=scope.code;if(typeof code=="string"&&code.length>0)return code}return null}function isRecord(value){return typeof value=="object"&&value!==null}async function resolveDeviceAuth(auth){return auth.mode==="anonymous"?{mode:"anonymous",publishableKey:auth.publishableKey,userRef:auth.userRef,...auth.sessionId?{sessionId:auth.sessionId}:{}}:{mode:"personalized",token:await auth.identity.currentToken(),userRef:auth.userRef,...auth.sessionId?{sessionId:auth.sessionId}:{}}}function boundedSignal(ms,timers){let ctrl=new AbortController,handle=timers.setTimeout(()=>ctrl.abort(),ms);return{signal:ctrl.signal,cancel:()=>timers.clearTimeout(handle)}}function mergeSignals(deadline,caller){let noop=()=>{};if(!caller)return{signal:deadline,dispose:noop};let ctrl=new AbortController;if(deadline.aborted||caller.aborted)return ctrl.abort(),{signal:ctrl.signal,dispose:noop};let onAbort=()=>ctrl.abort();return deadline.addEventListener("abort",onAbort,{once:true}),caller.addEventListener("abort",onAbort,{once:true}),{signal:ctrl.signal,dispose:()=>{deadline.removeEventListener("abort",onAbort),caller.removeEventListener("abort",onAbort)}}}function delayAbortable(ms,timers,signal){return ms<=0||signal?.aborted===true?Promise.resolve():new Promise(resolve=>{let handle=timers.setTimeout(()=>{signal?.removeEventListener("abort",onAbort),resolve()},ms),onAbort=()=>{timers.clearTimeout(handle),resolve()};signal?.addEventListener("abort",onAbort,{once:true})})}var noopTelemetry=/* @__PURE__ */Object.freeze({track(){},trackExpectedFailure(){}});function fileHandleFromMedia(source){let handle={uri:source.uri,mimeType:source.mimeType},size=mediaByteSize(source);return size!==null&&(handle.sizeBytes=size),/* @__PURE__ */Object.freeze(handle)}function mediaByteSize(source){let candidate=source.byteSize??source.sizeBytes;return typeof candidate=="number"&&Number.isFinite(candidate)&&candidate>=0?candidate:null}function mediaDurationMs(source){let seconds=source.durationSeconds;return typeof seconds=="number"&&Number.isFinite(seconds)&&seconds>=0?Math.round(seconds*1e3):null}function captureOptionsFor(mode,maxDurationSeconds){/* @__PURE__ */
|
|
101
|
-
return Object.freeze({mode:mode,maxDurationSeconds:maxDurationSeconds})}function isCaptureAvailable(camera){return camera!=null&&camera.isAvailable===true}var defaultTimers=/* @__PURE__ */Object.freeze({setTimeout:(handler,ms)=>setTimeout(handler,ms),clearTimeout:handle=>clearTimeout(handle),now:()=>Date.now()});function delayAbortable2(ms,signal,timers){return new Promise(resolve=>{if(signal.aborted){resolve();return}let holder={handle:void 0},done=()=>{timers.clearTimeout(holder.handle),signal.removeEventListener("abort",done),resolve()};holder.handle=timers.setTimeout(done,ms),signal.addEventListener("abort",done,{once:true})})}function mergeSignals2(a,b){if(!b)return a;let ctrl=new AbortController;if(a.aborted||b.aborted)return ctrl.abort(),ctrl.signal;let onAbort=()=>ctrl.abort();return a.addEventListener("abort",onAbort,{once:true}),b.addEventListener("abort",onAbort,{once:true}),ctrl.signal}var MediaStore=class{constructor(initial){this.listeners=/* @__PURE__ */new Set;this.epoch=0;this.inFlight=null;this.snapshot=/* @__PURE__ */Object.freeze({...initial})}subscribe(listener){return this.listeners.add(listener),()=>{this.listeners.delete(listener)}}getSnapshot(){return this.snapshot}patch(partial){this.snapshot=/* @__PURE__ */Object.freeze({...this.snapshot,...partial});for(let listener of this.listeners)listener()}beginOperation(external){this.inFlight?.abort();let ctrl=new AbortController;this.inFlight=ctrl;let epoch=this.epoch;return{signal:external?mergeSignals2(ctrl.signal,external):ctrl.signal,epoch:epoch,settle:()=>{this.inFlight===ctrl&&(this.inFlight=null)}}}alive(epoch){return epoch===this.epoch}rescope(){this.epoch+=1,this.inFlight?.abort(),this.inFlight=null}dispose(){this.epoch+=1,this.inFlight?.abort(),this.inFlight=null,this.listeners.clear()}};function hasLoneSurrogate(value){for(let i=0;i<value.length;i+=1){let code=value.charCodeAt(i);if(code>=55296&&code<=56319){let low=value.charCodeAt(i+1);if(!(low>=56320&&low<=57343))return true;i+=1}else if(code>=56320&&code<=57343)return true}return false}var CONSUMER_SAFE_DETECTION_KEYS=/* @__PURE__ */Object.freeze(["primary_label","primary_confidence","subtype_label","subtype_display","subtype_confidence","risk_tier","confidence_tier","copy_short","disease_name","disease_framing","model_version","skin_v2","eye_v2","llm_checkup"]),OPERATOR_INTERNAL_KEYS=/* @__PURE__ */Object.freeze(["decision_audit","decision_thresholds","per_class_auroc","ood_layers","gate1_score","possible_conditions","top_class"]),BOOLEAN_KEYS=/* @__PURE__ */new Set(["skin_v2","eye_v2","llm_checkup"]),CONFIDENCE_KEYS=/* @__PURE__ */new Set(["primary_confidence","subtype_confidence"]),RISK_TIER_VALUES=/* @__PURE__ */new Set(["low_risk","concern","uncertain"]),CONFIDENCE_TIER_VALUES=/* @__PURE__ */new Set(["possible","probable"]),STRING_LIMITS=/* @__PURE__ */Object.freeze({primary_label:64,subtype_label:64,subtype_display:128,copy_short:512,disease_name:128,disease_framing:512,model_version:64});function projectDetectionMetadata(raw){let source=isRecord2(raw)?raw:{},out={};for(let key of CONSUMER_SAFE_DETECTION_KEYS){if(!(key in source))continue;let value=source[key],accepted=acceptKey(key,value);accepted!==DROP&&(out[key]=accepted)}let dropped=0;for(let key of OPERATOR_INTERNAL_KEYS)key in source&&(dropped+=1);/* @__PURE__ */
|
|
102
|
-
return Object.freeze({metadata:/* @__PURE__ */Object.freeze(out),droppedOperatorKeys:dropped})}var DROP=/* @__PURE__ */Symbol("drop");function acceptKey(key,value){if(BOOLEAN_KEYS.has(key))return typeof value=="boolean"?value:DROP;if(CONFIDENCE_KEYS.has(key))return isUnitConfidence(value)?value:DROP;if(key==="risk_tier")return typeof value=="string"&&RISK_TIER_VALUES.has(value)?value:DROP;if(key==="confidence_tier")return typeof value=="string"&&CONFIDENCE_TIER_VALUES.has(value)?value:DROP;if(typeof value!="string")return DROP;let limit=STRING_LIMITS[key]??256;return value.length>limit?value.slice(0,limit):value}function isUnitConfidence(value){return typeof value=="number"&&Number.isFinite(value)&&value>=0&&value<=1}function parseInterpretation(raw){if(!isRecord2(raw))return null;let summary=asString(raw.summary),disclaimer=asString(raw.disclaimer),recommendations=asStringList(raw.recommendations??raw.recommendation);return summary===null&&disclaimer===null&&recommendations.length===0?null:/* @__PURE__ */Object.freeze({summary:summary??"",recommendations:/* @__PURE__ */Object.freeze(recommendations),disclaimer:disclaimer??""})}function locateDetectionMetadata(body){if(!isRecord2(body))return{};if(isRecord2(body.metadata))return body.metadata;let detections=body.detections;if(Array.isArray(detections)&&detections.length>0){let first=detections[0];if(isRecord2(first)&&isRecord2(first.metadata))return first.metadata;if(isRecord2(first))return first}return body}function locateInterpretation(body){return isRecord2(body)?isRecord2(body.interpretation)?body.interpretation:body:null}function
|
|
101
|
+
return Object.freeze({mode:mode,maxDurationSeconds:maxDurationSeconds})}function isCaptureAvailable(camera){return camera!=null&&camera.isAvailable===true}var defaultTimers=/* @__PURE__ */Object.freeze({setTimeout:(handler,ms)=>setTimeout(handler,ms),clearTimeout:handle=>clearTimeout(handle),now:()=>Date.now()});function delayAbortable2(ms,signal,timers){return new Promise(resolve=>{if(signal.aborted){resolve();return}let holder={handle:void 0},done=()=>{timers.clearTimeout(holder.handle),signal.removeEventListener("abort",done),resolve()};holder.handle=timers.setTimeout(done,ms),signal.addEventListener("abort",done,{once:true})})}function mergeSignals2(a,b){if(!b)return a;let ctrl=new AbortController;if(a.aborted||b.aborted)return ctrl.abort(),ctrl.signal;let onAbort=()=>ctrl.abort();return a.addEventListener("abort",onAbort,{once:true}),b.addEventListener("abort",onAbort,{once:true}),ctrl.signal}var MediaStore=class{constructor(initial){this.listeners=/* @__PURE__ */new Set;this.epoch=0;this.inFlight=null;this.snapshot=/* @__PURE__ */Object.freeze({...initial})}subscribe(listener){return this.listeners.add(listener),()=>{this.listeners.delete(listener)}}getSnapshot(){return this.snapshot}patch(partial){this.snapshot=/* @__PURE__ */Object.freeze({...this.snapshot,...partial});for(let listener of this.listeners)listener()}beginOperation(external){this.inFlight?.abort();let ctrl=new AbortController;this.inFlight=ctrl;let epoch=this.epoch;return{signal:external?mergeSignals2(ctrl.signal,external):ctrl.signal,epoch:epoch,settle:()=>{this.inFlight===ctrl&&(this.inFlight=null)}}}alive(epoch){return epoch===this.epoch}rescope(){this.epoch+=1,this.inFlight?.abort(),this.inFlight=null}dispose(){this.epoch+=1,this.inFlight?.abort(),this.inFlight=null,this.listeners.clear()}};function hasLoneSurrogate(value){for(let i=0;i<value.length;i+=1){let code=value.charCodeAt(i);if(code>=55296&&code<=56319){let low=value.charCodeAt(i+1);if(!(low>=56320&&low<=57343))return true;i+=1}else if(code>=56320&&code<=57343)return true}return false}function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}var CONSUMER_SAFE_DETECTION_KEYS=/* @__PURE__ */Object.freeze(["primary_label","primary_confidence","subtype_label","subtype_display","subtype_confidence","risk_tier","confidence_tier","copy_short","disease_name","disease_framing","model_version","skin_v2","eye_v2","llm_checkup"]),OPERATOR_INTERNAL_KEYS=/* @__PURE__ */Object.freeze(["decision_audit","decision_thresholds","per_class_auroc","ood_layers","gate1_score","possible_conditions","top_class"]),BOOLEAN_KEYS=/* @__PURE__ */new Set(["skin_v2","eye_v2","llm_checkup"]),CONFIDENCE_KEYS=/* @__PURE__ */new Set(["primary_confidence","subtype_confidence"]),RISK_TIER_VALUES=/* @__PURE__ */new Set(["low_risk","concern","uncertain"]),CONFIDENCE_TIER_VALUES=/* @__PURE__ */new Set(["possible","probable"]),STRING_LIMITS=/* @__PURE__ */Object.freeze({primary_label:64,subtype_label:64,subtype_display:128,copy_short:512,disease_name:128,disease_framing:512,model_version:64});function projectDetectionMetadata(raw){let source=isRecord2(raw)?raw:{},out={};for(let key of CONSUMER_SAFE_DETECTION_KEYS){if(!(key in source))continue;let value=source[key],accepted=acceptKey(key,value);accepted!==DROP&&(out[key]=accepted)}let dropped=0;for(let key of OPERATOR_INTERNAL_KEYS)key in source&&(dropped+=1);/* @__PURE__ */
|
|
102
|
+
return Object.freeze({metadata:/* @__PURE__ */Object.freeze(out),droppedOperatorKeys:dropped})}var DROP=/* @__PURE__ */Symbol("drop");function acceptKey(key,value){if(BOOLEAN_KEYS.has(key))return typeof value=="boolean"?value:DROP;if(CONFIDENCE_KEYS.has(key))return isUnitConfidence(value)?value:DROP;if(key==="risk_tier")return typeof value=="string"&&RISK_TIER_VALUES.has(value)?value:DROP;if(key==="confidence_tier")return typeof value=="string"&&CONFIDENCE_TIER_VALUES.has(value)?value:DROP;if(typeof value!="string")return DROP;let limit=STRING_LIMITS[key]??256;return value.length>limit?value.slice(0,limit):value}function isUnitConfidence(value){return typeof value=="number"&&Number.isFinite(value)&&value>=0&&value<=1}function parseInterpretation(raw){if(!isRecord2(raw))return null;let summary=asString(raw.summary),disclaimer=asString(raw.disclaimer),recommendations=asStringList(raw.recommendations??raw.recommendation);return summary===null&&disclaimer===null&&recommendations.length===0?null:/* @__PURE__ */Object.freeze({summary:summary??"",recommendations:/* @__PURE__ */Object.freeze(recommendations),disclaimer:disclaimer??""})}function locateDetectionMetadata(body){if(!isRecord2(body))return{};if(isRecord2(body.metadata))return body.metadata;let detections=body.detections;if(Array.isArray(detections)&&detections.length>0){let first=detections[0];if(isRecord2(first)&&isRecord2(first.metadata))return first.metadata;if(isRecord2(first))return first}return body}function locateInterpretation(body){return isRecord2(body)?isRecord2(body.interpretation)?body.interpretation:body:null}function asString(value){return typeof value=="string"&&value.length>0?value:null}function asStringList(value){return typeof value=="string"?value.length>0?[value]:[]:Array.isArray(value)?value.filter(entry=>typeof entry=="string"&&entry.length>0):[]}function asUnitNumber(value){return isUnitConfidence(value)?value:null}function asFiniteNumber(value){return typeof value=="number"&&Number.isFinite(value)?value:null}var ENDPOINTS=/* @__PURE__ */Object.freeze({initiate:"/widget/v1/uploads/initiate",precheck:"/widget/v1/photo/precheck",photoAnalyze:"/widget/v1/photo/analyze",videoAnalyze:"/widget/v1/video/analyze",job:jobId=>hasLoneSurrogate(jobId)?null:`/widget/v1/analysis/jobs/${encodeURIComponent(jobId)}`});async function initiateUpload(funnel,params){let body={purpose:params.purpose,content_type:params.contentType};params.byteSize!==null&&(body.byte_size=params.byteSize);let req={method:"POST",path:ENDPOINTS.initiate,body:body,...params.signal?{signal:params.signal}:{}},res=await funnel.send("media.initiateUpload",req);if(!res.ok)return err(res.error);let policy=parsePresigned(res.value);return policy===null?err(makeEverfurError("mediaUploadFailed",{retryable:false})):ok(policy)}function parsePresigned(raw){if(!isRecord2(raw))return null;let url=asString(raw.url),s3Key=asString(raw.s3_key);if(url===null||s3Key===null)return null;let fieldsRaw=raw.fields,fields={};if(isRecord2(fieldsRaw))for(let[key,value]of Object.entries(fieldsRaw))typeof value=="string"&&(fields[key]=value);/* @__PURE__ */
|
|
103
103
|
return Object.freeze({url:url,fields:/* @__PURE__ */Object.freeze(fields),s3Key:s3Key,expiresAt:asFiniteNumber(raw.expires_at)})}async function stageUpload(upload,source,policy,idempotencyKey,signal){try{return await upload.presignedPut(fileHandleFromMedia(source),{target:policy,idempotencyKey:idempotencyKey,...signal?{signal:signal}:{}}),ok(void 0)}catch{return err(makeEverfurError("mediaUploadFailed",{retryable:false}))}}async function submitAnalyze(funnel,path,body,detectGate,signal){let req={method:"POST",path:path,body:body,...signal?{signal:signal}:{}},res=await funnel.send("media.analyze",req);if(res.ok){let job=parseAsyncJob(res.value);return job!==null?{kind:"async",job:job}:{kind:"sync",body:res.value}}let gate=detectGate(res.error.httpStatus,res.error);return gate!==null?{kind:"gate",gate:gate}:{kind:"error",error:res.error}}function parseAsyncJob(raw){if(!isRecord2(raw))return null;let jobId=asString(raw.job_id);if(jobId===null)return null;let status=asString(raw.status);return status!==null&&isTerminalStatus(status)?null:/* @__PURE__ */Object.freeze({jobId:jobId,estimatedSeconds:asFiniteNumber(raw.estimated_completion_seconds)})}var POLL_FIRST_DELAY_MS=2e3,POLL_MAX_DELAY_MS=5e3,POLL_BUDGET_MS=9e4;async function pollJob(funnel,jobId,deps){let{timers:timers,signal:signal,alive:alive}=deps,start=timers.now(),budget=Math.max(POLL_BUDGET_MS,(deps.estimatedSeconds??0)*1e3),delay=POLL_FIRST_DELAY_MS;for(;;){if(signal.aborted||!alive())return{kind:"aborted"};if(await delayAbortable2(delay,signal,timers),signal.aborted||!alive())return{kind:"aborted"};if(timers.now()-start>budget)return{kind:"timeout"};let path=ENDPOINTS.job(jobId);if(path===null)return{kind:"notFound"};let res=await funnel.send("media.pollJob",{method:"GET",path:path,...signal?{signal:signal}:{}},{maxAttempts:1});if(signal.aborted||!alive())return{kind:"aborted"};if(!res.ok){if(res.error.httpStatus===404)return{kind:"notFound"};delay=Math.min(POLL_MAX_DELAY_MS,delay+1e3);continue}let status=jobStatusOf(res.value);if(status==="COMPLETED")return{kind:"complete",body:res.value};if(status==="FAILED")return{kind:"failed",error:jobFailureError(res.value)};delay=Math.min(POLL_MAX_DELAY_MS,delay+1e3)}}function jobStatusOf(body){return isRecord2(body)?(asString(body.status)??"PROCESSING").toUpperCase():"PROCESSING"}function isTerminalStatus(status){let upper=status.toUpperCase();return upper==="COMPLETED"||upper==="FAILED"}function jobFailureError(body){let wire=isRecord2(body)?asString(body.error)??asString(body.error_code):null;return makeEverfurError("internalError",{retryable:false,...wire?{wireMessage:wire}:{}})}function detectNoGate(){return null}function analyzeBody(s3Key,extra){let body={s3_key:s3Key};return extra.type!==void 0&&(body.type=extra.type),extra.petRef!=null&&(body.pet_id=extra.petRef),extra.precheckToken!=null&&(body.precheck_token=extra.precheckToken),body}function createVideoController(deps){return new VideoController(deps)}var VideoController=class extends MediaStore{constructor(deps){super({status:"idle",job:null,result:null,error:null,isCaptureAvailable:isCaptureAvailable(deps.camera),progress:0}),this.funnel=deps.funnel??createRequestFunnel({auth:deps.auth,...deps.errorPolicy?{errorPolicy:deps.errorPolicy}:{}}),this.camera=deps.camera,this.upload=deps.upload,this.defaultPetRef=deps.petRef??null,this.telemetry=deps.telemetry??noopTelemetry,this.timers=deps.timers??defaultTimers,this.makeIdempotencyKey=deps.makeIdempotencyKey??defaultIdempotencyFactory()}async capture(opts){if(!isCaptureAvailable(this.camera))return err(makeEverfurError("unknown",{retryable:false}));let source;try{source=await this.camera.capture(captureOptionsFor("video",15))}catch{return this.snapshot.status!=="idle"&&this.patch({status:"idle",progress:0}),err(makeEverfurError("unknown",{retryable:false}))}return this.submit(source,opts?.petRef!==void 0?{petRef:opts.petRef}:void 0)}async submit(source,opts){let op=this.beginOperation(opts?.signal),petRef=opts?.petRef??this.defaultPetRef,idempotencyKey=this.makeIdempotencyKey(),startedAt=this.timers.now();this.patch({status:"uploading",progress:0,error:null,result:null,job:null});try{let initiated=await initiateUpload(this.funnel,{purpose:"gait_video",contentType:source.mimeType,byteSize:mediaByteSize(source),signal:op.signal});if(op.signal.aborted||!this.alive(op.epoch))return abortedResult();if(!initiated.ok)return this.fail(op,initiated.error);let staged=await stageUpload(this.upload,source,initiated.value,idempotencyKey,op.signal);if(op.signal.aborted||!this.alive(op.epoch))return abortedResult();if(!staged.ok)return this.telemetry.track("analysis.upload",{capability:"video",purpose:"gait_video",outcome:"failed"}),this.fail(op,staged.error);this.patch({progress:1}),this.telemetry.track("analysis.upload",{capability:"video",purpose:"gait_video",byteSize:mediaByteSize(source)??0,durationMs:mediaDurationMs(source)??0,outcome:"ok"}),this.patch({status:"analyzing"});let outcome=await submitAnalyze(this.funnel,ENDPOINTS.videoAnalyze,analyzeBody(initiated.value.s3Key,{petRef:petRef}),detectNoGate,op.signal);if(op.signal.aborted||!this.alive(op.epoch))return abortedResult();if(outcome.kind==="error")return this.fail(op,outcome.error);if(outcome.kind==="gate")return this.fail(op,makeEverfurError("unknown",{retryable:!1}));if(outcome.kind==="sync"){let jobId=resultIdOf(outcome.body)??"";return this.complete(op,outcome.body,jobId,startedAt)}let job=outcome.job;this.patch({job:{id:job.jobId,state:"processing"}});let poll=await pollJob(this.funnel,job.jobId,{timers:this.timers,signal:op.signal,alive:()=>this.alive(op.epoch),estimatedSeconds:job.estimatedSeconds});if(op.signal.aborted||!this.alive(op.epoch))return abortedResult();switch(poll.kind){case"aborted":return abortedResult();case"complete":return this.complete(op,poll.body,job.jobId,startedAt);case"failed":return this.fail(op,poll.error);case"timeout":return this.fail(op,makeEverfurError("streamTimeout",{retryable:!0}));case"notFound":return this.patch({job:null}),this.fail(op,makeEverfurError("conversationNotFound",{retryable:!1,httpStatus:404}));default:return this.fail(op,makeEverfurError("internalError",{retryable:!1}))}}finally{op.settle()}}cancel(){this.inFlight?.abort(),this.inFlight=null,(this.snapshot.status==="uploading"||this.snapshot.status==="analyzing")&&this.patch({status:"idle",progress:0})}complete(op,body,jobId,startedAt){if(!this.alive(op.epoch))return abortedResult();let mapped=mapVideoResult(body,jobId);return mapped.droppedOperatorKeys>0&&this.telemetry.track("analysis.metadata_leak_guard",{droppedKeyCount:mapped.droppedOperatorKeys}),this.telemetry.track("analysis.quality_gate",{usable:mapped.result.quality.usable,reasons:mapped.result.quality.reasons}),this.patch({status:"complete",progress:1,result:mapped.result,error:null,job:{id:jobId,state:"complete"}}),this.telemetry.track("analysis.result",{capability:"video",modelVersion:mapped.result.modelVersion??"",timeToResultMs:this.timers.now()-startedAt}),ok(jobId)}fail(op,error){return this.alive(op.epoch)?(this.patch({status:"error",error:error,progress:0}),this.telemetry.trackExpectedFailure("analysis.error",{code:error.code,...error.httpStatus!==void 0?{httpStatus:error.httpStatus}:{}}),err(error)):abortedResult()}};function mapVideoResult(body,jobId){let projection=projectDetectionMetadata(locateDetectionMetadata(body)),interpretation=parseInterpretation(locateInterpretation(body)),modelVersion=asString(projection.metadata.model_version)??(isRecord2(body)?asString(body.model_version):null);return{result:/* @__PURE__ */Object.freeze({jobId:jobId,analysisType:"gait",detections:parseVideoDetections(body),interpretation:interpretation,modelVersion:modelVersion,quality:parseQuality(body)}),droppedOperatorKeys:projection.droppedOperatorKeys}}function parseVideoDetections(body){let raw=isRecord2(body)?body.detections:null;if(!Array.isArray(raw))/* @__PURE__ */return Object.freeze([]);let out=[];for(let entry of raw){if(!isRecord2(entry))continue;let label=asString(entry.label)??asString(entry.name);label!==null&&out.push(
|
|
104
104
|
/* @__PURE__ */Object.freeze({label:label,confidence:asUnitNumber(entry.confidence)??0,timestampMs:asFiniteNumber(entry.timestamp_ms??entry.timestamp),durationMs:asFiniteNumber(entry.duration_ms??entry.duration)}))}/* @__PURE__ */
|
|
105
105
|
return Object.freeze(out)}function parseQuality(body){let raw=isRecord2(body)?body.quality:null;if(!isRecord2(raw))/* @__PURE__ */return Object.freeze({usable:true,reasons:/* @__PURE__ */Object.freeze([])});let usable=raw.usable;/* @__PURE__ */
|
package/dist/video/index.js
CHANGED
|
@@ -98,8 +98,8 @@ return Object.freeze({ok:false,error:error})}var EverfurConfigError=class _Everf
|
|
|
98
98
|
return Object.freeze({kind:"error",terminal:true,code:fields.code,retryable:fields.retryable,wireMessage:fields.wireMessage,synthesized:fields.synthesized,lastEventId:fields.lastEventId,serverRequestId:null})}function mintFailedError(cause,refusal){let message=cause instanceof Error?cause.message:typeof cause=="string"?cause:null;return makeEverfurError("authRejected",{retryable:false,...refusal?.wireCode?{wireCode:refusal.wireCode}:{},...refusal?.requestId?{requestId:refusal.requestId}:{},...message?{wireMessage:message}:{},...cause!=null?{raw:cause}:{}})}function authHeaders(auth){let headers={};return auth.mode==="personalized"?headers.authorization=`Bearer ${auth.token}`:headers["x-everfur-partner-key"]=auth.publishableKey,auth.userRef&&(headers["x-everfur-user-ref"]=auth.userRef),auth.sessionId&&(headers["x-everfur-session-id"]=auth.sessionId),headers}function withAuthHeaders(req,auth){return{...req,headers:{...stripAuthHeaders(req.headers),...authHeaders(auth)}}}function stripAuthHeaders(headers){if(!headers)return{};let out={};for(let[key,value]of Object.entries(headers)){let lower=key.toLowerCase();lower==="authorization"||lower==="x-everfur-partner-key"||(out[key]=value)}return out}async function authedSend(req,ctx){if(ctx.mode==="anonymous")return ctx.transport.request(withAuthHeaders(req,{mode:"anonymous",publishableKey:ctx.publishableKey,userRef:ctx.userRef,...ctx.sessionId?{sessionId:ctx.sessionId}:{}}));let token;try{token=await ctx.identity.currentToken()}catch(cause){return ctx.identity.reportRejected?.(),err(mintFailedError(cause))}let first=await ctx.transport.request(withAuthHeaders(req,{mode:"personalized",token:token,userRef:ctx.userRef,...ctx.sessionId?{sessionId:ctx.sessionId}:{}}));if(first.ok||first.error.httpStatus!==401)return first;let refreshed;try{refreshed=await ctx.identity.currentToken({forceRefresh:!0})}catch(cause){return ctx.identity.reportRejected?.(),err(mintFailedError(cause,{wireCode:wireCodeOf(first.error.raw),requestId:first.error.requestId}))}let retry=await ctx.transport.request(withAuthHeaders(req,{mode:"personalized",token:refreshed,userRef:ctx.userRef,...ctx.sessionId?{sessionId:ctx.sessionId}:{}}));return!retry.ok&&retry.error.httpStatus===401?(ctx.identity.reportRejected?.(),err(refusedAfterRemintError(retry.error))):retry}function refusedAfterRemintError(refusal){let raw=refusal.raw,wireCode=wireCodeOf(raw);return makeEverfurError("authRejected",{retryable:false,...refusal.httpStatus!==void 0?{httpStatus:refusal.httpStatus}:{},...refusal.requestId?{requestId:refusal.requestId}:{},...wireCode?{wireCode:wireCode}:{},...refusal.reasonCode?{reasonCode:refusal.reasonCode}:{},...refusal.wireMessage?{wireMessage:refusal.wireMessage}:{},...raw!=null?{raw:raw}:{}})}function wireCodeOf(body){if(typeof body!="object"||body===null)return null;let b=body,code=(typeof b.error=="object"&&b.error!==null?b.error.code:void 0)??b.code;return typeof code=="string"&&code.length>0?code:null}function networkError(cause){return makeEverfurError("internalError",{retryable:true,wireMessage:describeCause(cause)})}function describeCause(cause){return cause instanceof Error?cause.message:typeof cause=="string"?cause:"network request failed"}var FUNNEL_UNARY_TIMEOUT_MS=3e4,RETRY_OVERRIDE_MAX_MS=BACKOFF_CAP_MS*2,IDEMPOTENCY_HEADER="idempotency-key",MUTATING_METHODS=/* @__PURE__ */new Set(["POST","PUT","PATCH","DELETE"]),NOOP_OBSERVER=/* @__PURE__ */Object.freeze({onEvent(){}}),defaultFunnelTimers=/* @__PURE__ */Object.freeze({setTimeout:(handler,ms)=>setTimeout(handler,ms),clearTimeout:handle=>clearTimeout(handle),now:()=>Date.now()});function seededIdempotencyKey(seed){let safe=seed.trim().replace(/[^A-Za-z0-9_.:-]/g,"-");return safe.length===0?null:`efs_${safe}`.slice(0,128)}function createRequestFunnel(deps){let observer=deps.observer??NOOP_OBSERVER,timers=deps.timers??defaultFunnelTimers,rng=deps.rng??Math.random,sleep=deps.sleep??((ms,signal)=>delayAbortable(ms,timers,signal)),ceiling=deps.maxAttempts??MAX_RETRY_ATTEMPTS,timeoutMs=deps.unaryTimeoutMs??FUNNEL_UNARY_TIMEOUT_MS,mintKey=deps.newIdempotencyKey??defaultIdempotencyKeyFactory(),emit=event=>{try{observer.onEvent(event)}catch{}};async function send(call,req,opts){let perCallMaxAttempts=opts?.maxAttempts,maxAttempts=Math.max(1,perCallMaxAttempts??ceiling),idempotent=opts?.idempotent??MUTATING_METHODS.has(req.method),seeded=opts?.idempotencyKey===void 0?null:seededIdempotencyKey(opts.idempotencyKey),idempotencyKey=idempotent?seeded??mintKey():null,base=assembleHeaders(req,idempotencyKey),attempt=0;for(;;){let stamp=extra=>/* @__PURE__ */Object.freeze({call:call,method:req.method,path:req.path,attempt:attempt,...idempotencyKey?{idempotencyKey:idempotencyKey}:{},...extra});emit(stamp({phase:"attempt"}));let deadline=boundedSignal(timeoutMs,timers),merged=mergeSignals(deadline.signal,req.signal),settled;try{settled=await authedSend({...base,signal:merged.signal},deps.auth)}catch(cause){settled=err(networkError(cause))}finally{merged.dispose(),deadline.cancel()}if(settled.ok)return emit(stamp({phase:"settled",ok:true,reason:"ok"})),settled;let error=settled.error,decision=decideRetry(error,attempt,{maxAttempts:maxAttempts,rng:rng,now:timers.now(),aborted:req.signal?.aborted===true,...perCallMaxAttempts!==void 0?{perCallMaxAttempts:perCallMaxAttempts}:{},...deps.errorPolicy!==void 0?{policy:deps.errorPolicy}:{}}),settledEvent={ok:false,code:error.code,reason:decision.reason,...error.httpStatus!==void 0?{httpStatus:error.httpStatus}:{},...error.requestId!==void 0?{requestId:error.requestId}:{}};if(!decision.retry)return emit(stamp({phase:"settled",...settledEvent})),err(error);if(emit(stamp({phase:"retry",...settledEvent,delayMs:decision.delayMs})),await sleep(decision.delayMs,req.signal),req.signal?.aborted===true)return emit(stamp({phase:"settled",...settledEvent,reason:"aborted"})),err(error);attempt+=1}}async function authorize(req){return withAuthHeaders(req,await resolveDeviceAuth(deps.auth))}async function*stream(call,req,signal){emit(
|
|
99
99
|
/* @__PURE__ */Object.freeze({call:call,phase:"stream.open",method:req.method,path:req.path,attempt:0}));try{yield*deps.auth.transport.stream(req,signal)}catch{yield errorFrame({code:"internal_error",retryable:true,wireMessage:null,synthesized:true,lastEventId:null})}}/* @__PURE__ */
|
|
100
100
|
return Object.freeze({send:send,authorize:authorize,stream:stream})}function assembleHeaders(req,idempotencyKey){let headers={};for(let[key,value]of Object.entries(req.headers??{}))key.toLowerCase()!==IDEMPOTENCY_HEADER&&(headers[key]=value);return idempotencyKey!==null&&(headers["Idempotency-Key"]=idempotencyKey),{...req,headers:headers}}function defaultIdempotencyKeyFactory(){let counter=0;return()=>`efk_${Date.now().toString(36)}_${(counter++).toString(36)}_${Math.random().toString(36).slice(2,12)}`}var POLICY_MAX_ATTEMPTS_CAP=10;function decideRetry(error,attempt,ctx){if(ctx.aborted)return{retry:false,reason:"aborted"};let throttle=throttleKind(error);if(throttle==="quota")return{retry:false,reason:"daily-quota-exhausted"};if(throttle!=="burst"&&!isAutoRetryable(error.code))return{retry:false,reason:"terminal-code"};let reason=throttle==="burst"?"burst-throttle":"retryable-code";if((()=>{if(ctx.policy===void 0)return false;try{return!ctx.policy.shouldRetry(error.code,attempt)}catch{return false}})())return{retry:false,reason:"terminal-code"};let policyCeiling=()=>{if(ctx.policy===void 0)return null;let raw;try{raw=ctx.policy.maxAttempts(error.code)}catch{return null}return typeof raw!="number"||!Number.isFinite(raw)?null:Math.max(1,Math.min(POLICY_MAX_ATTEMPTS_CAP,Math.floor(raw)))},ceiling=ctx.perCallMaxAttempts??policyCeiling()??ctx.maxAttempts;if(attempt+1>=ceiling)return{retry:false,reason:"attempts-exhausted"};let override=retryOverrideMs(error,ctx.now);return override!==null?override>RETRY_OVERRIDE_MAX_MS?{retry:false,reason:"server-reset-beyond-budget"}:{retry:true,reason:reason,delayMs:override}:{retry:true,reason:reason,delayMs:backoffDelayMs(attempt,ctx.rng)}}function throttleKind(error){let code=error.code==="unknown"?fromWire(rawWireCode(error.raw)):error.code;return code==="quotaExceeded"?"quota":code==="rateLimited"||error.httpStatus===429?"burst":null}function retryOverrideMs(error,now){let at=findResetsAt(error.raw);if(at!==null){let delta=at-now;return delta>0?delta:0}let wait=findRetryAfterSeconds(error.raw);return wait===null?null:Math.round(wait*1e3)}function findRetryAfterSeconds(raw){for(let scope of candidateScopes(raw)){let value=scope.retry_after_seconds;if(typeof value=="number"&&Number.isFinite(value)&&value>=0)return value}return null}function findResetsAt(raw){for(let scope of candidateScopes(raw)){let value=scope.resets_at,parsed=parseInstantMs(value);if(parsed!==null)return parsed}return null}function candidateScopes(raw){if(!isRecord(raw))return[];let out=[raw];for(let nested of["error","detail"]){let value=raw[nested];isRecord(value)&&out.push(value)}return out}function parseInstantMs(value){if(typeof value=="number"&&Number.isFinite(value))return value<1e11?Math.round(value*1e3):Math.round(value);if(typeof value=="string"&&value.trim().length>0){let parsed=Date.parse(value);return Number.isFinite(parsed)?parsed:null}return null}function rawWireCode(raw){for(let scope of candidateScopes(raw)){let code=scope.code;if(typeof code=="string"&&code.length>0)return code}return null}function isRecord(value){return typeof value=="object"&&value!==null}async function resolveDeviceAuth(auth){return auth.mode==="anonymous"?{mode:"anonymous",publishableKey:auth.publishableKey,userRef:auth.userRef,...auth.sessionId?{sessionId:auth.sessionId}:{}}:{mode:"personalized",token:await auth.identity.currentToken(),userRef:auth.userRef,...auth.sessionId?{sessionId:auth.sessionId}:{}}}function boundedSignal(ms,timers){let ctrl=new AbortController,handle=timers.setTimeout(()=>ctrl.abort(),ms);return{signal:ctrl.signal,cancel:()=>timers.clearTimeout(handle)}}function mergeSignals(deadline,caller){let noop=()=>{};if(!caller)return{signal:deadline,dispose:noop};let ctrl=new AbortController;if(deadline.aborted||caller.aborted)return ctrl.abort(),{signal:ctrl.signal,dispose:noop};let onAbort=()=>ctrl.abort();return deadline.addEventListener("abort",onAbort,{once:true}),caller.addEventListener("abort",onAbort,{once:true}),{signal:ctrl.signal,dispose:()=>{deadline.removeEventListener("abort",onAbort),caller.removeEventListener("abort",onAbort)}}}function delayAbortable(ms,timers,signal){return ms<=0||signal?.aborted===true?Promise.resolve():new Promise(resolve=>{let handle=timers.setTimeout(()=>{signal?.removeEventListener("abort",onAbort),resolve()},ms),onAbort=()=>{timers.clearTimeout(handle),resolve()};signal?.addEventListener("abort",onAbort,{once:true})})}var noopTelemetry=/* @__PURE__ */Object.freeze({track(){},trackExpectedFailure(){}});function fileHandleFromMedia(source){let handle={uri:source.uri,mimeType:source.mimeType},size=mediaByteSize(source);return size!==null&&(handle.sizeBytes=size),/* @__PURE__ */Object.freeze(handle)}function mediaByteSize(source){let candidate=source.byteSize??source.sizeBytes;return typeof candidate=="number"&&Number.isFinite(candidate)&&candidate>=0?candidate:null}function mediaDurationMs(source){let seconds=source.durationSeconds;return typeof seconds=="number"&&Number.isFinite(seconds)&&seconds>=0?Math.round(seconds*1e3):null}function captureOptionsFor(mode,maxDurationSeconds){/* @__PURE__ */
|
|
101
|
-
return Object.freeze({mode:mode,maxDurationSeconds:maxDurationSeconds})}function isCaptureAvailable(camera){return camera!=null&&camera.isAvailable===true}var defaultTimers=/* @__PURE__ */Object.freeze({setTimeout:(handler,ms)=>setTimeout(handler,ms),clearTimeout:handle=>clearTimeout(handle),now:()=>Date.now()});function delayAbortable2(ms,signal,timers){return new Promise(resolve=>{if(signal.aborted){resolve();return}let holder={handle:void 0},done=()=>{timers.clearTimeout(holder.handle),signal.removeEventListener("abort",done),resolve()};holder.handle=timers.setTimeout(done,ms),signal.addEventListener("abort",done,{once:true})})}function mergeSignals2(a,b){if(!b)return a;let ctrl=new AbortController;if(a.aborted||b.aborted)return ctrl.abort(),ctrl.signal;let onAbort=()=>ctrl.abort();return a.addEventListener("abort",onAbort,{once:true}),b.addEventListener("abort",onAbort,{once:true}),ctrl.signal}var MediaStore=class{constructor(initial){this.listeners=/* @__PURE__ */new Set;this.epoch=0;this.inFlight=null;this.snapshot=/* @__PURE__ */Object.freeze({...initial})}subscribe(listener){return this.listeners.add(listener),()=>{this.listeners.delete(listener)}}getSnapshot(){return this.snapshot}patch(partial){this.snapshot=/* @__PURE__ */Object.freeze({...this.snapshot,...partial});for(let listener of this.listeners)listener()}beginOperation(external){this.inFlight?.abort();let ctrl=new AbortController;this.inFlight=ctrl;let epoch=this.epoch;return{signal:external?mergeSignals2(ctrl.signal,external):ctrl.signal,epoch:epoch,settle:()=>{this.inFlight===ctrl&&(this.inFlight=null)}}}alive(epoch){return epoch===this.epoch}rescope(){this.epoch+=1,this.inFlight?.abort(),this.inFlight=null}dispose(){this.epoch+=1,this.inFlight?.abort(),this.inFlight=null,this.listeners.clear()}};function hasLoneSurrogate(value){for(let i=0;i<value.length;i+=1){let code=value.charCodeAt(i);if(code>=55296&&code<=56319){let low=value.charCodeAt(i+1);if(!(low>=56320&&low<=57343))return true;i+=1}else if(code>=56320&&code<=57343)return true}return false}var CONSUMER_SAFE_DETECTION_KEYS=/* @__PURE__ */Object.freeze(["primary_label","primary_confidence","subtype_label","subtype_display","subtype_confidence","risk_tier","confidence_tier","copy_short","disease_name","disease_framing","model_version","skin_v2","eye_v2","llm_checkup"]),OPERATOR_INTERNAL_KEYS=/* @__PURE__ */Object.freeze(["decision_audit","decision_thresholds","per_class_auroc","ood_layers","gate1_score","possible_conditions","top_class"]),BOOLEAN_KEYS=/* @__PURE__ */new Set(["skin_v2","eye_v2","llm_checkup"]),CONFIDENCE_KEYS=/* @__PURE__ */new Set(["primary_confidence","subtype_confidence"]),RISK_TIER_VALUES=/* @__PURE__ */new Set(["low_risk","concern","uncertain"]),CONFIDENCE_TIER_VALUES=/* @__PURE__ */new Set(["possible","probable"]),STRING_LIMITS=/* @__PURE__ */Object.freeze({primary_label:64,subtype_label:64,subtype_display:128,copy_short:512,disease_name:128,disease_framing:512,model_version:64});function projectDetectionMetadata(raw){let source=isRecord2(raw)?raw:{},out={};for(let key of CONSUMER_SAFE_DETECTION_KEYS){if(!(key in source))continue;let value=source[key],accepted=acceptKey(key,value);accepted!==DROP&&(out[key]=accepted)}let dropped=0;for(let key of OPERATOR_INTERNAL_KEYS)key in source&&(dropped+=1);/* @__PURE__ */
|
|
102
|
-
return Object.freeze({metadata:/* @__PURE__ */Object.freeze(out),droppedOperatorKeys:dropped})}var DROP=/* @__PURE__ */Symbol("drop");function acceptKey(key,value){if(BOOLEAN_KEYS.has(key))return typeof value=="boolean"?value:DROP;if(CONFIDENCE_KEYS.has(key))return isUnitConfidence(value)?value:DROP;if(key==="risk_tier")return typeof value=="string"&&RISK_TIER_VALUES.has(value)?value:DROP;if(key==="confidence_tier")return typeof value=="string"&&CONFIDENCE_TIER_VALUES.has(value)?value:DROP;if(typeof value!="string")return DROP;let limit=STRING_LIMITS[key]??256;return value.length>limit?value.slice(0,limit):value}function isUnitConfidence(value){return typeof value=="number"&&Number.isFinite(value)&&value>=0&&value<=1}function parseInterpretation(raw){if(!isRecord2(raw))return null;let summary=asString(raw.summary),disclaimer=asString(raw.disclaimer),recommendations=asStringList(raw.recommendations??raw.recommendation);return summary===null&&disclaimer===null&&recommendations.length===0?null:/* @__PURE__ */Object.freeze({summary:summary??"",recommendations:/* @__PURE__ */Object.freeze(recommendations),disclaimer:disclaimer??""})}function locateDetectionMetadata(body){if(!isRecord2(body))return{};if(isRecord2(body.metadata))return body.metadata;let detections=body.detections;if(Array.isArray(detections)&&detections.length>0){let first=detections[0];if(isRecord2(first)&&isRecord2(first.metadata))return first.metadata;if(isRecord2(first))return first}return body}function locateInterpretation(body){return isRecord2(body)?isRecord2(body.interpretation)?body.interpretation:body:null}function
|
|
101
|
+
return Object.freeze({mode:mode,maxDurationSeconds:maxDurationSeconds})}function isCaptureAvailable(camera){return camera!=null&&camera.isAvailable===true}var defaultTimers=/* @__PURE__ */Object.freeze({setTimeout:(handler,ms)=>setTimeout(handler,ms),clearTimeout:handle=>clearTimeout(handle),now:()=>Date.now()});function delayAbortable2(ms,signal,timers){return new Promise(resolve=>{if(signal.aborted){resolve();return}let holder={handle:void 0},done=()=>{timers.clearTimeout(holder.handle),signal.removeEventListener("abort",done),resolve()};holder.handle=timers.setTimeout(done,ms),signal.addEventListener("abort",done,{once:true})})}function mergeSignals2(a,b){if(!b)return a;let ctrl=new AbortController;if(a.aborted||b.aborted)return ctrl.abort(),ctrl.signal;let onAbort=()=>ctrl.abort();return a.addEventListener("abort",onAbort,{once:true}),b.addEventListener("abort",onAbort,{once:true}),ctrl.signal}var MediaStore=class{constructor(initial){this.listeners=/* @__PURE__ */new Set;this.epoch=0;this.inFlight=null;this.snapshot=/* @__PURE__ */Object.freeze({...initial})}subscribe(listener){return this.listeners.add(listener),()=>{this.listeners.delete(listener)}}getSnapshot(){return this.snapshot}patch(partial){this.snapshot=/* @__PURE__ */Object.freeze({...this.snapshot,...partial});for(let listener of this.listeners)listener()}beginOperation(external){this.inFlight?.abort();let ctrl=new AbortController;this.inFlight=ctrl;let epoch=this.epoch;return{signal:external?mergeSignals2(ctrl.signal,external):ctrl.signal,epoch:epoch,settle:()=>{this.inFlight===ctrl&&(this.inFlight=null)}}}alive(epoch){return epoch===this.epoch}rescope(){this.epoch+=1,this.inFlight?.abort(),this.inFlight=null}dispose(){this.epoch+=1,this.inFlight?.abort(),this.inFlight=null,this.listeners.clear()}};function hasLoneSurrogate(value){for(let i=0;i<value.length;i+=1){let code=value.charCodeAt(i);if(code>=55296&&code<=56319){let low=value.charCodeAt(i+1);if(!(low>=56320&&low<=57343))return true;i+=1}else if(code>=56320&&code<=57343)return true}return false}function isRecord2(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}var CONSUMER_SAFE_DETECTION_KEYS=/* @__PURE__ */Object.freeze(["primary_label","primary_confidence","subtype_label","subtype_display","subtype_confidence","risk_tier","confidence_tier","copy_short","disease_name","disease_framing","model_version","skin_v2","eye_v2","llm_checkup"]),OPERATOR_INTERNAL_KEYS=/* @__PURE__ */Object.freeze(["decision_audit","decision_thresholds","per_class_auroc","ood_layers","gate1_score","possible_conditions","top_class"]),BOOLEAN_KEYS=/* @__PURE__ */new Set(["skin_v2","eye_v2","llm_checkup"]),CONFIDENCE_KEYS=/* @__PURE__ */new Set(["primary_confidence","subtype_confidence"]),RISK_TIER_VALUES=/* @__PURE__ */new Set(["low_risk","concern","uncertain"]),CONFIDENCE_TIER_VALUES=/* @__PURE__ */new Set(["possible","probable"]),STRING_LIMITS=/* @__PURE__ */Object.freeze({primary_label:64,subtype_label:64,subtype_display:128,copy_short:512,disease_name:128,disease_framing:512,model_version:64});function projectDetectionMetadata(raw){let source=isRecord2(raw)?raw:{},out={};for(let key of CONSUMER_SAFE_DETECTION_KEYS){if(!(key in source))continue;let value=source[key],accepted=acceptKey(key,value);accepted!==DROP&&(out[key]=accepted)}let dropped=0;for(let key of OPERATOR_INTERNAL_KEYS)key in source&&(dropped+=1);/* @__PURE__ */
|
|
102
|
+
return Object.freeze({metadata:/* @__PURE__ */Object.freeze(out),droppedOperatorKeys:dropped})}var DROP=/* @__PURE__ */Symbol("drop");function acceptKey(key,value){if(BOOLEAN_KEYS.has(key))return typeof value=="boolean"?value:DROP;if(CONFIDENCE_KEYS.has(key))return isUnitConfidence(value)?value:DROP;if(key==="risk_tier")return typeof value=="string"&&RISK_TIER_VALUES.has(value)?value:DROP;if(key==="confidence_tier")return typeof value=="string"&&CONFIDENCE_TIER_VALUES.has(value)?value:DROP;if(typeof value!="string")return DROP;let limit=STRING_LIMITS[key]??256;return value.length>limit?value.slice(0,limit):value}function isUnitConfidence(value){return typeof value=="number"&&Number.isFinite(value)&&value>=0&&value<=1}function parseInterpretation(raw){if(!isRecord2(raw))return null;let summary=asString(raw.summary),disclaimer=asString(raw.disclaimer),recommendations=asStringList(raw.recommendations??raw.recommendation);return summary===null&&disclaimer===null&&recommendations.length===0?null:/* @__PURE__ */Object.freeze({summary:summary??"",recommendations:/* @__PURE__ */Object.freeze(recommendations),disclaimer:disclaimer??""})}function locateDetectionMetadata(body){if(!isRecord2(body))return{};if(isRecord2(body.metadata))return body.metadata;let detections=body.detections;if(Array.isArray(detections)&&detections.length>0){let first=detections[0];if(isRecord2(first)&&isRecord2(first.metadata))return first.metadata;if(isRecord2(first))return first}return body}function locateInterpretation(body){return isRecord2(body)?isRecord2(body.interpretation)?body.interpretation:body:null}function asString(value){return typeof value=="string"&&value.length>0?value:null}function asStringList(value){return typeof value=="string"?value.length>0?[value]:[]:Array.isArray(value)?value.filter(entry=>typeof entry=="string"&&entry.length>0):[]}function asUnitNumber(value){return isUnitConfidence(value)?value:null}function asFiniteNumber(value){return typeof value=="number"&&Number.isFinite(value)?value:null}var ENDPOINTS=/* @__PURE__ */Object.freeze({initiate:"/widget/v1/uploads/initiate",precheck:"/widget/v1/photo/precheck",photoAnalyze:"/widget/v1/photo/analyze",videoAnalyze:"/widget/v1/video/analyze",job:jobId=>hasLoneSurrogate(jobId)?null:`/widget/v1/analysis/jobs/${encodeURIComponent(jobId)}`});async function initiateUpload(funnel,params){let body={purpose:params.purpose,content_type:params.contentType};params.byteSize!==null&&(body.byte_size=params.byteSize);let req={method:"POST",path:ENDPOINTS.initiate,body:body,...params.signal?{signal:params.signal}:{}},res=await funnel.send("media.initiateUpload",req);if(!res.ok)return err(res.error);let policy=parsePresigned(res.value);return policy===null?err(makeEverfurError("mediaUploadFailed",{retryable:false})):ok(policy)}function parsePresigned(raw){if(!isRecord2(raw))return null;let url=asString(raw.url),s3Key=asString(raw.s3_key);if(url===null||s3Key===null)return null;let fieldsRaw=raw.fields,fields={};if(isRecord2(fieldsRaw))for(let[key,value]of Object.entries(fieldsRaw))typeof value=="string"&&(fields[key]=value);/* @__PURE__ */
|
|
103
103
|
return Object.freeze({url:url,fields:/* @__PURE__ */Object.freeze(fields),s3Key:s3Key,expiresAt:asFiniteNumber(raw.expires_at)})}async function stageUpload(upload,source,policy,idempotencyKey,signal){try{return await upload.presignedPut(fileHandleFromMedia(source),{target:policy,idempotencyKey:idempotencyKey,...signal?{signal:signal}:{}}),ok(void 0)}catch{return err(makeEverfurError("mediaUploadFailed",{retryable:false}))}}async function submitAnalyze(funnel,path,body,detectGate,signal){let req={method:"POST",path:path,body:body,...signal?{signal:signal}:{}},res=await funnel.send("media.analyze",req);if(res.ok){let job=parseAsyncJob(res.value);return job!==null?{kind:"async",job:job}:{kind:"sync",body:res.value}}let gate=detectGate(res.error.httpStatus,res.error);return gate!==null?{kind:"gate",gate:gate}:{kind:"error",error:res.error}}function parseAsyncJob(raw){if(!isRecord2(raw))return null;let jobId=asString(raw.job_id);if(jobId===null)return null;let status=asString(raw.status);return status!==null&&isTerminalStatus(status)?null:/* @__PURE__ */Object.freeze({jobId:jobId,estimatedSeconds:asFiniteNumber(raw.estimated_completion_seconds)})}var POLL_FIRST_DELAY_MS=2e3,POLL_MAX_DELAY_MS=5e3,POLL_BUDGET_MS=9e4;async function pollJob(funnel,jobId,deps){let{timers:timers,signal:signal,alive:alive}=deps,start=timers.now(),budget=Math.max(POLL_BUDGET_MS,(deps.estimatedSeconds??0)*1e3),delay=POLL_FIRST_DELAY_MS;for(;;){if(signal.aborted||!alive())return{kind:"aborted"};if(await delayAbortable2(delay,signal,timers),signal.aborted||!alive())return{kind:"aborted"};if(timers.now()-start>budget)return{kind:"timeout"};let path=ENDPOINTS.job(jobId);if(path===null)return{kind:"notFound"};let res=await funnel.send("media.pollJob",{method:"GET",path:path,...signal?{signal:signal}:{}},{maxAttempts:1});if(signal.aborted||!alive())return{kind:"aborted"};if(!res.ok){if(res.error.httpStatus===404)return{kind:"notFound"};delay=Math.min(POLL_MAX_DELAY_MS,delay+1e3);continue}let status=jobStatusOf(res.value);if(status==="COMPLETED")return{kind:"complete",body:res.value};if(status==="FAILED")return{kind:"failed",error:jobFailureError(res.value)};delay=Math.min(POLL_MAX_DELAY_MS,delay+1e3)}}function jobStatusOf(body){return isRecord2(body)?(asString(body.status)??"PROCESSING").toUpperCase():"PROCESSING"}function isTerminalStatus(status){let upper=status.toUpperCase();return upper==="COMPLETED"||upper==="FAILED"}function jobFailureError(body){let wire=isRecord2(body)?asString(body.error)??asString(body.error_code):null;return makeEverfurError("internalError",{retryable:false,...wire?{wireMessage:wire}:{}})}function detectNoGate(){return null}function analyzeBody(s3Key,extra){let body={s3_key:s3Key};return extra.type!==void 0&&(body.type=extra.type),extra.petRef!=null&&(body.pet_id=extra.petRef),extra.precheckToken!=null&&(body.precheck_token=extra.precheckToken),body}function createVideoController(deps){return new VideoController(deps)}var VideoController=class extends MediaStore{constructor(deps){super({status:"idle",job:null,result:null,error:null,isCaptureAvailable:isCaptureAvailable(deps.camera),progress:0}),this.funnel=deps.funnel??createRequestFunnel({auth:deps.auth,...deps.errorPolicy?{errorPolicy:deps.errorPolicy}:{}}),this.camera=deps.camera,this.upload=deps.upload,this.defaultPetRef=deps.petRef??null,this.telemetry=deps.telemetry??noopTelemetry,this.timers=deps.timers??defaultTimers,this.makeIdempotencyKey=deps.makeIdempotencyKey??defaultIdempotencyFactory()}async capture(opts){if(!isCaptureAvailable(this.camera))return err(makeEverfurError("unknown",{retryable:false}));let source;try{source=await this.camera.capture(captureOptionsFor("video",15))}catch{return this.snapshot.status!=="idle"&&this.patch({status:"idle",progress:0}),err(makeEverfurError("unknown",{retryable:false}))}return this.submit(source,opts?.petRef!==void 0?{petRef:opts.petRef}:void 0)}async submit(source,opts){let op=this.beginOperation(opts?.signal),petRef=opts?.petRef??this.defaultPetRef,idempotencyKey=this.makeIdempotencyKey(),startedAt=this.timers.now();this.patch({status:"uploading",progress:0,error:null,result:null,job:null});try{let initiated=await initiateUpload(this.funnel,{purpose:"gait_video",contentType:source.mimeType,byteSize:mediaByteSize(source),signal:op.signal});if(op.signal.aborted||!this.alive(op.epoch))return abortedResult();if(!initiated.ok)return this.fail(op,initiated.error);let staged=await stageUpload(this.upload,source,initiated.value,idempotencyKey,op.signal);if(op.signal.aborted||!this.alive(op.epoch))return abortedResult();if(!staged.ok)return this.telemetry.track("analysis.upload",{capability:"video",purpose:"gait_video",outcome:"failed"}),this.fail(op,staged.error);this.patch({progress:1}),this.telemetry.track("analysis.upload",{capability:"video",purpose:"gait_video",byteSize:mediaByteSize(source)??0,durationMs:mediaDurationMs(source)??0,outcome:"ok"}),this.patch({status:"analyzing"});let outcome=await submitAnalyze(this.funnel,ENDPOINTS.videoAnalyze,analyzeBody(initiated.value.s3Key,{petRef:petRef}),detectNoGate,op.signal);if(op.signal.aborted||!this.alive(op.epoch))return abortedResult();if(outcome.kind==="error")return this.fail(op,outcome.error);if(outcome.kind==="gate")return this.fail(op,makeEverfurError("unknown",{retryable:!1}));if(outcome.kind==="sync"){let jobId=resultIdOf(outcome.body)??"";return this.complete(op,outcome.body,jobId,startedAt)}let job=outcome.job;this.patch({job:{id:job.jobId,state:"processing"}});let poll=await pollJob(this.funnel,job.jobId,{timers:this.timers,signal:op.signal,alive:()=>this.alive(op.epoch),estimatedSeconds:job.estimatedSeconds});if(op.signal.aborted||!this.alive(op.epoch))return abortedResult();switch(poll.kind){case"aborted":return abortedResult();case"complete":return this.complete(op,poll.body,job.jobId,startedAt);case"failed":return this.fail(op,poll.error);case"timeout":return this.fail(op,makeEverfurError("streamTimeout",{retryable:!0}));case"notFound":return this.patch({job:null}),this.fail(op,makeEverfurError("conversationNotFound",{retryable:!1,httpStatus:404}));default:return this.fail(op,makeEverfurError("internalError",{retryable:!1}))}}finally{op.settle()}}cancel(){this.inFlight?.abort(),this.inFlight=null,(this.snapshot.status==="uploading"||this.snapshot.status==="analyzing")&&this.patch({status:"idle",progress:0})}complete(op,body,jobId,startedAt){if(!this.alive(op.epoch))return abortedResult();let mapped=mapVideoResult(body,jobId);return mapped.droppedOperatorKeys>0&&this.telemetry.track("analysis.metadata_leak_guard",{droppedKeyCount:mapped.droppedOperatorKeys}),this.telemetry.track("analysis.quality_gate",{usable:mapped.result.quality.usable,reasons:mapped.result.quality.reasons}),this.patch({status:"complete",progress:1,result:mapped.result,error:null,job:{id:jobId,state:"complete"}}),this.telemetry.track("analysis.result",{capability:"video",modelVersion:mapped.result.modelVersion??"",timeToResultMs:this.timers.now()-startedAt}),ok(jobId)}fail(op,error){return this.alive(op.epoch)?(this.patch({status:"error",error:error,progress:0}),this.telemetry.trackExpectedFailure("analysis.error",{code:error.code,...error.httpStatus!==void 0?{httpStatus:error.httpStatus}:{}}),err(error)):abortedResult()}};function mapVideoResult(body,jobId){let projection=projectDetectionMetadata(locateDetectionMetadata(body)),interpretation=parseInterpretation(locateInterpretation(body)),modelVersion=asString(projection.metadata.model_version)??(isRecord2(body)?asString(body.model_version):null);return{result:/* @__PURE__ */Object.freeze({jobId:jobId,analysisType:"gait",detections:parseVideoDetections(body),interpretation:interpretation,modelVersion:modelVersion,quality:parseQuality(body)}),droppedOperatorKeys:projection.droppedOperatorKeys}}function parseVideoDetections(body){let raw=isRecord2(body)?body.detections:null;if(!Array.isArray(raw))/* @__PURE__ */return Object.freeze([]);let out=[];for(let entry of raw){if(!isRecord2(entry))continue;let label=asString(entry.label)??asString(entry.name);label!==null&&out.push(
|
|
104
104
|
/* @__PURE__ */Object.freeze({label:label,confidence:asUnitNumber(entry.confidence)??0,timestampMs:asFiniteNumber(entry.timestamp_ms??entry.timestamp),durationMs:asFiniteNumber(entry.duration_ms??entry.duration)}))}/* @__PURE__ */
|
|
105
105
|
return Object.freeze(out)}function parseQuality(body){let raw=isRecord2(body)?body.quality:null;if(!isRecord2(raw))/* @__PURE__ */return Object.freeze({usable:true,reasons:/* @__PURE__ */Object.freeze([])});let usable=raw.usable;/* @__PURE__ */
|