@plasius/asset-contracts 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/README.md +130 -1
- package/dist/index.cjs +345 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +127 -2
- package/dist/index.d.ts +127 -2
- package/dist/index.js +329 -6
- package/dist/index.js.map +1 -1
- package/docs/adrs/adr-0010-public-conversion-diagnostics.md +61 -0
- package/docs/adrs/adr-0011-reloadable-texture-resource-roles.md +92 -0
- package/docs/adrs/index.md +2 -0
- package/docs/tdrs/index.md +2 -0
- package/docs/tdrs/tdr-0005-public-conversion-diagnostics.md +51 -0
- package/docs/tdrs/tdr-0006-reloadable-texture-resource-roles.md +91 -0
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/model-conversion-diagnostics.ts +185 -0
- package/src/model-texture-resources.ts +215 -0
package/CHANGELOG.md
CHANGED
|
@@ -14,6 +14,41 @@
|
|
|
14
14
|
- **Security**
|
|
15
15
|
- (placeholder)
|
|
16
16
|
|
|
17
|
+
## [0.7.0] - 2026-10-24
|
|
18
|
+
|
|
19
|
+
- **Added**
|
|
20
|
+
- Opt-in reloadable canonical texture/material resource qualification, exact
|
|
21
|
+
storage role/MIME mapping and separate GPU upload/atlas source bindings.
|
|
22
|
+
Preserves authored metadata and original resource identity through JSON reload.
|
|
23
|
+
- (placeholder)
|
|
24
|
+
|
|
25
|
+
- **Changed**
|
|
26
|
+
- (placeholder)
|
|
27
|
+
|
|
28
|
+
- **Fixed**
|
|
29
|
+
- (placeholder)
|
|
30
|
+
|
|
31
|
+
- **Security**
|
|
32
|
+
- (placeholder)
|
|
33
|
+
|
|
34
|
+
## [0.6.0] - 2026-10-24
|
|
35
|
+
|
|
36
|
+
- **Added**
|
|
37
|
+
- Opt-in public-safe canonical conversion diagnostics with fixed codes/text,
|
|
38
|
+
resource/source identity, explicit loss/fallback evidence and legacy converter
|
|
39
|
+
projections. Reuses lazy model-core evaluation; independent approval and
|
|
40
|
+
promotion gates remain required.
|
|
41
|
+
- (placeholder)
|
|
42
|
+
|
|
43
|
+
- **Changed**
|
|
44
|
+
- (placeholder)
|
|
45
|
+
|
|
46
|
+
- **Fixed**
|
|
47
|
+
- (placeholder)
|
|
48
|
+
|
|
49
|
+
- **Security**
|
|
50
|
+
- (placeholder)
|
|
51
|
+
|
|
17
52
|
## [0.5.0] - 2026-10-24
|
|
18
53
|
|
|
19
54
|
- **Added**
|
|
@@ -330,3 +365,5 @@
|
|
|
330
365
|
[0.4.5]: https://github.com/Plasius-LTD/asset-contracts/releases/tag/v0.4.5
|
|
331
366
|
[0.4.6]: https://github.com/Plasius-LTD/asset-contracts/releases/tag/v0.4.6
|
|
332
367
|
[0.5.0]: https://github.com/Plasius-LTD/asset-contracts/releases/tag/v0.5.0
|
|
368
|
+
[0.6.0]: https://github.com/Plasius-LTD/asset-contracts/releases/tag/v0.6.0
|
|
369
|
+
[0.7.0]: https://github.com/Plasius-LTD/asset-contracts/releases/tag/v0.7.0
|
package/README.md
CHANGED
|
@@ -28,6 +28,8 @@ The exported surface covers:
|
|
|
28
28
|
- asset job metadata contracts
|
|
29
29
|
- manifest and file descriptor contracts
|
|
30
30
|
- opt-in canonical model package inventory and exact-byte qualification
|
|
31
|
+
- reloadable canonical texture/material metadata and explicit upload/atlas roles
|
|
32
|
+
- opt-in public-safe canonical conversion diagnostics and resource/source binding
|
|
31
33
|
- screenshot plan definitions
|
|
32
34
|
- review findings and review report contracts
|
|
33
35
|
- immutable promotion record contracts
|
|
@@ -90,7 +92,7 @@ Embedded resources remain inside their owning entrypoint; list only actual
|
|
|
90
92
|
exported files. This helper checks bytes and declarations, not internal format
|
|
91
93
|
references, MIME sniffing, malware, rendering, storage or promotion authority.
|
|
92
94
|
Keep source provenance in the canonical document and do not substitute derived
|
|
93
|
-
hashes for original source hashes.
|
|
95
|
+
hashes for original source hashes. Role qualification is available through the additive helper below; animation/source
|
|
94
96
|
relationships and promotion closure remain separately tracked work. The result
|
|
95
97
|
is qualification at call time; callers must preserve the exact bytes in their
|
|
96
98
|
own immutable storage boundary.
|
|
@@ -104,6 +106,133 @@ runtime parser or renderer loading. Downstream adoption must use a released
|
|
|
104
106
|
package. See [ADR 0009](./docs/adrs/adr-0009-model-resource-manifest-qualification.md)
|
|
105
107
|
and [TDR 0004](./docs/tdrs/tdr-0004-model-resource-manifest-qualification.md).
|
|
106
108
|
|
|
109
|
+
## Reloadable Texture and Resource Roles
|
|
110
|
+
|
|
111
|
+
`qualifyModelTextureResources` composes exact byte/inventory qualification with
|
|
112
|
+
published model-core's verified material/texture graph. It keeps authored
|
|
113
|
+
metadata and source image identity separate from derived GPU uploads/atlases.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
import { qualifyModelTextureResources } from "@plasius/asset-contracts";
|
|
117
|
+
|
|
118
|
+
const reload = await qualifyModelTextureResources({
|
|
119
|
+
manifest, packageManifest, files: exportedFiles,
|
|
120
|
+
graph: verifiedCanonicalGraph,
|
|
121
|
+
resources: [
|
|
122
|
+
{ resourceId: "source-image", filePath: "textures/source.png" },
|
|
123
|
+
{ resourceId: "embedded-buffer", filePath: "model.gltf" },
|
|
124
|
+
], // Exactly one binding per graph resource.
|
|
125
|
+
derived: [
|
|
126
|
+
{ role: "gpu-upload", filePath: "derived/upload.bin", sourceResourceIds: ["source-image"] },
|
|
127
|
+
{ role: "texture-atlas", filePath: "derived/atlas.png", sourceResourceIds: ["source-image"] },
|
|
128
|
+
], // Or [] when no derivative is exported.
|
|
129
|
+
}, { signal: abortController.signal, timeoutMs: 10_000 });
|
|
130
|
+
// Persist JSON.stringify(reload) alongside the qualified immutable bytes.
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Use existing storage roles: canonical texture → texture with PNG/JPEG/WebP/KTX2
|
|
134
|
+
MIME; material/animation → metadata with application/json; mesh → model or
|
|
135
|
+
binary; auxiliary → binary or JSON metadata. Uploads require auxiliary/binary
|
|
136
|
+
buffer files, atlases texture/image files. See TDR 0006 for the exact MIME table.
|
|
137
|
+
Missing/duplicate resources, incompatible roles/MIME, unknown roles, graph
|
|
138
|
+
clones and source/output collisions reject. External files match graph path,
|
|
139
|
+
hash, byte length and MIME; embedded resources name the owning model entrypoint
|
|
140
|
+
and retain their independent resource hash. List only actual exported files.
|
|
141
|
+
|
|
142
|
+
The frozen version-1 result contains manifest, original source provenance,
|
|
143
|
+
resources, canonical materials/textures and derived records. Authored usage,
|
|
144
|
+
color space, sampler, binding transform, embedding policy and sourceMetadata
|
|
145
|
+
survive JSON reload. Original image IDs and bytes are never replaced by atlas
|
|
146
|
+
hashes or upload paths. No Blob payload or renderer allocation is serialized.
|
|
147
|
+
Adapters own model-internal references, derivation algorithms and image content
|
|
148
|
+
inspection; qualification does not attest those operations or grant promotion.
|
|
149
|
+
Task 12 animation schemas, Task 23 shader ABI and Task 51 promotion closure
|
|
150
|
+
remain separate.
|
|
151
|
+
|
|
152
|
+
This is **trusted package metadata**, including names, extensions, original
|
|
153
|
+
paths and authored sourceMetadata. Minimize/sanitize that data before public
|
|
154
|
+
distribution; use the separate public diagnostics API for technical responses.
|
|
155
|
+
Serialized graphs lose their private brand: verify reloaded canonical resources
|
|
156
|
+
and reconstruct a graph through core before qualifying again. Produce graphs
|
|
157
|
+
with the same installed model-core instance and matching module format (ESM
|
|
158
|
+
import with ESM, require with CJS). The normal named guard import preserves that
|
|
159
|
+
identity; unused exports remain tree-shakeable through sideEffects=false.
|
|
160
|
+
|
|
161
|
+
Inputs/bytes are snapshotted before awaiting. Fixed ceilings are 16,384 resource
|
|
162
|
+
bindings, 4,096 derivatives, 65,536 graph nodes, shared 262,144 metadata values,
|
|
163
|
+
2,097,152 UTF-16 characters, depth 16 and 2,048 characters/string. Existing file
|
|
164
|
+
limits also apply. Default deadline 10 seconds, allowed range 1–60,000 ms;
|
|
165
|
+
cancellation/deadline reject without a partial result. In-flight Web Crypto
|
|
166
|
+
cannot be cancelled. ModelTextureResourceError.code is value-free.
|
|
167
|
+
|
|
168
|
+
The backend evaluator gpu.model.conversion.enabled controls caller adoption;
|
|
169
|
+
disabled/rollback paths retain legacy factories. No lookup/mutation or UI
|
|
170
|
+
capability is introduced. Dependencies and legacy factories are unchanged.
|
|
171
|
+
See [ADR 0011](./docs/adrs/adr-0011-reloadable-texture-resource-roles.md) and
|
|
172
|
+
[TDR 0006](./docs/tdrs/tdr-0006-reloadable-texture-resource-roles.md).
|
|
173
|
+
|
|
174
|
+
## Public Conversion Diagnostics
|
|
175
|
+
|
|
176
|
+
`qualifyModelConversionDiagnostics` adds an opt-in, version-1 JSON boundary over
|
|
177
|
+
published model-core diagnostics. It reuses the canonical evaluator, loading it
|
|
178
|
+
only when this async helper is called. Existing factories remain compatible.
|
|
179
|
+
|
|
180
|
+
```ts
|
|
181
|
+
import { qualifyModelConversionDiagnostics } from "@plasius/asset-contracts";
|
|
182
|
+
|
|
183
|
+
const result = await qualifyModelConversionDiagnostics({
|
|
184
|
+
outcome: "completed", // or "unsupported" / "failed" from your trusted adapter
|
|
185
|
+
source: publicSourceProvenance, // existing ModelProvenance; original source hash
|
|
186
|
+
report: canonicalDiagnosticInput, // model-core GpuModelDiagnosticInput
|
|
187
|
+
resources: [{ path: "/meshes/0", resource: publicModelResourceRef }],
|
|
188
|
+
}, { signal: abortController.signal, timeoutMs: 10_000 });
|
|
189
|
+
// Only these existing diagnostic/loss fields belong in ModelConverterEvidence:
|
|
190
|
+
const converterEvidence = { ...trustedConverterIdentity, ...result.converter };
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Every non-root diagnostic path must match exactly one supplied resource binding.
|
|
194
|
+
The root path `/` refers to `result.source`; no resource is fabricated. Resource
|
|
195
|
+
references use existing credential-free `mcp://models/...` contracts and include
|
|
196
|
+
hash, length and MIME identity. Conflicting references for one URI reject. These
|
|
197
|
+
bindings and provenance are caller assertions, not proof that bytes were read.
|
|
198
|
+
Use manifest qualification and independent promotion checks at their boundaries.
|
|
199
|
+
|
|
200
|
+
Statuses are derived deterministically: explicit failure wins, then unsupported
|
|
201
|
+
data/outcome, then canonical rejection, then warning or clean success. Loss
|
|
202
|
+
requires canonical explicit consent; denied loss produces blocking legacy loss
|
|
203
|
+
evidence. Only canonical accepted repairs receive a fallback rule id. Unknown
|
|
204
|
+
repair rules remain blocking. Arbitrary adapter codes, messages, private paths,
|
|
205
|
+
provider exceptions, original repair values and forensic rawSource are never
|
|
206
|
+
serialized; unknown adapter codes map to fixed category codes. Public codes are
|
|
207
|
+
`conversion.warning`, `conversion.repair`, `conversion.loss.dropped`,
|
|
208
|
+
`conversion.loss.approximated`, `conversion.unsupported`, `conversion.blocked`
|
|
209
|
+
and `conversion.failed`, with fixed bounded messages. Malformed input rejects
|
|
210
|
+
with value-free `ModelConversionDiagnosticsError.code`.
|
|
211
|
+
|
|
212
|
+
This projection is technical evidence only. `technicalAccepted` never replaces
|
|
213
|
+
human approval, malware/security, rights, fidelity, confirmation or promotion
|
|
214
|
+
receipts. `result.converter` contains the exact existing diagnostics/losses
|
|
215
|
+
shape; the detailed `result.diagnostics` additionally binds resources and
|
|
216
|
+
loss/fallback metadata. Preserve all independent evidence when composing it.
|
|
217
|
+
|
|
218
|
+
Inputs must be inert JSON records; getters, exotic prototypes, sparse arrays,
|
|
219
|
+
cycles, symbols and extra contract keys reject. Metadata is snapshotted before
|
|
220
|
+
awaiting. Fixed ceilings are 100 issues/resources, depth 12, 16,384 values,
|
|
221
|
+
2,048 characters per string and 262,144 total string characters. Non-completed
|
|
222
|
+
outcomes reserve one issue slot for a terminal diagnostic, so accept at most
|
|
223
|
+
99 issues. Arrays never exceed legacy 100-entry limits. Default deadline is
|
|
224
|
+
10 seconds, configurable from 1–60,000 ms; cancellation/deadlines bound the
|
|
225
|
+
lazy import wait and are checked around bounded synchronous evaluation. They
|
|
226
|
+
cannot preempt JavaScript evaluation or cancel the platform module loader.
|
|
227
|
+
No network, filesystem, logs, retries or persistent state are introduced.
|
|
228
|
+
|
|
229
|
+
Use the backend-evaluated `gpu.model.conversion.enabled` adoption decision;
|
|
230
|
+
disabled/rollback paths retain existing factories and diagnostics. No live flag
|
|
231
|
+
lookup/mutation or UI capability is added. The already-published exact
|
|
232
|
+
model-core0.7.0 dependency supplies evaluation without adding a parser or
|
|
233
|
+
renderer. No dependency version changes are needed. See [ADR 0010](./docs/adrs/adr-0010-public-conversion-diagnostics.md)
|
|
234
|
+
and [TDR 0005](./docs/tdrs/tdr-0005-public-conversion-diagnostics.md).
|
|
235
|
+
|
|
107
236
|
## Private Artifact Prevention
|
|
108
237
|
|
|
109
238
|
Signed contributor agreements and contributor acceptance records are retained
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -39,6 +49,7 @@ __export(index_exports, {
|
|
|
39
49
|
MODEL_CANDIDATE_HARD_GATE_KINDS: () => MODEL_CANDIDATE_HARD_GATE_KINDS,
|
|
40
50
|
MODEL_CONFIRMATION_VIEW_KINDS: () => MODEL_CONFIRMATION_VIEW_KINDS,
|
|
41
51
|
MODEL_CONFIRMATION_VIEW_SIZE_PX: () => MODEL_CONFIRMATION_VIEW_SIZE_PX,
|
|
52
|
+
MODEL_CONVERSION_DIAGNOSTIC_LIMITS: () => MODEL_CONVERSION_DIAGNOSTIC_LIMITS,
|
|
42
53
|
MODEL_GENERATOR_DISABLED_REASON_CODE: () => MODEL_GENERATOR_DISABLED_REASON_CODE,
|
|
43
54
|
MODEL_MATCH_ASSURANCE_BANDS: () => MODEL_MATCH_ASSURANCE_BANDS,
|
|
44
55
|
MODEL_MATCH_ASSURANCE_THRESHOLDS: () => MODEL_MATCH_ASSURANCE_THRESHOLDS,
|
|
@@ -54,8 +65,11 @@ __export(index_exports, {
|
|
|
54
65
|
MODEL_RESOLUTION_V2_STATES: () => MODEL_RESOLUTION_V2_STATES,
|
|
55
66
|
MODEL_RESOURCE_MANIFEST_LIMITS: () => MODEL_RESOURCE_MANIFEST_LIMITS,
|
|
56
67
|
MODEL_RIGHTS_STATUSES: () => MODEL_RIGHTS_STATUSES,
|
|
68
|
+
MODEL_TEXTURE_RESOURCE_LIMITS: () => MODEL_TEXTURE_RESOURCE_LIMITS,
|
|
57
69
|
MODEL_TEXT_ONLY_ASSURANCE_CEILING_REASON_CODE: () => MODEL_TEXT_ONLY_ASSURANCE_CEILING_REASON_CODE,
|
|
70
|
+
ModelConversionDiagnosticsError: () => ModelConversionDiagnosticsError,
|
|
58
71
|
ModelResourceManifestError: () => ModelResourceManifestError,
|
|
72
|
+
ModelTextureResourceError: () => ModelTextureResourceError,
|
|
59
73
|
PVOX_ASSEMBLY_CLOSURE_HASH_DOMAIN: () => PVOX_ASSEMBLY_CLOSURE_HASH_DOMAIN,
|
|
60
74
|
PVOX_ASSET_MANIFEST_VERSION: () => PVOX_ASSET_MANIFEST_VERSION,
|
|
61
75
|
PVOX_BINARY_CLOSURE_HASH_DOMAIN: () => PVOX_BINARY_CLOSURE_HASH_DOMAIN,
|
|
@@ -246,7 +260,9 @@ __export(index_exports, {
|
|
|
246
260
|
normalizeAssetId: () => normalizeAssetId,
|
|
247
261
|
normalizePvoxRootHeaderForHashV1: () => normalizePvoxRootHeaderForHashV1,
|
|
248
262
|
projectPvoxNamedJsonClosureV1: () => projectPvoxNamedJsonClosureV1,
|
|
263
|
+
qualifyModelConversionDiagnostics: () => qualifyModelConversionDiagnostics,
|
|
249
264
|
qualifyModelResourceManifest: () => qualifyModelResourceManifest,
|
|
265
|
+
qualifyModelTextureResources: () => qualifyModelTextureResources,
|
|
250
266
|
toLegacyModelResolutionState: () => toLegacyModelResolutionState,
|
|
251
267
|
validateGpuAssetFiles: () => validateGpuAssetFiles
|
|
252
268
|
});
|
|
@@ -435,11 +451,11 @@ function assertNoDirectUrl(value, fieldName) {
|
|
|
435
451
|
}
|
|
436
452
|
}
|
|
437
453
|
function requiredToken(value, fieldName) {
|
|
438
|
-
const
|
|
439
|
-
if (!TOKEN_PATTERN.test(
|
|
454
|
+
const token3 = requiredString(value, fieldName, 128);
|
|
455
|
+
if (!TOKEN_PATTERN.test(token3)) {
|
|
440
456
|
throw new Error(`${fieldName} must be a token up to 128 characters.`);
|
|
441
457
|
}
|
|
442
|
-
return
|
|
458
|
+
return token3;
|
|
443
459
|
}
|
|
444
460
|
function requiredModelPathSegment(value, fieldName) {
|
|
445
461
|
const segment = requiredString(value, fieldName, 128);
|
|
@@ -6940,9 +6956,9 @@ function snapshot(value, budget, depth = 0) {
|
|
|
6940
6956
|
return value;
|
|
6941
6957
|
}
|
|
6942
6958
|
if (Array.isArray(value)) return Object.freeze(list(value).map((item) => snapshot(item, budget, depth + 1)));
|
|
6943
|
-
const
|
|
6944
|
-
for (const key of Object.keys(
|
|
6945
|
-
return Object.freeze(
|
|
6959
|
+
const fields3 = record(value);
|
|
6960
|
+
for (const key of Object.keys(fields3)) fields3[key] = snapshot(fields3[key], budget, depth + 1);
|
|
6961
|
+
return Object.freeze(fields3);
|
|
6946
6962
|
}
|
|
6947
6963
|
function path(value) {
|
|
6948
6964
|
if (typeof value !== "string" || value.length > 1024 || !value.length) fail();
|
|
@@ -7051,6 +7067,323 @@ async function qualify(input) {
|
|
|
7051
7067
|
return Object.freeze({ ...manifest, files: Object.freeze([...manifest.files].sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0)) });
|
|
7052
7068
|
}
|
|
7053
7069
|
|
|
7070
|
+
// src/model-texture-resources.ts
|
|
7071
|
+
var import_gpu_model_core = require("@plasius/gpu-model-core");
|
|
7072
|
+
var MODEL_TEXTURE_RESOURCE_LIMITS = Object.freeze({ resources: 16384, derived: 4096, nodes: 65536, values: 262144, characters: 2097152, depth: 16, timeoutMs: 6e4 });
|
|
7073
|
+
var ModelTextureResourceError = class extends TypeError {
|
|
7074
|
+
constructor(code) {
|
|
7075
|
+
super(`Invalid model texture resources: ${code}`);
|
|
7076
|
+
this.code = code;
|
|
7077
|
+
this.name = "ModelTextureResourceError";
|
|
7078
|
+
}
|
|
7079
|
+
code;
|
|
7080
|
+
};
|
|
7081
|
+
function fail2(code = "invalid-input") {
|
|
7082
|
+
throw new ModelTextureResourceError(code);
|
|
7083
|
+
}
|
|
7084
|
+
function fields(value, allowed) {
|
|
7085
|
+
if (!value || typeof value !== "object" || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) fail2();
|
|
7086
|
+
const keys = Reflect.ownKeys(value);
|
|
7087
|
+
if (keys.length > 1024) fail2("limit-exceeded");
|
|
7088
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
7089
|
+
for (const key of keys) {
|
|
7090
|
+
if (typeof key !== "string" || key.length > 128 || ["__proto__", "prototype", "constructor"].includes(key) || allowed && !allowed.includes(key)) fail2();
|
|
7091
|
+
const property = Object.getOwnPropertyDescriptor(value, key);
|
|
7092
|
+
if (!("value" in property) || !property.enumerable) fail2();
|
|
7093
|
+
result[key] = property.value;
|
|
7094
|
+
}
|
|
7095
|
+
return result;
|
|
7096
|
+
}
|
|
7097
|
+
function array(value, maximum) {
|
|
7098
|
+
if (!Array.isArray(value) || Object.getPrototypeOf(value) !== Array.prototype) fail2();
|
|
7099
|
+
if (value.length > maximum) fail2("limit-exceeded");
|
|
7100
|
+
if (Reflect.ownKeys(value).length !== value.length + 1) fail2();
|
|
7101
|
+
const result = [];
|
|
7102
|
+
for (let i = 0; i < value.length; i++) {
|
|
7103
|
+
const property = Object.getOwnPropertyDescriptor(value, String(i));
|
|
7104
|
+
if (!property || !("value" in property) || !property.enumerable) fail2();
|
|
7105
|
+
result.push(property.value);
|
|
7106
|
+
}
|
|
7107
|
+
return result;
|
|
7108
|
+
}
|
|
7109
|
+
function snapshot2(value, budget, depth = 0) {
|
|
7110
|
+
if (--budget.values < 0 || depth > MODEL_TEXTURE_RESOURCE_LIMITS.depth) fail2("limit-exceeded");
|
|
7111
|
+
if (value === null || value === void 0 || typeof value === "boolean") return value;
|
|
7112
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
7113
|
+
if (typeof value === "string") {
|
|
7114
|
+
budget.characters -= value.length;
|
|
7115
|
+
if (value.length > 2048 || budget.characters < 0) fail2("limit-exceeded");
|
|
7116
|
+
return value;
|
|
7117
|
+
}
|
|
7118
|
+
if (Array.isArray(value)) return Object.freeze(array(value, MODEL_TEXTURE_RESOURCE_LIMITS.resources).map((v) => snapshot2(v, budget, depth + 1)));
|
|
7119
|
+
const result = fields(value);
|
|
7120
|
+
for (const key of Object.keys(result)) {
|
|
7121
|
+
budget.characters -= key.length;
|
|
7122
|
+
if (budget.characters < 0) fail2("limit-exceeded");
|
|
7123
|
+
result[key] = snapshot2(result[key], budget, depth + 1);
|
|
7124
|
+
}
|
|
7125
|
+
return Object.freeze(result);
|
|
7126
|
+
}
|
|
7127
|
+
function token2(value) {
|
|
7128
|
+
if (typeof value !== "string" || !/^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/u.test(value)) fail2();
|
|
7129
|
+
return value;
|
|
7130
|
+
}
|
|
7131
|
+
var compare = (a, b) => a < b ? -1 : a > b ? 1 : 0;
|
|
7132
|
+
var imageMime = (value) => ["image/png", "image/jpeg", "image/webp", "image/ktx2"].includes(value);
|
|
7133
|
+
var bufferMime = (value) => ["application/octet-stream", "application/vnd.plasius.gpu-buffer"].includes(value);
|
|
7134
|
+
function storageRole(role, file) {
|
|
7135
|
+
const valid = role === "texture" ? file.role === "texture" && imageMime(file.contentType) : role === "material" || role === "animation" ? file.role === "metadata" && file.contentType === "application/json" : role === "mesh" ? file.role === "binary" && bufferMime(file.contentType) || file.role === "model" && (file.contentType.startsWith("model/") || ["application/json", "application/octet-stream", "text/plain"].includes(file.contentType)) : role === "auxiliary" && (file.role === "binary" && bufferMime(file.contentType) || file.role === "metadata" && file.contentType === "application/json");
|
|
7136
|
+
if (!valid) fail2("role-mismatch");
|
|
7137
|
+
}
|
|
7138
|
+
async function qualifyModelTextureResources(input, options = {}) {
|
|
7139
|
+
let timer;
|
|
7140
|
+
let signal;
|
|
7141
|
+
let onAbort;
|
|
7142
|
+
try {
|
|
7143
|
+
const started = performance.now();
|
|
7144
|
+
const controls = fields(options, ["signal", "timeoutMs"]);
|
|
7145
|
+
const timeoutMs = controls.timeoutMs === void 0 ? 1e4 : controls.timeoutMs;
|
|
7146
|
+
if (typeof timeoutMs !== "number" || !Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > MODEL_TEXTURE_RESOURCE_LIMITS.timeoutMs) fail2();
|
|
7147
|
+
signal = controls.signal;
|
|
7148
|
+
const aborted = Object.getOwnPropertyDescriptor(AbortSignal.prototype, "aborted").get;
|
|
7149
|
+
const check = () => {
|
|
7150
|
+
if (signal !== void 0 && aborted.call(signal)) fail2("aborted");
|
|
7151
|
+
if (performance.now() - started >= timeoutMs) fail2("deadline-exceeded");
|
|
7152
|
+
};
|
|
7153
|
+
check();
|
|
7154
|
+
const root = fields(input, ["manifest", "packageManifest", "files", "graph", "resources", "derived"]);
|
|
7155
|
+
const graph = root.graph;
|
|
7156
|
+
if (!(0, import_gpu_model_core.isGpuModelResourceGraph)(graph)) fail2("unverified-graph");
|
|
7157
|
+
if (graph.nodes.length > MODEL_TEXTURE_RESOURCE_LIMITS.nodes) fail2("limit-exceeded");
|
|
7158
|
+
const budget = { values: MODEL_TEXTURE_RESOURCE_LIMITS.values, characters: MODEL_TEXTURE_RESOURCE_LIMITS.characters };
|
|
7159
|
+
const inventory = snapshot2(root.packageManifest, budget);
|
|
7160
|
+
const bindings = array(snapshot2(root.resources, budget), MODEL_TEXTURE_RESOURCE_LIMITS.resources).map((value) => {
|
|
7161
|
+
const binding = fields(value, ["resourceId", "filePath"]);
|
|
7162
|
+
return Object.freeze({ resourceId: token2(binding.resourceId), filePath: tokenPath(binding.filePath) });
|
|
7163
|
+
});
|
|
7164
|
+
const derived = array(snapshot2(root.derived, budget), MODEL_TEXTURE_RESOURCE_LIMITS.derived).map((value) => {
|
|
7165
|
+
const record2 = fields(value, ["role", "filePath", "sourceResourceIds"]);
|
|
7166
|
+
if (record2.role !== "gpu-upload" && record2.role !== "texture-atlas") fail2("role-mismatch");
|
|
7167
|
+
const ids = array(record2.sourceResourceIds, MODEL_TEXTURE_RESOURCE_LIMITS.resources).map(token2);
|
|
7168
|
+
if (!ids.length || new Set(ids).size !== ids.length) fail2("resource-mismatch");
|
|
7169
|
+
return Object.freeze({ role: record2.role, filePath: tokenPath(record2.filePath), sourceResourceIds: Object.freeze(ids.sort(compare)) });
|
|
7170
|
+
});
|
|
7171
|
+
check();
|
|
7172
|
+
const interrupted = new Promise((_resolve, reject) => {
|
|
7173
|
+
timer = setTimeout(() => reject(new ModelTextureResourceError("deadline-exceeded")), Math.max(1, timeoutMs - (performance.now() - started)));
|
|
7174
|
+
onAbort = () => reject(new ModelTextureResourceError("aborted"));
|
|
7175
|
+
if (signal) AbortSignal.prototype.addEventListener.call(signal, "abort", onAbort, { once: true });
|
|
7176
|
+
});
|
|
7177
|
+
const manifest = await Promise.race([
|
|
7178
|
+
qualifyModelResourceManifest({ manifest: root.manifest, files: root.files, packageManifest: inventory, signal, timeoutMs }),
|
|
7179
|
+
interrupted
|
|
7180
|
+
]);
|
|
7181
|
+
check();
|
|
7182
|
+
const files = new Map(manifest.files.map((file) => [file.path, file]));
|
|
7183
|
+
const roles = new Map(inventory.entries.map((entry) => [entry.path, entry.role]));
|
|
7184
|
+
for (const entry of inventory.entries) storageRole(entry.role, files.get(entry.path));
|
|
7185
|
+
const resources = new Map(graph.nodes.filter((node) => node.kind === "resource").map((node) => [node.id, node.value]));
|
|
7186
|
+
if (bindings.length !== resources.size || new Set(bindings.map((b) => b.resourceId)).size !== bindings.length) fail2("resource-mismatch");
|
|
7187
|
+
const resourceFiles = /* @__PURE__ */ new Set();
|
|
7188
|
+
const qualified = bindings.map((binding) => {
|
|
7189
|
+
const value = resources.get(binding.resourceId);
|
|
7190
|
+
const file = files.get(binding.filePath);
|
|
7191
|
+
if (!value || !file) fail2("resource-mismatch");
|
|
7192
|
+
const { resource, location, exportEmbeddingPolicy } = value;
|
|
7193
|
+
if (location.kind === "external") {
|
|
7194
|
+
if (binding.filePath !== location.relativePath || file.sha256 !== resource.contentHash || file.byteLength !== resource.byteLength || file.contentType !== resource.mimeType) fail2("resource-mismatch");
|
|
7195
|
+
if (resource.kind === "image" ? roles.get(file.path) !== "texture" : file.role !== "binary") fail2("role-mismatch");
|
|
7196
|
+
} else if (binding.filePath !== manifest.entrypoint || file.role !== "model") fail2("resource-mismatch");
|
|
7197
|
+
resourceFiles.add(binding.filePath);
|
|
7198
|
+
return Object.freeze({ ...binding, kind: resource.kind, contentHash: resource.contentHash, byteLength: resource.byteLength, mimeType: resource.mimeType, location, exportEmbeddingPolicy });
|
|
7199
|
+
});
|
|
7200
|
+
const outputFiles = /* @__PURE__ */ new Set();
|
|
7201
|
+
for (const output of derived) {
|
|
7202
|
+
const file = files.get(output.filePath);
|
|
7203
|
+
if (!file || outputFiles.has(output.filePath) || resourceFiles.has(output.filePath)) fail2("resource-mismatch");
|
|
7204
|
+
outputFiles.add(output.filePath);
|
|
7205
|
+
for (const id of output.sourceResourceIds) {
|
|
7206
|
+
const source2 = resources.get(id);
|
|
7207
|
+
if (!source2 || output.role === "texture-atlas" && source2.resource.kind !== "image") fail2("resource-mismatch");
|
|
7208
|
+
}
|
|
7209
|
+
if (output.role === "gpu-upload" ? file.role !== "binary" || !bufferMime(file.contentType) || roles.get(file.path) !== "auxiliary" : file.role !== "texture" || !imageMime(file.contentType) || roles.get(file.path) !== "texture") fail2("role-mismatch");
|
|
7210
|
+
}
|
|
7211
|
+
const materials = graph.nodes.filter((node) => node.kind === "material").map((node) => node.value);
|
|
7212
|
+
const textures = graph.nodes.filter((node) => node.kind === "texture").map((node) => node.value);
|
|
7213
|
+
const source = graph.nodes.find((node) => node.kind === "provenance");
|
|
7214
|
+
if (source.kind !== "provenance") fail2();
|
|
7215
|
+
snapshot2({ materials, textures, source: source.value }, budget);
|
|
7216
|
+
check();
|
|
7217
|
+
return Object.freeze({
|
|
7218
|
+
contractVersion: 1,
|
|
7219
|
+
manifest,
|
|
7220
|
+
source: source.value,
|
|
7221
|
+
resources: Object.freeze(qualified.sort((a, b) => compare(a.resourceId, b.resourceId))),
|
|
7222
|
+
materials: Object.freeze(materials),
|
|
7223
|
+
textures: Object.freeze(textures),
|
|
7224
|
+
derived: Object.freeze(derived.sort((a, b) => compare(a.filePath, b.filePath)))
|
|
7225
|
+
});
|
|
7226
|
+
} catch (error) {
|
|
7227
|
+
if (error instanceof ModelTextureResourceError) throw error;
|
|
7228
|
+
if (error instanceof ModelResourceManifestError) return fail2(error.code === "aborted" || error.code === "deadline-exceeded" || error.code === "limit-exceeded" ? error.code : "package-mismatch");
|
|
7229
|
+
return fail2();
|
|
7230
|
+
} finally {
|
|
7231
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
7232
|
+
if (signal && onAbort) AbortSignal.prototype.removeEventListener.call(signal, "abort", onAbort);
|
|
7233
|
+
}
|
|
7234
|
+
}
|
|
7235
|
+
function tokenPath(value) {
|
|
7236
|
+
if (typeof value !== "string" || !value.length || value.length > 1024) fail2();
|
|
7237
|
+
return value;
|
|
7238
|
+
}
|
|
7239
|
+
|
|
7240
|
+
// src/model-conversion-diagnostics.ts
|
|
7241
|
+
var MODEL_CONVERSION_DIAGNOSTIC_LIMITS = Object.freeze({ issues: 100, resources: 100, values: 16384, depth: 12, string: 2048, characters: 262144, timeoutMs: 6e4 });
|
|
7242
|
+
var ModelConversionDiagnosticsError = class extends TypeError {
|
|
7243
|
+
constructor(code) {
|
|
7244
|
+
super(`Invalid model conversion diagnostics: ${code}`);
|
|
7245
|
+
this.code = code;
|
|
7246
|
+
this.name = "ModelConversionDiagnosticsError";
|
|
7247
|
+
}
|
|
7248
|
+
code;
|
|
7249
|
+
};
|
|
7250
|
+
function fail3(code = "invalid-input") {
|
|
7251
|
+
throw new ModelConversionDiagnosticsError(code);
|
|
7252
|
+
}
|
|
7253
|
+
function fields2(value) {
|
|
7254
|
+
if (!value || typeof value !== "object" || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) fail3();
|
|
7255
|
+
const result = /* @__PURE__ */ Object.create(null);
|
|
7256
|
+
const keys = Reflect.ownKeys(value);
|
|
7257
|
+
if (keys.length > 1024) fail3("limit-exceeded");
|
|
7258
|
+
for (const key of keys) {
|
|
7259
|
+
if (typeof key !== "string" || key.length > 128 || ["__proto__", "prototype", "constructor"].includes(key)) fail3();
|
|
7260
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
7261
|
+
if (!("value" in descriptor) || !descriptor.enumerable) fail3();
|
|
7262
|
+
result[key] = descriptor.value;
|
|
7263
|
+
}
|
|
7264
|
+
return result;
|
|
7265
|
+
}
|
|
7266
|
+
function only(record2, keys) {
|
|
7267
|
+
if (Object.keys(record2).some((key) => !keys.includes(key))) fail3();
|
|
7268
|
+
}
|
|
7269
|
+
function snapshot3(value, budget, depth = 0) {
|
|
7270
|
+
if (--budget.values < 0 || depth > MODEL_CONVERSION_DIAGNOSTIC_LIMITS.depth) fail3("limit-exceeded");
|
|
7271
|
+
if (value === null || typeof value === "boolean") return value;
|
|
7272
|
+
if (typeof value === "string") {
|
|
7273
|
+
budget.characters -= value.length;
|
|
7274
|
+
if (value.length > MODEL_CONVERSION_DIAGNOSTIC_LIMITS.string || budget.characters < 0) fail3("limit-exceeded");
|
|
7275
|
+
return value;
|
|
7276
|
+
}
|
|
7277
|
+
if (typeof value === "number" && Number.isFinite(value)) return value;
|
|
7278
|
+
if (Array.isArray(value)) {
|
|
7279
|
+
if (Object.getPrototypeOf(value) !== Array.prototype || value.length > 1024) fail3("limit-exceeded");
|
|
7280
|
+
if (Reflect.ownKeys(value).length !== value.length + 1) fail3();
|
|
7281
|
+
const result = [];
|
|
7282
|
+
for (let i = 0; i < value.length; i++) {
|
|
7283
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(i));
|
|
7284
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) fail3();
|
|
7285
|
+
result.push(snapshot3(descriptor.value, budget, depth + 1));
|
|
7286
|
+
}
|
|
7287
|
+
return Object.freeze(result);
|
|
7288
|
+
}
|
|
7289
|
+
const record2 = fields2(value);
|
|
7290
|
+
for (const key of Object.keys(record2)) {
|
|
7291
|
+
budget.characters -= key.length;
|
|
7292
|
+
if (budget.characters < 0) fail3("limit-exceeded");
|
|
7293
|
+
record2[key] = snapshot3(record2[key], budget, depth + 1);
|
|
7294
|
+
}
|
|
7295
|
+
return Object.freeze(record2);
|
|
7296
|
+
}
|
|
7297
|
+
function legacy(value) {
|
|
7298
|
+
return Object.freeze({ severity: value.severity, code: value.code, message: value.message });
|
|
7299
|
+
}
|
|
7300
|
+
async function qualifyModelConversionDiagnostics(input, options = {}) {
|
|
7301
|
+
let timer;
|
|
7302
|
+
let signal;
|
|
7303
|
+
let onAbort;
|
|
7304
|
+
try {
|
|
7305
|
+
const start = performance.now();
|
|
7306
|
+
const controls = fields2(options);
|
|
7307
|
+
only(controls, ["signal", "timeoutMs"]);
|
|
7308
|
+
const timeoutMs = controls.timeoutMs === void 0 ? 1e4 : controls.timeoutMs;
|
|
7309
|
+
if (typeof timeoutMs !== "number" || !Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > MODEL_CONVERSION_DIAGNOSTIC_LIMITS.timeoutMs) fail3();
|
|
7310
|
+
signal = controls.signal;
|
|
7311
|
+
const aborted = Object.getOwnPropertyDescriptor(AbortSignal.prototype, "aborted").get;
|
|
7312
|
+
const check = () => {
|
|
7313
|
+
if (signal !== void 0 && aborted.call(signal)) fail3("aborted");
|
|
7314
|
+
if (performance.now() - start >= timeoutMs) fail3("deadline-exceeded");
|
|
7315
|
+
};
|
|
7316
|
+
check();
|
|
7317
|
+
const args = fields2(snapshot3(input, { values: MODEL_CONVERSION_DIAGNOSTIC_LIMITS.values, characters: MODEL_CONVERSION_DIAGNOSTIC_LIMITS.characters }));
|
|
7318
|
+
only(args, ["outcome", "source", "report", "resources"]);
|
|
7319
|
+
if (!["completed", "unsupported", "failed"].includes(args.outcome)) fail3();
|
|
7320
|
+
const source = createModelProvenance(args.source);
|
|
7321
|
+
const reportInput = fields2(args.report);
|
|
7322
|
+
const maximumIssues = MODEL_CONVERSION_DIAGNOSTIC_LIMITS.issues - (args.outcome === "completed" ? 0 : 1);
|
|
7323
|
+
if (!Array.isArray(reportInput.issues) || reportInput.issues.length > maximumIssues) fail3("limit-exceeded");
|
|
7324
|
+
if (!Array.isArray(args.resources) || args.resources.length > MODEL_CONVERSION_DIAGNOSTIC_LIMITS.resources) fail3("limit-exceeded");
|
|
7325
|
+
const resources = /* @__PURE__ */ new Map();
|
|
7326
|
+
const identities = /* @__PURE__ */ new Map();
|
|
7327
|
+
for (const value of args.resources) {
|
|
7328
|
+
const binding = fields2(value);
|
|
7329
|
+
only(binding, ["path", "resource"]);
|
|
7330
|
+
if (typeof binding.path !== "string" || !binding.path.startsWith("/") || binding.path === "/" || resources.has(binding.path)) fail3();
|
|
7331
|
+
const resource = createModelResourceRef(binding.resource);
|
|
7332
|
+
const identity = JSON.stringify(resource);
|
|
7333
|
+
if (identities.has(resource.uri) && identities.get(resource.uri) !== identity) fail3();
|
|
7334
|
+
identities.set(resource.uri, identity);
|
|
7335
|
+
resources.set(binding.path, resource);
|
|
7336
|
+
}
|
|
7337
|
+
check();
|
|
7338
|
+
const interrupted = new Promise((_resolve, reject) => {
|
|
7339
|
+
timer = setTimeout(() => reject(new ModelConversionDiagnosticsError("deadline-exceeded")), Math.max(1, timeoutMs - (performance.now() - start)));
|
|
7340
|
+
onAbort = () => reject(new ModelConversionDiagnosticsError("aborted"));
|
|
7341
|
+
if (signal) AbortSignal.prototype.addEventListener.call(signal, "abort", onAbort, { once: true });
|
|
7342
|
+
});
|
|
7343
|
+
const core = await Promise.race([import("@plasius/gpu-model-core"), interrupted]);
|
|
7344
|
+
check();
|
|
7345
|
+
const report = core.evaluateGpuModelDiagnostics(reportInput);
|
|
7346
|
+
const diagnostics = report.diagnostics.map((diagnostic) => {
|
|
7347
|
+
const resource = resources.get(diagnostic.path);
|
|
7348
|
+
if (diagnostic.path !== "/" && !resource) fail3("unbound-resource");
|
|
7349
|
+
const base = resource ? { resource } : {};
|
|
7350
|
+
switch (diagnostic.kind) {
|
|
7351
|
+
case "warning":
|
|
7352
|
+
return Object.freeze({ ...base, severity: "warning", code: "conversion.warning", message: "Conversion completed with an advisory." });
|
|
7353
|
+
case "repair":
|
|
7354
|
+
return Object.freeze({ ...base, severity: "warning", code: "conversion.repair", message: "Conversion applied a canonical repair fallback.", fallback: diagnostic.ruleId });
|
|
7355
|
+
case "loss":
|
|
7356
|
+
return Object.freeze({ ...base, severity: reportInput.allowLoss === true ? "warning" : "blocking", code: `conversion.loss.${diagnostic.effect}`, message: diagnostic.effect === "dropped" ? "Conversion dropped source data." : "Conversion approximated source data.", effect: diagnostic.effect });
|
|
7357
|
+
case "unsupported":
|
|
7358
|
+
return Object.freeze({ ...base, severity: "blocking", code: "conversion.unsupported", message: "Conversion encountered unsupported data." });
|
|
7359
|
+
case "blocking-error":
|
|
7360
|
+
return Object.freeze({ ...base, severity: "blocking", code: "conversion.blocked", message: "Conversion did not satisfy canonical validation policy." });
|
|
7361
|
+
}
|
|
7362
|
+
});
|
|
7363
|
+
if (args.outcome !== "completed") diagnostics.push(Object.freeze({ severity: "blocking", code: args.outcome === "failed" ? "conversion.failed" : "conversion.unsupported", message: args.outcome === "failed" ? "Conversion failed." : "Conversion encountered unsupported data." }));
|
|
7364
|
+
const technicalAccepted = args.outcome === "completed" && report.accepted;
|
|
7365
|
+
const status = args.outcome === "failed" ? "failed" : args.outcome === "unsupported" || report.diagnostics.some((item) => item.kind === "unsupported") ? "unsupported" : !technicalAccepted ? "failed" : diagnostics.length ? "warning" : "succeeded";
|
|
7366
|
+
const losses = diagnostics.filter((item) => item.effect !== void 0).map(legacy);
|
|
7367
|
+
check();
|
|
7368
|
+
return Object.freeze({
|
|
7369
|
+
contractVersion: 1,
|
|
7370
|
+
status,
|
|
7371
|
+
technicalAccepted,
|
|
7372
|
+
standard: report.standard,
|
|
7373
|
+
mode: report.mode,
|
|
7374
|
+
source,
|
|
7375
|
+
diagnostics: Object.freeze(diagnostics),
|
|
7376
|
+
converter: Object.freeze({ diagnostics: Object.freeze(diagnostics.filter((item) => item.effect === void 0).map(legacy)), losses: Object.freeze(losses) })
|
|
7377
|
+
});
|
|
7378
|
+
} catch (error) {
|
|
7379
|
+
if (error instanceof ModelConversionDiagnosticsError) throw error;
|
|
7380
|
+
return fail3();
|
|
7381
|
+
} finally {
|
|
7382
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
7383
|
+
if (signal && onAbort) AbortSignal.prototype.removeEventListener.call(signal, "abort", onAbort);
|
|
7384
|
+
}
|
|
7385
|
+
}
|
|
7386
|
+
|
|
7054
7387
|
// src/index.ts
|
|
7055
7388
|
var ASSET_CONTRACTS_PACKAGE = "@plasius/asset-contracts";
|
|
7056
7389
|
var UNIFIED_ASSET_PIPELINE_FEATURE_FLAG_ID = "asset.pipeline.unified-ai-assets.enabled";
|
|
@@ -7839,6 +8172,7 @@ function assertRequiredString(value, fieldName) {
|
|
|
7839
8172
|
MODEL_CANDIDATE_HARD_GATE_KINDS,
|
|
7840
8173
|
MODEL_CONFIRMATION_VIEW_KINDS,
|
|
7841
8174
|
MODEL_CONFIRMATION_VIEW_SIZE_PX,
|
|
8175
|
+
MODEL_CONVERSION_DIAGNOSTIC_LIMITS,
|
|
7842
8176
|
MODEL_GENERATOR_DISABLED_REASON_CODE,
|
|
7843
8177
|
MODEL_MATCH_ASSURANCE_BANDS,
|
|
7844
8178
|
MODEL_MATCH_ASSURANCE_THRESHOLDS,
|
|
@@ -7854,8 +8188,11 @@ function assertRequiredString(value, fieldName) {
|
|
|
7854
8188
|
MODEL_RESOLUTION_V2_STATES,
|
|
7855
8189
|
MODEL_RESOURCE_MANIFEST_LIMITS,
|
|
7856
8190
|
MODEL_RIGHTS_STATUSES,
|
|
8191
|
+
MODEL_TEXTURE_RESOURCE_LIMITS,
|
|
7857
8192
|
MODEL_TEXT_ONLY_ASSURANCE_CEILING_REASON_CODE,
|
|
8193
|
+
ModelConversionDiagnosticsError,
|
|
7858
8194
|
ModelResourceManifestError,
|
|
8195
|
+
ModelTextureResourceError,
|
|
7859
8196
|
PVOX_ASSEMBLY_CLOSURE_HASH_DOMAIN,
|
|
7860
8197
|
PVOX_ASSET_MANIFEST_VERSION,
|
|
7861
8198
|
PVOX_BINARY_CLOSURE_HASH_DOMAIN,
|
|
@@ -8046,7 +8383,9 @@ function assertRequiredString(value, fieldName) {
|
|
|
8046
8383
|
normalizeAssetId,
|
|
8047
8384
|
normalizePvoxRootHeaderForHashV1,
|
|
8048
8385
|
projectPvoxNamedJsonClosureV1,
|
|
8386
|
+
qualifyModelConversionDiagnostics,
|
|
8049
8387
|
qualifyModelResourceManifest,
|
|
8388
|
+
qualifyModelTextureResources,
|
|
8050
8389
|
toLegacyModelResolutionState,
|
|
8051
8390
|
validateGpuAssetFiles
|
|
8052
8391
|
});
|