@deepblend/dsh-blender-host 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/lib/index.js +110 -0
  2. package/package.json +2 -2
package/lib/index.js CHANGED
@@ -143,6 +143,84 @@ export function contentTypeForArtifact(path) {
143
143
  * "the host bundle is missing" error at runtime. */
144
144
  export const RUNTIME_SERVICE = 'blenderRuntime'
145
145
 
146
+ /**
147
+ * The configuration a diagnostic bundle may carry.
148
+ *
149
+ * AN ALLOWLIST, AND IT LIVES HERE BECAUSE THIS IS WHERE THE KEYS ARE DECLARED. `config-surface.test.mjs`
150
+ * holds every `config.<key>` a package reads to that package's own schema, and it is right to: a value read
151
+ * where it cannot arrive is a knob that lies. The UI half projecting the Host's configuration would be
152
+ * exactly that — the UI's own schema declares none of these keys. So the Host names them, and the UI
153
+ * asks for the projection.
154
+ *
155
+ * The direction of the default matters: a key added to `StudioConfig` later is ABSENT from a bundle
156
+ * until somebody adds it here. A spread would publish it, and the bundle is the one artifact that
157
+ * leaves the machine.
158
+ *
159
+ * @param {Record<string, unknown>} config - the resolved `StudioConfig`
160
+ * @returns {Record<string, unknown>}
161
+ */
162
+ export function diagnosticConfiguration(config) {
163
+ const source = config ?? {}
164
+ return {
165
+ projectsRoot: source.projectsRoot ?? null,
166
+ workspaceRoot: source.workspaceRoot ?? null,
167
+ maxPreviewSamples: source.maxPreviewSamples ?? null,
168
+ assetMaxBytes: source.assetMaxBytes ?? null,
169
+ maxMeshPolygons: source.maxMeshPolygons ?? null,
170
+ maxVisualIterations: source.maxVisualIterations ?? null,
171
+ minVisualConfidenceForAutoFix: source.minVisualConfidenceForAutoFix ?? null,
172
+ stopOnRepeatedIssueCount: source.stopOnRepeatedIssueCount ?? null,
173
+ visualReviewProvider: source.visualReviewProvider ?? null,
174
+ visualReviewModel: source.visualReviewModel ?? null,
175
+ visualReviewMaxTokens: source.visualReviewMaxTokens ?? null,
176
+ visualReviewViews: source.visualReviewViews ?? [],
177
+ finalRenderProfile: source.finalRenderProfile ?? null,
178
+ maxFinalSamples: source.maxFinalSamples ?? null,
179
+ ffmpegPath: source.ffmpegPath ?? null,
180
+ ffprobePath: source.ffprobePath ?? null,
181
+ encodeCrf: source.encodeCrf ?? null,
182
+ encodePreset: source.encodePreset ?? null,
183
+ requireApprovalAboveFrames: source.requireApprovalAboveFrames ?? null,
184
+ progressPollMs: source.progressPollMs ?? null,
185
+ reconcileOnStart: source.reconcileOnStart ?? null,
186
+ orphanGraceMs: source.orphanGraceMs ?? null,
187
+ }
188
+ }
189
+
190
+ /**
191
+ * The product's version, from this package's own manifest.
192
+ *
193
+ * NOT A CONSTANT, and not a second copy of the number: `deepblend/version.json` is the single source,
194
+ * `tools/release-version.mjs --check` holds all eight manifests to it, so reading any one of them
195
+ * answers for the product — and `contract/diagnostics.test.mjs` compares what this returns against
196
+ * the source, which is what makes it a reading rather than a third copy.
197
+ *
198
+ * It answers `null` rather than throwing: the diagnostic bundle is what a user produces when
199
+ * something is already wrong, and a version field that crashed the export would be the least useful
200
+ * failure in the product. Read once and remembered — a manifest does not change under a running
201
+ * process.
202
+ *
203
+ * AND IT IS HERE, not in the UI half, because that half is asserted to import no filesystem module
204
+ * at all (`composition/ui-plane.e2e.mjs`): it is the layer the browser talks to. The first version of
205
+ * the diagnostics bundle read this manifest in `ui/lib/index.js` and that suite went red, correctly.
206
+ *
207
+ * @returns {string|null}
208
+ */
209
+ export function readProductVersion() {
210
+ if (cachedProductVersion === undefined) {
211
+ try {
212
+ const manifest = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'))
213
+ cachedProductVersion = typeof manifest.version === 'string' ? manifest.version : null
214
+ } catch {
215
+ cachedProductVersion = null
216
+ }
217
+ }
218
+ return cachedProductVersion
219
+ }
220
+
221
+ /** @type {string|null|undefined} */
222
+ let cachedProductVersion
223
+
146
224
  /**
147
225
  * Host-level configuration. Mirrors SPEC §17.
148
226
  *
@@ -400,6 +478,38 @@ export default class BlenderStudio extends Service {
400
478
  return HOST_API_VERSION
401
479
  }
402
480
 
481
+ /**
482
+ * The product's version, read from this package's own manifest.
483
+ *
484
+ * HERE RATHER THAN IN THE UI HALF, and that is a rule rather than a preference: the UI host is
485
+ * asserted to import no filesystem module at all (`composition/ui-plane.e2e.mjs`), because that
486
+ * layer is the one the browser talks to. The first version of the diagnostics bundle read this
487
+ * manifest in `ui/lib/index.js` and that suite went red, correctly.
488
+ *
489
+ * NOT A CONSTANT, and not a second copy of the number: `deepblend/version.json` is the single
490
+ * source, `tools/release-version.mjs --check` holds all eight manifests to it, so reading any one
491
+ * of them answers for the product — and `contract/diagnostics.test.mjs` compares what this returns
492
+ * against the source, which is what makes it a reading rather than a third copy.
493
+ *
494
+ * It answers `null` rather than throwing: the diagnostic bundle is what a user produces when
495
+ * something is already wrong, and a version field that crashed the export would be the least
496
+ * useful failure in the product.
497
+ *
498
+ * @returns {string|null}
499
+ */
500
+ productVersion() {
501
+ return readProductVersion()
502
+ }
503
+
504
+ /**
505
+ * The Host's own configuration, as a diagnostic bundle may carry it.
506
+ *
507
+ * @returns {Record<string, unknown>}
508
+ */
509
+ describeConfiguration() {
510
+ return diagnosticConfiguration(this.config)
511
+ }
512
+
403
513
  // ---------------------------------------------------------------------------
404
514
  // Capabilities (M0)
405
515
  // ---------------------------------------------------------------------------
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@deepblend/dsh-blender-host",
3
- "version": "0.1.0",
3
+ "version": "0.2.1",
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.1.0"
23
+ "@deepblend/dsh-blender-contracts": "0.2.1"
24
24
  },
25
25
  "license": "MIT",
26
26
  "repository": {