@everfur/sdk 0.1.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +634 -0
- package/README.md +58 -23
- package/consent/package.json +8 -0
- package/dist/Chat-DPUD6dnc.d.cts +128 -0
- package/dist/Chat-DwAC2vhB.d.ts +128 -0
- package/dist/DepthViews-DNEM96Se.d.ts +16 -0
- package/dist/DepthViews-DP0R-DhB.d.cts +19 -0
- package/dist/DepthViews-D_3hl4xk.d.ts +19 -0
- package/dist/DepthViews-DbFhR4Du.d.cts +16 -0
- package/dist/ErrorPolicyPort-CNf4uQZP.d.cts +22 -0
- package/dist/ErrorPolicyPort-CwbfmxzJ.d.ts +22 -0
- package/dist/{EverfurResult-D92-uL82.d.cts → EverfurResult-DN9pL2Ab.d.cts} +11 -10
- package/dist/{EverfurResult-D92-uL82.d.ts → EverfurResult-DN9pL2Ab.d.ts} +11 -10
- package/dist/{PhotoController-BItt5M7u.d.cts → PhotoController-3l7MT9jA.d.cts} +1 -1
- package/dist/{PhotoController-D8zMTdcW.d.ts → PhotoController-vzY5bfY_.d.ts} +1 -1
- package/dist/animations/index.cjs +1 -1997
- package/dist/animations/index.d.cts +35 -35
- package/dist/animations/index.d.ts +35 -35
- package/dist/animations/index.js +1 -1972
- package/dist/attachments-5NeobOCd.d.ts +256 -0
- package/dist/attachments-Bw3iMQgu.d.ts +146 -0
- package/dist/attachments-CQgFrEQ7.d.cts +146 -0
- package/dist/attachments-D8T5re7e.d.cts +256 -0
- package/dist/casesRepository-ClLv6qMl.d.ts +188 -0
- package/dist/casesRepository-DHwtGRYY.d.cts +188 -0
- package/dist/chat/index.cjs +1 -1170
- package/dist/chat/index.d.cts +31 -53
- package/dist/chat/index.d.ts +31 -53
- package/dist/chat/index.js +1 -1167
- package/dist/client/index.cjs +9 -2315
- package/dist/client/index.d.cts +77 -15
- package/dist/client/index.d.ts +77 -15
- package/dist/client/index.js +9 -2215
- package/dist/{config-CiJ0PVBB.d.ts → config-CzTZGlfF.d.cts} +63 -25
- package/dist/{config-BSjBdxrZ.d.cts → config-DW60uRb9.d.ts} +63 -25
- package/dist/consent/index.cjs +1 -0
- package/dist/consent/index.d.cts +33 -0
- package/dist/consent/index.d.ts +33 -0
- package/dist/consent/index.js +1 -0
- package/dist/context-DXhqHlPU.d.ts +159 -0
- package/dist/context-XvTzq1tE.d.cts +159 -0
- package/dist/copy-Mjoo91aS.d.ts +198 -0
- package/dist/copy-bKDNigLb.d.cts +198 -0
- package/dist/core/index.cjs +13 -3178
- package/dist/core/index.d.cts +58 -12
- package/dist/core/index.d.ts +58 -12
- package/dist/core/index.js +13 -3166
- package/dist/depth-CErXCU8J.d.cts +502 -0
- package/dist/depth-DjDcJ6kH.d.ts +502 -0
- package/dist/entitlementRepository-DKdXFgTo.d.cts +698 -0
- package/dist/entitlementRepository-DSbzuyAW.d.ts +698 -0
- package/dist/{identity-DK9zORrG.d.ts → identity-BMx2SUOM.d.ts} +19 -6
- package/dist/{identity-Brl-lDd6.d.cts → identity-DI4eVx9S.d.cts} +19 -6
- package/dist/{ids-CJ1S6adf.d.cts → ids-B2GAAifq.d.cts} +1 -1
- package/dist/{ids-CJ1S6adf.d.ts → ids-B2GAAifq.d.ts} +1 -1
- package/dist/index.cjs +12 -4494
- package/dist/index.d.cts +29 -121
- package/dist/index.d.ts +29 -121
- package/dist/index.js +12 -4470
- package/dist/models-B-Uh2LTf.d.ts +214 -0
- package/dist/models-D2EUxPZY.d.cts +214 -0
- package/dist/notifications/index.cjs +2 -0
- package/dist/notifications/index.d.cts +17 -0
- package/dist/notifications/index.d.ts +17 -0
- package/dist/notifications/index.js +2 -0
- package/dist/pets-CtQdRpWo.d.ts +92 -0
- package/dist/pets-aB8q0JyX.d.cts +92 -0
- package/dist/photo/index.cjs +1 -2189
- package/dist/photo/index.d.cts +6 -6
- package/dist/photo/index.d.ts +6 -6
- package/dist/photo/index.js +1 -2186
- package/dist/ports-BN6RHF9W.d.cts +48 -0
- package/dist/ports-BN6RHF9W.d.ts +48 -0
- package/dist/ports-DEBzEhbp.d.cts +386 -0
- package/dist/ports-DMolTRzU.d.ts +386 -0
- package/dist/profile-CSs1wlXT.d.cts +93 -0
- package/dist/profile-CSs1wlXT.d.ts +93 -0
- package/dist/records/depth/index.cjs +2 -0
- package/dist/records/depth/index.d.cts +13 -0
- package/dist/records/depth/index.d.ts +13 -0
- package/dist/records/depth/index.js +2 -0
- package/dist/records/index.cjs +3 -2839
- package/dist/records/index.d.cts +137 -203
- package/dist/records/index.d.ts +137 -203
- package/dist/records/index.js +3 -2833
- package/dist/requestFunnel-CjW7uDuA.d.ts +87 -0
- package/dist/requestFunnel-L-BQfi0z.d.cts +87 -0
- package/dist/{resolve-Dq_4_agU.d.ts → resolve-D4Ywz5OS.d.cts} +10 -4
- package/dist/{resolve-Dq_4_agU.d.cts → resolve-D4Ywz5OS.d.ts} +10 -4
- package/dist/{runtime-Bvr8yqXm.d.cts → runtime-B8s-_hv8.d.cts} +121 -59
- package/dist/{runtime-BIYzf9cK.d.ts → runtime-BR9ysG0J.d.ts} +121 -59
- package/dist/server/events/index.cjs +2 -0
- package/dist/server/events/index.d.cts +550 -0
- package/dist/server/events/index.d.ts +550 -0
- package/dist/server/events/index.js +2 -0
- package/dist/server/index.cjs +2 -533
- package/dist/server/index.d.cts +73 -18
- package/dist/server/index.d.ts +73 -18
- package/dist/server/index.js +2 -530
- package/dist/species-BXAIMh7I.d.cts +9 -0
- package/dist/species-BXAIMh7I.d.ts +9 -0
- package/dist/televet/index.cjs +1 -0
- package/dist/televet/index.d.cts +60 -0
- package/dist/televet/index.d.ts +60 -0
- package/dist/televet/index.js +1 -0
- package/dist/testing/index.cjs +5 -823
- package/dist/testing/index.d.cts +17 -3
- package/dist/testing/index.d.ts +17 -3
- package/dist/testing/index.js +5 -820
- package/dist/testing/rn/index.cjs +1 -449
- package/dist/testing/rn/index.d.cts +17 -29
- package/dist/testing/rn/index.d.ts +17 -29
- package/dist/testing/rn/index.js +1 -444
- package/dist/testing/web/index.cjs +1 -0
- package/dist/testing/web/index.d.cts +131 -0
- package/dist/testing/web/index.d.ts +131 -0
- package/dist/testing/web/index.js +1 -0
- package/dist/timelineRows-CaohZzXS.d.cts +19 -0
- package/dist/timelineRows-DZed6dAM.d.ts +19 -0
- package/dist/typeStyle-0TydiZ1w.d.cts +19 -0
- package/dist/typeStyle-CWMsoe6b.d.ts +19 -0
- package/dist/uploadTransport-D0M0T4hN.d.ts +38 -0
- package/dist/uploadTransport-DKJHs3Yj.d.cts +38 -0
- package/dist/useRecordsDepth-BHBzJ76R.d.cts +237 -0
- package/dist/useRecordsDepth-BU-OhzH6.d.ts +237 -0
- package/dist/useVetVisit-Bc84hWUU.d.cts +187 -0
- package/dist/useVetVisit-CjmMa896.d.ts +187 -0
- package/dist/video/index.cjs +1 -1941
- package/dist/video/index.d.cts +4 -4
- package/dist/video/index.d.ts +4 -4
- package/dist/video/index.js +1 -1938
- package/dist/view-C3qPIXGX.d.cts +310 -0
- package/dist/view-DtSPYpKa.d.ts +310 -0
- package/dist/visitIntent-D7_yVp1I.d.cts +8 -0
- package/dist/visitIntent-D7_yVp1I.d.ts +8 -0
- package/dist/web/consent/index.cjs +1 -0
- package/dist/web/consent/index.d.cts +34 -0
- package/dist/web/consent/index.d.ts +34 -0
- package/dist/web/consent/index.js +1 -0
- package/dist/web/index.cjs +14 -0
- package/dist/web/index.d.cts +217 -0
- package/dist/web/index.d.ts +217 -0
- package/dist/web/index.js +14 -0
- package/dist/web/notifications/index.cjs +2 -0
- package/dist/web/notifications/index.d.cts +213 -0
- package/dist/web/notifications/index.d.ts +213 -0
- package/dist/web/notifications/index.js +2 -0
- package/dist/web/records/depth/index.cjs +2 -0
- package/dist/web/records/depth/index.d.cts +12 -0
- package/dist/web/records/depth/index.d.ts +12 -0
- package/dist/web/records/depth/index.js +2 -0
- package/dist/web/records/index.cjs +4 -0
- package/dist/web/records/index.d.cts +194 -0
- package/dist/web/records/index.d.ts +194 -0
- package/dist/web/records/index.js +4 -0
- package/dist/web/televet/index.cjs +1 -0
- package/dist/web/televet/index.d.cts +50 -0
- package/dist/web/televet/index.d.ts +50 -0
- package/dist/web/televet/index.js +1 -0
- package/notifications/package.json +8 -0
- package/package.json +197 -9
- package/records/depth/package.json +8 -0
- package/server/events/device-blocked.cjs +15 -0
- package/server/events/package.json +9 -0
- package/televet/package.json +8 -0
- package/testing/web/native-blocked.cjs +12 -0
- package/testing/web/package.json +8 -0
- package/web/consent/native-blocked.cjs +12 -0
- package/web/consent/package.json +8 -0
- package/web/native-blocked.cjs +12 -0
- package/web/notifications/native-blocked.cjs +12 -0
- package/web/notifications/package.json +8 -0
- package/web/package.json +8 -0
- package/web/records/depth/native-blocked.cjs +12 -0
- package/web/records/depth/package.json +8 -0
- package/web/records/native-blocked.cjs +12 -0
- package/web/records/package.json +8 -0
- package/web/televet/native-blocked.cjs +12 -0
- package/web/televet/package.json +8 -0
- package/dist/ChatController-CKdBvPj2.d.ts +0 -146
- package/dist/ChatController-CpUMvvZf.d.cts +0 -146
- package/dist/FilePort-BabWrv7I.d.cts +0 -22
- package/dist/FilePort-BabWrv7I.d.ts +0 -22
- package/dist/petsRepository-BEGb97M9.d.cts +0 -326
- package/dist/petsRepository-Bu18r2kK.d.ts +0 -326
- package/dist/requestFunnel-DuUH-kAe.d.cts +0 -28
- package/dist/requestFunnel-dio5OmR9.d.ts +0 -28
package/dist/core/index.js
CHANGED
|
@@ -1,3166 +1,13 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
return Object.freeze(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
var EverfurConfigError = class _EverfurConfigError extends Error {
|
|
13
|
-
|
|
14
|
-
super(message);
|
|
15
|
-
this.name = "EverfurConfigError";
|
|
16
|
-
this.kind = kind;
|
|
17
|
-
Object.setPrototypeOf(this, _EverfurConfigError.prototype);
|
|
18
|
-
}
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
// src/core/ports/SecureStorePort.ts
|
|
22
|
-
var NULL_SECURE_STORE = Object.freeze({
|
|
23
|
-
isAvailable: false,
|
|
24
|
-
async getSecret() {
|
|
25
|
-
return null;
|
|
26
|
-
},
|
|
27
|
-
async setSecret() {
|
|
28
|
-
throw new EverfurConfigError(
|
|
29
|
-
"not-initialized",
|
|
30
|
-
"EF_NO_SECURE_STORE: token persistence requires an explicit SecureStorePort"
|
|
31
|
-
);
|
|
32
|
-
},
|
|
33
|
-
async deleteSecret() {
|
|
34
|
-
}
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
// src/core/ports/TelemetryPort.ts
|
|
38
|
-
var noopTelemetry = Object.freeze({
|
|
39
|
-
track() {
|
|
40
|
-
},
|
|
41
|
-
trackExpectedFailure() {
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
var CONTRACT_RETRYABILITY = Object.freeze([
|
|
45
|
-
Object.freeze({ wireCode: "AccessDeniedException", envelope: "http_envelope", httpStatus: 403, retryable: false }),
|
|
46
|
-
Object.freeze({ wireCode: "AuthorizationException", envelope: "http_envelope", httpStatus: 401, retryable: false }),
|
|
47
|
-
Object.freeze({ wireCode: "ConflictException", envelope: "http_envelope", httpStatus: 409, retryable: true }),
|
|
48
|
-
Object.freeze({ wireCode: "DAILY_QUOTA_EXCEEDED", envelope: "http_envelope", httpStatus: 429, retryable: true }),
|
|
49
|
-
Object.freeze({ wireCode: "IDEMPOTENCY_KEY_IN_FLIGHT", envelope: "http_envelope", httpStatus: 409, retryable: true }),
|
|
50
|
-
Object.freeze({ wireCode: "IDEMPOTENCY_KEY_REUSED_DIFFERENT_REQUEST", envelope: "http_envelope", httpStatus: 409, retryable: false }),
|
|
51
|
-
Object.freeze({ wireCode: "InternalFailureException", envelope: "http_envelope", httpStatus: 500, retryable: true }),
|
|
52
|
-
Object.freeze({ wireCode: "NotImplementedException", envelope: "http_envelope", httpStatus: 501, retryable: false }),
|
|
53
|
-
Object.freeze({ wireCode: "PaymentRequiredException", envelope: "http_envelope", httpStatus: 402, retryable: false }),
|
|
54
|
-
Object.freeze({ wireCode: "ResourceNotFoundException", envelope: "http_envelope", httpStatus: 404, retryable: false }),
|
|
55
|
-
Object.freeze({ wireCode: "ServiceUnavailableException", envelope: "http_envelope", httpStatus: 503, retryable: true }),
|
|
56
|
-
Object.freeze({ wireCode: "TIER_UPGRADE_REQUIRED", envelope: "http_envelope", httpStatus: 402, retryable: false }),
|
|
57
|
-
Object.freeze({ wireCode: "ThrottlingException", envelope: "http_envelope", httpStatus: 429, retryable: true }),
|
|
58
|
-
Object.freeze({ wireCode: "ValidationException", envelope: "http_envelope", httpStatus: 400, retryable: false }),
|
|
59
|
-
Object.freeze({ wireCode: "accessDenied", envelope: "http_envelope", httpStatus: 403, retryable: false }),
|
|
60
|
-
Object.freeze({ wireCode: "authExpired", envelope: "http_envelope", httpStatus: 401, retryable: true }),
|
|
61
|
-
Object.freeze({ wireCode: "internal_error", envelope: "sse_frame", httpStatus: 200, retryable: false }),
|
|
62
|
-
Object.freeze({ wireCode: "invalidRequest", envelope: "http_envelope", httpStatus: 400, retryable: false }),
|
|
63
|
-
Object.freeze({ wireCode: "not_found", envelope: "sse_frame", httpStatus: 200, retryable: false }),
|
|
64
|
-
Object.freeze({ wireCode: "session_required", envelope: "http_envelope", httpStatus: 403, retryable: false }),
|
|
65
|
-
Object.freeze({ wireCode: "timeout", envelope: "sse_frame", httpStatus: 200, retryable: true }),
|
|
66
|
-
Object.freeze({ wireCode: "unavailable", envelope: "http_envelope", httpStatus: 503, retryable: true })
|
|
67
|
-
]);
|
|
68
|
-
Object.freeze(
|
|
69
|
-
CONTRACT_RETRYABILITY.map((row) => row.wireCode)
|
|
70
|
-
);
|
|
71
|
-
|
|
72
|
-
// src/client/errors/contract.ts
|
|
73
|
-
var NORMALIZED_FOLD = Object.freeze({
|
|
74
|
-
// the default status-mapped envelope
|
|
75
|
-
ValidationException: "validationFailed",
|
|
76
|
-
AuthorizationException: "authRejected",
|
|
77
|
-
PaymentRequiredException: "paymentRequired",
|
|
78
|
-
AccessDeniedException: "accessDenied",
|
|
79
|
-
ResourceNotFoundException: "resourceNotFound",
|
|
80
|
-
ConflictException: "conflict",
|
|
81
|
-
ThrottlingException: "rateLimited",
|
|
82
|
-
InternalFailureException: "internalError",
|
|
83
|
-
NotImplementedException: "notImplemented",
|
|
84
|
-
ServiceUnavailableException: "serviceUnavailable",
|
|
85
|
-
// dict-detail codes on the widget surface
|
|
86
|
-
authExpired: "authExpired",
|
|
87
|
-
unavailable: "serviceUnavailable",
|
|
88
|
-
session_required: "sessionRequired",
|
|
89
|
-
accessDenied: "accessDenied",
|
|
90
|
-
invalidRequest: "sdkUpdateRequired",
|
|
91
|
-
// typed codes
|
|
92
|
-
IDEMPOTENCY_KEY_IN_FLIGHT: "idempotencyInFlight",
|
|
93
|
-
IDEMPOTENCY_KEY_REUSED_DIFFERENT_REQUEST: "idempotencyConflict",
|
|
94
|
-
DAILY_QUOTA_EXCEEDED: "quotaExceeded",
|
|
95
|
-
TIER_UPGRADE_REQUIRED: "paymentRequired",
|
|
96
|
-
// SSE error frames
|
|
97
|
-
not_found: "conversationNotFound",
|
|
98
|
-
timeout: "streamTimeout",
|
|
99
|
-
internal_error: "internalError"
|
|
100
|
-
});
|
|
101
|
-
var CONTRACT_ERROR_ROWS = Object.freeze(
|
|
102
|
-
CONTRACT_RETRYABILITY.map(
|
|
103
|
-
(generated) => Object.freeze({
|
|
104
|
-
wireCode: generated.wireCode,
|
|
105
|
-
envelope: generated.envelope,
|
|
106
|
-
retryable: generated.retryable,
|
|
107
|
-
normalized: NORMALIZED_FOLD[generated.wireCode]
|
|
108
|
-
})
|
|
109
|
-
)
|
|
110
|
-
);
|
|
111
|
-
var BY_UPPER = new Map(
|
|
112
|
-
CONTRACT_ERROR_ROWS.map((r) => [r.wireCode.toUpperCase(), r])
|
|
113
|
-
);
|
|
114
|
-
function contractErrorFor(wireCode) {
|
|
115
|
-
if (typeof wireCode !== "string") return void 0;
|
|
116
|
-
const key = wireCode.trim().toUpperCase();
|
|
117
|
-
return key.length > 0 ? BY_UPPER.get(key) : void 0;
|
|
118
|
-
}
|
|
119
|
-
var CATEGORY_OF = Object.freeze({
|
|
120
|
-
// the caller's sign-in state is wrong and a credential change is the remedy
|
|
121
|
-
authExpired: "authentication",
|
|
122
|
-
authRejected: "authentication",
|
|
123
|
-
sessionRequired: "authentication",
|
|
124
|
-
// signed in, correctly identified, and still not allowed
|
|
125
|
-
accessDenied: "authorization",
|
|
126
|
-
// a plan gate, not a permission failure: the remedy is commercial
|
|
127
|
-
paymentRequired: "entitlement",
|
|
128
|
-
// slow down / come back later
|
|
129
|
-
quotaExceeded: "rateLimit",
|
|
130
|
-
rateLimited: "rateLimit",
|
|
131
|
-
// the request itself was wrong; retrying it unchanged can never succeed
|
|
132
|
-
validationFailed: "invalidRequest",
|
|
133
|
-
sdkUpdateRequired: "invalidRequest",
|
|
134
|
-
// the target is gone, hidden, or was never visible to this caller
|
|
135
|
-
conversationNotFound: "notFound",
|
|
136
|
-
petNotFound: "notFound",
|
|
137
|
-
resourceNotFound: "notFound",
|
|
138
|
-
// something else already holds the thing
|
|
139
|
-
conflict: "conflict",
|
|
140
|
-
idempotencyConflict: "conflict",
|
|
141
|
-
idempotencyInFlight: "conflict",
|
|
142
|
-
// the pipe, not the request: timeouts, drops, a briefly unreachable dependency
|
|
143
|
-
streamTimeout: "connection",
|
|
144
|
-
streamIncomplete: "connection",
|
|
145
|
-
upstreamLlmTimeout: "connection",
|
|
146
|
-
serviceUnavailable: "connection",
|
|
147
|
-
// the server admits fault
|
|
148
|
-
internalError: "server",
|
|
149
|
-
notImplemented: "server",
|
|
150
|
-
mediaUploadFailed: "media",
|
|
151
|
-
moderationBlocked: "policy",
|
|
152
|
-
unknown: "unknown"
|
|
153
|
-
});
|
|
154
|
-
function categoryFor(code) {
|
|
155
|
-
return CATEGORY_OF[code];
|
|
156
|
-
}
|
|
157
|
-
function fromWire(wire) {
|
|
158
|
-
const contractRow = contractErrorFor(wire);
|
|
159
|
-
if (contractRow) return contractRow.normalized;
|
|
160
|
-
const upper = (wire ?? "").trim().toUpperCase();
|
|
161
|
-
const canonical = upper.replace(/[^A-Z0-9]/g, "");
|
|
162
|
-
if (canonical === "AUTHREJECTED") return "authRejected";
|
|
163
|
-
if (upper.startsWith("AUTH")) return "authExpired";
|
|
164
|
-
switch (canonical) {
|
|
165
|
-
case "DAILYQUOTAEXCEEDED":
|
|
166
|
-
case "QUOTAEXCEEDED":
|
|
167
|
-
return "quotaExceeded";
|
|
168
|
-
case "RATELIMITED":
|
|
169
|
-
case "TOOMANYREQUESTS":
|
|
170
|
-
return "rateLimited";
|
|
171
|
-
case "IDEMPOTENCYKEYCONFLICT":
|
|
172
|
-
case "IDEMPOTENCYCONFLICT":
|
|
173
|
-
return "idempotencyConflict";
|
|
174
|
-
case "ACCESSDENIED":
|
|
175
|
-
case "FORBIDDEN":
|
|
176
|
-
return "accessDenied";
|
|
177
|
-
case "NOTFOUND":
|
|
178
|
-
case "CONVERSATIONNOTFOUND":
|
|
179
|
-
return "conversationNotFound";
|
|
180
|
-
case "PETNOTFOUND":
|
|
181
|
-
return "petNotFound";
|
|
182
|
-
case "TIMEOUT":
|
|
183
|
-
case "STREAMTIMEOUT":
|
|
184
|
-
return "streamTimeout";
|
|
185
|
-
// Analysis-domain deterministic 400s (NON-retryable). Additive per SPEC-00 §3.1 / SPEC-11b §2.6:
|
|
186
|
-
// fold to a NON-retried target so the SDK never retries a permanently-failing bad-input request.
|
|
187
|
-
// (Comment above the group so the empty fall-through cases stay lint-clean under no-fallthrough.)
|
|
188
|
-
case "MEDIAUPLOADFAILED":
|
|
189
|
-
case "UNRECOGNIZEDVIDEOFORMAT":
|
|
190
|
-
case "FILETOOSMALL":
|
|
191
|
-
return "mediaUploadFailed";
|
|
192
|
-
case "MODERATIONBLOCKED":
|
|
193
|
-
return "moderationBlocked";
|
|
194
|
-
case "UPSTREAMLLMTIMEOUT":
|
|
195
|
-
return "upstreamLlmTimeout";
|
|
196
|
-
case "INTERNALERROR":
|
|
197
|
-
case "INTERNALSERVERERROR":
|
|
198
|
-
return "internalError";
|
|
199
|
-
case "STREAMINCOMPLETE":
|
|
200
|
-
case "CHATSTREAMINCOMPLETE":
|
|
201
|
-
return "streamIncomplete";
|
|
202
|
-
// Deterministic 400s that can only come from an SDK bug -> unknown (NON-retryable). NEVER internalError
|
|
203
|
-
// (which IS auto-retried): mapping a bad-input 400 to a retryable code retries a request that never succeeds.
|
|
204
|
-
case "INVALIDANALYSISTYPE":
|
|
205
|
-
case "INVALIDUPLOADPURPOSE":
|
|
206
|
-
return "unknown";
|
|
207
|
-
default:
|
|
208
|
-
return "unknown";
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
function fromHttpStatus(status) {
|
|
212
|
-
if (status === 401) return "authExpired";
|
|
213
|
-
if (status === 403) return "accessDenied";
|
|
214
|
-
if (status === 404) return "conversationNotFound";
|
|
215
|
-
if (status === 409) return "idempotencyConflict";
|
|
216
|
-
if (status === 421) return "unknown";
|
|
217
|
-
if (status === 429) return "rateLimited";
|
|
218
|
-
if (status === 400 || status === 422) return "unknown";
|
|
219
|
-
if (status >= 500) return "internalError";
|
|
220
|
-
return "unknown";
|
|
221
|
-
}
|
|
222
|
-
var AUTO_RETRYABLE_CODES = /* @__PURE__ */ new Set([
|
|
223
|
-
"streamTimeout",
|
|
224
|
-
"rateLimited",
|
|
225
|
-
"internalError",
|
|
226
|
-
"upstreamLlmTimeout",
|
|
227
|
-
"streamIncomplete"
|
|
228
|
-
]);
|
|
229
|
-
function isAutoRetryable(code) {
|
|
230
|
-
return AUTO_RETRYABLE_CODES.has(code);
|
|
231
|
-
}
|
|
232
|
-
var RETRYABLE_CONTRACT_CODES = /* @__PURE__ */ new Set([
|
|
233
|
-
"serviceUnavailable",
|
|
234
|
-
"conflict",
|
|
235
|
-
"idempotencyInFlight"
|
|
236
|
-
]);
|
|
237
|
-
function isRetryableCode(code) {
|
|
238
|
-
return isAutoRetryable(code) || RETRYABLE_CONTRACT_CODES.has(code);
|
|
239
|
-
}
|
|
240
|
-
function shouldRetry(code, frameRetryable = false) {
|
|
241
|
-
return frameRetryable || isAutoRetryable(code);
|
|
242
|
-
}
|
|
243
|
-
var BACKOFF_BASE_MS = 500;
|
|
244
|
-
var BACKOFF_CAP_MS = 8e3;
|
|
245
|
-
var MAX_RETRY_ATTEMPTS = 4;
|
|
246
|
-
function backoffDelayMs(attempt, rng = Math.random) {
|
|
247
|
-
const bounded = Math.max(0, attempt);
|
|
248
|
-
const ceiling = Math.min(BACKOFF_BASE_MS * 2 ** bounded, BACKOFF_CAP_MS);
|
|
249
|
-
return Math.floor(rng() * ceiling);
|
|
250
|
-
}
|
|
251
|
-
function canRecreateOnNotFound(code) {
|
|
252
|
-
return code === "conversationNotFound";
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// src/core/ports/ErrorPolicyPort.ts
|
|
256
|
-
var defaultErrorPolicy = Object.freeze({
|
|
257
|
-
shouldRetry(code, attempt) {
|
|
258
|
-
return isAutoRetryable(code) && attempt < MAX_RETRY_ATTEMPTS;
|
|
259
|
-
},
|
|
260
|
-
maxAttempts() {
|
|
261
|
-
return MAX_RETRY_ATTEMPTS;
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
// src/core/ports/CameraPort.ts
|
|
266
|
-
var unavailableCamera = Object.freeze({
|
|
267
|
-
isAvailable: false,
|
|
268
|
-
async capture() {
|
|
269
|
-
return Promise.reject(
|
|
270
|
-
new Error("CameraPort is unavailable; check isAvailable before calling capture")
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
|
|
275
|
-
// src/core/ports/optionalModule.ts
|
|
276
|
-
function optionalModule(name, load, validate2) {
|
|
277
|
-
let candidate;
|
|
278
|
-
try {
|
|
279
|
-
candidate = load();
|
|
280
|
-
} catch (cause) {
|
|
281
|
-
return frozenUnavailable(`optional peer '${name}' is not installed: ${describe(cause)}`);
|
|
282
|
-
}
|
|
283
|
-
const resolved = unwrapDefault(candidate);
|
|
284
|
-
if (resolved === null || resolved === void 0) {
|
|
285
|
-
return frozenUnavailable(`optional peer '${name}' resolved to no module`);
|
|
286
|
-
}
|
|
287
|
-
if (validate2 && !validate2(resolved)) {
|
|
288
|
-
return frozenUnavailable(`optional peer '${name}' is present but failed its shape check`);
|
|
289
|
-
}
|
|
290
|
-
return Object.freeze({ available: true, module: resolved });
|
|
291
|
-
}
|
|
292
|
-
function unwrapDefault(candidate) {
|
|
293
|
-
if (typeof candidate === "object" && candidate !== null && "default" in candidate && Object.keys(candidate).length <= 2) {
|
|
294
|
-
return candidate.default;
|
|
295
|
-
}
|
|
296
|
-
return candidate;
|
|
297
|
-
}
|
|
298
|
-
function frozenUnavailable(reason) {
|
|
299
|
-
return Object.freeze({ available: false, module: null, reason });
|
|
300
|
-
}
|
|
301
|
-
function describe(cause) {
|
|
302
|
-
if (cause instanceof Error) return cause.message;
|
|
303
|
-
return typeof cause === "string" ? cause : "unknown load error";
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// src/client/protocol/frames.ts
|
|
307
|
-
function assertNever(x) {
|
|
308
|
-
throw new Error(
|
|
309
|
-
`assertNever: unhandled discriminated-union member ${JSON.stringify(x)}`
|
|
310
|
-
);
|
|
311
|
-
}
|
|
312
|
-
function acceptedFrame(streamId, lastEventId, serverRequestId = null) {
|
|
313
|
-
return Object.freeze({ kind: "accepted", streamId, lastEventId, serverRequestId, terminal: false });
|
|
314
|
-
}
|
|
315
|
-
function heartbeatFrame(lastEventId, serverRequestId = null) {
|
|
316
|
-
return Object.freeze({ kind: "heartbeat", lastEventId, serverRequestId, terminal: false });
|
|
317
|
-
}
|
|
318
|
-
function deltaFrame(delta, lastEventId, serverRequestId = null) {
|
|
319
|
-
return Object.freeze({ kind: "delta", delta, lastEventId, serverRequestId, terminal: false });
|
|
320
|
-
}
|
|
321
|
-
function doneFrame(fields, serverRequestId = null) {
|
|
322
|
-
return Object.freeze({
|
|
323
|
-
kind: "done",
|
|
324
|
-
terminal: true,
|
|
325
|
-
conversationId: fields.conversationId,
|
|
326
|
-
messageId: fields.messageId,
|
|
327
|
-
title: fields.title,
|
|
328
|
-
followUpQuestions: Object.freeze([...fields.followUpQuestions]),
|
|
329
|
-
citations: Object.freeze([...fields.citations]),
|
|
330
|
-
citationStatus: fields.citationStatus,
|
|
331
|
-
urgencyLevel: fields.urgencyLevel,
|
|
332
|
-
urgencyReason: fields.urgencyReason,
|
|
333
|
-
resultId: fields.resultId,
|
|
334
|
-
lastEventId: fields.lastEventId,
|
|
335
|
-
serverRequestId
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
function errorFrame(fields) {
|
|
339
|
-
return Object.freeze({
|
|
340
|
-
kind: "error",
|
|
341
|
-
terminal: true,
|
|
342
|
-
code: fields.code,
|
|
343
|
-
retryable: fields.retryable,
|
|
344
|
-
wireMessage: fields.wireMessage,
|
|
345
|
-
synthesized: fields.synthesized,
|
|
346
|
-
lastEventId: fields.lastEventId,
|
|
347
|
-
serverRequestId: fields.serverRequestId ?? null
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
function analysisStartedFrame(requestId, lastEventId, serverRequestId = null) {
|
|
351
|
-
return Object.freeze({
|
|
352
|
-
kind: "analysisStarted",
|
|
353
|
-
requestId,
|
|
354
|
-
lastEventId,
|
|
355
|
-
serverRequestId,
|
|
356
|
-
terminal: false
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
function analysisCompleteFrame(fields, serverRequestId = null) {
|
|
360
|
-
return Object.freeze({
|
|
361
|
-
kind: "analysisComplete",
|
|
362
|
-
terminal: false,
|
|
363
|
-
resultId: fields.resultId,
|
|
364
|
-
analysisType: fields.analysisType,
|
|
365
|
-
modelVersion: fields.modelVersion,
|
|
366
|
-
confidence: fields.confidence,
|
|
367
|
-
detections: Object.freeze([...fields.detections]),
|
|
368
|
-
interpretation: fields.interpretation,
|
|
369
|
-
lastEventId: fields.lastEventId,
|
|
370
|
-
serverRequestId
|
|
371
|
-
});
|
|
372
|
-
}
|
|
373
|
-
function unknownFrame(raw, lastEventId, serverRequestId = null) {
|
|
374
|
-
return Object.freeze({
|
|
375
|
-
kind: "unknown",
|
|
376
|
-
raw: { ...raw },
|
|
377
|
-
lastEventId,
|
|
378
|
-
serverRequestId,
|
|
379
|
-
terminal: false
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
// src/client/errors/EverfurError.ts
|
|
384
|
-
var USER_FACING_COPY = Object.freeze({
|
|
385
|
-
authExpired: "Please sign in again to continue.",
|
|
386
|
-
authRejected: "Please sign in again to continue.",
|
|
387
|
-
sessionRequired: "This app needs to be updated to keep using Everfur.",
|
|
388
|
-
accessDenied: "This feature isn't available on your account right now.",
|
|
389
|
-
paymentRequired: "This is part of a paid plan.",
|
|
390
|
-
quotaExceeded: "You have used today's messages. This resets tomorrow.",
|
|
391
|
-
rateLimited: "You are sending messages quickly. Try again in a few seconds.",
|
|
392
|
-
validationFailed: "Something in that request was not right. Check the details and try again.",
|
|
393
|
-
sdkUpdateRequired: "This app needs to be updated to keep using Everfur.",
|
|
394
|
-
conflict: "That is already running. Wait for it to finish, then try again.",
|
|
395
|
-
idempotencyConflict: "That message was already delivered.",
|
|
396
|
-
idempotencyInFlight: "That is still processing. Give it a moment.",
|
|
397
|
-
conversationNotFound: "This conversation is no longer available.",
|
|
398
|
-
petNotFound: "We could not find that pet. Please pick a pet and try again.",
|
|
399
|
-
resourceNotFound: "We could not find that.",
|
|
400
|
-
streamTimeout: "The response timed out. Tap retry to try again.",
|
|
401
|
-
mediaUploadFailed: "We could not upload that photo. Please attach it again.",
|
|
402
|
-
moderationBlocked: "This request cannot be answered here.",
|
|
403
|
-
upstreamLlmTimeout: "The response timed out. Tap retry to try again.",
|
|
404
|
-
internalError: "We hit a snag on our end. Please try again.",
|
|
405
|
-
notImplemented: "That is not available yet.",
|
|
406
|
-
serviceUnavailable: "That service is briefly unavailable. Try again shortly.",
|
|
407
|
-
streamIncomplete: "The connection dropped mid-answer. Tap retry to continue.",
|
|
408
|
-
unknown: "Something went wrong. Please try again."
|
|
409
|
-
});
|
|
410
|
-
function userFacingError(code) {
|
|
411
|
-
return USER_FACING_COPY[code];
|
|
412
|
-
}
|
|
413
|
-
function defineHidden(target, key, value) {
|
|
414
|
-
Object.defineProperty(target, key, {
|
|
415
|
-
value,
|
|
416
|
-
enumerable: false,
|
|
417
|
-
writable: false,
|
|
418
|
-
configurable: false
|
|
419
|
-
});
|
|
420
|
-
}
|
|
421
|
-
function makeEverfurError(code, opts) {
|
|
422
|
-
contractErrorFor(opts?.wireCode);
|
|
423
|
-
const error = {
|
|
424
|
-
code,
|
|
425
|
-
category: categoryFor(code),
|
|
426
|
-
retryable: opts?.retryable ?? isRetryableCode(code),
|
|
427
|
-
displayMessage: userFacingError(code)
|
|
428
|
-
};
|
|
429
|
-
if (opts?.httpStatus !== void 0) error.httpStatus = opts.httpStatus;
|
|
430
|
-
if (opts?.requestId) error.requestId = opts.requestId;
|
|
431
|
-
if (opts?.wireMessage) defineHidden(error, "wireMessage", opts.wireMessage);
|
|
432
|
-
if (opts?.raw !== void 0 && opts.raw !== null) defineHidden(error, "raw", opts.raw);
|
|
433
|
-
return Object.freeze(error);
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
// src/client/identity.ts
|
|
437
|
-
function createIdentityProvider(userRef, getToken) {
|
|
438
|
-
let cached = null;
|
|
439
|
-
let inFlight = null;
|
|
440
|
-
let revoked = false;
|
|
441
|
-
const load = () => {
|
|
442
|
-
if (inFlight) return inFlight;
|
|
443
|
-
inFlight = (async () => {
|
|
444
|
-
try {
|
|
445
|
-
const token = await getToken();
|
|
446
|
-
if (typeof token !== "string" || token.length === 0) {
|
|
447
|
-
throw new EverfurConfigError("invalid-argument", "TokenProvider returned an empty token");
|
|
448
|
-
}
|
|
449
|
-
cached = token;
|
|
450
|
-
return token;
|
|
451
|
-
} finally {
|
|
452
|
-
inFlight = null;
|
|
453
|
-
}
|
|
454
|
-
})();
|
|
455
|
-
return inFlight;
|
|
456
|
-
};
|
|
457
|
-
return {
|
|
458
|
-
userRef,
|
|
459
|
-
async currentToken(opts) {
|
|
460
|
-
if (revoked) {
|
|
461
|
-
throw new EverfurConfigError("not-initialized", "This identity was cleared (sign-out); mint a new one.");
|
|
462
|
-
}
|
|
463
|
-
if (opts?.forceRefresh) cached = null;
|
|
464
|
-
if (cached !== null) return cached;
|
|
465
|
-
return load();
|
|
466
|
-
},
|
|
467
|
-
hasToken() {
|
|
468
|
-
return !revoked && cached !== null;
|
|
469
|
-
},
|
|
470
|
-
clear() {
|
|
471
|
-
revoked = true;
|
|
472
|
-
cached = null;
|
|
473
|
-
}
|
|
474
|
-
};
|
|
475
|
-
}
|
|
476
|
-
function newSessionId() {
|
|
477
|
-
const bytes = new Uint8Array(16);
|
|
478
|
-
const cryptoObj = globalThis.crypto;
|
|
479
|
-
if (typeof cryptoObj?.getRandomValues === "function") {
|
|
480
|
-
cryptoObj.getRandomValues(bytes);
|
|
481
|
-
} else {
|
|
482
|
-
for (let i = 0; i < bytes.length; i += 1) bytes[i] = Math.floor(Math.random() * 256);
|
|
483
|
-
}
|
|
484
|
-
bytes[6] = bytes[6] & 15 | 64;
|
|
485
|
-
bytes[8] = bytes[8] & 63 | 128;
|
|
486
|
-
const hex = [];
|
|
487
|
-
for (let i = 0; i < bytes.length; i += 1) hex.push(bytes[i].toString(16).padStart(2, "0"));
|
|
488
|
-
return hex.slice(0, 4).join("") + "-" + hex.slice(4, 6).join("") + "-" + hex.slice(6, 8).join("") + "-" + hex.slice(8, 10).join("") + "-" + hex.slice(10, 16).join("");
|
|
489
|
-
}
|
|
490
|
-
function authHeaders(auth) {
|
|
491
|
-
const headers = {};
|
|
492
|
-
if (auth.mode === "personalized") {
|
|
493
|
-
headers.authorization = `Bearer ${auth.token}`;
|
|
494
|
-
} else {
|
|
495
|
-
headers["x-everfur-partner-key"] = auth.publishableKey;
|
|
496
|
-
}
|
|
497
|
-
if (auth.userRef) headers["x-everfur-user-ref"] = auth.userRef;
|
|
498
|
-
if (auth.sessionId) headers["x-everfur-session-id"] = auth.sessionId;
|
|
499
|
-
return headers;
|
|
500
|
-
}
|
|
501
|
-
function withAuthHeaders(req, auth) {
|
|
502
|
-
return { ...req, headers: { ...stripAuthHeaders(req.headers), ...authHeaders(auth) } };
|
|
503
|
-
}
|
|
504
|
-
function stripAuthHeaders(headers) {
|
|
505
|
-
if (!headers) return {};
|
|
506
|
-
const out = {};
|
|
507
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
508
|
-
const lower = key.toLowerCase();
|
|
509
|
-
if (lower === "authorization" || lower === "x-everfur-partner-key") continue;
|
|
510
|
-
out[key] = value;
|
|
511
|
-
}
|
|
512
|
-
return out;
|
|
513
|
-
}
|
|
514
|
-
async function authedSend(req, ctx) {
|
|
515
|
-
if (ctx.mode === "anonymous") {
|
|
516
|
-
return ctx.transport.request(
|
|
517
|
-
withAuthHeaders(req, {
|
|
518
|
-
mode: "anonymous",
|
|
519
|
-
publishableKey: ctx.publishableKey,
|
|
520
|
-
userRef: ctx.userRef,
|
|
521
|
-
...ctx.sessionId ? { sessionId: ctx.sessionId } : {}
|
|
522
|
-
})
|
|
523
|
-
);
|
|
524
|
-
}
|
|
525
|
-
let token;
|
|
526
|
-
try {
|
|
527
|
-
token = await ctx.identity.currentToken();
|
|
528
|
-
} catch {
|
|
529
|
-
return err(authRejectedError());
|
|
530
|
-
}
|
|
531
|
-
const first = await ctx.transport.request(
|
|
532
|
-
withAuthHeaders(req, {
|
|
533
|
-
mode: "personalized",
|
|
534
|
-
token,
|
|
535
|
-
userRef: ctx.userRef,
|
|
536
|
-
...ctx.sessionId ? { sessionId: ctx.sessionId } : {}
|
|
537
|
-
})
|
|
538
|
-
);
|
|
539
|
-
if (first.ok || first.error.httpStatus !== 401) return first;
|
|
540
|
-
let refreshed;
|
|
541
|
-
try {
|
|
542
|
-
refreshed = await ctx.identity.currentToken({ forceRefresh: true });
|
|
543
|
-
} catch {
|
|
544
|
-
return err(authRejectedError());
|
|
545
|
-
}
|
|
546
|
-
const retry = await ctx.transport.request(
|
|
547
|
-
withAuthHeaders(req, {
|
|
548
|
-
mode: "personalized",
|
|
549
|
-
token: refreshed,
|
|
550
|
-
userRef: ctx.userRef,
|
|
551
|
-
...ctx.sessionId ? { sessionId: ctx.sessionId } : {}
|
|
552
|
-
})
|
|
553
|
-
);
|
|
554
|
-
if (!retry.ok && retry.error.httpStatus === 401) {
|
|
555
|
-
return err(authRejectedError(retry.error.httpStatus));
|
|
556
|
-
}
|
|
557
|
-
return retry;
|
|
558
|
-
}
|
|
559
|
-
function authRejectedError(httpStatus) {
|
|
560
|
-
return makeEverfurError("authRejected", {
|
|
561
|
-
retryable: false,
|
|
562
|
-
...httpStatus !== void 0 ? { httpStatus } : {}
|
|
563
|
-
});
|
|
564
|
-
}
|
|
565
|
-
var BLOCK_SEPARATOR = "\n\n";
|
|
566
|
-
var MAX_PENDING_BLOCK_CHARS = 1048576;
|
|
567
|
-
var wireObjectSchema = z.record(z.string(), z.unknown());
|
|
568
|
-
var URGENCY_LEVELS = ["emergency", "schedule_soon", "home_care"];
|
|
569
|
-
async function* parseSse(bytes, serverRequestId = null) {
|
|
570
|
-
let resolvedRequestId = null;
|
|
571
|
-
const requestIdNow = () => {
|
|
572
|
-
if (resolvedRequestId !== null) return resolvedRequestId;
|
|
573
|
-
resolvedRequestId = typeof serverRequestId === "function" ? serverRequestId() : serverRequestId;
|
|
574
|
-
return resolvedRequestId;
|
|
575
|
-
};
|
|
576
|
-
const decoder = new TextDecoder("utf-8");
|
|
577
|
-
let buffer = "";
|
|
578
|
-
let scanFrom = 0;
|
|
579
|
-
let sawDelta = false;
|
|
580
|
-
for await (const chunk of bytes) {
|
|
581
|
-
buffer += decoder.decode(chunk, { stream: true });
|
|
582
|
-
for (; ; ) {
|
|
583
|
-
const sep = buffer.indexOf(BLOCK_SEPARATOR, scanFrom);
|
|
584
|
-
if (sep === -1) break;
|
|
585
|
-
const block = buffer.slice(0, sep);
|
|
586
|
-
buffer = buffer.slice(sep + BLOCK_SEPARATOR.length);
|
|
587
|
-
scanFrom = 0;
|
|
588
|
-
const frame = parseBlock(block, requestIdNow());
|
|
589
|
-
if (frame === null) continue;
|
|
590
|
-
if (frame.kind === "delta") sawDelta = true;
|
|
591
|
-
yield frame;
|
|
592
|
-
if (frame.terminal) return;
|
|
593
|
-
}
|
|
594
|
-
scanFrom = buffer.length > 0 ? buffer.length - 1 : 0;
|
|
595
|
-
if (buffer.length > MAX_PENDING_BLOCK_CHARS) {
|
|
596
|
-
yield errorFrame({
|
|
597
|
-
code: sawDelta ? "CHAT_STREAM_INCOMPLETE" : "internal_error",
|
|
598
|
-
retryable: true,
|
|
599
|
-
wireMessage: null,
|
|
600
|
-
synthesized: true,
|
|
601
|
-
lastEventId: null,
|
|
602
|
-
serverRequestId: requestIdNow()
|
|
603
|
-
});
|
|
604
|
-
return;
|
|
605
|
-
}
|
|
606
|
-
}
|
|
607
|
-
buffer += decoder.decode();
|
|
608
|
-
if (buffer.trim().length > 0) {
|
|
609
|
-
const frame = parseBlock(buffer, requestIdNow());
|
|
610
|
-
if (frame !== null) {
|
|
611
|
-
if (frame.kind === "delta") sawDelta = true;
|
|
612
|
-
yield frame;
|
|
613
|
-
if (frame.terminal) return;
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
yield errorFrame({
|
|
617
|
-
code: sawDelta ? "CHAT_STREAM_INCOMPLETE" : "internal_error",
|
|
618
|
-
retryable: true,
|
|
619
|
-
wireMessage: null,
|
|
620
|
-
synthesized: true,
|
|
621
|
-
lastEventId: null,
|
|
622
|
-
serverRequestId: requestIdNow()
|
|
623
|
-
});
|
|
624
|
-
}
|
|
625
|
-
function parseBlock(block, serverRequestId) {
|
|
626
|
-
let id = null;
|
|
627
|
-
const dataLines = [];
|
|
628
|
-
for (const rawLine of block.split("\n")) {
|
|
629
|
-
const line = rawLine.replace(/\s+$/, "");
|
|
630
|
-
if (line.length === 0 || line.startsWith(":")) continue;
|
|
631
|
-
if (line.startsWith("id:")) {
|
|
632
|
-
id = line.slice(3).trim();
|
|
633
|
-
} else if (line.startsWith("data:")) {
|
|
634
|
-
dataLines.push(line.slice(5).replace(/^ /, ""));
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
if (dataLines.length === 0) return null;
|
|
638
|
-
let decoded;
|
|
639
|
-
try {
|
|
640
|
-
decoded = JSON.parse(dataLines.join("\n"));
|
|
641
|
-
} catch {
|
|
642
|
-
return null;
|
|
643
|
-
}
|
|
644
|
-
if (typeof decoded !== "object" || decoded === null || Array.isArray(decoded)) return null;
|
|
645
|
-
const parsed = wireObjectSchema.safeParse(decoded);
|
|
646
|
-
if (!parsed.success) return null;
|
|
647
|
-
return frameFromWire(parsed.data, id, serverRequestId);
|
|
648
|
-
}
|
|
649
|
-
function frameFromWire(json, lastEventId, serverRequestId) {
|
|
650
|
-
const type = json["type"];
|
|
651
|
-
const event = json["event"];
|
|
652
|
-
if (type === "error" || "error" in json) {
|
|
653
|
-
return errorFrame({
|
|
654
|
-
code: asString(json["code"]) ?? "unknown",
|
|
655
|
-
retryable: json["retryable"] === true,
|
|
656
|
-
wireMessage: asString(json["error"]),
|
|
657
|
-
synthesized: false,
|
|
658
|
-
lastEventId,
|
|
659
|
-
serverRequestId
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
if (type === "done" || json["done"] === true) {
|
|
663
|
-
return doneFrame({
|
|
664
|
-
conversationId: asString(json["conversation_id"]) ?? "",
|
|
665
|
-
messageId: asString(json["message_id"]),
|
|
666
|
-
title: asString(json["title"]),
|
|
667
|
-
followUpQuestions: asStringList(json["follow_up_questions"]),
|
|
668
|
-
citations: asMapList(json["citations"]),
|
|
669
|
-
citationStatus: asString(json["citation_status"]),
|
|
670
|
-
urgencyLevel: asUrgency(json["urgency_level"]),
|
|
671
|
-
urgencyReason: asString(json["urgency_reason"]),
|
|
672
|
-
resultId: asString(json["result_id"]),
|
|
673
|
-
lastEventId
|
|
674
|
-
}, serverRequestId);
|
|
675
|
-
}
|
|
676
|
-
if (type === "accepted" || json["status"] === "reasoning") {
|
|
677
|
-
return acceptedFrame(asString(json["stream_id"]), lastEventId, serverRequestId);
|
|
678
|
-
}
|
|
679
|
-
if (type === "heartbeat" || json["heartbeat"] === true) {
|
|
680
|
-
return heartbeatFrame(lastEventId, serverRequestId);
|
|
681
|
-
}
|
|
682
|
-
if (type === "text.delta" || "delta" in json || "token" in json) {
|
|
683
|
-
const delta = asString(json["delta"]) ?? asString(json["token"]) ?? "";
|
|
684
|
-
return deltaFrame(delta, lastEventId, serverRequestId);
|
|
685
|
-
}
|
|
686
|
-
if (event === "analysis_started") {
|
|
687
|
-
return analysisStartedFrame(asString(json["request_id"]), lastEventId, serverRequestId);
|
|
688
|
-
}
|
|
689
|
-
if (event === "analysis_complete") {
|
|
690
|
-
return analysisCompleteFrame({
|
|
691
|
-
resultId: asString(json["result_id"]),
|
|
692
|
-
analysisType: asString(json["analysis_type"]),
|
|
693
|
-
modelVersion: asString(json["model_version"]),
|
|
694
|
-
confidence: asNumber(json["confidence"]),
|
|
695
|
-
detections: asMapList(json["detections"]),
|
|
696
|
-
interpretation: asString(json["interpretation"]),
|
|
697
|
-
lastEventId
|
|
698
|
-
}, serverRequestId);
|
|
699
|
-
}
|
|
700
|
-
return unknownFrame(json, lastEventId, serverRequestId);
|
|
701
|
-
}
|
|
702
|
-
function asString(v) {
|
|
703
|
-
return typeof v === "string" ? v : null;
|
|
704
|
-
}
|
|
705
|
-
function asNumber(v) {
|
|
706
|
-
return typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
707
|
-
}
|
|
708
|
-
function asUrgency(v) {
|
|
709
|
-
return typeof v === "string" && URGENCY_LEVELS.includes(v) ? v : null;
|
|
710
|
-
}
|
|
711
|
-
function asStringList(v) {
|
|
712
|
-
if (!Array.isArray(v)) return [];
|
|
713
|
-
return v.map((e) => typeof e === "string" ? e : String(e));
|
|
714
|
-
}
|
|
715
|
-
function isPlainObject(v) {
|
|
716
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
717
|
-
}
|
|
718
|
-
function asMapList(v) {
|
|
719
|
-
if (!Array.isArray(v)) return [];
|
|
720
|
-
return v.filter(isPlainObject);
|
|
721
|
-
}
|
|
722
|
-
|
|
723
|
-
// src/client/config.ts
|
|
724
|
-
var SDK_VERSION = "0.1.0";
|
|
725
|
-
var SDK_PLATFORM = "react-native";
|
|
726
|
-
var DEFAULT_CONTRACT_VERSION = "2026-08-01";
|
|
727
|
-
var ENV_API_BASE_URL = "EVERFUR_API_BASE_URL";
|
|
728
|
-
function configFailure(reason, message) {
|
|
729
|
-
return Object.freeze({ ok: false, failure: Object.freeze({ reason, message }) });
|
|
730
|
-
}
|
|
731
|
-
function checkPublishableKey(raw) {
|
|
732
|
-
const publishableKey = typeof raw === "string" ? raw.trim() : "";
|
|
733
|
-
if (publishableKey.length === 0) {
|
|
734
|
-
return { reason: "missing-publishable-key", message: "publishableKey is required" };
|
|
735
|
-
}
|
|
736
|
-
if (/^sk[_-]/i.test(publishableKey)) {
|
|
737
|
-
return {
|
|
738
|
-
reason: "secret-key-as-publishable-key",
|
|
739
|
-
message: "publishableKey looks like a SECRET key (sk_...). A device must never hold a partner secret key: use the pk_ publishable key here, and keep the secret key on your server."
|
|
740
|
-
};
|
|
741
|
-
}
|
|
742
|
-
return null;
|
|
743
|
-
}
|
|
744
|
-
function tryResolveClientConfig(config) {
|
|
745
|
-
const keyFailure = checkPublishableKey(config?.publishableKey);
|
|
746
|
-
if (keyFailure !== null) {
|
|
747
|
-
return Object.freeze({ ok: false, failure: keyFailure });
|
|
748
|
-
}
|
|
749
|
-
const publishableKey = config.publishableKey.trim();
|
|
750
|
-
const baseUrl = tryResolveApiBaseUrl(config.apiBaseUrl);
|
|
751
|
-
if (!baseUrl.ok) {
|
|
752
|
-
return baseUrl;
|
|
753
|
-
}
|
|
754
|
-
const contractVersion = config.contractVersion?.trim() || DEFAULT_CONTRACT_VERSION;
|
|
755
|
-
return Object.freeze({
|
|
756
|
-
ok: true,
|
|
757
|
-
config: Object.freeze({
|
|
758
|
-
publishableKey,
|
|
759
|
-
apiBaseUrl: baseUrl.value,
|
|
760
|
-
contractVersion,
|
|
761
|
-
sdkVersion: SDK_VERSION,
|
|
762
|
-
platform: SDK_PLATFORM,
|
|
763
|
-
debug: config.debug === true
|
|
764
|
-
})
|
|
765
|
-
});
|
|
766
|
-
}
|
|
767
|
-
function tryResolveApiBaseUrl(apiBaseUrl) {
|
|
768
|
-
const explicit = apiBaseUrl?.trim();
|
|
769
|
-
const candidate = explicit && explicit.length > 0 ? explicit : readEnv(ENV_API_BASE_URL);
|
|
770
|
-
if (!candidate) {
|
|
771
|
-
return configFailure(
|
|
772
|
-
"missing-api-base-url",
|
|
773
|
-
`apiBaseUrl is required: pass config.apiBaseUrl or set ${ENV_API_BASE_URL}. The SDK never ships a hardcoded host.`
|
|
774
|
-
);
|
|
775
|
-
}
|
|
776
|
-
return normalizeBaseUrl(candidate);
|
|
777
|
-
}
|
|
778
|
-
function buildBaseHeaders(cfg) {
|
|
779
|
-
return {
|
|
780
|
-
"X-Everfur-SDK-Version": cfg.sdkVersion,
|
|
781
|
-
"X-Everfur-SDK-Platform": cfg.platform,
|
|
782
|
-
"X-Everfur-Contract": cfg.contractVersion
|
|
783
|
-
};
|
|
784
|
-
}
|
|
785
|
-
var ABSOLUTE_URL = /^([A-Za-z][A-Za-z0-9+.-]*):\/\/([^/?#]*)/;
|
|
786
|
-
function hostOf(authority) {
|
|
787
|
-
const afterUserinfo = authority.slice(authority.lastIndexOf("@") + 1);
|
|
788
|
-
return afterUserinfo.replace(/:\d+$/, "").toLowerCase();
|
|
789
|
-
}
|
|
790
|
-
function isPrintableHost(host) {
|
|
791
|
-
if (host.length === 0) return false;
|
|
792
|
-
if (host.includes("@")) return false;
|
|
793
|
-
if (host.startsWith("[") && host.endsWith("]")) return true;
|
|
794
|
-
return !host.includes(":");
|
|
795
|
-
}
|
|
796
|
-
function canEchoOrigin(rawTrimmed, host) {
|
|
797
|
-
const schemeEnd = rawTrimmed.indexOf("://");
|
|
798
|
-
if (schemeEnd < 0) return false;
|
|
799
|
-
if (rawTrimmed.slice(schemeEnd + 3).includes("@")) return false;
|
|
800
|
-
return isPrintableHost(host);
|
|
801
|
-
}
|
|
802
|
-
function safeOrigin(scheme, host) {
|
|
803
|
-
return `${scheme}://${host}`;
|
|
804
|
-
}
|
|
805
|
-
function normalizeBaseUrl(raw) {
|
|
806
|
-
const trimmed = raw.trim();
|
|
807
|
-
const match = ABSOLUTE_URL.exec(trimmed);
|
|
808
|
-
if (match === null || match[2] === void 0 || match[2].length === 0) {
|
|
809
|
-
return configFailure("malformed-api-base-url", "apiBaseUrl is not a valid absolute URL");
|
|
810
|
-
}
|
|
811
|
-
const scheme = (match[1] ?? "").toLowerCase();
|
|
812
|
-
const host = hostOf(match[2]);
|
|
813
|
-
if (host.length === 0) {
|
|
814
|
-
return configFailure("malformed-api-base-url", "apiBaseUrl is not a valid absolute URL");
|
|
815
|
-
}
|
|
816
|
-
const shown = canEchoOrigin(trimmed, host) ? `: ${safeOrigin(scheme, host)}` : "";
|
|
817
|
-
if (scheme === "https") ; else if (scheme === "http" && isLoopbackHost(host)) ; else if (scheme === "http") {
|
|
818
|
-
return configFailure(
|
|
819
|
-
"insecure-api-base-url",
|
|
820
|
-
`apiBaseUrl must use https (cleartext http is only allowed for localhost)${shown}`
|
|
821
|
-
);
|
|
822
|
-
} else {
|
|
823
|
-
return configFailure("unsupported-api-base-url-scheme", `apiBaseUrl must be http(s)${shown}`);
|
|
824
|
-
}
|
|
825
|
-
const value = trimmed.endsWith("/") ? trimmed.slice(0, -1) : trimmed;
|
|
826
|
-
return Object.freeze({ ok: true, value });
|
|
827
|
-
}
|
|
828
|
-
function isLoopbackHost(hostname) {
|
|
829
|
-
const host = hostname.toLowerCase();
|
|
830
|
-
return host === "localhost" || host === "127.0.0.1" || host === "[::1]" || host === "::1";
|
|
831
|
-
}
|
|
832
|
-
function readEnv(name) {
|
|
833
|
-
const g = globalThis;
|
|
834
|
-
const value = g.process?.env?.[name];
|
|
835
|
-
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
// src/client/transport.ts
|
|
839
|
-
var UNARY_TIMEOUT_MS = 3e4;
|
|
840
|
-
var REQUEST_ID_HEADER = "x-request-id";
|
|
841
|
-
async function* fetchByteSource(body) {
|
|
842
|
-
if (!body) return;
|
|
843
|
-
const reader = body.getReader();
|
|
844
|
-
try {
|
|
845
|
-
for (; ; ) {
|
|
846
|
-
const { done, value } = await reader.read();
|
|
847
|
-
if (done) break;
|
|
848
|
-
if (value && value.length > 0) yield value;
|
|
849
|
-
}
|
|
850
|
-
} finally {
|
|
851
|
-
await reader.cancel?.();
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
function eventSourceByteSource(es) {
|
|
855
|
-
const enc = new TextEncoder();
|
|
856
|
-
const queue = createByteQueue();
|
|
857
|
-
let cleaned = false;
|
|
858
|
-
const onMessage = (ev) => {
|
|
859
|
-
let block = "";
|
|
860
|
-
if (ev.lastEventId) block += `id: ${ev.lastEventId}
|
|
861
|
-
`;
|
|
862
|
-
const data = ev.data ?? "";
|
|
863
|
-
for (const line of data.split("\n")) block += `data: ${line}
|
|
864
|
-
`;
|
|
865
|
-
block += "\n";
|
|
866
|
-
queue.push(enc.encode(block));
|
|
867
|
-
};
|
|
868
|
-
const onDone = () => {
|
|
869
|
-
cleanup();
|
|
870
|
-
queue.end();
|
|
871
|
-
};
|
|
872
|
-
const onError = (ev) => {
|
|
873
|
-
const status = typeof ev.xhrStatus === "number" ? ev.xhrStatus : 0;
|
|
874
|
-
if (status >= 400) {
|
|
875
|
-
const wireCode = statusToWireCode(status);
|
|
876
|
-
const retryable = isAutoRetryable(fromWire(wireCode));
|
|
877
|
-
queue.push(enc.encode(`data: ${JSON.stringify({ type: "error", code: wireCode, retryable })}
|
|
878
|
-
|
|
879
|
-
`));
|
|
880
|
-
}
|
|
881
|
-
cleanup();
|
|
882
|
-
queue.end();
|
|
883
|
-
};
|
|
884
|
-
es.addEventListener("message", onMessage);
|
|
885
|
-
es.addEventListener("done", onDone);
|
|
886
|
-
es.addEventListener("error", onError);
|
|
887
|
-
function cleanup() {
|
|
888
|
-
if (cleaned) return;
|
|
889
|
-
cleaned = true;
|
|
890
|
-
es.removeEventListener("message", onMessage);
|
|
891
|
-
es.removeEventListener("done", onDone);
|
|
892
|
-
es.removeEventListener("error", onError);
|
|
893
|
-
try {
|
|
894
|
-
es.close();
|
|
895
|
-
} catch {
|
|
896
|
-
}
|
|
897
|
-
}
|
|
898
|
-
return sourceWithCleanup(queue.source, cleanup);
|
|
899
|
-
}
|
|
900
|
-
async function* sourceWithCleanup(source, cleanup) {
|
|
901
|
-
try {
|
|
902
|
-
yield* source;
|
|
903
|
-
} finally {
|
|
904
|
-
cleanup();
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
function createByteQueue() {
|
|
908
|
-
const buffer = [];
|
|
909
|
-
let done = false;
|
|
910
|
-
let wake = null;
|
|
911
|
-
const signal = () => {
|
|
912
|
-
if (wake) {
|
|
913
|
-
const fn = wake;
|
|
914
|
-
wake = null;
|
|
915
|
-
fn();
|
|
916
|
-
}
|
|
917
|
-
};
|
|
918
|
-
async function* gen() {
|
|
919
|
-
for (; ; ) {
|
|
920
|
-
const next = buffer.shift();
|
|
921
|
-
if (next !== void 0) {
|
|
922
|
-
yield next;
|
|
923
|
-
continue;
|
|
924
|
-
}
|
|
925
|
-
if (done) return;
|
|
926
|
-
await new Promise((resolve) => {
|
|
927
|
-
wake = resolve;
|
|
928
|
-
});
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
return {
|
|
932
|
-
source: gen(),
|
|
933
|
-
push: (u) => {
|
|
934
|
-
buffer.push(u);
|
|
935
|
-
signal();
|
|
936
|
-
},
|
|
937
|
-
end: () => {
|
|
938
|
-
done = true;
|
|
939
|
-
signal();
|
|
940
|
-
}
|
|
941
|
-
};
|
|
942
|
-
}
|
|
943
|
-
async function requestJson(req, deps) {
|
|
944
|
-
const fetchImpl = deps.fetchImpl ?? getGlobalFetch();
|
|
945
|
-
const url = buildUrl(deps.config.apiBaseUrl, req.path, req.query);
|
|
946
|
-
const headers = mergeHeaders(deps.config, req.headers, "application/json", req.body !== void 0 && req.multipart === void 0);
|
|
947
|
-
const deadline2 = timeoutSignal(UNARY_TIMEOUT_MS);
|
|
948
|
-
const signal = mergeAbortSignals(deadline2.signal, req.signal);
|
|
949
|
-
let res;
|
|
950
|
-
try {
|
|
951
|
-
res = await fetchImpl(url, buildInit({ ...req, signal }, headers));
|
|
952
|
-
} catch (cause) {
|
|
953
|
-
return err(networkError(cause));
|
|
954
|
-
} finally {
|
|
955
|
-
deadline2.cancel();
|
|
956
|
-
}
|
|
957
|
-
const bodyJson = await safeJson(res);
|
|
958
|
-
if (!res.ok) return err(errorFromResponse(res.status, bodyJson, requestIdOf(res)));
|
|
959
|
-
return ok(bodyJson);
|
|
960
|
-
}
|
|
961
|
-
function createHttpTransport(deps) {
|
|
962
|
-
return {
|
|
963
|
-
request: (req) => requestJson(req, deps),
|
|
964
|
-
stream: (req, signal) => streamFrames(withSignal(req, signal), deps)
|
|
965
|
-
};
|
|
966
|
-
}
|
|
967
|
-
async function* streamFrames(req, deps) {
|
|
968
|
-
const url = buildUrl(deps.config.apiBaseUrl, req.path, req.query);
|
|
969
|
-
const headers = mergeHeaders(deps.config, req.headers, "text/event-stream", req.body !== void 0 && req.multipart === void 0);
|
|
970
|
-
if (deps.eventSourceFactory) {
|
|
971
|
-
const es = deps.eventSourceFactory(url, buildEventSourceInit(req, headers));
|
|
972
|
-
yield* parseSse(eventSourceByteSource(es), () => eventSourceRequestId(es));
|
|
973
|
-
return;
|
|
974
|
-
}
|
|
975
|
-
const fetchImpl = deps.fetchImpl ?? getGlobalFetch();
|
|
976
|
-
let res;
|
|
977
|
-
try {
|
|
978
|
-
res = await fetchImpl(url, buildInit(req, headers));
|
|
979
|
-
} catch (cause) {
|
|
980
|
-
yield syntheticErrorFrame("", true, describeCause(cause));
|
|
981
|
-
return;
|
|
982
|
-
}
|
|
983
|
-
const requestId = requestIdOf(res);
|
|
984
|
-
if (!res.ok) {
|
|
985
|
-
const body = await safeJson(res);
|
|
986
|
-
const wireCode = extractWireCode(body) ?? statusToWireCode(res.status);
|
|
987
|
-
const retryable = extractRetryable(body) || isAutoRetryable(fromWire(wireCode));
|
|
988
|
-
yield syntheticErrorFrame(wireCode, retryable, extractWireMessage(body), requestId);
|
|
989
|
-
return;
|
|
990
|
-
}
|
|
991
|
-
if (res.body) {
|
|
992
|
-
yield* parseSse(fetchByteSource(res.body), requestId);
|
|
993
|
-
return;
|
|
994
|
-
}
|
|
995
|
-
yield* parseSse(fetchByteSource(null), requestId);
|
|
996
|
-
}
|
|
997
|
-
function buildEventSourceInit(req, headers) {
|
|
998
|
-
return {
|
|
999
|
-
method: req.method,
|
|
1000
|
-
headers,
|
|
1001
|
-
pollingInterval: 0,
|
|
1002
|
-
...req.body !== void 0 ? { body: JSON.stringify(req.body) } : {}
|
|
1003
|
-
};
|
|
1004
|
-
}
|
|
1005
|
-
function errorFromResponse(status, body, requestId) {
|
|
1006
|
-
const wireCode = extractWireCode(body);
|
|
1007
|
-
const code = wireCode ? fromWire(wireCode) : fromHttpStatus(status);
|
|
1008
|
-
const wireMessage = extractWireMessage(body);
|
|
1009
|
-
return makeEverfurError(code, {
|
|
1010
|
-
httpStatus: status,
|
|
1011
|
-
...extractRetryable(body) ? { retryable: true } : {},
|
|
1012
|
-
...requestId ? { requestId } : {},
|
|
1013
|
-
...wireCode ? { wireCode } : {},
|
|
1014
|
-
...wireMessage ? { wireMessage } : {},
|
|
1015
|
-
...body !== null && body !== void 0 ? { raw: body } : {}
|
|
1016
|
-
});
|
|
1017
|
-
}
|
|
1018
|
-
function networkError(cause) {
|
|
1019
|
-
return makeEverfurError("internalError", { retryable: true, wireMessage: describeCause(cause) });
|
|
1020
|
-
}
|
|
1021
|
-
function requestIdOf(res) {
|
|
1022
|
-
const value = res.headers.get(REQUEST_ID_HEADER);
|
|
1023
|
-
return typeof value === "string" && value.length > 0 ? value : null;
|
|
1024
|
-
}
|
|
1025
|
-
function eventSourceRequestId(es) {
|
|
1026
|
-
if (typeof es.getResponseHeader !== "function") return null;
|
|
1027
|
-
let value;
|
|
1028
|
-
try {
|
|
1029
|
-
value = es.getResponseHeader(REQUEST_ID_HEADER);
|
|
1030
|
-
} catch {
|
|
1031
|
-
return null;
|
|
1032
|
-
}
|
|
1033
|
-
return typeof value === "string" && value.length > 0 ? value : null;
|
|
1034
|
-
}
|
|
1035
|
-
function statusToWireCode(status) {
|
|
1036
|
-
if (status === 401) return "AUTH_EXPIRED";
|
|
1037
|
-
if (status === 403) return "ACCESS_DENIED";
|
|
1038
|
-
if (status === 404) return "NOT_FOUND";
|
|
1039
|
-
if (status === 409) return "IDEMPOTENCY_CONFLICT";
|
|
1040
|
-
if (status === 421) return "MISDIRECTED_REQUEST";
|
|
1041
|
-
if (status === 429) return "RATE_LIMITED";
|
|
1042
|
-
if (status === 400 || status === 422) return "INVALID_REQUEST";
|
|
1043
|
-
if (status === 503) return "INTERNAL_ERROR";
|
|
1044
|
-
if (status >= 500) return "INTERNAL_ERROR";
|
|
1045
|
-
return "";
|
|
1046
|
-
}
|
|
1047
|
-
function syntheticErrorFrame(code, retryable, wireMessage, serverRequestId = null) {
|
|
1048
|
-
return errorFrame({ code, retryable, wireMessage, synthesized: true, lastEventId: null, serverRequestId });
|
|
1049
|
-
}
|
|
1050
|
-
function getGlobalFetch() {
|
|
1051
|
-
const candidate = globalThis.fetch;
|
|
1052
|
-
if (typeof candidate !== "function") {
|
|
1053
|
-
throw new EverfurConfigError(
|
|
1054
|
-
"missing-peer-dependency",
|
|
1055
|
-
"global fetch is unavailable; provide config.transport or an injected fetch implementation"
|
|
1056
|
-
);
|
|
1057
|
-
}
|
|
1058
|
-
return candidate;
|
|
1059
|
-
}
|
|
1060
|
-
function buildUrl(base, path, query) {
|
|
1061
|
-
const rel = path.startsWith("/") ? path : `/${path}`;
|
|
1062
|
-
let url = `${base}${rel}`;
|
|
1063
|
-
if (query) {
|
|
1064
|
-
const qs = Object.entries(query).filter((entry) => entry[1] !== void 0).map(([k, v]) => `${encodeURIComponent(k)}=${encodeURIComponent(String(v))}`).join("&");
|
|
1065
|
-
if (qs) url += `?${qs}`;
|
|
1066
|
-
}
|
|
1067
|
-
return url;
|
|
1068
|
-
}
|
|
1069
|
-
function mergeHeaders(config, reqHeaders, accept, hasJsonBody) {
|
|
1070
|
-
const headers = { ...buildBaseHeaders(config), accept };
|
|
1071
|
-
if (hasJsonBody) headers["content-type"] = "application/json";
|
|
1072
|
-
if (reqHeaders) Object.assign(headers, reqHeaders);
|
|
1073
|
-
return headers;
|
|
1074
|
-
}
|
|
1075
|
-
function buildInit(req, headers) {
|
|
1076
|
-
const init = { method: req.method, headers };
|
|
1077
|
-
if (req.multipart !== void 0) init.body = req.multipart;
|
|
1078
|
-
else if (req.body !== void 0) init.body = JSON.stringify(req.body);
|
|
1079
|
-
if (req.signal) init.signal = req.signal;
|
|
1080
|
-
return init;
|
|
1081
|
-
}
|
|
1082
|
-
function withSignal(req, signal) {
|
|
1083
|
-
return req.signal ? req : { ...req, signal };
|
|
1084
|
-
}
|
|
1085
|
-
function timeoutSignal(ms) {
|
|
1086
|
-
const ctrl = new AbortController();
|
|
1087
|
-
const handle = setTimeout(() => ctrl.abort(), ms);
|
|
1088
|
-
return {
|
|
1089
|
-
signal: ctrl.signal,
|
|
1090
|
-
cancel: () => clearTimeout(handle)
|
|
1091
|
-
};
|
|
1092
|
-
}
|
|
1093
|
-
function mergeAbortSignals(deadline2, caller) {
|
|
1094
|
-
if (!caller) return deadline2;
|
|
1095
|
-
const ctrl = new AbortController();
|
|
1096
|
-
if (deadline2.aborted || caller.aborted) {
|
|
1097
|
-
ctrl.abort();
|
|
1098
|
-
return ctrl.signal;
|
|
1099
|
-
}
|
|
1100
|
-
const onAbort = () => ctrl.abort();
|
|
1101
|
-
deadline2.addEventListener("abort", onAbort, { once: true });
|
|
1102
|
-
caller.addEventListener("abort", onAbort, { once: true });
|
|
1103
|
-
return ctrl.signal;
|
|
1104
|
-
}
|
|
1105
|
-
async function safeJson(res) {
|
|
1106
|
-
try {
|
|
1107
|
-
return await res.json();
|
|
1108
|
-
} catch {
|
|
1109
|
-
return null;
|
|
1110
|
-
}
|
|
1111
|
-
}
|
|
1112
|
-
function extractWireCode(body) {
|
|
1113
|
-
const b = body;
|
|
1114
|
-
const code = b?.error?.code ?? b?.code;
|
|
1115
|
-
return typeof code === "string" && code.length > 0 ? code : null;
|
|
1116
|
-
}
|
|
1117
|
-
function extractWireMessage(body) {
|
|
1118
|
-
const b = body;
|
|
1119
|
-
const message = b?.error?.message ?? b?.message;
|
|
1120
|
-
return typeof message === "string" && message.length > 0 ? message : null;
|
|
1121
|
-
}
|
|
1122
|
-
function extractRetryable(body) {
|
|
1123
|
-
const b = body;
|
|
1124
|
-
return b?.error?.retryable === true || b?.retryable === true;
|
|
1125
|
-
}
|
|
1126
|
-
function describeCause(cause) {
|
|
1127
|
-
if (cause instanceof Error) return cause.message;
|
|
1128
|
-
return typeof cause === "string" ? cause : "network request failed";
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
// src/client/funnel/requestFunnel.ts
|
|
1132
|
-
var FUNNEL_UNARY_TIMEOUT_MS = 3e4;
|
|
1133
|
-
var RETRY_OVERRIDE_MAX_MS = BACKOFF_CAP_MS * 2;
|
|
1134
|
-
var IDEMPOTENCY_HEADER = "idempotency-key";
|
|
1135
|
-
var MUTATING_METHODS = /* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"]);
|
|
1136
|
-
var NOOP_OBSERVER = Object.freeze({
|
|
1137
|
-
onEvent() {
|
|
1138
|
-
}
|
|
1139
|
-
});
|
|
1140
|
-
var defaultFunnelTimers = Object.freeze({
|
|
1141
|
-
setTimeout: (handler, ms) => setTimeout(handler, ms),
|
|
1142
|
-
clearTimeout: (handle) => clearTimeout(handle),
|
|
1143
|
-
now: () => Date.now()
|
|
1144
|
-
});
|
|
1145
|
-
function createRequestFunnel(deps) {
|
|
1146
|
-
const observer = deps.observer ?? NOOP_OBSERVER;
|
|
1147
|
-
const timers = deps.timers ?? defaultFunnelTimers;
|
|
1148
|
-
const rng = deps.rng ?? Math.random;
|
|
1149
|
-
const sleep = deps.sleep ?? ((ms, signal) => delayAbortable(ms, timers, signal));
|
|
1150
|
-
const ceiling = deps.maxAttempts ?? MAX_RETRY_ATTEMPTS;
|
|
1151
|
-
const timeoutMs = deps.unaryTimeoutMs ?? FUNNEL_UNARY_TIMEOUT_MS;
|
|
1152
|
-
const mintKey = deps.newIdempotencyKey ?? defaultIdempotencyKeyFactory();
|
|
1153
|
-
const emit = (event) => {
|
|
1154
|
-
try {
|
|
1155
|
-
observer.onEvent(event);
|
|
1156
|
-
} catch {
|
|
1157
|
-
}
|
|
1158
|
-
};
|
|
1159
|
-
async function send(call, req, opts) {
|
|
1160
|
-
const perCallMaxAttempts = opts?.maxAttempts;
|
|
1161
|
-
const maxAttempts = Math.max(1, perCallMaxAttempts ?? ceiling);
|
|
1162
|
-
const idempotent = opts?.idempotent ?? MUTATING_METHODS.has(req.method);
|
|
1163
|
-
const idempotencyKey = idempotent ? mintKey() : null;
|
|
1164
|
-
const base = assembleHeaders(req, idempotencyKey);
|
|
1165
|
-
let attempt = 0;
|
|
1166
|
-
for (; ; ) {
|
|
1167
|
-
const stamp = (extra) => Object.freeze({
|
|
1168
|
-
call,
|
|
1169
|
-
method: req.method,
|
|
1170
|
-
path: req.path,
|
|
1171
|
-
attempt,
|
|
1172
|
-
...idempotencyKey ? { idempotencyKey } : {},
|
|
1173
|
-
...extra
|
|
1174
|
-
});
|
|
1175
|
-
emit(stamp({ phase: "attempt" }));
|
|
1176
|
-
const deadline2 = boundedSignal(timeoutMs, timers);
|
|
1177
|
-
const merged = mergeSignals(deadline2.signal, req.signal);
|
|
1178
|
-
let settled;
|
|
1179
|
-
try {
|
|
1180
|
-
settled = await authedSend({ ...base, signal: merged.signal }, deps.auth);
|
|
1181
|
-
} catch (cause) {
|
|
1182
|
-
settled = err(networkError(cause));
|
|
1183
|
-
} finally {
|
|
1184
|
-
merged.dispose();
|
|
1185
|
-
deadline2.cancel();
|
|
1186
|
-
}
|
|
1187
|
-
if (settled.ok) {
|
|
1188
|
-
emit(stamp({ phase: "settled", ok: true, reason: "ok" }));
|
|
1189
|
-
return settled;
|
|
1190
|
-
}
|
|
1191
|
-
const error = settled.error;
|
|
1192
|
-
const decision = decideRetry(error, attempt, {
|
|
1193
|
-
maxAttempts,
|
|
1194
|
-
rng,
|
|
1195
|
-
now: timers.now(),
|
|
1196
|
-
aborted: req.signal?.aborted === true,
|
|
1197
|
-
...perCallMaxAttempts !== void 0 ? { perCallMaxAttempts } : {},
|
|
1198
|
-
...deps.errorPolicy !== void 0 ? { policy: deps.errorPolicy } : {}
|
|
1199
|
-
});
|
|
1200
|
-
const settledEvent = {
|
|
1201
|
-
ok: false,
|
|
1202
|
-
code: error.code,
|
|
1203
|
-
reason: decision.reason,
|
|
1204
|
-
...error.httpStatus !== void 0 ? { httpStatus: error.httpStatus } : {},
|
|
1205
|
-
...error.requestId !== void 0 ? { requestId: error.requestId } : {}
|
|
1206
|
-
};
|
|
1207
|
-
if (!decision.retry) {
|
|
1208
|
-
emit(stamp({ phase: "settled", ...settledEvent }));
|
|
1209
|
-
return err(error);
|
|
1210
|
-
}
|
|
1211
|
-
emit(stamp({ phase: "retry", ...settledEvent, delayMs: decision.delayMs }));
|
|
1212
|
-
await sleep(decision.delayMs, req.signal);
|
|
1213
|
-
if (req.signal?.aborted === true) {
|
|
1214
|
-
emit(stamp({ phase: "settled", ...settledEvent, reason: "aborted" }));
|
|
1215
|
-
return err(error);
|
|
1216
|
-
}
|
|
1217
|
-
attempt += 1;
|
|
1218
|
-
}
|
|
1219
|
-
}
|
|
1220
|
-
async function authorize(req) {
|
|
1221
|
-
return withAuthHeaders(req, await resolveDeviceAuth(deps.auth));
|
|
1222
|
-
}
|
|
1223
|
-
async function* stream(call, req, signal) {
|
|
1224
|
-
emit(
|
|
1225
|
-
Object.freeze({
|
|
1226
|
-
call,
|
|
1227
|
-
phase: "stream.open",
|
|
1228
|
-
method: req.method,
|
|
1229
|
-
path: req.path,
|
|
1230
|
-
attempt: 0
|
|
1231
|
-
})
|
|
1232
|
-
);
|
|
1233
|
-
try {
|
|
1234
|
-
yield* deps.auth.transport.stream(req, signal);
|
|
1235
|
-
} catch {
|
|
1236
|
-
yield errorFrame({
|
|
1237
|
-
// The same wire spelling sse.ts synthesizes, so `fromWire` folds it to the retryable `internalError`
|
|
1238
|
-
// like any other transport failure. wireMessage stays null: it is the SERVER's text, and a thrown
|
|
1239
|
-
// host exception's `.message` is not that.
|
|
1240
|
-
code: "internal_error",
|
|
1241
|
-
retryable: true,
|
|
1242
|
-
wireMessage: null,
|
|
1243
|
-
synthesized: true,
|
|
1244
|
-
lastEventId: null,
|
|
1245
|
-
serverRequestId: null
|
|
1246
|
-
});
|
|
1247
|
-
}
|
|
1248
|
-
}
|
|
1249
|
-
return Object.freeze({ send, authorize, stream });
|
|
1250
|
-
}
|
|
1251
|
-
function assembleHeaders(req, idempotencyKey) {
|
|
1252
|
-
const headers = {};
|
|
1253
|
-
for (const [key, value] of Object.entries(req.headers ?? {})) {
|
|
1254
|
-
if (key.toLowerCase() === IDEMPOTENCY_HEADER) continue;
|
|
1255
|
-
headers[key] = value;
|
|
1256
|
-
}
|
|
1257
|
-
if (idempotencyKey !== null) headers["Idempotency-Key"] = idempotencyKey;
|
|
1258
|
-
return { ...req, headers };
|
|
1259
|
-
}
|
|
1260
|
-
function defaultIdempotencyKeyFactory() {
|
|
1261
|
-
let counter = 0;
|
|
1262
|
-
return () => `efk_${Date.now().toString(36)}_${(counter++).toString(36)}_${Math.random().toString(36).slice(2, 12)}`;
|
|
1263
|
-
}
|
|
1264
|
-
var POLICY_MAX_ATTEMPTS_CAP = 10;
|
|
1265
|
-
function decideRetry(error, attempt, ctx) {
|
|
1266
|
-
if (ctx.aborted) return { retry: false, reason: "aborted" };
|
|
1267
|
-
const throttle = throttleKind(error);
|
|
1268
|
-
if (throttle === "quota") {
|
|
1269
|
-
return { retry: false, reason: "daily-quota-exhausted" };
|
|
1270
|
-
}
|
|
1271
|
-
if (throttle !== "burst" && !isAutoRetryable(error.code)) {
|
|
1272
|
-
return { retry: false, reason: "terminal-code" };
|
|
1273
|
-
}
|
|
1274
|
-
const reason = throttle === "burst" ? "burst-throttle" : "retryable-code";
|
|
1275
|
-
const policyVetoedRetry = () => {
|
|
1276
|
-
if (ctx.policy === void 0) return false;
|
|
1277
|
-
try {
|
|
1278
|
-
return !ctx.policy.shouldRetry(error.code, attempt);
|
|
1279
|
-
} catch {
|
|
1280
|
-
return false;
|
|
1281
|
-
}
|
|
1282
|
-
};
|
|
1283
|
-
if (policyVetoedRetry()) return { retry: false, reason: "terminal-code" };
|
|
1284
|
-
const policyCeiling = () => {
|
|
1285
|
-
if (ctx.policy === void 0) return null;
|
|
1286
|
-
let raw;
|
|
1287
|
-
try {
|
|
1288
|
-
raw = ctx.policy.maxAttempts(error.code);
|
|
1289
|
-
} catch {
|
|
1290
|
-
return null;
|
|
1291
|
-
}
|
|
1292
|
-
if (typeof raw !== "number" || !Number.isFinite(raw)) return null;
|
|
1293
|
-
return Math.max(1, Math.min(POLICY_MAX_ATTEMPTS_CAP, Math.floor(raw)));
|
|
1294
|
-
};
|
|
1295
|
-
const ceiling = ctx.perCallMaxAttempts ?? policyCeiling() ?? ctx.maxAttempts;
|
|
1296
|
-
if (attempt + 1 >= ceiling) return { retry: false, reason: "attempts-exhausted" };
|
|
1297
|
-
const override = retryOverrideMs(error, ctx.now);
|
|
1298
|
-
if (override !== null) {
|
|
1299
|
-
if (override > RETRY_OVERRIDE_MAX_MS) {
|
|
1300
|
-
return { retry: false, reason: "server-reset-beyond-budget" };
|
|
1301
|
-
}
|
|
1302
|
-
return { retry: true, reason, delayMs: override };
|
|
1303
|
-
}
|
|
1304
|
-
return { retry: true, reason, delayMs: backoffDelayMs(attempt, ctx.rng) };
|
|
1305
|
-
}
|
|
1306
|
-
function throttleKind(error) {
|
|
1307
|
-
const code = error.code === "unknown" ? fromWire(rawWireCode(error.raw)) : error.code;
|
|
1308
|
-
if (code === "quotaExceeded") return "quota";
|
|
1309
|
-
if (code === "rateLimited") return "burst";
|
|
1310
|
-
if (error.httpStatus === 429) {
|
|
1311
|
-
return "burst";
|
|
1312
|
-
}
|
|
1313
|
-
return null;
|
|
1314
|
-
}
|
|
1315
|
-
function retryOverrideMs(error, now) {
|
|
1316
|
-
const at = findResetsAt(error.raw);
|
|
1317
|
-
if (at === null) return null;
|
|
1318
|
-
const delta = at - now;
|
|
1319
|
-
return delta > 0 ? delta : 0;
|
|
1320
|
-
}
|
|
1321
|
-
function findResetsAt(raw) {
|
|
1322
|
-
for (const scope of candidateScopes(raw)) {
|
|
1323
|
-
const value = scope["resets_at"];
|
|
1324
|
-
const parsed = parseInstantMs(value);
|
|
1325
|
-
if (parsed !== null) return parsed;
|
|
1326
|
-
}
|
|
1327
|
-
return null;
|
|
1328
|
-
}
|
|
1329
|
-
function candidateScopes(raw) {
|
|
1330
|
-
if (!isRecord(raw)) return [];
|
|
1331
|
-
const out = [raw];
|
|
1332
|
-
for (const nested of ["error", "detail"]) {
|
|
1333
|
-
const value = raw[nested];
|
|
1334
|
-
if (isRecord(value)) out.push(value);
|
|
1335
|
-
}
|
|
1336
|
-
return out;
|
|
1337
|
-
}
|
|
1338
|
-
function parseInstantMs(value) {
|
|
1339
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
1340
|
-
return value < 1e11 ? Math.round(value * 1e3) : Math.round(value);
|
|
1341
|
-
}
|
|
1342
|
-
if (typeof value === "string" && value.trim().length > 0) {
|
|
1343
|
-
const parsed = Date.parse(value);
|
|
1344
|
-
return Number.isFinite(parsed) ? parsed : null;
|
|
1345
|
-
}
|
|
1346
|
-
return null;
|
|
1347
|
-
}
|
|
1348
|
-
function rawWireCode(raw) {
|
|
1349
|
-
for (const scope of candidateScopes(raw)) {
|
|
1350
|
-
const code = scope["code"];
|
|
1351
|
-
if (typeof code === "string" && code.length > 0) return code;
|
|
1352
|
-
}
|
|
1353
|
-
return null;
|
|
1354
|
-
}
|
|
1355
|
-
function isRecord(value) {
|
|
1356
|
-
return typeof value === "object" && value !== null;
|
|
1357
|
-
}
|
|
1358
|
-
async function resolveDeviceAuth(auth) {
|
|
1359
|
-
if (auth.mode === "anonymous") {
|
|
1360
|
-
return {
|
|
1361
|
-
mode: "anonymous",
|
|
1362
|
-
publishableKey: auth.publishableKey,
|
|
1363
|
-
userRef: auth.userRef,
|
|
1364
|
-
...auth.sessionId ? { sessionId: auth.sessionId } : {}
|
|
1365
|
-
};
|
|
1366
|
-
}
|
|
1367
|
-
return {
|
|
1368
|
-
mode: "personalized",
|
|
1369
|
-
token: await auth.identity.currentToken(),
|
|
1370
|
-
userRef: auth.userRef,
|
|
1371
|
-
...auth.sessionId ? { sessionId: auth.sessionId } : {}
|
|
1372
|
-
};
|
|
1373
|
-
}
|
|
1374
|
-
function boundedSignal(ms, timers) {
|
|
1375
|
-
const ctrl = new AbortController();
|
|
1376
|
-
const handle = timers.setTimeout(() => ctrl.abort(), ms);
|
|
1377
|
-
return { signal: ctrl.signal, cancel: () => timers.clearTimeout(handle) };
|
|
1378
|
-
}
|
|
1379
|
-
function mergeSignals(deadline2, caller) {
|
|
1380
|
-
const noop = () => void 0;
|
|
1381
|
-
if (!caller) return { signal: deadline2, dispose: noop };
|
|
1382
|
-
const ctrl = new AbortController();
|
|
1383
|
-
if (deadline2.aborted || caller.aborted) {
|
|
1384
|
-
ctrl.abort();
|
|
1385
|
-
return { signal: ctrl.signal, dispose: noop };
|
|
1386
|
-
}
|
|
1387
|
-
const onAbort = () => ctrl.abort();
|
|
1388
|
-
deadline2.addEventListener("abort", onAbort, { once: true });
|
|
1389
|
-
caller.addEventListener("abort", onAbort, { once: true });
|
|
1390
|
-
return {
|
|
1391
|
-
signal: ctrl.signal,
|
|
1392
|
-
dispose: () => {
|
|
1393
|
-
deadline2.removeEventListener("abort", onAbort);
|
|
1394
|
-
caller.removeEventListener("abort", onAbort);
|
|
1395
|
-
}
|
|
1396
|
-
};
|
|
1397
|
-
}
|
|
1398
|
-
function delayAbortable(ms, timers, signal) {
|
|
1399
|
-
if (ms <= 0 || signal?.aborted === true) return Promise.resolve();
|
|
1400
|
-
return new Promise((resolve) => {
|
|
1401
|
-
const handle = timers.setTimeout(() => {
|
|
1402
|
-
signal?.removeEventListener("abort", onAbort);
|
|
1403
|
-
resolve();
|
|
1404
|
-
}, ms);
|
|
1405
|
-
const onAbort = () => {
|
|
1406
|
-
timers.clearTimeout(handle);
|
|
1407
|
-
resolve();
|
|
1408
|
-
};
|
|
1409
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
1410
|
-
});
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
// src/client/text.ts
|
|
1414
|
-
function hasLoneSurrogate(value) {
|
|
1415
|
-
for (let i = 0; i < value.length; i += 1) {
|
|
1416
|
-
const code = value.charCodeAt(i);
|
|
1417
|
-
if (code >= 55296 && code <= 56319) {
|
|
1418
|
-
const low = value.charCodeAt(i + 1);
|
|
1419
|
-
if (!(low >= 56320 && low <= 57343)) return true;
|
|
1420
|
-
i += 1;
|
|
1421
|
-
} else if (code >= 56320 && code <= 57343) {
|
|
1422
|
-
return true;
|
|
1423
|
-
}
|
|
1424
|
-
}
|
|
1425
|
-
return false;
|
|
1426
|
-
}
|
|
1427
|
-
function serverLength(value) {
|
|
1428
|
-
return [...value].length;
|
|
1429
|
-
}
|
|
1430
|
-
|
|
1431
|
-
// src/core/media/ports.ts
|
|
1432
|
-
var unavailableUpload = Object.freeze({
|
|
1433
|
-
async presignedPut() {
|
|
1434
|
-
return Promise.reject(new Error("UploadPort is unavailable; no presigned-upload adapter was injected"));
|
|
1435
|
-
}
|
|
1436
|
-
});
|
|
1437
|
-
function delayAbortable2(ms, signal, timers) {
|
|
1438
|
-
return new Promise((resolve) => {
|
|
1439
|
-
if (signal.aborted) {
|
|
1440
|
-
resolve();
|
|
1441
|
-
return;
|
|
1442
|
-
}
|
|
1443
|
-
const holder = { handle: void 0 };
|
|
1444
|
-
const done = () => {
|
|
1445
|
-
timers.clearTimeout(holder.handle);
|
|
1446
|
-
signal.removeEventListener("abort", done);
|
|
1447
|
-
resolve();
|
|
1448
|
-
};
|
|
1449
|
-
holder.handle = timers.setTimeout(done, ms);
|
|
1450
|
-
signal.addEventListener("abort", done, { once: true });
|
|
1451
|
-
});
|
|
1452
|
-
}
|
|
1453
|
-
function mergeSignals2(a, b) {
|
|
1454
|
-
if (!b) return a;
|
|
1455
|
-
const ctrl = new AbortController();
|
|
1456
|
-
if (a.aborted || b.aborted) {
|
|
1457
|
-
ctrl.abort();
|
|
1458
|
-
return ctrl.signal;
|
|
1459
|
-
}
|
|
1460
|
-
const onAbort = () => ctrl.abort();
|
|
1461
|
-
a.addEventListener("abort", onAbort, { once: true });
|
|
1462
|
-
b.addEventListener("abort", onAbort, { once: true });
|
|
1463
|
-
return ctrl.signal;
|
|
1464
|
-
}
|
|
1465
|
-
var MediaStore = class {
|
|
1466
|
-
constructor(initial) {
|
|
1467
|
-
this.listeners = /* @__PURE__ */ new Set();
|
|
1468
|
-
this.epoch = 0;
|
|
1469
|
-
this.inFlight = null;
|
|
1470
|
-
this.snapshot = Object.freeze({ ...initial });
|
|
1471
|
-
}
|
|
1472
|
-
subscribe(listener) {
|
|
1473
|
-
this.listeners.add(listener);
|
|
1474
|
-
return () => {
|
|
1475
|
-
this.listeners.delete(listener);
|
|
1476
|
-
};
|
|
1477
|
-
}
|
|
1478
|
-
getSnapshot() {
|
|
1479
|
-
return this.snapshot;
|
|
1480
|
-
}
|
|
1481
|
-
patch(partial) {
|
|
1482
|
-
this.snapshot = Object.freeze({ ...this.snapshot, ...partial });
|
|
1483
|
-
for (const listener of this.listeners) listener();
|
|
1484
|
-
}
|
|
1485
|
-
beginOperation(external) {
|
|
1486
|
-
this.inFlight?.abort();
|
|
1487
|
-
const ctrl = new AbortController();
|
|
1488
|
-
this.inFlight = ctrl;
|
|
1489
|
-
const epoch = this.epoch;
|
|
1490
|
-
const signal = external ? mergeSignals2(ctrl.signal, external) : ctrl.signal;
|
|
1491
|
-
return {
|
|
1492
|
-
signal,
|
|
1493
|
-
epoch,
|
|
1494
|
-
settle: () => {
|
|
1495
|
-
if (this.inFlight === ctrl) this.inFlight = null;
|
|
1496
|
-
}
|
|
1497
|
-
};
|
|
1498
|
-
}
|
|
1499
|
-
alive(epoch) {
|
|
1500
|
-
return epoch === this.epoch;
|
|
1501
|
-
}
|
|
1502
|
-
/** Re-scope on user/pet switch: aborts in-flight and bumps the epoch so a late write drops. */
|
|
1503
|
-
rescope() {
|
|
1504
|
-
this.epoch += 1;
|
|
1505
|
-
this.inFlight?.abort();
|
|
1506
|
-
this.inFlight = null;
|
|
1507
|
-
}
|
|
1508
|
-
/** Idempotent teardown: aborts in-flight, bumps the epoch, drops every listener. */
|
|
1509
|
-
dispose() {
|
|
1510
|
-
this.epoch += 1;
|
|
1511
|
-
this.inFlight?.abort();
|
|
1512
|
-
this.inFlight = null;
|
|
1513
|
-
this.listeners.clear();
|
|
1514
|
-
}
|
|
1515
|
-
};
|
|
1516
|
-
|
|
1517
|
-
// src/core/chat/chatMappers.ts
|
|
1518
|
-
function makeUser(id, text) {
|
|
1519
|
-
return Object.freeze({ id, role: "user", text, pending: true });
|
|
1520
|
-
}
|
|
1521
|
-
function makeAssistant(id, text) {
|
|
1522
|
-
return Object.freeze({ id, role: "assistant", text });
|
|
1523
|
-
}
|
|
1524
|
-
function stripPending(m) {
|
|
1525
|
-
return Object.freeze({ id: m.id, role: m.role, text: m.text });
|
|
1526
|
-
}
|
|
1527
|
-
function appendText(m, text) {
|
|
1528
|
-
const next = {
|
|
1529
|
-
id: m.id,
|
|
1530
|
-
role: m.role,
|
|
1531
|
-
text: m.text + text
|
|
1532
|
-
};
|
|
1533
|
-
if (m.citations) next.citations = m.citations;
|
|
1534
|
-
if (m.responseId) next.responseId = m.responseId;
|
|
1535
|
-
return Object.freeze(next);
|
|
1536
|
-
}
|
|
1537
|
-
function finalizeAssistant(m, done) {
|
|
1538
|
-
const next = {
|
|
1539
|
-
id: done.messageId ? done.messageId : m.id,
|
|
1540
|
-
role: "assistant",
|
|
1541
|
-
text: m.text
|
|
1542
|
-
};
|
|
1543
|
-
if (done.citations.length > 0) next.citations = done.citations;
|
|
1544
|
-
if (done.messageId) next.responseId = brandResponseId(done.messageId);
|
|
1545
|
-
return Object.freeze(next);
|
|
1546
|
-
}
|
|
1547
|
-
function freezeSnapshot(s) {
|
|
1548
|
-
return Object.freeze({
|
|
1549
|
-
status: s.status,
|
|
1550
|
-
messages: Object.freeze([...s.messages]),
|
|
1551
|
-
conversationId: s.conversationId,
|
|
1552
|
-
error: s.error,
|
|
1553
|
-
isStreaming: s.isStreaming,
|
|
1554
|
-
isBootstrapping: s.isBootstrapping,
|
|
1555
|
-
suggestedPrompts: Object.freeze([...s.suggestedPrompts])
|
|
1556
|
-
});
|
|
1557
|
-
}
|
|
1558
|
-
function makeError(code, retryable, wireMessage) {
|
|
1559
|
-
return makeEverfurError(code, { retryable, ...wireMessage ? { wireMessage } : {} });
|
|
1560
|
-
}
|
|
1561
|
-
function errorFromFrame(frame) {
|
|
1562
|
-
const code = fromWire(frame.code);
|
|
1563
|
-
return makeEverfurError(code, {
|
|
1564
|
-
retryable: frame.retryable || shouldRetry(code),
|
|
1565
|
-
wireCode: frame.code,
|
|
1566
|
-
...frame.serverRequestId ? { requestId: frame.serverRequestId } : {},
|
|
1567
|
-
...frame.wireMessage ? { wireMessage: frame.wireMessage } : {},
|
|
1568
|
-
raw: frame
|
|
1569
|
-
});
|
|
1570
|
-
}
|
|
1571
|
-
function synthErrorFrame(error) {
|
|
1572
|
-
return errorFrame({
|
|
1573
|
-
code: canonicalWireCode(error.code),
|
|
1574
|
-
retryable: error.retryable,
|
|
1575
|
-
wireMessage: error.wireMessage ?? null,
|
|
1576
|
-
synthesized: true,
|
|
1577
|
-
lastEventId: null,
|
|
1578
|
-
serverRequestId: error.requestId ?? null
|
|
1579
|
-
});
|
|
1580
|
-
}
|
|
1581
|
-
function canonicalWireCode(code) {
|
|
1582
|
-
switch (code) {
|
|
1583
|
-
case "authExpired":
|
|
1584
|
-
return "AUTH_EXPIRED";
|
|
1585
|
-
case "authRejected":
|
|
1586
|
-
return "AuthorizationException";
|
|
1587
|
-
case "sessionRequired":
|
|
1588
|
-
return "session_required";
|
|
1589
|
-
case "accessDenied":
|
|
1590
|
-
return "ACCESS_DENIED";
|
|
1591
|
-
case "paymentRequired":
|
|
1592
|
-
return "TIER_UPGRADE_REQUIRED";
|
|
1593
|
-
case "quotaExceeded":
|
|
1594
|
-
return "QUOTA_EXCEEDED";
|
|
1595
|
-
case "rateLimited":
|
|
1596
|
-
return "RATE_LIMITED";
|
|
1597
|
-
case "validationFailed":
|
|
1598
|
-
return "ValidationException";
|
|
1599
|
-
case "sdkUpdateRequired":
|
|
1600
|
-
return "invalidRequest";
|
|
1601
|
-
case "conflict":
|
|
1602
|
-
return "ConflictException";
|
|
1603
|
-
case "idempotencyConflict":
|
|
1604
|
-
return "IDEMPOTENCY_CONFLICT";
|
|
1605
|
-
case "idempotencyInFlight":
|
|
1606
|
-
return "IDEMPOTENCY_KEY_IN_FLIGHT";
|
|
1607
|
-
case "conversationNotFound":
|
|
1608
|
-
return "CONVERSATION_NOT_FOUND";
|
|
1609
|
-
case "petNotFound":
|
|
1610
|
-
return "PET_NOT_FOUND";
|
|
1611
|
-
case "resourceNotFound":
|
|
1612
|
-
return "ResourceNotFoundException";
|
|
1613
|
-
case "streamTimeout":
|
|
1614
|
-
return "STREAM_TIMEOUT";
|
|
1615
|
-
case "mediaUploadFailed":
|
|
1616
|
-
return "MEDIA_UPLOAD_FAILED";
|
|
1617
|
-
case "moderationBlocked":
|
|
1618
|
-
return "MODERATION_BLOCKED";
|
|
1619
|
-
case "upstreamLlmTimeout":
|
|
1620
|
-
return "UPSTREAM_LLM_TIMEOUT";
|
|
1621
|
-
case "internalError":
|
|
1622
|
-
return "INTERNAL_ERROR";
|
|
1623
|
-
case "notImplemented":
|
|
1624
|
-
return "NotImplementedException";
|
|
1625
|
-
case "serviceUnavailable":
|
|
1626
|
-
return "ServiceUnavailableException";
|
|
1627
|
-
case "streamIncomplete":
|
|
1628
|
-
return "STREAM_INCOMPLETE";
|
|
1629
|
-
case "unknown":
|
|
1630
|
-
return "UNKNOWN";
|
|
1631
|
-
default:
|
|
1632
|
-
return assertNever(code);
|
|
1633
|
-
}
|
|
1634
|
-
}
|
|
1635
|
-
function parsePromptCategories(raw) {
|
|
1636
|
-
const list = Array.isArray(raw) ? raw : isPlainObject2(raw) && Array.isArray(raw["categories"]) ? raw["categories"] : [];
|
|
1637
|
-
const out = [];
|
|
1638
|
-
for (const entry of list) {
|
|
1639
|
-
if (!isPlainObject2(entry)) continue;
|
|
1640
|
-
const category = asStr(entry["category"]) ?? asStr(entry["title"]) ?? "";
|
|
1641
|
-
const prompts = asPromptTextList(entry["prompts"] ?? entry["questions"]);
|
|
1642
|
-
if (category.length === 0 && prompts.length === 0) continue;
|
|
1643
|
-
out.push(Object.freeze({ category, prompts: Object.freeze(prompts) }));
|
|
1644
|
-
}
|
|
1645
|
-
return Object.freeze(out);
|
|
1646
|
-
}
|
|
1647
|
-
function flattenPrompts(categories) {
|
|
1648
|
-
const seen = /* @__PURE__ */ new Set();
|
|
1649
|
-
const out = [];
|
|
1650
|
-
for (const category of categories) {
|
|
1651
|
-
for (const prompt of category.prompts) {
|
|
1652
|
-
const trimmed = prompt.trim();
|
|
1653
|
-
if (trimmed.length === 0 || seen.has(trimmed)) continue;
|
|
1654
|
-
seen.add(trimmed);
|
|
1655
|
-
out.push(trimmed);
|
|
1656
|
-
}
|
|
1657
|
-
}
|
|
1658
|
-
return out;
|
|
1659
|
-
}
|
|
1660
|
-
function isPlainObject2(v) {
|
|
1661
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
1662
|
-
}
|
|
1663
|
-
function asStr(v) {
|
|
1664
|
-
return typeof v === "string" ? v : null;
|
|
1665
|
-
}
|
|
1666
|
-
function asPromptTextList(v) {
|
|
1667
|
-
if (!Array.isArray(v)) return [];
|
|
1668
|
-
const out = [];
|
|
1669
|
-
for (const entry of v) {
|
|
1670
|
-
if (typeof entry === "string") {
|
|
1671
|
-
out.push(entry);
|
|
1672
|
-
} else if (isPlainObject2(entry)) {
|
|
1673
|
-
const text = asStr(entry["text"]) ?? asStr(entry["prompt"]) ?? asStr(entry["title"]);
|
|
1674
|
-
if (text !== null) out.push(text);
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
return out;
|
|
1678
|
-
}
|
|
1679
|
-
function defaultIdFactory() {
|
|
1680
|
-
let counter = 0;
|
|
1681
|
-
return () => `m-${Date.now().toString(36)}-${(counter++).toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
1682
|
-
}
|
|
1683
|
-
function defaultIdempotencyFactory() {
|
|
1684
|
-
let counter = 0;
|
|
1685
|
-
return () => `chat-send-${Date.now().toString(36)}-${(counter++).toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
1686
|
-
}
|
|
1687
|
-
function brandConversationId(raw) {
|
|
1688
|
-
return raw;
|
|
1689
|
-
}
|
|
1690
|
-
function brandResponseId(raw) {
|
|
1691
|
-
return raw;
|
|
1692
|
-
}
|
|
1693
|
-
|
|
1694
|
-
// src/core/chat/watchdog.ts
|
|
1695
|
-
var defaultTimers2 = {
|
|
1696
|
-
setTimeout: (handler, ms) => setTimeout(handler, ms),
|
|
1697
|
-
clearTimeout: (handle) => clearTimeout(handle),
|
|
1698
|
-
now: () => Date.now()
|
|
1699
|
-
};
|
|
1700
|
-
async function* withWatchdog(source, budget, signal, timers) {
|
|
1701
|
-
const it = source[Symbol.asyncIterator]();
|
|
1702
|
-
const overall = deadline(budget.overallMs, timers);
|
|
1703
|
-
const idle = deadline(budget.idleMs, timers);
|
|
1704
|
-
const abort = abortPromise(signal);
|
|
1705
|
-
try {
|
|
1706
|
-
for (; ; ) {
|
|
1707
|
-
if (signal.aborted) return;
|
|
1708
|
-
const nextTagged = it.next().then(
|
|
1709
|
-
(value) => ({ tag: "next", value }),
|
|
1710
|
-
// A rejected it.next() is a RAW mid-stream transport drop (WiFi->cellular, backgrounding), NOT a clean
|
|
1711
|
-
// end-of-stream. The prior code coerced it to { done: true }, which silently short-circuited the SDK's
|
|
1712
|
-
// own retry ladder (SPEC-10 §7). Tag it so the loop can emit a retryable frame instead.
|
|
1713
|
-
() => ({ tag: "streamError" })
|
|
1714
|
-
);
|
|
1715
|
-
const outcome = await Promise.race([
|
|
1716
|
-
nextTagged,
|
|
1717
|
-
idle.promise.then(() => ({ tag: "idle" })),
|
|
1718
|
-
overall.promise.then(() => ({ tag: "overall" })),
|
|
1719
|
-
abort.then(() => ({ tag: "abort" }))
|
|
1720
|
-
]);
|
|
1721
|
-
if (outcome.tag === "abort") return;
|
|
1722
|
-
if (outcome.tag === "streamError") {
|
|
1723
|
-
if (signal.aborted) return;
|
|
1724
|
-
yield synthStreamErrorFrame();
|
|
1725
|
-
return;
|
|
1726
|
-
}
|
|
1727
|
-
if (outcome.tag === "idle" || outcome.tag === "overall") {
|
|
1728
|
-
yield synthTimeoutFrame();
|
|
1729
|
-
return;
|
|
1730
|
-
}
|
|
1731
|
-
const result = outcome.value;
|
|
1732
|
-
if (result.done) return;
|
|
1733
|
-
idle.reset(budget.idleMs);
|
|
1734
|
-
yield result.value;
|
|
1735
|
-
if (result.value.terminal) return;
|
|
1736
|
-
}
|
|
1737
|
-
} finally {
|
|
1738
|
-
idle.cancel();
|
|
1739
|
-
overall.cancel();
|
|
1740
|
-
void Promise.resolve(it.return?.(void 0)).catch(() => {
|
|
1741
|
-
});
|
|
1742
|
-
}
|
|
1743
|
-
}
|
|
1744
|
-
function synthTimeoutFrame() {
|
|
1745
|
-
return errorFrame({
|
|
1746
|
-
code: "STREAM_TIMEOUT",
|
|
1747
|
-
retryable: true,
|
|
1748
|
-
wireMessage: null,
|
|
1749
|
-
synthesized: true,
|
|
1750
|
-
lastEventId: null
|
|
1751
|
-
});
|
|
1752
|
-
}
|
|
1753
|
-
function synthStreamErrorFrame() {
|
|
1754
|
-
return errorFrame({
|
|
1755
|
-
code: "STREAM_INCOMPLETE",
|
|
1756
|
-
retryable: true,
|
|
1757
|
-
wireMessage: null,
|
|
1758
|
-
synthesized: true,
|
|
1759
|
-
lastEventId: null
|
|
1760
|
-
});
|
|
1761
|
-
}
|
|
1762
|
-
function deadline(ms, timers) {
|
|
1763
|
-
let resolveFn = () => {
|
|
1764
|
-
};
|
|
1765
|
-
const promise = new Promise((resolve) => {
|
|
1766
|
-
resolveFn = resolve;
|
|
1767
|
-
});
|
|
1768
|
-
let handle = timers.setTimeout(() => resolveFn(), ms);
|
|
1769
|
-
return {
|
|
1770
|
-
promise,
|
|
1771
|
-
reset(next) {
|
|
1772
|
-
timers.clearTimeout(handle);
|
|
1773
|
-
handle = timers.setTimeout(() => resolveFn(), next);
|
|
1774
|
-
},
|
|
1775
|
-
cancel() {
|
|
1776
|
-
timers.clearTimeout(handle);
|
|
1777
|
-
}
|
|
1778
|
-
};
|
|
1779
|
-
}
|
|
1780
|
-
function abortPromise(signal) {
|
|
1781
|
-
return new Promise((resolve) => {
|
|
1782
|
-
if (signal.aborted) {
|
|
1783
|
-
resolve();
|
|
1784
|
-
return;
|
|
1785
|
-
}
|
|
1786
|
-
signal.addEventListener("abort", () => resolve(), { once: true });
|
|
1787
|
-
});
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1790
|
-
// src/core/chat/ChatController.ts
|
|
1791
|
-
var DEFAULT_IDLE_MS = 6e4;
|
|
1792
|
-
var DEFAULT_OVERALL_MS = 18e4;
|
|
1793
|
-
var DELTA_FLUSH_MS = 24;
|
|
1794
|
-
var DELTA_FLUSH_CHARS = 512;
|
|
1795
|
-
var SEND_IS_SERVER_DEDUPED = false;
|
|
1796
|
-
function createChatController(deps) {
|
|
1797
|
-
return new ChatControllerImpl(deps);
|
|
1798
|
-
}
|
|
1799
|
-
var ChatControllerImpl = class extends MediaStore {
|
|
1800
|
-
constructor(deps) {
|
|
1801
|
-
super(
|
|
1802
|
-
freezeSnapshot({
|
|
1803
|
-
status: "idle",
|
|
1804
|
-
messages: [],
|
|
1805
|
-
conversationId: deps.initialConversationId ?? null,
|
|
1806
|
-
error: null,
|
|
1807
|
-
isStreaming: false,
|
|
1808
|
-
isBootstrapping: false,
|
|
1809
|
-
suggestedPrompts: []
|
|
1810
|
-
})
|
|
1811
|
-
);
|
|
1812
|
-
this.handlerTeardowns = /* @__PURE__ */ new Set();
|
|
1813
|
-
this.lastTurn = null;
|
|
1814
|
-
this.lastResponseIdValue = null;
|
|
1815
|
-
/** Delta coalescing buffer (PERF1): accumulated assistant text not yet flushed to the snapshot. */
|
|
1816
|
-
this.pendingDelta = "";
|
|
1817
|
-
this.flushHandle = null;
|
|
1818
|
-
this.auth = deps.auth;
|
|
1819
|
-
this.funnel = deps.funnel ?? createRequestFunnel({
|
|
1820
|
-
auth: deps.auth,
|
|
1821
|
-
...deps.errorPolicy ? { errorPolicy: deps.errorPolicy } : {}
|
|
1822
|
-
});
|
|
1823
|
-
this.telemetry = deps.telemetry ?? noopTelemetry;
|
|
1824
|
-
this.errorPolicy = deps.errorPolicy ?? defaultErrorPolicy;
|
|
1825
|
-
this.timers = deps.timers ?? defaultTimers2;
|
|
1826
|
-
this.rng = deps.rng ?? Math.random;
|
|
1827
|
-
this.newId = deps.newId ?? defaultIdFactory();
|
|
1828
|
-
this.makeIdempotencyKey = deps.makeIdempotencyKey ?? defaultIdempotencyFactory();
|
|
1829
|
-
this.budget = {
|
|
1830
|
-
idleMs: deps.budget?.idleMs ?? DEFAULT_IDLE_MS,
|
|
1831
|
-
overallMs: deps.budget?.overallMs ?? DEFAULT_OVERALL_MS
|
|
1832
|
-
};
|
|
1833
|
-
}
|
|
1834
|
-
// ---- store ------------------------------------------------------------
|
|
1835
|
-
// subscribe / getSnapshot / beginOperation / alive are inherited from MediaStore. patch is overridden so the
|
|
1836
|
-
// messages array stays deep-frozen (the base freezes only the snapshot object).
|
|
1837
|
-
patch(partial) {
|
|
1838
|
-
if (partial.messages !== void 0) {
|
|
1839
|
-
const frozen = Object.freeze([...partial.messages]);
|
|
1840
|
-
super.patch({ ...partial, messages: frozen });
|
|
1841
|
-
return;
|
|
1842
|
-
}
|
|
1843
|
-
super.patch(partial);
|
|
1844
|
-
}
|
|
1845
|
-
send(text, opts, handlers) {
|
|
1846
|
-
const options = opts ?? {};
|
|
1847
|
-
const invalid2 = validateMessageText(text);
|
|
1848
|
-
if (invalid2 !== null) {
|
|
1849
|
-
this.telemetry.track("chat.send.rejected", { reason: invalid2.reason });
|
|
1850
|
-
this.patch({ status: "error", isStreaming: false, error: invalid2.error });
|
|
1851
|
-
if (handlers) {
|
|
1852
|
-
handlers.onError(invalid2.error);
|
|
1853
|
-
return () => {
|
|
1854
|
-
};
|
|
1855
|
-
}
|
|
1856
|
-
return singleFrameStream(synthErrorFrame(invalid2.error));
|
|
1857
|
-
}
|
|
1858
|
-
if (handlers) return this.driveWithHandlers(text, options, handlers);
|
|
1859
|
-
const turn = this.beginTurn(text, options);
|
|
1860
|
-
return this.runTurn(turn, options.signal);
|
|
1861
|
-
}
|
|
1862
|
-
retryLast() {
|
|
1863
|
-
const turn = this.lastTurn;
|
|
1864
|
-
if (turn === null) return emptyStream();
|
|
1865
|
-
turn.assistantMessageId = null;
|
|
1866
|
-
turn.sawDelta = false;
|
|
1867
|
-
turn.conversationIdOverride = null;
|
|
1868
|
-
this.discardPendingDelta();
|
|
1869
|
-
const hasUser = this.snapshot.messages.some((m) => m.id === turn.userMessageId);
|
|
1870
|
-
const messages = hasUser ? this.snapshot.messages : [...this.snapshot.messages, makeUser(turn.userMessageId, turn.text)];
|
|
1871
|
-
this.patch({ error: null, messages });
|
|
1872
|
-
return this.runTurn(turn, void 0);
|
|
1873
|
-
}
|
|
1874
|
-
stop() {
|
|
1875
|
-
this.inFlight?.abort();
|
|
1876
|
-
this.inFlight = null;
|
|
1877
|
-
this.discardPendingDelta();
|
|
1878
|
-
this.telemetry.track("chat.cancel", {});
|
|
1879
|
-
const messages = this.snapshot.messages.filter((m) => !(m.role === "user" && m.pending === true));
|
|
1880
|
-
const changed = messages.length !== this.snapshot.messages.length;
|
|
1881
|
-
if (this.snapshot.status === "streaming" || changed) {
|
|
1882
|
-
this.patch({ status: "idle", isStreaming: false, ...changed ? { messages } : {} });
|
|
1883
|
-
}
|
|
1884
|
-
}
|
|
1885
|
-
rescope() {
|
|
1886
|
-
super.rescope();
|
|
1887
|
-
this.discardPendingDelta();
|
|
1888
|
-
if (this.snapshot.status === "streaming") this.patch({ status: "idle", isStreaming: false });
|
|
1889
|
-
}
|
|
1890
|
-
dispose() {
|
|
1891
|
-
this.discardPendingDelta();
|
|
1892
|
-
for (const teardown of this.handlerTeardowns) teardown();
|
|
1893
|
-
this.handlerTeardowns.clear();
|
|
1894
|
-
super.dispose();
|
|
1895
|
-
}
|
|
1896
|
-
adoptConversation(id) {
|
|
1897
|
-
if (this.snapshot.conversationId === id) return;
|
|
1898
|
-
this.patch({ conversationId: id });
|
|
1899
|
-
}
|
|
1900
|
-
adoptPrompts(categories) {
|
|
1901
|
-
const prompts = flattenPrompts(categories);
|
|
1902
|
-
if (prompts.length === 0 && this.snapshot.suggestedPrompts.length === 0) return;
|
|
1903
|
-
this.patch({ suggestedPrompts: Object.freeze(prompts) });
|
|
1904
|
-
}
|
|
1905
|
-
// ---- unary bootstrap helpers (§8) -------------------------------------
|
|
1906
|
-
async createConversation(opts) {
|
|
1907
|
-
return this.createConversationBounded(opts?.petRef ?? null);
|
|
1908
|
-
}
|
|
1909
|
-
/** The bounded create used by both the public helper and the turn pipeline (a caller signal ties it to op). */
|
|
1910
|
-
async createConversationBounded(petRef, signal) {
|
|
1911
|
-
const req = {
|
|
1912
|
-
method: "POST",
|
|
1913
|
-
path: "/widget/v1/conversations",
|
|
1914
|
-
body: petRef ? { pet_ref: petRef } : {}
|
|
1915
|
-
};
|
|
1916
|
-
const res = await this.authedUnary(
|
|
1917
|
-
"chat.createConversation",
|
|
1918
|
-
req,
|
|
1919
|
-
signal,
|
|
1920
|
-
// The widget lane does NOT read `Idempotency-Key`: its router is a plain APIRouter with no
|
|
1921
|
-
// idempotency route class, so a replay is a second CREATE, not a dedup, and retrying leaves the
|
|
1922
|
-
// partner with orphan threads nobody asked for. `maxAttempts: 1` stops the replay.
|
|
1923
|
-
//
|
|
1924
|
-
// The key itself is deliberately STILL SENT (no `idempotent: false`): it costs nothing on the wire,
|
|
1925
|
-
// it is what the funnel would mint anyway, and it starts working by itself the day the route dedups.
|
|
1926
|
-
// Deleting this one option is then the whole reversal.
|
|
1927
|
-
{ maxAttempts: 1 }
|
|
1928
|
-
);
|
|
1929
|
-
if (!res.ok) return err(res.error);
|
|
1930
|
-
const raw = res.value?.conversation_id ?? res.value?.id;
|
|
1931
|
-
if (typeof raw !== "string" || raw.length === 0) {
|
|
1932
|
-
return err(makeError("internalError", true));
|
|
1933
|
-
}
|
|
1934
|
-
return ok(brandConversationId(raw));
|
|
1935
|
-
}
|
|
1936
|
-
async getPrompts(opts) {
|
|
1937
|
-
const petRef = opts?.petRef ?? null;
|
|
1938
|
-
if (petRef !== null && hasLoneSurrogate(petRef)) {
|
|
1939
|
-
return err(
|
|
1940
|
-
makeEverfurError("validationFailed", {
|
|
1941
|
-
retryable: false,
|
|
1942
|
-
wireMessage: "pet_ref contains an unpaired surrogate and cannot be encoded"
|
|
1943
|
-
})
|
|
1944
|
-
);
|
|
1945
|
-
}
|
|
1946
|
-
const query = petRef !== null ? `?pet_ref=${encodeURIComponent(petRef)}` : "";
|
|
1947
|
-
const res = await this.authedUnary("chat.getPrompts", {
|
|
1948
|
-
method: "GET",
|
|
1949
|
-
path: `/widget/v1/suggested-prompts${query}`
|
|
1950
|
-
});
|
|
1951
|
-
if (!res.ok) return err(res.error);
|
|
1952
|
-
return ok(parsePromptCategories(res.value));
|
|
1953
|
-
}
|
|
1954
|
-
/**
|
|
1955
|
-
* A unary authed hop, through the ONE REQUEST FUNNEL. The funnel owns the per-attempt deadline (PERF2:
|
|
1956
|
-
* a stalled connection settles to a retryable error instead of hanging the spinner forever), the auth
|
|
1957
|
-
* spine, retry with full jitter, the client-minted idempotency key, and telemetry. Settles; never throws.
|
|
1958
|
-
*/
|
|
1959
|
-
async authedUnary(call, req, external, opts) {
|
|
1960
|
-
return this.funnel.send(call, external ? { ...req, signal: external } : req, opts);
|
|
1961
|
-
}
|
|
1962
|
-
// ---- imperative escape hatch ------------------------------------------
|
|
1963
|
-
driveWithHandlers(text, opts, handlers) {
|
|
1964
|
-
const cancel = new AbortController();
|
|
1965
|
-
const signal = mergeSignals2(cancel.signal, opts.signal);
|
|
1966
|
-
const turn = this.beginTurn(text, opts);
|
|
1967
|
-
const iterable = this.runTurn(turn, signal);
|
|
1968
|
-
let torn = false;
|
|
1969
|
-
const teardown = () => {
|
|
1970
|
-
if (torn) return;
|
|
1971
|
-
torn = true;
|
|
1972
|
-
cancel.abort();
|
|
1973
|
-
this.handlerTeardowns.delete(teardown);
|
|
1974
|
-
};
|
|
1975
|
-
this.handlerTeardowns.add(teardown);
|
|
1976
|
-
void (async () => {
|
|
1977
|
-
for await (const frame of iterable) {
|
|
1978
|
-
if (torn) break;
|
|
1979
|
-
handlers.onFrame(frame);
|
|
1980
|
-
if (frame.kind === "done") handlers.onDone(this.lastResponseIdValue);
|
|
1981
|
-
}
|
|
1982
|
-
if (!torn && this.snapshot.status === "error" && this.snapshot.error !== null) {
|
|
1983
|
-
handlers.onError(this.snapshot.error);
|
|
1984
|
-
}
|
|
1985
|
-
this.handlerTeardowns.delete(teardown);
|
|
1986
|
-
})();
|
|
1987
|
-
return teardown;
|
|
1988
|
-
}
|
|
1989
|
-
// ---- the turn pipeline ------------------------------------------------
|
|
1990
|
-
beginTurn(text, opts) {
|
|
1991
|
-
const turn = {
|
|
1992
|
-
epoch: this.epoch,
|
|
1993
|
-
text,
|
|
1994
|
-
petRef: opts.petRef ?? null,
|
|
1995
|
-
idempotencyKey: opts.idempotencyKey ?? this.makeIdempotencyKey(),
|
|
1996
|
-
userMessageId: this.newId(),
|
|
1997
|
-
assistantMessageId: null,
|
|
1998
|
-
sawDelta: false,
|
|
1999
|
-
conversationIdOverride: opts.conversationId ?? null
|
|
2000
|
-
};
|
|
2001
|
-
this.patch({
|
|
2002
|
-
error: null,
|
|
2003
|
-
messages: [...this.snapshot.messages, makeUser(turn.userMessageId, text)]
|
|
2004
|
-
});
|
|
2005
|
-
return turn;
|
|
2006
|
-
}
|
|
2007
|
-
async *runTurn(turn, external) {
|
|
2008
|
-
const op = this.beginOperation(external);
|
|
2009
|
-
turn.epoch = op.epoch;
|
|
2010
|
-
this.patch({ status: "streaming", isStreaming: true, error: null });
|
|
2011
|
-
this.lastTurn = turn;
|
|
2012
|
-
let retries = 0;
|
|
2013
|
-
let recreated = false;
|
|
2014
|
-
let refreshedOnce = false;
|
|
2015
|
-
try {
|
|
2016
|
-
for (; ; ) {
|
|
2017
|
-
if (op.signal.aborted || !this.alive(op.epoch)) return;
|
|
2018
|
-
const needsConversation = turn.conversationIdOverride === null && this.snapshot.conversationId === null;
|
|
2019
|
-
if (needsConversation) {
|
|
2020
|
-
const created = await this.createConversationBounded(turn.petRef, op.signal);
|
|
2021
|
-
if (op.signal.aborted || !this.alive(op.epoch)) return;
|
|
2022
|
-
if (!created.ok) {
|
|
2023
|
-
yield* this.emitTerminal(turn, created.error, synthErrorFrame(created.error));
|
|
2024
|
-
return;
|
|
2025
|
-
}
|
|
2026
|
-
this.adoptConversation(created.value);
|
|
2027
|
-
}
|
|
2028
|
-
const convId = turn.conversationIdOverride ?? this.snapshot.conversationId;
|
|
2029
|
-
if (convId === null) {
|
|
2030
|
-
const e = makeError("internalError", true);
|
|
2031
|
-
yield* this.emitTerminal(turn, e, synthErrorFrame(e));
|
|
2032
|
-
return;
|
|
2033
|
-
}
|
|
2034
|
-
this.clearAssistantInProgress(turn);
|
|
2035
|
-
const attemptCtrl = new AbortController();
|
|
2036
|
-
const attemptSignal = mergeSignals2(op.signal, attemptCtrl.signal);
|
|
2037
|
-
let terminalError = null;
|
|
2038
|
-
try {
|
|
2039
|
-
let authedReq;
|
|
2040
|
-
try {
|
|
2041
|
-
authedReq = await this.funnel.authorize(this.buildSendRequest(turn, convId));
|
|
2042
|
-
} catch {
|
|
2043
|
-
const e = this.authRejected();
|
|
2044
|
-
yield* this.emitTerminal(turn, e, synthErrorFrame(e));
|
|
2045
|
-
return;
|
|
2046
|
-
}
|
|
2047
|
-
if (op.signal.aborted || !this.alive(op.epoch)) return;
|
|
2048
|
-
const source = this.funnel.stream("chat.send", authedReq, attemptSignal);
|
|
2049
|
-
for await (const frame of withWatchdog(source, this.budget, attemptSignal, this.timers)) {
|
|
2050
|
-
if (!this.alive(op.epoch)) return;
|
|
2051
|
-
if (frame.kind === "error" && frame.terminal) {
|
|
2052
|
-
terminalError = frame;
|
|
2053
|
-
break;
|
|
2054
|
-
}
|
|
2055
|
-
this.applyFrame(frame, turn);
|
|
2056
|
-
yield frame;
|
|
2057
|
-
if (frame.terminal) {
|
|
2058
|
-
op.settle();
|
|
2059
|
-
return;
|
|
2060
|
-
}
|
|
2061
|
-
}
|
|
2062
|
-
} finally {
|
|
2063
|
-
attemptCtrl.abort();
|
|
2064
|
-
}
|
|
2065
|
-
if (op.signal.aborted || !this.alive(op.epoch)) return;
|
|
2066
|
-
if (terminalError === null) {
|
|
2067
|
-
if (this.snapshot.status === "complete") return;
|
|
2068
|
-
const e = makeError("streamIncomplete", true);
|
|
2069
|
-
yield* this.emitTerminal(turn, e, synthErrorFrame(e));
|
|
2070
|
-
return;
|
|
2071
|
-
}
|
|
2072
|
-
const code = fromWire(terminalError.code);
|
|
2073
|
-
if (code === "authExpired" && this.auth.mode === "personalized" && !refreshedOnce) {
|
|
2074
|
-
refreshedOnce = true;
|
|
2075
|
-
this.telemetry.track("chat.auth.refresh", {});
|
|
2076
|
-
const refreshed = await this.tryForceRefresh();
|
|
2077
|
-
if (op.signal.aborted || !this.alive(op.epoch)) return;
|
|
2078
|
-
if (!refreshed) {
|
|
2079
|
-
const e = this.authRejected();
|
|
2080
|
-
yield* this.emitTerminal(turn, e, terminalError);
|
|
2081
|
-
return;
|
|
2082
|
-
}
|
|
2083
|
-
continue;
|
|
2084
|
-
}
|
|
2085
|
-
if (code === "authExpired") {
|
|
2086
|
-
this.telemetry.track("chat.auth.rejected", {});
|
|
2087
|
-
const e = this.authRejected();
|
|
2088
|
-
yield* this.emitTerminal(turn, e, terminalError);
|
|
2089
|
-
return;
|
|
2090
|
-
}
|
|
2091
|
-
if (code === "accessDenied") {
|
|
2092
|
-
this.telemetry.track("chat.access_denied", {});
|
|
2093
|
-
yield* this.emitTerminal(turn, errorFromFrame(terminalError), terminalError);
|
|
2094
|
-
return;
|
|
2095
|
-
}
|
|
2096
|
-
if (canRecreateOnNotFound(code) && !recreated) {
|
|
2097
|
-
recreated = true;
|
|
2098
|
-
this.telemetry.track("chat.conv.recreate", {});
|
|
2099
|
-
this.adoptConversation(null);
|
|
2100
|
-
turn.conversationIdOverride = null;
|
|
2101
|
-
continue;
|
|
2102
|
-
}
|
|
2103
|
-
const framedRetry = terminalError.retryable && shouldRetry(code, true);
|
|
2104
|
-
if (SEND_IS_SERVER_DEDUPED && framedRetry && retries + 1 < this.errorPolicy.maxAttempts(code)) ;
|
|
2105
|
-
yield* this.emitTerminal(turn, errorFromFrame(terminalError), terminalError);
|
|
2106
|
-
return;
|
|
2107
|
-
}
|
|
2108
|
-
} finally {
|
|
2109
|
-
op.settle();
|
|
2110
|
-
}
|
|
2111
|
-
}
|
|
2112
|
-
*emitTerminal(turn, error, frame) {
|
|
2113
|
-
this.applyError(turn, error);
|
|
2114
|
-
yield frame;
|
|
2115
|
-
}
|
|
2116
|
-
// ---- frame -> state ---------------------------------------------------
|
|
2117
|
-
applyFrame(frame, turn) {
|
|
2118
|
-
switch (frame.kind) {
|
|
2119
|
-
case "accepted":
|
|
2120
|
-
if (!this.snapshot.isStreaming) this.patch({ status: "streaming", isStreaming: true });
|
|
2121
|
-
return;
|
|
2122
|
-
case "heartbeat":
|
|
2123
|
-
return;
|
|
2124
|
-
// silent; the watchdog resets its idle timer on any frame
|
|
2125
|
-
case "delta":
|
|
2126
|
-
this.applyDelta(frame.delta, turn);
|
|
2127
|
-
return;
|
|
2128
|
-
case "done":
|
|
2129
|
-
this.applyDone(frame, turn);
|
|
2130
|
-
return;
|
|
2131
|
-
case "analysisStarted":
|
|
2132
|
-
case "analysisComplete":
|
|
2133
|
-
return;
|
|
2134
|
-
// not part of chat render (analyze streams project elsewhere)
|
|
2135
|
-
case "unknown":
|
|
2136
|
-
this.telemetry.track("chat.frame.unknown", {});
|
|
2137
|
-
return;
|
|
2138
|
-
// forward-compat: ignore for render, keep streaming, never crash
|
|
2139
|
-
case "error":
|
|
2140
|
-
return;
|
|
2141
|
-
// terminal errors are driven by the recovery switch, never here
|
|
2142
|
-
default:
|
|
2143
|
-
return assertNever(frame);
|
|
2144
|
-
}
|
|
2145
|
-
}
|
|
2146
|
-
applyDelta(text, turn) {
|
|
2147
|
-
if (turn.assistantMessageId === null) {
|
|
2148
|
-
const assistantId = this.newId();
|
|
2149
|
-
turn.assistantMessageId = assistantId;
|
|
2150
|
-
turn.sawDelta = true;
|
|
2151
|
-
const cleared = this.snapshot.messages.map(
|
|
2152
|
-
(m) => m.id === turn.userMessageId && m.pending === true ? stripPending(m) : m
|
|
2153
|
-
);
|
|
2154
|
-
this.patch({
|
|
2155
|
-
status: "streaming",
|
|
2156
|
-
isStreaming: true,
|
|
2157
|
-
messages: [...cleared, makeAssistant(assistantId, text)]
|
|
2158
|
-
});
|
|
2159
|
-
return;
|
|
2160
|
-
}
|
|
2161
|
-
this.pendingDelta += text;
|
|
2162
|
-
if (this.pendingDelta.length >= DELTA_FLUSH_CHARS) {
|
|
2163
|
-
this.flushPendingDelta(turn);
|
|
2164
|
-
return;
|
|
2165
|
-
}
|
|
2166
|
-
this.scheduleDeltaFlush(turn);
|
|
2167
|
-
}
|
|
2168
|
-
scheduleDeltaFlush(turn) {
|
|
2169
|
-
if (this.flushHandle !== null) return;
|
|
2170
|
-
const scheduledEpoch = this.epoch;
|
|
2171
|
-
this.flushHandle = this.timers.setTimeout(() => {
|
|
2172
|
-
this.flushHandle = null;
|
|
2173
|
-
if (!this.alive(scheduledEpoch)) {
|
|
2174
|
-
this.pendingDelta = "";
|
|
2175
|
-
return;
|
|
2176
|
-
}
|
|
2177
|
-
this.flushPendingDelta(turn);
|
|
2178
|
-
}, DELTA_FLUSH_MS);
|
|
2179
|
-
}
|
|
2180
|
-
/** Fold the buffered deltas into the streaming assistant message as ONE patch (one listener notification). */
|
|
2181
|
-
flushPendingDelta(turn) {
|
|
2182
|
-
this.clearFlushTimer();
|
|
2183
|
-
if (this.pendingDelta.length === 0) return;
|
|
2184
|
-
const chunk = this.pendingDelta;
|
|
2185
|
-
this.pendingDelta = "";
|
|
2186
|
-
const assistantId = turn.assistantMessageId;
|
|
2187
|
-
if (assistantId === null) return;
|
|
2188
|
-
const messages = this.snapshot.messages.map((m) => m.id === assistantId ? appendText(m, chunk) : m);
|
|
2189
|
-
this.patch({ messages });
|
|
2190
|
-
}
|
|
2191
|
-
/** Drop a buffered-but-unflushed delta (cancel / rescope / dispose / retry): no stale text leaks forward. */
|
|
2192
|
-
discardPendingDelta() {
|
|
2193
|
-
this.clearFlushTimer();
|
|
2194
|
-
this.pendingDelta = "";
|
|
2195
|
-
}
|
|
2196
|
-
clearFlushTimer() {
|
|
2197
|
-
if (this.flushHandle !== null) {
|
|
2198
|
-
this.timers.clearTimeout(this.flushHandle);
|
|
2199
|
-
this.flushHandle = null;
|
|
2200
|
-
}
|
|
2201
|
-
}
|
|
2202
|
-
applyDone(done, turn) {
|
|
2203
|
-
this.flushPendingDelta(turn);
|
|
2204
|
-
this.lastResponseIdValue = done.messageId ? brandResponseId(done.messageId) : null;
|
|
2205
|
-
const nextConv = done.conversationId ? brandConversationId(done.conversationId) : this.snapshot.conversationId;
|
|
2206
|
-
let messages;
|
|
2207
|
-
if (turn.assistantMessageId !== null) {
|
|
2208
|
-
messages = this.snapshot.messages.map(
|
|
2209
|
-
(m) => m.id === turn.assistantMessageId ? finalizeAssistant(m, done) : m
|
|
2210
|
-
);
|
|
2211
|
-
} else {
|
|
2212
|
-
const assistantId = this.newId();
|
|
2213
|
-
turn.assistantMessageId = assistantId;
|
|
2214
|
-
turn.sawDelta = true;
|
|
2215
|
-
const cleared = this.snapshot.messages.map(
|
|
2216
|
-
(m) => m.id === turn.userMessageId && m.pending === true ? stripPending(m) : m
|
|
2217
|
-
);
|
|
2218
|
-
messages = [...cleared, finalizeAssistant(makeAssistant(assistantId, ""), done)];
|
|
2219
|
-
}
|
|
2220
|
-
this.patch({
|
|
2221
|
-
status: "complete",
|
|
2222
|
-
isStreaming: false,
|
|
2223
|
-
error: null,
|
|
2224
|
-
conversationId: nextConv,
|
|
2225
|
-
messages
|
|
2226
|
-
});
|
|
2227
|
-
}
|
|
2228
|
-
applyError(turn, error) {
|
|
2229
|
-
this.flushPendingDelta(turn);
|
|
2230
|
-
this.errorPolicy.onExpectedFailure?.(error);
|
|
2231
|
-
const messages = turn.sawDelta ? this.snapshot.messages : this.snapshot.messages.filter((m) => m.id !== turn.userMessageId);
|
|
2232
|
-
this.patch({ status: "error", isStreaming: false, error, messages });
|
|
2233
|
-
}
|
|
2234
|
-
clearAssistantInProgress(turn) {
|
|
2235
|
-
this.discardPendingDelta();
|
|
2236
|
-
if (turn.assistantMessageId === null) return;
|
|
2237
|
-
const assistantId = turn.assistantMessageId;
|
|
2238
|
-
turn.assistantMessageId = null;
|
|
2239
|
-
turn.sawDelta = false;
|
|
2240
|
-
const messages = this.snapshot.messages.filter((m) => m.id !== assistantId);
|
|
2241
|
-
if (messages.length !== this.snapshot.messages.length) this.patch({ messages });
|
|
2242
|
-
}
|
|
2243
|
-
// ---- auth + request build --------------------------------------------
|
|
2244
|
-
buildSendRequest(turn, convId) {
|
|
2245
|
-
const body = { message: turn.text };
|
|
2246
|
-
return {
|
|
2247
|
-
method: "POST",
|
|
2248
|
-
path: `/widget/v1/conversations/${convId}/messages`,
|
|
2249
|
-
body,
|
|
2250
|
-
// The TURN's own key, not a funnel mint. This is the streaming path, which the funnel deliberately
|
|
2251
|
-
// leaves alone, and the key is the identity of one logical turn: the same value is replayed by the
|
|
2252
|
-
// 404 recreate-and-resend and by the mid-stream refresh replay, so neither duplicates the user's
|
|
2253
|
-
// message. It is SDK-minted (`defaultIdempotencyFactory`), never taken from partner code.
|
|
2254
|
-
headers: { "Idempotency-Key": turn.idempotencyKey }
|
|
2255
|
-
};
|
|
2256
|
-
}
|
|
2257
|
-
async tryForceRefresh() {
|
|
2258
|
-
if (this.auth.mode !== "personalized") return false;
|
|
2259
|
-
try {
|
|
2260
|
-
await this.auth.identity.currentToken({ forceRefresh: true });
|
|
2261
|
-
return true;
|
|
2262
|
-
} catch {
|
|
2263
|
-
return false;
|
|
2264
|
-
}
|
|
2265
|
-
}
|
|
2266
|
-
authRejected() {
|
|
2267
|
-
return makeError("authRejected", false);
|
|
2268
|
-
}
|
|
2269
|
-
};
|
|
2270
|
-
var MESSAGE_MAX_CHARS = 4e3;
|
|
2271
|
-
function validateMessageText(text) {
|
|
2272
|
-
const raw = typeof text === "string" ? text : "";
|
|
2273
|
-
if (raw.trim().length === 0) {
|
|
2274
|
-
return { reason: "empty", error: makeError("validationFailed", false, "message is empty or whitespace-only") };
|
|
2275
|
-
}
|
|
2276
|
-
const codePoints = [...raw].length;
|
|
2277
|
-
if (codePoints > MESSAGE_MAX_CHARS) {
|
|
2278
|
-
return {
|
|
2279
|
-
reason: "too_long",
|
|
2280
|
-
error: makeError(
|
|
2281
|
-
"validationFailed",
|
|
2282
|
-
false,
|
|
2283
|
-
`message is ${codePoints} characters; the server accepts at most ${MESSAGE_MAX_CHARS}`
|
|
2284
|
-
)
|
|
2285
|
-
};
|
|
2286
|
-
}
|
|
2287
|
-
return null;
|
|
2288
|
-
}
|
|
2289
|
-
async function* singleFrameStream(frame) {
|
|
2290
|
-
yield frame;
|
|
2291
|
-
}
|
|
2292
|
-
async function* emptyStream() {
|
|
2293
|
-
}
|
|
2294
|
-
|
|
2295
|
-
// src/core/bootstrap.ts
|
|
2296
|
-
async function bootstrapChat(input, deps) {
|
|
2297
|
-
const { controller } = deps;
|
|
2298
|
-
const petRef = input.petRef ?? null;
|
|
2299
|
-
const resume = input.resumeConversationId ?? null;
|
|
2300
|
-
const candidateConversationIds = [];
|
|
2301
|
-
let sawForbidden = false;
|
|
2302
|
-
let sawUnauthorized = false;
|
|
2303
|
-
let sawConversationInitFailure = false;
|
|
2304
|
-
let authBlock = null;
|
|
2305
|
-
const conversationPromise = resume ? Promise.resolve(ok(resume)) : controller.createConversation(petRef ? { petRef } : void 0);
|
|
2306
|
-
const promptsPromise = controller.getPrompts(petRef !== null ? { petRef } : void 0);
|
|
2307
|
-
const [conversationRes, initialPromptsRes] = await Promise.all([conversationPromise, promptsPromise]);
|
|
2308
|
-
let conversationId = null;
|
|
2309
|
-
if (conversationRes.ok) {
|
|
2310
|
-
conversationId = conversationRes.value;
|
|
2311
|
-
candidateConversationIds.push(conversationRes.value);
|
|
2312
|
-
controller.adoptConversation(conversationRes.value);
|
|
2313
|
-
} else {
|
|
2314
|
-
const e = conversationRes.error;
|
|
2315
|
-
if (isUnauthorized(e)) {
|
|
2316
|
-
sawUnauthorized = true;
|
|
2317
|
-
authBlock = e;
|
|
2318
|
-
} else if (isForbidden(e)) {
|
|
2319
|
-
sawForbidden = true;
|
|
2320
|
-
sawConversationInitFailure = true;
|
|
2321
|
-
} else {
|
|
2322
|
-
sawConversationInitFailure = true;
|
|
2323
|
-
}
|
|
2324
|
-
}
|
|
2325
|
-
let suggestedPrompts = [];
|
|
2326
|
-
if (initialPromptsRes.ok) {
|
|
2327
|
-
suggestedPrompts = initialPromptsRes.value;
|
|
2328
|
-
} else {
|
|
2329
|
-
recordAuthSignals(initialPromptsRes.error);
|
|
2330
|
-
}
|
|
2331
|
-
function recordAuthSignals(e) {
|
|
2332
|
-
if (isUnauthorized(e)) {
|
|
2333
|
-
sawUnauthorized = true;
|
|
2334
|
-
if (authBlock === null) authBlock = e;
|
|
2335
|
-
} else if (isForbidden(e)) {
|
|
2336
|
-
sawForbidden = true;
|
|
2337
|
-
}
|
|
2338
|
-
}
|
|
2339
|
-
const error = authBlock !== null ? authBlock.displayMessage : null;
|
|
2340
|
-
const warning = error === null && conversationId === null && sawConversationInitFailure ? CONVERSATION_NOT_PRIMED_WARNING : null;
|
|
2341
|
-
return Object.freeze({
|
|
2342
|
-
conversationId,
|
|
2343
|
-
petRef,
|
|
2344
|
-
suggestedPrompts,
|
|
2345
|
-
error,
|
|
2346
|
-
warning,
|
|
2347
|
-
diagnostics: Object.freeze({
|
|
2348
|
-
candidateConversationIds: Object.freeze([...candidateConversationIds]),
|
|
2349
|
-
sawForbidden,
|
|
2350
|
-
sawUnauthorized,
|
|
2351
|
-
sawConversationInitFailure
|
|
2352
|
-
})
|
|
2353
|
-
});
|
|
2354
|
-
}
|
|
2355
|
-
var CONVERSATION_NOT_PRIMED_WARNING = "Chat is ready. Your first message will start the conversation.";
|
|
2356
|
-
function isUnauthorized(e) {
|
|
2357
|
-
return e.httpStatus === 401 || e.code === "authExpired" || e.code === "authRejected";
|
|
2358
|
-
}
|
|
2359
|
-
function isForbidden(e) {
|
|
2360
|
-
return e.httpStatus === 403 || e.code === "accessDenied";
|
|
2361
|
-
}
|
|
2362
|
-
|
|
2363
|
-
// src/client/pets/petsRepository.ts
|
|
2364
|
-
var PET_NAME_MAX = 100;
|
|
2365
|
-
var PET_SPECIES_MAX = 50;
|
|
2366
|
-
var PET_BREED_MAX = 100;
|
|
2367
|
-
var PET_AGE_YEARS_MAX = 50;
|
|
2368
|
-
var PET_WEIGHT_KG_MAX = 500;
|
|
2369
|
-
var PET_REF_MAX = 128;
|
|
2370
|
-
function invalid(wireMessage) {
|
|
2371
|
-
return makeEverfurError("validationFailed", { retryable: false, wireMessage });
|
|
2372
|
-
}
|
|
2373
|
-
function checkString(field, value, max) {
|
|
2374
|
-
if (typeof value !== "string") return invalid(`${field} must be a string`);
|
|
2375
|
-
const length = serverLength(value);
|
|
2376
|
-
if (length <= max) return null;
|
|
2377
|
-
return invalid(`${field} is ${length} characters; the server accepts at most ${max}`);
|
|
2378
|
-
}
|
|
2379
|
-
function outOfRange(field, value, max) {
|
|
2380
|
-
if (typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= max) return null;
|
|
2381
|
-
return invalid(`${field} must be a finite number between 0 and ${max}`);
|
|
2382
|
-
}
|
|
2383
|
-
function validate(petRef, profile) {
|
|
2384
|
-
if (typeof petRef !== "string") return invalid("pet_ref must be a string");
|
|
2385
|
-
if (petRef.trim().length === 0) return invalid("pet_ref must not be blank");
|
|
2386
|
-
if (hasLoneSurrogate(petRef)) return invalid("pet_ref contains an unpaired surrogate and cannot be encoded");
|
|
2387
|
-
if (profile !== void 0 && profile !== null && typeof profile !== "object") {
|
|
2388
|
-
return invalid("profile must be an object");
|
|
2389
|
-
}
|
|
2390
|
-
const checks = [checkString("pet_ref", petRef, PET_REF_MAX)];
|
|
2391
|
-
if (profile?.name !== void 0) checks.push(checkString("name", profile.name, PET_NAME_MAX));
|
|
2392
|
-
if (profile?.species !== void 0) checks.push(checkString("species", profile.species, PET_SPECIES_MAX));
|
|
2393
|
-
if (profile?.breed !== void 0) checks.push(checkString("breed", profile.breed, PET_BREED_MAX));
|
|
2394
|
-
if (profile?.ageYears !== void 0) checks.push(outOfRange("age_years", profile.ageYears, PET_AGE_YEARS_MAX));
|
|
2395
|
-
if (profile?.weightKg !== void 0) checks.push(outOfRange("weight_kg", profile.weightKg, PET_WEIGHT_KG_MAX));
|
|
2396
|
-
return checks.find((c) => c !== null) ?? null;
|
|
2397
|
-
}
|
|
2398
|
-
function toWire(profile) {
|
|
2399
|
-
if (profile === void 0 || profile === null) return {};
|
|
2400
|
-
return {
|
|
2401
|
-
...profile.name !== void 0 ? { name: profile.name } : {},
|
|
2402
|
-
...profile.species !== void 0 ? { species: profile.species } : {},
|
|
2403
|
-
...profile.breed !== void 0 ? { breed: profile.breed } : {},
|
|
2404
|
-
...profile.ageYears !== void 0 ? { age_years: profile.ageYears } : {},
|
|
2405
|
-
...profile.weightKg !== void 0 ? { weight_kg: profile.weightKg } : {}
|
|
2406
|
-
};
|
|
2407
|
-
}
|
|
2408
|
-
function fromWire2(raw, petRef) {
|
|
2409
|
-
const o = typeof raw === "object" && raw !== null ? raw : {};
|
|
2410
|
-
const str = (v) => typeof v === "string" ? v : null;
|
|
2411
|
-
const num = (v) => typeof v === "number" && Number.isFinite(v) ? v : null;
|
|
2412
|
-
return Object.freeze({
|
|
2413
|
-
petRef: str(o["pet_ref"]) ?? petRef,
|
|
2414
|
-
name: str(o["name"]),
|
|
2415
|
-
species: str(o["species"]),
|
|
2416
|
-
breed: str(o["breed"]),
|
|
2417
|
-
ageYears: num(o["age_years"]),
|
|
2418
|
-
weightKg: num(o["weight_kg"])
|
|
2419
|
-
});
|
|
2420
|
-
}
|
|
2421
|
-
function createPetsRepository(auth) {
|
|
2422
|
-
return createPetsRepositoryOver(createRequestFunnel({ auth }));
|
|
2423
|
-
}
|
|
2424
|
-
function createPetsRepositoryOver(funnel) {
|
|
2425
|
-
return {
|
|
2426
|
-
async registerPet(petRef, profile, opts) {
|
|
2427
|
-
const invalid2 = validate(petRef, profile);
|
|
2428
|
-
if (invalid2 !== null) return err(invalid2);
|
|
2429
|
-
const path = `/widget/v1/pets/${encodeURIComponent(petRef)}`;
|
|
2430
|
-
const base = { method: "POST", path, body: toWire(profile) };
|
|
2431
|
-
const res = await funnel.send(
|
|
2432
|
-
"pets.registerPet",
|
|
2433
|
-
opts?.signal ? { ...base, signal: opts.signal } : base
|
|
2434
|
-
);
|
|
2435
|
-
if (!res.ok) return err(res.error);
|
|
2436
|
-
return ok(fromWire2(res.value, petRef));
|
|
2437
|
-
}
|
|
2438
|
-
};
|
|
2439
|
-
}
|
|
2440
|
-
|
|
2441
|
-
// src/client/entitlements/resolve.ts
|
|
2442
|
-
var REQUIRES = Object.freeze({
|
|
2443
|
-
chat: Object.freeze(["chat.message.create"]),
|
|
2444
|
-
records: Object.freeze(["records.upload.create", "records.record.read"]),
|
|
2445
|
-
video: Object.freeze(["video.gait.execute"]),
|
|
2446
|
-
photo: Object.freeze(["photo.checkup.execute"]),
|
|
2447
|
-
animations: Object.freeze(["animations.state.read"])
|
|
2448
|
-
});
|
|
2449
|
-
function deniedDecisionsFor(level, reason) {
|
|
2450
|
-
const disabled = Object.freeze({ reason, level, recoverable: false });
|
|
2451
|
-
const rows = [];
|
|
2452
|
-
const seen = /* @__PURE__ */ new Set();
|
|
2453
|
-
for (const name of Object.keys(REQUIRES)) {
|
|
2454
|
-
for (const resource of REQUIRES[name]) {
|
|
2455
|
-
if (seen.has(resource)) continue;
|
|
2456
|
-
seen.add(resource);
|
|
2457
|
-
rows.push(Object.freeze({ resource, granted: false, disabled }));
|
|
2458
|
-
}
|
|
2459
|
-
}
|
|
2460
|
-
return Object.freeze(rows);
|
|
2461
|
-
}
|
|
2462
|
-
|
|
2463
|
-
// src/client/theme/resolve.ts
|
|
2464
|
-
function isEmptyBranding(b) {
|
|
2465
|
-
return b.displayName === null && b.logoUrl === null && b.primaryColor === null && b.accentColor === null && b.brightness === null && b.fontFamily === null && b.fontUrl === null && b.placeholder === null && b.hidePoweredBy === null;
|
|
2466
|
-
}
|
|
2467
|
-
function parseClientBranding(json) {
|
|
2468
|
-
if (json === null || typeof json !== "object") return null;
|
|
2469
|
-
const raw = json;
|
|
2470
|
-
const branding = {
|
|
2471
|
-
displayName: parseNonEmptyString(pick(raw, "display_name", "displayName")),
|
|
2472
|
-
logoUrl: parseNonEmptyString(pick(raw, "logo_url", "logoUrl")),
|
|
2473
|
-
primaryColor: parseColor(pick(raw, "primary_color", "primaryColor")),
|
|
2474
|
-
accentColor: parseColor(pick(raw, "accent_color", "accentColor")),
|
|
2475
|
-
brightness: parseBrightness(pick(raw, "brightness")),
|
|
2476
|
-
fontFamily: parseNonEmptyString(pick(raw, "font_family", "fontFamily")),
|
|
2477
|
-
fontUrl: parseNonEmptyString(pick(raw, "font_url", "fontUrl")),
|
|
2478
|
-
placeholder: parseNonEmptyString(pick(raw, "chat_placeholder", "placeholder", "chatPlaceholder")),
|
|
2479
|
-
hidePoweredBy: parseBool(pick(raw, "hide_powered_by", "hidePoweredBy"))
|
|
2480
|
-
};
|
|
2481
|
-
return isEmptyBranding(branding) ? null : Object.freeze(branding);
|
|
2482
|
-
}
|
|
2483
|
-
function parseBool(value) {
|
|
2484
|
-
if (typeof value === "boolean") return value;
|
|
2485
|
-
if (typeof value === "string") {
|
|
2486
|
-
const lower = value.trim().toLowerCase();
|
|
2487
|
-
if (lower === "true") return true;
|
|
2488
|
-
if (lower === "false") return false;
|
|
2489
|
-
}
|
|
2490
|
-
return null;
|
|
2491
|
-
}
|
|
2492
|
-
function pick(raw, ...keys) {
|
|
2493
|
-
for (const key of keys) {
|
|
2494
|
-
if (Object.prototype.hasOwnProperty.call(raw, key)) {
|
|
2495
|
-
const value = raw[key];
|
|
2496
|
-
if (value !== void 0) return value;
|
|
2497
|
-
}
|
|
2498
|
-
}
|
|
2499
|
-
return void 0;
|
|
2500
|
-
}
|
|
2501
|
-
function parseNonEmptyString(value) {
|
|
2502
|
-
if (typeof value !== "string") return null;
|
|
2503
|
-
const trimmed = value.trim();
|
|
2504
|
-
return trimmed.length === 0 ? null : trimmed;
|
|
2505
|
-
}
|
|
2506
|
-
function parseBrightness(value) {
|
|
2507
|
-
if (typeof value !== "string") return null;
|
|
2508
|
-
const lower = value.trim().toLowerCase();
|
|
2509
|
-
return lower === "light" || lower === "dark" ? lower : null;
|
|
2510
|
-
}
|
|
2511
|
-
function parseColor(value) {
|
|
2512
|
-
const rgba = toRgba(value);
|
|
2513
|
-
return rgba === null ? null : normalizeRgba(rgba);
|
|
2514
|
-
}
|
|
2515
|
-
function toRgba(value) {
|
|
2516
|
-
if (typeof value === "number") return argbIntToRgba(value);
|
|
2517
|
-
if (typeof value !== "string") return null;
|
|
2518
|
-
const s = value.trim();
|
|
2519
|
-
if (s.length === 0) return null;
|
|
2520
|
-
if (s.startsWith("#")) return fromHex(s.slice(1));
|
|
2521
|
-
if (s.toLowerCase().startsWith("0x")) return fromArgbHex(s.slice(2));
|
|
2522
|
-
if (s.toLowerCase().startsWith("rgb")) return fromRgbFunc(s);
|
|
2523
|
-
if (/^[0-9a-fA-F]+$/.test(s)) {
|
|
2524
|
-
const hex = fromHex(s);
|
|
2525
|
-
if (hex !== null) return hex;
|
|
2526
|
-
}
|
|
2527
|
-
if (/^\d+$/.test(s)) return argbIntToRgba(Number.parseInt(s, 10));
|
|
2528
|
-
return null;
|
|
2529
|
-
}
|
|
2530
|
-
function fromHex(hex) {
|
|
2531
|
-
const h = hex.trim();
|
|
2532
|
-
if (!/^[0-9a-fA-F]+$/.test(h)) return null;
|
|
2533
|
-
if (h.length === 3) {
|
|
2534
|
-
const r = dup(h[0]);
|
|
2535
|
-
const g = dup(h[1]);
|
|
2536
|
-
const b = dup(h[2]);
|
|
2537
|
-
return { r, g, b, a: 1 };
|
|
2538
|
-
}
|
|
2539
|
-
if (h.length === 6) {
|
|
2540
|
-
return { r: byte(h, 0), g: byte(h, 2), b: byte(h, 4), a: 1 };
|
|
2541
|
-
}
|
|
2542
|
-
if (h.length === 8) {
|
|
2543
|
-
const a = byte(h, 0);
|
|
2544
|
-
return { r: byte(h, 2), g: byte(h, 4), b: byte(h, 6), a: a / 255 };
|
|
2545
|
-
}
|
|
2546
|
-
return null;
|
|
2547
|
-
}
|
|
2548
|
-
function fromArgbHex(hex) {
|
|
2549
|
-
return fromHex(hex);
|
|
2550
|
-
}
|
|
2551
|
-
function fromRgbFunc(input) {
|
|
2552
|
-
const open = input.indexOf("(");
|
|
2553
|
-
const close = input.indexOf(")");
|
|
2554
|
-
if (open < 0 || close < 0 || close < open) return null;
|
|
2555
|
-
const parts = input.slice(open + 1, close).split(",").map((p) => p.trim());
|
|
2556
|
-
if (parts.length < 3) return null;
|
|
2557
|
-
const r = clampByte(Number(parts[0]));
|
|
2558
|
-
const g = clampByte(Number(parts[1]));
|
|
2559
|
-
const b = clampByte(Number(parts[2]));
|
|
2560
|
-
if (r === null || g === null || b === null) return null;
|
|
2561
|
-
let a = 1;
|
|
2562
|
-
if (parts.length >= 4) {
|
|
2563
|
-
const alpha = Number(parts[3]);
|
|
2564
|
-
if (!Number.isFinite(alpha)) return null;
|
|
2565
|
-
a = Math.min(1, Math.max(0, alpha));
|
|
2566
|
-
}
|
|
2567
|
-
return { r, g, b, a };
|
|
2568
|
-
}
|
|
2569
|
-
function argbIntToRgba(n) {
|
|
2570
|
-
if (!Number.isFinite(n)) return null;
|
|
2571
|
-
const int = Math.trunc(n) >>> 0;
|
|
2572
|
-
const a = int >>> 24 & 255;
|
|
2573
|
-
return {
|
|
2574
|
-
r: int >>> 16 & 255,
|
|
2575
|
-
g: int >>> 8 & 255,
|
|
2576
|
-
b: int & 255,
|
|
2577
|
-
// A 0x00RRGGBB with no alpha byte reads as fully transparent; treat a zero alpha byte as opaque so a
|
|
2578
|
-
// bare 0xRRGGBB (or small decimal) is not silently invisible.
|
|
2579
|
-
a: a === 0 ? 1 : a / 255
|
|
2580
|
-
};
|
|
2581
|
-
}
|
|
2582
|
-
function byte(hex, at) {
|
|
2583
|
-
return Number.parseInt(hex.slice(at, at + 2), 16);
|
|
2584
|
-
}
|
|
2585
|
-
function dup(nibble) {
|
|
2586
|
-
return Number.parseInt(`${nibble ?? "0"}${nibble ?? "0"}`, 16);
|
|
2587
|
-
}
|
|
2588
|
-
function clampByte(n) {
|
|
2589
|
-
if (!Number.isFinite(n)) return null;
|
|
2590
|
-
return Math.min(255, Math.max(0, Math.round(n)));
|
|
2591
|
-
}
|
|
2592
|
-
function normalizeRgba(rgba) {
|
|
2593
|
-
if (rgba.a >= 1) {
|
|
2594
|
-
return `#${hex2(rgba.r)}${hex2(rgba.g)}${hex2(rgba.b)}`.toUpperCase();
|
|
2595
|
-
}
|
|
2596
|
-
const a = Math.round(rgba.a * 1e3) / 1e3;
|
|
2597
|
-
return `rgba(${rgba.r},${rgba.g},${rgba.b},${a})`;
|
|
2598
|
-
}
|
|
2599
|
-
function hex2(n) {
|
|
2600
|
-
return n.toString(16).padStart(2, "0");
|
|
2601
|
-
}
|
|
2602
|
-
|
|
2603
|
-
// src/client/entitlements/entitlementRepository.ts
|
|
2604
|
-
var ENTITLEMENTS_PATH = "/widget/v1/entitlements";
|
|
2605
|
-
var HTTP_NOT_MODIFIED = 304;
|
|
2606
|
-
var NOT_MODIFIED = Object.freeze({ kind: "notModified" });
|
|
2607
|
-
async function fetchEntitlements(auth, args = {}, funnel = createRequestFunnel({ auth })) {
|
|
2608
|
-
const result = await funnel.send(
|
|
2609
|
-
"entitlements.fetch",
|
|
2610
|
-
buildRequest(args)
|
|
2611
|
-
);
|
|
2612
|
-
if (!result.ok) {
|
|
2613
|
-
if (result.error.httpStatus === HTTP_NOT_MODIFIED) return NOT_MODIFIED;
|
|
2614
|
-
return { kind: "failed", error: result.error };
|
|
2615
|
-
}
|
|
2616
|
-
return parseUpdated(result.value);
|
|
2617
|
-
}
|
|
2618
|
-
var REGION_MAX = 64;
|
|
2619
|
-
function buildRequest(args) {
|
|
2620
|
-
const headers = {};
|
|
2621
|
-
if (isFiniteNumber(args.cachedRevision)) {
|
|
2622
|
-
headers["if-none-match"] = `"${args.cachedRevision}"`;
|
|
2623
|
-
}
|
|
2624
|
-
if (args.region && args.region.length <= REGION_MAX) {
|
|
2625
|
-
return { method: "GET", path: ENTITLEMENTS_PATH, headers, query: { region: args.region } };
|
|
2626
|
-
}
|
|
2627
|
-
return { method: "GET", path: ENTITLEMENTS_PATH, headers };
|
|
2628
|
-
}
|
|
2629
|
-
function parseUpdated(body) {
|
|
2630
|
-
if (body === null || typeof body !== "object") return malformed();
|
|
2631
|
-
if (!isFiniteNumber(body.revision)) return malformed();
|
|
2632
|
-
const region = typeof body.region === "string" ? body.region : "";
|
|
2633
|
-
const ttlSeconds = isFiniteNumber(body.ttl_seconds) ? body.ttl_seconds : 0;
|
|
2634
|
-
return Object.freeze({
|
|
2635
|
-
kind: "updated",
|
|
2636
|
-
revision: body.revision,
|
|
2637
|
-
region,
|
|
2638
|
-
ttlSeconds,
|
|
2639
|
-
decisions: mapCapabilities(body.capabilities),
|
|
2640
|
-
// Branding is ADDITIVE and orthogonal to capabilities: a parse fault here NEVER affects the decisions and
|
|
2641
|
-
// fails closed to null (the compiled default theme). It cannot make a granted capability un-render.
|
|
2642
|
-
branding: parseBranding(body)
|
|
2643
|
-
});
|
|
2644
|
-
}
|
|
2645
|
-
function parseBranding(body) {
|
|
2646
|
-
const direct = parseClientBranding(body.branding);
|
|
2647
|
-
if (direct !== null) return direct;
|
|
2648
|
-
const hints = body.render_hints;
|
|
2649
|
-
if (hints !== null && typeof hints === "object") {
|
|
2650
|
-
const nested = parseClientBranding(hints.branding);
|
|
2651
|
-
if (nested !== null) return nested;
|
|
2652
|
-
return parseClientBranding(hints);
|
|
2653
|
-
}
|
|
2654
|
-
return null;
|
|
2655
|
-
}
|
|
2656
|
-
function mapCapabilities(capabilities) {
|
|
2657
|
-
if (capabilities === null || typeof capabilities !== "object") return Object.freeze([]);
|
|
2658
|
-
const out = [];
|
|
2659
|
-
for (const [resource, value] of Object.entries(capabilities)) {
|
|
2660
|
-
if (isEnabled(value)) out.push(Object.freeze({ resource, granted: true }));
|
|
2661
|
-
}
|
|
2662
|
-
return Object.freeze(out);
|
|
2663
|
-
}
|
|
2664
|
-
function isEnabled(value) {
|
|
2665
|
-
return typeof value === "object" && value !== null && value.enabled === true;
|
|
2666
|
-
}
|
|
2667
|
-
function malformed() {
|
|
2668
|
-
return {
|
|
2669
|
-
kind: "failed",
|
|
2670
|
-
error: makeEverfurError("internalError", {
|
|
2671
|
-
retryable: true,
|
|
2672
|
-
wireMessage: "malformed entitlements response"
|
|
2673
|
-
})
|
|
2674
|
-
};
|
|
2675
|
-
}
|
|
2676
|
-
function isFiniteNumber(value) {
|
|
2677
|
-
return typeof value === "number" && Number.isFinite(value);
|
|
2678
|
-
}
|
|
2679
|
-
|
|
2680
|
-
// src/core/entitlements/entitlementPoller.ts
|
|
2681
|
-
var MIN_POLL_INTERVAL_SECONDS = 30;
|
|
2682
|
-
function createEntitlementPoller(deps) {
|
|
2683
|
-
const scheduler = deps.scheduler ?? defaultScheduler;
|
|
2684
|
-
const resolve = deps.resolve ?? fetchEntitlements;
|
|
2685
|
-
const floorSeconds = Math.max(1, deps.floorSeconds ?? MIN_POLL_INTERVAL_SECONDS);
|
|
2686
|
-
const rng = deps.rng ?? Math.random;
|
|
2687
|
-
const jitteredFloorSeconds = () => floorSeconds + rng() * floorSeconds;
|
|
2688
|
-
let started = false;
|
|
2689
|
-
let stopped = false;
|
|
2690
|
-
let timer = null;
|
|
2691
|
-
let cachedRevision = null;
|
|
2692
|
-
let lastCadenceSeconds = floorSeconds;
|
|
2693
|
-
let generation = 0;
|
|
2694
|
-
const clearTimer = () => {
|
|
2695
|
-
if (timer !== null) {
|
|
2696
|
-
scheduler.clear(timer);
|
|
2697
|
-
timer = null;
|
|
2698
|
-
}
|
|
2699
|
-
};
|
|
2700
|
-
const schedule = (seconds) => {
|
|
2701
|
-
if (stopped) return;
|
|
2702
|
-
lastCadenceSeconds = Math.max(floorSeconds, seconds);
|
|
2703
|
-
timer = scheduler.set(() => {
|
|
2704
|
-
timer = null;
|
|
2705
|
-
void tick();
|
|
2706
|
-
}, lastCadenceSeconds * 1e3);
|
|
2707
|
-
};
|
|
2708
|
-
const tick = async () => {
|
|
2709
|
-
if (stopped) return;
|
|
2710
|
-
const myGen = generation;
|
|
2711
|
-
const args = deps.region ? { cachedRevision, region: deps.region } : { cachedRevision };
|
|
2712
|
-
let resolution;
|
|
2713
|
-
try {
|
|
2714
|
-
resolution = await resolve(deps.authFor(), args);
|
|
2715
|
-
} catch (cause) {
|
|
2716
|
-
deps.telemetry?.track("sdk.entitlements.poll_error", { reason: describe2(cause) });
|
|
2717
|
-
if (!stopped && myGen === generation) schedule(jitteredFloorSeconds());
|
|
2718
|
-
return;
|
|
2719
|
-
}
|
|
2720
|
-
if (stopped || myGen !== generation) return;
|
|
2721
|
-
switch (resolution.kind) {
|
|
2722
|
-
case "updated":
|
|
2723
|
-
cachedRevision = resolution.revision;
|
|
2724
|
-
deps.update(resolution.decisions, resolution.branding ?? null);
|
|
2725
|
-
schedule(resolution.ttlSeconds);
|
|
2726
|
-
return;
|
|
2727
|
-
case "notModified":
|
|
2728
|
-
schedule(lastCadenceSeconds);
|
|
2729
|
-
return;
|
|
2730
|
-
case "failed":
|
|
2731
|
-
deps.telemetry?.track("sdk.entitlements.poll_failed", { code: resolution.error.code });
|
|
2732
|
-
schedule(jitteredFloorSeconds());
|
|
2733
|
-
return;
|
|
2734
|
-
default:
|
|
2735
|
-
schedule(jitteredFloorSeconds());
|
|
2736
|
-
}
|
|
2737
|
-
};
|
|
2738
|
-
return {
|
|
2739
|
-
start() {
|
|
2740
|
-
if (started || stopped) return;
|
|
2741
|
-
started = true;
|
|
2742
|
-
void tick();
|
|
2743
|
-
},
|
|
2744
|
-
stop() {
|
|
2745
|
-
if (stopped) return;
|
|
2746
|
-
stopped = true;
|
|
2747
|
-
generation++;
|
|
2748
|
-
clearTimer();
|
|
2749
|
-
},
|
|
2750
|
-
refresh() {
|
|
2751
|
-
if (stopped || !started) return;
|
|
2752
|
-
generation++;
|
|
2753
|
-
cachedRevision = null;
|
|
2754
|
-
clearTimer();
|
|
2755
|
-
void tick();
|
|
2756
|
-
}
|
|
2757
|
-
};
|
|
2758
|
-
}
|
|
2759
|
-
var defaultScheduler = {
|
|
2760
|
-
set(callback, ms) {
|
|
2761
|
-
const handle = setTimeout(callback, ms);
|
|
2762
|
-
handle.unref?.();
|
|
2763
|
-
return handle;
|
|
2764
|
-
},
|
|
2765
|
-
clear(handle) {
|
|
2766
|
-
clearTimeout(handle);
|
|
2767
|
-
}
|
|
2768
|
-
};
|
|
2769
|
-
function describe2(cause) {
|
|
2770
|
-
return cause instanceof Error ? cause.message : "poll failed";
|
|
2771
|
-
}
|
|
2772
|
-
|
|
2773
|
-
// src/core/runtime.ts
|
|
2774
|
-
function compiledDefaultDecisions() {
|
|
2775
|
-
return Object.freeze([Object.freeze({ resource: "chat.message.create", granted: true })]);
|
|
2776
|
-
}
|
|
2777
|
-
function createEntitlementStore(floorDecisions = compiledDefaultDecisions) {
|
|
2778
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
2779
|
-
let snapshot = Object.freeze({
|
|
2780
|
-
decisions: floorDecisions(),
|
|
2781
|
-
isPending: false,
|
|
2782
|
-
branding: null
|
|
2783
|
-
});
|
|
2784
|
-
const emit = () => {
|
|
2785
|
-
for (const listener of listeners) listener();
|
|
2786
|
-
};
|
|
2787
|
-
return {
|
|
2788
|
-
subscribe(listener) {
|
|
2789
|
-
listeners.add(listener);
|
|
2790
|
-
return () => {
|
|
2791
|
-
listeners.delete(listener);
|
|
2792
|
-
};
|
|
2793
|
-
},
|
|
2794
|
-
getSnapshot() {
|
|
2795
|
-
return snapshot;
|
|
2796
|
-
},
|
|
2797
|
-
set(next) {
|
|
2798
|
-
snapshot = Object.freeze({
|
|
2799
|
-
decisions: Object.freeze([...next.decisions]),
|
|
2800
|
-
isPending: next.isPending,
|
|
2801
|
-
// Branding is additive; default to null (the compiled Everfur theme) when a caller omits it.
|
|
2802
|
-
branding: next.branding ?? null
|
|
2803
|
-
});
|
|
2804
|
-
emit();
|
|
2805
|
-
},
|
|
2806
|
-
reset() {
|
|
2807
|
-
snapshot = Object.freeze({
|
|
2808
|
-
decisions: floorDecisions(),
|
|
2809
|
-
isPending: false,
|
|
2810
|
-
branding: null
|
|
2811
|
-
});
|
|
2812
|
-
emit();
|
|
2813
|
-
}
|
|
2814
|
-
};
|
|
2815
|
-
}
|
|
2816
|
-
function createEverfurRuntime(input, opts) {
|
|
2817
|
-
return new EverfurRuntimeImpl(input, opts);
|
|
2818
|
-
}
|
|
2819
|
-
var PER_USER_KV_KEYS = Object.freeze([]);
|
|
2820
|
-
var EverfurRuntimeImpl = class {
|
|
2821
|
-
constructor(input, opts) {
|
|
2822
|
-
/**
|
|
2823
|
-
* One `x-everfur-session-id` for the life of this runtime. It MUST be stable across requests: the server
|
|
2824
|
-
* derives the anonymous identity from it, so a per-request value makes every call a different user and the
|
|
2825
|
-
* create/send pair can never agree. Minted here, never persisted, never a credential.
|
|
2826
|
-
*/
|
|
2827
|
-
/**
|
|
2828
|
-
* Rotated on sign-out. The server derives the ANONYMOUS identity from this
|
|
2829
|
-
* (`user_ref = f"anon-{session_id}"`), so keeping it across a logout would leave the next anonymous
|
|
2830
|
-
* session inheriting the previous user's server-side conversation history.
|
|
2831
|
-
*/
|
|
2832
|
-
this.sessionId = newSessionId();
|
|
2833
|
-
// ONE ref-counted controller table keyed by `${epoch}|${kind}|${scopeKey}`, plus each controller's
|
|
2834
|
-
// destroyer, so a re-scope / dispose can tear every open controller down without naming its type.
|
|
2835
|
-
this.entries = /* @__PURE__ */ new Map();
|
|
2836
|
-
this.destroyers = /* @__PURE__ */ new Map();
|
|
2837
|
-
this.epoch = 0;
|
|
2838
|
-
this.disposed = false;
|
|
2839
|
-
const cfg = input.config;
|
|
2840
|
-
if (cfg.secureStore !== void 0 && cfg.secureStore.isAvailable === true) {
|
|
2841
|
-
throw new EverfurConfigError(
|
|
2842
|
-
"invalid-argument",
|
|
2843
|
-
"config.secureStore is not yet consumable: SDK token persistence is unimplemented. Omit secureStore to keep memory-only tokens (SPEC-10 \xA75.3)."
|
|
2844
|
-
);
|
|
2845
|
-
}
|
|
2846
|
-
this.telemetry = cfg.telemetry ?? noopTelemetry;
|
|
2847
|
-
const publishableKey = typeof cfg?.publishableKey === "string" ? cfg.publishableKey.trim() : "";
|
|
2848
|
-
let failure = checkPublishableKey(cfg?.publishableKey);
|
|
2849
|
-
const transportInjected = cfg.transport !== void 0;
|
|
2850
|
-
let resolvedTransport;
|
|
2851
|
-
if (failure !== null) {
|
|
2852
|
-
resolvedTransport = refusingTransport(failure);
|
|
2853
|
-
} else if (cfg.transport !== void 0) {
|
|
2854
|
-
resolvedTransport = cfg.transport;
|
|
2855
|
-
} else {
|
|
2856
|
-
const resolved = tryResolveClient(cfg);
|
|
2857
|
-
if (resolved.ok) {
|
|
2858
|
-
resolvedTransport = createHttpTransport({
|
|
2859
|
-
config: resolved.config,
|
|
2860
|
-
...opts?.eventSourceFactory ? { eventSourceFactory: opts.eventSourceFactory } : {}
|
|
2861
|
-
});
|
|
2862
|
-
} else {
|
|
2863
|
-
failure = resolved.failure;
|
|
2864
|
-
resolvedTransport = refusingTransport(resolved.failure);
|
|
2865
|
-
}
|
|
2866
|
-
}
|
|
2867
|
-
this.configFailure = failure;
|
|
2868
|
-
this.publishableKey = failure === null ? publishableKey : "";
|
|
2869
|
-
this.transport = resolvedTransport;
|
|
2870
|
-
if (failure !== null) {
|
|
2871
|
-
reportConfigFailure(failure, this.telemetry);
|
|
2872
|
-
}
|
|
2873
|
-
this.errorPolicy = cfg.errorPolicy;
|
|
2874
|
-
this.camera = cfg.camera ?? unavailableCamera;
|
|
2875
|
-
this.upload = cfg.upload ?? unavailableUpload;
|
|
2876
|
-
this.uploadTransport = cfg.uploadTransport ?? unavailableUploadTransport;
|
|
2877
|
-
this.imageCache = cfg.imageCache ?? noopImageCache;
|
|
2878
|
-
this.kv = cfg.storage ?? createInMemoryKv();
|
|
2879
|
-
this.currentUser = input.user ?? null;
|
|
2880
|
-
this.identity = input.user ? createIdentityProvider(input.user.userRef, input.user.getToken) : null;
|
|
2881
|
-
this.activePet = input.activePet;
|
|
2882
|
-
this.store = failure === null ? createEntitlementStore() : createEntitlementStore(() => deniedDecisionsFor("sdk_config", userFacingError("accessDenied")));
|
|
2883
|
-
this.services = {
|
|
2884
|
-
authFor: (userRef) => this.buildAuth(userRef),
|
|
2885
|
-
telemetry: this.telemetry,
|
|
2886
|
-
errorPolicy: this.errorPolicy,
|
|
2887
|
-
camera: this.camera,
|
|
2888
|
-
upload: this.upload,
|
|
2889
|
-
uploadTransport: this.uploadTransport,
|
|
2890
|
-
imageCache: this.imageCache,
|
|
2891
|
-
kv: this.kv
|
|
2892
|
-
};
|
|
2893
|
-
this.registry = {
|
|
2894
|
-
services: this.services,
|
|
2895
|
-
acquireChat: (scope) => this.acquireInternal(
|
|
2896
|
-
"chat",
|
|
2897
|
-
`${scope.userRef ?? ""}|${scope.petRef ?? ""}|${scope.conversationId ?? ""}`,
|
|
2898
|
-
() => this.buildChatController(scope),
|
|
2899
|
-
(controller) => controller.dispose()
|
|
2900
|
-
),
|
|
2901
|
-
releaseChat: (controller) => this.releaseInternal(controller),
|
|
2902
|
-
acquire: (kind, scopeKey, create, destroy) => this.acquireInternal(kind, scopeKey, create, destroy),
|
|
2903
|
-
release: (controller) => this.releaseInternal(controller)
|
|
2904
|
-
};
|
|
2905
|
-
this.entitlements = this.store;
|
|
2906
|
-
const shouldPoll = failure === null && (opts?.startEntitlementPolling ?? !transportInjected);
|
|
2907
|
-
this.poller = shouldPoll ? this.buildPoller(opts?.pollScheduler) : null;
|
|
2908
|
-
this.poller?.start();
|
|
2909
|
-
}
|
|
2910
|
-
get isDisposed() {
|
|
2911
|
-
return this.disposed;
|
|
2912
|
-
}
|
|
2913
|
-
get scopeEpoch() {
|
|
2914
|
-
return this.epoch;
|
|
2915
|
-
}
|
|
2916
|
-
/**
|
|
2917
|
-
* Build the entitlement poller. `authFor` re-derives the device AuthContext each poll (so a token refresh /
|
|
2918
|
-
* re-scope is reflected), and `update` feeds the resolved decisions into the render store. The SERVER stays
|
|
2919
|
-
* authoritative; this only populates what the SDK renders.
|
|
2920
|
-
*/
|
|
2921
|
-
buildPoller(scheduler) {
|
|
2922
|
-
return createEntitlementPoller({
|
|
2923
|
-
authFor: () => this.buildAuth(this.currentUser?.userRef ?? null),
|
|
2924
|
-
update: (decisions, branding) => this.updateEntitlements({ decisions, isPending: false, branding }),
|
|
2925
|
-
telemetry: this.telemetry,
|
|
2926
|
-
...scheduler ? { scheduler } : {}
|
|
2927
|
-
});
|
|
2928
|
-
}
|
|
2929
|
-
// ---- ref-counted acquire / release (epoch-keyed) -----------------------
|
|
2930
|
-
acquireInternal(kind, scopeKey, create, destroy) {
|
|
2931
|
-
const key = `${this.epoch}|${kind}|${scopeKey}`;
|
|
2932
|
-
const existing = this.entries.get(key);
|
|
2933
|
-
if (existing) {
|
|
2934
|
-
existing.refCount += 1;
|
|
2935
|
-
return existing.controller;
|
|
2936
|
-
}
|
|
2937
|
-
const controller = create();
|
|
2938
|
-
this.entries.set(key, { controller, refCount: 1 });
|
|
2939
|
-
this.destroyers.set(controller, destroy);
|
|
2940
|
-
return controller;
|
|
2941
|
-
}
|
|
2942
|
-
releaseInternal(controller) {
|
|
2943
|
-
for (const [key, entry] of this.entries) {
|
|
2944
|
-
if (entry.controller !== controller) continue;
|
|
2945
|
-
entry.refCount -= 1;
|
|
2946
|
-
if (entry.refCount <= 0) {
|
|
2947
|
-
this.runDestroyer(controller);
|
|
2948
|
-
this.entries.delete(key);
|
|
2949
|
-
}
|
|
2950
|
-
return;
|
|
2951
|
-
}
|
|
2952
|
-
}
|
|
2953
|
-
runDestroyer(controller) {
|
|
2954
|
-
const destroy = this.destroyers.get(controller);
|
|
2955
|
-
this.destroyers.delete(controller);
|
|
2956
|
-
if (destroy) destroy(controller);
|
|
2957
|
-
}
|
|
2958
|
-
// ---- controller construction (only the spine capability is built here) -
|
|
2959
|
-
buildChatController(scope) {
|
|
2960
|
-
const controller = createChatController({
|
|
2961
|
-
auth: this.buildAuth(scope.userRef),
|
|
2962
|
-
telemetry: this.telemetry,
|
|
2963
|
-
...this.errorPolicy ? { errorPolicy: this.errorPolicy } : {},
|
|
2964
|
-
initialConversationId: scope.conversationId
|
|
2965
|
-
});
|
|
2966
|
-
const input = {};
|
|
2967
|
-
if (scope.petRef !== null) input.petRef = scope.petRef;
|
|
2968
|
-
if (scope.conversationId !== null) input.resumeConversationId = scope.conversationId;
|
|
2969
|
-
void bootstrapChat(input, { controller }).then((result) => controller.adoptPrompts(result.suggestedPrompts)).catch(() => {
|
|
2970
|
-
});
|
|
2971
|
-
return controller;
|
|
2972
|
-
}
|
|
2973
|
-
buildAuth(scopeUserRef) {
|
|
2974
|
-
if (this.identity !== null && this.currentUser !== null) {
|
|
2975
|
-
return {
|
|
2976
|
-
mode: "personalized",
|
|
2977
|
-
transport: this.transport,
|
|
2978
|
-
identity: this.identity,
|
|
2979
|
-
userRef: this.currentUser.userRef,
|
|
2980
|
-
sessionId: this.sessionId
|
|
2981
|
-
};
|
|
2982
|
-
}
|
|
2983
|
-
return {
|
|
2984
|
-
mode: "anonymous",
|
|
2985
|
-
transport: this.transport,
|
|
2986
|
-
publishableKey: this.publishableKey,
|
|
2987
|
-
// Only name a user while one is actually signed in. `scopeUserRef` is the REGISTRY scope key,
|
|
2988
|
-
// taken from the host's `user` prop, which a `logout()` call does not touch — so carrying it here
|
|
2989
|
-
// meant that after sign-out the SDK kept sending `x-everfur-user-ref` for the signed-out user
|
|
2990
|
-
// alongside the publishable key, and the widget plane resolves identity from exactly that pair.
|
|
2991
|
-
userRef: this.currentUser === null ? null : scopeUserRef,
|
|
2992
|
-
sessionId: this.sessionId
|
|
2993
|
-
};
|
|
2994
|
-
}
|
|
2995
|
-
// ---- imperative verbs (re-scope in one commit; SPEC-10 §3) -------------
|
|
2996
|
-
setUser(user) {
|
|
2997
|
-
if (this.disposed) return;
|
|
2998
|
-
const nextRef = user?.userRef ?? null;
|
|
2999
|
-
const currentRef = this.currentUser?.userRef ?? null;
|
|
3000
|
-
if (nextRef === currentRef) {
|
|
3001
|
-
this.currentUser = user;
|
|
3002
|
-
if (user && this.identity === null) {
|
|
3003
|
-
this.identity = createIdentityProvider(user.userRef, user.getToken);
|
|
3004
|
-
}
|
|
3005
|
-
return;
|
|
3006
|
-
}
|
|
3007
|
-
this.identity?.clear();
|
|
3008
|
-
this.currentUser = user;
|
|
3009
|
-
this.identity = user ? createIdentityProvider(user.userRef, user.getToken) : null;
|
|
3010
|
-
this.rescopeAll();
|
|
3011
|
-
}
|
|
3012
|
-
async logout() {
|
|
3013
|
-
if (this.disposed) return;
|
|
3014
|
-
const wasAnonymous = this.currentUser === null;
|
|
3015
|
-
this.sessionId = newSessionId();
|
|
3016
|
-
this.setUser(null);
|
|
3017
|
-
if (wasAnonymous) this.rescopeAll();
|
|
3018
|
-
await this.sweepPerUserKv();
|
|
3019
|
-
}
|
|
3020
|
-
async sweepPerUserKv() {
|
|
3021
|
-
if (PER_USER_KV_KEYS.length === 0) return;
|
|
3022
|
-
const results = await Promise.allSettled(
|
|
3023
|
-
PER_USER_KV_KEYS.map((key) => this.kv.removeItem(key))
|
|
3024
|
-
);
|
|
3025
|
-
const failedCount = results.filter((result) => result.status === "rejected").length;
|
|
3026
|
-
if (failedCount > 0) {
|
|
3027
|
-
this.telemetry.track("sdk.logout.sweepPartialFailure", {
|
|
3028
|
-
failedCount,
|
|
3029
|
-
totalCount: results.length
|
|
3030
|
-
});
|
|
3031
|
-
}
|
|
3032
|
-
}
|
|
3033
|
-
async registerPet(pet, profile) {
|
|
3034
|
-
if (this.disposed) {
|
|
3035
|
-
return err(
|
|
3036
|
-
makeEverfurError("validationFailed", {
|
|
3037
|
-
retryable: false,
|
|
3038
|
-
wireMessage: "the Everfur runtime is disposed; registerPet was called after unmount"
|
|
3039
|
-
})
|
|
3040
|
-
);
|
|
3041
|
-
}
|
|
3042
|
-
const repo = createPetsRepository(this.buildAuth(this.currentUser?.userRef ?? null));
|
|
3043
|
-
return profile === void 0 ? repo.registerPet(pet) : repo.registerPet(pet, profile);
|
|
3044
|
-
}
|
|
3045
|
-
setActivePet(pet) {
|
|
3046
|
-
if (this.disposed) return;
|
|
3047
|
-
const next = pet ?? null;
|
|
3048
|
-
if (next === this.activePet) return;
|
|
3049
|
-
this.activePet = next;
|
|
3050
|
-
this.rescopeAll();
|
|
3051
|
-
}
|
|
3052
|
-
updateEntitlements(next) {
|
|
3053
|
-
if (this.disposed) return;
|
|
3054
|
-
if (this.configFailure !== null) return;
|
|
3055
|
-
this.store.set(next);
|
|
3056
|
-
}
|
|
3057
|
-
open(capability) {
|
|
3058
|
-
this.telemetry.track("sdk.open", { capability });
|
|
3059
|
-
}
|
|
3060
|
-
dispose() {
|
|
3061
|
-
if (this.disposed) return;
|
|
3062
|
-
this.disposed = true;
|
|
3063
|
-
this.epoch += 1;
|
|
3064
|
-
this.poller?.stop();
|
|
3065
|
-
this.identity?.clear();
|
|
3066
|
-
this.disposeAllControllers();
|
|
3067
|
-
}
|
|
3068
|
-
rescopeAll() {
|
|
3069
|
-
this.epoch += 1;
|
|
3070
|
-
this.disposeAllControllers();
|
|
3071
|
-
this.store.reset();
|
|
3072
|
-
this.poller?.refresh();
|
|
3073
|
-
}
|
|
3074
|
-
disposeAllControllers() {
|
|
3075
|
-
for (const entry of this.entries.values()) this.runDestroyer(entry.controller);
|
|
3076
|
-
this.entries.clear();
|
|
3077
|
-
this.destroyers.clear();
|
|
3078
|
-
}
|
|
3079
|
-
};
|
|
3080
|
-
function tryResolveClient(cfg) {
|
|
3081
|
-
const clientCfg = {
|
|
3082
|
-
publishableKey: cfg.publishableKey,
|
|
3083
|
-
...cfg.apiBaseUrl !== void 0 ? { apiBaseUrl: cfg.apiBaseUrl } : {},
|
|
3084
|
-
...cfg.contractVersion !== void 0 ? { contractVersion: cfg.contractVersion } : {},
|
|
3085
|
-
...cfg.debug !== void 0 ? { debug: cfg.debug } : {}
|
|
3086
|
-
};
|
|
3087
|
-
return tryResolveClientConfig(clientCfg);
|
|
3088
|
-
}
|
|
3089
|
-
function reportConfigFailure(failure, telemetry) {
|
|
3090
|
-
try {
|
|
3091
|
-
telemetry.trackExpectedFailure("sdk.config.invalid", { reason: failure.reason });
|
|
3092
|
-
} catch {
|
|
3093
|
-
}
|
|
3094
|
-
const globalConsole = globalThis.console;
|
|
3095
|
-
globalConsole?.error?.(
|
|
3096
|
-
`[everfur] SDK disabled: ${failure.message}
|
|
3097
|
-
[everfur] Every Everfur capability will render its off-state until this is fixed. If the value is set in your environment, note that babel-preset-expo inlines only EXPO_PUBLIC_* variables into a release bundle.`
|
|
3098
|
-
);
|
|
3099
|
-
}
|
|
3100
|
-
function refusingTransport(failure) {
|
|
3101
|
-
const build = () => (
|
|
3102
|
-
// NOT `internalError`: the funnel's `decideRetry` keys on `isAutoRetryable(code)` and deliberately
|
|
3103
|
-
// ignores `error.retryable`, so `internalError` would be retried with backoff on every call even though
|
|
3104
|
-
// it can never succeed; and `categoryFor('internalError')` is `server`, i.e. "the server admits fault",
|
|
3105
|
-
// which would blame Everfur's backend for the partner's own config defect on their dashboards. The
|
|
3106
|
-
// whole point of the `sdk_config` level is to attribute this correctly. `validationFailed` is terminal
|
|
3107
|
-
// (`invalidRequest`: "retrying it unchanged can never succeed"), which is exactly true here.
|
|
3108
|
-
makeEverfurError("validationFailed", {
|
|
3109
|
-
retryable: false,
|
|
3110
|
-
// Developer-facing only: `wireMessage` is NON-ENUMERABLE and never rendered (EverfurError.ts).
|
|
3111
|
-
wireMessage: `Everfur SDK is not configured: ${failure.message}`
|
|
3112
|
-
})
|
|
3113
|
-
);
|
|
3114
|
-
return Object.freeze({
|
|
3115
|
-
request() {
|
|
3116
|
-
return Promise.resolve(err(build()));
|
|
3117
|
-
},
|
|
3118
|
-
stream(_req, signal) {
|
|
3119
|
-
const frame = errorFrame({
|
|
3120
|
-
code: "sdk_not_configured",
|
|
3121
|
-
retryable: false,
|
|
3122
|
-
wireMessage: `Everfur SDK is not configured: ${failure.message}`,
|
|
3123
|
-
synthesized: true,
|
|
3124
|
-
lastEventId: null
|
|
3125
|
-
});
|
|
3126
|
-
return {
|
|
3127
|
-
async *[Symbol.asyncIterator]() {
|
|
3128
|
-
if (signal.aborted) return;
|
|
3129
|
-
yield frame;
|
|
3130
|
-
}
|
|
3131
|
-
};
|
|
3132
|
-
}
|
|
3133
|
-
});
|
|
3134
|
-
}
|
|
3135
|
-
function createInMemoryKv() {
|
|
3136
|
-
const map = /* @__PURE__ */ new Map();
|
|
3137
|
-
return {
|
|
3138
|
-
async getItem(key) {
|
|
3139
|
-
return map.get(key) ?? null;
|
|
3140
|
-
},
|
|
3141
|
-
async setItem(key, value) {
|
|
3142
|
-
map.set(key, value);
|
|
3143
|
-
},
|
|
3144
|
-
async removeItem(key) {
|
|
3145
|
-
map.delete(key);
|
|
3146
|
-
},
|
|
3147
|
-
async keys(prefix) {
|
|
3148
|
-
return [...map.keys()].filter((k) => k.startsWith(prefix));
|
|
3149
|
-
}
|
|
3150
|
-
};
|
|
3151
|
-
}
|
|
3152
|
-
var unavailableUploadTransport = Object.freeze({
|
|
3153
|
-
postMultipart() {
|
|
3154
|
-
return Promise.reject(
|
|
3155
|
-
new Error("UploadTransport is unavailable; no records upload adapter was injected")
|
|
3156
|
-
);
|
|
3157
|
-
}
|
|
3158
|
-
});
|
|
3159
|
-
var noopImageCache = Object.freeze({
|
|
3160
|
-
clearMemoryCache() {
|
|
3161
|
-
},
|
|
3162
|
-
clearDiskCache() {
|
|
3163
|
-
}
|
|
3164
|
-
});
|
|
3165
|
-
|
|
3166
|
-
export { MESSAGE_MAX_CHARS, MIN_POLL_INTERVAL_SECONDS, NULL_SECURE_STORE, bootstrapChat, createChatController, createEntitlementPoller, createEverfurRuntime, defaultErrorPolicy, noopTelemetry, optionalModule, unavailableCamera };
|
|
1
|
+
import {z as z$1}from'zod';var Ho=Object.defineProperty;var i=(e,t)=>Ho(e,"name",{value:t,configurable:true});function _(e,t){return Object.freeze(t===void 0?{ok:true,value:e}:{ok:true,value:e,warning:t})}i(_,"ok");function f(e){return Object.freeze({ok:false,error:e})}i(f,"err");var xe=class xe extends Error{constructor(t,r){super(r),this.name="EverfurConfigError",this.kind=t,Object.setPrototypeOf(this,xe.prototype);}};i(xe,"EverfurConfigError");var H=xe;var Jl=Object.freeze({isAvailable:false,async getSecret(){return null},async setSecret(){throw new H("not-initialized","EF_NO_SECURE_STORE: token persistence requires an explicit SecureStorePort")},async deleteSecret(){}});var Ie=Object.freeze({track(){},trackExpectedFailure(){}});var Je=Object.freeze([Object.freeze({wireCode:"AccessDeniedException",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"AuthorizationException",envelope:"http_envelope",httpStatus:401,retryable:false}),Object.freeze({wireCode:"ConflictException",envelope:"http_envelope",httpStatus:409,retryable:true}),Object.freeze({wireCode:"DAILY_QUOTA_EXCEEDED",envelope:"http_envelope",httpStatus:429,retryable:true}),Object.freeze({wireCode:"FILE_TOO_LARGE",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"IDEMPOTENCY_KEY_IN_FLIGHT",envelope:"http_envelope",httpStatus:409,retryable:true}),Object.freeze({wireCode:"IDEMPOTENCY_KEY_REUSED_DIFFERENT_REQUEST",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"INVALID_CONTENT_TYPE",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"InternalFailureException",envelope:"http_envelope",httpStatus:500,retryable:true}),Object.freeze({wireCode:"MethodNotAllowedException",envelope:"http_envelope",httpStatus:405,retryable:false}),Object.freeze({wireCode:"NotImplementedException",envelope:"http_envelope",httpStatus:501,retryable:false}),Object.freeze({wireCode:"PaymentRequiredException",envelope:"http_envelope",httpStatus:402,retryable:false}),Object.freeze({wireCode:"ResourceNotFoundException",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"ServiceUnavailableException",envelope:"http_envelope",httpStatus:503,retryable:true}),Object.freeze({wireCode:"TIER_UPGRADE_REQUIRED",envelope:"http_envelope",httpStatus:402,retryable:false}),Object.freeze({wireCode:"ThrottlingException",envelope:"http_envelope",httpStatus:429,retryable:true}),Object.freeze({wireCode:"ValidationException",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"accessDenied",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"access_denied",envelope:"oauth_error",httpStatus:302,retryable:false}),Object.freeze({wireCode:"attachment_unreadable",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"authExpired",envelope:"http_envelope",httpStatus:401,retryable:true}),Object.freeze({wireCode:"authRejected",envelope:"http_envelope",httpStatus:401,retryable:false}),Object.freeze({wireCode:"consent_invalid",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"consent_required",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"consent_scope_wrong_route",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"device_cipher_unavailable",envelope:"http_envelope",httpStatus:503,retryable:true}),Object.freeze({wireCode:"email_invalid",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"event_cursor_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"event_filter_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"event_payload_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"event_type_not_available",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"event_type_unknown",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"idempotency_key_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"idempotency_key_required",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"idempotency_key_reused",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"insufficientCapability",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"insufficient_scope",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"internal_error",envelope:"sse_frame",httpStatus:200,retryable:false}),Object.freeze({wireCode:"invalidRequest",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_client",envelope:"oauth_error",httpStatus:401,retryable:false}),Object.freeze({wireCode:"invalid_client_metadata",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_grant",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_redirect_uri",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_request",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_scope",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"invalid_target",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"mcp_connection_not_found",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"mcp_request_conflict",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"mcp_request_gone",envelope:"http_envelope",httpStatus:410,retryable:false}),Object.freeze({wireCode:"mcp_request_not_found",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"not_found",envelope:"sse_frame",httpStatus:200,retryable:false}),Object.freeze({wireCode:"partner_visit_link_conflict",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"partner_visit_owner_only",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"partner_visit_pet_already_mapped",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"payload_too_large",envelope:"http_envelope",httpStatus:413,retryable:false}),Object.freeze({wireCode:"petRefInUse",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"pet_health_list_removals_unconfirmed",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"pet_health_species_unsupported",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"pet_not_registered",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"provider_unsupported",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"rateLimited",envelope:"http_envelope",httpStatus:429,retryable:true}),Object.freeze({wireCode:"record_species_unsupported",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"record_subject_not_found",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"record_upload_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"records_consent_required",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"sandbox_only",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"session_required",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"share_limit_reached",envelope:"http_envelope",httpStatus:429,retryable:false}),Object.freeze({wireCode:"slow_down",envelope:"oauth_error",httpStatus:429,retryable:true}),Object.freeze({wireCode:"species_unsupported",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"tenant_filter_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"tenant_has_no_capabilities",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"tenant_resource_not_found",envelope:"http_envelope",httpStatus:404,retryable:false}),Object.freeze({wireCode:"tenant_surface_not_enabled",envelope:"http_envelope",httpStatus:409,retryable:false}),Object.freeze({wireCode:"timeout",envelope:"sse_frame",httpStatus:200,retryable:true}),Object.freeze({wireCode:"token_invalid",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"unavailable",envelope:"sse_frame",httpStatus:200,retryable:true}),Object.freeze({wireCode:"unavailable",envelope:"http_envelope",httpStatus:503,retryable:true}),Object.freeze({wireCode:"unsupported_grant_type",envelope:"oauth_error",httpStatus:400,retryable:false}),Object.freeze({wireCode:"unsupported_response_type",envelope:"oauth_error",httpStatus:302,retryable:false}),Object.freeze({wireCode:"verify_mint_rate_limited",envelope:"http_envelope",httpStatus:429,retryable:true}),Object.freeze({wireCode:"verify_mint_refused",envelope:"http_envelope",httpStatus:403,retryable:false}),Object.freeze({wireCode:"verify_mint_unavailable",envelope:"http_envelope",httpStatus:503,retryable:true}),Object.freeze({wireCode:"verify_user_ref_invalid",envelope:"http_envelope",httpStatus:422,retryable:false}),Object.freeze({wireCode:"webhook_endpoint_update_empty",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"webhook_endpoint_update_invalid",envelope:"http_envelope",httpStatus:400,retryable:false}),Object.freeze({wireCode:"webhook_url_rejected",envelope:"http_envelope",httpStatus:400,retryable:false})]);Object.freeze(Je.map(e=>e.wireCode));var Ko=Object.freeze({ValidationException:"validationFailed",AuthorizationException:"authRejected",PaymentRequiredException:"paymentRequired",AccessDeniedException:"accessDenied",ResourceNotFoundException:"resourceNotFound",ConflictException:"conflict",ThrottlingException:"rateLimited",InternalFailureException:"internalError",NotImplementedException:"notImplemented",ServiceUnavailableException:"serviceUnavailable",MethodNotAllowedException:"validationFailed",authExpired:"authExpired",unavailable:"serviceUnavailable",session_required:"sessionRequired",accessDenied:"accessDenied",invalidRequest:"sdkUpdateRequired",authRejected:"authRejected",rateLimited:"rateLimited",insufficientCapability:"accessDenied",event_cursor_invalid:"validationFailed",event_filter_invalid:"validationFailed",event_payload_invalid:"validationFailed",event_type_unknown:"validationFailed",idempotency_key_invalid:"validationFailed",idempotency_key_required:"validationFailed",idempotency_key_reused:"idempotencyConflict",payload_too_large:"validationFailed",webhook_url_rejected:"validationFailed",webhook_endpoint_update_empty:"validationFailed",webhook_endpoint_update_invalid:"validationFailed",event_type_not_available:"conflict",record_subject_not_found:"resourceNotFound",records_consent_required:"conflict",record_species_unsupported:"validationFailed",record_upload_invalid:"validationFailed",FILE_TOO_LARGE:"validationFailed",INVALID_CONTENT_TYPE:"validationFailed",attachment_unreadable:"validationFailed",provider_unsupported:"validationFailed",token_invalid:"validationFailed",device_cipher_unavailable:"serviceUnavailable",email_invalid:"validationFailed",consent_required:"validationFailed",consent_invalid:"validationFailed",consent_scope_wrong_route:"validationFailed",IDEMPOTENCY_KEY_IN_FLIGHT:"idempotencyInFlight",IDEMPOTENCY_KEY_REUSED_DIFFERENT_REQUEST:"idempotencyConflict",DAILY_QUOTA_EXCEEDED:"quotaExceeded",TIER_UPGRADE_REQUIRED:"paymentRequired",not_found:"conversationNotFound",timeout:"streamTimeout",internal_error:"internalError",invalid_request:"validationFailed",invalid_client:"authRejected",invalid_grant:"authRejected",unsupported_grant_type:"validationFailed",invalid_scope:"validationFailed",invalid_target:"validationFailed",invalid_redirect_uri:"validationFailed",invalid_client_metadata:"validationFailed",unsupported_response_type:"validationFailed",access_denied:"accessDenied",slow_down:"rateLimited",mcp_request_not_found:"resourceNotFound",mcp_request_gone:"resourceNotFound",mcp_connection_not_found:"resourceNotFound",mcp_request_conflict:"conflict",sandbox_only:"accessDenied",tenant_has_no_capabilities:"conflict",verify_mint_refused:"accessDenied",verify_mint_rate_limited:"rateLimited",verify_mint_unavailable:"serviceUnavailable",verify_user_ref_invalid:"validationFailed",insufficient_scope:"accessDenied",tenant_filter_invalid:"validationFailed",tenant_resource_not_found:"resourceNotFound",tenant_surface_not_enabled:"conflict",pet_health_species_unsupported:"validationFailed",pet_health_list_removals_unconfirmed:"validationFailed",petRefInUse:"conflict",share_limit_reached:"conflict",pet_not_registered:"resourceNotFound",species_unsupported:"validationFailed",partner_visit_owner_only:"accessDenied",partner_visit_link_conflict:"conflict",partner_visit_pet_already_mapped:"conflict"}),rr=Object.freeze(Je.map(e=>Object.freeze({wireCode:e.wireCode,envelope:e.envelope,retryable:e.retryable,normalized:Ko[e.wireCode]}))),$o=new Map(rr.map(e=>[e.envelope+e.wireCode.toUpperCase(),e])),Vo=Object.freeze(["http_envelope",...[...new Set(rr.map(e=>e.envelope))].filter(e=>e!=="http_envelope").sort()]);function Oe(e,t){if(typeof e!="string")return;let r=e.trim().toUpperCase();if(r.length!==0)for(let n of [t??"http_envelope",...Vo]){let o=$o.get(n+r);if(o)return o}}i(Oe,"contractErrorFor");function Wo(e){return e.envelope==="sse_frame"?`/errors#sse-${e.wireCode}`:e.envelope==="oauth_error"?`/errors#oauth-${e.wireCode}`:`/errors#${e.wireCode}`}i(Wo,"contractDocUrl");function nr(e){return null}i(nr,"publishedDocUrl");var Go=Object.freeze({authExpired:"authentication",authRejected:"authentication",sessionRequired:"authentication",accessDenied:"authorization",paymentRequired:"entitlement",quotaExceeded:"rateLimit",rateLimited:"rateLimit",validationFailed:"invalidRequest",sdkUpdateRequired:"invalidRequest",conversationNotFound:"notFound",petNotFound:"notFound",resourceNotFound:"notFound",conflict:"conflict",idempotencyConflict:"conflict",idempotencyInFlight:"conflict",streamTimeout:"connection",streamIncomplete:"connection",upstreamLlmTimeout:"connection",serviceUnavailable:"connection",internalError:"server",notImplemented:"server",mediaUploadFailed:"media",moderationBlocked:"policy",unknown:"unknown"});function or(e){return Go[e]}i(or,"categoryFor");function W(e){let t=Oe(e);if(t)return t.normalized;let r=(e??"").trim().toUpperCase(),n=r.replace(/[^A-Z0-9]/g,"");if(n==="AUTHREJECTED")return "authRejected";if(r.startsWith("AUTH"))return "authExpired";switch(n){case "DAILYQUOTAEXCEEDED":case "QUOTAEXCEEDED":return "quotaExceeded";case "RATELIMITED":case "TOOMANYREQUESTS":return "rateLimited";case "IDEMPOTENCYKEYCONFLICT":case "IDEMPOTENCYCONFLICT":return "idempotencyConflict";case "ACCESSDENIED":case "FORBIDDEN":return "accessDenied";case "NOTFOUND":case "CONVERSATIONNOTFOUND":return "conversationNotFound";case "PETNOTFOUND":return "petNotFound";case "TIMEOUT":case "STREAMTIMEOUT":return "streamTimeout";case "MEDIAUPLOADFAILED":case "UNRECOGNIZEDVIDEOFORMAT":case "FILETOOSMALL":return "mediaUploadFailed";case "MODERATIONBLOCKED":return "moderationBlocked";case "UPSTREAMLLMTIMEOUT":return "upstreamLlmTimeout";case "INTERNALERROR":case "INTERNALSERVERERROR":return "internalError";case "STREAMINCOMPLETE":case "CHATSTREAMINCOMPLETE":return "streamIncomplete";case "INVALIDANALYSISTYPE":case "INVALIDUPLOADPURPOSE":return "unknown";default:return "unknown"}}i(W,"fromWire");function ir(e){return e===401?"authExpired":e===403?"accessDenied":e===404?"conversationNotFound":e===409?"idempotencyConflict":e===421?"unknown":e===429?"rateLimited":e===400||e===422?"unknown":e>=500?"internalError":"unknown"}i(ir,"fromHttpStatus");var Yo=new Set(["streamTimeout","rateLimited","internalError","upstreamLlmTimeout","streamIncomplete"]);function J(e){return Yo.has(e)}i(J,"isAutoRetryable");var Xo=new Set(["serviceUnavailable","conflict","idempotencyInFlight"]);function sr(e){return J(e)||Xo.has(e)}i(sr,"isRetryableCode");function Ae(e,t=false){return t||J(e)}i(Ae,"shouldRetry");var Qo=500,Ze=8e3,de=4;function Fe(e,t=Math.random){let r=Math.max(0,e),n=Math.min(Qo*2**r,Ze);return Math.floor(t()*n)}i(Fe,"backoffDelayMs");function ar(e){return e==="conversationNotFound"}i(ar,"canRecreateOnNotFound");var lr=Object.freeze({shouldRetry(e,t){return J(e)&&t<de},maxAttempts(){return de}});var ur=Object.freeze({isAvailable:false,async capture(){return Promise.reject(new Error("CameraPort is unavailable; check isAvailable before calling capture"))}});function yu(e,t,r){let n;try{n=t();}catch(s){return et(`optional peer '${e}' is not installed: ${Zo(s)}`)}let o=Jo(n);return o==null?et(`optional peer '${e}' resolved to no module`):r&&!r(o)?et(`optional peer '${e}' is present but failed its shape check`):Object.freeze({available:true,module:o})}i(yu,"optionalModule");function Jo(e){return typeof e=="object"&&e!==null&&"default"in e&&Object.keys(e).length<=2?e.default:e}i(Jo,"unwrapDefault");function et(e){return Object.freeze({available:false,module:null,reason:e})}i(et,"frozenUnavailable");function Zo(e){return e instanceof Error?e.message:typeof e=="string"?e:"unknown load error"}i(Zo,"describe");function Me(e){throw new Error(`assertNever: unhandled discriminated-union member ${JSON.stringify(e)}`)}i(Me,"assertNever");function dr(e,t,r=null){return Object.freeze({kind:"accepted",streamId:e,lastEventId:t,serverRequestId:r,terminal:false})}i(dr,"acceptedFrame");function cr(e,t=null){return Object.freeze({kind:"heartbeat",lastEventId:e,serverRequestId:t,terminal:false})}i(cr,"heartbeatFrame");function fr(e,t,r=null){return Object.freeze({kind:"delta",delta:e,lastEventId:t,serverRequestId:r,terminal:false})}i(fr,"deltaFrame");function pr(e,t=null){return Object.freeze({kind:"done",terminal:true,conversationId:e.conversationId,messageId:e.messageId,title:e.title,followUpQuestions:Object.freeze([...e.followUpQuestions]),citations:Object.freeze([...e.citations]),citationStatus:e.citationStatus,urgencyLevel:e.urgencyLevel,urgencyReason:e.urgencyReason,urgencyProvided:e.urgencyProvided??e.urgencyLevel!==null,resultId:e.resultId,lastEventId:e.lastEventId,serverRequestId:t})}i(pr,"doneFrame");function N(e){return Object.freeze({kind:"error",terminal:true,code:e.code,retryable:e.retryable,wireMessage:e.wireMessage,synthesized:e.synthesized,lastEventId:e.lastEventId,serverRequestId:e.serverRequestId??null})}i(N,"errorFrame");function mr(e,t,r=null){return Object.freeze({kind:"analysisStarted",requestId:e,lastEventId:t,serverRequestId:r,terminal:false})}i(mr,"analysisStartedFrame");function yr(e,t=null){return Object.freeze({kind:"analysisComplete",terminal:false,resultId:e.resultId,analysisType:e.analysisType,modelVersion:e.modelVersion,confidence:e.confidence,detections:Object.freeze([...e.detections]),interpretation:e.interpretation,lastEventId:e.lastEventId,serverRequestId:t})}i(yr,"analysisCompleteFrame");function gr(e,t,r=null){return Object.freeze({kind:"unknown",raw:{...e},lastEventId:t,serverRequestId:r,terminal:false})}i(gr,"unknownFrame");var ri=Object.freeze({authExpired:"Please sign in again to continue.",authRejected:"Please sign in again to continue.",sessionRequired:"This app needs to be updated to keep using Everfur.",accessDenied:"This feature isn't available on your account right now.",paymentRequired:"This is part of a paid plan.",quotaExceeded:"You have used today's messages. This resets tomorrow.",rateLimited:"You are sending messages quickly. Try again in a few seconds.",validationFailed:"Something in that request was not right. Check the details and try again.",sdkUpdateRequired:"This app needs to be updated to keep using Everfur.",conflict:"That is already running. Wait for it to finish, then try again.",idempotencyConflict:"That message was already delivered.",idempotencyInFlight:"That is still processing. Give it a moment.",conversationNotFound:"This conversation is no longer available.",petNotFound:"We could not find that pet. Please pick a pet and try again.",resourceNotFound:"We could not find that.",streamTimeout:"The response timed out. Tap retry to try again.",mediaUploadFailed:"We could not upload that photo. Please attach it again.",moderationBlocked:"This request cannot be answered here.",upstreamLlmTimeout:"The response timed out. Tap retry to try again.",internalError:"We hit a snag on our end. Please try again.",notImplemented:"That is not available yet.",serviceUnavailable:"That service is briefly unavailable. Try again shortly.",streamIncomplete:"The connection dropped mid-answer. Tap retry to continue.",unknown:"Something went wrong. Please try again."});function tt(e){return ri[e]}i(tt,"userFacingError");function hr(e,t,r){Object.defineProperty(e,t,{value:r,enumerable:false,writable:false,configurable:false});}i(hr,"defineHidden");var ni=/^[a-z][a-z0-9_]{0,63}$/;function S(e,t){let r=Oe(t?.wireCode,t?.wireEnvelope),n={code:e,category:or(e),retryable:t?.retryable??sr(e),displayMessage:tt(e)};if(t?.httpStatus!==void 0&&(n.httpStatus=t.httpStatus),t?.requestId&&(n.requestId=t.requestId),typeof t?.reasonCode=="string"&&ni.test(t.reasonCode)&&(n.reasonCode=t.reasonCode),r);return t?.wireMessage&&hr(n,"wireMessage",t.wireMessage),t?.raw!==void 0&&t.raw!==null&&hr(n,"raw",t.raw),Object.freeze(n)}i(S,"makeEverfurError");function br(e,t,r){let n=null,o=null,s=false,l=i(()=>o||(o=(async()=>{try{let u=await t(),a=typeof u=="string"?u:u?.token;if(typeof a!="string"||a.length===0)throw new H("invalid-argument","TokenProvider returned an empty token");return n=a,r?.(typeof u=="string"?null:oi(u.expiresAt)),a}finally{o=null;}})(),o),"load");return {userRef:e,async currentToken(u){if(s)throw new H("not-initialized","This identity was cleared (sign-out); mint a new one.");return u?.forceRefresh&&(n=null),n!==null?n:l()},hasToken(){return !s&&n!==null},clear(){s=true,n=null;}}}i(br,"createIdentityProvider");function oi(e){if(e===void 0)return null;let t=typeof e=="number"?e<1e11?e*1e3:e:new Date(e).getTime();return Number.isFinite(t)?t:null}i(oi,"expiryMs");function nt(){let e=new Uint8Array(16),t=globalThis.crypto;if(typeof t?.getRandomValues=="function")t.getRandomValues(e);else for(let n=0;n<e.length;n+=1)e[n]=Math.floor(Math.random()*256);e[6]=e[6]&15|64,e[8]=e[8]&63|128;let r=[];for(let n=0;n<e.length;n+=1)r.push(e[n].toString(16).padStart(2,"0"));return r.slice(0,4).join("")+"-"+r.slice(4,6).join("")+"-"+r.slice(6,8).join("")+"-"+r.slice(8,10).join("")+"-"+r.slice(10,16).join("")}i(nt,"newSessionId");function ii(e){let t={};return e.mode==="personalized"?t.authorization=`Bearer ${e.token}`:t["x-everfur-partner-key"]=e.publishableKey,e.userRef&&(t["x-everfur-user-ref"]=e.userRef),e.sessionId&&(t["x-everfur-session-id"]=e.sessionId),t}i(ii,"authHeaders");function ce(e,t){return {...e,headers:{...si(e.headers),...ii(t)}}}i(ce,"withAuthHeaders");function si(e){if(!e)return {};let t={};for(let[r,n]of Object.entries(e)){let o=r.toLowerCase();o==="authorization"||o==="x-everfur-partner-key"||(t[r]=n);}return t}i(si,"stripAuthHeaders");async function vr(e,t){if(t.mode==="anonymous")return t.transport.request(ce(e,{mode:"anonymous",publishableKey:t.publishableKey,userRef:t.userRef,...t.sessionId?{sessionId:t.sessionId}:{}}));let r;try{r=await t.identity.currentToken();}catch{return f(rt())}let n=await t.transport.request(ce(e,{mode:"personalized",token:r,userRef:t.userRef,...t.sessionId?{sessionId:t.sessionId}:{}}));if(n.ok||n.error.httpStatus!==401)return n;let o;try{o=await t.identity.currentToken({forceRefresh:!0});}catch{return f(rt())}let s=await t.transport.request(ce(e,{mode:"personalized",token:o,userRef:t.userRef,...t.sessionId?{sessionId:t.sessionId}:{}}));return !s.ok&&s.error.httpStatus===401?f(rt(s.error.httpStatus)):s}i(vr,"authedSend");function rt(e){return S("authRejected",{retryable:false,...e!==void 0?{httpStatus:e}:{}})}i(rt,"authRejectedError");var _r=`
|
|
2
|
+
|
|
3
|
+
`,ai=1048576,li=z$1.record(z$1.string(),z$1.unknown()),ui=["emergency","schedule_soon","home_care"];async function*je(e,t=null){let r=null,n=i(()=>(r!==null||(r=typeof t=="function"?t():t),r),"requestIdNow"),o=new TextDecoder("utf-8"),s="",l=0,u=false;for await(let a of e){for(s+=o.decode(a,{stream:true});;){let d=s.indexOf(_r,l);if(d===-1)break;let c=s.slice(0,d);s=s.slice(d+_r.length),l=0;let m=Rr(c,n());if(m!==null&&(m.kind==="delta"&&(u=true),yield m,m.terminal))return}if(l=s.length>0?s.length-1:0,s.length>ai){yield N({code:u?"CHAT_STREAM_INCOMPLETE":"internal_error",retryable:true,wireMessage:null,synthesized:true,lastEventId:null,serverRequestId:n()});return}}if(s+=o.decode(),s.trim().length>0){let a=Rr(s,n());if(a!==null&&(a.kind==="delta"&&(u=true),yield a,a.terminal))return}yield N({code:u?"CHAT_STREAM_INCOMPLETE":"internal_error",retryable:true,wireMessage:null,synthesized:true,lastEventId:null,serverRequestId:n()});}i(je,"parseSse");function Rr(e,t){let r=null,n=[];for(let l of e.split(`
|
|
4
|
+
`)){let u=l.replace(/\s+$/,"");u.length===0||u.startsWith(":")||(u.startsWith("id:")?r=u.slice(3).trim():u.startsWith("data:")&&n.push(u.slice(5).replace(/^ /,"")));}if(n.length===0)return null;let o;try{o=JSON.parse(n.join(`
|
|
5
|
+
`));}catch{return null}if(typeof o!="object"||o===null||Array.isArray(o))return null;let s=li.safeParse(o);return s.success?di(s.data,r,t):null}i(Rr,"parseBlock");function di(e,t,r){let n=e.type,o=e.event;if(n==="error"||"error"in e)return N({code:z(e.code)??"unknown",retryable:e.retryable===true,wireMessage:z(e.error),synthesized:false,lastEventId:t,serverRequestId:r});if(n==="done"||e.done===true)return pr({conversationId:z(e.conversation_id)??"",messageId:z(e.message_id),title:z(e.title),followUpQuestions:pi(e.follow_up_questions),citations:Er(e.citations),citationStatus:z(e.citation_status),urgencyLevel:Cr(e.urgency_level),urgencyReason:z(e.urgency_reason),urgencyProvided:fi(e),resultId:z(e.result_id),lastEventId:t},r);if(n==="accepted"||e.status==="reasoning")return dr(z(e.stream_id),t,r);if(n==="heartbeat"||e.heartbeat===true)return cr(t,r);if(n==="text.delta"||"delta"in e||"token"in e){let s=z(e.delta)??z(e.token)??"";return fr(s,t,r)}return o==="analysis_started"?mr(z(e.request_id),t,r):o==="analysis_complete"?yr({resultId:z(e.result_id),analysisType:z(e.analysis_type),modelVersion:z(e.model_version),confidence:ci(e.confidence),detections:Er(e.detections),interpretation:z(e.interpretation),lastEventId:t},r):gr(e,t,r)}i(di,"frameFromWire");function z(e){return typeof e=="string"?e:null}i(z,"asString");function ci(e){return typeof e=="number"&&Number.isFinite(e)?e:null}i(ci,"asNumber");function Cr(e){return typeof e=="string"&&ui.includes(e)?e:null}i(Cr,"asUrgency");function fi(e){if(!Object.prototype.hasOwnProperty.call(e,"urgency_level"))return false;let t=e.urgency_level;return t===null||Cr(t)!==null}i(fi,"urgencySlotProvided");function pi(e){return Array.isArray(e)?e.map(t=>typeof t=="string"?t:String(t)):[]}i(pi,"asStringList");function mi(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}i(mi,"isPlainObject");function Er(e){return Array.isArray(e)?e.filter(mi):[]}i(Er,"asMapList");var yi="0.3.0",gi="react-native",hi="2026-09-19",Sr="EVERFUR_API_BASE_URL";function fe(e,t){return Object.freeze({ok:false,failure:Object.freeze({reason:e,message:t})})}i(fe,"configFailure");function it(e){let t=typeof e=="string"?e.trim():"";return t.length===0?{reason:"missing-publishable-key",message:"publishableKey is required"}:/^sk[_-]/i.test(t)?{reason:"secret-key-as-publishable-key",message:"publishableKey looks like a SECRET key (sk_...). A device must never hold a partner secret key: use the pk_ publishable key here, and keep the secret key on your server."}:null}i(it,"checkPublishableKey");function wr(e,t){let r=it(e?.publishableKey);if(r!==null)return Object.freeze({ok:false,failure:r});let n=e.publishableKey.trim(),o=bi(e.apiBaseUrl);if(!o.ok)return o;let s=e.contractVersion?.trim()||hi;return Object.freeze({ok:true,config:Object.freeze({publishableKey:n,apiBaseUrl:o.value,contractVersion:s,sdkVersion:yi,platform:t?.platform??gi,debug:e.debug===true})})}i(wr,"tryResolveClientConfig");function bi(e){let t=e?.trim(),r=t&&t.length>0?t:ki(Sr);return r?Si(r):fe("missing-api-base-url",`apiBaseUrl is required: pass config.apiBaseUrl or set ${Sr}. The SDK never ships a hardcoded host.`)}i(bi,"tryResolveApiBaseUrl");function kr(e){return {"X-Everfur-SDK-Version":e.sdkVersion,"X-Everfur-SDK-Platform":e.platform,"X-Everfur-Contract":e.contractVersion}}i(kr,"buildBaseHeaders");var vi=/^([A-Za-z][A-Za-z0-9+.-]*):\/\/([^/?#]*)/;function _i(e){return e.slice(e.lastIndexOf("@")+1).replace(/:\d+$/,"").toLowerCase()}i(_i,"hostOf");function Ri(e){return e.length===0||e.includes("@")?false:e.startsWith("[")&&e.endsWith("]")?true:!e.includes(":")}i(Ri,"isPrintableHost");function Ei(e,t){let r=e.indexOf("://");return r<0||e.slice(r+3).includes("@")?false:Ri(t)}i(Ei,"canEchoOrigin");function Ci(e,t){return `${e}://${t}`}i(Ci,"safeOrigin");function Si(e){let t=e.trim(),r=vi.exec(t);if(r===null||r[2]===void 0||r[2].length===0)return fe("malformed-api-base-url","apiBaseUrl is not a valid absolute URL");let n=(r[1]??"").toLowerCase(),o=_i(r[2]);if(o.length===0)return fe("malformed-api-base-url","apiBaseUrl is not a valid absolute URL");let s=Ei(t,o)?`: ${Ci(n,o)}`:"";if(n!=="https"){if(!(n==="http"&&wi(o)))return n==="http"?fe("insecure-api-base-url",`apiBaseUrl must use https (cleartext http is only allowed for localhost)${s}`):fe("unsupported-api-base-url-scheme",`apiBaseUrl must be http(s)${s}`)}let l=t.endsWith("/")?t.slice(0,-1):t;return Object.freeze({ok:true,value:l})}i(Si,"normalizeBaseUrl");function wi(e){let t=e.toLowerCase();return t==="localhost"||t==="127.0.0.1"||t==="[::1]"||t==="::1"}i(wi,"isLoopbackHost");function ki(e){let r=globalThis.process?.env?.[e];return typeof r=="string"&&r.trim().length>0?r.trim():void 0}i(ki,"readEnv");var Pi=3e4,Ir="x-request-id";async function*Pr(e){if(!e)return;let t=e.getReader();try{for(;;){let{done:r,value:n}=await t.read();if(r)break;n&&n.length>0&&(yield n);}}finally{await t.cancel?.();}}i(Pr,"fetchByteSource");function Ti(e){let t=new TextEncoder,r=Ii(),n=false,o=i(a=>{let d="";a.lastEventId&&(d+=`id: ${a.lastEventId}
|
|
6
|
+
`);let c=a.data??"";for(let m of c.split(`
|
|
7
|
+
`))d+=`data: ${m}
|
|
8
|
+
`;d+=`
|
|
9
|
+
`,r.push(t.encode(d));},"onMessage"),s=i(()=>{u(),r.end();},"onDone"),l=i(a=>{let d=typeof a.xhrStatus=="number"?a.xhrStatus:0;if(d>=400){let c=Fr(d),m=J(W(c));r.push(t.encode(`data: ${JSON.stringify({type:"error",code:c,retryable:m})}
|
|
10
|
+
|
|
11
|
+
`));}u(),r.end();},"onError");e.addEventListener("message",o),e.addEventListener("done",s),e.addEventListener("error",l);function u(){if(!n){n=true,e.removeEventListener("message",o),e.removeEventListener("done",s),e.removeEventListener("error",l);try{e.close();}catch{}}}return i(u,"cleanup"),xi(r.source,u)}i(Ti,"eventSourceByteSource");async function*xi(e,t){try{yield*e;}finally{t();}}i(xi,"sourceWithCleanup");function Ii(){let e=[],t=false,r=null,n=i(()=>{if(r){let s=r;r=null,s();}},"signal");async function*o(){for(;;){let s=e.shift();if(s!==void 0){yield s;continue}if(t)return;await new Promise(l=>{r=l;});}}return i(o,"gen"),{source:o(),push:i(s=>{e.push(s),n();},"push"),end:i(()=>{t=true,n();},"end")}}i(Ii,"createByteQueue");async function Oi(e,t){let r=t.fetchImpl??Mr(),n=jr(t.config.apiBaseUrl,e.path,e.query),o=Dr(t.config,e.headers,"application/json",e.body!==void 0&&e.multipart===void 0),s=zi(Pi),l=Ui(s.signal,e.signal),u;try{u=await r(n,zr({...e,signal:l},o));}catch(d){return f(st(d))}finally{s.cancel();}let a=await Ur(u);return u.ok?_(a):f(Mi(u.status,a,Ar(u)))}i(Oi,"requestJson");function Or(e){return {request:i(t=>Oi(t,e),"request"),stream:i((t,r)=>Ai(Di(t,r),e),"stream")}}i(Or,"createHttpTransport");async function*Ai(e,t){let r=jr(t.config.apiBaseUrl,e.path,e.query),n=Dr(t.config,e.headers,"text/event-stream",e.body!==void 0&&e.multipart===void 0);if(t.eventSourceFactory){let u=t.eventSourceFactory(r,Fi(e,n));yield*je(Ti(u),()=>ji(u));return}let o=t.fetchImpl??Mr(),s;try{s=await o(r,zr(e,n));}catch(u){yield Tr("",true,qr(u));return}let l=Ar(s);if(!s.ok){let u=await Ur(s),a=Lr(u)??Fr(s.status),d=Br(u)||J(W(a));yield Tr(a,d,Nr(u),l);return}if(s.body){yield*je(Pr(s.body),l);return}yield*je(Pr(null),l);}i(Ai,"streamFrames");function Fi(e,t){return {method:e.method,headers:t,pollingInterval:0,...e.body!==void 0?{body:JSON.stringify(e.body)}:{}}}i(Fi,"buildEventSourceInit");function Mi(e,t,r){let n=Lr(t),o=n?W(n):ir(e),s=Nr(t);return S(o,{httpStatus:e,...Br(t)?{retryable:true}:{},...r?{requestId:r}:{},...n?{wireCode:n}:{},...xr(t)?{reasonCode:xr(t)}:{},...s?{wireMessage:s}:{},...t!=null?{raw:t}:{}})}i(Mi,"errorFromResponse");function st(e){return S("internalError",{retryable:true,wireMessage:qr(e)})}i(st,"networkError");function Ar(e){let t=e.headers.get(Ir);return typeof t=="string"&&t.length>0?t:null}i(Ar,"requestIdOf");function ji(e){if(typeof e.getResponseHeader!="function")return null;let t;try{t=e.getResponseHeader(Ir);}catch{return null}return typeof t=="string"&&t.length>0?t:null}i(ji,"eventSourceRequestId");function Fr(e){return e===401?"AUTH_EXPIRED":e===403?"ACCESS_DENIED":e===404?"NOT_FOUND":e===409?"IDEMPOTENCY_CONFLICT":e===421?"MISDIRECTED_REQUEST":e===429?"RATE_LIMITED":e===400||e===422?"INVALID_REQUEST":e===503||e>=500?"INTERNAL_ERROR":""}i(Fr,"statusToWireCode");function Tr(e,t,r,n=null){return N({code:e,retryable:t,wireMessage:r,synthesized:true,lastEventId:null,serverRequestId:n})}i(Tr,"syntheticErrorFrame");function Mr(){let e=globalThis.fetch;if(typeof e!="function")throw new H("missing-peer-dependency","global fetch is unavailable; provide config.transport or an injected fetch implementation");return e}i(Mr,"getGlobalFetch");function jr(e,t,r){let n=t.startsWith("/")?t:`/${t}`,o=`${e}${n}`;if(r){let s=Object.entries(r).filter(l=>l[1]!==void 0).map(([l,u])=>`${encodeURIComponent(l)}=${encodeURIComponent(String(u))}`).join("&");s&&(o+=`?${s}`);}return o}i(jr,"buildUrl");function Dr(e,t,r,n){let o={...kr(e),accept:r};return n&&(o["content-type"]="application/json"),t&&Object.assign(o,t),o}i(Dr,"mergeHeaders");function zr(e,t){let r={method:e.method,headers:t};return e.multipart!==void 0?r.body=e.multipart:e.body!==void 0&&(r.body=JSON.stringify(e.body)),e.signal&&(r.signal=e.signal),r}i(zr,"buildInit");function Di(e,t){return e.signal?e:{...e,signal:t}}i(Di,"withSignal");function zi(e){let t=new AbortController,r=setTimeout(()=>t.abort(),e);return {signal:t.signal,cancel:i(()=>clearTimeout(r),"cancel")}}i(zi,"timeoutSignal");function Ui(e,t){if(!t)return e;let r=new AbortController;if(e.aborted||t.aborted)return r.abort(),r.signal;let n=i(()=>r.abort(),"onAbort");return e.addEventListener("abort",n,{once:true}),t.addEventListener("abort",n,{once:true}),r.signal}i(Ui,"mergeAbortSignals");async function Ur(e){try{return await e.json()}catch{return null}}i(Ur,"safeJson");function xr(e){let t=e,r=t?.error?.reason_code??t?.reason_code;return typeof r=="string"&&r.length>0?r:null}i(xr,"extractReasonCode");function Lr(e){let t=e,r=t?.error?.code??t?.code;return typeof r=="string"&&r.length>0?r:null}i(Lr,"extractWireCode");function Nr(e){let t=e,r=t?.error?.message??t?.message;return typeof r=="string"&&r.length>0?r:null}i(Nr,"extractWireMessage");function Br(e){let t=e;return t?.error?.retryable===true||t?.retryable===true}i(Br,"extractRetryable");function qr(e){return e instanceof Error?e.message:typeof e=="string"?e:"network request failed"}i(qr,"describeCause");var Li=3e4,Ni=Ze*2,Bi="idempotency-key",qi=new Set(["POST","PUT","PATCH","DELETE"]),Hi=Object.freeze({onEvent(){}}),Ki=Object.freeze({setTimeout:i((e,t)=>setTimeout(e,t),"setTimeout"),clearTimeout:i(e=>clearTimeout(e),"clearTimeout"),now:i(()=>Date.now(),"now")});function K(e){let t=e.observer??Hi,r=e.timers??Ki,n=e.rng??Math.random,o=e.sleep??((h,g)=>ns(h,r,g)),s=e.maxAttempts??de,l=e.unaryTimeoutMs??Li,u=e.newIdempotencyKey??Vi(),a=i(h=>{try{t.onEvent(h);}catch{}},"emit");async function d(h,g,C){let P=C?.maxAttempts,E=Math.max(1,P??s),I=C?.idempotent??qi.has(g.method)?u():null,B=$i(g,I),O=0;for(;;){let b=i(ue=>Object.freeze({call:h,method:g.method,path:g.path,attempt:O,...I?{idempotencyKey:I}:{},...ue}),"stamp");a(b({phase:"attempt"}));let w=ts(l,r),D=rs(w.signal,g.signal),M;try{M=await vr({...B,signal:D.signal},e.auth);}catch(ue){M=f(st(ue));}finally{D.dispose(),w.cancel();}if(M.ok)return a(b({phase:"settled",ok:true,reason:"ok"})),M;let q=M.error,ne=Gi(q,O,{maxAttempts:E,rng:n,now:r.now(),aborted:g.signal?.aborted===true,...P!==void 0?{perCallMaxAttempts:P}:{},...e.errorPolicy!==void 0?{policy:e.errorPolicy}:{}}),ae={ok:false,code:q.code,reason:ne.reason,...q.httpStatus!==void 0?{httpStatus:q.httpStatus}:{},...q.requestId!==void 0?{requestId:q.requestId}:{}};if(!ne.retry)return a(b({phase:"settled",...ae})),f(q);if(a(b({phase:"retry",...ae,delayMs:ne.delayMs})),await o(ne.delayMs,g.signal),g.signal?.aborted===true)return a(b({phase:"settled",...ae,reason:"aborted"})),f(q);O+=1;}}i(d,"send");async function c(h){return ce(h,await es(e.auth))}i(c,"authorize");async function*m(h,g,C){a(Object.freeze({call:h,phase:"stream.open",method:g.method,path:g.path,attempt:0}));try{yield*e.auth.transport.stream(g,C);}catch{yield N({code:"internal_error",retryable:true,wireMessage:null,synthesized:true,lastEventId:null,serverRequestId:null});}}return i(m,"stream"),Object.freeze({send:d,authorize:c,stream:m})}i(K,"createRequestFunnel");function $i(e,t){let r={};for(let[n,o]of Object.entries(e.headers??{}))n.toLowerCase()!==Bi&&(r[n]=o);return t!==null&&(r["Idempotency-Key"]=t),{...e,headers:r}}i($i,"assembleHeaders");function Vi(){let e=0;return ()=>`efk_${Date.now().toString(36)}_${(e++).toString(36)}_${Math.random().toString(36).slice(2,12)}`}i(Vi,"defaultIdempotencyKeyFactory");var Wi=10;function Gi(e,t,r){if(r.aborted)return {retry:false,reason:"aborted"};let n=Yi(e);if(n==="quota")return {retry:false,reason:"daily-quota-exhausted"};if(n!=="burst"&&!J(e.code))return {retry:false,reason:"terminal-code"};let o=n==="burst"?"burst-throttle":"retryable-code";if(i(()=>{if(r.policy===void 0)return false;try{return !r.policy.shouldRetry(e.code,t)}catch{return false}},"policyVetoedRetry")())return {retry:false,reason:"terminal-code"};let l=i(()=>{if(r.policy===void 0)return null;let d;try{d=r.policy.maxAttempts(e.code);}catch{return null}return typeof d!="number"||!Number.isFinite(d)?null:Math.max(1,Math.min(Wi,Math.floor(d)))},"policyCeiling"),u=r.perCallMaxAttempts??l()??r.maxAttempts;if(t+1>=u)return {retry:false,reason:"attempts-exhausted"};let a=Xi(e,r.now);return a!==null?a>Ni?{retry:false,reason:"server-reset-beyond-budget"}:{retry:true,reason:o,delayMs:a}:{retry:true,reason:o,delayMs:Fe(t,r.rng)}}i(Gi,"decideRetry");function Yi(e){let t=e.code==="unknown"?W(Zi(e.raw)):e.code;return t==="quotaExceeded"?"quota":t==="rateLimited"||e.httpStatus===429?"burst":null}i(Yi,"throttleKind");function Xi(e,t){let r=Qi(e.raw);if(r===null)return null;let n=r-t;return n>0?n:0}i(Xi,"retryOverrideMs");function Qi(e){for(let t of Kr(e)){let r=t.resets_at,n=Ji(r);if(n!==null)return n}return null}i(Qi,"findResetsAt");function Kr(e){if(!Hr(e))return [];let t=[e];for(let r of ["error","detail"]){let n=e[r];Hr(n)&&t.push(n);}return t}i(Kr,"candidateScopes");function Ji(e){if(typeof e=="number"&&Number.isFinite(e))return e<1e11?Math.round(e*1e3):Math.round(e);if(typeof e=="string"&&e.trim().length>0){let t=Date.parse(e);return Number.isFinite(t)?t:null}return null}i(Ji,"parseInstantMs");function Zi(e){for(let t of Kr(e)){let r=t.code;if(typeof r=="string"&&r.length>0)return r}return null}i(Zi,"rawWireCode");function Hr(e){return typeof e=="object"&&e!==null}i(Hr,"isRecord");async function es(e){return e.mode==="anonymous"?{mode:"anonymous",publishableKey:e.publishableKey,userRef:e.userRef,...e.sessionId?{sessionId:e.sessionId}:{}}:{mode:"personalized",token:await e.identity.currentToken(),userRef:e.userRef,...e.sessionId?{sessionId:e.sessionId}:{}}}i(es,"resolveDeviceAuth");function ts(e,t){let r=new AbortController,n=t.setTimeout(()=>r.abort(),e);return {signal:r.signal,cancel:i(()=>t.clearTimeout(n),"cancel")}}i(ts,"boundedSignal");function rs(e,t){let r=i(()=>{},"noop");if(!t)return {signal:e,dispose:r};let n=new AbortController;if(e.aborted||t.aborted)return n.abort(),{signal:n.signal,dispose:r};let o=i(()=>n.abort(),"onAbort");return e.addEventListener("abort",o,{once:true}),t.addEventListener("abort",o,{once:true}),{signal:n.signal,dispose:i(()=>{e.removeEventListener("abort",o),t.removeEventListener("abort",o);},"dispose")}}i(rs,"mergeSignals");function ns(e,t,r){return e<=0||r?.aborted===true?Promise.resolve():new Promise(n=>{let o=t.setTimeout(()=>{r?.removeEventListener("abort",s),n();},e),s=i(()=>{t.clearTimeout(o),n();},"onAbort");r?.addEventListener("abort",s,{once:true});})}i(ns,"delayAbortable");function U(e){for(let t=0;t<e.length;t+=1){let r=e.charCodeAt(t);if(r>=55296&&r<=56319){let n=e.charCodeAt(t+1);if(!(n>=56320&&n<=57343))return true;t+=1;}else if(r>=56320&&r<=57343)return true}return false}i(U,"hasLoneSurrogate");function De(e){return [...e].length}i(De,"serverLength");var Gr=Object.freeze(["better","same","worse"]),lt=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;function $r(e){return f(S("validationFailed",{retryable:false,wireMessage:e}))}i($r,"invalid");function at(){return f(S("internalError",{retryable:false}))}i(at,"malformed");function Vr(e){return typeof e!="string"||e.trim().length===0?S("validationFailed",{retryable:false,wireMessage:"pet_ref must not be blank"}):U(e)?S("validationFailed",{retryable:false,wireMessage:"pet_ref contains an unpaired surrogate and cannot be encoded"}):`/widget/v1/pets/${encodeURIComponent(e)}/cases`}i(Vr,"petPath");var Z=i(e=>typeof e=="string"?e:null,"str");function Wr(e){if(typeof e!="object"||e===null)return null;let t=e,r=Z(t.case_id),n=Z(t.status);if(r===null||n===null)return null;let o=Z(t.last_response);return Object.freeze({caseId:r,status:n,bodyLocation:Z(t.body_location),lastResponse:o!==null&&Gr.includes(o)?o:null,checkInDueAt:Z(t.check_in_due_at),openedAt:Z(t.opened_at),resolvedAt:Z(t.resolved_at),resolutionText:Z(t.resolution_text)})}i(Wr,"caseFromWire");function Yr(e){return {async list(t,r){let n=Vr(t);if(typeof n!="string")return f(n);let o=await e.send("cases.list",{method:"GET",path:n,...r?.signal?{signal:r.signal}:{}});if(!o.ok)return f(o.error);let s=typeof o.value=="object"&&o.value!==null?o.value.cases:null;if(!Array.isArray(s))return at();let l=s.map(Wr);return l.every(u=>u!==null)?_(Object.freeze(l)):at()},async checkin(t,r,n,o){let s=Vr(t);if(typeof s!="string")return f(s);if(typeof r!="string"||!lt.test(r))return $r("case_id must be a UUID");if(!Gr.includes(n))return $r("response must be one of better, same, worse");let l=await e.send("cases.checkin",{method:"POST",path:`${s}/${r}/checkin`,body:{response:n},...o?.signal?{signal:o.signal}:{}});if(!l.ok)return f(l.error);let u=typeof l.value=="object"&&l.value!==null?l.value:{},a=Wr(u.case);return a===null?at():_(Object.freeze({case:a,ctaDeepLink:Z(u.cta_deep_link)}))}}}i(Yr,"createCasesRepositoryOver");var Xr=Object.freeze({async presignedPut(){return Promise.reject(new Error("UploadPort is unavailable; no presigned-upload adapter was injected"))}});var Qr=Object.freeze({setTimeout:i((e,t)=>setTimeout(e,t),"setTimeout"),clearTimeout:i(e=>clearTimeout(e),"clearTimeout"),now:i(()=>Date.now(),"now")});function Ue(e,t,r){return new Promise(n=>{if(t.aborted){n();return}let o={handle:void 0},s=i(()=>{r.clearTimeout(o.handle),t.removeEventListener("abort",s),n();},"done");o.handle=r.setTimeout(s,e),t.addEventListener("abort",s,{once:true});})}i(Ue,"delayAbortable");function Le(e,t){if(!t)return e;let r=new AbortController;if(e.aborted||t.aborted)return r.abort(),r.signal;let n=i(()=>r.abort(),"onAbort");return e.addEventListener("abort",n,{once:true}),t.addEventListener("abort",n,{once:true}),r.signal}i(Le,"mergeSignals");var ut=class ut{constructor(t){this.listeners=new Set;this.epoch=0;this.inFlight=null;this.snapshot=Object.freeze({...t});}subscribe(t){return this.listeners.add(t),()=>{this.listeners.delete(t);}}getSnapshot(){return this.snapshot}patch(t){this.snapshot=Object.freeze({...this.snapshot,...t});for(let r of this.listeners)r();}beginOperation(t){this.inFlight?.abort();let r=new AbortController;this.inFlight=r;let n=this.epoch;return {signal:t?Le(r.signal,t):r.signal,epoch:n,settle:i(()=>{this.inFlight===r&&(this.inFlight=null);},"settle")}}alive(t){return t===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();}};i(ut,"MediaStore");var ze=ut;function ct(e,t,r){return Object.freeze({id:e,role:"user",text:t,createdAt:r,pending:true})}i(ct,"makeUser");function ft(e,t,r){return Object.freeze({id:e,role:"assistant",text:t,createdAt:r})}i(ft,"makeAssistant");function me(e){return Object.freeze({id:e.id,role:e.role,text:e.text,createdAt:e.createdAt})}i(me,"stripPending");function Jr(e,t){let r={id:e.id,role:e.role,text:e.text+t,createdAt:e.createdAt};return e.citations&&(r.citations=e.citations),e.responseId&&(r.responseId=e.responseId),Object.freeze(r)}i(Jr,"appendText");function pt(e,t){let r={id:t.messageId?t.messageId:e.id,role:"assistant",text:e.text,createdAt:e.createdAt};return t.citations.length>0&&(r.citations=t.citations),t.messageId&&(r.responseId=t.messageId),r.urgencyLevel=t.urgencyLevel,r.urgencyReason=t.urgencyReason,r.urgencyProvided=t.urgencyProvided,Object.freeze(r)}i(pt,"finalizeAssistant");function Zr(e){return Object.freeze({status:e.status,messages:Object.freeze([...e.messages]),conversationId:e.conversationId,error:e.error,isStreaming:e.isStreaming,isBootstrapping:e.isBootstrapping,suggestedPrompts:Object.freeze([...e.suggestedPrompts]),unreadCount:e.unreadCount})}i(Zr,"freezeSnapshot");function R(e,t,r){return S(e,{retryable:t,...r?{wireMessage:r}:{}})}i(R,"makeError");function mt(e){let t=W(e.code);return S(t,{retryable:e.retryable||Ae(t),wireCode:e.code,wireEnvelope:"sse_frame",...e.serverRequestId?{requestId:e.serverRequestId}:{},...e.wireMessage?{wireMessage:e.wireMessage}:{},raw:e})}i(mt,"errorFromFrame");function G(e){return N({code:os(e.code),retryable:e.retryable,wireMessage:e.wireMessage??null,synthesized:true,lastEventId:null,serverRequestId:e.requestId??null})}i(G,"synthErrorFrame");function os(e){switch(e){case "authExpired":return "AUTH_EXPIRED";case "authRejected":return "AuthorizationException";case "sessionRequired":return "session_required";case "accessDenied":return "ACCESS_DENIED";case "paymentRequired":return "TIER_UPGRADE_REQUIRED";case "quotaExceeded":return "QUOTA_EXCEEDED";case "rateLimited":return "RATE_LIMITED";case "validationFailed":return "ValidationException";case "sdkUpdateRequired":return "invalidRequest";case "conflict":return "ConflictException";case "idempotencyConflict":return "IDEMPOTENCY_CONFLICT";case "idempotencyInFlight":return "IDEMPOTENCY_KEY_IN_FLIGHT";case "conversationNotFound":return "CONVERSATION_NOT_FOUND";case "petNotFound":return "PET_NOT_FOUND";case "resourceNotFound":return "ResourceNotFoundException";case "streamTimeout":return "STREAM_TIMEOUT";case "mediaUploadFailed":return "MEDIA_UPLOAD_FAILED";case "moderationBlocked":return "MODERATION_BLOCKED";case "upstreamLlmTimeout":return "UPSTREAM_LLM_TIMEOUT";case "internalError":return "INTERNAL_ERROR";case "notImplemented":return "NotImplementedException";case "serviceUnavailable":return "ServiceUnavailableException";case "streamIncomplete":return "STREAM_INCOMPLETE";case "unknown":return "UNKNOWN";default:return Me(e)}}i(os,"canonicalWireCode");function en(e){let t=Array.isArray(e)?e:dt(e)&&Array.isArray(e.categories)?e.categories:[],r=[];for(let n of t){if(!dt(n))continue;let o=pe(n.category)??pe(n.title)??"",s=is(n.prompts??n.questions);o.length===0&&s.length===0||r.push(Object.freeze({category:o,prompts:Object.freeze(s)}));}return Object.freeze(r)}i(en,"parsePromptCategories");function yt(e){let t=new Set,r=[];for(let n of e)for(let o of n.prompts){let s=o.trim();s.length===0||t.has(s)||(t.add(s),r.push(s));}return r}i(yt,"flattenPrompts");function dt(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}i(dt,"isPlainObject");function pe(e){return typeof e=="string"?e:null}i(pe,"asStr");function is(e){if(!Array.isArray(e))return [];let t=[];for(let r of e)if(typeof r=="string")t.push(r);else if(dt(r)){let n=pe(r.text)??pe(r.prompt)??pe(r.title);n!==null&&t.push(n);}return t}i(is,"asPromptTextList");function tn(){let e=0;return ()=>`m-${Date.now().toString(36)}-${(e++).toString(36)}-${Math.random().toString(36).slice(2,8)}`}i(tn,"defaultIdFactory");function rn(){let e=0;return ()=>`chat-send-${Date.now().toString(36)}-${(e++).toString(36)}-${Math.random().toString(36).slice(2,10)}`}i(rn,"defaultIdempotencyFactory");var on={setTimeout:i((e,t)=>setTimeout(e,t),"setTimeout"),clearTimeout:i(e=>clearTimeout(e),"clearTimeout"),now:i(()=>Date.now(),"now")};async function*sn(e,t,r,n){let o=e[Symbol.asyncIterator](),s=nn(t.overallMs,n),l=nn(t.idleMs,n),u=ls(r);try{for(;;){if(r.aborted)return;let a=o.next().then(m=>({tag:"next",value:m}),()=>({tag:"streamError"})),d=await Promise.race([a,l.promise.then(()=>({tag:"idle"})),s.promise.then(()=>({tag:"overall"})),u.then(()=>({tag:"abort"}))]);if(d.tag==="abort")return;if(d.tag==="streamError"){if(r.aborted)return;yield as();return}if(d.tag==="idle"||d.tag==="overall"){yield ss();return}let c=d.value;if(c.done||(l.reset(t.idleMs),yield c.value,c.value.terminal))return}}finally{l.cancel(),s.cancel(),Promise.resolve(o.return?.(void 0)).catch(()=>{});}}i(sn,"withWatchdog");function ss(){return N({code:"STREAM_TIMEOUT",retryable:true,wireMessage:null,synthesized:true,lastEventId:null})}i(ss,"synthTimeoutFrame");function as(){return N({code:"STREAM_INCOMPLETE",retryable:true,wireMessage:null,synthesized:true,lastEventId:null})}i(as,"synthStreamErrorFrame");function nn(e,t){let r=i(()=>{},"resolveFn"),n=new Promise(s=>{r=s;}),o=t.setTimeout(()=>r(),e);return {promise:n,reset(s){t.clearTimeout(o),o=t.setTimeout(()=>r(),s);},cancel(){t.clearTimeout(o);}}}i(nn,"deadline");function ls(e){return new Promise(t=>{if(e.aborted){t();return}e.addEventListener("abort",()=>t(),{once:true});})}i(ls,"abortPromise");var us="checkin",ds=/^\d{4}-\d{2}-\d{2}$/,ye="watching";function cs(e){return e.status!=null&&e.status!==ye}i(cs,"isCheckinSettled");function an(e){if(typeof e!="string")return null;let t=e.split(":");if(t.length!==3)return null;let[r,n,o]=t;return r!==us||n===void 0||o===void 0||!lt.test(n)||!ds.test(o)?null:n}i(an,"parseCheckinOriginRef");function gt(e,t){if(e?.limit!==void 0&&(!Number.isInteger(e.limit)||e.limit<1||e.limit>t))return f(S("validationFailed"));let r=[];for(let[n,o]of [["cursor",e?.cursor],["pet_ref",e?.petRef]])if(o!==void 0){if(typeof o!="string"||o.length===0||U(o))return f(S("validationFailed"));r.push(`${n}=${encodeURIComponent(o)}`);}return e?.limit!==void 0&&r.push(`limit=${e.limit}`),_(r.length?`?${r.join("&")}`:"")}i(gt,"historyQuery");function be(e){return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(e)}i(be,"validConversationId");function he(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)?e:null}i(he,"object");function ln(e){return e==null||typeof e=="string"&&e.length>0&&!U(e)}i(ln,"cursor");function ge(){return f(S("internalError",{retryable:false}))}i(ge,"malformed");function un(e){let t=he(e);if(!t||!Array.isArray(t.conversations)||!ln(t.next_cursor))return ge();let r=[];for(let n of t.conversations){let o=he(n);if(!o||typeof o.conversation_id!="string"||!be(o.conversation_id)||!(o.title==null||typeof o.title=="string")||typeof o.created_at!="string"||typeof o.updated_at!="string")return ge();let s=o.unread_message_count;if(!(s==null||Number.isInteger(s)&&s>=0))return ge();r.push(Object.freeze({id:o.conversation_id,title:o.title??null,createdAt:o.created_at,updatedAt:o.updated_at,unreadCount:s??null}));}return _(Object.freeze({conversations:Object.freeze(r),nextCursor:t.next_cursor??null}))}i(un,"mapConversationPage");function dn(e){let t=he(e);if(!t||!Array.isArray(t.messages)||!ln(t.next_cursor))return ge();let r=[],n=new Set;for(let o of t.messages){let s=he(o);if(!s||typeof s.message_id!="string"||!be(s.message_id)||typeof s.role!="string"||typeof s.content!="string"||typeof s.created_at!="string")return ge();if(s.role!=="user"&&s.role!=="assistant"||n.has(s.message_id))continue;n.add(s.message_id);let l=typeof s.proactive_origin_ref=="string"?s.proactive_origin_ref:null,u=s.role==="assistant"?an(l):null;r.push(Object.freeze({id:s.message_id,role:s.role,text:s.content,createdAt:s.created_at,...s.role==="assistant"?{responseId:s.message_id}:{},...s.urgency_level!==void 0?{urgencyLevel:fs(s.urgency_level)}:{},...Array.isArray(s.citations)?{citations:ps(s.citations)}:{},...l!==null?{proactiveOriginRef:l}:{},...u!==null?{checkin:Object.freeze({caseId:u,answer:null,resolutionText:null,status:null})}:{}}));}return _(Object.freeze({messages:Object.freeze(r),nextCursor:t.next_cursor??null}))}i(dn,"mapMessagePage");function fs(e){return e==="emergency"||e==="schedule_soon"||e==="home_care"?e:null}i(fs,"normalizeUrgency");function ps(e){let t=["source_name","source_abbrev","section","authority_tier","doi","url","title","year","study_type","journal","excerpt","monograph_chunk_id"];return Object.freeze(e.flatMap(r=>{let n=he(r);if(!n||typeof n.source_name!="string"||typeof n.authority_tier!="string")return [];let o={};for(let s of t){let l=n[s];(typeof l=="string"||l===null)&&(o[s]=l);}return [Object.freeze(o)]}))}i(ps,"historyCitations");var Be=5,cn=Object.freeze(["helpful","neutral","not_helpful","wrong","outdated","dangerous","unclear"]),fn=4e3,ms=6e4,ys=18e4,gs=24,hs=512,bs=false;function yn(e){return new ht(e)}i(yn,"createChatController");var bt=class bt extends ze{constructor(r){super(Zr({status:"idle",messages:[],conversationId:r.initialConversationId??null,error:null,isStreaming:false,isBootstrapping:false,suggestedPrompts:[],unreadCount:null}));this.handlerTeardowns=new Set;this.lastTurn=null;this.unadoptedCreate=null;this.lastResponseIdValue=null;this.historyGeneration=0;this.disposed=false;this.bootstrapPrompts=[];this.replyPrompts=null;this.unreadByConversation=new Map;this.classifiedMessageIds=new Set;this.pendingDelta="";this.flushHandle=null;this.auth=r.auth,this.funnel=r.funnel??K({auth:r.auth,...r.errorPolicy?{errorPolicy:r.errorPolicy}:{}}),this.petRef=r.petRef??null,this.cases=Yr(this.funnel),this.telemetry=r.telemetry??Ie,this.errorPolicy=r.errorPolicy??lr,this.timers=r.timers??on,this.rng=r.rng??Math.random,this.newId=r.newId??tn(),this.makeIdempotencyKey=r.makeIdempotencyKey??rn(),this.budget={idleMs:r.budget?.idleMs??ms,overallMs:r.budget?.overallMs??ys};}patch(r){if(r.messages!==void 0){let n=Object.freeze([...r.messages]);super.patch({...r,messages:n});return}super.patch(r);}send(r,n,o){let s=n??{};if(this.disposed||this.snapshot.isBootstrapping){let a=R(this.disposed?"accessDenied":"internalError",!this.disposed);return o?(o.onError(a),()=>{}):Ne(G(a))}let l=mn(r)??vs(s.imageS3Keys);if(l!==null)return this.telemetry.track("chat.send.rejected",{reason:l.reason}),this.patch({status:"error",isStreaming:false,error:l.error}),o?(o.onError(l.error),()=>{}):Ne(G(l.error));if(o)return this.driveWithHandlers(r,s,o);let u=this.beginTurn(r,s);return this.runTurn(u,s.signal)}askEverfur(r,n){if(this.disposed)return Ne(G(R("accessDenied",false)));let o=mn(r);return o!==null?(this.telemetry.track("chat.send.rejected",{reason:o.reason}),Ne(G(o.error))):(this.resetThread(),this.send(r,n??{}))}retryLast(){let r=this.lastTurn;if(r===null){let s=this.snapshot.conversationId;return s!==null&&this.snapshot.status==="error"?this.retryHistory(s):Rs()}r.assistantMessageId=null,r.sawDelta=false,r.conversationIdOverride=null,this.discardPendingDelta();let o=this.snapshot.messages.some(s=>s.id===r.userMessageId)?this.snapshot.messages:[...this.snapshot.messages,ct(r.userMessageId,r.text,this.stamp())];return this.patch({error:null,stopped:false,messages:o}),this.runTurn(r,void 0)}stop(){this.inFlight?.abort(),this.inFlight=null,this.discardPendingDelta(),this.telemetry.track("chat.cancel",{});let r=this.snapshot.messages.some(o=>o.role==="user"&&o.pending===true),n=r?this.snapshot.messages.map(o=>o.pending===true?me(o):o):this.snapshot.messages;(this.snapshot.status==="streaming"||r)&&this.patch({status:"idle",isStreaming:false,reconnecting:false,...r?{messages:n,stopped:true}:{}});}rescope(){this.resetThread(),this.unreadByConversation.clear(),this.classifiedMessageIds.clear(),this.reflectUnreadDot();}resetThread(){super.rescope(),this.historyGeneration+=1,this.unadoptedCreate=null,this.lastTurn=null,this.lastResponseIdValue=null,this.bootstrapPrompts=[],this.replyPrompts=null,this.discardPendingDelta(),this.patch({status:"idle",isStreaming:false,messages:[],conversationId:null,error:null,suggestedPrompts:[],historyCursor:null,isLoadingHistory:false,isBootstrapping:false,unreadCount:null,stopped:false,reconnecting:false});}dispose(){this.rescope(),this.disposed=true,this.unadoptedCreate=null,this.discardPendingDelta();for(let r of this.handlerTeardowns)r();this.handlerTeardowns.clear(),super.dispose();}adoptConversation(r){this.disposed||(this.unadoptedCreate=null,this.snapshot.conversationId!==r&&this.patch({conversationId:r}));}adoptPrompts(r){if(this.disposed)return;let n=Object.freeze(yt(r));this.bootstrapPrompts=n,this.replyPrompts===null&&(n.length===0&&this.snapshot.suggestedPrompts.length===0||this.patch({suggestedPrompts:n}));}async listConversations(r){return this.listConversationsWith(r)}async listConversationsWith(r,n){let o=gt(r,100);if(!o.ok)return o;let s=this.epoch;if(this.disposed)return f(R("accessDenied",false));let l=await this.authedUnary("chat.listConversations",{method:"GET",path:`/widget/v1/conversations${o.value}`},r?.signal,n);if(!this.alive(s)||this.disposed)return f(R("accessDenied",false));if(!l.ok)return l;let u=un(l.value);if(u.ok){for(let c of u.value.conversations)c.unreadCount!==null&&this.unreadByConversation.set(c.id,c.unreadCount);let a=this.snapshot.conversationId,d=a===null?void 0:this.unreadByConversation.get(a);d!==void 0&&d!==this.snapshot.unreadCount&&this.patch({unreadCount:d}),this.reflectUnreadDot();}return u}reflectUnreadDot(){let r=false;for(let n of this.unreadByConversation.values())if(n>0){r=true;break}r!==(this.snapshot.hasUnreadThreads??false)&&this.patch({hasUnreadThreads:r});}async openCheckin(r){if(this.disposed)return f(R("accessDenied",false));let n=r?.conversationId??null;if(n!==null){let a=await this.resumeConversation(n);return a.ok?_(n):f(a.error)}let o=r?.petRef??this.petRef,s=await this.listConversations({...o===null?{}:{petRef:o},limit:1});if(!s.ok)return f(s.error);let l=s.value.conversations[0];if(l===void 0)return _(null);let u=await this.resumeConversation(l.id);return u.ok?_(l.id):f(u.error)}async markRead(r){if(this.disposed)return f(R("accessDenied",false));let n=this.snapshot.conversationId;if(n===null)return _(void 0);let o=this.epoch,s=await this.authedUnary("chat.markRead",{method:"POST",path:`/widget/v1/conversations/${n}/read`},r?.signal);return !this.alive(o)||this.disposed?f(R("accessDenied",false)):s.ok?(this.unreadByConversation.set(n,0),this.snapshot.conversationId===n&&this.snapshot.unreadCount!==0&&this.patch({unreadCount:0}),this.reflectUnreadDot(),_(void 0)):f(s.error)}async submitFeedback(r,n,o,s){if(this.disposed)return f(R("accessDenied",false));if(typeof r!="string"||r.trim().length===0||U(r))return f(R("validationFailed",false,"feedback needs the server message id of an assistant reply"));if(!cn.includes(n))return f(R("validationFailed",false,`feedback_type must be one of ${cn.join(", ")}`));let l=typeof o=="string"?o.trim():"";if([...l].length>fn)return f(R("validationFailed",false,`notes is over ${fn} characters`));let u={feedback_type:n};l.length>0&&(u.notes=l);let a=this.epoch,d=await this.authedUnary("chat.submitFeedback",{method:"POST",path:`/widget/v1/messages/${encodeURIComponent(r)}/feedback`,body:u},s?.signal);if(!this.alive(a)||this.disposed)return f(R("accessDenied",false));if(!d.ok)return f(d.error);let c=d.value?.feedback_id;return _(Object.freeze({feedbackId:typeof c=="string"?c:""}))}async answerCheckin(r,n,o){if(this.disposed)return f(R("accessDenied",false));let s=o?.petRef??this.petRef;if(s===null)return f(R("validationFailed",false,"a check-in needs the pet the case belongs to"));let l=this.epoch,u=await this.cases.checkin(s,r,n,o?.signal?{signal:o.signal}:{});if(!this.alive(l)||this.disposed)return f(R("accessDenied",false));if(!u.ok)return u;let a=Object.freeze({caseId:r,answer:n,resolutionText:u.value.case.resolutionText,status:u.value.case.status??null}),d=i(c=>c.checkin?.caseId===r,"carries");return this.snapshot.messages.some(d)&&this.patch({messages:this.snapshot.messages.map(c=>d(c)?Object.freeze({...c,checkin:a}):c)}),u}async getMessages(r,n){if(!be(r))return f(R("validationFailed",false));let o=gt(n,200);if(!o.ok)return o;let s=this.epoch;if(this.disposed)return f(R("accessDenied",false));let l=await this.authedUnary("chat.getMessages",{method:"GET",path:`/widget/v1/conversations/${r}/messages${o.value}`},n?.signal);return !this.alive(s)||this.disposed?f(R("accessDenied",false)):l.ok?dn(l.value):l}async resumeConversation(r){if(this.disposed)return f(R("accessDenied",false));if(!be(r))return f(R("validationFailed",false));this.resetThread();let n=this.historyGeneration;this.patch({conversationId:r,isBootstrapping:true,isLoadingHistory:true});let o=await this.getMessages(r);if(n!==this.historyGeneration||this.disposed)return f(R("accessDenied",false));if(!o.ok)return this.patch({status:"error",error:o.error,isBootstrapping:false,isLoadingHistory:false}),o;let s=this.unreadByConversation.get(r)??null;return this.patch({messages:o.value.messages,historyCursor:o.value.nextCursor,isBootstrapping:false,isLoadingHistory:false,unreadCount:s}),this.stampCheckinStatuses(n),s!==null&&s>0&&this.markRead(),_(void 0)}async stampCheckinStatuses(r){let n=this.petRef;if(n===null||!this.snapshot.messages.some(d=>d.checkin!==void 0&&d.checkin.status===null))return;let o=await this.cases.list(n);if(!o.ok||r!==this.historyGeneration||this.disposed)return;let s=new Set(o.value.filter(d=>d.status===ye).map(d=>d.caseId)),l=new Map(o.value.map(d=>[d.caseId,d])),u=false,a=this.snapshot.messages.map(d=>{let c=d.checkin;if(c===void 0||c.status!==null)return d;u=true;let m=l.get(c.caseId);return Object.freeze({...d,checkin:Object.freeze({...c,status:s.has(c.caseId)?ye:m?.status??"resolved",answer:c.answer??m?.lastResponse??null,resolutionText:c.resolutionText??m?.resolutionText??null})})});u&&this.patch({messages:a});}async refreshActiveThread(){if(this.disposed)return f(R("accessDenied",false));let r=this.snapshot.conversationId;if(r===null||this.snapshot.isStreaming)return _(void 0);let n=this.historyGeneration,o=await this.getMessages(r);if(n!==this.historyGeneration||this.disposed)return f(R("accessDenied",false));if(!o.ok)return f(o.error);let s=new Set(this.snapshot.messages.map(u=>u.id)),l=o.value.messages.filter(u=>!s.has(u.id));return l.length>0&&this.patch({messages:[...this.snapshot.messages,...l]}),await this.listConversationsWith({...this.petRef===null?{}:{petRef:this.petRef},limit:1},{maxAttempts:1}),_(void 0)}async loadOlderMessages(){if(this.disposed)return f(R("accessDenied",false));let r=this.snapshot.conversationId,n=this.snapshot.historyCursor;if(!r||!n||this.snapshot.isLoadingHistory)return _(void 0);let o=this.historyGeneration;this.patch({isLoadingHistory:true});let s=await this.getMessages(r,{cursor:n});if(o!==this.historyGeneration||this.disposed)return f(R("accessDenied",false));if(this.patch({isLoadingHistory:false}),!s.ok)return s;let l=new Set(this.snapshot.messages.map(a=>a.id)),u=s.value.messages.filter(a=>!l.has(a.id));return this.patch({messages:[...u,...this.snapshot.messages],historyCursor:s.value.nextCursor===n?null:s.value.nextCursor}),_(void 0)}async*retryHistory(r){let n=await this.resumeConversation(r);n.ok||(yield G(n.error));}async primeConversation(r){if(this.disposed)return f(R("accessDenied",false));let n=r?.petRef??null,o={petRef:n,settled:this.primeBounded(n)};this.unadoptedCreate=o;let s=await o.settled;return this.disposed?f(R("accessDenied",false)):(!s.ok&&this.unadoptedCreate===o&&(this.unadoptedCreate=null),s)}async primeBounded(r){let n=await this.headThreadWithUnread(r);if(n!==null&&!this.snapshot.isStreaming&&this.snapshot.conversationId===null&&(await this.resumeConversation(n)).ok)return _(n);let o=this.snapshot.conversationId;return o!==null?_(o):this.createConversationBounded(r)}async headThreadWithUnread(r){let n=await this.listConversationsWith({...r===null?{}:{petRef:r},limit:1},{maxAttempts:1});if(!n.ok)return null;let o=n.value.conversations[0];return o===void 0||o.unreadCount===null||o.unreadCount<=0?null:o.id}async createConversation(r){let n=this.epoch;if(this.disposed)return f(R("accessDenied",false));let o=r?.petRef??null,s={petRef:o,settled:this.createConversationBounded(o)};this.unadoptedCreate=s;let l=await s.settled;return !this.alive(n)||this.disposed?f(R("accessDenied",false)):(!l.ok&&this.unadoptedCreate===s&&(this.unadoptedCreate=null),l)}async createConversationBounded(r,n){let o={method:"POST",path:"/widget/v1/conversations",body:r?{pet_ref:r}:{}},s=await this.authedUnary("chat.createConversation",o,n,{maxAttempts:1});if(!s.ok)return f(s.error);let l=s.value?.conversation_id??s.value?.id;return typeof l!="string"||l.length===0?f(R("internalError",true)):_(l)}async getPrompts(r){let n=this.epoch;if(this.disposed)return f(R("accessDenied",false));let o=r?.petRef??null;if(o!==null&&U(o))return f(S("validationFailed",{retryable:false,wireMessage:"pet_ref contains an unpaired surrogate and cannot be encoded"}));let s=o!==null?`?pet_ref=${encodeURIComponent(o)}`:"",l=await this.authedUnary("chat.getPrompts",{method:"GET",path:`/widget/v1/suggested-prompts${s}`});return !this.alive(n)||this.disposed?f(R("accessDenied",false)):l.ok?_(en(l.value)):f(l.error)}async authedUnary(r,n,o,s){return this.funnel.send(r,o?{...n,signal:o}:n,s)}driveWithHandlers(r,n,o){let s=new AbortController,l=Le(s.signal,n.signal),u=this.beginTurn(r,n),a=this.runTurn(u,l),d=false,c=i(()=>{d||(d=true,s.abort(),this.handlerTeardowns.delete(c));},"teardown");return this.handlerTeardowns.add(c),(async()=>{for await(let m of a){if(d)break;o.onFrame(m),m.kind==="done"&&o.onDone(this.lastResponseIdValue);}!d&&this.snapshot.status==="error"&&this.snapshot.error!==null&&o.onError(this.snapshot.error),this.handlerTeardowns.delete(c);})(),c}beginTurn(r,n){let o={epoch:this.epoch,text:r,petRef:n.petRef??null,imageS3Keys:Object.freeze([...n.imageS3Keys??[]]),idempotencyKey:n.idempotencyKey??this.makeIdempotencyKey(),userMessageId:this.newId(),assistantMessageId:null,sawDelta:false,conversationIdOverride:n.conversationId??null};return this.patch({error:null,stopped:false,reconnecting:false,messages:[...this.snapshot.messages,ct(o.userMessageId,r,this.stamp())]}),o}async*runTurn(r,n){let o=this.beginOperation(n);r.epoch=o.epoch,this.patch({status:"streaming",isStreaming:true,error:null}),this.lastTurn=r;let s=0,l=false,u=false;try{for(;;){if(o.signal.aborted||!this.alive(o.epoch))return;let a=r.conversationIdOverride===null&&this.snapshot.conversationId===null,d=a?this.unadoptedCreate:null;if(d!==null&&(r.petRef===null||r.petRef===d.petRef)){let E=await d.settled;if(o.signal.aborted||!this.alive(o.epoch))return;E.ok&&this.snapshot.conversationId===null&&this.adoptConversation(E.value);}if(a&&this.snapshot.conversationId===null){let E=await this.createConversationBounded(r.petRef,o.signal);if(o.signal.aborted||!this.alive(o.epoch))return;if(!E.ok){yield*this.emitTerminal(r,E.error,G(E.error));return}this.adoptConversation(E.value);}let c=r.conversationIdOverride??this.snapshot.conversationId;if(c===null){let E=R("internalError",!0);yield*this.emitTerminal(r,E,G(E));return}this.clearAssistantInProgress(r);let m=new AbortController,h=Le(o.signal,m.signal),g=null;try{let E;try{E=await this.funnel.authorize(this.buildSendRequest(r,c));}catch{let I=this.authRejected();yield*this.emitTerminal(r,I,G(I));return}if(o.signal.aborted||!this.alive(o.epoch))return;let T=this.funnel.stream("chat.send",E,h);for await(let I of sn(T,this.budget,h,this.timers)){if(!this.alive(o.epoch))return;if(I.kind==="error"&&I.terminal){g=I;break}if(this.applyFrame(I,r),yield I,I.terminal){o.settle();return}}}finally{m.abort();}if(o.signal.aborted||!this.alive(o.epoch))return;if(g===null){if(this.snapshot.status==="complete")return;let E=R("streamIncomplete",!0);yield*this.emitTerminal(r,E,G(E));return}let C=W(g.code);if(C==="authExpired"&&this.auth.mode==="personalized"&&!u){u=!0,this.telemetry.track("chat.auth.refresh",{});let E=await this.tryForceRefresh();if(o.signal.aborted||!this.alive(o.epoch))return;if(!E){let T=this.authRejected();yield*this.emitTerminal(r,T,g);return}this.patch({reconnecting:!0});continue}if(C==="authExpired"){this.telemetry.track("chat.auth.rejected",{});let E=this.authRejected();yield*this.emitTerminal(r,E,g);return}if(C==="accessDenied"){this.telemetry.track("chat.access_denied",{}),yield*this.emitTerminal(r,mt(g),g);return}if(ar(C)&&!l){l=!0,this.telemetry.track("chat.conv.recreate",{}),this.adoptConversation(null),r.conversationIdOverride=null,this.patch({reconnecting:!0});continue}let P=g.retryable&&Ae(C,!0);if(bs&&P&&s+1<this.errorPolicy.maxAttempts(C));yield*this.emitTerminal(r,mt(g),g);return}}finally{o.settle();}}*emitTerminal(r,n,o){this.applyError(r,n),yield o;}applyFrame(r,n){switch(r.kind){case "accepted":this.snapshot.isStreaming||this.patch({status:"streaming",isStreaming:true});return;case "heartbeat":return;case "delta":this.applyDelta(r.delta,n);return;case "done":this.applyDone(r,n);return;case "analysisStarted":case "analysisComplete":return;case "unknown":this.telemetry.track("chat.frame.unknown",{});return;case "error":return;default:return Me(r)}}stamp(){return new Date(this.timers.now()).toISOString()}applyDelta(r,n){if(n.assistantMessageId===null){let o=this.newId();n.assistantMessageId=o,n.sawDelta=true;let s=this.snapshot.messages.map(l=>l.id===n.userMessageId&&l.pending===true?me(l):l);this.patch({status:"streaming",isStreaming:true,messages:[...s,ft(o,r,this.stamp())]});return}if(this.pendingDelta+=r,this.pendingDelta.length>=hs){this.flushPendingDelta(n);return}this.scheduleDeltaFlush(n);}scheduleDeltaFlush(r){if(this.flushHandle!==null)return;let n=this.epoch;this.flushHandle=this.timers.setTimeout(()=>{if(this.flushHandle=null,!this.alive(n)){this.pendingDelta="";return}this.flushPendingDelta(r);},gs);}flushPendingDelta(r){if(this.clearFlushTimer(),this.pendingDelta.length===0)return;let n=this.pendingDelta;this.pendingDelta="";let o=r.assistantMessageId;if(o===null)return;let s=this.snapshot.messages.map(l=>l.id===o?Jr(l,n):l);this.patch({messages:s});}discardPendingDelta(){this.clearFlushTimer(),this.pendingDelta="";}clearFlushTimer(){this.flushHandle!==null&&(this.timers.clearTimeout(this.flushHandle),this.flushHandle=null);}applyDone(r,n){this.flushPendingDelta(n),this.lastResponseIdValue=r.messageId?r.messageId:null;let o=r.conversationId?r.conversationId:this.snapshot.conversationId,s;if(n.assistantMessageId!==null)s=this.snapshot.messages.map(u=>u.id===n.assistantMessageId?pt(u,r):u);else {let u=this.newId();n.assistantMessageId=u,n.sawDelta=true,s=[...this.snapshot.messages.map(d=>d.id===n.userMessageId&&d.pending===true?me(d):d),pt(ft(u,"",this.stamp()),r)];}let l=yt([{category:"",prompts:r.followUpQuestions}]);this.replyPrompts=l.length>0?Object.freeze(l):null,this.patch({status:"complete",isStreaming:false,error:null,conversationId:o,messages:s,suggestedPrompts:this.replyPrompts??this.bootstrapPrompts,reconnecting:false}),!r.urgencyProvided&&o!==null&&this.classifyTurn(o,this.lastResponseIdValue);}async classifyTurn(r,n){if(n===null||this.disposed)return;let o=String(n);if(this.classifiedMessageIds.has(o))return;this.classifiedMessageIds.add(o);let s=this.epoch,l=this.historyGeneration,u=await this.authedUnary("chat.classifyUrgency",{method:"POST",path:`/widget/v1/conversations/${r}/classify`});if(!u.ok||!this.alive(s)||this.disposed||l!==this.historyGeneration||this.snapshot.conversationId!==r)return;let a=_s(u.value?.urgency),d=typeof u.value?.reason=="string"?u.value.reason:null,c=i(m=>m.responseId===n,"carries");this.snapshot.messages.some(c)&&this.patch({messages:this.snapshot.messages.map(m=>c(m)?Object.freeze({...m,urgencyLevel:a,urgencyReason:d,urgencyProvided:true}):m)});}applyError(r,n){this.flushPendingDelta(r);let o=this.snapshot.messages.map(s=>s.id===r.userMessageId&&s.pending===true?me(s):s);this.patch({status:"error",isStreaming:false,error:n,messages:o,reconnecting:false});try{this.errorPolicy.onExpectedFailure?.(n);}catch{}}clearAssistantInProgress(r){if(this.discardPendingDelta(),r.assistantMessageId===null)return;let n=r.assistantMessageId;r.assistantMessageId=null,r.sawDelta=false;let o=this.snapshot.messages.filter(s=>s.id!==n);o.length!==this.snapshot.messages.length&&this.patch({messages:o});}buildSendRequest(r,n){let o={message:r.text};return r.imageS3Keys.length>0&&(o.image_s3_keys=r.imageS3Keys),{method:"POST",path:`/widget/v1/conversations/${n}/messages`,body:o,headers:{"Idempotency-Key":r.idempotencyKey}}}async tryForceRefresh(){if(this.auth.mode!=="personalized")return false;try{return await this.auth.identity.currentToken({forceRefresh:!0}),!0}catch{return false}}authRejected(){return R("authRejected",false)}};i(bt,"ChatControllerImpl");var ht=bt,pn=4e3;function vs(e){return e===void 0?null:!Array.isArray(e)||e.length>Be?{reason:"too_many_images",error:R("validationFailed",false,`image_s3_keys accepts at most ${Be} keys`)}:e.some(t=>typeof t!="string"||t.trim().length===0)?{reason:"bad_image_key",error:R("validationFailed",false,"image_s3_keys must be non-empty strings")}:null}i(vs,"validateImageKeys");function mn(e){let t=typeof e=="string"?e:"";if(t.trim().length===0)return {reason:"empty",error:R("validationFailed",false,"message is empty or whitespace-only")};let r=[...t].length;return r>pn?{reason:"too_long",error:R("validationFailed",false,`message is ${r} characters; the server accepts at most ${pn}`)}:null}i(mn,"validateMessageText");function _s(e){return e==="emergency"||e==="schedule_soon"||e==="home_care"?e:null}i(_s,"urgencyTier");async function*Ne(e){yield e;}i(Ne,"singleFrameStream");async function*Rs(){}i(Rs,"emptyStream");async function bn(e,t){let{controller:r}=t,n=e.petRef??null,o=e.resumeConversationId??null,s=[],l=false,u=false,a=false,d=null,c=null,m=o?r.resumeConversation(o).then(O=>O.ok?_(o):O):r.primeConversation(n?{petRef:n}:void 0),h=r.getPrompts(n!==null?{petRef:n}:void 0),[g,C]=await Promise.all([m,h]),P=null;if(g.ok)P=g.value,s.push(g.value),r.getSnapshot().conversationId===null&&r.adoptConversation(g.value);else {let O=g.error;c=O,gn(O)?(u=true,d=O):(hn(O)&&(l=true),a=true);}let E=[];C.ok?E=C.value:T(C.error);function T(O){gn(O)?(u=true,d===null&&(d=O)):hn(O)&&(l=true);}i(T,"recordAuthSignals");let I=d!==null?d.displayMessage:null;return Object.freeze({conversationId:P,petRef:n,suggestedPrompts:E,error:I,warning:I===null&&P===null&&a?Es:null,cause:d??c,diagnostics:Object.freeze({candidateConversationIds:Object.freeze([...s]),sawForbidden:l,sawUnauthorized:u,sawConversationInitFailure:a})})}i(bn,"bootstrapChat");var Es="Chat is ready. Your first message will start the conversation.";function gn(e){return e.httpStatus===401||e.code==="authExpired"||e.code==="authRejected"}i(gn,"isUnauthorized");function hn(e){return e.httpStatus===403||e.code==="accessDenied"}i(hn,"isForbidden");var vt=Object.freeze({postMultipart(){return Promise.reject(new Error("UploadTransport is unavailable; no records upload adapter was injected"))}});function vn(e){return e!==vt}i(vn,"isUploadTransportAvailable");var _n=128,te=128;var Cs=Object.freeze(["image/jpeg","image/jpg","image/png","image/heic","image/heif","image/webp"]),Jd="image/jpeg,image/png,image/webp,image/heic,image/heif,.jpg,.jpeg,.png,.webp,.heic,.heif",En=10*1024*1024,Ss=Be,ve=120,ws="/widget/v1/uploads/initiate";function ks(e){return typeof e=="string"&&Cs.includes(e.trim().toLowerCase())}i(ks,"isAttachmentMime");function Ps(e){if(!e)return "attachment";let t=e.replace(/[\\/]+/g," ").replace(/[\x00-\x1f\x7f"]/g,"").replace(/\s+/g," ").trim();if(!t)return "attachment";if(t.length<=ve)return t;let r=t.lastIndexOf(".");if(r===-1||r===t.length-1)return t.slice(0,ve);let n=t.slice(r);return n.length>=ve?t.slice(0,ve):`${t.slice(0,r).slice(0,ve-n.length)}${n}`}i(Ps,"sanitizeFilename");function Zd(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}i(Zd,"formatBytes");var _e=i(e=>Object.freeze({ok:true,value:e}),"ok"),$=i(e=>Object.freeze({ok:false,error:e}),"err");function j(e,t,r,n){return Object.freeze({code:e,retryable:t,filename:r,...n??{}})}i(j,"failure");function Ts(e){if(typeof e.sizeBytes=="number"&&Number.isFinite(e.sizeBytes)&&e.sizeBytes>=0)return e.sizeBytes;let t=e.blob;return t!==void 0&&typeof t.size=="number"&&Number.isFinite(t.size)?t.size:null}i(Ts,"attachmentSize");function xs(e){let t=Ps(e.name),r=typeof e.mimeType=="string"?e.mimeType.trim().toLowerCase():"";if(!ks(r))return $(j("unsupported_type",false,t));let n=Ts(e);return n===null?$(j("unknown",false,t)):n>En?$(j("too_large",false,t,{sizeBytes:n})):_e(Object.freeze({file:e,filename:t,contentType:r,sizeBytes:n}))}i(xs,"validateAttachment");function Is(e){if(typeof e!="object"||e===null)return null;let t=e,r=i(d=>typeof d=="string"&&d.length>0?d:null,"str"),n=i(d=>typeof d=="number"&&Number.isFinite(d)?d:null,"num"),o=r(t.upload_id),s=r(t.upload_url),l=r(t.s3_key);if(o===null||s===null||l===null)return null;let u={},a=t.upload_fields;if(typeof a=="object"&&a!==null)for(let[d,c]of Object.entries(a))typeof c=="string"&&(u[d]=c);return Object.freeze({upload_id:o,upload_url:s,upload_fields:Object.freeze(u),expires_in_seconds:n(t.expires_in_seconds)??0,max_content_length:n(t.max_content_length)??En,s3_key:l,purpose:r(t.purpose)})}i(Is,"parsePolicy");function Os(e,t){let r=e.httpStatus;switch(e.code){case "quotaExceeded":return j("quota_exceeded",false,t,{cause:e});case "rateLimited":return j("rate_limited",true,t,{cause:e});case "idempotencyConflict":case "idempotencyInFlight":return j("idempotency_conflict",true,t,{cause:e});case "validationFailed":return j("unsupported_type",false,t,{cause:e});case "serviceUnavailable":case "streamTimeout":return j("network",true,t,{cause:e});default:return r===429?j("rate_limited",true,t,{cause:e}):r===503?j("network",true,t,{cause:e}):r===void 0?j("network",true,t,{cause:e}):j("server",e.retryable,t,{httpStatus:r,cause:e})}}i(Os,"initiateFailure");async function As(e,t,r){let n=await e.send("chat.attachments.initiate",{method:"POST",path:ws,body:{filename:t.filename,content_type:t.contentType,file_size:t.sizeBytes},...r?.signal?{signal:r.signal}:{}});if(!n.ok)return $(Os(n.error,t.filename));let o=Is(n.value);return o===null?$(j("server",false,t.filename)):_e(o)}i(As,"initiateAttachmentUpload");async function Fs(e,t,r,n){let o=i(()=>n?.signal?.aborted===true,"cancelled");if(o())return $(j("cancelled",true,r.filename));try{return await e.postMultipart(t,r.file,{...n?.signal?{signal:n.signal}:{},...n?.onProgress?{onProgress:n.onProgress}:{}}),_e(void 0)}catch{return o()?$(j("cancelled",true,r.filename)):$(j("server",true,r.filename))}}i(Fs,"uploadAttachmentBytes");var Ms=2,js=3,Ds=Object.freeze([1e3,2e3,4e3]),Rn=0;function zs(){return Rn+=1,`attachment-${Rn}`}i(zs,"defaultNewId");function ec(e){let t=Math.max(1,e.concurrency??Ms),r=Math.max(1,e.maxAttempts??js),n=e.backoffMs??Ds,o=Math.max(1,e.maxPerMessage??Ss),s=e.timers??Qr,l=e.newId??zs,u=vn(e.transport),a=new Map,d=[],c=[],m=new Set,h=new Set,g=Object.freeze({attachments:Object.freeze([])}),C=false,P=i(()=>{g=Object.freeze({attachments:Object.freeze(d.flatMap(b=>{let w=a.get(b);return w===void 0?[]:[w.state]}))});for(let b of h)b();},"publish"),E=i((b,w)=>{b.state=Object.freeze({...b.state,...w}),P();},"patch"),T=i(()=>{for(;!C&&m.size<t&&c.length>0;){let b=c.shift(),w=a.get(b);w!==void 0&&(m.add(b),I(w).finally(()=>{m.delete(b),T();}));}},"pump"),I=i(async b=>{let{attachment:w}=b;for(;b.attempts<r;){if(C||b.controller.signal.aborted)return;b.attempts+=1;let D=b.controller.signal;E(b,{status:"uploading",error:null,progress:0});let M=await As(e.funnel,w,{signal:D});if(C||D.aborted)return;let q;if(!M.ok)q=$(M.error);else {let er=await Fs(e.transport,M.value,w,{signal:D,onProgress:i(qo=>{!D.aborted&&b.state.status==="uploading"&&E(b,{progress:Us(qo)});},"onProgress")});if(C||D.aborted)return;q=er.ok?_e(M.value.s3_key):$(er.error);}if(q.ok){E(b,{status:"uploaded",s3Key:q.value,error:null,progress:1});return}let ne=q.error,ae=ne.retryable&&b.attempts<r;if(E(b,{status:ae?"uploading":"failed",error:ne,progress:0}),!ae)return;let ue=n[Math.min(b.attempts-1,n.length-1)]??0;await Ue(ue,D,s);}},"run"),B=i(b=>{c.push(b.state.id),T();},"enqueue"),O={available:u,subscribe(b){return h.add(b),()=>{h.delete(b);}},getSnapshot:i(()=>g,"getSnapshot"),get uploading(){return g.attachments.some(b=>b.status==="uploading")},get s3Keys(){return g.attachments.flatMap(b=>b.status==="uploaded"&&b.s3Key!==null?[b.s3Key]:[])},add(b){let w=xs(b);if(!w.ok)return w;if(C||d.length>=o)return $(j("too_many",false,w.value.filename));let D=l(),M={attachment:w.value,controller:new AbortController,attempts:0,state:Object.freeze({id:D,filename:w.value.filename,previewUri:b.uri,contentType:w.value.contentType,sizeBytes:w.value.sizeBytes,status:"uploading",s3Key:null,error:null,progress:0})};return a.set(D,M),d.push(D),P(),B(M),_e(M.state)},retry(b){let w=a.get(b);w===void 0||C||w.state.status!=="failed"||(w.controller=new AbortController,w.attempts=0,E(w,{status:"uploading",error:null,progress:0,s3Key:null}),B(w));},remove(b){let w=a.get(b);if(w===void 0)return;w.controller.abort(),a.delete(b);let D=d.indexOf(b);D>=0&&d.splice(D,1);let M=c.indexOf(b);M>=0&&c.splice(M,1),P();},clear(){for(let b of [...d])O.remove(b);},dispose(){C=true;for(let b of a.values())b.controller.abort();a.clear(),d.length=0,c.length=0,h.clear(),g=Object.freeze({attachments:Object.freeze([])});}};return O}i(ec,"createAttachmentQueue");function Us(e){return Number.isNaN(e)||e<0?0:e>1?1:e}i(Us,"clamp");var Cn=Object.freeze({dog:"dog",canine:"dog",k9:"dog",puppy:"dog",cat:"cat",feline:"cat",kitten:"cat"});function Sn(e){if(typeof e!="string")return null;let t=e.trim().toLowerCase();return Object.prototype.hasOwnProperty.call(Cn,t)?Cn[t]:null}i(Sn,"canonicalPetSpecies");var wn=50,Ls=128,_t=120,kn=120,Ns=2e3,Pn=120,Bs=80,In=new Set(["male","female","unknown"]),On=new Set(["day","month","year"]),An=new Set(["low","medium","high","athletic"]),Fn=new Set(["indoor","outdoor","both"]),Mn=new Set(["mild","moderate","severe"]),qs=/^(\d{4})-(\d{2})-(\d{2})$/,jn=[["sex","sex"],["spayedNeutered","spayed_neutered"],["birthDate","birth_date"],["birthDatePrecision","birth_date_precision"],["activityLevel","activity_level"],["indoorOutdoor","indoor_outdoor"],["foodBrand","food_brand"],["foodType","food_type"],["microchipId","microchip_id"]],Dn=[["allergies","allergies"],["medications","medications"],["supplements","supplements"],["conditions","conditions"]];Object.freeze([...jn,...Dn].map(([e])=>e));function Hs(e){let t=qs.exec(e);if(t===null)return false;let[r,n,o]=[Number(t[1]),Number(t[2]),Number(t[3])],s=new Date(Date.UTC(r,n-1,o));return s.getUTCFullYear()===r&&s.getUTCMonth()===n-1&&s.getUTCDate()===o}i(Hs,"isRealDate");var Ee=i(e=>(t,r)=>typeof r=="string"&&e.has(r)?null:`${t} must be one of ${[...e].join(", ")}`,"oneOf"),Ks=i((e,t)=>typeof t=="boolean"?null:`${e} must be true or false`,"boolean"),He=i((e,t)=>typeof t=="string"&&Hs(t)?null:`${e} must be a real date written YYYY-MM-DD`,"date"),Y=i((e,t={})=>(r,n)=>{if(typeof n!="string")return `${r} must be a string`;if(U(n))return `${r} contains an unpaired surrogate and cannot be encoded`;let o=t.trimmed?n.trim():n;if(t.required&&o.length===0)return `${r} is required and must not be blank`;let s=De(o);return s<=e?null:`${r} is ${s} characters; the server accepts at most ${e}`},"text"),$s={sex:Ee(In),spayedNeutered:Ks,birthDate:He,birthDatePrecision:Ee(On),activityLevel:Ee(An),indoorOutdoor:Ee(Fn),foodBrand:Y(Pn),foodType:Y(Pn),microchipId:Y(Bs)},Rt=["ref","ref",false,Y(Ls,{required:true,trimmed:true})],Et=["notes","notes",false,Y(Ns,{trimmed:true})],Tn=[Rt,["name","name",true,Y(_t,{required:true,trimmed:true})],["dose","dose",false,Y(kn,{trimmed:true})],["frequency","frequency",false,Y(kn,{trimmed:true})],["startDate","start_date",false,He],["endDate","end_date",false,He],Et],Vs={allergies:[Rt,["allergen","allergen",true,Y(_t,{required:true,trimmed:true})],["severity","severity",false,Ee(Mn)],Et],medications:Tn,supplements:Tn,conditions:[Rt,["conditionName","condition_name",true,Y(_t,{required:true,trimmed:true})],["diagnosedDate","diagnosed_date",false,He],Et]};function Ws(e,t,r){let n=`${e}[${t}]`;if(typeof r!="object"||r===null||Array.isArray(r))return {error:`${n} must be an object`};let o=r,s={};for(let[a,d,c,m]of Vs[e]){let h=o[a];if(h==null){if(c)return {error:`${n}.${a} is required`};h===null&&(s[d]=null);continue}let g=m(`${n}.${a}`,h);if(g!==null)return {error:g};s[d]=h;}let l=s.start_date,u=s.end_date;return typeof l=="string"&&typeof u=="string"&&u<l?{error:`${n}.endDate must not be before startDate`}:{item:s}}i(Ws,"itemToWire");function Gs(e,t){if(!Array.isArray(t))return {error:`${e} must be an array (send [] to clear it)`};if(t.length>wn)return {error:`${e} has ${t.length} items; the server accepts at most ${wn}`};let r=[],n=new Set;for(let o=0;o<t.length;o+=1){let s=Ws(e,o,t[o]);if("error"in s)return s;let l=s.item.ref;if(typeof l=="string"){let u=l.trim();if(n.has(u))return {error:`${e}: ref ${JSON.stringify(u)} is used twice; a ref names one item`};n.add(u);}r.push(s.item);}return {items:r}}i(Gs,"listToWire");function zn(e,t){let r=e,n={};for(let[l,u]of jn){let a=r[l];if(a!==void 0){if(a!==null){let d=$s[l](l,a);if(d!==null)return {error:d}}n[u]=a;}}let o=r.birthDate!==void 0,s=r.birthDatePrecision!==void 0;if(o!==s||o&&r.birthDate===null!=(r.birthDatePrecision===null))return {error:"birthDate and birthDatePrecision must be sent together, both set or both null"};for(let[l,u]of Dn){let a=r[l];if(a===void 0)continue;let d=Gs(l,a);if("error"in d)return d;n[u]=d.items;}return Object.keys(n).length>0&&t!==void 0&&Sn(t)===null?{error:"health fields need a pet Everfur reads as a dog or a cat (dog, canine, k9, puppy, cat, feline, kitten)"}:{body:n}}i(zn,"petHealthToWire");var F=i(e=>typeof e=="string"?e:null,"str"),Re=i((e,t)=>typeof t=="string"&&e.has(t)?t:null,"pick"),Ys=i(e=>typeof e=="boolean"?e:null,"bool");function qe(e,t){return Array.isArray(e)?Object.freeze(e.flatMap(r=>{if(typeof r!="object"||r===null||Array.isArray(r))return [];let n=t(r);return n===null?[]:[n]})):Object.freeze([])}i(qe,"itemsFromWire");function xn(e){let t=F(e.name);return t===null||t.length===0?null:Object.freeze({ref:F(e.ref),name:t,dose:F(e.dose),frequency:F(e.frequency),startDate:F(e.start_date),endDate:F(e.end_date),notes:F(e.notes)})}i(xn,"medicationFromWire");function Un(e){let t=e.profile_version;return Object.freeze({profileVersion:typeof t=="number"&&Number.isInteger(t)&&t>=0?t:0,sex:Re(In,e.sex),spayedNeutered:Ys(e.spayed_neutered),birthDate:F(e.birth_date),birthDatePrecision:Re(On,e.birth_date_precision),activityLevel:Re(An,e.activity_level),indoorOutdoor:Re(Fn,e.indoor_outdoor),foodBrand:F(e.food_brand),foodType:F(e.food_type),microchipId:F(e.microchip_id),allergies:qe(e.allergies,r=>{let n=F(r.allergen);return n===null||n.length===0?null:Object.freeze({ref:F(r.ref),allergen:n,severity:Re(Mn,r.severity),notes:F(r.notes)})}),medications:qe(e.medications,xn),supplements:qe(e.supplements,xn),conditions:qe(e.conditions,r=>{let n=F(r.condition_name);return n===null||n.length===0?null:Object.freeze({ref:F(r.ref),conditionName:n,diagnosedDate:F(r.diagnosed_date),notes:F(r.notes)})})})}i(Un,"petHealthFromWire");var Bn=100,qn=50,Hn=100,Kn=50,$n=500,Xs=128,Qs=6e4;function Q(e){return S("validationFailed",{retryable:false,wireMessage:e})}i(Q,"invalid");function oe(e,t,r){if(typeof t!="string")return Q(`${e} must be a string`);let n=De(t);return n<=r?null:Q(`${e} is ${n} characters; the server accepts at most ${r}`)}i(oe,"checkString");function Ke(e,t,r){return typeof t=="number"&&Number.isFinite(t)&&t>=0&&t<=r?null:Q(`${e} must be a finite number between 0 and ${r}`)}i(Ke,"outOfRange");function Ln(e,t){if(typeof e!="string")return Q("pet_ref must be a string");if(e.trim().length===0)return Q("pet_ref must not be blank");if(U(e))return Q("pet_ref contains an unpaired surrogate and cannot be encoded");if(t!=null&&typeof t!="object")return Q("profile must be an object");let r=[oe("pet_ref",e,Xs)];return t?.name!==void 0&&r.push(oe("name",t.name,Bn)),t?.species!==void 0&&r.push(oe("species",t.species,qn)),t?.breed!==void 0&&r.push(oe("breed",t.breed,Hn)),t?.ageYears!==void 0&&r.push(Ke("age_years",t.ageYears,Kn)),t?.weightKg!==void 0&&r.push(Ke("weight_kg",t.weightKg,$n)),r.find(n=>n!==null)??null}i(Ln,"validate");function Vn(e,t){let r=zn(e,t);return "error"in r?{error:Q(r.error)}:r}i(Vn,"healthToWire");function Js(e){if(typeof e!="object"||e===null)return {error:Q("patch must be an object")};let t=e,r=[["name","name",s=>oe("name",s,Bn)],["species","species",s=>oe("species",s,qn)],["breed","breed",s=>oe("breed",s,Hn)],["ageYears","age_years",s=>Ke("age_years",s,Kn)],["weightKg","weight_kg",s=>Ke("weight_kg",s,$n)]],n={};for(let[s,l,u]of r){let a=t[s];if(a!==void 0){if(a!==null){let d=u(a);if(d!==null)return {error:d}}n[l]=a;}}let o=Vn(t,t.species);return "error"in o?o:(Object.assign(n,o.body),Object.keys(n).length===0?{error:Q("patch must change at least one field")}:{body:n})}i(Js,"patchToWire");function Zs(e){if(e==null)return {body:{}};let t=Vn(e,e.species);return "error"in t?t:{body:{...e.name!==void 0?{name:e.name}:{},...e.species!==void 0?{species:e.species}:{},...e.breed!==void 0?{breed:e.breed}:{},...e.ageYears!==void 0?{age_years:e.ageYears}:{},...e.weightKg!==void 0?{weight_kg:e.weightKg}:{},...t.body}}}i(Zs,"toWire");var X=i(e=>typeof e=="string"?e:null,"str"),$e=i(e=>typeof e=="number"&&Number.isFinite(e)?e:null,"num");function Nn(e,t){let r=typeof e=="object"&&e!==null?e:{};return Object.freeze({petRef:X(r.pet_ref)??t,name:X(r.name),species:X(r.species),breed:X(r.breed),ageYears:$e(r.age_years),weightKg:$e(r.weight_kg)})}i(Nn,"fromWire");function Wn(e){if(typeof e!="object"||e===null)return null;let t=e,r=X(t.pet_ref);return r===null||r.length===0?null:Object.freeze({petId:X(t.pet_id),petRef:r,name:X(t.name),species:X(t.species),breed:X(t.breed),ageYears:$e(t.age_years),weightKg:$e(t.weight_kg),updatedAt:X(t.updated_at)})}i(Wn,"widgetPetFromWire");function ea(e){let t=Wn(e);return t===null?null:Object.freeze({...t,...Un(e)})}i(ea,"widgetPetProfileFromWire");function ta(e){let t=Array.isArray(e)?e:typeof e=="object"&&e!==null&&Array.isArray(e.pets)?e.pets:[];return Object.freeze(t.flatMap(r=>{let n=Wn(r);return n===null?[]:[n]}))}i(ta,"petListFromWire");function Gn(e){return ra(K({auth:e}),K({auth:e,unaryTimeoutMs:Qs}))}i(Gn,"createPetsRepository");function ra(e,t=e){let r=i((o,s)=>s?{...o,signal:s}:o,"withSignal"),n=i(o=>Ln(o,void 0)??`/widget/v1/pets/${encodeURIComponent(o)}`,"petPath");return {async list(o){let s=await e.send("pets.list",r({method:"GET",path:"/widget/v1/pets"},o?.signal));return s.ok?_(ta(s.value)):f(s.error)},async registerPet(o,s,l){let u=Ln(o,s);if(u!==null)return f(u);let a=Zs(s);if("error"in a)return f(a.error);let c={method:"POST",path:`/widget/v1/pets/${encodeURIComponent(o)}`,body:a.body},m=await e.send("pets.registerPet",l?.signal?{...c,signal:l.signal}:c);return m.ok?_(Nn(m.value,o)):f(m.error)},async updatePet(o,s,l){let u=n(o);if(typeof u!="string")return f(u);let a=Js(s);if("error"in a)return f(a.error);let d=await e.send("pets.updatePet",r({method:"PATCH",path:u,body:a.body},l?.signal));return d.ok?_(Nn(d.value,o)):f(d.error)},async getPetProfile(o,s){let l=n(o);if(typeof l!="string")return f(l);let u=await e.send("pets.getPetProfile",r({method:"GET",path:`${l}/profile`},s?.signal));if(!u.ok)return f(u.error);let a=ea(u.value);return a===null?f(S("internalError",{retryable:false,httpStatus:502,wireMessage:"the pet profile response carried no pet_ref"})):_(a)},async deletePet(o,s){let l=n(o);if(typeof l!="string")return f(l);let u=await e.send("pets.deletePet",r({method:"DELETE",path:l},s?.signal));return u.ok?_(void 0):f(u.error)},async eraseUserData(o){let s=await t.send("pets.eraseUserData",r({method:"DELETE",path:"/widget/v1/me"},o?.signal),{maxAttempts:1});return s.ok?_(void 0):f(s.error)}}}i(ra,"createPetsRepositoryOver");var Yn=Object.freeze({chat:Object.freeze(["chat.message.create"]),records:Object.freeze(["records.upload.create","records.record.read"]),recordsClinic:Object.freeze(["records.clinic.create"]),video:Object.freeze(["video.gait.execute"]),photo:Object.freeze(["photo.checkup.execute"]),animations:Object.freeze(["animations.state.read"]),televet:Object.freeze(["televet.visit.create"])});function Xn(e,t){let r=Object.freeze({reason:t,level:e,recoverable:false}),n=[],o=new Set;for(let s of Object.keys(Yn))for(let l of Yn[s])o.has(l)||(o.add(l),n.push(Object.freeze({resource:l,granted:false,disabled:r})));return Object.freeze(n)}i(Xn,"deniedDecisionsFor");function ee(e){let t=Jn(e);return t===null?null:oa(t)}i(ee,"parseColor");function Jn(e){if(typeof e=="number")return Qn(e);if(typeof e!="string")return null;let t=e.trim();if(t.length===0)return null;if(t.startsWith("#"))return Ct(t.slice(1));if(t.toLowerCase().startsWith("0x"))return Ct(t.slice(2));if(t.toLowerCase().startsWith("rgb"))return na(t);if(/^[0-9a-fA-F]+$/.test(t)){let r=Ct(t);if(r!==null)return r}return /^\d+$/.test(t)?Qn(Number.parseInt(t,10)):null}i(Jn,"toRgba");function Ct(e){let t=e.trim();if(!/^[0-9a-fA-F]+$/.test(t))return null;if(t.length===3)return {r:St(t[0]),g:St(t[1]),b:St(t[2]),a:1};if(t.length===6)return {r:ie(t,0),g:ie(t,2),b:ie(t,4),a:1};if(t.length===8){let r=ie(t,0);return {r:ie(t,2),g:ie(t,4),b:ie(t,6),a:r/255}}return null}i(Ct,"fromHex");function na(e){let t=e.indexOf("("),r=e.indexOf(")");if(t<0||r<0||r<t)return null;let n=e.slice(t+1,r).split(",").map(a=>a.trim());if(n.length<3)return null;let o=wt(Number(n[0])),s=wt(Number(n[1])),l=wt(Number(n[2]));if(o===null||s===null||l===null)return null;let u=1;if(n.length>=4){let a=Number(n[3]);if(!Number.isFinite(a))return null;u=Math.min(1,Math.max(0,a));}return {r:o,g:s,b:l,a:u}}i(na,"fromRgbFunc");function Qn(e){if(!Number.isFinite(e))return null;let t=Math.trunc(e)>>>0,r=t>>>24&255;return {r:t>>>16&255,g:t>>>8&255,b:t&255,a:r===0?1:r/255}}i(Qn,"argbIntToRgba");function ie(e,t){return Number.parseInt(e.slice(t,t+2),16)}i(ie,"byte");function St(e){return Number.parseInt(`${e??"0"}${e??"0"}`,16)}i(St,"dup");function wt(e){return Number.isFinite(e)?Math.min(255,Math.max(0,Math.round(e))):null}i(wt,"clampByte");function oa(e){if(e.a>=1)return ia(e.r,e.g,e.b);let t=Math.round(e.a*1e3)/1e3;return `rgba(${e.r},${e.g},${e.b},${t})`}i(oa,"normalizeRgba");function ia(e,t,r){return `#${kt(e)}${kt(t)}${kt(r)}`.toUpperCase()}i(ia,"rgbToHex");function kt(e){return e.toString(16).padStart(2,"0")}i(kt,"hex2");var Pt=Object.freeze(["composerInput","sendButton","userBubble","assistantBubble","recordCard","vetVisitButton","primaryButton","link"]);function ua(e){return Pt.includes(e)}i(ua,"isSlotName");function da(e){let t=typeof e=="number"?e:typeof e=="string"?Number(e.trim()):Number.NaN;return Number.isFinite(t)?Math.max(0,t):null}i(da,"parseRadius");function Zn(e){if(e===null||typeof e!="object"||Array.isArray(e))return null;let t={},r=false;for(let[n,o]of Object.entries(e)){if(!ua(n)||o===null||typeof o!="object")continue;let s=ca(o);s!==null&&(t[n]=s,r=true);}return r?Object.freeze(t):null}i(Zn,"parseThemeSlots");function Ve(e,t,r){return e[t]!==void 0?e[t]:e[r]}i(Ve,"pick");function ca(e){let t={},r=ee(Ve(e,"background_color","backgroundColor"));r!==null&&(t.backgroundColor=r);let n=ee(Ve(e,"border_color","borderColor"));n!==null&&(t.borderColor=n);let o=da(Ve(e,"border_radius","borderRadius"));o!==null&&(t.borderRadius=o);let s=ee(Ve(e,"text_color","textColor"));return s!==null&&(t.textColor=s),Object.keys(t).length===0?null:Object.freeze(t)}i(ca,"parseSlot");var fa=Object.freeze(["display_name","logo_url","logo_url_dark","primary_color","accent_color","primary_color_dark","accent_color_dark","brightness","color_scheme","font_family","font_url","fonts","font_urls","chat_placeholder","surface_style","radius_scale","accessibility_max_font_scale","slots"]),Tt="slots.";function pa(e){return Object.keys(e).every(t=>t==="schemaVersion"||(e[t]??null)===null)}i(pa,"isEmptyBranding");function ma(e){return e==="hide_powered_by"||fa.includes(e)?true:e.startsWith(Tt)&&Pt.includes(e.slice(Tt.length))}i(ma,"isThemeLockName");function We(e){if(e===null||typeof e!="object")return null;let t=e,r={displayName:se(x(t,"display_name","displayName")),logoUrl:se(x(t,"logo_url","logoUrl")),primaryColor:ee(x(t,"primary_color","primaryColor")),accentColor:ee(x(t,"accent_color","accentColor")),brightness:va(x(t,"brightness","color_scheme","colorScheme")),fontFamily:se(x(t,"font_family","fontFamily")),fontUrl:se(x(t,"font_url","fontUrl")),fonts:eo(x(t,"fonts")),fontUrls:eo(x(t,"font_urls","fontUrls")),placeholder:se(x(t,"chat_placeholder","placeholder","chatPlaceholder")),hidePoweredBy:ya(x(t,"hide_powered_by","hidePoweredBy")),primaryColorDark:ee(x(t,"primary_color_dark","primaryColorDark")),accentColorDark:ee(x(t,"accent_color_dark","accentColorDark")),surfaceStyle:to(x(t,"surface_style","surfaceStyle"),ha),radiusScale:to(x(t,"radius_scale","radiusScale"),ba),logoUrlDark:se(x(t,"logo_url_dark","logoUrlDark")),slots:Zn(x(t,"slots")),accessibilityMaxFontScale:Ea(x(t,"accessibility_max_font_scale","accessibilityMaxFontScale")),lockedFields:wa(x(t,"locked_fields","lockedFields")),schemaVersion:Ca(x(t,"schema_version","schemaVersion"))};return pa(r)?null:Object.freeze(r)}i(We,"parseClientBranding");function ya(e){if(typeof e=="boolean")return e;if(typeof e=="string"){let t=e.trim().toLowerCase();if(t==="true")return true;if(t==="false")return false}return null}i(ya,"parseBool");function x(e,...t){for(let r of t)if(Object.prototype.hasOwnProperty.call(e,r)){let n=e[r];if(n!==void 0)return n}}i(x,"pick");function se(e){if(typeof e!="string")return null;let t=e.trim();return t.length===0?null:t}i(se,"parseNonEmptyString");var ga=["regular","medium","bold","mono","monoMedium","monoBold"];function eo(e){if(e===null||typeof e!="object"||Array.isArray(e))return null;let t=e,r={};for(let n of ga){let o=se(x(t,n));o!==null&&(r[n]=o);}return Object.keys(r).length===0?null:Object.freeze(r)}i(eo,"parseFaceMap");var ha=["white","cream","subtle"],ba=["sharp","default","round"];function to(e,t){if(typeof e!="string")return null;let r=e.trim().toLowerCase();return t.includes(r)?r:null}i(to,"parseEnum");function va(e){if(typeof e!="string")return null;let t=e.trim().toLowerCase();return t==="light"||t==="dark"||t==="auto"?t:null}i(va,"parseBrightness");function ro(e){let t=typeof e=="number"?e:typeof e=="string"?Number(e.trim()):Number.NaN;return Number.isFinite(t)&&(typeof e!="string"||e.trim().length>0)?t:null}i(ro,"parseNumber");var _a=1,Ra=3.1;function Ea(e){let t=ro(e);return t===null?null:t<=0?0:Math.min(Ra,Math.max(_a,t))}i(Ea,"parseMaxFontScale");function Ca(e){if(e==null)return null;let t=ro(e);return t!==null&&Number.isInteger(t)&&t>=1?t:0}i(Ca,"parseSchemaVersion");function Sa(e){let t=e.trim();return t.startsWith(Tt)?t:t.replace(/([a-z0-9])([A-Z])/g,"$1_$2").toLowerCase()}i(Sa,"toWireName");function wa(e){if(!Array.isArray(e))return null;let t=[];for(let r of e){if(typeof r!="string")continue;let n=Sa(r);ma(n)&&!t.includes(n)&&t.push(n);}return t.length===0?null:Object.freeze(t)}i(wa,"parseLockedFields");var no="/widget/v1/entitlements",ka=304,Pa=Object.freeze({kind:"notModified"});async function io(e,t={},r=K({auth:e})){let n=await r.send("entitlements.fetch",xa(t));return n.ok?Ia(n.value):n.error.httpStatus===ka?Pa:{kind:"failed",error:n.error}}i(io,"fetchEntitlements");var Ta=64;function xa(e){let t={};return xt(e.cachedRevision)&&(t["if-none-match"]=`"${e.cachedRevision}"`),e.region&&e.region.length<=Ta?{method:"GET",path:no,headers:t,query:{region:e.region}}:{method:"GET",path:no,headers:t}}i(xa,"buildRequest");function Ia(e){if(e===null||typeof e!="object"||!xt(e.revision))return oo();let t=typeof e.region=="string"?e.region:"",r=xt(e.ttl_seconds)?e.ttl_seconds:0;return Object.freeze({kind:"updated",revision:e.revision,region:t,ttlSeconds:r,decisions:Aa(e.capabilities),branding:Oa(e)})}i(Ia,"parseUpdated");function Oa(e){let t=We(e.branding);if(t!==null)return t;let r=e.render_hints;if(r!==null&&typeof r=="object"){let n=We(r.branding);return n!==null?n:We(r)}return null}i(Oa,"parseBranding");function Aa(e){if(e===null||typeof e!="object")return Object.freeze([]);let t=[];for(let[r,n]of Object.entries(e))Fa(n)&&t.push(Object.freeze({resource:r,granted:true}));return Object.freeze(t)}i(Aa,"mapCapabilities");function Fa(e){return typeof e=="object"&&e!==null&&e.enabled===true}i(Fa,"isEnabled");function oo(){return {kind:"failed",error:S("internalError",{retryable:true,wireMessage:"malformed entitlements response"})}}i(oo,"malformed");function xt(e){return typeof e=="number"&&Number.isFinite(e)}i(xt,"isFiniteNumber");var Ma=30;function so(e){let t=e.scheduler??ja,r=e.resolve??io,n=Math.max(1,e.floorSeconds??Ma),o=e.rng??Math.random,s=i(()=>n+o()*n,"jitteredFloorSeconds"),l=false,u=false,a=null,d=null,c=n,m=0,h=i(()=>{a!==null&&(t.clear(a),a=null);},"clearTimer"),g=i(T=>{u||!l||(c=Math.max(n,T),a=t.set(()=>{a=null,E();},c*1e3));},"schedule"),C=null,P=i(async()=>{if(u)return null;let T=m;e.onFetch?.();let I=e.region?{cachedRevision:d,region:e.region}:{cachedRevision:d},B;try{B=await r(e.authFor(),I);}catch(O){return e.telemetry?.track("sdk.entitlements.poll_error",{reason:Da(O)}),!u&&T===m&&(e.onSettled?.(),g(s())),null}if(u||T!==m)return null;switch(B.kind){case "updated":d=B.revision,e.update(B.decisions,B.branding??null),g(B.ttlSeconds);break;case "notModified":g(c);break;case "failed":e.telemetry?.track("sdk.entitlements.poll_failed",{code:B.error.code}),g(s());break;default:g(s());}return e.onSettled?.(),B},"tick"),E=i(()=>{let T=P().finally(()=>{C===T&&(C=null);});return C=T,T},"run");return {start(){l||u||(l=true,E());},prime(){return u?Promise.resolve(null):C??E()},stop(){u||(u=true,m++,h());},refresh(){u||!l||(m++,d=null,h(),E());}}}i(so,"createEntitlementPoller");var ja={set(e,t){let r=setTimeout(e,t);return r.unref?.(),r},clear(e){clearTimeout(e);}};function Da(e){return e instanceof Error?e.message:"poll failed"}i(Da,"describe");var ao="everfur.notifications.device";var lo=3e3;function za(){return Object.freeze([Object.freeze({resource:"chat.message.create",granted:true})])}i(za,"compiledDefaultDecisions");function uo(e=za){let t=new Set,r=Object.freeze({decisions:e(),isPending:false,branding:null}),n=i(()=>{for(let o of t)o();},"emit");return {subscribe(o){return t.add(o),()=>{t.delete(o);}},getSnapshot(){return r},set(o){r=Object.freeze({decisions:Object.freeze([...o.decisions]),isPending:o.isPending,branding:o.branding??null}),n();},reset(){r=Object.freeze({decisions:e(),isPending:false,branding:null}),n();},setPending(o){r.isPending!==o&&(r=Object.freeze({...r,isPending:o}),n());}}}i(uo,"createEntitlementStore");function df(e,t){return new Ot(e,t)}i(df,"createEverfurRuntime");var Ua=6e4,co=Object.freeze([ao]),At=class At{constructor(t,r){this.sessionId=nt();this.entries=new Map;this.destroyers=new Map;this.epoch=0;this.disposed=false;this.verdictSettled=false;this.refreshTimer=null;this.bootstraps=new WeakMap;this.prepared=null;this.beforeLogoutHooks=new Set;this.pendingBeforeLogout=null;this.leavingSessionId=null;let n=t.config;if(n.secureStore!==void 0&&n.secureStore.isAvailable===true)throw new H("invalid-argument","config.secureStore is not yet consumable: SDK token persistence is unimplemented. Omit secureStore to keep memory-only tokens (SPEC-10 \xA75.3).");this.telemetry=n.telemetry?Na(n.telemetry):Ie;let o=typeof n?.publishableKey=="string"?n.publishableKey.trim():"",s=it(n?.publishableKey),l=n.transport!==void 0,u,a=typeof n.apiBaseUrl=="string"&&n.apiBaseUrl.trim().length>0?n.apiBaseUrl.trim():null;if(s!==null)u=mo(s);else if(n.transport!==void 0)u=n.transport;else {let c=La(n,r?.platform);c.ok?(a=c.config.apiBaseUrl,u=Or({config:c.config,...r?.eventSourceFactory?{eventSourceFactory:r.eventSourceFactory}:{}})):(s=c.failure,u=mo(c.failure));}this.configFailure=s,this.publishableKey=s===null?o:"",this.transport=u,s!==null&&Ba(s,this.telemetry),this.errorPolicy=n.errorPolicy,this.camera=n.camera??ur,this.upload=n.upload??Xr,this.uploadTransport=n.uploadTransport??vt,this.imageCache=n.imageCache??Ha,this.kv=n.storage??qa(),this.currentUser=t.user??null,this.identity=this.buildIdentity(t.user??null),this.activePet=t.activePet,this.store=s===null?uo():uo(()=>Xn("sdk_config",tt("accessDenied"))),this.services={authFor:i(c=>this.buildAuth(c),"authFor"),telemetry:this.telemetry,errorPolicy:this.errorPolicy,camera:this.camera,upload:this.upload,uploadTransport:this.uploadTransport,imageCache:this.imageCache,kv:this.kv,apiBaseUrl:a},this.registry={services:this.services,acquireChat:i(c=>this.acquireInternal("chat",It(c),()=>this.buildChatController(c),fo),"acquireChat"),releaseChat:i(c=>this.releaseInternal(c),"releaseChat"),peekChat:i(c=>this.entries.get(`${this.epoch}|chat|${It(c)}`)?.controller??null,"peekChat"),acquire:i((c,m,h,g)=>this.acquireInternal(c,m,h,g),"acquire"),release:i(c=>this.releaseInternal(c),"release")},this.entitlements=this.store;let d=s===null&&(r?.startEntitlementPolling??!l);this.poller=s===null?this.buildPoller(r?.pollScheduler):null,d&&this.poller?.start();}get isDisposed(){return this.disposed}get scopeEpoch(){return this.epoch}buildIdentity(t){if(t===null)return null;let r=br(t.userRef,t.getToken,n=>this.armTokenRefresh(r,n));return r}armTokenRefresh(t,r){if(this.clearTokenRefresh(),r===null||this.disposed||t!==this.identity)return;let n=r-Date.now();if(n<=0)return;let o=Math.max(n-Ua,n/2);this.refreshTimer=setTimeout(()=>{this.refreshTimer=null,!(this.disposed||t!==this.identity)&&t.currentToken({forceRefresh:true}).catch(()=>{});},o),this.refreshTimer.unref?.();}clearTokenRefresh(){this.refreshTimer!==null&&clearTimeout(this.refreshTimer),this.refreshTimer=null;}buildPoller(t){return so({authFor:i(()=>this.buildAuth(this.currentUser?.userRef??null),"authFor"),update:i((r,n)=>this.updateEntitlements({decisions:r,isPending:false,branding:n}),"update"),onFetch:i(()=>{this.verdictSettled||this.store.setPending(true);},"onFetch"),onSettled:i(()=>{this.verdictSettled=true,this.store.setPending(false);},"onSettled"),telemetry:this.telemetry,...t?{scheduler:t}:{}})}acquireInternal(t,r,n,o,s=false){let l=`${this.epoch}|${t}|${r}`,u=this.entries.get(l);if(u)return s||(u.warm?u.warm=false:u.refCount+=1),u.controller;let a=n();return this.entries.set(l,{controller:a,refCount:1,warm:s}),this.destroyers.set(a,o),a}releaseInternal(t){for(let[r,n]of this.entries)if(n.controller===t){n.refCount-=1,n.refCount<=0&&(this.runDestroyer(t),this.entries.delete(r));return}}runDestroyer(t){let r=this.destroyers.get(t);this.destroyers.delete(t),r&&r(t);}buildChatController(t){let r=yn({auth:this.buildAuth(t.userRef),telemetry:this.telemetry,...this.errorPolicy?{errorPolicy:this.errorPolicy}:{},initialConversationId:t.conversationId,petRef:t.petRef});return this.runBootstrap(r,t),r}runBootstrap(t,r){let n={};r.petRef!==null&&(n.petRef=r.petRef),r.conversationId!==null&&(n.resumeConversationId=r.conversationId);let o=bn(n,{controller:t});return o.then(s=>t.adoptPrompts(s.suggestedPrompts)).catch(()=>{}),this.bootstraps.set(t,o),o}buildAuth(t){return this.identity!==null&&this.currentUser!==null?{mode:"personalized",transport:this.transport,identity:this.identity,userRef:this.currentUser.userRef,sessionId:this.sessionId}:{mode:"anonymous",transport:this.transport,publishableKey:this.publishableKey,userRef:this.currentUser===null?null:t,sessionId:this.sessionId}}setUser(t){if(this.disposed)return;let r=t?.userRef??null,n=this.currentUser?.userRef??null;if(r===n){this.currentUser=t,t&&this.identity===null&&(this.identity=this.buildIdentity(t));return}this.pendingBeforeLogout=this.startBeforeLogoutHooks(),this.identity?.clear(),this.clearTokenRefresh(),this.currentUser=t,this.identity=this.buildIdentity(t),this.rescopeAll();}async logout(){if(this.disposed)return;let t=this.currentUser===null;this.leavingSessionId=this.sessionId,this.sessionId=nt(),this.setUser(null),this.leavingSessionId=null,t&&this.rescopeAll();let r=this.pendingBeforeLogout;this.pendingBeforeLogout=null,r!==null&&await r,await this.sweepPerUserKv();}onBeforeLogout(t){return this.disposed?()=>{}:(this.beforeLogoutHooks.add(t),()=>{this.beforeLogoutHooks.delete(t);})}startBeforeLogoutHooks(){let t=this.currentUser,r=this.identity;if(t===null||r===null||this.beforeLogoutHooks.size===0)return null;let n=Object.freeze({userRef:t.userRef,auth:this.graceAuth(t,r)}),o=[...this.beforeLogoutHooks].map(u=>{try{return Promise.resolve(u(n))}catch(a){return Promise.reject(a)}}),s=i((u,a)=>{try{this.telemetry.track("sdk.logout.hookFailed",{reason:u,count:a,totalCount:o.length});}catch{}},"report"),l=Promise.allSettled(o).then(u=>{let a=u.filter(d=>d.status==="rejected").length;a>0&&s("failed",a);});return new Promise(u=>{let a=false,d=i(()=>{a||(a=true,clearTimeout(c),u());},"finish"),c=setTimeout(()=>{a||s("timeout",o.length),d();},3e3);l.then(d,d);})}graceAuth(t,r){let n=r.currentToken();n.catch(()=>{});let o={userRef:t.userRef,currentToken:i(()=>n,"currentToken"),hasToken:i(()=>true,"hasToken"),clear:i(()=>{},"clear")};return {mode:"personalized",transport:this.transport,identity:o,userRef:t.userRef,sessionId:this.leavingSessionId??this.sessionId}}async sweepPerUserKv(){if(co.length===0)return;let t=await Promise.allSettled(co.map(n=>this.kv.removeItem(n))),r=t.filter(n=>n.status==="rejected").length;r>0&&this.telemetry.track("sdk.logout.sweepPartialFailure",{failedCount:r,totalCount:t.length});}async registerPet(t,r){return this.withPets("registerPet",n=>r===void 0?n.registerPet(t):n.registerPet(t,r))}updatePet(t,r){return this.withPets("updatePet",n=>n.updatePet(t,r))}deletePet(t){return this.withPets("deletePet",r=>r.deletePet(t))}eraseUserData(){return this.withPets("eraseUserData",t=>t.eraseUserData())}async withPets(t,r){return this.disposed?f(po(t)):r(Gn(this.buildAuth(this.currentUser?.userRef??null)))}prepare(t){let r=t?.petRef??null,n=`${this.epoch}|${this.currentUser?.userRef??""}|${r??""}`,o=this.prepared;if(o!==null&&o.key===n&&(o.result===null||o.result.status==="ready"))return o.promise;let s={key:n,result:null,promise:this.runPrepare(r).then(l=>(s.result=l,l))};return this.prepared=s,s.promise}async runPrepare(t){let r=Date.now(),n=this.configFailure,o=this.disposed?po("prepare"):n===null?null:yo(n),s=this.identity,[l,u,a]=await Promise.all([o?f(o):s===null?_(void 0):s.currentToken().then(()=>_(void 0),()=>f(S("authRejected",{retryable:false}))),o?f(o):this.primeEntitlements(),t===null?void 0:o?f(o):this.primeChat(t)]),d=l.ok?u.ok&&(a?.ok??true)?"ready":"partial":"failed",c=Date.now()-r;try{this.telemetry.track("sdk.prepare.timing",{durationMs:c,status:d});}catch{}return Object.freeze({status:d,durationMs:c,session:l,entitlements:u,...a?{chat:a}:{}})}async primeEntitlements(){let t=await this.poller?.prime();return t?t.kind==="failed"?f(t.error):_(void 0):f(S("internalError",{retryable:true}))}async primeChat(t){let r={userRef:this.currentUser?.userRef??null,petRef:t,conversationId:null},n=this.acquireInternal("chat",It(r),()=>this.buildChatController(r),fo,true),o=await this.bootstraps.get(n);return o?.cause&&n.getSnapshot().conversationId===null&&(o=await this.runBootstrap(n,r)),o?.cause?f(o.cause):_(void 0)}setActivePet(t){if(this.disposed)return;let r=t??null;r!==this.activePet&&(this.activePet=r,this.rescopeAll());}updateEntitlements(t){this.disposed||this.configFailure===null&&this.store.set(t);}open(t){this.telemetry.track("sdk.open",{capability:t});}dispose(){this.disposed||(this.disposed=true,this.epoch+=1,this.poller?.stop(),this.identity?.clear(),this.clearTokenRefresh(),this.disposeAllControllers());}rescopeAll(){this.epoch+=1,this.disposeAllControllers(),this.store.reset(),this.verdictSettled=false,this.poller?.refresh();}disposeAllControllers(){for(let t of this.entries.values())this.runDestroyer(t.controller);this.entries.clear(),this.destroyers.clear();}};i(At,"EverfurRuntimeImpl");var Ot=At;function It(e){return `${e.userRef??""}|${e.petRef??""}|${e.conversationId??""}`}i(It,"chatScopeKey");function fo(e){e.dispose();}i(fo,"disposeChat");function po(e){return S("validationFailed",{retryable:false,wireMessage:`the Everfur runtime is disposed; ${e} was called after unmount`})}i(po,"disposedError");function yo(e){return S("validationFailed",{retryable:false,wireMessage:`Everfur SDK is not configured: ${e.message}`})}i(yo,"notConfiguredError");function La(e,t){let r={publishableKey:e.publishableKey,...e.apiBaseUrl!==void 0?{apiBaseUrl:e.apiBaseUrl}:{},...e.contractVersion!==void 0?{contractVersion:e.contractVersion}:{},...e.debug!==void 0?{debug:e.debug}:{}};return wr(r,t===void 0?void 0:{platform:t})}i(La,"tryResolveClient");function Na(e){return Object.freeze({track(t,r){try{e.track(t,r);}catch{}},trackExpectedFailure(t,r){try{e.trackExpectedFailure(t,r);}catch{}}})}i(Na,"guardTelemetry");function Ba(e,t){try{t.trackExpectedFailure("sdk.config.invalid",{reason:e.reason});}catch{}globalThis.console?.error?.(`[everfur] SDK disabled: ${e.message}
|
|
12
|
+
[everfur] Every Everfur capability will render its off-state until this is fixed. If the value is set in your environment, note that babel-preset-expo inlines only EXPO_PUBLIC_* variables into a release bundle.`);}i(Ba,"reportConfigFailure");function mo(e){return Object.freeze({request(){return Promise.resolve(f(yo(e)))},stream(t,r){let n=N({code:"sdk_not_configured",retryable:false,wireMessage:`Everfur SDK is not configured: ${e.message}`,synthesized:true,lastEventId:null});return {async*[Symbol.asyncIterator](){r.aborted||(yield n);}}}})}i(mo,"refusingTransport");function qa(){let e=new Map;return {async getItem(t){return e.get(t)??null},async setItem(t,r){e.set(t,r);},async removeItem(t){e.delete(t);},async keys(t){return [...e.keys()].filter(r=>r.startsWith(t))}}}i(qa,"createInMemoryKv");var Ha=Object.freeze({clearMemoryCache(){},clearDiskCache(){}});var bo=new Set(["requested","awaiting_clinic","awaiting_upload","received","parsing","in_review","published","failed","revoked"]),go=Object.freeze({submitted:"requested",sent:"requested",dispatching:"requested",awaiting_response:"awaiting_clinic",clinic_responded_no_records:"awaiting_clinic",records_received:"received",parsing_failed:"in_review",review_email_failed:"in_review",clinic_declined:"failed"});function Ka(e){let t=Object.prototype.hasOwnProperty.call(go,e)?go[e]:void 0;if(t!==void 0)return t;let r=e;return bo.has(r)?r:"parsing"}i(Ka,"normalizeStatus");function $a(e){return e==="owner_reported"||e==="clinic_document"?e:null}i($a,"normalizeOrigin");var Va=z$1.object({request_id:z$1.string().min(1),pet_ref:z$1.string().min(1),status:z$1.string(),simple_status:z$1.string().nullish(),simple_status_detail:z$1.string().nullish(),status_label:z$1.string().optional(),dispatch_status:z$1.string().nullish(),can_retry_send:z$1.boolean().optional(),can_revoke:z$1.boolean().optional(),can_convert_to_upload:z$1.boolean().optional(),can_update_clinic_email:z$1.boolean().optional(),reminder_count:z$1.number().int().nonnegative().optional(),last_reminder_at:z$1.string().nullish(),waiting_expectation:z$1.string().nullish(),document_count:z$1.number().optional(),held_item_count:z$1.number().optional(),received_at:z$1.string().nullish(),parsing_started_at:z$1.string().nullish(),review_started_at:z$1.string().nullish(),created_at:z$1.string().optional(),updated_at:z$1.string().optional(),source:z$1.string().nullish().catch(null),action_needed_label:z$1.string().nullish().catch(null),failure_reason:z$1.string().nullish().catch(null),failure_code:z$1.string().nullish().catch(null),recovery_stage:z$1.string().nullish().catch(null),show_clinic_phone:z$1.boolean().optional().catch(void 0),clinic_name:z$1.string().nullish().catch(null),clinic_email:z$1.string().nullish().catch(null),clinic_phone:z$1.string().nullish().catch(null),converted_to_upload_at:z$1.string().nullish().catch(null),request_group_id:z$1.string().nullish().catch(null)}).passthrough();function vo(e){let t=Va.safeParse(e);if(!t.success)return null;let r=t.data,n=Wa(r.simple_status),o=n==="requested"&&(r.status==="awaiting_upload"||r.simple_status_detail==="awaiting_owner_upload")?"awaiting_upload":n==="parsing"&&(r.simple_status_detail==="in_review"||r.simple_status_detail==="review_email_failed")?"in_review":n??Ka(r.status);return Object.freeze({id:r.request_id,petRef:r.pet_ref,status:o,simpleStatus:n,simpleStatusDetail:r.simple_status_detail??null,statusLabel:r.status_label??"",dispatchStatus:r.dispatch_status??null,canRetrySend:r.can_retry_send===true,canRevoke:r.can_revoke===true,canConvertToUpload:r.can_convert_to_upload===true,canUpdateClinicEmail:r.can_update_clinic_email===true,reminderCount:r.reminder_count??0,lastReminderAt:r.last_reminder_at??null,waitingExpectation:r.waiting_expectation??null,documentCount:ho(r.document_count,0),heldItemCount:ho(r.held_item_count,0),receivedAt:r.received_at??null,parsingStartedAt:r.parsing_started_at??null,reviewStartedAt:r.review_started_at??null,createdAt:r.created_at??"",updatedAt:r.updated_at??"",wireStatus:r.status,source:r.source??null,actionNeededLabel:r.action_needed_label??null,failureReason:r.failure_reason??null,failureCode:r.failure_code??null,recoveryStage:r.recovery_stage??null,showClinicPhone:r.show_clinic_phone===true,clinicName:r.clinic_name??null,clinicEmail:r.clinic_email??null,clinicPhone:r.clinic_phone??null,convertedToUploadAt:r.converted_to_upload_at??null,requestGroupId:r.request_group_id??null})}i(vo,"mapRequestView");z$1.object({request_group_id:z$1.string().min(1),pet_ref:z$1.string().min(1),total:z$1.number().int().nonnegative(),responded:z$1.number().int().nonnegative(),pending:z$1.number().int().nonnegative(),members:z$1.array(z$1.unknown())});function Wa(e){return !e||e==="awaiting_upload"||e==="in_review"?null:bo.has(e)?e:null}i(Wa,"normalizeSimpleStatus");z$1.object({source_doc_id:z$1.string().min(1),request_id:z$1.string().min(1)});var Ga=z$1.object({label:z$1.string(),value:z$1.string()}),Ft=z$1.object({key:z$1.string(),category:z$1.string().optional(),label:z$1.string().optional(),value:z$1.string().nullish(),unit:z$1.string().nullish(),observed_at:z$1.string().nullish(),status:z$1.string().nullish(),origin:z$1.string().nullish(),canonical_key:z$1.string().nullish()}),Ya=z$1.object({at:z$1.string(),value:z$1.number().nullish(),display:z$1.string().nullish(),origin:z$1.string().nullish()}),Xa=z$1.object({key:z$1.string(),label:z$1.string().optional(),points:z$1.array(Ya).optional()}),Qa=z$1.object({title:z$1.string(),detail:z$1.string().nullish(),due_at:z$1.string().nullish()}),Mt=z$1.object({doc_id:z$1.string(),title:z$1.string().nullish(),page_count:z$1.number().nullish(),received_at:z$1.string().nullish()});function _o(e){return Object.freeze({key:e.key,category:e.category??"",label:e.label??e.key,value:e.value??null,unit:e.unit??null,observedAt:e.observed_at??null,status:e.status??null,origin:$a(e.origin),canonicalKey:e.canonical_key??null})}i(_o,"mapEntityRow");function Ro(e){return Object.freeze({docId:e.doc_id,title:e.title??null,pageCount:e.page_count??null,receivedAt:e.received_at??null})}i(Ro,"mapDocumentRow");z$1.object({identity:z$1.array(Ga).optional(),entities:z$1.array(Ft).optional(),entity_series:z$1.array(Xa).optional(),forward_looking:z$1.array(Qa).optional(),documents:z$1.array(Mt).optional()});z$1.object({pet_ref:z$1.string().optional(),granted:z$1.boolean().optional(),version:z$1.string().nullish(),granted_at:z$1.string().nullish()});function ho(e,t){return typeof e=="number"&&Number.isFinite(e)?e:t}i(ho,"numberOr");var Co=10,Ge=z$1.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i),Ce=i((e,t=1)=>z$1.string().refine(r=>!U(r)&&[...r].length>=t&&[...r].length<=e),"text"),So=i(e=>[...e].some(t=>t.charCodeAt(0)<32||t.charCodeAt(0)===127),"hasControl"),Ja=z$1.object({clinicId:Ge.optional(),clinicFreeText:Ce(200).refine(e=>e.trim().length>0).optional(),clinicEmail:Ce(320,3).refine(e=>!So(e)&&/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(e.trim())).optional(),signatureId:Ge.optional(),signaturePngBase64:z$1.string().min(1).max(2*1024*1024).optional(),idempotencyKey:z$1.string().regex(/^[A-Za-z0-9._-]{8,128}$/)}).strict().refine(e=>e.clinicId===void 0!=(e.clinicFreeText===void 0)).refine(e=>e.signatureId===void 0!=(e.signaturePngBase64===void 0)),Za=z$1.object({petRef:Ce(128),ownerName:Ce(200).refine(e=>e.trim().length>0&&!So(e)),authorizationVersion:Ce(64),clinics:z$1.array(Ja).min(1).max(Co)}).strict(),el=z$1.object({request_group_id:Ge,pet_ref:z$1.string(),created_count:z$1.number().int().nonnegative(),failed_count:z$1.number().int().nonnegative(),results:z$1.array(z$1.object({idempotency_key:z$1.string(),clinic_id:Ge.nullable().optional(),clinic_free_text:z$1.string().nullable().optional(),created:z$1.boolean(),request:z$1.unknown().optional(),failure_code:z$1.string().nullable().optional(),failure_reason:z$1.string().nullable().optional()}))});function tl(e){let t=e.funnel??K({auth:e.auth,...e.errorPolicy?{errorPolicy:e.errorPolicy}:{}});return {async createClinicRequestBatch(r){if(!Za.safeParse(r).success)return f(S("validationFailed",{retryable:false}));let n=await t.send("records.clinic.createBatch",{method:"POST",path:"/widget/v1/records/clinic-requests/batch",body:{pet_ref:r.petRef,owner_name:r.ownerName,authorization_version:r.authorizationVersion,clinics:r.clinics.map(l=>({...l.clinicId!==void 0?{clinic_id:l.clinicId}:{clinic_free_text:l.clinicFreeText},...l.clinicEmail!==void 0?{clinic_email:l.clinicEmail}:{},...l.signatureId!==void 0?{signature_id:l.signatureId}:{signature_png_base64:l.signaturePngBase64},idempotency_key:l.idempotencyKey}))}});if(!n.ok)return n;let o=el.safeParse(n.value);if(!o.success||o.data.pet_ref!==r.petRef)return Eo();let s=[];for(let l of o.data.results){let u=l.request===void 0||l.request===null?null:vo(l.request);if(l.created!==(u!==null))return Eo();s.push(Object.freeze({idempotencyKey:l.idempotency_key,clinicId:l.clinic_id??null,clinicFreeText:l.clinic_free_text??null,created:l.created,request:u,failureCode:l.failure_code??null,failureReason:l.failure_reason??null}));}return _(Object.freeze({requestGroupId:o.data.request_group_id,petRef:o.data.pet_ref,results:Object.freeze(s),createdCount:o.data.created_count,failedCount:o.data.failed_count}))}}}i(tl,"createRecordsClinicBatchClient");function Eo(){return f(S("internalError",{retryable:false}))}i(Eo,"malformed");var rl="records_consent_required";function nl(e){let t=e.raw;if(t===null||typeof t!="object")return null;let r=t,n=typeof r.error=="object"&&r.error!==null?r.error.code:r.code;return typeof n=="string"&&n.length>0?n:null}i(nl,"recordsWireCodeOf");function wo(e){return e===null||e.httpStatus!==409?false:nl(e)===rl}i(wo,"isRecordsConsentRequired");var jt="value_text",ko=64,Po=512;function ol(e){return e!==null&&e.httpStatus===409&&!wo(e)}i(ol,"isFactReviewerLocked");function il(e){return Object.freeze({[jt]:e.trim()})}i(il,"factValueCorrection");var Se=Object.freeze({num:"value_num",date:"value_date",bool:"value_bool",text:jt}),To=/^[+-]?(?:\d+\.?\d*|\.\d+)$/,xo=/^\d{4}-\d{2}-\d{2}$/;function Io(e){if(e==null)return "text";let t=e.trim();return To.test(t)?"num":xo.test(t)&&!Number.isNaN(Date.parse(t))?"date":t==="true"||t==="false"?"bool":"text"}i(Io,"inferFactValueKind");function sl(e,t){let r=t.trim(),n=Io(e);if(n==="num"&&To.test(r)){let o=Number(r);if(Number.isFinite(o))return Object.freeze({[Se.num]:o})}return n==="date"&&xo.test(r)&&!Number.isNaN(Date.parse(r))?Object.freeze({[Se.date]:r}):Object.freeze(n==="bool"&&(r==="true"||r==="false")?{[Se.bool]:r==="true"}:{[Se.text]:r})}i(sl,"factCorrectionFor");var k=z$1.string().nullish(),Ye=z$1.number().nullish(),al=z$1.object({collected_at:k,at:k,value:Ye,unit:k,qualitative_result:k,ref_low:Ye,ref_high:Ye,status:k,source_clinic:k,source_doc_id:k,doc_id:k,reviewed:z$1.boolean().nullish()}),ll=z$1.object({collected_at:k,at:k,value:Ye,unit:k,qualitative_result:k,status:k}),ul=z$1.object({marker_id:z$1.string().min(1),canonical_name:k,name:k,loinc_code:k,canonical_unit:k,unit:k,panel_name:k,panel:k,meaning_text:k,meaning:k,latest:ll.nullish(),trajectory:k,points:z$1.array(al).optional()}),dl=z$1.object({total_markers:z$1.number().int().nonnegative(),in_range_count:z$1.number().int().nonnegative(),out_of_range_count:z$1.number().int().nonnegative(),unknown_count:z$1.number().int().nonnegative()}),cl=z$1.object({markers:z$1.array(ul).optional(),summary:dl.nullish(),disclaimer:z$1.string().optional(),featured_marker_id:k});function fl(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}i(fl,"isObject");function Oo(e){return Object.freeze({petRef:e,withheld:true,markers:Object.freeze([]),summary:null,disclaimer:"",featuredMarkerId:null})}i(Oo,"withheldMarkers");function Dt(e,t){let r=fl(t)?t:{},n=typeof r.pet_ref=="string"&&r.pet_ref.length>0?r.pet_ref:e;if(r.withheld===true)return Oo(n);let o=cl.safeParse(r);if(!o.success)return Oo(n);let s=o.data,l=i(a=>Object.freeze({at:a.collected_at??a.at??null,value:a.value??null,unit:a.unit??null,qualitativeResult:a.qualitative_result??null,refLow:a.ref_low??null,refHigh:a.ref_high??null,status:a.status??null,sourceClinic:a.source_clinic??null,docId:a.source_doc_id??a.doc_id??null,reviewed:a.reviewed===true}),"point"),u=(s.markers??[]).map(a=>Object.freeze({markerId:a.marker_id,name:a.canonical_name??a.name??a.marker_id,loincCode:a.loinc_code??null,unit:a.canonical_unit??a.unit??null,panel:a.panel_name??a.panel??null,meaning:a.meaning_text??a.meaning??null,latest:a.latest?Object.freeze({at:a.latest.collected_at??a.latest.at??null,value:a.latest.value??null,unit:a.latest.unit??null,qualitativeResult:a.latest.qualitative_result??null,status:a.latest.status??null}):null,trajectory:a.trajectory??null,points:Object.freeze((a.points??[]).map(l))}));return Object.freeze({petRef:n,withheld:false,markers:Object.freeze(u),summary:s.summary?Object.freeze({totalMarkers:s.summary.total_markers,inRangeCount:s.summary.in_range_count,outOfRangeCount:s.summary.out_of_range_count,unknownCount:s.summary.unknown_count}):null,disclaimer:s.disclaimer??"",featuredMarkerId:s.featured_marker_id??null})}i(Dt,"mapRecordMarkers");var pl=z$1.string().min(1).refine(e=>e.startsWith("https://")),we=z$1.string().nullish(),ml=z$1.object({share_id:z$1.string().min(1),share_url:z$1.string().min(1),expires_at:we}),yl=z$1.object({shares:z$1.array(z$1.object({share_id:z$1.string().min(1),expires_at:we,created_at:we,view_count:z$1.number().int().nonnegative().nullish(),last_viewed_at:we})).optional()}),gl=z$1.object({download_url:pl,expires_at:we});function Ao(e,t){let r=e.trim();if(r.length===0)return null;try{let n=/^[a-z][a-z0-9+.-]*:/i.test(r)?new URL(r):t!==void 0?new URL(r,t):null;return n===null||n.protocol!=="https:"?null:n.toString()}catch{return null}}i(Ao,"resolveShareUrl");function zt(e,t){let r=ml.safeParse(e);if(!r.success)return null;let n=Ao(r.data.share_url,t);return n===null?null:Object.freeze({shareId:r.data.share_id,shareUrl:n,expiresAt:r.data.expires_at??null})}i(zt,"mapRecordShareLink");function Ut(e){let t=yl.safeParse(e);return t.success?Object.freeze((t.data.shares??[]).map(r=>Object.freeze({shareId:r.share_id,expiresAt:r.expires_at??null,createdAt:r.created_at??null,viewCount:r.view_count??0,lastViewedAt:r.last_viewed_at??null}))):null}i(Ut,"mapRecordShareList");function Lt(e){let t=gl.safeParse(e);return t.success?Object.freeze({downloadUrl:t.data.download_url,expiresAt:t.data.expires_at??null}):null}i(Lt,"mapRecordPdfLink");var hl=z$1.object({signatures:z$1.array(z$1.object({signature_id:z$1.string().min(1),preview_url:z$1.string().min(1).refine(e=>e.startsWith("https://")),created_at:z$1.string().nullish()})).optional()});function Nt(e){let t=hl.safeParse(e);return t.success?Object.freeze((t.data.signatures??[]).map(r=>Object.freeze({signatureId:r.signature_id,previewUrl:r.preview_url,createdAt:r.created_at??null}))):null}i(Nt,"mapSignatureSuggestions");var v=z$1.string().nullish(),ke=z$1.number().nullish(),bl=z$1.object({at:v,value:ke,unit:v,qualitative_result:v,ref_low:ke,ref_high:ke,status:v,doc_id:v}),vl=z$1.object({marker_id:z$1.string(),name:z$1.string(),loinc_code:v,unit:v,panel:v,meaning:v,latest:z$1.object({at:v,value:ke,unit:v,qualitative_result:v,status:v}).nullish(),trajectory:v,points:z$1.array(bl).optional()}),_l=z$1.object({encounter_id:z$1.string(),date:v,type:v,clinic_name:v,veterinarian:v,doc_id:v}),Rl=z$1.object({note_id:z$1.string(),encounter_id:v,observed_on:v,sections:z$1.array(z$1.object({section:z$1.string(),text:z$1.string()})).optional()}),El=z$1.object({exam_id:z$1.string(),encounter_id:v,observed_on:v,doc_id:v,systems:z$1.record(z$1.object({finding_status:v,finding:v})).optional()}),Cl=z$1.object({has_lab_history:z$1.boolean().optional(),has_vaccination_history:z$1.boolean().optional(),has_weight_history:z$1.boolean().optional(),has_vitals_history:z$1.boolean().optional(),has_physical_exam_history:z$1.boolean().optional(),has_procedure_history:z$1.boolean().optional(),has_genetic_history:z$1.boolean().optional(),has_reproductive_history:z$1.boolean().optional(),has_parasite_prevention_history:z$1.boolean().optional(),earliest_record_at:v,latest_record_at:v,documents_ingested:z$1.number().int().nonnegative().optional(),documents_in_review:z$1.number().int().nonnegative().optional(),entities_pending_review:z$1.record(z$1.number().int().nonnegative()).optional(),held_total:z$1.number().int().nonnegative().optional()}),Sl=z$1.object({conflict_id:z$1.string(),entity_type:z$1.string(),field:v,severity:v,candidates:z$1.array(z$1.object({value:z$1.string(),source_doc_id:v,doc_id:v,collected_at:v})).optional()}),wl=z$1.object({lab_results:z$1.array(vl).optional(),encounters:z$1.array(_l).optional(),clinician_notes:z$1.array(Rl).optional(),physical_exams:z$1.array(El).optional(),completeness:Cl.nullish(),conflicts:z$1.array(Sl).optional()}),kl=z$1.object({visits:z$1.array(z$1.object({visit_id:z$1.string(),visit_date:v,veterinarian:v,summary:v,doc_id:v})),vaccines:z$1.array(z$1.object({vaccine_id:z$1.string(),product:v,lot:v,administered_on:v,expires_on:v,doc_id:v})),weights:z$1.array(z$1.object({weight_id:z$1.string(),observed_on:v,weight_kg:ke,doc_id:v})),medications:z$1.array(z$1.object({medication_id:z$1.string(),drug_name:v,dose:v,route:v,frequency:v,sig:v,rx_number:v,started_on:v,stopped_on:v,doc_id:v})),disclaimer:z$1.string().optional()}),Pl=z$1.object({document:Mt,contributions:z$1.array(Ft),contribution_count:z$1.number().int().nonnegative().optional()});function qt(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}i(qt,"isObject");function Ht(e,t){return typeof e.pet_ref=="string"&&e.pet_ref.length>0?e.pet_ref:t}i(Ht,"petOf");function Bt(e,t){return Object.freeze({petRef:e,available:false,withheld:t,labResults:Object.freeze([]),encounters:Object.freeze([]),clinicianNotes:Object.freeze([]),physicalExams:Object.freeze([]),completeness:null,conflicts:Object.freeze([])})}i(Bt,"emptyDepth");function Mo(e,t){let r=qt(t)?t:{},n=Ht(r,e);if(r.withheld===true)return Bt(n,true);if(!["lab_results","encounters","clinician_notes","physical_exams","completeness","conflicts"].some(a=>a in r))return Bt(n,false);let s=wl.safeParse(r);if(!s.success)return Bt(n,true);let l=s.data,u=i(a=>Object.freeze({at:a.at??null,value:a.value??null,unit:a.unit??null,qualitativeResult:a.qualitative_result??null,refLow:a.ref_low??null,refHigh:a.ref_high??null,status:a.status??null,docId:a.doc_id??null}),"point");return Object.freeze({petRef:n,available:true,withheld:false,labResults:Object.freeze((l.lab_results??[]).map(a=>Object.freeze({markerId:a.marker_id,name:a.name,loincCode:a.loinc_code??null,unit:a.unit??null,panel:a.panel??null,meaning:a.meaning??null,latest:Object.freeze({at:a.latest?.at??null,value:a.latest?.value??null,unit:a.latest?.unit??null,qualitativeResult:a.latest?.qualitative_result??null,status:a.latest?.status??null}),trajectory:a.trajectory??null,points:Object.freeze((a.points??[]).map(u))}))),encounters:Object.freeze((l.encounters??[]).map(a=>Object.freeze({encounterId:a.encounter_id,date:a.date??null,type:a.type??null,clinicName:a.clinic_name??null,veterinarian:a.veterinarian??null,docId:a.doc_id??null}))),clinicianNotes:Object.freeze((l.clinician_notes??[]).map(a=>Object.freeze({noteId:a.note_id,encounterId:a.encounter_id??null,observedOn:a.observed_on??null,sections:Object.freeze((a.sections??[]).map(d=>Object.freeze({section:d.section,text:d.text})))}))),physicalExams:Object.freeze((l.physical_exams??[]).map(a=>Object.freeze({examId:a.exam_id,encounterId:a.encounter_id??null,observedOn:a.observed_on??null,docId:a.doc_id??null,systems:Object.freeze(Object.entries(a.systems??{}).map(([d,c])=>Object.freeze({system:d,findingStatus:c.finding_status??null,finding:c.finding??null})))}))),completeness:l.completeness?Object.freeze({hasLabHistory:l.completeness.has_lab_history===true,hasVaccinationHistory:l.completeness.has_vaccination_history===true,hasWeightHistory:l.completeness.has_weight_history===true,hasVitalsHistory:l.completeness.has_vitals_history===true,hasPhysicalExamHistory:l.completeness.has_physical_exam_history===true,hasProcedureHistory:l.completeness.has_procedure_history===true,hasGeneticHistory:l.completeness.has_genetic_history===true,hasReproductiveHistory:l.completeness.has_reproductive_history===true,hasParasitePreventionHistory:l.completeness.has_parasite_prevention_history===true,earliestRecordAt:l.completeness.earliest_record_at??null,latestRecordAt:l.completeness.latest_record_at??null,documentsIngested:l.completeness.documents_ingested??0,documentsInReview:l.completeness.documents_in_review??0,entitiesPendingReview:Object.freeze({...l.completeness.entities_pending_review??{}}),heldTotal:l.completeness.held_total??0}):null,conflicts:Object.freeze((l.conflicts??[]).map(a=>Object.freeze({conflictId:a.conflict_id,entityType:a.entity_type,field:a.field??null,severity:a.severity??"needs_review",candidates:Object.freeze((a.candidates??[]).map(d=>Object.freeze({value:d.value,docId:d.source_doc_id??d.doc_id??null,collectedAt:d.collected_at??null})))})))})}i(Mo,"mapRecordDepth");function Fo(e){return Object.freeze({petRef:e,withheld:true,isEmpty:false,visits:Object.freeze([]),vaccines:Object.freeze([]),weights:Object.freeze([]),medications:Object.freeze([]),disclaimer:""})}i(Fo,"withheldTimeline");function jo(e,t){let r=qt(t)?t:{},n=Ht(r,e);if(r.withheld===true)return Fo(n);let o=kl.safeParse(r);if(!o.success)return Fo(n);let s=o.data,l=s.visits.map(c=>Object.freeze({visitId:c.visit_id,visitDate:c.visit_date??null,veterinarian:c.veterinarian??null,summary:c.summary??null,docId:c.doc_id??null})),u=s.vaccines.map(c=>Object.freeze({vaccineId:c.vaccine_id,product:c.product??null,lot:c.lot??null,administeredOn:c.administered_on??null,expiresOn:c.expires_on??null,docId:c.doc_id??null})),a=s.weights.map(c=>Object.freeze({weightId:c.weight_id,observedOn:c.observed_on??null,weightKg:c.weight_kg??null,docId:c.doc_id??null})),d=s.medications.map(c=>Object.freeze({medicationId:c.medication_id,drugName:c.drug_name??null,dose:c.dose??null,route:c.route??null,frequency:c.frequency??null,sig:c.sig??null,rxNumber:c.rx_number??null,startedOn:c.started_on??null,stoppedOn:c.stopped_on??null,docId:c.doc_id??null}));return Object.freeze({petRef:n,withheld:false,isEmpty:l.length===0&&u.length===0&&a.length===0&&d.length===0,visits:Object.freeze(l),vaccines:Object.freeze(u),weights:Object.freeze(a),medications:Object.freeze(d),disclaimer:s.disclaimer??""})}i(jo,"mapRecordsTimeline");function Do(e,t){let r=qt(t)?t:{},n=Ht(r,e),o=i(()=>Object.freeze({petRef:n,withheld:true,document:null,contributions:Object.freeze([]),contributionCount:0}),"withheld");if(r.withheld===true)return o();let s=Pl.safeParse(r);if(!s.success)return o();let l=Object.freeze(s.data.contributions.map(_o));return Object.freeze({petRef:n,withheld:false,document:Ro(s.data.document),contributions:l,contributionCount:s.data.contribution_count??l.length})}i(Do,"mapDocumentContributions");var Tl="/widget/v1/records/pets";function xl(e){let t=e.funnel??K({auth:e.auth,...e.errorPolicy?{errorPolicy:e.errorPolicy}:{}}),r=i((a,d)=>typeof a=="string"&&a.length>0&&!U(a)&&[...a].length<=d,"segment"),n=i(async(a,d,c,m)=>{if(!r(d,te))return re();let h=await t.send(a,{method:"GET",path:c});if(!h.ok)return h;let g=m(h.value);return g.petRef===d?_(g):f(S("internalError",{retryable:false}))},"read"),o=i(a=>`${Tl}/${encodeURIComponent(a)}`,"pet"),s=i(a=>`${o(a)}/everfur_record`,"record"),l=i(async(a,d,c)=>{let m=await t.send(a,d,d.method==="POST"?{idempotent:false,maxAttempts:1}:void 0);if(!m.ok)return m;let h=c(m.value);return h===null?f(S("internalError",{retryable:false})):_(h)},"parsed"),u=i((a,d)=>!r(a.entityType,ko)||!r(a.canonicalKey,Po)||a.idempotencyKey!==void 0&&!r(a.idempotencyKey,_n)||d!==void 0&&Object.keys(d).length===0?null:{entity_type:a.entityType,canonical_key:a.canonicalKey,...d!==void 0?{corrected_fields:d}:{},...a.idempotencyKey!==void 0?{idempotency_key:a.idempotencyKey}:{}},"factBody");return {getRecordDepth:i(a=>n("records.depth.record",a,`${o(a)}/record`,d=>Mo(a,d)),"getRecordDepth"),getTimeline:i(a=>n("records.depth.timeline",a,`${o(a)}/timeline`,d=>jo(a,d)),"getTimeline"),getDocumentContributions(a,d){return r(d,64)?n("records.depth.contributions",a,`${o(a)}/documents/${encodeURIComponent(d)}/contributions`,c=>Do(a,c)):re()},getMarkers:i(a=>n("records.depth.markers",a,`${o(a)}/markers`,d=>Dt(a,d)),"getMarkers"),createShare(a){return r(a,te)?l("records.share.create",{method:"POST",path:`${s(a)}/share`},d=>zt(d,e.apiBaseUrl)):re()},listShares(a){return r(a,te)?l("records.share.list",{method:"GET",path:`${s(a)}/shares`},Ut):re()},async revokeShare(a,d){if(!r(a,te)||!r(d,64))return re();let c=await t.send("records.share.revoke",{method:"DELETE",path:`${s(a)}/shares/${encodeURIComponent(d)}`},{idempotent:false,maxAttempts:1});return c.ok?_(void 0):c},getPdfLink(a){return r(a,te)?l("records.pdf.link",{method:"GET",path:`${s(a)}/pdf-link`},Lt):re()},async editFact(a,d){let c=r(a,te)?u(d,d.correctedFields):null;if(c===null)return re();let m=await t.send("records.fact.edit",{method:"POST",path:`${s(a)}/facts/edit`,body:c},{idempotent:false,maxAttempts:1});return m.ok?_(void 0):m},async removeFact(a,d){let c=r(a,te)?u(d):null;if(c===null)return re();let m=await t.send("records.fact.remove",{method:"POST",path:`${s(a)}/facts/remove`,body:c},{idempotent:false,maxAttempts:1});return m.ok?_(void 0):m},listAuthorizationSignatures:i(()=>l("records.signatures.list",{method:"GET",path:"/widget/v1/records/authorization-signatures"},Nt),"listAuthorizationSignatures")}}i(xl,"createRecordsDepthClient");function re(){return Promise.resolve(f(S("validationFailed",{retryable:false})))}i(re,"invalid");var Te=Object.freeze({width:360,height:120});function No(e,t){return {width:e,height:t,pixels:new Uint8Array(e*t)}}i(No,"blank");function Bo(e,t,r,n){for(let o=-n;o<=n;o+=1)for(let s=-n;s<=n;s+=1){if(s*s+o*o>n*n+n)continue;let l=t+s,u=r+o;l<0||u<0||l>=e.width||u>=e.height||(e.pixels[u*e.width+l]=1);}}i(Bo,"stamp");var Il=16384;function Ol(e,t){let[r,n]=e;if(!Number.isFinite(r)||!Number.isFinite(n))return null;let o=Math.min(2*t.width,Math.max(-t.width,Math.round(r))),s=Math.min(2*t.height,Math.max(-t.height,Math.round(n)));return [o,s]}i(Ol,"padPoint");function Al(e,t,r,n,o){let[s,l]=t,[u,a]=r,d=Math.abs(u-s),c=-Math.abs(a-l),m=s<u?1:-1,h=l<a?1:-1,g=d+c,C=0;for(;C<o&&(Bo(e,s,l,n),C+=1,!(s===u&&l===a));){let P=2*g;P>=c&&(g+=c,s+=m),P<=d&&(g+=d,l+=h);}return C}i(Al,"line");function Fl(e,t=1){let r=No(Te.width,Te.height);for(let n of e){let o=[];for(let l of n){let u=Ol(l,r);u!==null&&o.push(u);}if(o.length===0)continue;if(o.length===1){let[l,u]=o[0];Bo(r,l,u,t);continue}let s=Il;for(let l=1;l<o.length&&s>0;l+=1)s-=Al(r,o[l-1],o[l],t,s);}return r}i(Fl,"rasterizeStrokes");var Ml="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789.,'-",jl="ehhvhhhuhhuhhufgggggfuhhhhhuvgguggvvggugggfggnhhfhhhvhhhv44444v72222ichikokihggggggvhrllhhhhpljhhhehhhhheuhhugggehhhliduhhukihfgge11uv444444hhhhhhehhhhha4hhhllrhhha4ahhhha4444v1248gv00e1fhfgguhhhu00fgggf11fhhhf00ehvgf698s8880fhhf1egguhhhh40c444e20622icggikokic44444e00qllhh00uhhhh00ehhhe0uhhugg0fhhf1100mpggg00fge1u88s889600hhhjd00hhha400hhlla00ha4ah00hhf1e00v248vehjlphe4c4444eeh1248vv2421he26aiv22vgu11he68guhhev124888ehhehheehhf12c00000cc0000c48c480000000v000",Dl="0123456789abcdefghijklmnopqrstuv",Yt=5,Xt=7,Kt=Yt+1;function zl(e,t){let r=Ml.indexOf(e);return r<0?0:Dl.indexOf(jl.charAt(r*Xt+t))}i(zl,"glyphRow");function Ul(e){let t=No(Te.width,Te.height),r=e.trim();if(r.length===0)return t;let n=[...r],o=4;for(;o>1&&(n.length*Kt-1)*o>t.width-8;)o-=1;let s=(n.length*Kt-1)*o,l=Math.max(0,Math.floor((t.width-s)/2)),u=Math.floor((t.height-Xt*o)/2);return n.forEach((a,d)=>{let c=l+d*Kt*o;for(let m=0;m<Xt;m+=1){let h=zl(a,m);for(let g=0;g<Yt;g+=1)if((h>>Yt-1-g&1)!==0)for(let C=0;C<o;C+=1)for(let P=0;P<o;P+=1){let E=c+g*o+P,T=u+m*o+C;E<t.width&&T<t.height&&(t.pixels[T*t.width+E]=1);}}}),t}i(Ul,"rasterizeTypedName");var Zt=class Zt{constructor(){this.bytes=[];this.acc=0;this.count=0;}writeBits(t,r){for(this.acc|=t<<this.count,this.count+=r;this.count>=8;)this.bytes.push(this.acc&255),this.acc>>>=8,this.count-=8;}writeCode(t,r){let n=0;for(let o=0;o<r;o+=1)n=n<<1|t>>o&1;this.writeBits(n,r);}finish(){return this.count>0&&this.bytes.push(this.acc&255),Uint8Array.from(this.bytes)}};i(Zt,"BitWriter");var Qt=Zt;function Jt(e,t){t<144?e.writeCode(48+t,8):t<256?e.writeCode(400+(t-144),9):t<280?e.writeCode(t-256,7):e.writeCode(192+(t-280),8);}i(Jt,"writeLiteral");var $t=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258],zo=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0],Vt=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],Uo=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13];function Ll(e,t,r){let n=$t.length-1;for(;$t[n]>t;)n-=1;Jt(e,257+n),zo[n]>0&&e.writeBits(t-$t[n],zo[n]);let o=Vt.length-1;for(;Vt[o]>r;)o-=1;e.writeCode(o,5),Uo[o]>0&&e.writeBits(r-Vt[o],Uo[o]);}i(Ll,"writeMatch");var Nl=32768,Wt=3,Bl=258,Lo=15,ql=64;function Hl(e){let t=new Qt;t.writeBits(1,1),t.writeBits(1,2);let r=new Int32Array(1<<Lo).fill(-1),n=new Int32Array(e.length).fill(-1),o=i(u=>(e[u]<<10^e[u+1]<<5^e[u+2])&(1<<Lo)-1,"hashAt"),s=i(u=>{if(u+Wt>e.length)return;let a=o(u);n[u]=r[a],r[a]=u;},"insert"),l=0;for(;l<e.length;){let u=0,a=0;if(l+Wt<=e.length){let d=r[o(l)],c=0,m=Math.min(Bl,e.length-l);for(;d>=0&&c<ql&&l-d<=Nl;){let h=0;for(;h<m&&e[d+h]===e[l+h];)h+=1;if(h>u&&(u=h,a=l-d,h===m))break;d=n[d],c+=1;}}if(u>=Wt){Ll(t,u,a);for(let d=0;d<u;d+=1)s(l+d);l+=u;}else Jt(t,e[l]),s(l),l+=1;}return Jt(t,256),t.finish()}i(Hl,"deflate");function Kl(e){let t=1,r=0;for(let n of e)t=(t+n)%65521,r=(r+t)%65521;return (r<<16|t)>>>0}i(Kl,"adler32");var Xe=null;function $l(e){if(Xe===null){Xe=new Uint32Array(256);for(let r=0;r<256;r+=1){let n=r;for(let o=0;o<8;o+=1)n=n&1?3988292384^n>>>1:n>>>1;Xe[r]=n>>>0;}}let t=4294967295;for(let r of e)t=Xe[(t^r)&255]^t>>>8;return (t^4294967295)>>>0}i($l,"crc32");function Pe(e){return [e>>>24&255,e>>>16&255,e>>>8&255,e&255]}i(Pe,"u32");function Gt(e,t){let r=Uint8Array.from([...e].map(o=>o.charCodeAt(0))),n=new Uint8Array(r.length+t.length);return n.set(r,0),n.set(t,r.length),[...Pe(t.length),...n,...Pe($l(n))]}i(Gt,"chunk");var Qe="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";function Vl(e){let t="";for(let r=0;r<e.length;r+=3){let n=e[r],o=r+1<e.length?e[r+1]:0,s=r+2<e.length?e[r+2]:0,l=n<<16|o<<8|s;t+=Qe.charAt(l>>18&63)+Qe.charAt(l>>12&63),t+=r+1<e.length?Qe.charAt(l>>6&63):"=",t+=r+2<e.length?Qe.charAt(l&63):"=";}return t}i(Vl,"toBase64");function Wl(e){let{width:t,height:r,pixels:n}=e,o=Math.ceil(t/8)+1,s=new Uint8Array(o*r);for(let c=0;c<r;c+=1){let m=c*o;s[m]=0,s.fill(255,m+1,m+o);for(let h=0;h<t;h+=1)if(n[c*t+h]===1){let g=m+1+(h>>3);s[g]=s[g]&~(128>>(h&7));}}let l=Hl(s),u=new Uint8Array(2+l.length+4);u[0]=120,u[1]=1,u.set(l,2),u.set(Pe(Kl(s)),2+l.length);let a=Uint8Array.from([...Pe(t),...Pe(r),1,0,0,0,0]),d=Uint8Array.from([137,80,78,71,13,10,26,10,...Gt("IHDR",a),...Gt("IDAT",u),...Gt("IEND",new Uint8Array(0))]);return Vl(d)}i(Wl,"encodeSignaturePng");
|
|
13
|
+
export{Jd as ATTACHMENT_ACCEPT,Ds as ATTACHMENT_BACKOFF_MS,ws as ATTACHMENT_INITIATE_PATH,js as ATTACHMENT_MAX_ATTEMPTS,Cs as ATTACHMENT_MIME_TYPES,Ms as ATTACHMENT_QUEUE_CONCURRENCY,cn as CHAT_FEEDBACK_TYPES,ye as CHECKIN_ANSWERABLE_STATUS,Se as FACT_FIELD_BY_KIND,jt as FACT_VALUE_FIELD,fn as FEEDBACK_NOTES_MAX_CHARS,lo as LOGOUT_HOOK_BUDGET_MS,Ss as MAX_ATTACHMENTS_PER_MESSAGE,En as MAX_ATTACHMENT_BYTES,ve as MAX_FILENAME_LENGTH,Be as MAX_IMAGE_KEYS_PER_MESSAGE,pn as MESSAGE_MAX_CHARS,Ma as MIN_POLL_INTERVAL_SECONDS,Jl as NULL_SECURE_STORE,Co as RECORDS_CLINIC_BATCH_MAX,Te as SIGNATURE_CANVAS,Ts as attachmentSize,bn as bootstrapChat,ec as createAttachmentQueue,yn as createChatController,so as createEntitlementPoller,df as createEverfurRuntime,tl as createRecordsClinicBatchClient,xl as createRecordsDepthClient,lr as defaultErrorPolicy,Wl as encodeSignaturePng,sl as factCorrectionFor,il as factValueCorrection,Zd as formatBytes,Io as inferFactValueKind,As as initiateAttachmentUpload,ks as isAttachmentMime,cs as isCheckinSettled,ol as isFactReviewerLocked,Do as mapDocumentContributions,Mo as mapRecordDepth,Dt as mapRecordMarkers,Lt as mapRecordPdfLink,zt as mapRecordShareLink,Ut as mapRecordShareList,jo as mapRecordsTimeline,Nt as mapSignatureSuggestions,Ie as noopTelemetry,yu as optionalModule,Fl as rasterizeStrokes,Ul as rasterizeTypedName,Ao as resolveShareUrl,Ps as sanitizeFilename,ur as unavailableCamera,Fs as uploadAttachmentBytes,xs as validateAttachment};
|