realtime-avatar 0.11.4 → 0.12.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.
@@ -1,4 +1,4 @@
1
- import { RealtimeAvatar, isQueued, RealtimeAvatarHttpError } from './chunk-UMFUVCWT.js';
1
+ import { RealtimeAvatar, isQueued, RealtimeAvatarHttpError } from './chunk-ZFYNUHKB.js';
2
2
 
3
3
  // ../proxy/src/config.ts
4
4
  var json = (body, status = 200) => new Response(JSON.stringify(body), {
@@ -61,6 +61,21 @@ function createProxyHandler(config) {
61
61
  minted.set(call.sessionId, now);
62
62
  return json(call.raw);
63
63
  } catch (error) {
64
+ if (error instanceof RealtimeAvatarHttpError && error.status === 429) {
65
+ const concurrency = error.code === "concurrency_limit_reached";
66
+ const counts = error.concurrency;
67
+ const message = concurrency ? counts?.maxConcurrentSessions !== void 0 && counts.activeSessions !== void 0 && counts.connectingSessions !== void 0 && counts.pendingSessions !== void 0 ? `Session limit reached (${counts.maxConcurrentSessions} allowed): ${counts.activeSessions} active, ${counts.connectingSessions} connecting, ${counts.pendingSessions} starting. End a session or wait for pending starts to clear, then retry.` : "The concurrent session limit is reached. Active and starting sessions count. End a session or wait for pending starts to clear, then retry." : "Too many requests. Wait before retrying.";
68
+ const response = json({
69
+ error: message,
70
+ code: concurrency ? "concurrency_limit_reached" : "rate_limited",
71
+ status: 429,
72
+ retryable: true,
73
+ ...concurrency ? counts : {},
74
+ ...error.requestId ? { requestId: error.requestId } : {}
75
+ }, 429);
76
+ if (error.requestId) response.headers.set("X-Request-ID", error.requestId);
77
+ return response;
78
+ }
64
79
  if (error instanceof RealtimeAvatarHttpError && error.isBilling) {
65
80
  return json({ code: error.code ?? "insufficient_credits" }, 402);
66
81
  }
@@ -11,12 +11,32 @@ var RealtimeAvatarHttpError = class extends RealtimeAvatarError {
11
11
  status;
12
12
  code;
13
13
  body;
14
- constructor(status, code, body) {
15
- super(`Realtime Avatar API ${status}${code ? ` (${code})` : ""}: ${body || "no body"}`);
14
+ requestId;
15
+ concurrency;
16
+ constructor(status, code, body, requestId) {
17
+ const bounded = body.slice(0, 400);
18
+ super(`Realtime Avatar API ${status}${code ? ` (${code})` : ""}: ${bounded || "no body"}`);
16
19
  this.name = "RealtimeAvatarHttpError";
17
20
  this.status = status;
18
21
  this.code = code;
19
- this.body = body;
22
+ this.body = bounded;
23
+ let parsed = {};
24
+ try {
25
+ const value = JSON.parse(body);
26
+ if (value && typeof value === "object" && !Array.isArray(value)) parsed = value;
27
+ } catch {
28
+ }
29
+ const validId = (value) => typeof value === "string" && /^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(value);
30
+ this.requestId = validId(parsed.requestId) ? parsed.requestId : validId(requestId) ? requestId : void 0;
31
+ if (status === 429 && code === "concurrency_limit_reached") {
32
+ this.concurrency = {};
33
+ for (const key of ["maxConcurrentSessions", "liveSessions", "activeSessions", "connectingSessions", "pendingSessions"]) {
34
+ const value = parsed[key];
35
+ if (typeof value === "number" && Number.isSafeInteger(value) && value >= (key === "maxConcurrentSessions" ? 1 : 0)) {
36
+ this.concurrency[key] = value;
37
+ }
38
+ }
39
+ }
20
40
  }
21
41
  /** Out of credits, or over this key's spend limit. Surface a paywall, not an error. */
22
42
  get isBilling() {
@@ -26,12 +46,12 @@ var RealtimeAvatarHttpError = class extends RealtimeAvatarError {
26
46
  var motionIdSchema = z.string().regex(/^[A-Za-z0-9_-]{1,64}$/).refine((value) => !["__proto__", "constructor", "prototype"].includes(value), "Reserved identifier");
27
47
  function motionRecord(valueSchema) {
28
48
  const record = z.record(motionIdSchema, valueSchema);
29
- return z.transform((value, ctx) => {
49
+ return z.preprocess((value, ctx) => {
30
50
  if (value !== null && typeof value === "object" && Object.hasOwn(value, "__proto__")) {
31
51
  ctx.addIssue({ code: "custom", path: ["__proto__"], message: "Reserved identifier" });
32
52
  }
33
53
  return value;
34
- }).pipe(record);
54
+ }, record);
35
55
  }
36
56
  var clipSourceSchema = z.union([
37
57
  z.strictObject({ assetId: z.string().trim().min(1).max(160) }),
@@ -134,9 +154,7 @@ var schema13 = z.strictObject({
134
154
  "verdict": schema11,
135
155
  "issues": schema12,
136
156
  "firstFrameUrl": schema4,
137
- "lastFrameUrl": schema4,
138
- "trimStartMs": schema8,
139
- "trimEndMs": schema8
157
+ "lastFrameUrl": schema4
140
158
  });
141
159
  var schema14 = z.union([schema13, schema3]);
142
160
  var schema15 = z.strictObject({
@@ -218,7 +236,7 @@ function isTransient(cause) {
218
236
 
219
237
  // ../http-client/src/client.ts
220
238
  var DEFAULT_BASE_URL = "https://realtimeavatar.ai/api/v1";
221
- var SDK_VERSION = "0.11.4";
239
+ var SDK_VERSION = "0.12.0";
222
240
  var RealtimeAvatar = class {
223
241
  #apiKey;
224
242
  #baseUrl;
@@ -270,14 +288,16 @@ var RealtimeAvatar = class {
270
288
  if (options.video !== void 0) Object.assign(body, videoToWire(options.video));
271
289
  const response = await this.#request("POST", "/realtime/livekit/session", { json: body });
272
290
  if (response.status === 429) {
273
- const busy = await response.json();
274
- return {
275
- queued: true,
276
- position: typeof busy.queue_position === "number" ? busy.queue_position : null,
277
- size: typeof busy.queue_size === "number" ? busy.queue_size : 0,
278
- retryAfterMs: typeof busy.recommended_retry_ms === "number" ? busy.recommended_retry_ms : 3e3,
279
- queueTicketId: typeof busy.queue_ticket_id === "string" ? busy.queue_ticket_id : null
280
- };
291
+ const busy = await response.clone().json().catch(() => null);
292
+ if (isRecord(busy) && !("code" in busy) && typeof busy.queue_size === "number" && Number.isFinite(busy.queue_size) && busy.queue_size >= 0 && typeof busy.recommended_retry_ms === "number" && Number.isFinite(busy.recommended_retry_ms) && busy.recommended_retry_ms >= 0) {
293
+ return {
294
+ queued: true,
295
+ position: typeof busy.queue_position === "number" ? busy.queue_position : null,
296
+ size: busy.queue_size,
297
+ retryAfterMs: busy.recommended_retry_ms,
298
+ queueTicketId: typeof busy.queue_ticket_id === "string" ? busy.queue_ticket_id : null
299
+ };
300
+ }
281
301
  }
282
302
  const grant = await this.#json(response);
283
303
  return {
@@ -657,7 +677,7 @@ var RealtimeAvatar = class {
657
677
  code = JSON.parse(text).code;
658
678
  } catch {
659
679
  }
660
- throw new RealtimeAvatarHttpError(response.status, code, text.slice(0, 400));
680
+ throw new RealtimeAvatarHttpError(response.status, code, text, response.headers.get("x-request-id") ?? void 0);
661
681
  }
662
682
  };
663
683
  function toUsageSessionPage(raw) {
package/dist/express.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as ProxyConfig } from './types-9a0bRdXl.js';
2
- import './types-nxdohaiH.js';
1
+ import { P as ProxyConfig } from './types-CJcTowDB.js';
2
+ import './types-B9GTrpx0.js';
3
3
 
4
4
  type Expressish = {
5
5
  method: string;
package/dist/express.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createProxyHandler } from './chunk-WUUXNNDP.js';
2
- import './chunk-UMFUVCWT.js';
1
+ import { createProxyHandler } from './chunk-FQWEKJCX.js';
2
+ import './chunk-ZFYNUHKB.js';
3
3
 
4
4
  // ../proxy/src/express.ts
5
5
  function realtimeAvatarExpress(config) {
package/dist/hono.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as ProxyConfig } from './types-9a0bRdXl.js';
2
- import './types-nxdohaiH.js';
1
+ import { P as ProxyConfig } from './types-CJcTowDB.js';
2
+ import './types-B9GTrpx0.js';
3
3
 
4
4
  /**
5
5
  * Hono (and anything else built on Fetch handlers — Workers, Bun, Deno).
package/dist/hono.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createProxyHandler } from './chunk-WUUXNNDP.js';
2
- import './chunk-UMFUVCWT.js';
1
+ import { createProxyHandler } from './chunk-FQWEKJCX.js';
2
+ import './chunk-ZFYNUHKB.js';
3
3
 
4
4
  // ../proxy/src/hono.ts
5
5
  function realtimeAvatarHono(config) {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as CallPolicy, C as CallMode, S as StartCallResult, E as EndCallOptions, A as Avatar, b as AvatarUpdate, c as AvatarSourceSwap, d as ClipLibraryDeclaration, e as ClipLibraryUpdate, L as LoopRedirect, f as ClipLibrary, g as AssetKind, h as Asset, i as ListSessionsOptions, U as UsageSessionPage, j as UsageSession, k as CreditBalance, T as TranscriptPayload } from './types-nxdohaiH.js';
2
- export { l as AvatarClip, m as CallConnection, n as CallQueued, o as ClipDeclaration, p as ClipLibraryPlan, q as ClipSource, r as ContextMessage, s as EndCallReason, V as VideoPolicy, t as isQueued } from './types-nxdohaiH.js';
1
+ import { a as CallPolicy, C as CallMode, S as StartCallResult, E as EndCallOptions, A as Avatar, b as AvatarUpdate, c as AvatarSourceSwap, d as ClipLibraryDeclaration, e as ClipLibraryUpdate, L as LoopRedirect, f as ClipLibrary, g as AssetKind, h as Asset, i as ListSessionsOptions, U as UsageSessionPage, j as UsageSession, k as CreditBalance, T as TranscriptPayload } from './types-B9GTrpx0.js';
2
+ export { l as AvatarClip, m as CallConnection, n as CallQueued, o as ClipDeclaration, p as ClipLibraryPlan, q as ClipSource, r as ContextMessage, s as EndCallReason, V as VideoPolicy, t as isQueued } from './types-B9GTrpx0.js';
3
3
  import { z } from 'zod';
4
4
 
5
5
  interface RealtimeAvatarOptions {
@@ -294,6 +294,7 @@ declare class RealtimeAvatarError extends Error {
294
294
  * | `loop_pending` · `anchor_pending` | 409 | one is already in flight — wait, then retry |
295
295
  * | `revision_conflict` | 409 | someone declared first. Re-read `listClips`, re-decide, re-declare |
296
296
  * | `clip_render_limit` | 429 | a true rate limit; nothing was applied. Retry later |
297
+ * | `concurrency_limit_reached` | 429 | active and starting sessions occupy the limit; release one or wait for pending starts before retrying |
297
298
  * | `clip_screen_unavailable` | 503 | the prose screen could not run. Retry |
298
299
  *
299
300
  * Pose validation does NOT appear here: a rejected upload is not an error response at all.
@@ -308,7 +309,9 @@ declare class RealtimeAvatarHttpError extends RealtimeAvatarError {
308
309
  readonly status: number;
309
310
  readonly code: string | undefined;
310
311
  readonly body: string;
311
- constructor(status: number, code: string | undefined, body: string);
312
+ readonly requestId?: string;
313
+ readonly concurrency?: Partial<Record<"maxConcurrentSessions" | "liveSessions" | "activeSessions" | "connectingSessions" | "pendingSessions", number>>;
314
+ constructor(status: number, code: string | undefined, body: string, requestId?: string);
312
315
  /** Out of credits, or over this key's spend limit. Surface a paywall, not an error. */
313
316
  get isBilling(): boolean;
314
317
  }
@@ -338,32 +341,12 @@ declare const clipLibraryDeclarationSchema: z.ZodObject<{
338
341
  clips: z.ZodArray<z.ZodString>;
339
342
  }, z.core.$strict>>;
340
343
  }, z.core.$strict>>;
341
- actions: z.ZodOptional<z.ZodPipe<z.ZodTransform<Record<string, {
342
- description: string;
343
- clips: string[];
344
- }>, Record<string, {
345
- description: string;
346
- clips: string[];
347
- }>>, z.ZodRecord<z.ZodString, z.ZodObject<{
344
+ actions: z.ZodOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
348
345
  description: z.ZodString;
349
346
  clips: z.ZodArray<z.ZodString>;
350
347
  }, z.core.$strict>>>>;
351
348
  expectedRevision: z.ZodInt;
352
- clips: z.ZodNonOptional<z.ZodPipe<z.ZodTransform<Record<string, {
353
- source: {
354
- assetId: string;
355
- } | {
356
- motionPrompt: string;
357
- durationSeconds?: number | undefined;
358
- };
359
- }>, Record<string, {
360
- source: {
361
- assetId: string;
362
- } | {
363
- motionPrompt: string;
364
- durationSeconds?: number | undefined;
365
- };
366
- }>>, z.ZodRecord<z.ZodString, z.ZodObject<{
349
+ clips: z.ZodNonOptional<z.ZodPreprocess<z.ZodRecord<z.ZodString, z.ZodObject<{
367
350
  source: z.ZodUnion<readonly [z.ZodObject<{
368
351
  assetId: z.ZodString;
369
352
  }, z.core.$strict>, z.ZodObject<{
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, verifyTranscript } from './chunk-UMFUVCWT.js';
1
+ export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, verifyTranscript } from './chunk-ZFYNUHKB.js';
package/dist/nextjs.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as ProxyConfig } from './types-9a0bRdXl.js';
2
- import './types-nxdohaiH.js';
1
+ import { P as ProxyConfig } from './types-CJcTowDB.js';
2
+ import './types-B9GTrpx0.js';
3
3
 
4
4
  /**
5
5
  * App Router. Mount at `app/api/realtime-avatar/[...path]/route.ts`:
package/dist/nextjs.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createProxyHandler } from './chunk-WUUXNNDP.js';
2
- import './chunk-UMFUVCWT.js';
1
+ import { createProxyHandler } from './chunk-FQWEKJCX.js';
2
+ import './chunk-ZFYNUHKB.js';
3
3
 
4
4
  // ../proxy/src/nextjs.ts
5
5
  function createRealtimeAvatarRoute(config) {
@@ -241,6 +241,13 @@ function normalizeRealtimeAvatarError(input) {
241
241
  if (status === 409) {
242
242
  return { code: "conflict", message: "That request is already in progress. Try again in a moment.", retryable: true };
243
243
  }
244
+ if (status === 429 && rawCode === "concurrency_limit_reached") {
245
+ return {
246
+ code: rawCode,
247
+ message: userSafeMessage(rawMessage) ?? "The concurrent session limit is reached. Active and starting sessions count. End a session or wait for pending starts to clear, then retry.",
248
+ retryable: true
249
+ };
250
+ }
244
251
  if (status === 429) {
245
252
  return { code: "rate_limited", message: "Too many realtime requests. Please slow down and retry.", retryable: true };
246
253
  }
@@ -723,8 +730,28 @@ var DEFAULT_GOVERNOR_CONFIG = {
723
730
  downgradeFreezeMs: 150,
724
731
  probationFreezeMs: 100,
725
732
  openingDwellMs: 2e3,
726
- dwellBaseMs: 8e3,
727
- dwellMaxMs: 12e4,
733
+ // HOW LONG THE PICTURE STAYS SOFT AFTER A DEMOTE. Swept against this reducer, 300 s per
734
+ // run, five link profiles, scored as switches / percent of time on the top rung / worst
735
+ // single spell on the low cap:
736
+ //
737
+ // profile 8s x 2^n max 120s flat 3s 3s x 2^n max 12s
738
+ // a spurious blip, link fine 2 / 94% / 19s 2 / 98% / 6s 2 / 97% / 9s
739
+ // ordinary jitter, /30s 20 / 61% / 19s 20 / 80% / 6s 20 / 79% / 9s
740
+ // flaky, /10s 9 / 7% / 123s 59 / 40% / 6s 31 / 25% / 15s
741
+ // genuinely bad, 600ms /5s 9 / 4% / 123s 59 / 20% / 8s 31 / 11% / 18s
742
+ //
743
+ // Two things that table says. First, the old `dwellMaxMs` of 120 s was the real damage:
744
+ // a link that is merely flaky could sit soft for TWO MINUTES, which is far worse than
745
+ // the churn the backoff exists to prevent. Second, removing the backoff entirely (flat
746
+ // 3 s) buys the last few points of quality at 59 switches instead of 31, and a switch is
747
+ // a decoder reconfigure plus a keyframe wait, measured at about 1.3 s of dead air on a
748
+ // weak link. So the shape is kept and only the numbers move: start lower, cap far lower.
749
+ //
750
+ // This depends on not charging a layer switch to the link (see the size-change reset in
751
+ // avatar-video-surface). Probing more often is only safe once a failed probe cannot
752
+ // trigger the next demotion by itself.
753
+ dwellBaseMs: 3e3,
754
+ dwellMaxMs: 12e3,
728
755
  cleanMs: 3e3,
729
756
  probeMs: 1e4,
730
757
  healthyResetMs: 12e4
@@ -2575,8 +2602,13 @@ function createProxyClient(options) {
2575
2602
  requestOptions
2576
2603
  );
2577
2604
  if (response.status === 429) {
2578
- const busy = await response.json().catch(() => ({}));
2579
- return { status: "busy", busy };
2605
+ const value = await response.clone().json().catch(() => null);
2606
+ if (value && typeof value === "object" && !Array.isArray(value)) {
2607
+ const busy = value;
2608
+ const valid = (n) => typeof n === "number" && Number.isFinite(n) && n >= 0;
2609
+ const queue2 = busy.queued === true && valid(busy.size) && valid(busy.retryAfterMs) || valid(busy.queue_size) && valid(busy.recommended_retry_ms);
2610
+ if (!("code" in busy) && queue2) return { status: "busy", busy };
2611
+ }
2580
2612
  }
2581
2613
  if (!response.ok) {
2582
2614
  throw await RealtimeAvatarApiError.fromResponse(response);
package/dist/react.js CHANGED
@@ -394,6 +394,13 @@ function normalizeRealtimeAvatarError(input) {
394
394
  if (status === 409) {
395
395
  return { code: "conflict", message: "That request is already in progress. Try again in a moment.", retryable: true };
396
396
  }
397
+ if (status === 429 && rawCode === "concurrency_limit_reached") {
398
+ return {
399
+ code: rawCode,
400
+ message: userSafeMessage(rawMessage) ?? "The concurrent session limit is reached. Active and starting sessions count. End a session or wait for pending starts to clear, then retry.",
401
+ retryable: true
402
+ };
403
+ }
397
404
  if (status === 429) {
398
405
  return { code: "rate_limited", message: "Too many realtime requests. Please slow down and retry.", retryable: true };
399
406
  }
@@ -924,8 +931,28 @@ var DEFAULT_GOVERNOR_CONFIG = {
924
931
  downgradeFreezeMs: 150,
925
932
  probationFreezeMs: 100,
926
933
  openingDwellMs: 2e3,
927
- dwellBaseMs: 8e3,
928
- dwellMaxMs: 12e4,
934
+ // HOW LONG THE PICTURE STAYS SOFT AFTER A DEMOTE. Swept against this reducer, 300 s per
935
+ // run, five link profiles, scored as switches / percent of time on the top rung / worst
936
+ // single spell on the low cap:
937
+ //
938
+ // profile 8s x 2^n max 120s flat 3s 3s x 2^n max 12s
939
+ // a spurious blip, link fine 2 / 94% / 19s 2 / 98% / 6s 2 / 97% / 9s
940
+ // ordinary jitter, /30s 20 / 61% / 19s 20 / 80% / 6s 20 / 79% / 9s
941
+ // flaky, /10s 9 / 7% / 123s 59 / 40% / 6s 31 / 25% / 15s
942
+ // genuinely bad, 600ms /5s 9 / 4% / 123s 59 / 20% / 8s 31 / 11% / 18s
943
+ //
944
+ // Two things that table says. First, the old `dwellMaxMs` of 120 s was the real damage:
945
+ // a link that is merely flaky could sit soft for TWO MINUTES, which is far worse than
946
+ // the churn the backoff exists to prevent. Second, removing the backoff entirely (flat
947
+ // 3 s) buys the last few points of quality at 59 switches instead of 31, and a switch is
948
+ // a decoder reconfigure plus a keyframe wait, measured at about 1.3 s of dead air on a
949
+ // weak link. So the shape is kept and only the numbers move: start lower, cap far lower.
950
+ //
951
+ // This depends on not charging a layer switch to the link (see the size-change reset in
952
+ // avatar-video-surface). Probing more often is only safe once a failed probe cannot
953
+ // trigger the next demotion by itself.
954
+ dwellBaseMs: 3e3,
955
+ dwellMaxMs: 12e3,
929
956
  cleanMs: 3e3,
930
957
  probeMs: 1e4,
931
958
  healthyResetMs: 12e4
@@ -3194,8 +3221,13 @@ function createProxyClient(options) {
3194
3221
  requestOptions
3195
3222
  );
3196
3223
  if (response.status === 429) {
3197
- const busy = await response.json().catch(() => ({}));
3198
- return { status: "busy", busy };
3224
+ const value = await response.clone().json().catch(() => null);
3225
+ if (value && typeof value === "object" && !Array.isArray(value)) {
3226
+ const busy = value;
3227
+ const valid = (n) => typeof n === "number" && Number.isFinite(n) && n >= 0;
3228
+ const queue2 = busy.queued === true && valid(busy.size) && valid(busy.retryAfterMs) || valid(busy.queue_size) && valid(busy.recommended_retry_ms);
3229
+ if (!("code" in busy) && queue2) return { status: "busy", busy };
3230
+ }
3199
3231
  }
3200
3232
  if (!response.ok) {
3201
3233
  throw await RealtimeAvatarApiError.fromResponse(response);
package/dist/server.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, RealtimeAvatarOptions, StartCallOptions, clipLibraryDeclarationSchema, verifyTranscript } from './index.js';
2
- export { h as Asset, g as AssetKind, A as Avatar, l as AvatarClip, c as AvatarSourceSwap, b as AvatarUpdate, m as CallConnection, C as CallMode, a as CallPolicy, n as CallQueued, o as ClipDeclaration, f as ClipLibrary, d as ClipLibraryDeclaration, p as ClipLibraryPlan, e as ClipLibraryUpdate, q as ClipSource, r as ContextMessage, k as CreditBalance, E as EndCallOptions, s as EndCallReason, i as ListSessionsOptions, L as LoopRedirect, S as StartCallResult, T as TranscriptPayload, j as UsageSession, U as UsageSessionPage, V as VideoPolicy, t as isQueued } from './types-nxdohaiH.js';
2
+ export { h as Asset, g as AssetKind, A as Avatar, l as AvatarClip, c as AvatarSourceSwap, b as AvatarUpdate, m as CallConnection, C as CallMode, a as CallPolicy, n as CallQueued, o as ClipDeclaration, f as ClipLibrary, d as ClipLibraryDeclaration, p as ClipLibraryPlan, e as ClipLibraryUpdate, q as ClipSource, r as ContextMessage, k as CreditBalance, E as EndCallOptions, s as EndCallReason, i as ListSessionsOptions, L as LoopRedirect, S as StartCallResult, T as TranscriptPayload, j as UsageSession, U as UsageSessionPage, V as VideoPolicy, t as isQueued } from './types-B9GTrpx0.js';
3
3
  import 'zod';
package/dist/server.js CHANGED
@@ -1 +1 @@
1
- export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, verifyTranscript } from './chunk-UMFUVCWT.js';
1
+ export { RealtimeAvatar, RealtimeAvatarError, RealtimeAvatarHttpError, clipLibraryDeclarationSchema, isQueued, verifyTranscript } from './chunk-ZFYNUHKB.js';
@@ -1,5 +1,5 @@
1
- import { P as ProxyConfig } from './types-9a0bRdXl.js';
2
- import './types-nxdohaiH.js';
1
+ import { P as ProxyConfig } from './types-CJcTowDB.js';
2
+ import './types-B9GTrpx0.js';
3
3
 
4
4
  /**
5
5
  * TanStack Start. Mount at `routes/api/realtime-avatar/$.ts` — the trailing `$` is Start's
@@ -1,5 +1,5 @@
1
- import { createProxyHandler } from './chunk-WUUXNNDP.js';
2
- import './chunk-UMFUVCWT.js';
1
+ import { createProxyHandler } from './chunk-FQWEKJCX.js';
2
+ import './chunk-ZFYNUHKB.js';
3
3
 
4
4
  // src/tanstack-start.ts
5
5
  function realtimeAvatarServerRoute(config) {
@@ -343,10 +343,10 @@ interface components {
343
343
  CreateApiKeyRequest: {
344
344
  name: string;
345
345
  /**
346
- * @default test
346
+ * @description Deprecated. Accepted for older clients but ignored; all new keys use the same tic_ format.
347
347
  * @enum {string}
348
348
  */
349
- environment: "live" | "test";
349
+ environment?: "live" | "test";
350
350
  /**
351
351
  * @default [
352
352
  * "realtime:write",
@@ -363,15 +363,16 @@ interface components {
363
363
  keyId: string;
364
364
  tenantId: string;
365
365
  name: string;
366
- /** @enum {string} */
367
- environment: "live" | "test";
368
366
  redactedKey: string;
367
+ /** @default false */
368
+ canReveal: boolean;
369
369
  scopes: ("*" | "api_keys:write" | "credits:read" | "avatars:read" | "avatars:write" | "realtime:write" | "usage:read" | "usage:write")[];
370
370
  /** @enum {string} */
371
371
  status: "active" | "revoked" | "expired";
372
372
  spendLimitCreditMicros: number | null;
373
373
  createdAt: string;
374
374
  expiresAt: string | null;
375
+ /** Format: starts_with */
375
376
  apiKey: string;
376
377
  };
377
378
  Asset: {
@@ -482,8 +483,6 @@ interface components {
482
483
  issues: string[];
483
484
  firstFrameUrl: string | null;
484
485
  lastFrameUrl: string | null;
485
- trimStartMs: number | null;
486
- trimEndMs: number | null;
487
486
  } | null;
488
487
  error: {
489
488
  code: string;
@@ -522,6 +521,13 @@ interface components {
522
521
  };
523
522
  };
524
523
  };
524
+ ReviewAvatarClipRequest: {
525
+ clipId: string;
526
+ uploadAssetId: string;
527
+ expectedRevision: number;
528
+ expectedAnchorVersion: number;
529
+ reason: string;
530
+ };
525
531
  PutAvatarClipsRequest: {
526
532
  expectedRevision: number;
527
533
  clips: {
@@ -573,8 +579,6 @@ interface components {
573
579
  issues: string[];
574
580
  firstFrameUrl: string | null;
575
581
  lastFrameUrl: string | null;
576
- trimStartMs: number | null;
577
- trimEndMs: number | null;
578
582
  } | null;
579
583
  error: {
580
584
  code: string;
@@ -659,6 +663,16 @@ interface components {
659
663
  grantedScopes?: ("*" | "api_keys:write" | "credits:read" | "avatars:read" | "avatars:write" | "realtime:write" | "usage:read" | "usage:write")[];
660
664
  /** @description Present on 402 — where to send the user to top up. */
661
665
  billingUrl?: string;
666
+ /** @description On concurrency_limit_reached: the workspace's concurrent session limit. */
667
+ maxConcurrentSessions?: number;
668
+ /** @description Legacy concurrency count: occupied reservations, including active, connecting and starting sessions. Not the number of active conversations. */
669
+ liveSessions?: number;
670
+ /** @description On concurrency_limit_reached: counted reservations with started media, observed at refusal. */
671
+ activeSessions?: number;
672
+ /** @description On concurrency_limit_reached: counted reservations with an attached session that has not started media. */
673
+ connectingSessions?: number;
674
+ /** @description On concurrency_limit_reached: counted in-flight starts with no attached session yet. */
675
+ pendingSessions?: number;
662
676
  } & {
663
677
  [key: string]: unknown;
664
678
  };
@@ -1,4 +1,4 @@
1
- import { C as CallMode, a as CallPolicy } from './types-nxdohaiH.js';
1
+ import { C as CallMode, a as CallPolicy } from './types-B9GTrpx0.js';
2
2
 
3
3
  /** The three things a caller can ask the proxy to do. Gate on these, not on URLs. */
4
4
  type ProxyOperation = "connect" | "end" | "avatars" | "credits";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "realtime-avatar",
3
- "version": "0.11.4",
3
+ "version": "0.12.0",
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",