@deepblend/dsh-blender-host 0.3.9 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/asset-preview.js +3 -0
- package/lib/diagnostic-preview.js +3 -0
- package/lib/index.js +5 -0
- package/lib/revision-transaction.js +3 -0
- package/lib/runtime-scene-features.js +21 -0
- package/package.json +2 -2
- package/recipes/modular-speaker/recipe.json +2428 -5
- package/recipes/modular-speaker/scene-spec.json +48 -16
package/lib/asset-preview.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** Fixed asset preview scenes, compiled in batch mode outside project revisions. */
|
|
2
|
+
import { assertRuntimeSceneFeatures } from './runtime-scene-features.js'
|
|
2
3
|
import { copyFileSync, existsSync, writeFileSync } from 'node:fs'
|
|
3
4
|
import { join } from 'node:path'
|
|
4
5
|
import { randomUUID } from 'node:crypto'
|
|
@@ -100,6 +101,8 @@ export async function renderAssetPreview({ runtime, asset, directory, maxMeshPol
|
|
|
100
101
|
'The isolated preview scene is invalid.', { detail: { errors: checked.errors } })
|
|
101
102
|
const compiled = compileSceneSpec(scene).spec
|
|
102
103
|
writeFileSync(sceneSpecPath, JSON.stringify(compiled))
|
|
104
|
+
const featureCheck = assertRuntimeSceneFeatures(runtime, compiled, { signal })
|
|
105
|
+
if (featureCheck) await featureCheck
|
|
103
106
|
const result = await runtime.compileScene({ sceneSpecPath, profile: 'preview', projectRoot: directory,
|
|
104
107
|
jobId: `asset-compile-${randomUUID()}`, session: false, signal,
|
|
105
108
|
onWorkingDirectory: info => { copyFileSync(join(info.directory, 'result.blend'), checkpointPath) } })
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
/** Isolated inspection renders. Successful tasks are published with one directory rename. */
|
|
2
|
+
import { assertRuntimeSceneFeatures } from './runtime-scene-features.js'
|
|
2
3
|
import { createReadStream, copyFileSync, existsSync, mkdirSync, readdirSync, renameSync, writeFileSync } from 'node:fs'
|
|
3
4
|
import { dirname, join } from 'node:path'
|
|
4
5
|
import { randomUUID } from 'node:crypto'
|
|
@@ -186,6 +187,8 @@ export async function renderDiagnostic(host, request) {
|
|
|
186
187
|
}
|
|
187
188
|
const sceneSpecPath = join(compileRoot, 'scene-spec.json'), checkpointPath = join(compileRoot, 'derived.blend')
|
|
188
189
|
writeJsonAtomic(sceneSpecPath, scene)
|
|
190
|
+
const featureCheck = assertRuntimeSceneFeatures(runtime, scene, { signal })
|
|
191
|
+
if (featureCheck) await featureCheck
|
|
189
192
|
const compiled = await runtime.compileScene({ sceneSpecPath, projectRoot: compileRoot, profile: 'preview',
|
|
190
193
|
jobId: `${jobId}-compile`, session: false, signal,
|
|
191
194
|
onWorkingDirectory: info => copyFileSync(join(info.directory, 'result.blend'), checkpointPath) })
|
package/lib/index.js
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* Plane: Host composition
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
+
import { assertRuntimeSceneFeatures } from './runtime-scene-features.js'
|
|
28
29
|
import { Service } from '@deepseek-ai/cordis'
|
|
29
30
|
import z from '@deepseek-ai/schemastery'
|
|
30
31
|
|
|
@@ -35,6 +36,7 @@ import {
|
|
|
35
36
|
BlenderError,
|
|
36
37
|
BlenderErrorCode,
|
|
37
38
|
CREATION_REQUEST_VERSION,
|
|
39
|
+
CAMERA_UPDATE_FIELDS,
|
|
38
40
|
BlenderWarningCode,
|
|
39
41
|
SCENE_PATCH_VERSION,
|
|
40
42
|
buildViewPlan,
|
|
@@ -626,6 +628,7 @@ export default class BlenderStudio extends Service {
|
|
|
626
628
|
}
|
|
627
629
|
|
|
628
630
|
get creationRequestProtocol() { return CREATION_REQUEST_VERSION }
|
|
631
|
+
get cameraTargetResetSupported() { return CAMERA_UPDATE_FIELDS.includes('clearTarget') }
|
|
629
632
|
|
|
630
633
|
async _createProject(request, creationRequest) {
|
|
631
634
|
const source = request.recipe ? this.recipes.instantiate(request.recipe) : null
|
|
@@ -1185,6 +1188,8 @@ export default class BlenderStudio extends Service {
|
|
|
1185
1188
|
*/
|
|
1186
1189
|
async compileRevisionForRender(input) {
|
|
1187
1190
|
const { projectId, revision, spec } = input
|
|
1191
|
+
const featureCheck = assertRuntimeSceneFeatures(this.runtime, spec, { signal: input.signal })
|
|
1192
|
+
if (featureCheck) await featureCheck
|
|
1188
1193
|
const scratch = resolveInside(
|
|
1189
1194
|
this.store.workspaceRoot,
|
|
1190
1195
|
join(this.store.workspaceRoot, 'tmp', `render-${revision}-${Date.now().toString(36)}`),
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
* Plane: Host composition
|
|
42
42
|
*/
|
|
43
43
|
|
|
44
|
+
import { assertRuntimeSceneFeatures } from './runtime-scene-features.js'
|
|
44
45
|
import { existsSync, mkdirSync, readdirSync, renameSync, statSync } from 'node:fs'
|
|
45
46
|
import { randomUUID } from 'node:crypto'
|
|
46
47
|
import { join } from 'node:path'
|
|
@@ -570,6 +571,8 @@ export class RevisionTransaction {
|
|
|
570
571
|
const checkpointStaging = join(staging, 'scene.blend')
|
|
571
572
|
|
|
572
573
|
try {
|
|
574
|
+
const featureCheck = assertRuntimeSceneFeatures(this.runtime, plan.spec, { signal: plan.signal })
|
|
575
|
+
if (featureCheck) await featureCheck
|
|
573
576
|
const run = await this.runtime.compileScene({
|
|
574
577
|
sceneSpecPath: specPath,
|
|
575
578
|
profile: plan.spec.renderProfiles?.preview === undefined ? undefined : 'preview',
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { BlenderError, BlenderErrorCode, requiredSceneFeatures } from '@deepblend/dsh-blender-contracts'
|
|
2
|
+
|
|
3
|
+
/** Old runtimes must not silently compile an axis-sized box as their scalar default. */
|
|
4
|
+
export function assertRuntimeSceneFeatures(runtime, spec, { signal } = {}) {
|
|
5
|
+
const required = requiredSceneFeatures(spec)
|
|
6
|
+
if (required.length === 0) return
|
|
7
|
+
return (async () => {
|
|
8
|
+
signal?.throwIfAborted()
|
|
9
|
+
const capabilities = typeof runtime?.getCapabilities === 'function'
|
|
10
|
+
? await runtime.getCapabilities({ signal }) : null
|
|
11
|
+
signal?.throwIfAborted()
|
|
12
|
+
if (capabilities?.installed === false) {
|
|
13
|
+
throw new BlenderError(BlenderErrorCode.NOT_FOUND, 'Blender is unavailable for this scene.')
|
|
14
|
+
}
|
|
15
|
+
const supported = Array.isArray(capabilities?.sceneFeatures) ? capabilities.sceneFeatures : []
|
|
16
|
+
const missing = required.filter(feature => !supported.includes(feature))
|
|
17
|
+
if (missing.length) throw new BlenderError(BlenderErrorCode.SCENE_FEATURE_UNSUPPORTED,
|
|
18
|
+
`The runtime does not support ${missing.join(', ')}. Update the runtime before compiling this scene.`,
|
|
19
|
+
{ detail: { required, supported, missing } })
|
|
20
|
+
})()
|
|
21
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepblend/dsh-blender-host",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "DeepBlend Host service: the blenderStudio business facade over the BlenderRuntime seam.",
|
|
6
6
|
"main": "lib/index.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"./package.json": "./package.json"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@deepblend/dsh-blender-contracts": "0.
|
|
23
|
+
"@deepblend/dsh-blender-contracts": "0.5.0",
|
|
24
24
|
"sharp": "0.35.5"
|
|
25
25
|
},
|
|
26
26
|
"license": "MIT",
|