@indiegems/gem-web-sdk 13.0.0 → 13.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +4 -3
  3. package/dist/function.d.ts +2 -1
  4. package/dist/game.d.ts +37 -2
  5. package/dist/gem-web-sdk.bridge.js +1 -1
  6. package/dist/gem-web-sdk.esm.js +2 -2
  7. package/dist/gem-web-sdk.function.js +2 -2
  8. package/dist/gem-web-sdk.game.js +2 -2
  9. package/dist/gem-web-sdk.min.js +2 -2
  10. package/dist/gem-web-sdk.sdk.js +2 -2
  11. package/dist/gem-web-sdk.server-api.js +1 -1
  12. package/dist/gem-web-sdk.server.js +2 -2
  13. package/dist/index.d.ts +39 -5
  14. package/dist/sdk.d.ts +37 -2
  15. package/dist/server-api.d.ts +1 -0
  16. package/dist/server.d.ts +1 -0
  17. package/docs/analytics.md +6 -3
  18. package/docs/api/api-reference-function.md +38 -7
  19. package/docs/api/api-reference-game.md +381 -33
  20. package/docs/api/api-reference-server.md +23 -2
  21. package/docs/api/reference.json +401 -25
  22. package/docs/arcade-avatars.md +194 -26
  23. package/docs/brand-art.md +3 -3
  24. package/docs/changelog.md +30 -0
  25. package/docs/deprecation-policy.md +6 -0
  26. package/docs/getting-started.md +9 -5
  27. package/docs/inventory-and-catalogs.md +1 -1
  28. package/docs/manifest.json +29 -29
  29. package/docs/platform-moments.md +266 -0
  30. package/docs/rewarded-ads.md +26 -9
  31. package/docs/server-bundles.md +2 -2
  32. package/docs/serverless-functions-js.md +17 -1
  33. package/docs/serverless-functions.md +13 -7
  34. package/docs/what-a-game-must-do.md +126 -70
  35. package/package.json +6 -2
  36. package/rigs/adult_human.glb +0 -0
  37. package/schema/bridge.v1.json +160 -7
  38. package/schema/capabilities.public.json +16 -0
  39. package/schema/moment-log-line.json +109 -0
  40. package/docs/cross-promotion.md +0 -232
package/dist/sdk.d.ts CHANGED
@@ -87,6 +87,7 @@ interface RequestOptions {
87
87
  readonly keepalive?: boolean;
88
88
  readonly ifMatch?: string;
89
89
  readonly replaySafe?: boolean;
90
+ readonly retryRateLimited?: boolean;
90
91
  }
91
92
  interface VersionedGetOptions {
92
93
  readonly signal?: AbortSignal;
@@ -1177,7 +1178,7 @@ interface PlayerBadge$1 {
1177
1178
  readonly itemId: string;
1178
1179
  readonly iconUrl: string;
1179
1180
  }
1180
- type Avatar3dFamily = "small_human" | (string & {});
1181
+ type Avatar3dFamily = "small_human" | "adult_human" | (string & {});
1181
1182
  interface WornAvatar3d$1 {
1182
1183
  readonly family: Avatar3dFamily;
1183
1184
  readonly id: string;
@@ -2264,6 +2265,12 @@ interface GemAdResult {
2264
2265
  readonly requestId: string;
2265
2266
  readonly outcome: "shown" | "no_ad" | "unavailable";
2266
2267
  }
2268
+ interface GemMomentResult {
2269
+ readonly gem: typeof PROTOCOL;
2270
+ readonly type: "gem.momentResult";
2271
+ readonly requestId: string;
2272
+ readonly shown: boolean;
2273
+ }
2267
2274
  interface GemSignInResult {
2268
2275
  readonly gem: typeof PROTOCOL;
2269
2276
  readonly type: "gem.signInResult";
@@ -4460,6 +4467,7 @@ interface RewardCue {
4460
4467
  y: number;
4461
4468
  };
4462
4469
  }
4470
+ type GemCorner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
4463
4471
  type FrameState = "waiting" | "connected" | "refused" | "closed";
4464
4472
  interface FramePlayer extends PlayerIdentity {
4465
4473
  readonly displayName: PlayerText;
@@ -4499,6 +4507,7 @@ interface FrameCallbacks {
4499
4507
  onDeviceSettings?(msg: GemDeviceSettings): void;
4500
4508
  onDeviceSettingsResult?(msg: GemDeviceSettingsResult): void;
4501
4509
  onAdResult?(msg: GemAdResult): void;
4510
+ onMomentResult?(msg: GemMomentResult): void;
4502
4511
  onSignInResult?(msg: GemSignInResult): void;
4503
4512
  onFriendChallengeResult?(msg: GemFriendChallengeResult): void;
4504
4513
  onError?(code: GemErrorCode, message?: string): void;
@@ -4554,6 +4563,7 @@ declare class GemFrame {
4554
4563
  readonly id: string;
4555
4564
  readonly label: string;
4556
4565
  }>): boolean;
4566
+ setGemCorner(corner: GemCorner): boolean;
4557
4567
  requestShare(params: ReadonlyArray<{
4558
4568
  readonly key: string;
4559
4569
  readonly value: string;
@@ -4572,6 +4582,8 @@ declare class GemFrame {
4572
4582
  requestAvatar3dPurchase(requestId: string, itemId: string, currencySlug: string): boolean;
4573
4583
  putDeviceSettings(requestId: string, settings: Readonly<Record<string, unknown>>): boolean;
4574
4584
  requestAd(requestId: string, placement: string, format: "interstitial" | "rewarded"): boolean;
4585
+ signalMoment(requestId: string, kind: string, placement?: string): boolean;
4586
+ readyCalled(): boolean;
4575
4587
  requestSignIn(requestId: string): boolean;
4576
4588
  requestFriendChallenge(requestId: string, playerId: string, template: string, params?: Readonly<Record<string, string | number>>): boolean;
4577
4589
  close(): void;
@@ -4580,6 +4592,7 @@ declare class GemFrame {
4580
4592
  private dropUnknownType;
4581
4593
  private refuse;
4582
4594
  private fail;
4595
+ private gated;
4583
4596
  private send;
4584
4597
  private receive;
4585
4598
  private dispatchInbound;
@@ -4648,6 +4661,17 @@ interface AdsApi {
4648
4661
  requestAd(req: AdRequest): Promise<AdOutcome>;
4649
4662
  rewardedStatus(placement: string): Promise<RewardedStatus>;
4650
4663
  }
4664
+ type MomentKind = "level_end" | "run_end" | "match_end" | "menu_return" | "other_break";
4665
+ interface MomentSignal {
4666
+ kind: MomentKind;
4667
+ placement?: string;
4668
+ }
4669
+ interface MomentResult {
4670
+ readonly shown: boolean;
4671
+ }
4672
+ interface MomentsApi {
4673
+ signal(moment: MomentSignal): Promise<MomentResult>;
4674
+ }
4651
4675
  type DeviceSettings = Readonly<Record<string, unknown>>;
4652
4676
  type DeviceSettingsPutOutcome = "stored" | "too_large" | "unavailable";
4653
4677
  interface DeviceSettingsApi {
@@ -4658,6 +4682,15 @@ interface DeviceSettingsApi {
4658
4682
  declare class GemUnframedError extends Error {
4659
4683
  constructor();
4660
4684
  }
4685
+ interface AvatarRigNode {
4686
+ readonly node: string;
4687
+ readonly parent: string | null;
4688
+ }
4689
+ interface AvatarRigs {
4690
+ readonly small_human: readonly AvatarRigNode[];
4691
+ readonly adult_human: readonly AvatarRigNode[];
4692
+ }
4693
+ declare const AVATAR_RIGS: AvatarRigs;
4661
4694
  declare const DEVICE_SETTINGS_MAX_BYTES = 16384;
4662
4695
  declare const ARCADE_EMBEDDERS: readonly string[];
4663
4696
  interface GemOptions {
@@ -4773,6 +4806,7 @@ interface Gem {
4773
4806
  readonly gameConfig: GameConfigApi;
4774
4807
  readonly purchases: PurchaseApi;
4775
4808
  readonly deviceSettings: DeviceSettingsApi;
4809
+ readonly moments: MomentsApi;
4776
4810
  readonly ads: AdsApi;
4777
4811
  readonly account: AccountApi;
4778
4812
  readonly share: ShareApi;
@@ -4802,6 +4836,7 @@ interface Gem {
4802
4836
  cueReward(cue: RewardCue): boolean;
4803
4837
  setWalletVisible(visible: boolean, options?: WalletVisibleOptions): boolean;
4804
4838
  setMenu(menu: GameMenu): boolean;
4839
+ setGemCorner(corner: GemCorner): boolean;
4805
4840
  exit(reason?: string): Promise<void>;
4806
4841
  readonly boot: BootTimeline;
4807
4842
  readonly frame: GemFrame;
@@ -4827,4 +4862,4 @@ interface ExitAnalytics {
4827
4862
  }
4828
4863
  declare function leaveAndExit(rooms: ExitRooms, bridge: ExitBridge | null, reason?: string, analytics?: ExitAnalytics): Promise<void>;
4829
4864
  declare function createGem(options?: GemOptions): Gem;
4830
- export { ARCADE_EMBEDDERS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection$1 as AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, type Avatar3dOffer, type Avatar3dPrice, type Avatar3dPurchaseRequest, type Avatars3dApi, type Base64String, type BootMark, type BootTimeline, type BroadcastOptions, type BytesResponse, CONDITIONAL_HEADERS, type Challenge, type ChallengeWindow, ChallengesApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type ControlsApi, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType$1 as EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameApi, type GameConfig, type GameMenu, type GameMenuItem, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemDevTools, type GemErrorReason, GemFrame, GemFunctionError, type GemGraphicsQuality, type GemIdentity, type GemInsets, type GemLook, type GemLookBase, type GemLookDelta, type GemLookOptions, type GemLookSpeed, type GemMatchApi, type GemMatchServer, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServer, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerIdentity, type GemServerLifecycle, type GemServerOptions, type GemServerProfile, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type HostTokenSource, type HostTokenSourceOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchBackfillState, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchPlayerReport, type MatchPlayerReportResult, type MatchServeOptions, type MatchTransport, type MessageMeta, type MultiTransportSession, PLATFORM_EVENTS, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge$1 as PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry$1 as ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RequestOptions, type RewardCue, type RewardedStatus, type RoomArgValue, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerApi, type ServerBundleHost, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TokenGrant, type Transport, type TransportAdvert, type TransportKind, TransportRefusal, type TransportRequest, type TransportResponse, UNRELIABLE_CHANNEL_LABEL, type VersionedGetOptions, type VersionedResponse, type VibrationApi, type WalletVisibleOptions, type WornAvatar3d$1 as WornAvatar3d, asPlayerText, createBootTimeline, createGem, createGemServer, createHostTokenSource, createMatchServer, defineServer, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, systemClock, text, toBase64, webTransportAvailable };
4865
+ export { ARCADE_EMBEDDERS, AVATAR_RIGS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection$1 as AnalyticsRejection, type AnalyticsValue, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, type Avatar3dOffer, type Avatar3dPrice, type Avatar3dPurchaseRequest, type AvatarRigNode, type AvatarRigs, type Avatars3dApi, type Base64String, type BootMark, type BootTimeline, type BroadcastOptions, type BytesResponse, CONDITIONAL_HEADERS, type Challenge, type ChallengeWindow, ChallengesApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type ControlsApi, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType$1 as EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameApi, type GameConfig, type GameMenu, type GameMenuItem, type GameServerLink, type Gem, GemApiError, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemCorner, type GemDevTools, type GemErrorReason, GemFrame, GemFunctionError, type GemGraphicsQuality, type GemIdentity, type GemInsets, type GemLook, type GemLookBase, type GemLookDelta, type GemLookOptions, type GemLookSpeed, type GemMatchApi, type GemMatchServer, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServer, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerIdentity, type GemServerLifecycle, type GemServerOptions, type GemServerProfile, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type HostTokenSource, type HostTokenSourceOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchBackfillState, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchPlayerReport, type MatchPlayerReportResult, type MatchServeOptions, type MatchTransport, type MessageMeta, type MomentKind, type MomentResult, type MomentSignal, type MomentsApi, type MultiTransportSession, PLATFORM_EVENTS, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge$1 as PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, PlayerText, type ProfileCallOptions, type ProfileShowcaseEntry$1 as ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RequestOptions, type RewardCue, type RewardedStatus, type RoomArgValue, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerApi, type ServerBundleHost, type ServerTokenGrant, type SessionEndReason, type ShareApi, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SnapshotCurrency, type SnapshotItem, type TokenGrant, type Transport, type TransportAdvert, type TransportKind, TransportRefusal, type TransportRequest, type TransportResponse, UNRELIABLE_CHANNEL_LABEL, type VersionedGetOptions, type VersionedResponse, type VibrationApi, type WalletVisibleOptions, type WornAvatar3d$1 as WornAvatar3d, asPlayerText, createBootTimeline, createGem, createGemServer, createHostTokenSource, createMatchServer, defineServer, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, systemClock, text, toBase64, webTransportAvailable };
@@ -40,6 +40,7 @@ interface RequestOptions {
40
40
  readonly keepalive?: boolean;
41
41
  readonly ifMatch?: string;
42
42
  readonly replaySafe?: boolean;
43
+ readonly retryRateLimited?: boolean;
43
44
  }
44
45
  interface VersionedGetOptions {
45
46
  readonly signal?: AbortSignal;
package/dist/server.d.ts CHANGED
@@ -69,6 +69,7 @@ interface RequestOptions {
69
69
  readonly keepalive?: boolean;
70
70
  readonly ifMatch?: string;
71
71
  readonly replaySafe?: boolean;
72
+ readonly retryRateLimited?: boolean;
72
73
  }
73
74
  interface VersionedGetOptions {
74
75
  readonly signal?: AbortSignal;
package/docs/analytics.md CHANGED
@@ -11,9 +11,9 @@ you design around them:
11
11
  - **Nothing is recorded that you did not declare.** There is no free-text property. Every event,
12
12
  every dimension and every value a dimension may take is published in your game config ahead of
13
13
  time, and anything else is refused per event rather than stored.
14
- - **Detail older than 30 days is gone.** Raw events live 30 days. The daily counters built from
14
+ - **Detail older than 60 days is gone.** Raw events live 60 days. The daily counters built from
15
15
  them live 400. A question you can only answer by reading individual events is a question you can
16
- only ask about the last month.
16
+ only ask about the last two months.
17
17
 
18
18
  What you record here is **yours**. It feeds your own reporting and nothing the platform treats as
19
19
  authoritative — see [section 8](#8-what-analytics-is-not) before you attach a reward to it.
@@ -253,7 +253,10 @@ Two results are not refusals and should not be treated as one:
253
253
  being counted twice.
254
254
 
255
255
  A rate limit or a temporarily unreachable backend **keeps the queue** and rejects the `flush`
256
- promise, so the next send carries the same events. A refusal that would fail identically forever
256
+ promise, so the next send carries the same events. The SDK's own sends then wait for the longer
257
+ of the platform's `Retry-After` and a cooldown that starts at 10 seconds and doubles with each
258
+ refusal in a row, up to five minutes; the send on the way out of the page goes regardless. Only one
259
+ `flush` is on the wire at a time. A refusal that would fail identically forever
257
260
  discards its batch instead, because a queue that can never empty fills up and starts dropping the
258
261
  events that would explain the problem.
259
262
 
@@ -1,6 +1,6 @@
1
1
  # The function surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/function` v13.0.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/function` v13.2.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
4
4
 
5
5
  `@indiegems/gem-web-sdk/function` exports exactly the symbols on this page and nothing else.
6
6
 
@@ -8,6 +8,8 @@ Generated from `@indiegems/gem-web-sdk/function` v13.0.0, the version of the pac
8
8
  import { createGem } from '@indiegems/gem-web-sdk/function';
9
9
  ```
10
10
 
11
+ ⚠️ **JavaScript functions are disabled for now, due to performance issues.** Uploading a new JavaScript function is refused with `400 js_functions_disabled`: write a new function in Rust, as [serverless-functions](../serverless-functions.md#3-writing-one) shows. A JavaScript function already published keeps running, and this page is what it imports.
12
+
11
13
  A function imports the same package your game already depends on, written out in [getting-started](../getting-started.md#3-add-the-sdk) — the only place the install is written out. Your function’s build bundles this module, so the version your function runs is the one your `package.json` names: pin the version your game pins. A function published importing the SDK from the engine runs the engine’s built-in copy instead; [serverless-functions-js](../serverless-functions-js.md) says what that means.
12
14
 
13
15
  <a id="analyticsvalue"></a>
@@ -243,7 +245,7 @@ is what says which events exist, which dimensions each has and which values
243
245
  each dimension may take. An undeclared name or key is not stored — it comes
244
246
  back as a rejection, which the SDK prints to the console during development.
245
247
 
246
- ⚠️ **Detail older than 30 days is gone.** Raw events live 30 days; the daily
248
+ ⚠️ **Detail older than 60 days is gone.** Raw events live 60 days; the daily
247
249
  counters live 400. Anything you want to be able to ask about a year from now
248
250
  has to be a declared dimension today.
249
251
 
@@ -355,9 +357,14 @@ the page.
355
357
  A refusal that could clear on its own — a 429 from the rate limiter, a 503
356
358
  while the platform's idempotency store is unreachable — KEEPS the queue
357
359
  and rejects, so the next flush sends the same events rather than losing
358
- them. A refusal that cannot clear discards the batch it was sent for,
360
+ them. The SDK's own flushes then hold off for the longer of the server's
361
+ `Retry-After` and a cooldown that doubles from 10 seconds, up to five
362
+ minutes. A refusal that cannot clear discards the batch it was sent for,
359
363
  because resending it can only fail identically.
360
364
 
365
+ One flush at a time: called while another is still on the wire, this
366
+ resolves at once with nothing sent, and what is queued goes out after it.
367
+
361
368
  | Parameter | Type |
362
369
  | --- | --- |
363
370
  | `options` | `AnalyticsFlushOptions` |
@@ -666,6 +673,22 @@ It buys the same budget a read gets — see [ClientOptions.maxRetries](#clientop
666
673
  final: only the failures [GemApiError.retryable](#gemapierror-retryable) describes, and a
667
674
  connection that died with no answer, are attempted again.
668
675
 
676
+ <a id="requestoptions-retryratelimited"></a>
677
+
678
+ ## RequestOptions.retryRateLimited
679
+
680
+ ```ts
681
+ readonly retryRateLimited?: boolean
682
+ ```
683
+
684
+ Set `false` to make a 429 final for this call instead of waiting out
685
+ `Retry-After` and trying again.
686
+
687
+ For a caller that keeps its own queue and its own cooldown, such as a
688
+ batch sender on a timer: retrying inside the call only spends more of the
689
+ same limit, and holds the caller's queue while it does. Every other
690
+ failure is retried exactly as before. Defaults to `true`.
691
+
669
692
  <a id="versionedgetoptions"></a>
670
693
 
671
694
  ## VersionedGetOptions
@@ -4884,13 +4907,21 @@ putting it in an `<img src>`.
4884
4907
  ## Avatar3dFamily
4885
4908
 
4886
4909
  ```ts
4887
- type Avatar3dFamily = "small_human" | string & object
4910
+ type Avatar3dFamily = "small_human" | "adult_human" | string & object
4888
4911
  ```
4889
4912
 
4890
4913
  A rig family — the skeleton contract a 3D avatar is built on, and what a
4891
- game declares it can animate. `small_human` is the first: a `root` node
4892
- with a `body` child, which holds `head`, `arm_l`, `arm_r`, `leg_l` and
4893
- `leg_r`, and a `hand_socket` under `arm_r`.
4914
+ game declares it can animate. Two today:
4915
+
4916
+ - `small_human`, the toy rig: a `root` node with a `body` child, which holds
4917
+ `head`, `arm_l`, `arm_r`, `leg_l` and `leg_r`, and a `hand_socket` under
4918
+ `arm_r`.
4919
+ - `adult_human`, a full humanoid with fingers: 56 nodes from `root` and
4920
+ `hips` down to `toes_r`, every one world-aligned at rest, so one clip plays
4921
+ on every avatar in the family.
4922
+
4923
+ `AVATAR_RIGS` (from `@indiegems/gem-web-sdk/sdk`) lists every node of
4924
+ both, with its parent.
4894
4925
 
4895
4926
  Open-ended (`| (string & {})`) so a family the platform adds later does not
4896
4927
  break a `switch` you compiled against this version: keep a `default` arm and