soonspacejs 3.0.0-alpha.10 → 3.0.0-alpha.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "soonspacejs",
3
- "version": "3.0.0-alpha.10",
3
+ "version": "3.0.0-alpha.12",
4
4
  "homepage": "https://www.xwbuilders.com/soonspacejs/",
5
5
  "description": "SoonSpace.js 3.0 alpha",
6
6
  "module": "./dist/index.esm.js",
@@ -0,0 +1,6 @@
1
+ import { Texture } from 'three';
2
+ /** Only fresh pixels decoded by the parsed-model cache enter this registry. */
3
+ export declare function ownDecodedImage(image: ImageBitmap): () => void;
4
+ export declare function assertDecodedTextureAlive(texture: Texture): void;
5
+ /** Capture the current pixels so later texture mutation cannot release another image. */
6
+ export declare function retainDecodedTexture(texture: Texture): () => void;
@@ -1,15 +1,37 @@
1
+ import { ModelCacheDiagnostic } from '../Interface/modelCache';
2
+ interface CacheOptions {
3
+ maxEntryBytes?: number;
4
+ onDiagnostic?: (event: ModelCacheDiagnostic) => void;
5
+ }
6
+ export interface ModelBufferResult {
7
+ buffer: ArrayBuffer;
8
+ /** Hashed request identity; never a URL or credential. */
9
+ cacheKey: string | null;
10
+ cacheable: boolean;
11
+ forbidPersistence: boolean;
12
+ isCurrent: () => boolean;
13
+ }
14
+ type RequestInit = {
15
+ headers: Headers;
16
+ credentials: RequestCredentials;
17
+ signal?: AbortSignal;
18
+ redirect?: RequestRedirect;
19
+ };
1
20
  /** Raw HTTP model bytes only. Runtime leases / GPU graphs are never persisted. */
2
21
  export declare class ModelBufferCache {
3
22
  private readonly store;
4
23
  private readonly enabled;
5
- constructor(store?: LocalForage, enabled?: () => boolean);
6
- load(url: string, init: {
7
- headers: Headers;
8
- credentials: RequestCredentials;
9
- signal?: AbortSignal;
10
- redirect?: RequestRedirect;
11
- }): Promise<ArrayBuffer>;
24
+ private readonly options;
25
+ private warned;
26
+ constructor(store?: LocalForage, enabled?: () => boolean, options?: () => CacheOptions);
27
+ private maximumEntryBytes;
28
+ private withinLimit;
29
+ private diagnose;
30
+ load(url: string, init: RequestInit): Promise<ArrayBuffer>;
31
+ loadWithMetadata(url: string, init: RequestInit): Promise<ModelBufferResult>;
32
+ private loadBytes;
12
33
  private key;
13
34
  private mutate;
14
35
  clear(): Promise<void>;
15
36
  }
37
+ export {};
@@ -0,0 +1,81 @@
1
+ import { ModelBufferResult } from './ModelBufferCache';
2
+ import { ParsedModelSnapshot } from './ParsedModelCodec';
3
+ import { ParsedCacheLimits, ParsedCacheMetadata, ParsedCacheStore } from './ParsedModelStore';
4
+ import { ParsedModelCacheDiagnostic } from '../Interface/modelCache';
5
+ export interface ParsedModelCacheOptions {
6
+ enabled?: boolean;
7
+ maxBytes?: number;
8
+ maxEntryBytes?: number;
9
+ maxEntries?: number;
10
+ onDiagnostic?: (event: ParsedModelCacheDiagnostic) => void;
11
+ }
12
+ export interface ParsedCacheIdentity {
13
+ key: string;
14
+ rootKey: string;
15
+ version: string;
16
+ }
17
+ interface RootState {
18
+ latest: symbol;
19
+ refs: number;
20
+ }
21
+ interface Coordinator {
22
+ epoch: number;
23
+ roots: Map<string, RootState>;
24
+ scopes: Set<ParsedCacheScope>;
25
+ limitsKey?: string;
26
+ pruning?: Promise<unknown>;
27
+ }
28
+ export declare class ParsedCacheScope {
29
+ private coordinator;
30
+ private root;
31
+ private identity;
32
+ private release;
33
+ readonly controller: AbortController;
34
+ readonly token: symbol;
35
+ readonly epoch: number;
36
+ storageEpoch?: number;
37
+ sourceCurrent: () => boolean;
38
+ entry?: ParsedCacheMetadata;
39
+ private finished;
40
+ private parentAbort;
41
+ constructor(coordinator: Coordinator, root: RootState, identity: string, release: () => void, parent?: AbortSignal);
42
+ get signal(): AbortSignal;
43
+ isCurrent(): boolean;
44
+ assertCurrent(): void;
45
+ invalidate(): void;
46
+ finish(): void;
47
+ }
48
+ /** Coordinates live requests; the storage adapter owns atomic byte/count/LRU limits. */
49
+ export declare class ParsedModelCache {
50
+ private options;
51
+ private store;
52
+ private coordinator;
53
+ private scopes;
54
+ private warned;
55
+ private disposed;
56
+ readonly stats: {
57
+ hits: number;
58
+ misses: number;
59
+ writes: number;
60
+ evictions: number;
61
+ errors: number;
62
+ skipped: number;
63
+ bytes: number;
64
+ entries: number;
65
+ };
66
+ constructor(options?: () => ParsedModelCacheOptions, store?: ParsedCacheStore);
67
+ get limits(): ParsedCacheLimits;
68
+ get enabled(): boolean;
69
+ begin(identity: string, parent?: AbortSignal): ParsedCacheScope;
70
+ private diagnostic;
71
+ private enforceLimits;
72
+ identify(scope: ParsedCacheScope, source: ModelBufferResult, profile: string): Promise<ParsedCacheIdentity | null>;
73
+ assertAvailable(scope: ParsedCacheScope, bytes: number): void;
74
+ read(scope: ParsedCacheScope, identity: ParsedCacheIdentity): Promise<ParsedModelSnapshot | null>;
75
+ discard(scope: ParsedCacheScope, identity: ParsedCacheIdentity): Promise<void>;
76
+ write(scope: ParsedCacheScope, identity: ParsedCacheIdentity, snapshot: ParsedModelSnapshot): Promise<void>;
77
+ clear(): Promise<void>;
78
+ dispose(): void;
79
+ }
80
+ export declare const clearParsedModelCache: () => Promise<void>;
81
+ export {};
@@ -0,0 +1,102 @@
1
+ import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js';
2
+ import { RegisteredPart } from '../Entity/ModelResources';
3
+ import * as THREE from 'three';
4
+ declare const arrays: {
5
+ Float32Array: Float32ArrayConstructor;
6
+ Float64Array: Float64ArrayConstructor;
7
+ Uint32Array: Uint32ArrayConstructor;
8
+ Uint16Array: Uint16ArrayConstructor;
9
+ Uint8Array: Uint8ArrayConstructor;
10
+ Uint8ClampedArray: Uint8ClampedArrayConstructor;
11
+ Int32Array: Int32ArrayConstructor;
12
+ Int16Array: Int16ArrayConstructor;
13
+ Int8Array: Int8ArrayConstructor;
14
+ };
15
+ declare const materialTypes: {
16
+ MeshBasicMaterial: typeof THREE.MeshBasicMaterial;
17
+ MeshStandardMaterial: typeof THREE.MeshStandardMaterial;
18
+ MeshPhysicalMaterial: typeof THREE.MeshPhysicalMaterial;
19
+ };
20
+ type MaterialType = keyof typeof materialTypes;
21
+ interface AttributeData {
22
+ buffer: number;
23
+ type: keyof typeof arrays;
24
+ itemSize: number;
25
+ normalized: boolean;
26
+ name: string;
27
+ stride?: number;
28
+ offset?: number;
29
+ interleavedId?: number;
30
+ float16: boolean;
31
+ gpuType?: number;
32
+ usage: number;
33
+ }
34
+ interface GeometryData {
35
+ attributes: Record<string, number>;
36
+ index: number | null;
37
+ groups: {
38
+ start: number;
39
+ count: number;
40
+ materialIndex?: number;
41
+ }[];
42
+ drawRange: {
43
+ start: number;
44
+ count: number;
45
+ };
46
+ box: number[][] | null;
47
+ sphere: [number[], number] | null;
48
+ }
49
+ interface MaterialData {
50
+ type: MaterialType;
51
+ json: Record<string, any>;
52
+ colors: Record<string, number[]>;
53
+ vectors: Record<string, number[]>;
54
+ values: Record<string, number | boolean>;
55
+ }
56
+ interface TextureData {
57
+ json: Record<string, any>;
58
+ matrix: number[];
59
+ matrixAutoUpdate: boolean;
60
+ }
61
+ type PartData = Omit<RegisteredPart, 'geometry' | 'material' | 'matrix'> & {
62
+ geometry: number;
63
+ material: number;
64
+ matrix: number[];
65
+ };
66
+ export interface ParsedModelSnapshot {
67
+ schema: 2;
68
+ three: string;
69
+ bytes: number;
70
+ parts: PartData[];
71
+ buffers: Blob[];
72
+ attributes: AttributeData[];
73
+ geometries: GeometryData[];
74
+ materials: MaterialData[];
75
+ textures: TextureData[];
76
+ images: {
77
+ uuid: string;
78
+ blob: Blob;
79
+ width: number;
80
+ height: number;
81
+ }[];
82
+ bitmapOptions: ImageBitmapOptions;
83
+ }
84
+ export interface ParsedCodecOptions {
85
+ signal?: AbortSignal;
86
+ assertCurrent?: () => void;
87
+ maxBytes?: number;
88
+ decodeImage?: (blob: Blob, options: ImageBitmapOptions, signal: AbortSignal) => Promise<ImageBitmap>;
89
+ }
90
+ export interface HydratedParsedModel {
91
+ parts: RegisteredPart[];
92
+ /** Call only after ModelResources has retained every resource. */
93
+ transfer(): void;
94
+ dispose(): void;
95
+ }
96
+ /** Logical payload size, including a bounded JSON metadata estimate, not physical disk usage. */
97
+ export declare function parsedSnapshotBytes(snapshot: ParsedModelSnapshot): number;
98
+ /** No runtime objects or decoded pixels enter persistent storage. */
99
+ export declare function packParsedModel(gltf: GLTF, parts: readonly RegisteredPart[], options?: ParsedCodecOptions): Promise<ParsedModelSnapshot | null>;
100
+ export declare function validateParsedModel(value: unknown, maximum?: number): asserts value is ParsedModelSnapshot;
101
+ export declare function hydrateParsedModel(snapshot: ParsedModelSnapshot, options?: ParsedCodecOptions): Promise<HydratedParsedModel>;
102
+ export {};
@@ -0,0 +1,58 @@
1
+ import { ParsedModelSnapshot } from './ParsedModelCodec';
2
+ export interface ParsedCacheLimits {
3
+ maxBytes: number;
4
+ maxEntryBytes: number;
5
+ maxEntries: number;
6
+ }
7
+ export interface ParsedCacheMetadata {
8
+ key: string;
9
+ rootKey: string;
10
+ version: string;
11
+ bytes: number;
12
+ lastUsed: number;
13
+ writeId: string;
14
+ }
15
+ export interface ParsedCacheRead {
16
+ epoch: number;
17
+ entry?: {
18
+ metadata: ParsedCacheMetadata;
19
+ snapshot: ParsedModelSnapshot;
20
+ };
21
+ }
22
+ export interface ParsedCacheWrite {
23
+ stored: boolean;
24
+ evicted: number;
25
+ bytes: number;
26
+ entries: number;
27
+ }
28
+ export interface ParsedCacheStore {
29
+ read(key: string, version: string, signal?: AbortSignal): Promise<ParsedCacheRead>;
30
+ write(metadata: ParsedCacheMetadata, snapshot: ParsedModelSnapshot, epoch: number, limits: ParsedCacheLimits, guard: () => boolean, signal?: AbortSignal): Promise<ParsedCacheWrite>;
31
+ remove(key: string, writeId: string, guard: () => boolean): Promise<void>;
32
+ invalidateRoot(rootKey: string, guard: () => boolean): Promise<void>;
33
+ prune(limits: ParsedCacheLimits): Promise<ParsedCacheWrite>;
34
+ touch(metadata: ParsedCacheMetadata): void;
35
+ clear(): Promise<void>;
36
+ onClear(listener: () => void): () => void;
37
+ }
38
+ /** Payload and LRU metadata are committed/evicted in the same native transaction. */
39
+ export declare class IndexedParsedModelStore implements ParsedCacheStore {
40
+ readonly name: string;
41
+ private database?;
42
+ private channel?;
43
+ private listeners;
44
+ private touches;
45
+ private touchTimer?;
46
+ constructor(name?: string);
47
+ private open;
48
+ private transaction;
49
+ read(key: string, version: string, signal?: AbortSignal): Promise<ParsedCacheRead>;
50
+ write(metadata: ParsedCacheMetadata, snapshot: ParsedModelSnapshot, epoch: number, limits: ParsedCacheLimits, guard: () => boolean, signal?: AbortSignal): Promise<ParsedCacheWrite>;
51
+ remove(key: string, writeId: string, guard: () => boolean): Promise<void>;
52
+ invalidateRoot(rootKey: string, guard: () => boolean): Promise<void>;
53
+ prune(limits: ParsedCacheLimits): Promise<ParsedCacheWrite>;
54
+ touch(metadata: ParsedCacheMetadata): void;
55
+ clear(): Promise<void>;
56
+ onClear(listener: () => void): () => void;
57
+ }
58
+ export declare const parsedModelStore: IndexedParsedModelStore;
@@ -0,0 +1,5 @@
1
+ export declare function parsedAbortError(): DOMException;
2
+ export declare function checkParsedSignal(signal?: AbortSignal): void;
3
+ /** Races cancellation without leaving rejection handlers or abort listeners behind. */
4
+ export declare function parsedAbortable<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T>;
5
+ export declare function parsedParallel<T, R>(values: readonly T[], work: (value: T, index: number) => Promise<R>, check: () => void, concurrency?: number): Promise<R[]>;
@@ -1,6 +1,7 @@
1
1
  import { BufferGeometry, Material, Matrix4, Texture } from 'three';
2
2
  import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
3
3
  import { ModelBufferCache } from '../Cache/ModelBufferCache';
4
+ import { ParsedModelCacheOptions } from '../Cache/ParsedModelCache';
4
5
  export interface ModelPart {
5
6
  /** Omitted for triangle meshes. Basic line segments share the Entity lifecycle. */
6
7
  kind?: 'mesh' | 'line-segments';
@@ -29,6 +30,7 @@ interface ResourceRecord<T> {
29
30
  dead: boolean;
30
31
  gpu: Set<BufferGeometry | Material | Texture>;
31
32
  dependencies: Set<ResourceRecord<Material>>;
33
+ imageReleases: Set<() => void>;
32
34
  }
33
35
  export declare class ResourceLease<T> {
34
36
  readonly registry: ModelResources;
@@ -65,8 +67,12 @@ export declare class ModelResources {
65
67
  private urls;
66
68
  private gltfLoader;
67
69
  private bufferCache;
70
+ private parsedCacheOptions;
71
+ private parsedCache;
68
72
  /** Borrow a host-configured loader; its decoder workers remain host-owned. */
69
- setGLTFLoader(loader: GLTFLoader, bufferCache?: ModelBufferCache): void;
73
+ setGLTFLoader(loader: GLTFLoader, bufferCache?: ModelBufferCache, parsedOptions?: () => ParsedModelCacheOptions & {
74
+ profile?: string;
75
+ }): void;
70
76
  readonly materials: {
71
77
  register: (material: Material, options: {
72
78
  ownership: "transfer";
@@ -11,3 +11,4 @@ export * from './sbmCache';
11
11
  export * from './sbmXmlToJson';
12
12
  export * from './gmlToJson';
13
13
  export * from './poiMesh';
14
+ export * from './modelCache';
@@ -0,0 +1,20 @@
1
+ /** Cache diagnostics never contain resource URLs, headers or exception messages. */
2
+ export interface ModelCacheDiagnostic {
3
+ key: string;
4
+ operation: 'read' | 'write' | 'skip';
5
+ reason: 'storage-error' | 'invalid-entry' | 'entry-too-large';
6
+ bytes?: number;
7
+ maxEntryBytes: number;
8
+ errorName?: string;
9
+ }
10
+ /** Parsed-cache evidence is bounded and contains no URLs, headers or exception text. */
11
+ export interface ParsedModelCacheDiagnostic {
12
+ key: string;
13
+ operation: 'read' | 'write' | 'skip' | 'evict' | 'clear';
14
+ reason: 'storage-error' | 'invalid-entry' | 'entry-too-large' | 'capacity';
15
+ maxBytes: number;
16
+ maxEntryBytes: number;
17
+ maxEntries: number;
18
+ bytes?: number;
19
+ errorName?: string;
20
+ }
@@ -6,6 +6,10 @@ interface SignalsState {
6
6
  backgroundChanged: Signal;
7
7
  beforeRender: Signal;
8
8
  sceneRendered: Signal;
9
+ /** Dispatches ModelCacheDiagnostic when persistent model caching fails or skips a size limit. */
10
+ modelCacheDiagnostic: Signal;
11
+ /** Dispatches redacted ParsedModelCacheDiagnostic for storage/capacity failures. */
12
+ parsedModelCacheDiagnostic: Signal;
9
13
  tweenUpdate: Signal;
10
14
  hover: Signal;
11
15
  click: Signal;
@@ -102,6 +102,16 @@ interface ViewportOptions {
102
102
  closeInfoLog?: boolean;
103
103
  closeWarnLog?: boolean;
104
104
  useIndexedDB?: boolean;
105
+ /** Maximum bytes per persistent model resource; default 1 GiB, zero disables persistence. */
106
+ modelCacheMaxEntryBytes?: number;
107
+ /** Cache decoded static Entity model resources when useIndexedDB is enabled; default true. */
108
+ useParsedModelCache?: boolean;
109
+ /** Parsed cache logical total budget; default 512 MiB. Zero disables and trims this cache. */
110
+ parsedModelCacheMaxBytes?: number;
111
+ /** Maximum logical parsed resource size; default 256 MiB. */
112
+ parsedModelCacheMaxEntryBytes?: number;
113
+ /** Maximum persistent parsed resources; default 256. */
114
+ parsedModelCacheMaxEntries?: number;
105
115
  }
106
116
  interface ViewportState {
107
117
  useFreq: number;
@@ -0,0 +1,6 @@
1
+ import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
2
+ /** Called during SDK construction, before host code can customize its loader. */
3
+ export declare function parsedLoaderPolicy(loader: GLTFLoader): {
4
+ eligible: () => boolean;
5
+ profile: () => string;
6
+ };
@@ -36,6 +36,7 @@ export declare class TexturePreloader {
36
36
  private onContextRestored;
37
37
  private cancelFrame;
38
38
  prepare(root: Object3D, signal?: AbortSignal, managerSignal?: AbortSignal): Promise<void>;
39
+ prepareMaterials(materials: Iterable<unknown>, signal?: AbortSignal, managerSignal?: AbortSignal): Promise<void>;
39
40
  private schedule;
40
41
  private pump;
41
42
  private cancel;
package/types/index.d.ts CHANGED
@@ -1142,6 +1142,11 @@ declare class Bvh {
1142
1142
  dispose(): void;
1143
1143
  }
1144
1144
 
1145
+ declare interface CacheOptions {
1146
+ maxEntryBytes?: number;
1147
+ onDiagnostic?: (event: ModelCacheDiagnostic) => void;
1148
+ }
1149
+
1145
1150
  declare const calculateScaleFactor: (point3: Vector3, radiusPx: number, camera: Camera, size: Vector2) => number;
1146
1151
 
1147
1152
  declare class CameraManager {
@@ -3527,18 +3532,39 @@ export declare interface ModelAnimationFindFunc {
3527
3532
  declare class ModelBufferCache {
3528
3533
  private readonly store;
3529
3534
  private readonly enabled;
3530
- constructor(store?: LocalForage, enabled?: () => boolean);
3531
- load(url: string, init: {
3532
- headers: Headers;
3533
- credentials: RequestCredentials;
3534
- signal?: AbortSignal;
3535
- redirect?: RequestRedirect;
3536
- }): Promise<ArrayBuffer>;
3535
+ private readonly options;
3536
+ private warned;
3537
+ constructor(store?: LocalForage, enabled?: () => boolean, options?: () => CacheOptions);
3538
+ private maximumEntryBytes;
3539
+ private withinLimit;
3540
+ private diagnose;
3541
+ load(url: string, init: RequestInit_2): Promise<ArrayBuffer>;
3542
+ loadWithMetadata(url: string, init: RequestInit_2): Promise<ModelBufferResult>;
3543
+ private loadBytes;
3537
3544
  private key;
3538
3545
  private mutate;
3539
3546
  clear(): Promise<void>;
3540
3547
  }
3541
3548
 
3549
+ declare interface ModelBufferResult {
3550
+ buffer: ArrayBuffer;
3551
+ /** Hashed request identity; never a URL or credential. */
3552
+ cacheKey: string | null;
3553
+ cacheable: boolean;
3554
+ forbidPersistence: boolean;
3555
+ isCurrent: () => boolean;
3556
+ }
3557
+
3558
+ /** Cache diagnostics never contain resource URLs, headers or exception messages. */
3559
+ export declare interface ModelCacheDiagnostic {
3560
+ key: string;
3561
+ operation: 'read' | 'write' | 'skip';
3562
+ reason: 'storage-error' | 'invalid-entry' | 'entry-too-large';
3563
+ bytes?: number;
3564
+ maxEntryBytes: number;
3565
+ errorName?: string;
3566
+ }
3567
+
3542
3568
  export declare interface ModelEventParams {
3543
3569
  target: Model;
3544
3570
  currentTarget: Mesh;
@@ -3708,8 +3734,12 @@ export declare class ModelResources {
3708
3734
  private urls;
3709
3735
  private gltfLoader;
3710
3736
  private bufferCache;
3737
+ private parsedCacheOptions;
3738
+ private parsedCache;
3711
3739
  /** Borrow a host-configured loader; its decoder workers remain host-owned. */
3712
- setGLTFLoader(loader: GLTFLoader, bufferCache?: ModelBufferCache): void;
3740
+ setGLTFLoader(loader: GLTFLoader, bufferCache?: ModelBufferCache, parsedOptions?: () => ParsedModelCacheOptions & {
3741
+ profile?: string;
3742
+ }): void;
3713
3743
  readonly materials: {
3714
3744
  register: (material: Material, options: {
3715
3745
  ownership: "transfer";
@@ -3853,6 +3883,26 @@ export declare type OrbitControlsProperties = Required<Omit<OrbitControlsOptions
3853
3883
 
3854
3884
  export declare type OrbitControlsType = 'orbit';
3855
3885
 
3886
+ /** Parsed-cache evidence is bounded and contains no URLs, headers or exception text. */
3887
+ export declare interface ParsedModelCacheDiagnostic {
3888
+ key: string;
3889
+ operation: 'read' | 'write' | 'skip' | 'evict' | 'clear';
3890
+ reason: 'storage-error' | 'invalid-entry' | 'entry-too-large' | 'capacity';
3891
+ maxBytes: number;
3892
+ maxEntryBytes: number;
3893
+ maxEntries: number;
3894
+ bytes?: number;
3895
+ errorName?: string;
3896
+ }
3897
+
3898
+ declare interface ParsedModelCacheOptions {
3899
+ enabled?: boolean;
3900
+ maxBytes?: number;
3901
+ maxEntryBytes?: number;
3902
+ maxEntries?: number;
3903
+ onDiagnostic?: (event: ParsedModelCacheDiagnostic) => void;
3904
+ }
3905
+
3856
3906
  declare const parseFilePath: (url: string) => string;
3857
3907
 
3858
3908
  /**
@@ -4270,6 +4320,13 @@ export declare function renderLoop(frameFun: (time: DOMHighResTimeStamp) => void
4270
4320
  /** Default headers for SDK-owned HTTP(S) resource requests. */
4271
4321
  export declare const RequestHeaders: Record<string, string>;
4272
4322
 
4323
+ declare type RequestInit_2 = {
4324
+ headers: Headers;
4325
+ credentials: RequestCredentials;
4326
+ signal?: AbortSignal;
4327
+ redirect?: RequestRedirect;
4328
+ };
4329
+
4273
4330
  export declare class ResourceLease<T> {
4274
4331
  readonly registry: ModelResources;
4275
4332
  private record;
@@ -4288,6 +4345,7 @@ declare interface ResourceRecord<T> {
4288
4345
  dead: boolean;
4289
4346
  gpu: Set<BufferGeometry | Material | Texture>;
4290
4347
  dependencies: Set<ResourceRecord<Material>>;
4348
+ imageReleases: Set<() => void>;
4291
4349
  }
4292
4350
 
4293
4351
  declare const rgbeLoader: HDRLoader;
@@ -4576,6 +4634,10 @@ export declare interface SignalsState {
4576
4634
  backgroundChanged: Signal;
4577
4635
  beforeRender: Signal;
4578
4636
  sceneRendered: Signal;
4637
+ /** Dispatches ModelCacheDiagnostic when persistent model caching fails or skips a size limit. */
4638
+ modelCacheDiagnostic: Signal;
4639
+ /** Dispatches redacted ParsedModelCacheDiagnostic for storage/capacity failures. */
4640
+ parsedModelCacheDiagnostic: Signal;
4579
4641
  tweenUpdate: Signal;
4580
4642
  hover: Signal;
4581
4643
  click: Signal;
@@ -6828,6 +6890,16 @@ export declare interface ViewportOptions {
6828
6890
  closeInfoLog?: boolean;
6829
6891
  closeWarnLog?: boolean;
6830
6892
  useIndexedDB?: boolean;
6893
+ /** Maximum bytes per persistent model resource; default 1 GiB, zero disables persistence. */
6894
+ modelCacheMaxEntryBytes?: number;
6895
+ /** Cache decoded static Entity model resources when useIndexedDB is enabled; default true. */
6896
+ useParsedModelCache?: boolean;
6897
+ /** Parsed cache logical total budget; default 512 MiB. Zero disables and trims this cache. */
6898
+ parsedModelCacheMaxBytes?: number;
6899
+ /** Maximum logical parsed resource size; default 256 MiB. */
6900
+ parsedModelCacheMaxEntryBytes?: number;
6901
+ /** Maximum persistent parsed resources; default 256. */
6902
+ parsedModelCacheMaxEntries?: number;
6831
6903
  }
6832
6904
 
6833
6905
  export declare interface ViewportState {