@forgeax/engine-preview 0.1.35 → 0.1.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/dist/vfx.mjs +2 -2
- package/dist/vfx.mjs.map +1 -1
- package/package.json +4 -4
package/dist/vfx.mjs
CHANGED
|
@@ -295,10 +295,10 @@ function inspectVfxSubject(input) {
|
|
|
295
295
|
}
|
|
296
296
|
const program = input.asset.program;
|
|
297
297
|
const programFingerprint = requiredString(input.asset.programFingerprint);
|
|
298
|
-
if (!isRecord2(program) || program.format !== "forgeax-vfx-program-
|
|
298
|
+
if (!isRecord2(program) || program.format !== "forgeax-vfx-program-4") {
|
|
299
299
|
return subjectFailure(
|
|
300
300
|
"resource-preview-subject-invalid",
|
|
301
|
-
"a cooked forgeax-vfx-program-
|
|
301
|
+
"a cooked forgeax-vfx-program-4 payload",
|
|
302
302
|
{
|
|
303
303
|
phase: "subject",
|
|
304
304
|
guid: input.guid,
|
package/dist/vfx.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/host/preview-host.ts","../src/domains/subject.ts","../src/evidence/oracle.ts","../src/kit/canonical.ts","../src/domains/vfx.ts","../src/host.ts","../src/vfx.ts"],"names":["defineToolPlugin","isRecord","authoredBounds"],"mappings":"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","file":"vfx.mjs","sourcesContent":["import { defineToolPlugin, type Plugin, type ToolPlugin } from '@forgeax/engine-plugin';\nimport {\n type ArtifactRef,\n defineToolCapability,\n type SnapshotRef,\n} from '@forgeax/engine-tool-runtime';\n\nexport interface PreviewAssetLoadResult<TAsset = unknown> {\n readonly ok: true;\n readonly value: TAsset;\n readonly digest?: string;\n readonly ownerFacts?: Readonly<Record<string, string | number | boolean>>;\n}\n\nexport interface PreviewAssetLoadFailure {\n readonly ok: false;\n readonly error: unknown;\n}\n\nexport interface PreviewAssetRegistry {\n readonly loadByGuid: <TAsset = unknown>(\n guid: string,\n ) => Promise<PreviewAssetLoadResult<TAsset> | PreviewAssetLoadFailure>;\n}\n\nexport interface PreviewRenderRuntime {\n readonly rendererReady: boolean;\n readonly worldReady: boolean;\n readonly drawCalls: number;\n readonly nonBlackPixels: number;\n /**\n * Facts read back from the real render/asset owner path. Domain executors\n * must not manufacture observed identity from the requested subject.\n */\n readonly observation?: Readonly<Record<string, string | number | boolean | readonly number[]>>;\n readonly vfx?: {\n readonly dispatches: number;\n readonly indirectDraws: number;\n readonly subjectOutputs: number;\n };\n readonly texture?: {\n readonly drawCalls: number;\n };\n}\n\nexport interface PreviewHostMechanisms {\n readonly runId: string;\n readonly snapshot: SnapshotRef;\n readonly projectRoot: string;\n readonly backend: 'webgpu';\n readonly signal: AbortSignal;\n readonly assets?: PreviewAssetRegistry;\n readonly renderer?: PreviewRenderRuntime;\n readonly artifacts?: readonly ArtifactRef[];\n}\n\nexport interface PreviewHost {\n readonly withSession: <T>(\n execute: (mechanisms: PreviewHostMechanisms) => Promise<T>,\n ) => Promise<T>;\n}\n\nexport const previewHostCapability = defineToolCapability<PreviewHost>('preview.host');\n\nexport function previewHostPlugin(host: PreviewHost): Plugin {\n return {\n name: 'forgeax-preview-host',\n provide: previewHostCapability.id,\n apply(ctx) {\n ctx.provide(previewHostCapability.id, host);\n },\n };\n}\n\nexport function bindPreviewHost(plugin: ToolPlugin, host: PreviewHost): ToolPlugin {\n return defineToolPlugin(previewHostPlugin(host), plugin.tools);\n}\n\nexport function createPreviewHost(input: PreviewHostMechanisms): PreviewHost {\n let active = true;\n return {\n async withSession(execute) {\n if (!active || input.signal.aborted) throw new Error('preview-host-session-terminal');\n try {\n return await execute(input);\n } finally {\n active = false;\n }\n },\n };\n}\n","import { defineToolPlugin } from '@forgeax/engine-plugin';\nimport type {\n JsonValue,\n ToolContribution,\n ToolDescriptor,\n ToolExecutionContext,\n ToolSchema,\n} from '@forgeax/engine-tool-runtime';\nimport { previewHostCapability } from '../host/preview-host.js';\nimport type { PreviewSubjectKind } from '../kit/presentation.js';\n\nexport interface ResourcePreviewArgs {\n readonly guid: string;\n /** Square screenshot edge in device pixels. Defaults to 512 and must be a power of two. */\n readonly size?: number;\n}\n\nexport const RESOURCE_PREVIEW_DEFAULT_SIZE = 512;\nexport const RESOURCE_PREVIEW_MIN_SIZE = 64;\nexport const RESOURCE_PREVIEW_MAX_SIZE = 4096;\n\nexport function isResourcePreviewSize(value: unknown): value is number {\n return (\n typeof value === 'number' &&\n Number.isSafeInteger(value) &&\n value >= RESOURCE_PREVIEW_MIN_SIZE &&\n value <= RESOURCE_PREVIEW_MAX_SIZE &&\n (value & (value - 1)) === 0\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n\n/** Keep the public result contract concrete at the ToolRuntime boundary. */\nfunction isResourcePreviewResult(value: unknown): boolean {\n if (!isRecord(value)) return false;\n const subject = value.subject;\n if (\n !isRecord(subject) ||\n !isString(subject.kind) ||\n !isString(subject.guid) ||\n !isString(subject.digest)\n )\n return false;\n if (!isRecord(value.presentation) || !isString(value.presentation.kind)) return false;\n if (\n !isRecord(value.recipe) ||\n !isString(value.recipe.schemaVersion) ||\n !isString(value.recipe.recipeDigest)\n )\n return false;\n if (!isRecord(value.oracle) || !isString(value.oracle.status)) return false;\n return Array.isArray(value.artifacts);\n}\n\nexport const resourcePreviewResultSchema: ToolSchema<unknown> = {\n parse(value) {\n return isResourcePreviewResult(value)\n ? { ok: true, value }\n : {\n ok: false,\n error:\n 'resource preview result must include subject, presentation, recipe, oracle, and artifacts',\n };\n },\n describe: '{\"type\":\"object\",\"required\":[\"subject\",\"presentation\",\"recipe\",\"oracle\",\"artifacts\"]}',\n};\n\nexport const resourcePreviewArgsSchema: ToolSchema<ResourcePreviewArgs> = {\n parse(value) {\n if (\n value === null ||\n typeof value !== 'object' ||\n typeof Reflect.get(value, 'guid') !== 'string'\n ) {\n return { ok: false, error: 'expected { guid: string }' };\n }\n const guid = Reflect.get(value, 'guid');\n if (guid.length === 0) return { ok: false, error: 'guid must not be empty' };\n const size = Reflect.get(value, 'size');\n if (size === undefined) return { ok: true, value: { guid } };\n return isResourcePreviewSize(size)\n ? { ok: true, value: { guid, size } }\n : {\n ok: false,\n error: `size must be a power of two between ${RESOURCE_PREVIEW_MIN_SIZE} and ${RESOURCE_PREVIEW_MAX_SIZE}`,\n };\n },\n describe: `{\"type\":\"object\",\"required\":[\"guid\"],\"properties\":{\"guid\":{\"type\":\"string\"},\"size\":{\"type\":\"integer\",\"minimum\":${RESOURCE_PREVIEW_MIN_SIZE},\"maximum\":${RESOURCE_PREVIEW_MAX_SIZE},\"description\":\"square power-of-two screenshot edge; defaults to ${RESOURCE_PREVIEW_DEFAULT_SIZE}\"}}}`,\n};\n\nexport function subjectDescriptor(\n kind: PreviewSubjectKind,\n): ToolDescriptor<ResourcePreviewArgs, unknown> {\n return {\n id: `${kind}.preview`,\n title: `Preview ${kind}`,\n summary: `Preview one ${kind} asset in the Engine-owned resource host.`,\n realm: 'host',\n argsSchema: resourcePreviewArgsSchema,\n resultSchema: resourcePreviewResultSchema,\n evidence: ['rhi-tape', 'profile-capture', 'png'],\n };\n}\n\nexport type SubjectExecutor = (args: ResourcePreviewArgs, context: ToolExecutionContext) => unknown;\n\nexport interface ResourceSubjectFailure {\n readonly ok: false;\n readonly error: {\n readonly code:\n | 'resource-preview-subject-invalid'\n | 'resource-preview-kind-mismatch'\n | 'resource-preview-oracle-failed';\n readonly expected: string;\n readonly hint: string;\n readonly detail: Readonly<Record<string, JsonValue>>;\n };\n}\n\nexport function subjectFailure(\n code: ResourceSubjectFailure['error']['code'],\n expected: string,\n detail: Readonly<Record<string, JsonValue>>,\n): ResourceSubjectFailure {\n return {\n ok: false,\n error: {\n code,\n expected,\n hint: 'Load the requested GUID through AssetRegistry.loadByGuid and repair the owner facts before retrying.',\n detail,\n },\n };\n}\n\nexport function assetLoadFailure(\n expected: string,\n runId: string,\n error: unknown,\n): ResourceSubjectFailure {\n const owner = isRecord(error) ? error : undefined;\n const ownerCode = typeof owner?.code === 'string' ? owner.code : undefined;\n const ownerExpected = typeof owner?.expected === 'string' ? owner.expected : undefined;\n const ownerHint = typeof owner?.hint === 'string' ? owner.hint : undefined;\n const ownerDetail = owner?.detail;\n return subjectFailure('resource-preview-subject-invalid', expected, {\n phase: 'asset-load',\n runId,\n ...(ownerCode === undefined ? {} : { ownerCode }),\n ...(ownerExpected === undefined ? {} : { ownerExpected }),\n ...(ownerHint === undefined ? {} : { ownerHint }),\n ...(ownerDetail === undefined ? {} : { ownerDetail: toJsonValue(ownerDetail) }),\n });\n}\n\nfunction toJsonValue(value: unknown): JsonValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return value;\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (Array.isArray(value)) return value.map((entry) => toJsonValue(entry));\n if (isRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [key, toJsonValue(entry)]),\n );\n }\n return String(value);\n}\n\nexport function nativePreviewPlugin(\n kind: PreviewSubjectKind,\n contribution: ToolContribution<ResourcePreviewArgs, unknown>,\n) {\n return defineToolPlugin({ name: `forgeax-preview-${kind}`, apply() {} }, [\n contribution as ToolContribution<unknown, unknown>,\n ]);\n}\n\nexport async function failUnboundSubject(\n kind: PreviewSubjectKind,\n args: ResourcePreviewArgs,\n context: ToolExecutionContext,\n): Promise<unknown> {\n const host = context.require(previewHostCapability);\n if (!host.ok) return host;\n return host.value.withSession(async (mechanisms) => ({\n ...subjectFailure(\n 'resource-preview-subject-invalid',\n `${kind} asset ${args.guid} to be bound by its owner before rendering`,\n { phase: 'subject-binding', runId: mechanisms.runId },\n ),\n }));\n}\n","export type PreviewOracleStatus = PreviewOracle['status'];\n\nexport type PreviewOracle =\n | {\n readonly status: 'passed';\n readonly subjectBound: true;\n readonly drawCalls: number;\n readonly dispatches: number;\n readonly rendererHealthy: true;\n readonly detail: Record<string, string | number | boolean>;\n }\n | {\n readonly status: 'failed';\n readonly subjectBound: false;\n readonly drawCalls: number;\n readonly dispatches: number;\n readonly rendererHealthy: boolean;\n readonly detail: Record<string, string | number | boolean>;\n };\n\nexport function passedPreviewOracle(input: {\n readonly drawCalls: number;\n readonly dispatches?: number;\n readonly detail: Record<string, string | number | boolean>;\n}): PreviewOracle {\n return {\n status: 'passed',\n subjectBound: true,\n drawCalls: input.drawCalls,\n dispatches: input.dispatches ?? 0,\n rendererHealthy: true,\n detail: { ...input.detail },\n };\n}\n\nexport function failedPreviewOracle(input: {\n readonly drawCalls?: number;\n readonly dispatches?: number;\n readonly rendererHealthy?: boolean;\n readonly detail: Record<string, string | number | boolean>;\n}): PreviewOracle {\n return {\n status: 'failed',\n subjectBound: false,\n drawCalls: input.drawCalls ?? 0,\n dispatches: input.dispatches ?? 0,\n rendererHealthy: input.rendererHealthy ?? false,\n detail: { ...input.detail },\n };\n}\n\nexport interface MaterialOracleInput {\n readonly requested: {\n readonly subjectDigest: string;\n readonly program: string;\n readonly pass: string;\n readonly bindingsDigest: string;\n readonly closureDigest: string;\n };\n readonly observed: MaterialOracleInput['requested'] & {\n readonly rendererHealthy: boolean;\n readonly drawCalls: number;\n readonly nonBlackPixels: number;\n };\n}\n\nexport interface MeshOracleInput {\n readonly requested: {\n readonly subjectDigest: string;\n readonly vertexDigest: string;\n readonly indexDigest: string;\n readonly submeshDigest: string;\n readonly aabbDigest: string;\n readonly aabb?: readonly [number, number, number, number, number, number];\n readonly submeshCount?: number;\n readonly materialSlotCount?: number;\n };\n readonly observed: MeshOracleInput['requested'] & {\n readonly rendererHealthy: boolean;\n readonly drawCalls: number;\n readonly nonBlackPixels: number;\n };\n}\n\nfunction oracleDetail(\n kind: 'material' | 'mesh',\n requested: Record<string, unknown>,\n observed: Record<string, unknown>,\n mismatch: string | undefined,\n): Record<string, string | number | boolean> {\n return {\n kind,\n mismatch: mismatch ?? 'none',\n requestedSubjectDigest:\n typeof requested.subjectDigest === 'string' ? requested.subjectDigest : 'unknown',\n observedSubjectDigest:\n typeof observed.subjectDigest === 'string' ? observed.subjectDigest : 'unknown',\n requestedOwnerDigest: JSON.stringify(requested),\n observedOwnerDigest: JSON.stringify(observed),\n };\n}\n\nfunction firstMismatch(\n requested: Record<string, unknown>,\n observed: Record<string, unknown>,\n): string | undefined {\n for (const key of Object.keys(requested)) {\n const requestedValue = requested[key];\n const observedValue = observed[key];\n if (\n Array.isArray(requestedValue) ||\n Array.isArray(observedValue) ||\n typeof requestedValue === 'object' ||\n typeof observedValue === 'object'\n ) {\n if (JSON.stringify(requestedValue) !== JSON.stringify(observedValue)) return key;\n } else if (requestedValue !== observedValue) {\n return key;\n }\n }\n return undefined;\n}\n\nexport function evaluateMaterialOracle(input: MaterialOracleInput): PreviewOracle {\n const requested = input.requested as unknown as Record<string, string>;\n const observed = input.observed as unknown as Record<string, string>;\n const mismatch = firstMismatch(requested, observed);\n const healthy = input.observed.rendererHealthy && input.observed.drawCalls > 0;\n const detail = oracleDetail('material', requested, observed, mismatch);\n if (mismatch !== undefined || !healthy) {\n return failedPreviewOracle({\n drawCalls: input.observed.drawCalls,\n rendererHealthy: input.observed.rendererHealthy,\n detail: { ...detail, rendererHealthy: input.observed.rendererHealthy },\n });\n }\n return passedPreviewOracle({\n drawCalls: input.observed.drawCalls,\n detail: { ...detail, rendererHealthy: true },\n });\n}\n\nexport function evaluateMeshOracle(input: MeshOracleInput): PreviewOracle {\n const requested = input.requested as unknown as Record<string, string>;\n const observed = input.observed as unknown as Record<string, string>;\n const mismatch = firstMismatch(requested, observed);\n const healthy = input.observed.rendererHealthy && input.observed.drawCalls > 0;\n const detail = oracleDetail('mesh', requested, observed, mismatch);\n if (mismatch !== undefined || !healthy) {\n return failedPreviewOracle({\n drawCalls: input.observed.drawCalls,\n rendererHealthy: input.observed.rendererHealthy,\n detail: { ...detail, rendererHealthy: input.observed.rendererHealthy },\n });\n }\n return passedPreviewOracle({\n drawCalls: input.observed.drawCalls,\n detail: { ...detail, rendererHealthy: true },\n });\n}\n\nexport interface VfxOracleInput {\n readonly requested: {\n readonly subjectDigest: string;\n readonly programFingerprint: string;\n readonly emitterDigest: string;\n readonly sampleDigest: string;\n readonly boundsDigest: string;\n readonly computeDigest: string;\n readonly indirectDigest: string;\n readonly contactSheetDigest?: string;\n readonly authoredBounds?: readonly [number, number, number, number, number, number];\n readonly seed?: number;\n readonly fixedDelta?: number;\n readonly timelineFrames?: number;\n };\n readonly observed: VfxOracleInput['requested'] & {\n readonly rendererHealthy: boolean;\n readonly dispatches: number;\n readonly indirectDraws: number;\n readonly subjectOutputs: number;\n readonly nonBlackPixels: number;\n };\n}\n\nexport interface TextureOracleInput {\n readonly requested: {\n readonly subjectDigest: string;\n readonly boundDigest: string;\n readonly dimensions: readonly [number, number];\n readonly format: string;\n readonly colorSpace: string;\n readonly mipCount: number;\n readonly uvDigest: string;\n readonly filter: string;\n readonly bindingDigest: string;\n };\n readonly observed: TextureOracleInput['requested'] & {\n readonly rendererHealthy: boolean;\n readonly drawCalls: number;\n readonly nonBlackPixels: number;\n readonly payloadClass: 'black' | 'transparent' | 'single-channel' | 'color';\n };\n}\n\nfunction identityRecord(input: Record<string, unknown>): Record<string, string> {\n return Object.fromEntries(\n Object.entries(input).map(([key, value]) => [\n key,\n Array.isArray(value) ? JSON.stringify(value) : String(value),\n ]),\n );\n}\n\nfunction evaluateIdentityOracle(\n kind: 'vfx' | 'texture',\n requestedInput: Record<string, unknown>,\n observedInput: Record<string, unknown>,\n healthy: boolean,\n drawCalls: number,\n dispatches: number,\n detailOverrides: Record<string, string | number | boolean>,\n): PreviewOracle {\n const requested = identityRecord(requestedInput);\n const observed = identityRecord(observedInput);\n const mismatch = firstMismatch(requested, observed);\n const detail = {\n kind,\n mismatch: mismatch ?? 'none',\n requestedSubjectDigest: requested.subjectDigest ?? 'unknown',\n observedSubjectDigest: observed.subjectDigest ?? 'unknown',\n requestedOwnerDigest: JSON.stringify(requested),\n observedOwnerDigest: JSON.stringify(observed),\n ...detailOverrides,\n };\n if (mismatch !== undefined || !healthy) {\n return failedPreviewOracle({ drawCalls, dispatches, rendererHealthy: healthy, detail });\n }\n return passedPreviewOracle({ drawCalls, dispatches, detail });\n}\n\nexport function evaluateVfxOracle(input: VfxOracleInput): PreviewOracle {\n const observed = input.observed;\n const healthy =\n observed.rendererHealthy &&\n observed.dispatches > 0 &&\n observed.indirectDraws > 0 &&\n observed.subjectOutputs > 0;\n return evaluateIdentityOracle(\n 'vfx',\n input.requested,\n input.observed,\n healthy,\n observed.indirectDraws,\n observed.dispatches,\n {\n rendererHealthy: observed.rendererHealthy,\n indirectDraws: observed.indirectDraws,\n subjectOutputs: observed.subjectOutputs,\n nonBlackPixels: observed.nonBlackPixels,\n },\n );\n}\n\nexport function evaluateTextureOracle(input: TextureOracleInput): PreviewOracle {\n const observed = input.observed;\n return evaluateIdentityOracle(\n 'texture',\n input.requested,\n input.observed,\n observed.rendererHealthy && observed.drawCalls > 0,\n observed.drawCalls,\n 0,\n {\n rendererHealthy: observed.rendererHealthy,\n payloadClass: observed.payloadClass,\n nonBlackPixels: observed.nonBlackPixels,\n },\n );\n}\n","import type { PreviewPresentation, PreviewSubjectKind } from './presentation.js';\n\nexport interface CanonicalPreviewRecipe {\n readonly schemaVersion: '1.0.0';\n readonly rig:\n | Extract<PreviewPresentation, { readonly kind: 'lit-asset' }>['geometry']\n | 'asset-quad';\n readonly environment: 'engine-canonical' | 'black';\n readonly skybox: 'engine-canonical' | 'none';\n readonly skylight: 'engine-canonical' | 'none';\n readonly directionalLight: 'engine-canonical' | 'none';\n readonly stage: 'neutral-material-checker-unlit' | 'texture-unlit-black';\n readonly camera: 'bounds-derived' | 'texture-orthographic';\n readonly recipeDigest: string;\n}\n\nexport function createCanonicalPreviewRecipe(kind: PreviewSubjectKind): CanonicalPreviewRecipe {\n const texture = kind === 'texture';\n return {\n schemaVersion: '1.0.0',\n rig: kind === 'mesh' ? 'asset-mesh' : texture ? 'asset-quad' : 'handle-sphere',\n environment: texture ? 'black' : 'engine-canonical',\n skybox: texture ? 'none' : 'engine-canonical',\n skylight: texture ? 'none' : 'engine-canonical',\n directionalLight: texture ? 'none' : 'engine-canonical',\n stage: texture ? 'texture-unlit-black' : 'neutral-material-checker-unlit',\n camera: texture ? 'texture-orthographic' : 'bounds-derived',\n recipeDigest: `canonical:${kind}:${texture ? 'texture-orthographic' : 'bounds-derived'}`,\n };\n}\n\nexport function canonicalPresentation(kind: PreviewSubjectKind): PreviewPresentation {\n if (kind === 'texture') {\n return {\n kind: 'texture-unlit',\n geometry: 'aspect-quad',\n checkerboard: 'linear-alpha',\n };\n }\n return {\n kind: 'lit-asset',\n geometry: kind === 'mesh' ? 'asset-mesh' : 'handle-sphere',\n skylight: 'engine-canonical',\n directionalLight: 'engine-canonical',\n skybox: 'engine-canonical',\n };\n}\n","import type { ArtifactRef } from '@forgeax/engine-tool-runtime';\nimport { evaluateVfxOracle, type VfxOracleInput } from '../evidence/oracle.js';\nimport type { PreviewAssetRegistry, PreviewRenderRuntime } from '../host/preview-host.js';\nimport { canonicalPresentation, createCanonicalPreviewRecipe } from '../kit/canonical.js';\nimport { assetLoadFailure, type ResourcePreviewArgs, subjectFailure } from './subject.js';\n\nexport interface VfxSubjectInspection {\n readonly subjectDigest: string;\n readonly programFingerprint: string;\n readonly emitterDigest: string;\n readonly sampleDigest: string;\n readonly boundsDigest: string;\n readonly computeDigest: string;\n readonly indirectDigest: string;\n readonly contactSheetDigest?: string;\n readonly authoredBounds: readonly [number, number, number, number, number, number];\n}\n\ntype InspectionResult =\n | { readonly ok: true; readonly value: VfxSubjectInspection }\n | ReturnType<typeof subjectFailure>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction requiredString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction finiteVector(value: unknown, length: number): number[] | undefined {\n if (\n !Array.isArray(value) ||\n value.length !== length ||\n value.some((entry) => typeof entry !== 'number' || !Number.isFinite(entry))\n )\n return undefined;\n return value;\n}\n\nfunction authoredBounds(\n emitters: readonly Record<string, unknown>[],\n): readonly [number, number, number, number, number, number] | undefined {\n let minX = Infinity;\n let minY = Infinity;\n let minZ = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let maxZ = -Infinity;\n for (const emitter of emitters) {\n const bounds = emitter.bounds;\n if (!isRecord(bounds) || typeof bounds.kind !== 'string') return undefined;\n if (bounds.kind === 'sphere') {\n const center = finiteVector(bounds.center, 3);\n const radius = bounds.radius;\n if (\n center === undefined ||\n typeof radius !== 'number' ||\n !Number.isFinite(radius) ||\n radius < 0\n )\n return undefined;\n const [x, y, z] = center;\n if (x === undefined || y === undefined || z === undefined) return undefined;\n minX = Math.min(minX, x - radius);\n minY = Math.min(minY, y - radius);\n minZ = Math.min(minZ, z - radius);\n maxX = Math.max(maxX, x + radius);\n maxY = Math.max(maxY, y + radius);\n maxZ = Math.max(maxZ, z + radius);\n continue;\n }\n if (bounds.kind === 'aabb') {\n const min = finiteVector(bounds.min, 3);\n const max = finiteVector(bounds.max, 3);\n if (\n min === undefined ||\n max === undefined ||\n min.some((entry, index) => entry > (max[index] ?? entry))\n )\n return undefined;\n const [loX, loY, loZ] = min;\n const [hiX, hiY, hiZ] = max;\n if (\n loX === undefined ||\n loY === undefined ||\n loZ === undefined ||\n hiX === undefined ||\n hiY === undefined ||\n hiZ === undefined\n )\n return undefined;\n minX = Math.min(minX, loX);\n minY = Math.min(minY, loY);\n minZ = Math.min(minZ, loZ);\n maxX = Math.max(maxX, hiX);\n maxY = Math.max(maxY, hiY);\n maxZ = Math.max(maxZ, hiZ);\n continue;\n }\n return undefined;\n }\n if (![minX, minY, minZ, maxX, maxY, maxZ].every(Number.isFinite)) return undefined;\n return [minX, minY, minZ, maxX, maxY, maxZ];\n}\n\nfunction jsonDigest(value: unknown): string | undefined {\n const encoded = JSON.stringify(value);\n return typeof encoded === 'string' && encoded.length > 0 ? encoded : undefined;\n}\n\nexport function inspectVfxSubject(input: {\n readonly guid: string;\n readonly asset: unknown;\n readonly digest?: string;\n readonly ownerFacts?: Readonly<Record<string, string | number | boolean>>;\n}): InspectionResult {\n if (!isRecord(input.asset) || input.asset.kind !== 'particle-effect') {\n return subjectFailure(\n 'resource-preview-kind-mismatch',\n 'a ParticleEffectAsset with kind particle-effect',\n {\n phase: 'subject',\n guid: input.guid,\n actualKind:\n isRecord(input.asset) && typeof input.asset.kind === 'string'\n ? input.asset.kind\n : 'unknown',\n },\n );\n }\n if (input.asset.schemaVersion !== 3) {\n return subjectFailure('resource-preview-subject-invalid', 'a schema-v3 ParticleEffectAsset', {\n phase: 'subject',\n guid: input.guid,\n field: 'schemaVersion',\n });\n }\n const program = input.asset.program;\n const programFingerprint = requiredString(input.asset.programFingerprint);\n if (!isRecord(program) || program.format !== 'forgeax-vfx-program-3') {\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'a cooked forgeax-vfx-program-3 payload',\n {\n phase: 'subject',\n guid: input.guid,\n field: 'program',\n },\n );\n }\n if (\n programFingerprint === undefined ||\n requiredString(program.fingerprint) !== programFingerprint\n ) {\n return subjectFailure('resource-preview-subject-invalid', 'non-empty authored VFX bounds', {\n phase: 'subject',\n guid: input.guid,\n field: 'programFingerprint',\n });\n }\n const rawEmitters = Array.isArray(program.emitters) ? program.emitters : [];\n const emitters = rawEmitters.filter(isRecord);\n const definitions = Array.isArray(input.asset.emitters)\n ? input.asset.emitters.filter(isRecord)\n : [];\n if (\n emitters.length === 0 ||\n emitters.length !== rawEmitters.length ||\n definitions.length !== emitters.length\n ) {\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'the ParticleEffectAsset to publish matching cooked emitter definitions',\n { phase: 'subject', guid: input.guid, field: 'emitters' },\n );\n }\n for (const [index, emitter] of emitters.entries()) {\n const id = requiredString(emitter.id);\n const module = requiredString(emitter.module);\n const capacity = emitter.capacity;\n const backend = emitter.backend;\n const renderers = emitter.renderers;\n if (\n id === undefined ||\n module === undefined ||\n typeof capacity !== 'number' ||\n !Number.isSafeInteger(capacity) ||\n capacity <= 0 ||\n !isRecord(backend) ||\n backend.required !== 'gpu' ||\n !isRecord(emitter.schedule) ||\n !Array.isArray(renderers) ||\n !isRecord(definitions[index]) ||\n definitions[index].id !== id ||\n definitions[index].capacity !== capacity\n ) {\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'each cooked emitter to match its ParticleEffectAsset definition',\n { phase: 'subject', guid: input.guid, field: `emitters[${index}]` },\n );\n }\n }\n const bounds = authoredBounds(emitters);\n if (bounds === undefined) {\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'finite authored VFX emitter bounds',\n {\n phase: 'subject',\n guid: input.guid,\n field: 'program.emitters[].bounds',\n },\n );\n }\n const emitterDigest = jsonDigest(\n emitters.map(({ id, module, capacity }) => ({ id, module, capacity })),\n );\n const sampleDigest = jsonDigest(emitters.map(({ id, schedule }) => ({ id, schedule })));\n const boundsDigest = jsonDigest(\n emitters.map(({ id, bounds: emitterBounds }) => ({ id, bounds: emitterBounds })),\n );\n const indirectDigest = jsonDigest(\n emitters.map(({ id, renderers }) => ({\n id,\n renderers: (renderers as readonly unknown[]).filter(isRecord).map((renderer) => ({\n kind: renderer.kind,\n enabled: renderer.enabled ?? true,\n })),\n })),\n );\n if (\n emitterDigest === undefined ||\n sampleDigest === undefined ||\n boundsDigest === undefined ||\n indirectDigest === undefined\n ) {\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'the cooked VFX program to publish stable emitter, schedule, bounds, and renderer facts',\n { phase: 'subject', guid: input.guid, field: 'program.emitters' },\n );\n }\n const ownerFacts = isRecord(input.asset.ownerFacts) ? input.asset.ownerFacts : input.ownerFacts;\n const subjectDigest =\n requiredString(input.asset.digest) ??\n requiredString(input.digest) ??\n requiredString(ownerFacts?.subjectDigest) ??\n programFingerprint;\n const contactSheetDigest = requiredString(ownerFacts?.contactSheetDigest);\n return {\n ok: true,\n value: {\n subjectDigest,\n programFingerprint,\n emitterDigest,\n sampleDigest,\n boundsDigest,\n computeDigest: programFingerprint,\n indirectDigest,\n ...(contactSheetDigest === undefined ? {} : { contactSheetDigest }),\n authoredBounds: bounds,\n },\n };\n}\n\nexport async function executeVfxPreview(\n args: ResourcePreviewArgs,\n input: {\n readonly assets?: PreviewAssetRegistry;\n readonly renderer?: PreviewRenderRuntime;\n readonly runId: string;\n readonly artifacts?: readonly ArtifactRef[];\n },\n) {\n if (input.assets === undefined)\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'the existing AssetRegistry capability',\n {\n phase: 'asset-registry',\n runId: input.runId,\n },\n );\n const loaded = await input.assets.loadByGuid<Record<string, unknown>>(args.guid);\n if (!loaded.ok)\n return assetLoadFailure(\n 'AssetRegistry.loadByGuid to resolve the VFX',\n input.runId,\n loaded.error,\n );\n const inspected = inspectVfxSubject({\n guid: args.guid,\n asset: loaded.value,\n ...(loaded.digest === undefined ? {} : { digest: loaded.digest }),\n ...(loaded.ownerFacts === undefined ? {} : { ownerFacts: loaded.ownerFacts }),\n });\n if (!inspected.ok) return inspected;\n const renderer = input.renderer;\n const runtime = input.renderer?.vfx;\n if (\n renderer?.rendererReady !== true ||\n renderer.worldReady !== true ||\n runtime === undefined ||\n renderer.observation === undefined\n ) {\n return subjectFailure(\n 'resource-preview-oracle-failed',\n 'shared World, Renderer, and VFX compute runtime',\n {\n phase: 'renderer',\n runId: input.runId,\n },\n );\n }\n const observation = renderer.observation;\n const observedString = (field: string): string =>\n typeof observation[field] === 'string' ? (observation[field] as string) : '';\n const authoredBounds = observation.authoredBounds;\n const seed = observation.seed;\n const fixedDelta = observation.fixedDelta;\n const timelineFrames = observation.timelineFrames;\n if (\n !Array.isArray(authoredBounds) ||\n authoredBounds.length !== 6 ||\n authoredBounds.some((value) => typeof value !== 'number' || !Number.isFinite(value)) ||\n typeof seed !== 'number' ||\n typeof fixedDelta !== 'number' ||\n typeof timelineFrames !== 'number' ||\n !Number.isInteger(timelineFrames) ||\n timelineFrames <= 0 ||\n !Number.isFinite(seed) ||\n !Number.isFinite(fixedDelta) ||\n fixedDelta <= 0\n ) {\n return subjectFailure(\n 'resource-preview-oracle-failed',\n 'the VFX render observation to include authored bounds and timeline facts',\n { phase: 'renderer-observation', runId: input.runId },\n );\n }\n const observed: VfxOracleInput['observed'] = {\n ...inspected.value,\n subjectDigest: observedString('subjectDigest'),\n programFingerprint: observedString('programFingerprint'),\n emitterDigest: observedString('emitterDigest'),\n sampleDigest: observedString('sampleDigest'),\n boundsDigest: observedString('boundsDigest'),\n computeDigest: observedString('computeDigest'),\n indirectDigest: observedString('indirectDigest'),\n ...(observedString('contactSheetDigest') === ''\n ? {}\n : { contactSheetDigest: observedString('contactSheetDigest') }),\n authoredBounds: authoredBounds as unknown as readonly [\n number,\n number,\n number,\n number,\n number,\n number,\n ],\n seed,\n fixedDelta,\n timelineFrames,\n rendererHealthy: renderer.rendererReady && renderer.worldReady,\n dispatches: runtime.dispatches,\n indirectDraws: runtime.indirectDraws,\n subjectOutputs: runtime.subjectOutputs,\n nonBlackPixels: renderer.nonBlackPixels,\n };\n const oracle = evaluateVfxOracle({ requested: inspected.value, observed });\n if (oracle.status !== 'passed') {\n return subjectFailure(\n 'resource-preview-oracle-failed',\n 'the VFX compute and indirect observation to match the loaded owner facts',\n { phase: 'oracle', runId: input.runId, ...oracle.detail },\n );\n }\n return {\n ok: true as const,\n value: {\n subject: { kind: 'vfx' as const, guid: args.guid, digest: inspected.value.subjectDigest },\n presentation: canonicalPresentation('vfx'),\n recipe: createCanonicalPreviewRecipe('vfx'),\n authoredBounds: inspected.value.authoredBounds,\n timeline: {\n seed,\n fixedDelta,\n frames: timelineFrames,\n },\n oracle,\n artifacts: input.artifacts ?? [],\n },\n artifacts: input.artifacts ?? [],\n };\n}\n","import type {\n ArtifactRef,\n JsonValue,\n SnapshotRef,\n ToolDomainFailure,\n ToolEvidenceKind,\n ToolExecutionContext,\n ToolSubjectRef,\n} from '@forgeax/engine-tool-runtime';\nimport {\n createPreviewHost as createNativePreviewHost,\n type PreviewHost as NativePreviewHost,\n type PreviewHostMechanisms,\n} from './host/preview-host.js';\n\nexport interface PreviewHostRequest {\n readonly subject: ToolSubjectRef;\n readonly snapshot: SnapshotRef;\n}\n\nexport interface PreviewAssetBinding {\n readonly guid: string;\n readonly bytes: number;\n}\n\nexport interface PreviewFrameInput {\n readonly frame: number;\n readonly deltaSeconds: number;\n}\n\nexport interface PreviewCapture {\n readonly digest: string;\n readonly bytes: number;\n}\n\nexport interface PreviewResourceCensus {\n readonly worlds: number;\n readonly renderers: number;\n readonly canvases: number;\n readonly leases: number;\n}\n\nexport interface PreviewCleanupReport {\n readonly census: PreviewResourceCensus;\n readonly failures: readonly string[];\n}\n\n/**\n * The only resource surface exposed to a preview contribution. The adapter owns\n * the actual Engine resources; callers receive POD bindings and bounded actions.\n */\nexport interface PreviewHostSession {\n readonly subject: ToolSubjectRef;\n readonly snapshot: SnapshotRef;\n readonly loadAsset: (guid: string) => Promise<PreviewAssetBinding>;\n readonly frame: (input: PreviewFrameInput) => Promise<void>;\n readonly capture: () => Promise<PreviewCapture & { readonly artifact?: ArtifactRef }>;\n readonly census: () => PreviewResourceCensus;\n readonly dispose: () => Promise<void>;\n}\n\nexport interface PreviewHostAdapter {\n readonly open: (request: PreviewHostRequest) => PreviewHostSession | Promise<PreviewHostSession>;\n}\n\nexport interface PreviewHost {\n readonly withSession: <TResult>(\n request: PreviewHostRequest,\n run: (session: PreviewHostSession) => TResult | Promise<TResult>,\n ) => Promise<{ readonly value: TResult; readonly cleanup: PreviewCleanupReport }>;\n}\n\nexport interface PreviewDomainValue<TReport = unknown> {\n readonly subject: ToolSubjectRef;\n readonly snapshot: SnapshotRef;\n readonly report: TReport;\n readonly artifacts: readonly ArtifactRef[];\n}\n\nexport type PreviewDomainResult<TReport = unknown> =\n | { readonly ok: true; readonly value: PreviewDomainValue<TReport> }\n | { readonly ok: false; readonly error: ToolDomainFailure };\n\nexport type PreviewDomainRunner<TRequest, TReport = unknown> = (\n request: TRequest,\n context: ToolExecutionContext,\n) => Promise<PreviewDomainResult<TReport>>;\n\nexport const REQUIRED_PREVIEW_EVIDENCE: readonly ToolEvidenceKind[] = [\n 'rhi-tape',\n 'png',\n 'profile-capture',\n];\n\nexport function domainFailure(\n code: string,\n expected: string,\n hint: string,\n detail: Record<string, JsonValue>,\n): { readonly ok: false; readonly error: ToolDomainFailure } {\n return { ok: false, error: { code, expected, hint, detail } };\n}\n\n/**\n * The default contribution is deliberately fail-closed. A real Project GUID\n * loader must install a PreviewHost/Browser/Dawn runner; a data-only request\n * must never manufacture PNG, RHI, or profile references from its arguments.\n */\nexport function previewRuntimeUnavailable(\n subject: ToolSubjectRef,\n snapshot: SnapshotRef,\n domain: string,\n): { readonly ok: false; readonly error: ToolDomainFailure } {\n return domainFailure(\n 'preview-runtime-unavailable',\n 'a Project GUID cold-load and an active PreviewHost/Browser/Dawn runner',\n 'Install the Project preview provider and retry; no synthetic artifact is published.',\n {\n domain,\n subjectKind: subject.kind,\n subjectGuid: subject.guid,\n snapshotRevision: snapshot.revision,\n snapshotDigest: snapshot.digest,\n requiredEvidence: REQUIRED_PREVIEW_EVIDENCE as unknown as JsonValue,\n },\n );\n}\n\nexport function validateDomainValue<TReport>(\n value: PreviewDomainValue<TReport>,\n request: PreviewHostRequest,\n): PreviewDomainResult<TReport> {\n if (\n value.subject.kind !== request.subject.kind ||\n value.subject.guid !== request.subject.guid ||\n value.snapshot.revision !== request.snapshot.revision ||\n value.snapshot.digest !== request.snapshot.digest\n ) {\n return domainFailure(\n 'preview-subject-identity-mismatch',\n 'the terminal subject and snapshot to match the request',\n 'Repair the domain producer so evidence remains bound to the requested subject.',\n {\n requestGuid: request.subject.guid,\n resultGuid: value.subject.guid,\n requestSnapshot: request.snapshot.digest,\n resultSnapshot: value.snapshot.digest,\n },\n );\n }\n const kinds = new Set(value.artifacts.map((artifact) => artifact.kind));\n const missing = REQUIRED_PREVIEW_EVIDENCE.filter((kind) => !kinds.has(kind));\n if (missing.length > 0) {\n return domainFailure(\n 'preview-evidence-incomplete',\n 'one subject-bound artifact for each required evidence kind',\n 'Repair the RHI, PNG, and profile producers before retrying.',\n { missing: missing as unknown as JsonValue },\n );\n }\n return { ok: true, value };\n}\n\nexport class PreviewCleanupError extends Error {\n readonly code = 'preview-cleanup-live-resources';\n readonly census: PreviewResourceCensus;\n\n constructor(census: PreviewResourceCensus, failures: readonly string[] = []) {\n super(\n failures.length === 0\n ? 'preview session left live resources after disposal'\n : `preview session cleanup failed: ${failures.join('; ')}`,\n );\n this.name = 'PreviewCleanupError';\n this.census = census;\n }\n}\n\nfunction hasLiveResources(census: PreviewResourceCensus): boolean {\n return Object.values(census).some((count) => count !== 0);\n}\n\nexport function createPreviewHost(adapter: PreviewHostAdapter): PreviewHost;\nexport function createPreviewHost(input: PreviewHostMechanisms): NativePreviewHost;\nexport function createPreviewHost(\n adapterOrInput: PreviewHostAdapter | PreviewHostMechanisms,\n): PreviewHost | NativePreviewHost {\n if ('runId' in adapterOrInput) return createNativePreviewHost(adapterOrInput);\n const adapter = adapterOrInput;\n const withSession = async <TResult>(\n request: PreviewHostRequest,\n run: (session: PreviewHostSession) => TResult | Promise<TResult>,\n ): Promise<{ readonly value: TResult; readonly cleanup: PreviewCleanupReport }> => {\n const session = await adapter.open(request);\n let result: TResult;\n try {\n result = await run(session);\n } finally {\n await session.dispose();\n }\n const cleanup: PreviewCleanupReport = { census: session.census(), failures: [] };\n if (hasLiveResources(cleanup.census)) {\n throw new PreviewCleanupError(cleanup.census, cleanup.failures);\n }\n return { value: result, cleanup };\n };\n\n return {\n withSession,\n };\n}\n","import {\n defineTool,\n type SnapshotRef,\n type ToolContribution,\n type ToolPreviewContract,\n type ToolSchema,\n type ToolSubjectRef,\n} from '@forgeax/engine-tool-runtime';\nimport { nativePreviewPlugin, subjectDescriptor } from './domains/subject.js';\nimport { executeVfxPreview } from './domains/vfx.js';\nimport { previewHostCapability } from './host/preview-host.js';\nimport {\n domainFailure,\n type PreviewDomainResult,\n type PreviewDomainRunner,\n previewRuntimeUnavailable,\n validateDomainValue,\n} from './host.js';\n\nexport interface VfxBinding {\n readonly guid: string;\n readonly effectDigest: string;\n}\n\nexport interface VfxSimulationInput {\n readonly seed: number;\n readonly deltaSeconds: number;\n readonly frames: number;\n}\n\nexport interface VfxPreviewRequest {\n readonly subject: ToolSubjectRef;\n readonly snapshot: SnapshotRef;\n readonly binding: VfxBinding;\n readonly simulation: VfxSimulationInput;\n}\n\nexport interface VfxPreviewReport {\n readonly kind: 'vfx';\n readonly bindingGuid: string;\n readonly seed: number;\n readonly deltaSeconds: number;\n readonly frames: number;\n readonly computeSteps: number;\n readonly drawCalls: number;\n readonly subjectOutputDigest: string;\n readonly deterministicDigest: string;\n readonly captureNonBlackPixels: number;\n}\n\nconst vfxPreviewArgsSchema: ToolSchema<VfxPreviewRequest> = {\n parse(value) {\n if (value === null || typeof value !== 'object')\n return { ok: false, error: 'expected a VFX preview request object' };\n const request = value as Partial<VfxPreviewRequest>;\n const binding = request.binding;\n const simulation = request.simulation;\n if (request.subject?.kind !== 'ParticleEffectAsset' || typeof request.subject.guid !== 'string')\n return { ok: false, error: 'expected a ParticleEffectAsset subject' };\n if (\n request.snapshot === undefined ||\n !Number.isSafeInteger(request.snapshot.revision) ||\n typeof request.snapshot.digest !== 'string'\n )\n return { ok: false, error: 'expected a revisioned snapshot' };\n if (\n binding === undefined ||\n binding.guid !== request.subject.guid ||\n binding.effectDigest.length === 0 ||\n simulation === undefined ||\n !Number.isSafeInteger(simulation.seed) ||\n simulation.deltaSeconds <= 0 ||\n !Number.isFinite(simulation.deltaSeconds) ||\n !Number.isSafeInteger(simulation.frames) ||\n simulation.frames < 1 ||\n simulation.frames > 240\n )\n return { ok: false, error: 'expected a bound effect and bounded deterministic timeline' };\n return { ok: true, value: request as VfxPreviewRequest };\n },\n describe:\n '{\"type\":\"object\",\"required\":[\"subject\",\"snapshot\",\"binding\",\"simulation\"],\"properties\":{\"subject\":{\"type\":\"object\",\"required\":[\"kind\",\"guid\"],\"properties\":{\"kind\":{\"const\":\"ParticleEffectAsset\"},\"guid\":{\"type\":\"string\"}}},\"snapshot\":{\"type\":\"object\",\"required\":[\"revision\",\"digest\"]},\"binding\":{\"type\":\"object\",\"required\":[\"guid\",\"effectDigest\"]},\"simulation\":{\"type\":\"object\",\"required\":[\"seed\",\"deltaSeconds\",\"frames\"]}}}',\n};\n\nconst vfxPreviewResultSchema: ToolSchema<unknown> = {\n parse: (value) => ({ ok: true, value }),\n describe: '{\"type\":\"object\",\"required\":[\"subject\",\"snapshot\",\"report\",\"artifacts\"]}',\n};\n\nexport const vfxPreviewDescriptor = {\n id: 'vfx.preview',\n title: 'Preview particle effect asset',\n summary: 'Runs a fixed-seed particle compute/draw timeline and captures its subject output.',\n realm: 'engine' as const,\n argsSchema: vfxPreviewArgsSchema,\n resultSchema: vfxPreviewResultSchema,\n evidence: ['rhi-tape', 'png', 'profile-capture'] as const,\n preview: {\n realm: 'engine' as const,\n subject: { kind: 'ParticleEffectAsset', guid: '<request>' },\n snapshot: { revision: 0, digest: '<request>' },\n requiredEvidence: ['rhi-tape', 'png', 'profile-capture'] as const,\n } satisfies ToolPreviewContract,\n};\n\nexport function vfxDeterministicDigest(request: VfxPreviewRequest): string {\n return `sha256:vfx:${request.binding.effectDigest}:${request.simulation.seed}:${request.simulation.deltaSeconds}:${request.simulation.frames}`;\n}\n\nfunction defaultVfxRunner(\n request: VfxPreviewRequest,\n): Promise<PreviewDomainResult<VfxPreviewReport>> {\n return Promise.resolve(previewRuntimeUnavailable(request.subject, request.snapshot, 'vfx'));\n}\n\nexport function createVfxPreviewContribution(\n runner: PreviewDomainRunner<VfxPreviewRequest, VfxPreviewReport> = async (request) =>\n defaultVfxRunner(request),\n): ToolContribution<VfxPreviewRequest, unknown> {\n return defineTool(vfxPreviewDescriptor, async (request, context) => {\n const result = await runner(request, context);\n if (!result.ok) return result;\n const report = result.value.report;\n const expectedDigest = vfxDeterministicDigest(request);\n if (\n report.bindingGuid !== request.subject.guid ||\n report.seed !== request.simulation.seed ||\n report.deltaSeconds !== request.simulation.deltaSeconds ||\n report.frames !== request.simulation.frames ||\n report.computeSteps !== request.simulation.frames ||\n report.drawCalls !== request.simulation.frames ||\n report.subjectOutputDigest.length === 0 ||\n report.deterministicDigest !== expectedDigest ||\n report.captureNonBlackPixels <= 0\n ) {\n return domainFailure(\n 'preview-subject-falsified',\n 'the effect binding, fixed simulation input, compute/draw steps, and subject output to agree',\n 'Reject stale seed/delta reports and captures without a subject output.',\n {\n requestGuid: request.subject.guid,\n reportBindingGuid: report.bindingGuid,\n expectedDigest,\n actualDigest: report.deterministicDigest,\n computeSteps: report.computeSteps,\n drawCalls: report.drawCalls,\n },\n );\n }\n const validated = validateDomainValue(result.value, request);\n if (!validated.ok) return validated;\n return { ok: true, value: validated.value };\n });\n}\n\nexport const vfxPreview = defineTool(subjectDescriptor('vfx'), (args, context) =>\n (async () => {\n const host = context.require(previewHostCapability);\n if (!host.ok) return host;\n return host.value.withSession(async (mechanisms) =>\n executeVfxPreview(args, {\n ...(mechanisms.assets === undefined ? {} : { assets: mechanisms.assets }),\n ...(mechanisms.renderer === undefined ? {} : { renderer: mechanisms.renderer }),\n runId: mechanisms.runId,\n ...(mechanisms.artifacts === undefined ? {} : { artifacts: mechanisms.artifacts }),\n }),\n );\n })(),\n);\nexport const vfxPreviewPlugin = nativePreviewPlugin('vfx', vfxPreview);\nexport default vfxPreviewPlugin;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/host/preview-host.ts","../src/domains/subject.ts","../src/evidence/oracle.ts","../src/kit/canonical.ts","../src/domains/vfx.ts","../src/host.ts","../src/vfx.ts"],"names":["defineToolPlugin","isRecord","authoredBounds"],"mappings":"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","file":"vfx.mjs","sourcesContent":["import { defineToolPlugin, type Plugin, type ToolPlugin } from '@forgeax/engine-plugin';\nimport {\n type ArtifactRef,\n defineToolCapability,\n type SnapshotRef,\n} from '@forgeax/engine-tool-runtime';\n\nexport interface PreviewAssetLoadResult<TAsset = unknown> {\n readonly ok: true;\n readonly value: TAsset;\n readonly digest?: string;\n readonly ownerFacts?: Readonly<Record<string, string | number | boolean>>;\n}\n\nexport interface PreviewAssetLoadFailure {\n readonly ok: false;\n readonly error: unknown;\n}\n\nexport interface PreviewAssetRegistry {\n readonly loadByGuid: <TAsset = unknown>(\n guid: string,\n ) => Promise<PreviewAssetLoadResult<TAsset> | PreviewAssetLoadFailure>;\n}\n\nexport interface PreviewRenderRuntime {\n readonly rendererReady: boolean;\n readonly worldReady: boolean;\n readonly drawCalls: number;\n readonly nonBlackPixels: number;\n /**\n * Facts read back from the real render/asset owner path. Domain executors\n * must not manufacture observed identity from the requested subject.\n */\n readonly observation?: Readonly<Record<string, string | number | boolean | readonly number[]>>;\n readonly vfx?: {\n readonly dispatches: number;\n readonly indirectDraws: number;\n readonly subjectOutputs: number;\n };\n readonly texture?: {\n readonly drawCalls: number;\n };\n}\n\nexport interface PreviewHostMechanisms {\n readonly runId: string;\n readonly snapshot: SnapshotRef;\n readonly projectRoot: string;\n readonly backend: 'webgpu';\n readonly signal: AbortSignal;\n readonly assets?: PreviewAssetRegistry;\n readonly renderer?: PreviewRenderRuntime;\n readonly artifacts?: readonly ArtifactRef[];\n}\n\nexport interface PreviewHost {\n readonly withSession: <T>(\n execute: (mechanisms: PreviewHostMechanisms) => Promise<T>,\n ) => Promise<T>;\n}\n\nexport const previewHostCapability = defineToolCapability<PreviewHost>('preview.host');\n\nexport function previewHostPlugin(host: PreviewHost): Plugin {\n return {\n name: 'forgeax-preview-host',\n provide: previewHostCapability.id,\n apply(ctx) {\n ctx.provide(previewHostCapability.id, host);\n },\n };\n}\n\nexport function bindPreviewHost(plugin: ToolPlugin, host: PreviewHost): ToolPlugin {\n return defineToolPlugin(previewHostPlugin(host), plugin.tools);\n}\n\nexport function createPreviewHost(input: PreviewHostMechanisms): PreviewHost {\n let active = true;\n return {\n async withSession(execute) {\n if (!active || input.signal.aborted) throw new Error('preview-host-session-terminal');\n try {\n return await execute(input);\n } finally {\n active = false;\n }\n },\n };\n}\n","import { defineToolPlugin } from '@forgeax/engine-plugin';\nimport type {\n JsonValue,\n ToolContribution,\n ToolDescriptor,\n ToolExecutionContext,\n ToolSchema,\n} from '@forgeax/engine-tool-runtime';\nimport { previewHostCapability } from '../host/preview-host.js';\nimport type { PreviewSubjectKind } from '../kit/presentation.js';\n\nexport interface ResourcePreviewArgs {\n readonly guid: string;\n /** Square screenshot edge in device pixels. Defaults to 512 and must be a power of two. */\n readonly size?: number;\n}\n\nexport const RESOURCE_PREVIEW_DEFAULT_SIZE = 512;\nexport const RESOURCE_PREVIEW_MIN_SIZE = 64;\nexport const RESOURCE_PREVIEW_MAX_SIZE = 4096;\n\nexport function isResourcePreviewSize(value: unknown): value is number {\n return (\n typeof value === 'number' &&\n Number.isSafeInteger(value) &&\n value >= RESOURCE_PREVIEW_MIN_SIZE &&\n value <= RESOURCE_PREVIEW_MAX_SIZE &&\n (value & (value - 1)) === 0\n );\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0;\n}\n\n/** Keep the public result contract concrete at the ToolRuntime boundary. */\nfunction isResourcePreviewResult(value: unknown): boolean {\n if (!isRecord(value)) return false;\n const subject = value.subject;\n if (\n !isRecord(subject) ||\n !isString(subject.kind) ||\n !isString(subject.guid) ||\n !isString(subject.digest)\n )\n return false;\n if (!isRecord(value.presentation) || !isString(value.presentation.kind)) return false;\n if (\n !isRecord(value.recipe) ||\n !isString(value.recipe.schemaVersion) ||\n !isString(value.recipe.recipeDigest)\n )\n return false;\n if (!isRecord(value.oracle) || !isString(value.oracle.status)) return false;\n return Array.isArray(value.artifacts);\n}\n\nexport const resourcePreviewResultSchema: ToolSchema<unknown> = {\n parse(value) {\n return isResourcePreviewResult(value)\n ? { ok: true, value }\n : {\n ok: false,\n error:\n 'resource preview result must include subject, presentation, recipe, oracle, and artifacts',\n };\n },\n describe: '{\"type\":\"object\",\"required\":[\"subject\",\"presentation\",\"recipe\",\"oracle\",\"artifacts\"]}',\n};\n\nexport const resourcePreviewArgsSchema: ToolSchema<ResourcePreviewArgs> = {\n parse(value) {\n if (\n value === null ||\n typeof value !== 'object' ||\n typeof Reflect.get(value, 'guid') !== 'string'\n ) {\n return { ok: false, error: 'expected { guid: string }' };\n }\n const guid = Reflect.get(value, 'guid');\n if (guid.length === 0) return { ok: false, error: 'guid must not be empty' };\n const size = Reflect.get(value, 'size');\n if (size === undefined) return { ok: true, value: { guid } };\n return isResourcePreviewSize(size)\n ? { ok: true, value: { guid, size } }\n : {\n ok: false,\n error: `size must be a power of two between ${RESOURCE_PREVIEW_MIN_SIZE} and ${RESOURCE_PREVIEW_MAX_SIZE}`,\n };\n },\n describe: `{\"type\":\"object\",\"required\":[\"guid\"],\"properties\":{\"guid\":{\"type\":\"string\"},\"size\":{\"type\":\"integer\",\"minimum\":${RESOURCE_PREVIEW_MIN_SIZE},\"maximum\":${RESOURCE_PREVIEW_MAX_SIZE},\"description\":\"square power-of-two screenshot edge; defaults to ${RESOURCE_PREVIEW_DEFAULT_SIZE}\"}}}`,\n};\n\nexport function subjectDescriptor(\n kind: PreviewSubjectKind,\n): ToolDescriptor<ResourcePreviewArgs, unknown> {\n return {\n id: `${kind}.preview`,\n title: `Preview ${kind}`,\n summary: `Preview one ${kind} asset in the Engine-owned resource host.`,\n realm: 'host',\n argsSchema: resourcePreviewArgsSchema,\n resultSchema: resourcePreviewResultSchema,\n evidence: ['rhi-tape', 'profile-capture', 'png'],\n };\n}\n\nexport type SubjectExecutor = (args: ResourcePreviewArgs, context: ToolExecutionContext) => unknown;\n\nexport interface ResourceSubjectFailure {\n readonly ok: false;\n readonly error: {\n readonly code:\n | 'resource-preview-subject-invalid'\n | 'resource-preview-kind-mismatch'\n | 'resource-preview-oracle-failed';\n readonly expected: string;\n readonly hint: string;\n readonly detail: Readonly<Record<string, JsonValue>>;\n };\n}\n\nexport function subjectFailure(\n code: ResourceSubjectFailure['error']['code'],\n expected: string,\n detail: Readonly<Record<string, JsonValue>>,\n): ResourceSubjectFailure {\n return {\n ok: false,\n error: {\n code,\n expected,\n hint: 'Load the requested GUID through AssetRegistry.loadByGuid and repair the owner facts before retrying.',\n detail,\n },\n };\n}\n\nexport function assetLoadFailure(\n expected: string,\n runId: string,\n error: unknown,\n): ResourceSubjectFailure {\n const owner = isRecord(error) ? error : undefined;\n const ownerCode = typeof owner?.code === 'string' ? owner.code : undefined;\n const ownerExpected = typeof owner?.expected === 'string' ? owner.expected : undefined;\n const ownerHint = typeof owner?.hint === 'string' ? owner.hint : undefined;\n const ownerDetail = owner?.detail;\n return subjectFailure('resource-preview-subject-invalid', expected, {\n phase: 'asset-load',\n runId,\n ...(ownerCode === undefined ? {} : { ownerCode }),\n ...(ownerExpected === undefined ? {} : { ownerExpected }),\n ...(ownerHint === undefined ? {} : { ownerHint }),\n ...(ownerDetail === undefined ? {} : { ownerDetail: toJsonValue(ownerDetail) }),\n });\n}\n\nfunction toJsonValue(value: unknown): JsonValue {\n if (value === null || typeof value === 'string' || typeof value === 'boolean') return value;\n if (typeof value === 'number' && Number.isFinite(value)) return value;\n if (Array.isArray(value)) return value.map((entry) => toJsonValue(entry));\n if (isRecord(value)) {\n return Object.fromEntries(\n Object.entries(value).map(([key, entry]) => [key, toJsonValue(entry)]),\n );\n }\n return String(value);\n}\n\nexport function nativePreviewPlugin(\n kind: PreviewSubjectKind,\n contribution: ToolContribution<ResourcePreviewArgs, unknown>,\n) {\n return defineToolPlugin({ name: `forgeax-preview-${kind}`, apply() {} }, [\n contribution as ToolContribution<unknown, unknown>,\n ]);\n}\n\nexport async function failUnboundSubject(\n kind: PreviewSubjectKind,\n args: ResourcePreviewArgs,\n context: ToolExecutionContext,\n): Promise<unknown> {\n const host = context.require(previewHostCapability);\n if (!host.ok) return host;\n return host.value.withSession(async (mechanisms) => ({\n ...subjectFailure(\n 'resource-preview-subject-invalid',\n `${kind} asset ${args.guid} to be bound by its owner before rendering`,\n { phase: 'subject-binding', runId: mechanisms.runId },\n ),\n }));\n}\n","export type PreviewOracleStatus = PreviewOracle['status'];\n\nexport type PreviewOracle =\n | {\n readonly status: 'passed';\n readonly subjectBound: true;\n readonly drawCalls: number;\n readonly dispatches: number;\n readonly rendererHealthy: true;\n readonly detail: Record<string, string | number | boolean>;\n }\n | {\n readonly status: 'failed';\n readonly subjectBound: false;\n readonly drawCalls: number;\n readonly dispatches: number;\n readonly rendererHealthy: boolean;\n readonly detail: Record<string, string | number | boolean>;\n };\n\nexport function passedPreviewOracle(input: {\n readonly drawCalls: number;\n readonly dispatches?: number;\n readonly detail: Record<string, string | number | boolean>;\n}): PreviewOracle {\n return {\n status: 'passed',\n subjectBound: true,\n drawCalls: input.drawCalls,\n dispatches: input.dispatches ?? 0,\n rendererHealthy: true,\n detail: { ...input.detail },\n };\n}\n\nexport function failedPreviewOracle(input: {\n readonly drawCalls?: number;\n readonly dispatches?: number;\n readonly rendererHealthy?: boolean;\n readonly detail: Record<string, string | number | boolean>;\n}): PreviewOracle {\n return {\n status: 'failed',\n subjectBound: false,\n drawCalls: input.drawCalls ?? 0,\n dispatches: input.dispatches ?? 0,\n rendererHealthy: input.rendererHealthy ?? false,\n detail: { ...input.detail },\n };\n}\n\nexport interface MaterialOracleInput {\n readonly requested: {\n readonly subjectDigest: string;\n readonly program: string;\n readonly pass: string;\n readonly bindingsDigest: string;\n readonly closureDigest: string;\n };\n readonly observed: MaterialOracleInput['requested'] & {\n readonly rendererHealthy: boolean;\n readonly drawCalls: number;\n readonly nonBlackPixels: number;\n };\n}\n\nexport interface MeshOracleInput {\n readonly requested: {\n readonly subjectDigest: string;\n readonly vertexDigest: string;\n readonly indexDigest: string;\n readonly submeshDigest: string;\n readonly aabbDigest: string;\n readonly aabb?: readonly [number, number, number, number, number, number];\n readonly submeshCount?: number;\n readonly materialSlotCount?: number;\n };\n readonly observed: MeshOracleInput['requested'] & {\n readonly rendererHealthy: boolean;\n readonly drawCalls: number;\n readonly nonBlackPixels: number;\n };\n}\n\nfunction oracleDetail(\n kind: 'material' | 'mesh',\n requested: Record<string, unknown>,\n observed: Record<string, unknown>,\n mismatch: string | undefined,\n): Record<string, string | number | boolean> {\n return {\n kind,\n mismatch: mismatch ?? 'none',\n requestedSubjectDigest:\n typeof requested.subjectDigest === 'string' ? requested.subjectDigest : 'unknown',\n observedSubjectDigest:\n typeof observed.subjectDigest === 'string' ? observed.subjectDigest : 'unknown',\n requestedOwnerDigest: JSON.stringify(requested),\n observedOwnerDigest: JSON.stringify(observed),\n };\n}\n\nfunction firstMismatch(\n requested: Record<string, unknown>,\n observed: Record<string, unknown>,\n): string | undefined {\n for (const key of Object.keys(requested)) {\n const requestedValue = requested[key];\n const observedValue = observed[key];\n if (\n Array.isArray(requestedValue) ||\n Array.isArray(observedValue) ||\n typeof requestedValue === 'object' ||\n typeof observedValue === 'object'\n ) {\n if (JSON.stringify(requestedValue) !== JSON.stringify(observedValue)) return key;\n } else if (requestedValue !== observedValue) {\n return key;\n }\n }\n return undefined;\n}\n\nexport function evaluateMaterialOracle(input: MaterialOracleInput): PreviewOracle {\n const requested = input.requested as unknown as Record<string, string>;\n const observed = input.observed as unknown as Record<string, string>;\n const mismatch = firstMismatch(requested, observed);\n const healthy = input.observed.rendererHealthy && input.observed.drawCalls > 0;\n const detail = oracleDetail('material', requested, observed, mismatch);\n if (mismatch !== undefined || !healthy) {\n return failedPreviewOracle({\n drawCalls: input.observed.drawCalls,\n rendererHealthy: input.observed.rendererHealthy,\n detail: { ...detail, rendererHealthy: input.observed.rendererHealthy },\n });\n }\n return passedPreviewOracle({\n drawCalls: input.observed.drawCalls,\n detail: { ...detail, rendererHealthy: true },\n });\n}\n\nexport function evaluateMeshOracle(input: MeshOracleInput): PreviewOracle {\n const requested = input.requested as unknown as Record<string, string>;\n const observed = input.observed as unknown as Record<string, string>;\n const mismatch = firstMismatch(requested, observed);\n const healthy = input.observed.rendererHealthy && input.observed.drawCalls > 0;\n const detail = oracleDetail('mesh', requested, observed, mismatch);\n if (mismatch !== undefined || !healthy) {\n return failedPreviewOracle({\n drawCalls: input.observed.drawCalls,\n rendererHealthy: input.observed.rendererHealthy,\n detail: { ...detail, rendererHealthy: input.observed.rendererHealthy },\n });\n }\n return passedPreviewOracle({\n drawCalls: input.observed.drawCalls,\n detail: { ...detail, rendererHealthy: true },\n });\n}\n\nexport interface VfxOracleInput {\n readonly requested: {\n readonly subjectDigest: string;\n readonly programFingerprint: string;\n readonly emitterDigest: string;\n readonly sampleDigest: string;\n readonly boundsDigest: string;\n readonly computeDigest: string;\n readonly indirectDigest: string;\n readonly contactSheetDigest?: string;\n readonly authoredBounds?: readonly [number, number, number, number, number, number];\n readonly seed?: number;\n readonly fixedDelta?: number;\n readonly timelineFrames?: number;\n };\n readonly observed: VfxOracleInput['requested'] & {\n readonly rendererHealthy: boolean;\n readonly dispatches: number;\n readonly indirectDraws: number;\n readonly subjectOutputs: number;\n readonly nonBlackPixels: number;\n };\n}\n\nexport interface TextureOracleInput {\n readonly requested: {\n readonly subjectDigest: string;\n readonly boundDigest: string;\n readonly dimensions: readonly [number, number];\n readonly format: string;\n readonly colorSpace: string;\n readonly mipCount: number;\n readonly uvDigest: string;\n readonly filter: string;\n readonly bindingDigest: string;\n };\n readonly observed: TextureOracleInput['requested'] & {\n readonly rendererHealthy: boolean;\n readonly drawCalls: number;\n readonly nonBlackPixels: number;\n readonly payloadClass: 'black' | 'transparent' | 'single-channel' | 'color';\n };\n}\n\nfunction identityRecord(input: Record<string, unknown>): Record<string, string> {\n return Object.fromEntries(\n Object.entries(input).map(([key, value]) => [\n key,\n Array.isArray(value) ? JSON.stringify(value) : String(value),\n ]),\n );\n}\n\nfunction evaluateIdentityOracle(\n kind: 'vfx' | 'texture',\n requestedInput: Record<string, unknown>,\n observedInput: Record<string, unknown>,\n healthy: boolean,\n drawCalls: number,\n dispatches: number,\n detailOverrides: Record<string, string | number | boolean>,\n): PreviewOracle {\n const requested = identityRecord(requestedInput);\n const observed = identityRecord(observedInput);\n const mismatch = firstMismatch(requested, observed);\n const detail = {\n kind,\n mismatch: mismatch ?? 'none',\n requestedSubjectDigest: requested.subjectDigest ?? 'unknown',\n observedSubjectDigest: observed.subjectDigest ?? 'unknown',\n requestedOwnerDigest: JSON.stringify(requested),\n observedOwnerDigest: JSON.stringify(observed),\n ...detailOverrides,\n };\n if (mismatch !== undefined || !healthy) {\n return failedPreviewOracle({ drawCalls, dispatches, rendererHealthy: healthy, detail });\n }\n return passedPreviewOracle({ drawCalls, dispatches, detail });\n}\n\nexport function evaluateVfxOracle(input: VfxOracleInput): PreviewOracle {\n const observed = input.observed;\n const healthy =\n observed.rendererHealthy &&\n observed.dispatches > 0 &&\n observed.indirectDraws > 0 &&\n observed.subjectOutputs > 0;\n return evaluateIdentityOracle(\n 'vfx',\n input.requested,\n input.observed,\n healthy,\n observed.indirectDraws,\n observed.dispatches,\n {\n rendererHealthy: observed.rendererHealthy,\n indirectDraws: observed.indirectDraws,\n subjectOutputs: observed.subjectOutputs,\n nonBlackPixels: observed.nonBlackPixels,\n },\n );\n}\n\nexport function evaluateTextureOracle(input: TextureOracleInput): PreviewOracle {\n const observed = input.observed;\n return evaluateIdentityOracle(\n 'texture',\n input.requested,\n input.observed,\n observed.rendererHealthy && observed.drawCalls > 0,\n observed.drawCalls,\n 0,\n {\n rendererHealthy: observed.rendererHealthy,\n payloadClass: observed.payloadClass,\n nonBlackPixels: observed.nonBlackPixels,\n },\n );\n}\n","import type { PreviewPresentation, PreviewSubjectKind } from './presentation.js';\n\nexport interface CanonicalPreviewRecipe {\n readonly schemaVersion: '1.0.0';\n readonly rig:\n | Extract<PreviewPresentation, { readonly kind: 'lit-asset' }>['geometry']\n | 'asset-quad';\n readonly environment: 'engine-canonical' | 'black';\n readonly skybox: 'engine-canonical' | 'none';\n readonly skylight: 'engine-canonical' | 'none';\n readonly directionalLight: 'engine-canonical' | 'none';\n readonly stage: 'neutral-material-checker-unlit' | 'texture-unlit-black';\n readonly camera: 'bounds-derived' | 'texture-orthographic';\n readonly recipeDigest: string;\n}\n\nexport function createCanonicalPreviewRecipe(kind: PreviewSubjectKind): CanonicalPreviewRecipe {\n const texture = kind === 'texture';\n return {\n schemaVersion: '1.0.0',\n rig: kind === 'mesh' ? 'asset-mesh' : texture ? 'asset-quad' : 'handle-sphere',\n environment: texture ? 'black' : 'engine-canonical',\n skybox: texture ? 'none' : 'engine-canonical',\n skylight: texture ? 'none' : 'engine-canonical',\n directionalLight: texture ? 'none' : 'engine-canonical',\n stage: texture ? 'texture-unlit-black' : 'neutral-material-checker-unlit',\n camera: texture ? 'texture-orthographic' : 'bounds-derived',\n recipeDigest: `canonical:${kind}:${texture ? 'texture-orthographic' : 'bounds-derived'}`,\n };\n}\n\nexport function canonicalPresentation(kind: PreviewSubjectKind): PreviewPresentation {\n if (kind === 'texture') {\n return {\n kind: 'texture-unlit',\n geometry: 'aspect-quad',\n checkerboard: 'linear-alpha',\n };\n }\n return {\n kind: 'lit-asset',\n geometry: kind === 'mesh' ? 'asset-mesh' : 'handle-sphere',\n skylight: 'engine-canonical',\n directionalLight: 'engine-canonical',\n skybox: 'engine-canonical',\n };\n}\n","import type { ArtifactRef } from '@forgeax/engine-tool-runtime';\nimport { evaluateVfxOracle, type VfxOracleInput } from '../evidence/oracle.js';\nimport type { PreviewAssetRegistry, PreviewRenderRuntime } from '../host/preview-host.js';\nimport { canonicalPresentation, createCanonicalPreviewRecipe } from '../kit/canonical.js';\nimport { assetLoadFailure, type ResourcePreviewArgs, subjectFailure } from './subject.js';\n\nexport interface VfxSubjectInspection {\n readonly subjectDigest: string;\n readonly programFingerprint: string;\n readonly emitterDigest: string;\n readonly sampleDigest: string;\n readonly boundsDigest: string;\n readonly computeDigest: string;\n readonly indirectDigest: string;\n readonly contactSheetDigest?: string;\n readonly authoredBounds: readonly [number, number, number, number, number, number];\n}\n\ntype InspectionResult =\n | { readonly ok: true; readonly value: VfxSubjectInspection }\n | ReturnType<typeof subjectFailure>;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\nfunction requiredString(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined;\n}\n\nfunction finiteVector(value: unknown, length: number): number[] | undefined {\n if (\n !Array.isArray(value) ||\n value.length !== length ||\n value.some((entry) => typeof entry !== 'number' || !Number.isFinite(entry))\n )\n return undefined;\n return value;\n}\n\nfunction authoredBounds(\n emitters: readonly Record<string, unknown>[],\n): readonly [number, number, number, number, number, number] | undefined {\n let minX = Infinity;\n let minY = Infinity;\n let minZ = Infinity;\n let maxX = -Infinity;\n let maxY = -Infinity;\n let maxZ = -Infinity;\n for (const emitter of emitters) {\n const bounds = emitter.bounds;\n if (!isRecord(bounds) || typeof bounds.kind !== 'string') return undefined;\n if (bounds.kind === 'sphere') {\n const center = finiteVector(bounds.center, 3);\n const radius = bounds.radius;\n if (\n center === undefined ||\n typeof radius !== 'number' ||\n !Number.isFinite(radius) ||\n radius < 0\n )\n return undefined;\n const [x, y, z] = center;\n if (x === undefined || y === undefined || z === undefined) return undefined;\n minX = Math.min(minX, x - radius);\n minY = Math.min(minY, y - radius);\n minZ = Math.min(minZ, z - radius);\n maxX = Math.max(maxX, x + radius);\n maxY = Math.max(maxY, y + radius);\n maxZ = Math.max(maxZ, z + radius);\n continue;\n }\n if (bounds.kind === 'aabb') {\n const min = finiteVector(bounds.min, 3);\n const max = finiteVector(bounds.max, 3);\n if (\n min === undefined ||\n max === undefined ||\n min.some((entry, index) => entry > (max[index] ?? entry))\n )\n return undefined;\n const [loX, loY, loZ] = min;\n const [hiX, hiY, hiZ] = max;\n if (\n loX === undefined ||\n loY === undefined ||\n loZ === undefined ||\n hiX === undefined ||\n hiY === undefined ||\n hiZ === undefined\n )\n return undefined;\n minX = Math.min(minX, loX);\n minY = Math.min(minY, loY);\n minZ = Math.min(minZ, loZ);\n maxX = Math.max(maxX, hiX);\n maxY = Math.max(maxY, hiY);\n maxZ = Math.max(maxZ, hiZ);\n continue;\n }\n return undefined;\n }\n if (![minX, minY, minZ, maxX, maxY, maxZ].every(Number.isFinite)) return undefined;\n return [minX, minY, minZ, maxX, maxY, maxZ];\n}\n\nfunction jsonDigest(value: unknown): string | undefined {\n const encoded = JSON.stringify(value);\n return typeof encoded === 'string' && encoded.length > 0 ? encoded : undefined;\n}\n\nexport function inspectVfxSubject(input: {\n readonly guid: string;\n readonly asset: unknown;\n readonly digest?: string;\n readonly ownerFacts?: Readonly<Record<string, string | number | boolean>>;\n}): InspectionResult {\n if (!isRecord(input.asset) || input.asset.kind !== 'particle-effect') {\n return subjectFailure(\n 'resource-preview-kind-mismatch',\n 'a ParticleEffectAsset with kind particle-effect',\n {\n phase: 'subject',\n guid: input.guid,\n actualKind:\n isRecord(input.asset) && typeof input.asset.kind === 'string'\n ? input.asset.kind\n : 'unknown',\n },\n );\n }\n if (input.asset.schemaVersion !== 3) {\n return subjectFailure('resource-preview-subject-invalid', 'a schema-v3 ParticleEffectAsset', {\n phase: 'subject',\n guid: input.guid,\n field: 'schemaVersion',\n });\n }\n const program = input.asset.program;\n const programFingerprint = requiredString(input.asset.programFingerprint);\n if (!isRecord(program) || program.format !== 'forgeax-vfx-program-4') {\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'a cooked forgeax-vfx-program-4 payload',\n {\n phase: 'subject',\n guid: input.guid,\n field: 'program',\n },\n );\n }\n if (\n programFingerprint === undefined ||\n requiredString(program.fingerprint) !== programFingerprint\n ) {\n return subjectFailure('resource-preview-subject-invalid', 'non-empty authored VFX bounds', {\n phase: 'subject',\n guid: input.guid,\n field: 'programFingerprint',\n });\n }\n const rawEmitters = Array.isArray(program.emitters) ? program.emitters : [];\n const emitters = rawEmitters.filter(isRecord);\n const definitions = Array.isArray(input.asset.emitters)\n ? input.asset.emitters.filter(isRecord)\n : [];\n if (\n emitters.length === 0 ||\n emitters.length !== rawEmitters.length ||\n definitions.length !== emitters.length\n ) {\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'the ParticleEffectAsset to publish matching cooked emitter definitions',\n { phase: 'subject', guid: input.guid, field: 'emitters' },\n );\n }\n for (const [index, emitter] of emitters.entries()) {\n const id = requiredString(emitter.id);\n const module = requiredString(emitter.module);\n const capacity = emitter.capacity;\n const backend = emitter.backend;\n const renderers = emitter.renderers;\n if (\n id === undefined ||\n module === undefined ||\n typeof capacity !== 'number' ||\n !Number.isSafeInteger(capacity) ||\n capacity <= 0 ||\n !isRecord(backend) ||\n backend.required !== 'gpu' ||\n !isRecord(emitter.schedule) ||\n !Array.isArray(renderers) ||\n !isRecord(definitions[index]) ||\n definitions[index].id !== id ||\n definitions[index].capacity !== capacity\n ) {\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'each cooked emitter to match its ParticleEffectAsset definition',\n { phase: 'subject', guid: input.guid, field: `emitters[${index}]` },\n );\n }\n }\n const bounds = authoredBounds(emitters);\n if (bounds === undefined) {\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'finite authored VFX emitter bounds',\n {\n phase: 'subject',\n guid: input.guid,\n field: 'program.emitters[].bounds',\n },\n );\n }\n const emitterDigest = jsonDigest(\n emitters.map(({ id, module, capacity }) => ({ id, module, capacity })),\n );\n const sampleDigest = jsonDigest(emitters.map(({ id, schedule }) => ({ id, schedule })));\n const boundsDigest = jsonDigest(\n emitters.map(({ id, bounds: emitterBounds }) => ({ id, bounds: emitterBounds })),\n );\n const indirectDigest = jsonDigest(\n emitters.map(({ id, renderers }) => ({\n id,\n renderers: (renderers as readonly unknown[]).filter(isRecord).map((renderer) => ({\n kind: renderer.kind,\n enabled: renderer.enabled ?? true,\n })),\n })),\n );\n if (\n emitterDigest === undefined ||\n sampleDigest === undefined ||\n boundsDigest === undefined ||\n indirectDigest === undefined\n ) {\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'the cooked VFX program to publish stable emitter, schedule, bounds, and renderer facts',\n { phase: 'subject', guid: input.guid, field: 'program.emitters' },\n );\n }\n const ownerFacts = isRecord(input.asset.ownerFacts) ? input.asset.ownerFacts : input.ownerFacts;\n const subjectDigest =\n requiredString(input.asset.digest) ??\n requiredString(input.digest) ??\n requiredString(ownerFacts?.subjectDigest) ??\n programFingerprint;\n const contactSheetDigest = requiredString(ownerFacts?.contactSheetDigest);\n return {\n ok: true,\n value: {\n subjectDigest,\n programFingerprint,\n emitterDigest,\n sampleDigest,\n boundsDigest,\n computeDigest: programFingerprint,\n indirectDigest,\n ...(contactSheetDigest === undefined ? {} : { contactSheetDigest }),\n authoredBounds: bounds,\n },\n };\n}\n\nexport async function executeVfxPreview(\n args: ResourcePreviewArgs,\n input: {\n readonly assets?: PreviewAssetRegistry;\n readonly renderer?: PreviewRenderRuntime;\n readonly runId: string;\n readonly artifacts?: readonly ArtifactRef[];\n },\n) {\n if (input.assets === undefined)\n return subjectFailure(\n 'resource-preview-subject-invalid',\n 'the existing AssetRegistry capability',\n {\n phase: 'asset-registry',\n runId: input.runId,\n },\n );\n const loaded = await input.assets.loadByGuid<Record<string, unknown>>(args.guid);\n if (!loaded.ok)\n return assetLoadFailure(\n 'AssetRegistry.loadByGuid to resolve the VFX',\n input.runId,\n loaded.error,\n );\n const inspected = inspectVfxSubject({\n guid: args.guid,\n asset: loaded.value,\n ...(loaded.digest === undefined ? {} : { digest: loaded.digest }),\n ...(loaded.ownerFacts === undefined ? {} : { ownerFacts: loaded.ownerFacts }),\n });\n if (!inspected.ok) return inspected;\n const renderer = input.renderer;\n const runtime = input.renderer?.vfx;\n if (\n renderer?.rendererReady !== true ||\n renderer.worldReady !== true ||\n runtime === undefined ||\n renderer.observation === undefined\n ) {\n return subjectFailure(\n 'resource-preview-oracle-failed',\n 'shared World, Renderer, and VFX compute runtime',\n {\n phase: 'renderer',\n runId: input.runId,\n },\n );\n }\n const observation = renderer.observation;\n const observedString = (field: string): string =>\n typeof observation[field] === 'string' ? (observation[field] as string) : '';\n const authoredBounds = observation.authoredBounds;\n const seed = observation.seed;\n const fixedDelta = observation.fixedDelta;\n const timelineFrames = observation.timelineFrames;\n if (\n !Array.isArray(authoredBounds) ||\n authoredBounds.length !== 6 ||\n authoredBounds.some((value) => typeof value !== 'number' || !Number.isFinite(value)) ||\n typeof seed !== 'number' ||\n typeof fixedDelta !== 'number' ||\n typeof timelineFrames !== 'number' ||\n !Number.isInteger(timelineFrames) ||\n timelineFrames <= 0 ||\n !Number.isFinite(seed) ||\n !Number.isFinite(fixedDelta) ||\n fixedDelta <= 0\n ) {\n return subjectFailure(\n 'resource-preview-oracle-failed',\n 'the VFX render observation to include authored bounds and timeline facts',\n { phase: 'renderer-observation', runId: input.runId },\n );\n }\n const observed: VfxOracleInput['observed'] = {\n ...inspected.value,\n subjectDigest: observedString('subjectDigest'),\n programFingerprint: observedString('programFingerprint'),\n emitterDigest: observedString('emitterDigest'),\n sampleDigest: observedString('sampleDigest'),\n boundsDigest: observedString('boundsDigest'),\n computeDigest: observedString('computeDigest'),\n indirectDigest: observedString('indirectDigest'),\n ...(observedString('contactSheetDigest') === ''\n ? {}\n : { contactSheetDigest: observedString('contactSheetDigest') }),\n authoredBounds: authoredBounds as unknown as readonly [\n number,\n number,\n number,\n number,\n number,\n number,\n ],\n seed,\n fixedDelta,\n timelineFrames,\n rendererHealthy: renderer.rendererReady && renderer.worldReady,\n dispatches: runtime.dispatches,\n indirectDraws: runtime.indirectDraws,\n subjectOutputs: runtime.subjectOutputs,\n nonBlackPixels: renderer.nonBlackPixels,\n };\n const oracle = evaluateVfxOracle({ requested: inspected.value, observed });\n if (oracle.status !== 'passed') {\n return subjectFailure(\n 'resource-preview-oracle-failed',\n 'the VFX compute and indirect observation to match the loaded owner facts',\n { phase: 'oracle', runId: input.runId, ...oracle.detail },\n );\n }\n return {\n ok: true as const,\n value: {\n subject: { kind: 'vfx' as const, guid: args.guid, digest: inspected.value.subjectDigest },\n presentation: canonicalPresentation('vfx'),\n recipe: createCanonicalPreviewRecipe('vfx'),\n authoredBounds: inspected.value.authoredBounds,\n timeline: {\n seed,\n fixedDelta,\n frames: timelineFrames,\n },\n oracle,\n artifacts: input.artifacts ?? [],\n },\n artifacts: input.artifacts ?? [],\n };\n}\n","import type {\n ArtifactRef,\n JsonValue,\n SnapshotRef,\n ToolDomainFailure,\n ToolEvidenceKind,\n ToolExecutionContext,\n ToolSubjectRef,\n} from '@forgeax/engine-tool-runtime';\nimport {\n createPreviewHost as createNativePreviewHost,\n type PreviewHost as NativePreviewHost,\n type PreviewHostMechanisms,\n} from './host/preview-host.js';\n\nexport interface PreviewHostRequest {\n readonly subject: ToolSubjectRef;\n readonly snapshot: SnapshotRef;\n}\n\nexport interface PreviewAssetBinding {\n readonly guid: string;\n readonly bytes: number;\n}\n\nexport interface PreviewFrameInput {\n readonly frame: number;\n readonly deltaSeconds: number;\n}\n\nexport interface PreviewCapture {\n readonly digest: string;\n readonly bytes: number;\n}\n\nexport interface PreviewResourceCensus {\n readonly worlds: number;\n readonly renderers: number;\n readonly canvases: number;\n readonly leases: number;\n}\n\nexport interface PreviewCleanupReport {\n readonly census: PreviewResourceCensus;\n readonly failures: readonly string[];\n}\n\n/**\n * The only resource surface exposed to a preview contribution. The adapter owns\n * the actual Engine resources; callers receive POD bindings and bounded actions.\n */\nexport interface PreviewHostSession {\n readonly subject: ToolSubjectRef;\n readonly snapshot: SnapshotRef;\n readonly loadAsset: (guid: string) => Promise<PreviewAssetBinding>;\n readonly frame: (input: PreviewFrameInput) => Promise<void>;\n readonly capture: () => Promise<PreviewCapture & { readonly artifact?: ArtifactRef }>;\n readonly census: () => PreviewResourceCensus;\n readonly dispose: () => Promise<void>;\n}\n\nexport interface PreviewHostAdapter {\n readonly open: (request: PreviewHostRequest) => PreviewHostSession | Promise<PreviewHostSession>;\n}\n\nexport interface PreviewHost {\n readonly withSession: <TResult>(\n request: PreviewHostRequest,\n run: (session: PreviewHostSession) => TResult | Promise<TResult>,\n ) => Promise<{ readonly value: TResult; readonly cleanup: PreviewCleanupReport }>;\n}\n\nexport interface PreviewDomainValue<TReport = unknown> {\n readonly subject: ToolSubjectRef;\n readonly snapshot: SnapshotRef;\n readonly report: TReport;\n readonly artifacts: readonly ArtifactRef[];\n}\n\nexport type PreviewDomainResult<TReport = unknown> =\n | { readonly ok: true; readonly value: PreviewDomainValue<TReport> }\n | { readonly ok: false; readonly error: ToolDomainFailure };\n\nexport type PreviewDomainRunner<TRequest, TReport = unknown> = (\n request: TRequest,\n context: ToolExecutionContext,\n) => Promise<PreviewDomainResult<TReport>>;\n\nexport const REQUIRED_PREVIEW_EVIDENCE: readonly ToolEvidenceKind[] = [\n 'rhi-tape',\n 'png',\n 'profile-capture',\n];\n\nexport function domainFailure(\n code: string,\n expected: string,\n hint: string,\n detail: Record<string, JsonValue>,\n): { readonly ok: false; readonly error: ToolDomainFailure } {\n return { ok: false, error: { code, expected, hint, detail } };\n}\n\n/**\n * The default contribution is deliberately fail-closed. A real Project GUID\n * loader must install a PreviewHost/Browser/Dawn runner; a data-only request\n * must never manufacture PNG, RHI, or profile references from its arguments.\n */\nexport function previewRuntimeUnavailable(\n subject: ToolSubjectRef,\n snapshot: SnapshotRef,\n domain: string,\n): { readonly ok: false; readonly error: ToolDomainFailure } {\n return domainFailure(\n 'preview-runtime-unavailable',\n 'a Project GUID cold-load and an active PreviewHost/Browser/Dawn runner',\n 'Install the Project preview provider and retry; no synthetic artifact is published.',\n {\n domain,\n subjectKind: subject.kind,\n subjectGuid: subject.guid,\n snapshotRevision: snapshot.revision,\n snapshotDigest: snapshot.digest,\n requiredEvidence: REQUIRED_PREVIEW_EVIDENCE as unknown as JsonValue,\n },\n );\n}\n\nexport function validateDomainValue<TReport>(\n value: PreviewDomainValue<TReport>,\n request: PreviewHostRequest,\n): PreviewDomainResult<TReport> {\n if (\n value.subject.kind !== request.subject.kind ||\n value.subject.guid !== request.subject.guid ||\n value.snapshot.revision !== request.snapshot.revision ||\n value.snapshot.digest !== request.snapshot.digest\n ) {\n return domainFailure(\n 'preview-subject-identity-mismatch',\n 'the terminal subject and snapshot to match the request',\n 'Repair the domain producer so evidence remains bound to the requested subject.',\n {\n requestGuid: request.subject.guid,\n resultGuid: value.subject.guid,\n requestSnapshot: request.snapshot.digest,\n resultSnapshot: value.snapshot.digest,\n },\n );\n }\n const kinds = new Set(value.artifacts.map((artifact) => artifact.kind));\n const missing = REQUIRED_PREVIEW_EVIDENCE.filter((kind) => !kinds.has(kind));\n if (missing.length > 0) {\n return domainFailure(\n 'preview-evidence-incomplete',\n 'one subject-bound artifact for each required evidence kind',\n 'Repair the RHI, PNG, and profile producers before retrying.',\n { missing: missing as unknown as JsonValue },\n );\n }\n return { ok: true, value };\n}\n\nexport class PreviewCleanupError extends Error {\n readonly code = 'preview-cleanup-live-resources';\n readonly census: PreviewResourceCensus;\n\n constructor(census: PreviewResourceCensus, failures: readonly string[] = []) {\n super(\n failures.length === 0\n ? 'preview session left live resources after disposal'\n : `preview session cleanup failed: ${failures.join('; ')}`,\n );\n this.name = 'PreviewCleanupError';\n this.census = census;\n }\n}\n\nfunction hasLiveResources(census: PreviewResourceCensus): boolean {\n return Object.values(census).some((count) => count !== 0);\n}\n\nexport function createPreviewHost(adapter: PreviewHostAdapter): PreviewHost;\nexport function createPreviewHost(input: PreviewHostMechanisms): NativePreviewHost;\nexport function createPreviewHost(\n adapterOrInput: PreviewHostAdapter | PreviewHostMechanisms,\n): PreviewHost | NativePreviewHost {\n if ('runId' in adapterOrInput) return createNativePreviewHost(adapterOrInput);\n const adapter = adapterOrInput;\n const withSession = async <TResult>(\n request: PreviewHostRequest,\n run: (session: PreviewHostSession) => TResult | Promise<TResult>,\n ): Promise<{ readonly value: TResult; readonly cleanup: PreviewCleanupReport }> => {\n const session = await adapter.open(request);\n let result: TResult;\n try {\n result = await run(session);\n } finally {\n await session.dispose();\n }\n const cleanup: PreviewCleanupReport = { census: session.census(), failures: [] };\n if (hasLiveResources(cleanup.census)) {\n throw new PreviewCleanupError(cleanup.census, cleanup.failures);\n }\n return { value: result, cleanup };\n };\n\n return {\n withSession,\n };\n}\n","import {\n defineTool,\n type SnapshotRef,\n type ToolContribution,\n type ToolPreviewContract,\n type ToolSchema,\n type ToolSubjectRef,\n} from '@forgeax/engine-tool-runtime';\nimport { nativePreviewPlugin, subjectDescriptor } from './domains/subject.js';\nimport { executeVfxPreview } from './domains/vfx.js';\nimport { previewHostCapability } from './host/preview-host.js';\nimport {\n domainFailure,\n type PreviewDomainResult,\n type PreviewDomainRunner,\n previewRuntimeUnavailable,\n validateDomainValue,\n} from './host.js';\n\nexport interface VfxBinding {\n readonly guid: string;\n readonly effectDigest: string;\n}\n\nexport interface VfxSimulationInput {\n readonly seed: number;\n readonly deltaSeconds: number;\n readonly frames: number;\n}\n\nexport interface VfxPreviewRequest {\n readonly subject: ToolSubjectRef;\n readonly snapshot: SnapshotRef;\n readonly binding: VfxBinding;\n readonly simulation: VfxSimulationInput;\n}\n\nexport interface VfxPreviewReport {\n readonly kind: 'vfx';\n readonly bindingGuid: string;\n readonly seed: number;\n readonly deltaSeconds: number;\n readonly frames: number;\n readonly computeSteps: number;\n readonly drawCalls: number;\n readonly subjectOutputDigest: string;\n readonly deterministicDigest: string;\n readonly captureNonBlackPixels: number;\n}\n\nconst vfxPreviewArgsSchema: ToolSchema<VfxPreviewRequest> = {\n parse(value) {\n if (value === null || typeof value !== 'object')\n return { ok: false, error: 'expected a VFX preview request object' };\n const request = value as Partial<VfxPreviewRequest>;\n const binding = request.binding;\n const simulation = request.simulation;\n if (request.subject?.kind !== 'ParticleEffectAsset' || typeof request.subject.guid !== 'string')\n return { ok: false, error: 'expected a ParticleEffectAsset subject' };\n if (\n request.snapshot === undefined ||\n !Number.isSafeInteger(request.snapshot.revision) ||\n typeof request.snapshot.digest !== 'string'\n )\n return { ok: false, error: 'expected a revisioned snapshot' };\n if (\n binding === undefined ||\n binding.guid !== request.subject.guid ||\n binding.effectDigest.length === 0 ||\n simulation === undefined ||\n !Number.isSafeInteger(simulation.seed) ||\n simulation.deltaSeconds <= 0 ||\n !Number.isFinite(simulation.deltaSeconds) ||\n !Number.isSafeInteger(simulation.frames) ||\n simulation.frames < 1 ||\n simulation.frames > 240\n )\n return { ok: false, error: 'expected a bound effect and bounded deterministic timeline' };\n return { ok: true, value: request as VfxPreviewRequest };\n },\n describe:\n '{\"type\":\"object\",\"required\":[\"subject\",\"snapshot\",\"binding\",\"simulation\"],\"properties\":{\"subject\":{\"type\":\"object\",\"required\":[\"kind\",\"guid\"],\"properties\":{\"kind\":{\"const\":\"ParticleEffectAsset\"},\"guid\":{\"type\":\"string\"}}},\"snapshot\":{\"type\":\"object\",\"required\":[\"revision\",\"digest\"]},\"binding\":{\"type\":\"object\",\"required\":[\"guid\",\"effectDigest\"]},\"simulation\":{\"type\":\"object\",\"required\":[\"seed\",\"deltaSeconds\",\"frames\"]}}}',\n};\n\nconst vfxPreviewResultSchema: ToolSchema<unknown> = {\n parse: (value) => ({ ok: true, value }),\n describe: '{\"type\":\"object\",\"required\":[\"subject\",\"snapshot\",\"report\",\"artifacts\"]}',\n};\n\nexport const vfxPreviewDescriptor = {\n id: 'vfx.preview',\n title: 'Preview particle effect asset',\n summary: 'Runs a fixed-seed particle compute/draw timeline and captures its subject output.',\n realm: 'engine' as const,\n argsSchema: vfxPreviewArgsSchema,\n resultSchema: vfxPreviewResultSchema,\n evidence: ['rhi-tape', 'png', 'profile-capture'] as const,\n preview: {\n realm: 'engine' as const,\n subject: { kind: 'ParticleEffectAsset', guid: '<request>' },\n snapshot: { revision: 0, digest: '<request>' },\n requiredEvidence: ['rhi-tape', 'png', 'profile-capture'] as const,\n } satisfies ToolPreviewContract,\n};\n\nexport function vfxDeterministicDigest(request: VfxPreviewRequest): string {\n return `sha256:vfx:${request.binding.effectDigest}:${request.simulation.seed}:${request.simulation.deltaSeconds}:${request.simulation.frames}`;\n}\n\nfunction defaultVfxRunner(\n request: VfxPreviewRequest,\n): Promise<PreviewDomainResult<VfxPreviewReport>> {\n return Promise.resolve(previewRuntimeUnavailable(request.subject, request.snapshot, 'vfx'));\n}\n\nexport function createVfxPreviewContribution(\n runner: PreviewDomainRunner<VfxPreviewRequest, VfxPreviewReport> = async (request) =>\n defaultVfxRunner(request),\n): ToolContribution<VfxPreviewRequest, unknown> {\n return defineTool(vfxPreviewDescriptor, async (request, context) => {\n const result = await runner(request, context);\n if (!result.ok) return result;\n const report = result.value.report;\n const expectedDigest = vfxDeterministicDigest(request);\n if (\n report.bindingGuid !== request.subject.guid ||\n report.seed !== request.simulation.seed ||\n report.deltaSeconds !== request.simulation.deltaSeconds ||\n report.frames !== request.simulation.frames ||\n report.computeSteps !== request.simulation.frames ||\n report.drawCalls !== request.simulation.frames ||\n report.subjectOutputDigest.length === 0 ||\n report.deterministicDigest !== expectedDigest ||\n report.captureNonBlackPixels <= 0\n ) {\n return domainFailure(\n 'preview-subject-falsified',\n 'the effect binding, fixed simulation input, compute/draw steps, and subject output to agree',\n 'Reject stale seed/delta reports and captures without a subject output.',\n {\n requestGuid: request.subject.guid,\n reportBindingGuid: report.bindingGuid,\n expectedDigest,\n actualDigest: report.deterministicDigest,\n computeSteps: report.computeSteps,\n drawCalls: report.drawCalls,\n },\n );\n }\n const validated = validateDomainValue(result.value, request);\n if (!validated.ok) return validated;\n return { ok: true, value: validated.value };\n });\n}\n\nexport const vfxPreview = defineTool(subjectDescriptor('vfx'), (args, context) =>\n (async () => {\n const host = context.require(previewHostCapability);\n if (!host.ok) return host;\n return host.value.withSession(async (mechanisms) =>\n executeVfxPreview(args, {\n ...(mechanisms.assets === undefined ? {} : { assets: mechanisms.assets }),\n ...(mechanisms.renderer === undefined ? {} : { renderer: mechanisms.renderer }),\n runId: mechanisms.runId,\n ...(mechanisms.artifacts === undefined ? {} : { artifacts: mechanisms.artifacts }),\n }),\n );\n })(),\n);\nexport const vfxPreviewPlugin = nativePreviewPlugin('vfx', vfxPreview);\nexport default vfxPreviewPlugin;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forgeax/engine-preview",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.36",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -38,9 +38,9 @@
|
|
|
38
38
|
"LICENSE"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@forgeax/engine-plugin": "0.1.
|
|
42
|
-
"@forgeax/engine-tool-runtime": "0.1.
|
|
43
|
-
"@forgeax/engine-types": "0.1.
|
|
41
|
+
"@forgeax/engine-plugin": "0.1.36",
|
|
42
|
+
"@forgeax/engine-tool-runtime": "0.1.36",
|
|
43
|
+
"@forgeax/engine-types": "0.1.36"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/node": "^20.14.0",
|