realtime-avatar 0.7.2 → 0.7.3
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/dist/{chunk-ARILC2U3.js → chunk-2V333KRZ.js} +1 -1
- package/dist/{chunk-MQQKAUOB.js → chunk-OMOEUVO5.js} +1 -1
- package/dist/express.js +2 -2
- package/dist/hono.js +2 -2
- package/dist/index.js +1 -1
- package/dist/nextjs.js +2 -2
- package/dist/react-native.js +139 -2
- package/dist/react.js +139 -2
- package/dist/server.js +1 -1
- package/dist/tanstack-start.js +2 -2
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { RealtimeAvatar, isQueued, RealtimeAvatarHttpError } from './chunk-
|
|
1
|
+
import { RealtimeAvatar, isQueued, RealtimeAvatarHttpError } from './chunk-2V333KRZ.js';
|
|
2
2
|
|
|
3
3
|
// ../proxy/src/config.ts
|
|
4
4
|
var json = (body, status = 200) => new Response(JSON.stringify(body), {
|
package/dist/express.js
CHANGED
package/dist/hono.js
CHANGED
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, isQueued, verifyTranscript } from './chunk-
|
|
1
|
+
export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, isQueued, verifyTranscript } from './chunk-2V333KRZ.js';
|
package/dist/nextjs.js
CHANGED
package/dist/react-native.js
CHANGED
|
@@ -131,6 +131,43 @@ function timeoutSetter(fn, ms) {
|
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
// ../client/src/errors.ts
|
|
134
|
+
var RealtimeAvatarApiError = class _RealtimeAvatarApiError extends Error {
|
|
135
|
+
constructor(message, status, body, response, metadata = {}) {
|
|
136
|
+
super(message);
|
|
137
|
+
this.status = status;
|
|
138
|
+
this.body = body;
|
|
139
|
+
this.response = response;
|
|
140
|
+
this.name = "RealtimeAvatarApiError";
|
|
141
|
+
this.code = metadata.code;
|
|
142
|
+
this.retryable = metadata.retryable;
|
|
143
|
+
this.billingUrl = metadata.billingUrl;
|
|
144
|
+
this.rawMessage = metadata.rawMessage ?? null;
|
|
145
|
+
}
|
|
146
|
+
status;
|
|
147
|
+
body;
|
|
148
|
+
response;
|
|
149
|
+
code;
|
|
150
|
+
retryable;
|
|
151
|
+
billingUrl;
|
|
152
|
+
/** Debug detail returned by the API. Do not render directly in user-facing UI. */
|
|
153
|
+
rawMessage;
|
|
154
|
+
get isBillingRequired() {
|
|
155
|
+
return this.status === 402 || this.code === "insufficient_credits" || this.code === "spend_limit_exceeded";
|
|
156
|
+
}
|
|
157
|
+
static async fromResponse(response) {
|
|
158
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
159
|
+
const body = contentType.includes("application/json") ? await response.clone().json().catch(() => null) : await response.clone().text().catch(() => "");
|
|
160
|
+
const rawMessage = (extractErrorMessage(body) ?? response.statusText) || null;
|
|
161
|
+
const metadata = extractErrorMetadata(body, response.status, rawMessage);
|
|
162
|
+
return new _RealtimeAvatarApiError(
|
|
163
|
+
metadata.message,
|
|
164
|
+
response.status,
|
|
165
|
+
body,
|
|
166
|
+
response,
|
|
167
|
+
metadata
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
134
171
|
var RealtimeAvatarCapacityError = class extends Error {
|
|
135
172
|
constructor(message, busy) {
|
|
136
173
|
super(message);
|
|
@@ -151,6 +188,107 @@ var RealtimeAvatarCapacityError = class extends Error {
|
|
|
151
188
|
return this.busy.recommended_retry_ms;
|
|
152
189
|
}
|
|
153
190
|
};
|
|
191
|
+
function extractErrorMessage(body) {
|
|
192
|
+
if (!body || typeof body !== "object") return typeof body === "string" && body ? body : null;
|
|
193
|
+
const record = body;
|
|
194
|
+
const detail = readMessageValue(record.detail);
|
|
195
|
+
if (detail) return detail;
|
|
196
|
+
const error = readMessageValue(record.error);
|
|
197
|
+
if (error) return error;
|
|
198
|
+
const message = readMessageValue(record.message);
|
|
199
|
+
if (message) return message;
|
|
200
|
+
return null;
|
|
201
|
+
}
|
|
202
|
+
function normalizeRealtimeAvatarError(input) {
|
|
203
|
+
const status = input.status ?? 0;
|
|
204
|
+
const rawCode = input.code?.trim() || null;
|
|
205
|
+
const rawMessage = input.message?.trim() || "";
|
|
206
|
+
const blob = `${rawCode ?? ""} ${rawMessage}`.toLowerCase();
|
|
207
|
+
if (rawCode === "insufficient_credits" || rawCode === "spend_limit_exceeded" || status === 402) {
|
|
208
|
+
return {
|
|
209
|
+
code: rawCode ?? "billing_required",
|
|
210
|
+
message: rawMessage && !hasInternalDetail(rawMessage) ? rawMessage : "Add credits to continue using realtime avatars.",
|
|
211
|
+
retryable: false
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
if (status === 401) {
|
|
215
|
+
return { code: "unauthorized", message: "Authentication is required to use Realtime Avatar.", retryable: false };
|
|
216
|
+
}
|
|
217
|
+
if (status === 403) {
|
|
218
|
+
return { code: "forbidden", message: "This API key does not have access to that action.", retryable: false };
|
|
219
|
+
}
|
|
220
|
+
if (status === 404 || blob.includes("unknown avatar_id") || blob.includes("avatar not found")) {
|
|
221
|
+
return { code: "not_found", message: "We could not find that avatar or resource.", retryable: false };
|
|
222
|
+
}
|
|
223
|
+
if (status === 409) {
|
|
224
|
+
return { code: "conflict", message: "That request is already in progress. Try again in a moment.", retryable: true };
|
|
225
|
+
}
|
|
226
|
+
if (status === 429) {
|
|
227
|
+
return { code: "rate_limited", message: "Too many realtime requests. Please slow down and retry.", retryable: true };
|
|
228
|
+
}
|
|
229
|
+
if (isWarmingMessage(blob)) {
|
|
230
|
+
return { code: "service_unavailable", message: "Realtime Avatar is warming up. Try again in a moment.", retryable: true };
|
|
231
|
+
}
|
|
232
|
+
if (status === 400 || status === 422) {
|
|
233
|
+
return { code: "invalid_request", message: userSafeMessage(rawMessage) ?? "Check the request and try again.", retryable: false };
|
|
234
|
+
}
|
|
235
|
+
if (status >= 500) {
|
|
236
|
+
return { code: "service_unavailable", message: "Realtime Avatar is temporarily unavailable. Try again in a moment.", retryable: true };
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
code: isPublicErrorCode(rawCode) ? rawCode : "request_failed",
|
|
240
|
+
message: userSafeMessage(rawMessage) ?? "Realtime Avatar request failed. Try again.",
|
|
241
|
+
retryable: status === 0 || status >= 500
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function extractErrorMetadata(body, status, rawMessage) {
|
|
245
|
+
if (!body || typeof body !== "object") {
|
|
246
|
+
const normalized2 = normalizeRealtimeAvatarError({ status, message: rawMessage });
|
|
247
|
+
return { ...normalized2, rawMessage };
|
|
248
|
+
}
|
|
249
|
+
const record = body;
|
|
250
|
+
const code = typeof record.code === "string" ? record.code : null;
|
|
251
|
+
const normalized = normalizeRealtimeAvatarError({ status, code, message: rawMessage });
|
|
252
|
+
return {
|
|
253
|
+
code: normalized.code,
|
|
254
|
+
retryable: typeof record.retryable === "boolean" ? record.retryable : normalized.retryable,
|
|
255
|
+
...typeof record.billingUrl === "string" ? { billingUrl: record.billingUrl } : {},
|
|
256
|
+
rawMessage,
|
|
257
|
+
message: normalized.message
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
var PUBLIC_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
261
|
+
"billing_required",
|
|
262
|
+
"invalid_request",
|
|
263
|
+
"unauthorized",
|
|
264
|
+
"forbidden",
|
|
265
|
+
"not_found",
|
|
266
|
+
"conflict",
|
|
267
|
+
"rate_limited",
|
|
268
|
+
"service_unavailable",
|
|
269
|
+
"request_failed",
|
|
270
|
+
"network_error"
|
|
271
|
+
]);
|
|
272
|
+
function isPublicErrorCode(code) {
|
|
273
|
+
return Boolean(code && PUBLIC_ERROR_CODES.has(code));
|
|
274
|
+
}
|
|
275
|
+
function readMessageValue(value) {
|
|
276
|
+
if (typeof value === "string") return value.trim() || null;
|
|
277
|
+
if (!value || typeof value !== "object") return null;
|
|
278
|
+
const record = value;
|
|
279
|
+
return readMessageValue(record.message) ?? readMessageValue(record.error) ?? readMessageValue(record.detail);
|
|
280
|
+
}
|
|
281
|
+
function userSafeMessage(message) {
|
|
282
|
+
if (!message || hasInternalDetail(message)) return null;
|
|
283
|
+
return message.length > 180 ? `${message.slice(0, 177)}...` : message;
|
|
284
|
+
}
|
|
285
|
+
function isWarmingMessage(blob) {
|
|
286
|
+
return blob.includes("warming") || blob.includes("not ready") || blob.includes("starting up");
|
|
287
|
+
}
|
|
288
|
+
var MACHINE_SHAPED = /[_=<>{}\[\]|\\$`]|\w+\.\w+\.\w|\S:\d|\w\(\)|^\s*(?:at|File)\b/mu;
|
|
289
|
+
function hasInternalDetail(message) {
|
|
290
|
+
return MACHINE_SHAPED.test(message);
|
|
291
|
+
}
|
|
154
292
|
function splitCallTranscript(all, localIdentity) {
|
|
155
293
|
if (!localIdentity) return { user: [], agent: all };
|
|
156
294
|
const user = [];
|
|
@@ -2390,8 +2528,7 @@ function createProxyClient(options) {
|
|
|
2390
2528
|
return { status: "busy", busy };
|
|
2391
2529
|
}
|
|
2392
2530
|
if (!response.ok) {
|
|
2393
|
-
|
|
2394
|
-
throw new Error(`realtime-avatar: proxy refused the call (${response.status}) ${detail}`.trim());
|
|
2531
|
+
throw await RealtimeAvatarApiError.fromResponse(response);
|
|
2395
2532
|
}
|
|
2396
2533
|
return { status: "ready", grant: await response.json() };
|
|
2397
2534
|
},
|
package/dist/react.js
CHANGED
|
@@ -90,6 +90,43 @@ function timeoutSetter(fn, ms) {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
// ../client/src/errors.ts
|
|
93
|
+
var RealtimeAvatarApiError = class _RealtimeAvatarApiError extends Error {
|
|
94
|
+
constructor(message, status, body, response, metadata = {}) {
|
|
95
|
+
super(message);
|
|
96
|
+
this.status = status;
|
|
97
|
+
this.body = body;
|
|
98
|
+
this.response = response;
|
|
99
|
+
this.name = "RealtimeAvatarApiError";
|
|
100
|
+
this.code = metadata.code;
|
|
101
|
+
this.retryable = metadata.retryable;
|
|
102
|
+
this.billingUrl = metadata.billingUrl;
|
|
103
|
+
this.rawMessage = metadata.rawMessage ?? null;
|
|
104
|
+
}
|
|
105
|
+
status;
|
|
106
|
+
body;
|
|
107
|
+
response;
|
|
108
|
+
code;
|
|
109
|
+
retryable;
|
|
110
|
+
billingUrl;
|
|
111
|
+
/** Debug detail returned by the API. Do not render directly in user-facing UI. */
|
|
112
|
+
rawMessage;
|
|
113
|
+
get isBillingRequired() {
|
|
114
|
+
return this.status === 402 || this.code === "insufficient_credits" || this.code === "spend_limit_exceeded";
|
|
115
|
+
}
|
|
116
|
+
static async fromResponse(response) {
|
|
117
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
118
|
+
const body = contentType.includes("application/json") ? await response.clone().json().catch(() => null) : await response.clone().text().catch(() => "");
|
|
119
|
+
const rawMessage = (extractErrorMessage(body) ?? response.statusText) || null;
|
|
120
|
+
const metadata = extractErrorMetadata(body, response.status, rawMessage);
|
|
121
|
+
return new _RealtimeAvatarApiError(
|
|
122
|
+
metadata.message,
|
|
123
|
+
response.status,
|
|
124
|
+
body,
|
|
125
|
+
response,
|
|
126
|
+
metadata
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
93
130
|
var RealtimeAvatarCapacityError = class extends Error {
|
|
94
131
|
constructor(message, busy) {
|
|
95
132
|
super(message);
|
|
@@ -110,6 +147,107 @@ var RealtimeAvatarCapacityError = class extends Error {
|
|
|
110
147
|
return this.busy.recommended_retry_ms;
|
|
111
148
|
}
|
|
112
149
|
};
|
|
150
|
+
function extractErrorMessage(body) {
|
|
151
|
+
if (!body || typeof body !== "object") return typeof body === "string" && body ? body : null;
|
|
152
|
+
const record = body;
|
|
153
|
+
const detail = readMessageValue(record.detail);
|
|
154
|
+
if (detail) return detail;
|
|
155
|
+
const error = readMessageValue(record.error);
|
|
156
|
+
if (error) return error;
|
|
157
|
+
const message = readMessageValue(record.message);
|
|
158
|
+
if (message) return message;
|
|
159
|
+
return null;
|
|
160
|
+
}
|
|
161
|
+
function normalizeRealtimeAvatarError(input) {
|
|
162
|
+
const status = input.status ?? 0;
|
|
163
|
+
const rawCode = input.code?.trim() || null;
|
|
164
|
+
const rawMessage = input.message?.trim() || "";
|
|
165
|
+
const blob = `${rawCode ?? ""} ${rawMessage}`.toLowerCase();
|
|
166
|
+
if (rawCode === "insufficient_credits" || rawCode === "spend_limit_exceeded" || status === 402) {
|
|
167
|
+
return {
|
|
168
|
+
code: rawCode ?? "billing_required",
|
|
169
|
+
message: rawMessage && !hasInternalDetail(rawMessage) ? rawMessage : "Add credits to continue using realtime avatars.",
|
|
170
|
+
retryable: false
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
if (status === 401) {
|
|
174
|
+
return { code: "unauthorized", message: "Authentication is required to use Realtime Avatar.", retryable: false };
|
|
175
|
+
}
|
|
176
|
+
if (status === 403) {
|
|
177
|
+
return { code: "forbidden", message: "This API key does not have access to that action.", retryable: false };
|
|
178
|
+
}
|
|
179
|
+
if (status === 404 || blob.includes("unknown avatar_id") || blob.includes("avatar not found")) {
|
|
180
|
+
return { code: "not_found", message: "We could not find that avatar or resource.", retryable: false };
|
|
181
|
+
}
|
|
182
|
+
if (status === 409) {
|
|
183
|
+
return { code: "conflict", message: "That request is already in progress. Try again in a moment.", retryable: true };
|
|
184
|
+
}
|
|
185
|
+
if (status === 429) {
|
|
186
|
+
return { code: "rate_limited", message: "Too many realtime requests. Please slow down and retry.", retryable: true };
|
|
187
|
+
}
|
|
188
|
+
if (isWarmingMessage(blob)) {
|
|
189
|
+
return { code: "service_unavailable", message: "Realtime Avatar is warming up. Try again in a moment.", retryable: true };
|
|
190
|
+
}
|
|
191
|
+
if (status === 400 || status === 422) {
|
|
192
|
+
return { code: "invalid_request", message: userSafeMessage(rawMessage) ?? "Check the request and try again.", retryable: false };
|
|
193
|
+
}
|
|
194
|
+
if (status >= 500) {
|
|
195
|
+
return { code: "service_unavailable", message: "Realtime Avatar is temporarily unavailable. Try again in a moment.", retryable: true };
|
|
196
|
+
}
|
|
197
|
+
return {
|
|
198
|
+
code: isPublicErrorCode(rawCode) ? rawCode : "request_failed",
|
|
199
|
+
message: userSafeMessage(rawMessage) ?? "Realtime Avatar request failed. Try again.",
|
|
200
|
+
retryable: status === 0 || status >= 500
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
function extractErrorMetadata(body, status, rawMessage) {
|
|
204
|
+
if (!body || typeof body !== "object") {
|
|
205
|
+
const normalized2 = normalizeRealtimeAvatarError({ status, message: rawMessage });
|
|
206
|
+
return { ...normalized2, rawMessage };
|
|
207
|
+
}
|
|
208
|
+
const record = body;
|
|
209
|
+
const code = typeof record.code === "string" ? record.code : null;
|
|
210
|
+
const normalized = normalizeRealtimeAvatarError({ status, code, message: rawMessage });
|
|
211
|
+
return {
|
|
212
|
+
code: normalized.code,
|
|
213
|
+
retryable: typeof record.retryable === "boolean" ? record.retryable : normalized.retryable,
|
|
214
|
+
...typeof record.billingUrl === "string" ? { billingUrl: record.billingUrl } : {},
|
|
215
|
+
rawMessage,
|
|
216
|
+
message: normalized.message
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
var PUBLIC_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
220
|
+
"billing_required",
|
|
221
|
+
"invalid_request",
|
|
222
|
+
"unauthorized",
|
|
223
|
+
"forbidden",
|
|
224
|
+
"not_found",
|
|
225
|
+
"conflict",
|
|
226
|
+
"rate_limited",
|
|
227
|
+
"service_unavailable",
|
|
228
|
+
"request_failed",
|
|
229
|
+
"network_error"
|
|
230
|
+
]);
|
|
231
|
+
function isPublicErrorCode(code) {
|
|
232
|
+
return Boolean(code && PUBLIC_ERROR_CODES.has(code));
|
|
233
|
+
}
|
|
234
|
+
function readMessageValue(value) {
|
|
235
|
+
if (typeof value === "string") return value.trim() || null;
|
|
236
|
+
if (!value || typeof value !== "object") return null;
|
|
237
|
+
const record = value;
|
|
238
|
+
return readMessageValue(record.message) ?? readMessageValue(record.error) ?? readMessageValue(record.detail);
|
|
239
|
+
}
|
|
240
|
+
function userSafeMessage(message) {
|
|
241
|
+
if (!message || hasInternalDetail(message)) return null;
|
|
242
|
+
return message.length > 180 ? `${message.slice(0, 177)}...` : message;
|
|
243
|
+
}
|
|
244
|
+
function isWarmingMessage(blob) {
|
|
245
|
+
return blob.includes("warming") || blob.includes("not ready") || blob.includes("starting up");
|
|
246
|
+
}
|
|
247
|
+
var MACHINE_SHAPED = /[_=<>{}\[\]|\\$`]|\w+\.\w+\.\w|\S:\d|\w\(\)|^\s*(?:at|File)\b/mu;
|
|
248
|
+
function hasInternalDetail(message) {
|
|
249
|
+
return MACHINE_SHAPED.test(message);
|
|
250
|
+
}
|
|
113
251
|
function splitCallTranscript(all, localIdentity) {
|
|
114
252
|
if (!localIdentity) return { user: [], agent: all };
|
|
115
253
|
const user = [];
|
|
@@ -2695,8 +2833,7 @@ function createProxyClient(options) {
|
|
|
2695
2833
|
return { status: "busy", busy };
|
|
2696
2834
|
}
|
|
2697
2835
|
if (!response.ok) {
|
|
2698
|
-
|
|
2699
|
-
throw new Error(`realtime-avatar: proxy refused the call (${response.status}) ${detail}`.trim());
|
|
2836
|
+
throw await RealtimeAvatarApiError.fromResponse(response);
|
|
2700
2837
|
}
|
|
2701
2838
|
return { status: "ready", grant: await response.json() };
|
|
2702
2839
|
},
|
package/dist/server.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, isQueued, verifyTranscript } from './chunk-
|
|
1
|
+
export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, isQueued, verifyTranscript } from './chunk-2V333KRZ.js';
|
package/dist/tanstack-start.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "realtime-avatar",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.3",
|
|
4
4
|
"description": "Realtime Avatar SDK. `realtime-avatar` and the route adapters hold your API key and are server-only; `realtime-avatar/react`, `/browser` and `/tools` never can — importing a server entry into a browser build throws at bundle time.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "The Influence Company",
|