@womp/spark-agent 4.4.0 → 4.4.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.
package/README.md CHANGED
@@ -102,11 +102,12 @@ A failed barrier aborts the loop. The default model-step limit is 100; a limit r
102
102
 
103
103
  Spark does not estimate or limit input tokens or automatically shorten conversation history.
104
104
  The provider enforces its context limit; rejections follow the normal provider-error path.
105
- Provider-reported usage and cost tracking are unchanged.
106
105
 
107
- Screenshot and file APIs return serializable artifact references. `emitImage` and `emitFile` resolve
108
- them through the host's artifact resolver. Keep references resolvable when reloading history, and
109
- pass `createSparkTools(...)` to AI SDK's `convertToModelMessages` to reconstruct multimodal results.
106
+ Screenshot and file APIs return serializable artifact references. `emitImage` and `emitFile` resolve
107
+ them through the host's artifact resolver. Keep references resolvable when reloading history, and
108
+ pass `createSparkTools(...)` to AI SDK's `convertToModelMessages` to reconstruct multimodal results.
109
+ `emitImage(artifact, { inspect: false })` displays an image without adding its bytes to model input,
110
+ including restored history. Inspection is enabled by default.
110
111
  Kakapo skill declarations are generated from its actual typed API during the build and packaged as
111
112
  JavaScript strings; they do not need filesystem or Markdown loading in the browser.
112
113
 
@@ -142,9 +143,11 @@ const chat = useChat<SparkUIMessage>({
142
143
  ```
143
144
 
144
145
  Render `message.parts`. Standard AI SDK parts represent text, reasoning, files, tool inputs, tool
145
- outputs, approvals, and step boundaries. Spark adds typed `data-console`, `data-artifact`,
146
- `data-run-status`, `data-step-metrics`, and `data-execution-receipt` parts. Receipts are emitted before
147
- their storage barrier, keeping known effects visible even when saving the tool result fails.
146
+ outputs, approvals, and step boundaries. Spark adds typed `data-console`, `data-artifact`,
147
+ `data-run-status`, `data-step-metrics`, and `data-execution-receipt` parts. Receipts are emitted before
148
+ their storage barrier, keeping known effects visible even when saving the tool result fails.
149
+ Hosts can consume `data-tool-input-label` once the tool's label field is complete, while the
150
+ remaining input is still streaming.
148
151
 
149
152
  An explicit Stop action must cancel the durable run before stopping local observation:
150
153
 
@@ -174,7 +177,7 @@ that turn, independently of the selector.
174
177
 
175
178
  Custom stores must implement `saveConversationSettings` as a settings-only update, and preserve
176
179
  stored settings during `saveConversation` so streaming history saves cannot overwrite preferences.
177
- The built-in memory and SQLite stores do this without a database migration.
180
+ The built-in memory and SQLite stores implement this contract.
178
181
 
179
182
  The SSE response contains ordered persistence envelopes around standard AI SDK chunks:
180
183
 
@@ -219,9 +222,17 @@ app.use(
219
222
  );
220
223
  ```
221
224
 
222
- `MemorySparkAgentStore` and `MemorySparkArtifactStore` are development implementations. Production
223
- hosts must supply durable implementations backed by their database/object storage and must preserve
224
- the ordering contract of `appendRunChunk()`.
225
+ `MemorySparkAgentStore` and `MemorySparkArtifactStore` are development implementations. Production
226
+ hosts must supply durable implementations backed by their database/object storage and must preserve
227
+ the ordering contract of `appendRunChunk()`.
228
+
229
+ `SparkAgentServiceOptions.endOrphanedRuns` defaults to `false`. Enable it only when one process
230
+ owns the store: a message or Stop then ends unfinished runs not held by that process. On a shared
231
+ store, enabling it could end another process's live run.
232
+
233
+ Custom stores can implement `releaseActiveRun(conversationId, runId, updatedAt)` to clear the active
234
+ run only if its ID still matches. Memory and SQLite stores implement it. Without it, the service
235
+ serializes read-and-save release against its own submissions.
225
236
 
226
237
  ## Standalone development server
227
238
 
@@ -257,8 +268,8 @@ acknowledgement proves only renderer-local history, not durable backend storage.
257
268
  The standalone server persists conversations, run streams, and screenshot bytes in SQLite. Only
258
269
  one local process can execute against a database. After a terminated process is replaced, startup
259
270
  preserves recorded output and marks abandoned queued/running runs incomplete without replaying
260
- scene edits. Pending approvals remain pending. Full operation reconciliation and run continuation
261
- are still being integrated. Node 22 reports an experimental warning for its built-in SQLite module.
271
+ scene edits. Pending approvals remain pending; startup does not resume abandoned runs.
272
+ Node 22 reports an experimental warning for its built-in SQLite module.
262
273
 
263
274
  Set `SPARK_SCENE_IDENTITY` only when the host can verify that the value names the same durable
264
275
  scene across renderer reconnects. Without it, Spark uses a process-scoped identity and does not
@@ -267,9 +278,8 @@ authorize interrupted scene mutations to continue after a server restart.
267
278
  `createStandaloneSparkAgentApp(options)` is asynchronous. Await it before listening, and call
268
279
  `await app.dispose()` on shutdown to settle active runs and release storage ownership.
269
280
 
270
- This development branch currently installs `kakapo-sdk` from the sibling checkout. Run `yarn build`
271
- in `../kakapo-sdk` before installing Spark dependencies. A registry version must replace this local
272
- dependency before release; no new package has been published by this migration.
281
+ When using a sibling `kakapo-sdk` dependency, run `yarn build` in `../kakapo-sdk` before installing
282
+ Spark dependencies. Replace local dependencies with registry versions before publishing.
273
283
 
274
284
  For the explicit fictional account profile, use `yarn dev:demo-account` or
275
285
  `spark-agent --profile demo-account`. It adds the `account` skill and `womp.account.read`
@@ -345,85 +355,17 @@ yarn test
345
355
  yarn web:build
346
356
  ```
347
357
 
348
- ## Release procedure
349
-
350
- Releases use a manual package publication; no separate release service is required.
351
-
352
- ### Migration to 0.3
353
-
354
- - The package root is browser-safe. Import `KakapoRuntime`, `createWompSceneApi`, and its enums
355
- from `/kakapo`, and `QuickJSJavaScriptExecutor` from `/quickjs`.
356
- - `runSparkAgent` takes the host's selected model, executor, capability composition, artifact
357
- resolver, and persistence hooks. The host owns connection setup and disposal. The model sees
358
- only `read_skill` and `execute_javascript`; domain methods live under the supplied `womp` APIs.
359
- - Replace fixed scene/screenshot tool history with the host's history adapter. Use
360
- `convertSparkMessages` when rebuilding model input from current Spark UI messages so artifact
361
- references become model-visible content. Preserve old records; do not replay historical tools.
362
- - Custom server executors receive `uiMessages` and convert them using their actual capability
363
- tools. `SparkRunExecutionContext.modelMessages` has been removed.
364
- - Custom JavaScript executors must honor cancellation and host-owned user waits. Callback-based
365
- scene edits and artifact references work with both the native and QuickJS executors.
366
-
367
- ### 4.1.0
368
-
369
- - `emitImage(artifact, { inspect: false })` displays an image without adding its bytes to model input, including restored history. Inspection remains the default.
370
- - Generation instructions use completed outputs directly and avoid redundant listing or emission; explicit inspection and follow-up imports remain supported.
371
- - Streamed tool labels are emitted only after their label field is complete. Hosts can consume `data-tool-input-label` while the rest of the input streams.
372
- - Server cancellation waits for active execution to settle before reporting its terminal state.
373
- - Includes the latest geometry material, scalar-port, and primitive improvements from main.
374
-
375
- ### 4.2.2
376
-
377
- The published 4.2.1 was packed from the 4.2.0 sources and differs from 4.2.0 only in its version
378
- number, so none of the changes below are in it. Use 4.2.2.
379
-
380
- Compatible: both additions are optional, and a host that sets neither behaves as before except that a
381
- run whose progress cannot be stored now ends instead of staying `running`.
382
-
383
- - A run whose stream chunk, `running` status or ending cannot be stored ends `failed` with a sentence
384
- instead of staying `running` until a restart. The final status and the conversation release are
385
- retried in the background for about five minutes; a message or a Stop for that conversation stores
386
- the ending at once.
387
- - `SparkAgentServiceOptions.endOrphanedRuns` (default `false`): a message or a Stop ends an unfinished
388
- active run that no execution in this process holds, with "This run stopped unexpectedly and could
389
- not be finished." Turn it on only when one process owns the store; on a shared store it would end
390
- another process's live runs.
391
- - `SparkAgentStore.releaseActiveRun(conversationId, runId, updatedAt)` (optional): clears the active
392
- run only while it still names that run. The memory and SQLite stores implement it. A store without
393
- it has the read-and-save release serialised against the service's own submits, so a late retry
394
- cannot overwrite a newer message.
395
-
396
- ### 4.2.0
397
-
398
- Incompatible: a color that can only be a 0-1 one is now refused where it used to be stored as
399
- near-black, and the `scene-editing` skill payload changed. Hosts that pin the skill surface in a
400
- fixture must regenerate it.
401
-
402
- - Model-facing colors state their domain in the declared parameter name: `nodeSetColor`,
403
- `materialSetColor`, `materialSetSecondaryColor`, `materialSetSubsurfaceColor` and
404
- `setBackgroundColor` take `rgb255`, and the internal type is `Color255`. The `scene-editing` skill
405
- version is 30.
406
- - A color whose every component is strictly between 0 and 1 and none an integer throws, naming the
407
- 0-255 conversion (`{r:0.2, g:0.4, b:0.6}` → "use `{r:51, g:102, b:153}` … or `{r:0, g:0, b:0}` for
408
- black"). Nothing is auto-scaled: `{r:1, g:0, b:0}`, `{r:0, g:0, b:0}`, `{r:0.5, g:0, b:0}` and
409
- every 0-255 color write exactly as before.
410
- - `scene.health` accepts the object ids `scene.read()` publishes, including `0`; a value that is not
411
- an id is refused with a sentence naming it instead of a serialized schema error. Ids belonging to
412
- no Area (the root, a root-level Group, a Light) are dropped and reported rather than making the
413
- whole reading `unverified`.
414
- - A tool result can no longer cost a turn. Geometry diagnostics quote a source line once per line
415
- and cap at 5 diagnostics and 4 KiB; the `execute_javascript` envelope bounds the error to 8 KiB and
416
- the receipts to a 1 MiB model input, always as valid JSON. Only model input is bounded —
417
- `persistence.afterToolCall`, the UI stream and the host's own receipts keep the original object.
418
- - A scene-health receipt keeps its totals, limits and overflow flags whole and bounds the per-Area
419
- rows to 8, affected and overflowing Areas first, naming the omission in `reason`. Health read for a
420
- decision (`hasGeometryOverflow`, `hasSceneResourcePressure`, `options.onHealth`) still sees every
421
- row, so no repair decision changes. A consumer fixture that recorded a receipt with more than 8
422
- Areas will differ.
423
- - `operations.generate` keeps a host's own cancellation message on a stopped generation instead of
424
- replacing it with the bare abort reason.
425
-
426
- ### Publishing
358
+ ## Release procedure
359
+
360
+ Releases use a manual package publication; no separate release service is required.
361
+
362
+ Versions follow **MAJOR.MINOR.PATCH** (for example, `4.4.0`):
363
+
364
+ - **Major:** breaking changes.
365
+ - **Minor:** backward-compatible new features.
366
+ - **Patch:** backward-compatible bug fixes.
367
+
368
+ ### Publishing
427
369
 
428
370
  1. Choose an unused package version after checking `npm view @womp/spark-agent versions --json`.
429
371
  Update `package.json` and record public API changes and migration notes. Use a new minor version
@@ -0,0 +1,9 @@
1
+ import type { KakapoAPI, Vec3, CameraConfiguration } from "@womp/kakapo-sdk";
2
+ export type BenchBounds = {
3
+ min: Vec3;
4
+ max: Vec3;
5
+ };
6
+ /** Groups organize geometry; query their visible renderable children, not Group bounds. */
7
+ export declare function benchGeometryIds(api: Pick<KakapoAPI, "listNodes">, parentId?: number): number[];
8
+ /** Fixed Spark-space three-quarter view, fitted against all eight native-world bounding-box corners. */
9
+ export declare function benchCamera(bounds: BenchBounds, aspect: number): CameraConfiguration;
@@ -0,0 +1,32 @@
1
+ import { toEnginePosition } from "./coordinates.js";
2
+ /** Groups organize geometry; query their visible renderable children, not Group bounds. */
3
+ export function benchGeometryIds(api, parentId = 0) {
4
+ return api.listNodes({ parentId }).flatMap(node => {
5
+ if (("hidden" in node && node.hidden) || node.kind === "light")
6
+ return [];
7
+ return node.kind === "group" ? benchGeometryIds(api, node.id) : [node.id];
8
+ });
9
+ }
10
+ /** Fixed Spark-space three-quarter view, fitted against all eight native-world bounding-box corners. */
11
+ export function benchCamera(bounds, aspect) {
12
+ const axes = ["x", "y", "z"];
13
+ if (!Number.isFinite(aspect) || aspect <= 0 || axes.some(a => !Number.isFinite(bounds.min[a]) || !Number.isFinite(bounds.max[a]) || bounds.min[a] > bounds.max[a]))
14
+ throw new Error("Benchmark framing requires finite ordered bounds and a positive aspect ratio.");
15
+ const target = { x: (bounds.min.x + bounds.max.x) / 2, y: (bounds.min.y + bounds.max.y) / 2, z: (bounds.min.z + bounds.max.z) / 2 };
16
+ const offset = toEnginePosition({ x: 1, y: 0.65, z: 1 });
17
+ const length = Math.hypot(offset.x, offset.y, offset.z);
18
+ const back = { x: offset.x / length, y: offset.y / length, z: offset.z / length };
19
+ const horizontal = Math.hypot(back.x, back.z);
20
+ const right = { x: back.z / horizontal, y: 0, z: -back.x / horizontal };
21
+ const up = { x: -back.x * back.y / horizontal, y: horizontal, z: -back.z * back.y / horizontal };
22
+ const dot = (a, b) => a.x * b.x + a.y * b.y + a.z * b.z;
23
+ const tanH = Math.tan(Math.PI / 6);
24
+ let distance = 0.1;
25
+ for (const x of [bounds.min.x, bounds.max.x])
26
+ for (const y of [bounds.min.y, bounds.max.y])
27
+ for (const z of [bounds.min.z, bounds.max.z]) {
28
+ const point = { x: x - target.x, y: y - target.y, z: z - target.z };
29
+ distance = Math.max(distance, dot(point, back) + 1.1 * Math.max(Math.abs(dot(point, right)) / tanH, Math.abs(dot(point, up)) * aspect / tanH));
30
+ }
31
+ return { position: { x: target.x + back.x * distance, y: target.y + back.y * distance, z: target.z + back.z * distance }, target, projection: "perspective", horizontalFovDegrees: 60 };
32
+ }
@@ -1,18 +1,5 @@
1
- // Byte budgets for everything a tool call hands back to the model.
2
- //
3
- // WHY THIS FILE EXISTS. `execute_javascript` already refuses a printed payload
4
- // or a returned value over 1 MiB (agent-tools.ts `jsonValue` and `print`), but
5
- // nothing bounded the rest of the envelope: the `error` string and the receipts.
6
- // One rejected `geometry.write` over a one-character enum value produced a
7
- // compiler diagnostic that repeated the offending source line once per
8
- // diagnostic, and the resulting tool result cost a whole turn -- 65,136 output
9
- // tokens, a run that ended `incomplete`, ~235 KB rendered into the panel and an
10
- // unresponsive tab. A bad argument must cost one tool result, not a turn, so the
11
- // same budget that guards `print` now guards the whole serialized result.
12
- //
13
- // These helpers truncate and say so. They never throw: an over-long diagnostic
14
- // is still the most useful thing the model can read, so it is cut and labelled
15
- // rather than replaced.
1
+ // Bound the full serialized tool result, including errors and receipts, before
2
+ // handing it to the model. Oversized diagnostics are cut and labelled.
16
3
  const encoder = new TextEncoder();
17
4
  const decoder = new TextDecoder();
18
5
  export const MODEL_RESULT_BYTE_LIMIT = 1024 * 1024;
@@ -37,10 +24,11 @@ export function truncateUtf8(text, limit) {
37
24
  * incomplete rather than wrong.
38
25
  */
39
26
  export function boundedText(text, limit, label) {
40
- const total = byteLength(text);
27
+ const bytes = encoder.encode(text);
28
+ const total = bytes.byteLength;
41
29
  if (total <= limit)
42
30
  return text;
43
- const kept = truncateUtf8(text, limit);
31
+ const kept = decoder.decode(bytes.subarray(0, limit)).replace(/�$/u, "");
44
32
  return `${kept}\n[${label} truncated at ${limit} bytes; ${total - byteLength(kept)} bytes omitted.]`;
45
33
  }
46
34
  /**
@@ -67,12 +55,13 @@ export function boundedResultText(output, limit = MODEL_RESULT_BYTE_LIMIT) {
67
55
  if (receipt.details === undefined)
68
56
  return receipt;
69
57
  const details = asText(receipt.details);
70
- if (byteLength(details) <= detailsLimit)
58
+ const detailsBytes = byteLength(details);
59
+ if (detailsBytes <= detailsLimit)
71
60
  return receipt;
72
61
  return {
73
62
  ...receipt,
74
63
  details: {
75
- omitted: `This receipt's details were ${byteLength(details)} bytes, over the ${detailsLimit} byte limit for one receipt in a tool result. Read the receipt from the host if the outcome matters.`,
64
+ omitted: `This receipt's details were ${detailsBytes} bytes, over the ${detailsLimit} byte limit for one receipt in a tool result. Read the receipt from the host if the outcome matters.`,
76
65
  },
77
66
  };
78
67
  });
@@ -1,4 +1,5 @@
1
1
  import { z } from "zod";
2
+ import { maxLightIntensity } from "@womp/kakapo-sdk";
2
3
  import { WOMP_SCENE_DECLARATIONS } from "../generated/scene-declarations.js";
3
4
  import { unverifiedSceneHealth } from "../scene-health.js";
4
5
  // A node id, as `scene.read()` publishes them: the scene root is 0, so a health
@@ -37,7 +38,7 @@ export function createSceneCapability(host) {
37
38
  skills: [
38
39
  {
39
40
  name: "scene-editing",
40
- version: "39",
41
+ version: "42",
41
42
  description: "Inspect the open scene and edit its objects, materials, curves, and environment.",
42
43
  instructions: `Read the scene first and keep its revision and object IDs. read() includes health.
43
44
  Use womp.scene.health() to refresh whole-scene health or womp.scene.health(objectIds) to check specific objects (mapped to their owning Areas).
@@ -56,7 +57,10 @@ known IDs when editing rather than creating duplicates. Distances follow the cur
56
57
  Convert a dimension in millimetres to project units by multiplying it by read().unitMultiplier.
57
58
  The SDK-backed draft clamps dimension writes to 0.01–1000 mm per component before converting to native units; this is an adapter limit, not a scene-wide size limit. Read back dimensions when physical size matters.
58
59
  Area size is a dimensionless scale; Group size stays fixed at one. Lights must be created at root (parentId 0); their size has x/y dimensions.
59
- Light power must be a finite number in [0, 100].
60
+ Light power is linear emitted intensity before collimation, not a percentage or physical unit: doubling it doubles emission, not tone-mapped pixel brightness. Valid ranges are 0–${maxLightIntensity("rect")} for Rect/Sphere and 0–${maxLightIntensity("distant")} for Distant; these limits are not brightness targets. A light-type change preserves intensity and rejects values outside the new type's range; lower intensity first if needed. Rect size is width/height; Sphere uses x as diameter; Distant uses direction, not position or size.
61
+ Use nodeSetFacing(id, target - position) to aim light emission or the readable face of text/decals at a target in the same parent-local space. It keeps Y up (Z up for vertical directions); generic lookAt aligns a different axis and does not aim these faces.
62
+ For text, nodeSetTextSize(id, {fontSize, depth}) sets font em size and extrusion in project units, not a bounding box. Layout width and additional letter spacing also use project units; spacing clamps to ±25 mm. Line height is a multiplier clamped to 0.5–3. The origin anchors the first baseline; alignment uses the layout width. Empty text clears its geometry.
63
+ Decals require an existing loaded image and receiving geometry. Projection is a uniform cube: native scale.x (public size.z) controls all dimensions, not independent width/height/depth. Restriction to an Area requires that parent Area; root decals project globally. Missing image data can yield no projection even when no resource is pending.
60
64
  nodeCreate(Curve, parentId) creates an empty curve with zero blend. curvePointAdd(curveId, point, index?) returns the new index; omit index to append or supply an integer from 0 through point count to insert before that position.
61
65
  Point defaults: position/rotation/handles zero, profile size {x:1,y:1,z:1} in project units, the curve's material, fixed false, round 0. Pass {} for defaults.
62
66
  Removing all points is supported. One point renders a single profile primitive, not a path.
@@ -107,7 +111,7 @@ For library materials, use listSuperMaterials(), then await materialImport(name)
107
111
  Filter large read results with JavaScript and print only useful details.
108
112
  After a major edit, capture a screenshot outside the transaction and emitImage its reference.
109
113
  screenshot({ camera: { position: {x,y,z}, target: {x,y,z}, projection: 'perspective', horizontalFovDegrees: 60 } })
110
- sets a world-space camera in the same Womp coordinates and project units as scene positions (Y-up).
114
+ sets a world-space camera in the same Womp coordinates and project units as scene positions (Y-up).
111
115
  For orthographic framing use projection: 'orthographic' and orthographicWidth in project units instead of FOV.
112
116
  Direction is derived from position/target; do not use coincident points or an exactly vertical viewing direction.
113
117
  Omitted projection/lens settings come from the active camera. Pass the camera again for repeatable captures.
@@ -1 +1 @@
1
- export declare const WOMP_SCENE_DECLARATIONS = "declare const womp: { scene: {\n\"read\": (() => Promise<{\n\"health\": {\n\"status\": \"within_limits\" | \"overflow\" | \"unverified\";\n\"freshness\": \"unverified\" | \"snapshot\" | \"post_ack_event\";\n\"revisionVerified\": false;\n\"affectedAreaIds\": Array<string>;\n\"emptyAreaIds\"?: undefined | Array<string>;\n\"thermometer\"?: undefined | {\n\"objects\": {\n[key: string]: {\n\"num_prims\": number;\n\"flag_prim_overflow\": number;\n\"flag_depth_overflow\": number;\n\"flag_vox_overflow\": number;\n\"voxels\": number;\n};\n};\n\"max_num_prims\": number;\n\"max_total_depth\": number;\n\"max_per_object\": number;\n\"total\": number;\n\"max_total\": number;\n\"assets_budget_used\": number;\n\"assets_budget_total\": number;\n\"mesh_instances_used\"?: undefined | number;\n\"mesh_instances_total\"?: undefined | number;\n\"decal_instances_used\"?: undefined | number;\n\"decal_instances_total\"?: undefined | number;\n\"field_instances_used\"?: undefined | number;\n\"field_instances_total\"?: undefined | number;\n};\n\"reason\"?: undefined | string;\n};\n\"revision\": string;\n\"projectId\"?: undefined | number;\n\"unitMultiplier\": number;\n\"nodes\": Array<{\n\"id\": number;\n\"name\": string;\n\"type\": number;\n\"parentId\": number;\n}>;\n}>);\n\"health\": ((objectIds?: undefined | Array<number>) => Promise<{\n\"status\": \"within_limits\" | \"overflow\" | \"unverified\";\n\"freshness\": \"unverified\" | \"snapshot\" | \"post_ack_event\";\n\"revisionVerified\": false;\n\"affectedAreaIds\": Array<string>;\n\"emptyAreaIds\"?: undefined | Array<string>;\n\"thermometer\"?: undefined | {\n\"objects\": {\n[key: string]: {\n\"num_prims\": number;\n\"flag_prim_overflow\": number;\n\"flag_depth_overflow\": number;\n\"flag_vox_overflow\": number;\n\"voxels\": number;\n};\n};\n\"max_num_prims\": number;\n\"max_total_depth\": number;\n\"max_per_object\": number;\n\"total\": number;\n\"max_total\": number;\n\"assets_budget_used\": number;\n\"assets_budget_total\": number;\n\"mesh_instances_used\"?: undefined | number;\n\"mesh_instances_total\"?: undefined | number;\n\"decal_instances_used\"?: undefined | number;\n\"decal_instances_total\"?: undefined | number;\n\"field_instances_used\"?: undefined | number;\n\"field_instances_total\"?: undefined | number;\n};\n\"reason\"?: undefined | string;\n}>);\n\"edit\": (<T>(callback: ((draft: {\n\"listSuperMaterials\": (() => Array<string>);\n\"_getParentId\": ((childId: number) => number);\n\"_getScaleProductUpTo\": ((nodeId: number, includeNodeSelfUnion?: false | true) => number);\n\"NodeType\": {\n\"Primitive\": 0;\n\"Union\": 1;\n\"Light\": 2;\n\"Curve\": 3;\n\"Group\": 4;\n\"Text\": 5;\n\"Field\": 6;\n\"SVG\": 7;\n\"Mesh\": 8;\n\"Decal\": 9;\n\"OpenSCAD\": 10;\n\"Socket\": 11;\n} & {\n[key: number]: string;\n};\n\"PrimitiveType\": {\n\"Sphere\": 0;\n\"Cylinder\": 1;\n\"Cube\": 2;\n\"Cone\": 3;\n\"Torus\": 4;\n\"Pyramid\": 9;\n} & {\n[key: number]: string;\n};\n\"OperationType\": {\n\"Subtract\": 0;\n\"Union\": 1;\n\"Stain\": 2;\n\"Intersect\": 3;\n} & {\n[key: number]: string;\n};\n\"LightType\": {\n\"Rect\": 0;\n\"Sphere\": 1;\n\"Distant\": 2;\n} & {\n[key: number]: string;\n};\n\"nodeCreate\": ((type: number, parentId?: number) => number);\n\"nodeDelete\": ((id: number) => void);\n\"nodeClone\": ((id: number) => number);\n\"cloneSubtree\": ((id: number, options?: {\n\"parentId\"?: undefined | number;\n\"name\"?: undefined | string;\n\"index\"?: undefined | number;\n}) => Promise<number>);\n\"nodeList\": (() => Array<number>);\n\"nodeChildren\": ((parentId: number) => Array<number>);\n\"nodeSetParent\": ((id: number, parentId: number, index?: undefined | number) => void);\n\"nodeGetType\": ((id: number) => number);\n\"nodeGetName\": ((id: number) => string);\n\"nodeSetName\": ((id: number, name: string) => void);\n\"nodeGetParentId\": ((id: number) => number);\n\"nodeGetPos\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeGetLock\": ((id: number) => false | true);\n\"nodeSetLock\": ((id: number, locked: false | true) => void);\n\"nodeSetPos\": ((id: number, position: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetRot\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeSetRot\": ((id: number, rotation: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetSize\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n} | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeSetSize\": ((id: number, sizeValue: {\n\"x\": number;\n\"y\": number;\n} | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetHide\": ((id: number) => false | true);\n\"nodeSetHide\": ((id: number, hidden: false | true) => void);\n\"nodeGetOp\": ((id: number) => number);\n\"nodeSetOp\": ((id: number, operation: number) => void);\n\"nodeGetBlend\": ((id: number) => number);\n\"nodeSetBlend\": ((id: number, blend: number) => void);\n\"nodeGetRound\": ((id: number) => number);\n\"nodeSetRound\": ((id: number, round: number) => void);\n\"nodeGetColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"nodeSetColor\": ((id: number, rgb255: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n} | {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"nodeGetMaterialId\": ((id: number) => null | number);\n\"nodeSetMaterialId\": ((id: number, materialId: number) => void);\n\"nodeGetResolution\": ((id: number) => number);\n\"nodeSetUnionResolution\": ((unionId: number, resolution: number) => void);\n\"nodeGetLightType\": ((id: number) => number);\n\"nodeSetLightType\": ((id: number, lightType: number) => void);\n\"nodeGetPower\": ((id: number) => number);\n\"nodeSetPower\": ((id: number, power: number) => void);\n\"nodeGetText\": ((id: number) => string);\n\"nodeSetText\": ((id: number, text: string) => void);\n\"nodeGetFont\": ((id: number) => string);\n\"nodeSetFont\": ((id: number, font: string) => void);\n\"nodeGetWeight\": ((id: number) => number);\n\"nodeSetWeight\": ((id: number, weight: number) => void);\n\"nodeGetItalic\": ((id: number) => false | true);\n\"nodeSetItalic\": ((id: number, italic: false | true) => void);\n\"nodeGetAlign\": ((id: number) => number);\n\"nodeSetAlign\": ((id: number, align: number) => void);\n\"nodeGetWrap\": ((id: number) => number);\n\"nodeSetWrap\": ((id: number, wrap: number) => void);\n\"nodeGetWidth\": ((id: number) => number);\n\"nodeSetWidth\": ((id: number, width: number) => void);\n\"nodeGetSpacing\": ((id: number) => number);\n\"nodeSetSpacing\": ((id: number, spacing: number) => void);\n\"nodeGetLineHeight\": ((id: number) => number);\n\"nodeSetLineHeight\": ((id: number, lineHeight: number) => void);\n\"nodeGetDensity\": ((id: number) => number);\n\"nodeSetDensity\": ((id: number, density: number) => void);\n\"nodeGetRoundness\": ((id: number) => number);\n\"nodeSetRoundness\": ((id: number, roundness: number) => void);\n\"nodeGetSmoothing\": ((id: number) => number);\n\"nodeSetSmoothing\": ((id: number, smoothing: number) => void);\n\"nodeGetPrimType\": ((id: number) => number);\n\"nodeSetPrimType\": ((id: number, primitive: number) => void);\n\"nodeGetMirror\": ((id: number, slot: number) => {\n\"axis\": \"custom\" | \"x\" | \"y\" | \"z\" | \"disabled\";\n\"planePosition\": number;\n\"goop\": number;\n});\n\"nodeSetMirror\": ((id: number, slot: number, axis: \"x\" | \"y\" | \"z\" | \"disabled\", planePosition?: number, goop?: number) => void);\n\"nodeGetThickness\": ((id: number) => number);\n\"nodeSetThickness\": ((id: number, thickness: number) => void);\n\"curveGetClosed\": ((curveId: number) => false | true);\n\"curveSetClosed\": ((curveId: number, closed: false | true) => void);\n\"curvePointGetHandleIn\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointGetHandleOut\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetHandleIn\": ((curveId: number, pointIndex: number, value: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointSetHandleOut\": ((curveId: number, pointIndex: number, value: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointCount\": ((curveId: number) => number);\n\"curvePointAdd\": ((curveId: number, point: {\n\"name\"?: undefined | string;\n\"pos\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"rot\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"size\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"fixed\"?: undefined | false | true;\n\"round\"?: undefined | number;\n\"materialId\"?: undefined | number;\n}, pointIndex?: undefined | number) => number);\n\"curvePointRemove\": ((curveId: number, pointIndex: number) => void);\n\"curvePointGetName\": ((curveId: number, pointIndex: number) => string);\n\"curvePointSetName\": ((curveId: number, pointIndex: number, name: string) => void);\n\"curvePointGetPos\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetPos\": ((curveId: number, pointIndex: number, position: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetRot\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetRot\": ((curveId: number, pointIndex: number, rotation: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetSize\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetSize\": ((curveId: number, pointIndex: number, sizeValue: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetFixed\": ((curveId: number, pointIndex: number) => false | true);\n\"curvePointSetFixed\": ((curveId: number, pointIndex: number, fixed: false | true) => void);\n\"curvePointGetRound\": ((curveId: number, pointIndex: number) => number);\n\"curvePointSetRound\": ((curveId: number, pointIndex: number, round: number) => void);\n\"curvePointGetMaterialId\": ((curveId: number, pointIndex: number) => null | number);\n\"curvePointSetMaterialId\": ((curveId: number, pointIndex: number, materialId: number) => void);\n\"materialImport\": ((name: string) => Promise<number>);\n\"materialCreate\": (() => number);\n\"materialDelete\": ((id: number) => void);\n\"materialList\": (() => Array<number>);\n\"materialGetName\": ((id: number) => string);\n\"materialSetName\": ((id: number, name: string) => void);\n\"materialGetTier\": ((id: number) => number);\n\"materialSetTier\": ((id: number, tier: number) => void);\n\"materialGetColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetSecondaryColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetSecondaryColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetSubsurfaceColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetSubsurfaceColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetRoughness\": ((id: number) => number);\n\"materialSetRoughness\": ((id: number, value: number) => void);\n\"materialGetMetalness\": ((id: number) => number);\n\"materialSetMetalness\": ((id: number, value: number) => void);\n\"materialGetTransmittance\": ((id: number) => number);\n\"materialSetTransmittance\": ((id: number, value: number) => void);\n\"materialGetTranslucency\": ((id: number) => number);\n\"materialSetTranslucency\": ((id: number, value: number) => void);\n\"materialGetIor\": ((id: number) => number);\n\"materialSetIor\": ((id: number, value: number) => void);\n\"materialGetSheen\": ((id: number) => number);\n\"materialSetSheen\": ((id: number, value: number) => void);\n\"materialGetSheenRoughness\": ((id: number) => number);\n\"materialSetSheenRoughness\": ((id: number, value: number) => void);\n\"materialGetSpecularTint\": ((id: number) => number);\n\"materialSetSpecularTint\": ((id: number, value: number) => void);\n\"materialGetAbsorption\": ((id: number) => number);\n\"materialSetAbsorption\": ((id: number, value: number) => void);\n\"materialGetEmission\": ((id: number) => number);\n\"materialSetEmission\": ((id: number, value: number) => void);\n\"materialGetIridescence\": ((id: number) => number);\n\"materialSetIridescence\": ((id: number, value: number) => void);\n\"materialGetTranslucencyWeight\": ((id: number) => number);\n\"materialSetTranslucencyWeight\": ((id: number, value: number) => void);\n\"materialGetDispersion\": ((id: number) => number);\n\"materialSetDispersion\": ((id: number, value: number) => void);\n\"materialGetSurfaceOpacity\": ((id: number) => number);\n\"materialSetSurfaceOpacity\": ((id: number, value: number) => void);\n\"listFontFamilies\": (() => Array<{\n\"name\": string;\n\"variants\": Array<{\n\"weight\": string;\n\"italic\": false | true;\n}>;\n}>);\n\"print\": ((...values: Array<unknown>) => void);\n\"nodeGetAABB\": ((id: number) => Promise<{\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}>);\n\"nodeResize\": ((id: number, dimensions: {\n\"x\"?: undefined | number;\n\"y\"?: undefined | number;\n\"z\"?: undefined | number;\n}) => Promise<void>);\n\"aabbCenter\": ((box: {\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"aabbRadius\": ((box: {\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}) => number);\n\"lookAt\": ((origin: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}, target: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"alignAxis\": ((direction: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}, axis: \"x\" | \"y\" | \"z\") => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"scenePropertiesRead\": (() => {\n\"hdr_name\": undefined | string;\n\"hdr_multiplier\": undefined | number;\n\"hdr_orientation\": undefined | {\n\"x\": number;\n\"y\": number;\n};\n\"backdrop_color1\": undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"backdrop_color2\": undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"backdrop_grad_offset\": undefined | {\n\"x\": number;\n\"y\": number;\n};\n});\n\"listHDRs\": (() => Array<string>);\n\"setHdrName\": ((name: string) => void);\n\"setHdrMultiplier\": ((multiplier: number) => void);\n\"setHdrOrientation\": ((orientation: {\n\"x\": number;\n\"y\": number;\n}) => void);\n\"setBackgroundColor\": ((rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n}) => T | Promise<T>), expectedRevision: string) => Promise<T>);\n\"screenshot\": ((options?: undefined | {\n\"camera\"?: undefined | {\n\"position\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"target\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"projection\"?: undefined | \"perspective\" | \"orthographic\";\n\"horizontalFovDegrees\"?: undefined | number;\n\"orthographicWidth\"?: undefined | number;\n};\n}) => Promise<{\n\"id\": string;\n\"mediaType\": string;\n\"name\"?: undefined | string;\n}>);\n} };\ndeclare function print(...values: unknown[]): void;\ndeclare function emitImage(ref: { id: string; mediaType: string; name?: string }, options?: { inspect?: boolean }): Promise<void>;\ndeclare function emitFile(ref: { id: string; mediaType: string; name?: string }): Promise<void>;\n";
1
+ export declare const WOMP_SCENE_DECLARATIONS = "declare const womp: { scene: {\n\"read\": (() => Promise<{\n\"health\": {\n\"status\": \"within_limits\" | \"overflow\" | \"unverified\";\n\"freshness\": \"unverified\" | \"snapshot\" | \"post_ack_event\";\n\"revisionVerified\": false;\n\"affectedAreaIds\": Array<string>;\n\"emptyAreaIds\"?: undefined | Array<string>;\n\"thermometer\"?: undefined | {\n\"objects\": {\n[key: string]: {\n\"num_prims\": number;\n\"flag_prim_overflow\": number;\n\"flag_depth_overflow\": number;\n\"flag_vox_overflow\": number;\n\"voxels\": number;\n};\n};\n\"max_num_prims\": number;\n\"max_total_depth\": number;\n\"max_per_object\": number;\n\"total\": number;\n\"max_total\": number;\n\"assets_budget_used\": number;\n\"assets_budget_total\": number;\n\"mesh_instances_used\"?: undefined | number;\n\"mesh_instances_total\"?: undefined | number;\n\"decal_instances_used\"?: undefined | number;\n\"decal_instances_total\"?: undefined | number;\n\"field_instances_used\"?: undefined | number;\n\"field_instances_total\"?: undefined | number;\n};\n\"reason\"?: undefined | string;\n};\n\"revision\": string;\n\"projectId\"?: undefined | number;\n\"unitMultiplier\": number;\n\"nodes\": Array<{\n\"id\": number;\n\"name\": string;\n\"type\": number;\n\"parentId\": number;\n}>;\n}>);\n\"health\": ((objectIds?: undefined | Array<number>) => Promise<{\n\"status\": \"within_limits\" | \"overflow\" | \"unverified\";\n\"freshness\": \"unverified\" | \"snapshot\" | \"post_ack_event\";\n\"revisionVerified\": false;\n\"affectedAreaIds\": Array<string>;\n\"emptyAreaIds\"?: undefined | Array<string>;\n\"thermometer\"?: undefined | {\n\"objects\": {\n[key: string]: {\n\"num_prims\": number;\n\"flag_prim_overflow\": number;\n\"flag_depth_overflow\": number;\n\"flag_vox_overflow\": number;\n\"voxels\": number;\n};\n};\n\"max_num_prims\": number;\n\"max_total_depth\": number;\n\"max_per_object\": number;\n\"total\": number;\n\"max_total\": number;\n\"assets_budget_used\": number;\n\"assets_budget_total\": number;\n\"mesh_instances_used\"?: undefined | number;\n\"mesh_instances_total\"?: undefined | number;\n\"decal_instances_used\"?: undefined | number;\n\"decal_instances_total\"?: undefined | number;\n\"field_instances_used\"?: undefined | number;\n\"field_instances_total\"?: undefined | number;\n};\n\"reason\"?: undefined | string;\n}>);\n\"edit\": (<T>(callback: ((draft: {\n\"listSuperMaterials\": (() => Array<string>);\n\"_getParentId\": ((childId: number) => number);\n\"_getScaleProductUpTo\": ((nodeId: number, includeNodeSelfUnion?: false | true) => number);\n\"NodeType\": {\n\"Primitive\": 0;\n\"Union\": 1;\n\"Light\": 2;\n\"Curve\": 3;\n\"Group\": 4;\n\"Text\": 5;\n\"Field\": 6;\n\"SVG\": 7;\n\"Mesh\": 8;\n\"Decal\": 9;\n\"OpenSCAD\": 10;\n\"Socket\": 11;\n} & {\n[key: number]: string;\n};\n\"PrimitiveType\": {\n\"Sphere\": 0;\n\"Cylinder\": 1;\n\"Cube\": 2;\n\"Cone\": 3;\n\"Torus\": 4;\n\"Pyramid\": 9;\n} & {\n[key: number]: string;\n};\n\"OperationType\": {\n\"Subtract\": 0;\n\"Union\": 1;\n\"Stain\": 2;\n\"Intersect\": 3;\n} & {\n[key: number]: string;\n};\n\"LightType\": {\n\"Rect\": 0;\n\"Sphere\": 1;\n\"Distant\": 2;\n} & {\n[key: number]: string;\n};\n\"nodeCreate\": ((type: number, parentId?: number) => number);\n\"nodeDelete\": ((id: number) => void);\n\"nodeClone\": ((id: number) => number);\n\"cloneSubtree\": ((id: number, options?: {\n\"parentId\"?: undefined | number;\n\"name\"?: undefined | string;\n\"index\"?: undefined | number;\n}) => Promise<number>);\n\"nodeList\": (() => Array<number>);\n\"nodeChildren\": ((parentId: number) => Array<number>);\n\"nodeSetParent\": ((id: number, parentId: number, index?: undefined | number) => void);\n\"nodeGetType\": ((id: number) => number);\n\"nodeGetName\": ((id: number) => string);\n\"nodeSetName\": ((id: number, name: string) => void);\n\"nodeGetParentId\": ((id: number) => number);\n\"nodeGetPos\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeGetLock\": ((id: number) => false | true);\n\"nodeSetLock\": ((id: number, locked: false | true) => void);\n\"nodeSetPos\": ((id: number, position: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetRot\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeSetRot\": ((id: number, rotation: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetSize\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n} | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeSetSize\": ((id: number, sizeValue: {\n\"x\": number;\n\"y\": number;\n} | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetHide\": ((id: number) => false | true);\n\"nodeSetHide\": ((id: number, hidden: false | true) => void);\n\"nodeGetOp\": ((id: number) => number);\n\"nodeSetOp\": ((id: number, operation: number) => void);\n\"nodeGetBlend\": ((id: number) => number);\n\"nodeSetBlend\": ((id: number, blend: number) => void);\n\"nodeGetRound\": ((id: number) => number);\n\"nodeSetRound\": ((id: number, round: number) => void);\n\"nodeGetColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"nodeSetColor\": ((id: number, rgb255: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n} | {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"nodeGetMaterialId\": ((id: number) => null | number);\n\"nodeSetMaterialId\": ((id: number, materialId: number) => void);\n\"nodeGetResolution\": ((id: number) => number);\n\"nodeSetUnionResolution\": ((unionId: number, resolution: number) => void);\n\"nodeGetLightType\": ((id: number) => number);\n\"nodeSetLightType\": ((id: number, lightType: number) => void);\n\"nodeGetPower\": ((id: number) => number);\n\"nodeSetPower\": ((id: number, power: number) => void);\n\"nodeGetText\": ((id: number) => string);\n\"nodeSetFacing\": ((id: number, direction: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeSetTextSize\": ((id: number, size: {\n\"fontSize\": number;\n\"depth\": number;\n}) => void);\n\"nodeGetTextSize\": ((id: number) => {\n\"fontSize\": number;\n\"depth\": number;\n});\n\"nodeSetText\": ((id: number, text: string) => void);\n\"nodeGetFont\": ((id: number) => string);\n\"nodeSetFont\": ((id: number, font: string) => void);\n\"nodeGetWeight\": ((id: number) => number);\n\"nodeSetWeight\": ((id: number, weight: number) => void);\n\"nodeGetItalic\": ((id: number) => false | true);\n\"nodeSetItalic\": ((id: number, italic: false | true) => void);\n\"nodeGetAlign\": ((id: number) => number);\n\"nodeSetAlign\": ((id: number, align: number) => void);\n\"nodeGetWrap\": ((id: number) => number);\n\"nodeSetWrap\": ((id: number, wrap: number) => void);\n\"nodeGetWidth\": ((id: number) => number);\n\"nodeSetWidth\": ((id: number, width: number) => void);\n\"nodeGetSpacing\": ((id: number) => number);\n\"nodeSetSpacing\": ((id: number, spacing: number) => void);\n\"nodeGetLineHeight\": ((id: number) => number);\n\"nodeSetLineHeight\": ((id: number, lineHeight: number) => void);\n\"nodeGetDensity\": ((id: number) => number);\n\"nodeSetDensity\": ((id: number, density: number) => void);\n\"nodeGetRoundness\": ((id: number) => number);\n\"nodeSetRoundness\": ((id: number, roundness: number) => void);\n\"nodeGetSmoothing\": ((id: number) => number);\n\"nodeSetSmoothing\": ((id: number, smoothing: number) => void);\n\"nodeGetPrimType\": ((id: number) => number);\n\"nodeSetPrimType\": ((id: number, primitive: number) => void);\n\"nodeGetMirror\": ((id: number, slot: number) => {\n\"axis\": \"custom\" | \"x\" | \"y\" | \"z\" | \"disabled\";\n\"planePosition\": number;\n\"goop\": number;\n});\n\"nodeSetMirror\": ((id: number, slot: number, axis: \"x\" | \"y\" | \"z\" | \"disabled\", planePosition?: number, goop?: number) => void);\n\"nodeGetThickness\": ((id: number) => number);\n\"nodeSetThickness\": ((id: number, thickness: number) => void);\n\"curveGetClosed\": ((curveId: number) => false | true);\n\"curveSetClosed\": ((curveId: number, closed: false | true) => void);\n\"curvePointGetHandleIn\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointGetHandleOut\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetHandleIn\": ((curveId: number, pointIndex: number, value: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointSetHandleOut\": ((curveId: number, pointIndex: number, value: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointCount\": ((curveId: number) => number);\n\"curvePointAdd\": ((curveId: number, point: {\n\"name\"?: undefined | string;\n\"pos\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"rot\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"size\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"fixed\"?: undefined | false | true;\n\"round\"?: undefined | number;\n\"materialId\"?: undefined | number;\n}, pointIndex?: undefined | number) => number);\n\"curvePointRemove\": ((curveId: number, pointIndex: number) => void);\n\"curvePointGetName\": ((curveId: number, pointIndex: number) => string);\n\"curvePointSetName\": ((curveId: number, pointIndex: number, name: string) => void);\n\"curvePointGetPos\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetPos\": ((curveId: number, pointIndex: number, position: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetRot\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetRot\": ((curveId: number, pointIndex: number, rotation: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetSize\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetSize\": ((curveId: number, pointIndex: number, sizeValue: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetFixed\": ((curveId: number, pointIndex: number) => false | true);\n\"curvePointSetFixed\": ((curveId: number, pointIndex: number, fixed: false | true) => void);\n\"curvePointGetRound\": ((curveId: number, pointIndex: number) => number);\n\"curvePointSetRound\": ((curveId: number, pointIndex: number, round: number) => void);\n\"curvePointGetMaterialId\": ((curveId: number, pointIndex: number) => null | number);\n\"curvePointSetMaterialId\": ((curveId: number, pointIndex: number, materialId: number) => void);\n\"materialImport\": ((name: string) => Promise<number>);\n\"materialCreate\": (() => number);\n\"materialDelete\": ((id: number) => void);\n\"materialList\": (() => Array<number>);\n\"materialGetName\": ((id: number) => string);\n\"materialSetName\": ((id: number, name: string) => void);\n\"materialGetTier\": ((id: number) => number);\n\"materialSetTier\": ((id: number, tier: number) => void);\n\"materialGetColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetSecondaryColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetSecondaryColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetSubsurfaceColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetSubsurfaceColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetRoughness\": ((id: number) => number);\n\"materialSetRoughness\": ((id: number, value: number) => void);\n\"materialGetMetalness\": ((id: number) => number);\n\"materialSetMetalness\": ((id: number, value: number) => void);\n\"materialGetTransmittance\": ((id: number) => number);\n\"materialSetTransmittance\": ((id: number, value: number) => void);\n\"materialGetTranslucency\": ((id: number) => number);\n\"materialSetTranslucency\": ((id: number, value: number) => void);\n\"materialGetIor\": ((id: number) => number);\n\"materialSetIor\": ((id: number, value: number) => void);\n\"materialGetSheen\": ((id: number) => number);\n\"materialSetSheen\": ((id: number, value: number) => void);\n\"materialGetSheenRoughness\": ((id: number) => number);\n\"materialSetSheenRoughness\": ((id: number, value: number) => void);\n\"materialGetSpecularTint\": ((id: number) => number);\n\"materialSetSpecularTint\": ((id: number, value: number) => void);\n\"materialGetAbsorption\": ((id: number) => number);\n\"materialSetAbsorption\": ((id: number, value: number) => void);\n\"materialGetEmission\": ((id: number) => number);\n\"materialSetEmission\": ((id: number, value: number) => void);\n\"materialGetIridescence\": ((id: number) => number);\n\"materialSetIridescence\": ((id: number, value: number) => void);\n\"materialGetTranslucencyWeight\": ((id: number) => number);\n\"materialSetTranslucencyWeight\": ((id: number, value: number) => void);\n\"materialGetDispersion\": ((id: number) => number);\n\"materialSetDispersion\": ((id: number, value: number) => void);\n\"materialGetSurfaceOpacity\": ((id: number) => number);\n\"materialSetSurfaceOpacity\": ((id: number, value: number) => void);\n\"listFontFamilies\": (() => Array<{\n\"name\": string;\n\"variants\": Array<{\n\"weight\": string;\n\"italic\": false | true;\n}>;\n}>);\n\"print\": ((...values: Array<unknown>) => void);\n\"nodeGetAABB\": ((id: number) => Promise<{\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}>);\n\"nodeResize\": ((id: number, dimensions: {\n\"x\"?: undefined | number;\n\"y\"?: undefined | number;\n\"z\"?: undefined | number;\n}) => Promise<void>);\n\"aabbCenter\": ((box: {\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"aabbRadius\": ((box: {\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}) => number);\n\"lookAt\": ((origin: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}, target: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"alignAxis\": ((direction: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}, axis: \"x\" | \"y\" | \"z\") => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"scenePropertiesRead\": (() => {\n\"hdr_name\": undefined | string;\n\"hdr_multiplier\": undefined | number;\n\"hdr_orientation\": undefined | {\n\"x\": number;\n\"y\": number;\n};\n\"backdrop_color1\": undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"backdrop_color2\": undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"backdrop_grad_offset\": undefined | {\n\"x\": number;\n\"y\": number;\n};\n});\n\"listHDRs\": (() => Array<string>);\n\"setHdrName\": ((name: string) => void);\n\"setHdrMultiplier\": ((multiplier: number) => void);\n\"setHdrOrientation\": ((orientation: {\n\"x\": number;\n\"y\": number;\n}) => void);\n\"setBackgroundColor\": ((rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n}) => T | Promise<T>), expectedRevision: string) => Promise<T>);\n\"screenshot\": ((options?: undefined | {\n\"camera\"?: undefined | {\n\"position\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"target\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"projection\"?: undefined | \"perspective\" | \"orthographic\";\n\"horizontalFovDegrees\"?: undefined | number;\n\"orthographicWidth\"?: undefined | number;\n};\n}) => Promise<{\n\"id\": string;\n\"mediaType\": string;\n\"name\"?: undefined | string;\n}>);\n} };\ndeclare function print(...values: unknown[]): void;\ndeclare function emitImage(ref: { id: string; mediaType: string; name?: string }, options?: { inspect?: boolean }): Promise<void>;\ndeclare function emitFile(ref: { id: string; mediaType: string; name?: string }): Promise<void>;\n";
@@ -1,3 +1,3 @@
1
1
  // Generated by scripts/generate-skill-declarations.mjs.
2
2
  // prettier-ignore
3
- export const WOMP_SCENE_DECLARATIONS = "declare const womp: { scene: {\n\"read\": (() => Promise<{\n\"health\": {\n\"status\": \"within_limits\" | \"overflow\" | \"unverified\";\n\"freshness\": \"unverified\" | \"snapshot\" | \"post_ack_event\";\n\"revisionVerified\": false;\n\"affectedAreaIds\": Array<string>;\n\"emptyAreaIds\"?: undefined | Array<string>;\n\"thermometer\"?: undefined | {\n\"objects\": {\n[key: string]: {\n\"num_prims\": number;\n\"flag_prim_overflow\": number;\n\"flag_depth_overflow\": number;\n\"flag_vox_overflow\": number;\n\"voxels\": number;\n};\n};\n\"max_num_prims\": number;\n\"max_total_depth\": number;\n\"max_per_object\": number;\n\"total\": number;\n\"max_total\": number;\n\"assets_budget_used\": number;\n\"assets_budget_total\": number;\n\"mesh_instances_used\"?: undefined | number;\n\"mesh_instances_total\"?: undefined | number;\n\"decal_instances_used\"?: undefined | number;\n\"decal_instances_total\"?: undefined | number;\n\"field_instances_used\"?: undefined | number;\n\"field_instances_total\"?: undefined | number;\n};\n\"reason\"?: undefined | string;\n};\n\"revision\": string;\n\"projectId\"?: undefined | number;\n\"unitMultiplier\": number;\n\"nodes\": Array<{\n\"id\": number;\n\"name\": string;\n\"type\": number;\n\"parentId\": number;\n}>;\n}>);\n\"health\": ((objectIds?: undefined | Array<number>) => Promise<{\n\"status\": \"within_limits\" | \"overflow\" | \"unverified\";\n\"freshness\": \"unverified\" | \"snapshot\" | \"post_ack_event\";\n\"revisionVerified\": false;\n\"affectedAreaIds\": Array<string>;\n\"emptyAreaIds\"?: undefined | Array<string>;\n\"thermometer\"?: undefined | {\n\"objects\": {\n[key: string]: {\n\"num_prims\": number;\n\"flag_prim_overflow\": number;\n\"flag_depth_overflow\": number;\n\"flag_vox_overflow\": number;\n\"voxels\": number;\n};\n};\n\"max_num_prims\": number;\n\"max_total_depth\": number;\n\"max_per_object\": number;\n\"total\": number;\n\"max_total\": number;\n\"assets_budget_used\": number;\n\"assets_budget_total\": number;\n\"mesh_instances_used\"?: undefined | number;\n\"mesh_instances_total\"?: undefined | number;\n\"decal_instances_used\"?: undefined | number;\n\"decal_instances_total\"?: undefined | number;\n\"field_instances_used\"?: undefined | number;\n\"field_instances_total\"?: undefined | number;\n};\n\"reason\"?: undefined | string;\n}>);\n\"edit\": (<T>(callback: ((draft: {\n\"listSuperMaterials\": (() => Array<string>);\n\"_getParentId\": ((childId: number) => number);\n\"_getScaleProductUpTo\": ((nodeId: number, includeNodeSelfUnion?: false | true) => number);\n\"NodeType\": {\n\"Primitive\": 0;\n\"Union\": 1;\n\"Light\": 2;\n\"Curve\": 3;\n\"Group\": 4;\n\"Text\": 5;\n\"Field\": 6;\n\"SVG\": 7;\n\"Mesh\": 8;\n\"Decal\": 9;\n\"OpenSCAD\": 10;\n\"Socket\": 11;\n} & {\n[key: number]: string;\n};\n\"PrimitiveType\": {\n\"Sphere\": 0;\n\"Cylinder\": 1;\n\"Cube\": 2;\n\"Cone\": 3;\n\"Torus\": 4;\n\"Pyramid\": 9;\n} & {\n[key: number]: string;\n};\n\"OperationType\": {\n\"Subtract\": 0;\n\"Union\": 1;\n\"Stain\": 2;\n\"Intersect\": 3;\n} & {\n[key: number]: string;\n};\n\"LightType\": {\n\"Rect\": 0;\n\"Sphere\": 1;\n\"Distant\": 2;\n} & {\n[key: number]: string;\n};\n\"nodeCreate\": ((type: number, parentId?: number) => number);\n\"nodeDelete\": ((id: number) => void);\n\"nodeClone\": ((id: number) => number);\n\"cloneSubtree\": ((id: number, options?: {\n\"parentId\"?: undefined | number;\n\"name\"?: undefined | string;\n\"index\"?: undefined | number;\n}) => Promise<number>);\n\"nodeList\": (() => Array<number>);\n\"nodeChildren\": ((parentId: number) => Array<number>);\n\"nodeSetParent\": ((id: number, parentId: number, index?: undefined | number) => void);\n\"nodeGetType\": ((id: number) => number);\n\"nodeGetName\": ((id: number) => string);\n\"nodeSetName\": ((id: number, name: string) => void);\n\"nodeGetParentId\": ((id: number) => number);\n\"nodeGetPos\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeGetLock\": ((id: number) => false | true);\n\"nodeSetLock\": ((id: number, locked: false | true) => void);\n\"nodeSetPos\": ((id: number, position: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetRot\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeSetRot\": ((id: number, rotation: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetSize\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n} | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeSetSize\": ((id: number, sizeValue: {\n\"x\": number;\n\"y\": number;\n} | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetHide\": ((id: number) => false | true);\n\"nodeSetHide\": ((id: number, hidden: false | true) => void);\n\"nodeGetOp\": ((id: number) => number);\n\"nodeSetOp\": ((id: number, operation: number) => void);\n\"nodeGetBlend\": ((id: number) => number);\n\"nodeSetBlend\": ((id: number, blend: number) => void);\n\"nodeGetRound\": ((id: number) => number);\n\"nodeSetRound\": ((id: number, round: number) => void);\n\"nodeGetColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"nodeSetColor\": ((id: number, rgb255: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n} | {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"nodeGetMaterialId\": ((id: number) => null | number);\n\"nodeSetMaterialId\": ((id: number, materialId: number) => void);\n\"nodeGetResolution\": ((id: number) => number);\n\"nodeSetUnionResolution\": ((unionId: number, resolution: number) => void);\n\"nodeGetLightType\": ((id: number) => number);\n\"nodeSetLightType\": ((id: number, lightType: number) => void);\n\"nodeGetPower\": ((id: number) => number);\n\"nodeSetPower\": ((id: number, power: number) => void);\n\"nodeGetText\": ((id: number) => string);\n\"nodeSetText\": ((id: number, text: string) => void);\n\"nodeGetFont\": ((id: number) => string);\n\"nodeSetFont\": ((id: number, font: string) => void);\n\"nodeGetWeight\": ((id: number) => number);\n\"nodeSetWeight\": ((id: number, weight: number) => void);\n\"nodeGetItalic\": ((id: number) => false | true);\n\"nodeSetItalic\": ((id: number, italic: false | true) => void);\n\"nodeGetAlign\": ((id: number) => number);\n\"nodeSetAlign\": ((id: number, align: number) => void);\n\"nodeGetWrap\": ((id: number) => number);\n\"nodeSetWrap\": ((id: number, wrap: number) => void);\n\"nodeGetWidth\": ((id: number) => number);\n\"nodeSetWidth\": ((id: number, width: number) => void);\n\"nodeGetSpacing\": ((id: number) => number);\n\"nodeSetSpacing\": ((id: number, spacing: number) => void);\n\"nodeGetLineHeight\": ((id: number) => number);\n\"nodeSetLineHeight\": ((id: number, lineHeight: number) => void);\n\"nodeGetDensity\": ((id: number) => number);\n\"nodeSetDensity\": ((id: number, density: number) => void);\n\"nodeGetRoundness\": ((id: number) => number);\n\"nodeSetRoundness\": ((id: number, roundness: number) => void);\n\"nodeGetSmoothing\": ((id: number) => number);\n\"nodeSetSmoothing\": ((id: number, smoothing: number) => void);\n\"nodeGetPrimType\": ((id: number) => number);\n\"nodeSetPrimType\": ((id: number, primitive: number) => void);\n\"nodeGetMirror\": ((id: number, slot: number) => {\n\"axis\": \"custom\" | \"x\" | \"y\" | \"z\" | \"disabled\";\n\"planePosition\": number;\n\"goop\": number;\n});\n\"nodeSetMirror\": ((id: number, slot: number, axis: \"x\" | \"y\" | \"z\" | \"disabled\", planePosition?: number, goop?: number) => void);\n\"nodeGetThickness\": ((id: number) => number);\n\"nodeSetThickness\": ((id: number, thickness: number) => void);\n\"curveGetClosed\": ((curveId: number) => false | true);\n\"curveSetClosed\": ((curveId: number, closed: false | true) => void);\n\"curvePointGetHandleIn\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointGetHandleOut\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetHandleIn\": ((curveId: number, pointIndex: number, value: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointSetHandleOut\": ((curveId: number, pointIndex: number, value: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointCount\": ((curveId: number) => number);\n\"curvePointAdd\": ((curveId: number, point: {\n\"name\"?: undefined | string;\n\"pos\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"rot\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"size\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"fixed\"?: undefined | false | true;\n\"round\"?: undefined | number;\n\"materialId\"?: undefined | number;\n}, pointIndex?: undefined | number) => number);\n\"curvePointRemove\": ((curveId: number, pointIndex: number) => void);\n\"curvePointGetName\": ((curveId: number, pointIndex: number) => string);\n\"curvePointSetName\": ((curveId: number, pointIndex: number, name: string) => void);\n\"curvePointGetPos\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetPos\": ((curveId: number, pointIndex: number, position: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetRot\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetRot\": ((curveId: number, pointIndex: number, rotation: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetSize\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetSize\": ((curveId: number, pointIndex: number, sizeValue: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetFixed\": ((curveId: number, pointIndex: number) => false | true);\n\"curvePointSetFixed\": ((curveId: number, pointIndex: number, fixed: false | true) => void);\n\"curvePointGetRound\": ((curveId: number, pointIndex: number) => number);\n\"curvePointSetRound\": ((curveId: number, pointIndex: number, round: number) => void);\n\"curvePointGetMaterialId\": ((curveId: number, pointIndex: number) => null | number);\n\"curvePointSetMaterialId\": ((curveId: number, pointIndex: number, materialId: number) => void);\n\"materialImport\": ((name: string) => Promise<number>);\n\"materialCreate\": (() => number);\n\"materialDelete\": ((id: number) => void);\n\"materialList\": (() => Array<number>);\n\"materialGetName\": ((id: number) => string);\n\"materialSetName\": ((id: number, name: string) => void);\n\"materialGetTier\": ((id: number) => number);\n\"materialSetTier\": ((id: number, tier: number) => void);\n\"materialGetColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetSecondaryColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetSecondaryColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetSubsurfaceColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetSubsurfaceColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetRoughness\": ((id: number) => number);\n\"materialSetRoughness\": ((id: number, value: number) => void);\n\"materialGetMetalness\": ((id: number) => number);\n\"materialSetMetalness\": ((id: number, value: number) => void);\n\"materialGetTransmittance\": ((id: number) => number);\n\"materialSetTransmittance\": ((id: number, value: number) => void);\n\"materialGetTranslucency\": ((id: number) => number);\n\"materialSetTranslucency\": ((id: number, value: number) => void);\n\"materialGetIor\": ((id: number) => number);\n\"materialSetIor\": ((id: number, value: number) => void);\n\"materialGetSheen\": ((id: number) => number);\n\"materialSetSheen\": ((id: number, value: number) => void);\n\"materialGetSheenRoughness\": ((id: number) => number);\n\"materialSetSheenRoughness\": ((id: number, value: number) => void);\n\"materialGetSpecularTint\": ((id: number) => number);\n\"materialSetSpecularTint\": ((id: number, value: number) => void);\n\"materialGetAbsorption\": ((id: number) => number);\n\"materialSetAbsorption\": ((id: number, value: number) => void);\n\"materialGetEmission\": ((id: number) => number);\n\"materialSetEmission\": ((id: number, value: number) => void);\n\"materialGetIridescence\": ((id: number) => number);\n\"materialSetIridescence\": ((id: number, value: number) => void);\n\"materialGetTranslucencyWeight\": ((id: number) => number);\n\"materialSetTranslucencyWeight\": ((id: number, value: number) => void);\n\"materialGetDispersion\": ((id: number) => number);\n\"materialSetDispersion\": ((id: number, value: number) => void);\n\"materialGetSurfaceOpacity\": ((id: number) => number);\n\"materialSetSurfaceOpacity\": ((id: number, value: number) => void);\n\"listFontFamilies\": (() => Array<{\n\"name\": string;\n\"variants\": Array<{\n\"weight\": string;\n\"italic\": false | true;\n}>;\n}>);\n\"print\": ((...values: Array<unknown>) => void);\n\"nodeGetAABB\": ((id: number) => Promise<{\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}>);\n\"nodeResize\": ((id: number, dimensions: {\n\"x\"?: undefined | number;\n\"y\"?: undefined | number;\n\"z\"?: undefined | number;\n}) => Promise<void>);\n\"aabbCenter\": ((box: {\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"aabbRadius\": ((box: {\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}) => number);\n\"lookAt\": ((origin: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}, target: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"alignAxis\": ((direction: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}, axis: \"x\" | \"y\" | \"z\") => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"scenePropertiesRead\": (() => {\n\"hdr_name\": undefined | string;\n\"hdr_multiplier\": undefined | number;\n\"hdr_orientation\": undefined | {\n\"x\": number;\n\"y\": number;\n};\n\"backdrop_color1\": undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"backdrop_color2\": undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"backdrop_grad_offset\": undefined | {\n\"x\": number;\n\"y\": number;\n};\n});\n\"listHDRs\": (() => Array<string>);\n\"setHdrName\": ((name: string) => void);\n\"setHdrMultiplier\": ((multiplier: number) => void);\n\"setHdrOrientation\": ((orientation: {\n\"x\": number;\n\"y\": number;\n}) => void);\n\"setBackgroundColor\": ((rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n}) => T | Promise<T>), expectedRevision: string) => Promise<T>);\n\"screenshot\": ((options?: undefined | {\n\"camera\"?: undefined | {\n\"position\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"target\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"projection\"?: undefined | \"perspective\" | \"orthographic\";\n\"horizontalFovDegrees\"?: undefined | number;\n\"orthographicWidth\"?: undefined | number;\n};\n}) => Promise<{\n\"id\": string;\n\"mediaType\": string;\n\"name\"?: undefined | string;\n}>);\n} };\ndeclare function print(...values: unknown[]): void;\ndeclare function emitImage(ref: { id: string; mediaType: string; name?: string }, options?: { inspect?: boolean }): Promise<void>;\ndeclare function emitFile(ref: { id: string; mediaType: string; name?: string }): Promise<void>;\n";
3
+ export const WOMP_SCENE_DECLARATIONS = "declare const womp: { scene: {\n\"read\": (() => Promise<{\n\"health\": {\n\"status\": \"within_limits\" | \"overflow\" | \"unverified\";\n\"freshness\": \"unverified\" | \"snapshot\" | \"post_ack_event\";\n\"revisionVerified\": false;\n\"affectedAreaIds\": Array<string>;\n\"emptyAreaIds\"?: undefined | Array<string>;\n\"thermometer\"?: undefined | {\n\"objects\": {\n[key: string]: {\n\"num_prims\": number;\n\"flag_prim_overflow\": number;\n\"flag_depth_overflow\": number;\n\"flag_vox_overflow\": number;\n\"voxels\": number;\n};\n};\n\"max_num_prims\": number;\n\"max_total_depth\": number;\n\"max_per_object\": number;\n\"total\": number;\n\"max_total\": number;\n\"assets_budget_used\": number;\n\"assets_budget_total\": number;\n\"mesh_instances_used\"?: undefined | number;\n\"mesh_instances_total\"?: undefined | number;\n\"decal_instances_used\"?: undefined | number;\n\"decal_instances_total\"?: undefined | number;\n\"field_instances_used\"?: undefined | number;\n\"field_instances_total\"?: undefined | number;\n};\n\"reason\"?: undefined | string;\n};\n\"revision\": string;\n\"projectId\"?: undefined | number;\n\"unitMultiplier\": number;\n\"nodes\": Array<{\n\"id\": number;\n\"name\": string;\n\"type\": number;\n\"parentId\": number;\n}>;\n}>);\n\"health\": ((objectIds?: undefined | Array<number>) => Promise<{\n\"status\": \"within_limits\" | \"overflow\" | \"unverified\";\n\"freshness\": \"unverified\" | \"snapshot\" | \"post_ack_event\";\n\"revisionVerified\": false;\n\"affectedAreaIds\": Array<string>;\n\"emptyAreaIds\"?: undefined | Array<string>;\n\"thermometer\"?: undefined | {\n\"objects\": {\n[key: string]: {\n\"num_prims\": number;\n\"flag_prim_overflow\": number;\n\"flag_depth_overflow\": number;\n\"flag_vox_overflow\": number;\n\"voxels\": number;\n};\n};\n\"max_num_prims\": number;\n\"max_total_depth\": number;\n\"max_per_object\": number;\n\"total\": number;\n\"max_total\": number;\n\"assets_budget_used\": number;\n\"assets_budget_total\": number;\n\"mesh_instances_used\"?: undefined | number;\n\"mesh_instances_total\"?: undefined | number;\n\"decal_instances_used\"?: undefined | number;\n\"decal_instances_total\"?: undefined | number;\n\"field_instances_used\"?: undefined | number;\n\"field_instances_total\"?: undefined | number;\n};\n\"reason\"?: undefined | string;\n}>);\n\"edit\": (<T>(callback: ((draft: {\n\"listSuperMaterials\": (() => Array<string>);\n\"_getParentId\": ((childId: number) => number);\n\"_getScaleProductUpTo\": ((nodeId: number, includeNodeSelfUnion?: false | true) => number);\n\"NodeType\": {\n\"Primitive\": 0;\n\"Union\": 1;\n\"Light\": 2;\n\"Curve\": 3;\n\"Group\": 4;\n\"Text\": 5;\n\"Field\": 6;\n\"SVG\": 7;\n\"Mesh\": 8;\n\"Decal\": 9;\n\"OpenSCAD\": 10;\n\"Socket\": 11;\n} & {\n[key: number]: string;\n};\n\"PrimitiveType\": {\n\"Sphere\": 0;\n\"Cylinder\": 1;\n\"Cube\": 2;\n\"Cone\": 3;\n\"Torus\": 4;\n\"Pyramid\": 9;\n} & {\n[key: number]: string;\n};\n\"OperationType\": {\n\"Subtract\": 0;\n\"Union\": 1;\n\"Stain\": 2;\n\"Intersect\": 3;\n} & {\n[key: number]: string;\n};\n\"LightType\": {\n\"Rect\": 0;\n\"Sphere\": 1;\n\"Distant\": 2;\n} & {\n[key: number]: string;\n};\n\"nodeCreate\": ((type: number, parentId?: number) => number);\n\"nodeDelete\": ((id: number) => void);\n\"nodeClone\": ((id: number) => number);\n\"cloneSubtree\": ((id: number, options?: {\n\"parentId\"?: undefined | number;\n\"name\"?: undefined | string;\n\"index\"?: undefined | number;\n}) => Promise<number>);\n\"nodeList\": (() => Array<number>);\n\"nodeChildren\": ((parentId: number) => Array<number>);\n\"nodeSetParent\": ((id: number, parentId: number, index?: undefined | number) => void);\n\"nodeGetType\": ((id: number) => number);\n\"nodeGetName\": ((id: number) => string);\n\"nodeSetName\": ((id: number, name: string) => void);\n\"nodeGetParentId\": ((id: number) => number);\n\"nodeGetPos\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeGetLock\": ((id: number) => false | true);\n\"nodeSetLock\": ((id: number, locked: false | true) => void);\n\"nodeSetPos\": ((id: number, position: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetRot\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeSetRot\": ((id: number, rotation: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetSize\": ((id: number) => {\n\"x\": number;\n\"y\": number;\n} | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"nodeSetSize\": ((id: number, sizeValue: {\n\"x\": number;\n\"y\": number;\n} | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeGetHide\": ((id: number) => false | true);\n\"nodeSetHide\": ((id: number, hidden: false | true) => void);\n\"nodeGetOp\": ((id: number) => number);\n\"nodeSetOp\": ((id: number, operation: number) => void);\n\"nodeGetBlend\": ((id: number) => number);\n\"nodeSetBlend\": ((id: number, blend: number) => void);\n\"nodeGetRound\": ((id: number) => number);\n\"nodeSetRound\": ((id: number, round: number) => void);\n\"nodeGetColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"nodeSetColor\": ((id: number, rgb255: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n} | {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"nodeGetMaterialId\": ((id: number) => null | number);\n\"nodeSetMaterialId\": ((id: number, materialId: number) => void);\n\"nodeGetResolution\": ((id: number) => number);\n\"nodeSetUnionResolution\": ((unionId: number, resolution: number) => void);\n\"nodeGetLightType\": ((id: number) => number);\n\"nodeSetLightType\": ((id: number, lightType: number) => void);\n\"nodeGetPower\": ((id: number) => number);\n\"nodeSetPower\": ((id: number, power: number) => void);\n\"nodeGetText\": ((id: number) => string);\n\"nodeSetFacing\": ((id: number, direction: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"nodeSetTextSize\": ((id: number, size: {\n\"fontSize\": number;\n\"depth\": number;\n}) => void);\n\"nodeGetTextSize\": ((id: number) => {\n\"fontSize\": number;\n\"depth\": number;\n});\n\"nodeSetText\": ((id: number, text: string) => void);\n\"nodeGetFont\": ((id: number) => string);\n\"nodeSetFont\": ((id: number, font: string) => void);\n\"nodeGetWeight\": ((id: number) => number);\n\"nodeSetWeight\": ((id: number, weight: number) => void);\n\"nodeGetItalic\": ((id: number) => false | true);\n\"nodeSetItalic\": ((id: number, italic: false | true) => void);\n\"nodeGetAlign\": ((id: number) => number);\n\"nodeSetAlign\": ((id: number, align: number) => void);\n\"nodeGetWrap\": ((id: number) => number);\n\"nodeSetWrap\": ((id: number, wrap: number) => void);\n\"nodeGetWidth\": ((id: number) => number);\n\"nodeSetWidth\": ((id: number, width: number) => void);\n\"nodeGetSpacing\": ((id: number) => number);\n\"nodeSetSpacing\": ((id: number, spacing: number) => void);\n\"nodeGetLineHeight\": ((id: number) => number);\n\"nodeSetLineHeight\": ((id: number, lineHeight: number) => void);\n\"nodeGetDensity\": ((id: number) => number);\n\"nodeSetDensity\": ((id: number, density: number) => void);\n\"nodeGetRoundness\": ((id: number) => number);\n\"nodeSetRoundness\": ((id: number, roundness: number) => void);\n\"nodeGetSmoothing\": ((id: number) => number);\n\"nodeSetSmoothing\": ((id: number, smoothing: number) => void);\n\"nodeGetPrimType\": ((id: number) => number);\n\"nodeSetPrimType\": ((id: number, primitive: number) => void);\n\"nodeGetMirror\": ((id: number, slot: number) => {\n\"axis\": \"custom\" | \"x\" | \"y\" | \"z\" | \"disabled\";\n\"planePosition\": number;\n\"goop\": number;\n});\n\"nodeSetMirror\": ((id: number, slot: number, axis: \"x\" | \"y\" | \"z\" | \"disabled\", planePosition?: number, goop?: number) => void);\n\"nodeGetThickness\": ((id: number) => number);\n\"nodeSetThickness\": ((id: number, thickness: number) => void);\n\"curveGetClosed\": ((curveId: number) => false | true);\n\"curveSetClosed\": ((curveId: number, closed: false | true) => void);\n\"curvePointGetHandleIn\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointGetHandleOut\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetHandleIn\": ((curveId: number, pointIndex: number, value: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointSetHandleOut\": ((curveId: number, pointIndex: number, value: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointCount\": ((curveId: number) => number);\n\"curvePointAdd\": ((curveId: number, point: {\n\"name\"?: undefined | string;\n\"pos\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"rot\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"size\"?: undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"fixed\"?: undefined | false | true;\n\"round\"?: undefined | number;\n\"materialId\"?: undefined | number;\n}, pointIndex?: undefined | number) => number);\n\"curvePointRemove\": ((curveId: number, pointIndex: number) => void);\n\"curvePointGetName\": ((curveId: number, pointIndex: number) => string);\n\"curvePointSetName\": ((curveId: number, pointIndex: number, name: string) => void);\n\"curvePointGetPos\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetPos\": ((curveId: number, pointIndex: number, position: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetRot\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetRot\": ((curveId: number, pointIndex: number, rotation: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetSize\": ((curveId: number, pointIndex: number) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"curvePointSetSize\": ((curveId: number, pointIndex: number, sizeValue: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => void);\n\"curvePointGetFixed\": ((curveId: number, pointIndex: number) => false | true);\n\"curvePointSetFixed\": ((curveId: number, pointIndex: number, fixed: false | true) => void);\n\"curvePointGetRound\": ((curveId: number, pointIndex: number) => number);\n\"curvePointSetRound\": ((curveId: number, pointIndex: number, round: number) => void);\n\"curvePointGetMaterialId\": ((curveId: number, pointIndex: number) => null | number);\n\"curvePointSetMaterialId\": ((curveId: number, pointIndex: number, materialId: number) => void);\n\"materialImport\": ((name: string) => Promise<number>);\n\"materialCreate\": (() => number);\n\"materialDelete\": ((id: number) => void);\n\"materialList\": (() => Array<number>);\n\"materialGetName\": ((id: number) => string);\n\"materialSetName\": ((id: number, name: string) => void);\n\"materialGetTier\": ((id: number) => number);\n\"materialSetTier\": ((id: number, tier: number) => void);\n\"materialGetColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetSecondaryColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetSecondaryColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetSubsurfaceColor\": ((id: number) => {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n});\n\"materialSetSubsurfaceColor\": ((id: number, rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n\"materialGetRoughness\": ((id: number) => number);\n\"materialSetRoughness\": ((id: number, value: number) => void);\n\"materialGetMetalness\": ((id: number) => number);\n\"materialSetMetalness\": ((id: number, value: number) => void);\n\"materialGetTransmittance\": ((id: number) => number);\n\"materialSetTransmittance\": ((id: number, value: number) => void);\n\"materialGetTranslucency\": ((id: number) => number);\n\"materialSetTranslucency\": ((id: number, value: number) => void);\n\"materialGetIor\": ((id: number) => number);\n\"materialSetIor\": ((id: number, value: number) => void);\n\"materialGetSheen\": ((id: number) => number);\n\"materialSetSheen\": ((id: number, value: number) => void);\n\"materialGetSheenRoughness\": ((id: number) => number);\n\"materialSetSheenRoughness\": ((id: number, value: number) => void);\n\"materialGetSpecularTint\": ((id: number) => number);\n\"materialSetSpecularTint\": ((id: number, value: number) => void);\n\"materialGetAbsorption\": ((id: number) => number);\n\"materialSetAbsorption\": ((id: number, value: number) => void);\n\"materialGetEmission\": ((id: number) => number);\n\"materialSetEmission\": ((id: number, value: number) => void);\n\"materialGetIridescence\": ((id: number) => number);\n\"materialSetIridescence\": ((id: number, value: number) => void);\n\"materialGetTranslucencyWeight\": ((id: number) => number);\n\"materialSetTranslucencyWeight\": ((id: number, value: number) => void);\n\"materialGetDispersion\": ((id: number) => number);\n\"materialSetDispersion\": ((id: number, value: number) => void);\n\"materialGetSurfaceOpacity\": ((id: number) => number);\n\"materialSetSurfaceOpacity\": ((id: number, value: number) => void);\n\"listFontFamilies\": (() => Array<{\n\"name\": string;\n\"variants\": Array<{\n\"weight\": string;\n\"italic\": false | true;\n}>;\n}>);\n\"print\": ((...values: Array<unknown>) => void);\n\"nodeGetAABB\": ((id: number) => Promise<{\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}>);\n\"nodeResize\": ((id: number, dimensions: {\n\"x\"?: undefined | number;\n\"y\"?: undefined | number;\n\"z\"?: undefined | number;\n}) => Promise<void>);\n\"aabbCenter\": ((box: {\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"aabbRadius\": ((box: {\n\"min\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"max\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n}) => number);\n\"lookAt\": ((origin: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}, target: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}) => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"alignAxis\": ((direction: {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n}, axis: \"x\" | \"y\" | \"z\") => {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n});\n\"scenePropertiesRead\": (() => {\n\"hdr_name\": undefined | string;\n\"hdr_multiplier\": undefined | number;\n\"hdr_orientation\": undefined | {\n\"x\": number;\n\"y\": number;\n};\n\"backdrop_color1\": undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"backdrop_color2\": undefined | {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"backdrop_grad_offset\": undefined | {\n\"x\": number;\n\"y\": number;\n};\n});\n\"listHDRs\": (() => Array<string>);\n\"setHdrName\": ((name: string) => void);\n\"setHdrMultiplier\": ((multiplier: number) => void);\n\"setHdrOrientation\": ((orientation: {\n\"x\": number;\n\"y\": number;\n}) => void);\n\"setBackgroundColor\": ((rgb255: {\n\"r\": number;\n\"g\": number;\n\"b\": number;\n}) => void);\n}) => T | Promise<T>), expectedRevision: string) => Promise<T>);\n\"screenshot\": ((options?: undefined | {\n\"camera\"?: undefined | {\n\"position\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"target\": {\n\"x\": number;\n\"y\": number;\n\"z\": number;\n};\n\"projection\"?: undefined | \"perspective\" | \"orthographic\";\n\"horizontalFovDegrees\"?: undefined | number;\n\"orthographicWidth\"?: undefined | number;\n};\n}) => Promise<{\n\"id\": string;\n\"mediaType\": string;\n\"name\"?: undefined | string;\n}>);\n} };\ndeclare function print(...values: unknown[]): void;\ndeclare function emitImage(ref: { id: string; mediaType: string; name?: string }, options?: { inspect?: boolean }): Promise<void>;\ndeclare function emitFile(ref: { id: string; mediaType: string; name?: string }): Promise<void>;\n";
@@ -15,15 +15,29 @@ export function createBenchMetrics() {
15
15
  return { toolCounts, steps: Array.from(steps.values()) };
16
16
  },
17
17
  snapshot() {
18
- const names = Array.from(calls.values());
19
- const priced = Array.from(steps.values()).map((step) => step.cost?.totalUsd ?? null)
20
- .filter((cost) => cost !== null);
18
+ let readSkill = 0;
19
+ let executeJavaScript = 0;
20
+ for (const name of calls.values()) {
21
+ if (name === "read_skill")
22
+ readSkill++;
23
+ if (name === "execute_javascript")
24
+ executeJavaScript++;
25
+ }
26
+ let pricedSteps = 0;
27
+ let costUsd = 0;
28
+ for (const step of steps.values()) {
29
+ const cost = step.cost?.totalUsd ?? null;
30
+ if (cost === null)
31
+ continue;
32
+ pricedSteps++;
33
+ costUsd += cost;
34
+ }
21
35
  return {
22
36
  steps: steps.size,
23
- readSkill: names.filter((name) => name === "read_skill").length,
24
- executeJavaScript: names.filter((name) => name === "execute_javascript").length,
25
- costUsd: priced.length ? priced.reduce((sum, cost) => sum + cost, 0) : null,
26
- costStatus: (priced.length === 0 ? "unavailable" : priced.length < steps.size ? "partial" : "estimated"),
37
+ readSkill,
38
+ executeJavaScript,
39
+ costUsd: pricedSteps ? costUsd : null,
40
+ costStatus: (pricedSteps === 0 ? "unavailable" : pricedSteps < steps.size ? "partial" : "estimated"),
27
41
  };
28
42
  },
29
43
  };
@@ -65,11 +65,19 @@ export function receiptSceneHealth(health, limit = MAX_RECEIPT_THERMOMETER_OBJEC
65
65
  object.num_prims >= thermometer.max_num_prims ||
66
66
  object.voxels >= thermometer.max_per_object));
67
67
  };
68
- const ordered = [
69
- ...health.affectedAreaIds.filter((id) => thermometer.objects[id] !== undefined),
70
- ...ids.filter((id) => !health.affectedAreaIds.includes(id) && overflowing(id)),
71
- ...ids.filter((id) => !health.affectedAreaIds.includes(id) && !overflowing(id)),
72
- ];
68
+ const affected = health.affectedAreaIds.filter((id) => thermometer.objects[id] !== undefined);
69
+ const affectedIds = new Set(health.affectedAreaIds);
70
+ const overflowingIds = [];
71
+ const remainingIds = [];
72
+ for (const id of ids) {
73
+ if (affectedIds.has(id))
74
+ continue;
75
+ if (overflowing(id))
76
+ overflowingIds.push(id);
77
+ else
78
+ remainingIds.push(id);
79
+ }
80
+ const ordered = [...affected, ...overflowingIds, ...remainingIds];
73
81
  const kept = ordered.slice(0, limit);
74
82
  const objects = {};
75
83
  for (const id of kept)
@@ -129,6 +129,15 @@ export declare function createSdkSceneDraft(api: KakapoAPI, scene: SceneEdit, se
129
129
  nodeGetPower: (id: number) => number;
130
130
  nodeSetPower: (id: number, power: number) => void;
131
131
  nodeGetText: (id: number) => string;
132
+ nodeSetFacing: (id: number, direction: import("@womp/kakapo-sdk").Vec3) => void;
133
+ nodeSetTextSize: (id: number, size: {
134
+ fontSize: number;
135
+ depth: number;
136
+ }) => void;
137
+ nodeGetTextSize: (id: number) => {
138
+ fontSize: number;
139
+ depth: number;
140
+ };
132
141
  nodeSetText: (id: number, text: string) => void;
133
142
  nodeGetFont: (id: number) => string;
134
143
  nodeSetFont: (id: number, font: string) => void;
@@ -12,5 +12,6 @@ export async function captureSdkSceneScreenshot(api, input) {
12
12
  };
13
13
  if (camera.orthographicWidth !== undefined)
14
14
  camera.orthographicWidth *= INTERNAL_UNITS_PER_MM / units;
15
+ await api.setCamera(camera);
15
16
  return api.captureScreenshot({ camera, timeoutMs: 30_000 });
16
17
  }
@@ -1,28 +1,5 @@
1
- export declare const BENCH_PROMPTS: readonly [{
2
- readonly id: "armchair";
3
- readonly prompt: "Make a mustard-yellow upholstered armchair, 85 cm wide, 90 cm deep, and 85 cm tall. Give it a thick square seat cushion, a slightly reclined backrest, rounded armrests, and four short tapered wooden legs.";
4
- }, {
5
- readonly id: "desk-lamp";
6
- readonly prompt: "Make a matte-black desk lamp, 45 cm tall, with a circular base 18 cm in diameter, two slender articulated arms, and a conical shade 15 cm wide. Give the shade a white interior and a warm-white bulb.";
7
- }, {
8
- readonly id: "coffee-mug";
9
- readonly prompt: "Make a teal ceramic mug, 10 cm tall and 9 cm in diameter, with a gently rounded base, an open top, a thick rim, and a large C-shaped handle. Give it a cream-colored interior.";
10
- }, {
11
- readonly id: "bookshelf";
12
- readonly prompt: "Make a light-oak bookshelf, 180 cm tall, 90 cm wide, and 30 cm deep. Give it five evenly spaced open compartments, thick rectangular side panels, a solid back panel, and a recessed base.";
13
- }, {
14
- readonly id: "backpack";
15
- readonly prompt: "Make a navy-blue backpack, 45 cm tall, 30 cm wide, and 18 cm deep. Give it a rounded rectangular body, a large front zipper pocket, two padded shoulder straps, a top carry handle, and light-gray zipper pulls.";
16
- }, {
17
- readonly id: "toaster";
18
- readonly prompt: "Make a cream-colored two-slot toaster, 28 cm wide, 18 cm deep, and 20 cm tall. Give it rounded corners, a brushed-metal top, two long bread slots, a silver side lever, and a circular browning dial.";
19
- }, {
20
- readonly id: "plant-pot";
21
- readonly prompt: "Make a terracotta plant pot, 25 cm tall, tapering from a 30 cm opening to a 20 cm base. Give it a thick rolled rim and dark soil containing a small plant with six broad green leaves on short stems.";
22
- }, {
23
- readonly id: "suitcase";
24
- readonly prompt: "Make a burgundy hard-shell suitcase, 65 cm tall, 42 cm wide, and 26 cm deep. Give it rounded corners, five vertical ribs on each broad face, four black spinner wheels, a silver telescoping handle, and a black side carry handle.";
25
- }, {
26
- readonly id: "dining-table";
27
- readonly prompt: "Make a rectangular walnut dining table, 160 cm long, 90 cm wide, and 75 cm tall. Give it a 4 cm thick tabletop with softly rounded corners, four square tapered legs, and a recessed wooden apron beneath the top.";
28
- }];
1
+ export declare const BENCH_ORIENTATION = "Orient the object upright (+Y), with its front facing +Z and its base centered at the origin.";
2
+ export declare const BENCH_PROMPTS: {
3
+ prompt: string;
4
+ id: string;
5
+ }[];
@@ -1,3 +1,4 @@
1
+ export const BENCH_ORIENTATION = "Orient the object upright (+Y), with its front facing +Z and its base centered at the origin.";
1
2
  export const BENCH_PROMPTS = [
2
3
  { id: "armchair", prompt: "Make a mustard-yellow upholstered armchair, 85 cm wide, 90 cm deep, and 85 cm tall. Give it a thick square seat cushion, a slightly reclined backrest, rounded armrests, and four short tapered wooden legs." },
3
4
  { id: "desk-lamp", prompt: "Make a matte-black desk lamp, 45 cm tall, with a circular base 18 cm in diameter, two slender articulated arms, and a conical shade 15 cm wide. Give the shade a white interior and a warm-white bulb." },
@@ -8,4 +9,4 @@ export const BENCH_PROMPTS = [
8
9
  { id: "plant-pot", prompt: "Make a terracotta plant pot, 25 cm tall, tapering from a 30 cm opening to a 20 cm base. Give it a thick rolled rim and dark soil containing a small plant with six broad green leaves on short stems." },
9
10
  { id: "suitcase", prompt: "Make a burgundy hard-shell suitcase, 65 cm tall, 42 cm wide, and 26 cm deep. Give it rounded corners, five vertical ribs on each broad face, four black spinner wheels, a silver telescoping handle, and a black side carry handle." },
10
11
  { id: "dining-table", prompt: "Make a rectangular walnut dining table, 160 cm long, 90 cm wide, and 75 cm tall. Give it a 4 cm thick tabletop with softly rounded corners, four square tapered legs, and a recessed wooden apron beneath the top." },
11
- ];
12
+ ].map(item => ({ ...item, prompt: `${item.prompt} ${BENCH_ORIENTATION}` }));
@@ -2,7 +2,7 @@ import { once } from "node:events";
2
2
  import { mkdir, writeFile } from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { KakapoAPI } from "@womp/kakapo-sdk";
5
- import { z } from "zod";
5
+ import { benchCamera, benchGeometryIds } from "./bench-camera.js";
6
6
  import { SparkChatTransport } from "./client.js";
7
7
  import { createStandaloneSparkAgentApp } from "./server/standalone.js";
8
8
  import { BENCH_PROMPTS } from "./simple-bench-prompts.js";
@@ -40,7 +40,7 @@ export async function runSimpleBench(options) {
40
40
  const report = async () => {
41
41
  await writeFile(path.join(options.output, "results.json"), JSON.stringify({
42
42
  version: 1, startedAt, nodeVersion: process.version, settings: options.settings,
43
- timeoutMs: options.timeoutMs, camera: "fitted-perspective-preserving-direction", plannedPrompts: prompts.map((item) => item.id),
43
+ timeoutMs: options.timeoutMs, camera: "fixed-three-quarter-v3", plannedPrompts: prompts.map((item) => item.id),
44
44
  totalCost: totalBenchCost(results), results,
45
45
  }, null, 2));
46
46
  const columns = ["id", "status", "steps", "readSkill", "executeJavaScript", "screenshots", "durationMs", "costUsd", "costStatus", "image", "error"];
@@ -100,30 +100,18 @@ export async function runSimpleBench(options) {
100
100
  const api = new KakapoAPI({ url: options.kakapoUrl, requestTimeoutMs: 30_000 });
101
101
  try {
102
102
  await api.connect();
103
- const ids = api.listNodes({ parentId: 0 })
104
- .filter((node) => node.kind !== "light" && (!("hidden" in node) || !node.hidden))
105
- .map((node) => node.id);
103
+ const snapshot = await api.rpc("scene_state_get");
104
+ await writeFile(path.join(options.output, `${item.id}.scene.json`), typeof snapshot === "string" ? snapshot : JSON.stringify(snapshot));
105
+ const ids = benchGeometryIds(api);
106
106
  const bounds = await api.getNodesBoundingBox(ids);
107
107
  const viewport = await api.captureScreenshot({});
108
- const { camera } = await api.refreshScene();
109
- const direction = z.object({ x: z.number().finite(), y: z.number().finite(), z: z.number().finite() }).parse(camera.dir);
110
- const directionLength = Math.hypot(direction.x, direction.y, direction.z);
111
- if (directionLength === 0)
112
- throw new Error("Cannot frame a scene with a zero camera direction.");
113
- const target = {
114
- x: (bounds.min.x + bounds.max.x) / 2,
115
- y: (bounds.min.y + bounds.max.y) / 2,
116
- z: (bounds.min.z + bounds.max.z) / 2,
117
- };
118
- const radius = Math.hypot(bounds.max.x - bounds.min.x, bounds.max.y - bounds.min.y, bounds.max.z - bounds.min.z) / 2;
119
- const halfAngle = Math.atan(Math.tan(Math.PI / 6) * Math.min(1, viewport.height / viewport.width));
120
- const offset = Math.max(0.1, radius * 1.1 / Math.sin(halfAngle)) / directionLength;
121
- const image = await api.captureScreenshot({ camera: {
122
- position: { x: target.x - direction.x * offset, y: target.y - direction.y * offset, z: target.z - direction.z * offset },
123
- target, projection: "perspective", horizontalFovDegrees: 60,
124
- }, timeoutMs: 30_000 });
108
+ const camera = benchCamera(bounds, viewport.width / viewport.height);
109
+ await writeFile(path.join(options.output, `${item.id}.framing.json`), JSON.stringify({ ids, bounds, width: viewport.width, height: viewport.height, cameras: { "three-quarter": camera } }, null, 2));
110
+ const image = await api.captureScreenshot({ camera, timeoutMs: 30_000 });
111
+ if (image.width !== viewport.width || image.height !== viewport.height)
112
+ throw new Error("Viewport changed during benchmark capture.");
113
+ await writeFile(path.join(options.output, `${item.id}.jpg`), image.data);
125
114
  result.image = `${item.id}.jpg`;
126
- await writeFile(path.join(options.output, result.image), image.data);
127
115
  }
128
116
  finally {
129
117
  api.disconnect();
@@ -164,8 +164,20 @@ export declare function createWompSceneApi(context: WompSceneApiContext): {
164
164
  nodeGetLightType: (id: number) => number;
165
165
  nodeSetLightType: (id: number, lightType: number) => void;
166
166
  nodeGetPower: (id: number) => number;
167
+ /** Linear emitted intensity before collimation; not a percentage or physical unit. */
167
168
  nodeSetPower: (id: number, power: number) => void;
168
169
  nodeGetText: (id: number) => string;
170
+ /** Aim light emission or the readable text/decal face using target minus node position in parent-local coordinates. Use instead of generic lookAt for these faces. Y-up, Z-up when vertical. */
171
+ nodeSetFacing: (id: number, direction: Vec3) => void;
172
+ /** Font em size and extrusion depth in project units, not text bounding-box dimensions. */
173
+ nodeSetTextSize: (id: number, size: {
174
+ fontSize: number;
175
+ depth: number;
176
+ }) => void;
177
+ nodeGetTextSize: (id: number) => {
178
+ fontSize: number;
179
+ depth: number;
180
+ };
169
181
  nodeSetText: (id: number, text: string) => void;
170
182
  nodeGetFont: (id: number) => string;
171
183
  nodeSetFont: (id: number, font: string) => void;
@@ -177,8 +189,10 @@ export declare function createWompSceneApi(context: WompSceneApiContext): {
177
189
  nodeSetAlign: (id: number, align: number) => void;
178
190
  nodeGetWrap: (id: number) => number;
179
191
  nodeSetWrap: (id: number, wrap: number) => void;
192
+ /** Text layout width in project units, including owning Area scale. */
180
193
  nodeGetWidth: (id: number) => number;
181
194
  nodeSetWidth: (id: number, width: number) => void;
195
+ /** Additional letter spacing in project units, including owning Area scale. */
182
196
  nodeGetSpacing: (id: number) => number;
183
197
  nodeSetSpacing: (id: number, spacing: number) => void;
184
198
  nodeGetLineHeight: (id: number) => number;
@@ -272,6 +286,7 @@ export declare function createWompSceneApi(context: WompSceneApiContext): {
272
286
  nodeResize: (id: number, dimensions: Partial<Vec3>) => Promise<void>;
273
287
  aabbCenter: (box: AABB) => Vec3;
274
288
  aabbRadius: (box: AABB) => number;
289
+ /** Align local +Z from origin toward target, not a light's emission or a text/decal face; use nodeSetFacing for those. */
275
290
  lookAt: typeof lookAt;
276
291
  alignAxis: typeof alignAxis;
277
292
  scenePropertiesRead: () => {
@@ -1,8 +1,8 @@
1
- import { xyzRotationFromMatrix, MAX_BLEND_RADIUS_MM, MAX_MIRROR_BLEND_RADIUS_MM } from "@womp/kakapo-sdk";
1
+ import { xyzRotationFromMatrix, MAX_BLEND_RADIUS_MM, MAX_MIRROR_BLEND_RADIUS_MM, maxLightIntensity } from "@womp/kakapo-sdk";
2
2
  import { metadataObject, readMaterialMetadata, removeMaterialMetadata, shiftCurvePointMetadata, writeMaterialMetadata, } from "./scene-metadata.js";
3
3
  import { createSceneEnvironment } from "./scene-environment.js";
4
4
  import { assertColor255 } from "./color.js";
5
- import { convertRotationBasis, sceneUnitMultiplier, fromEngineDimensions, fromEngineMirrorRotation, fromEnginePosition, toEngineDimensions, toEngineMirrorRotation, toEnginePosition, } from "./coordinates.js";
5
+ import { INTERNAL_UNITS_PER_MM, convertRotationBasis, sceneUnitMultiplier, fromEngineDimensions, fromEngineMirrorRotation, fromEnginePosition, toEngineDimensions, toEngineMirrorRotation, toEnginePosition, } from "./coordinates.js";
6
6
  export const NodeType = {
7
7
  Primitive: 0,
8
8
  Union: 1,
@@ -395,6 +395,8 @@ export function createWompSceneApi(context) {
395
395
  const y = finite(sizeValue?.y, "size.y");
396
396
  if (x <= 0 || y <= 0)
397
397
  throw new Error("Light size.x and size.y must be positive");
398
+ if ("z" in sizeValue)
399
+ finite(sizeValue.z, "size.z");
398
400
  const converted = toEngineDimensions({ x, y, z: 1 }, unitMultiplier);
399
401
  update(id, { size: { x: converted.z, y: converted.y } });
400
402
  return;
@@ -643,7 +645,7 @@ export function createWompSceneApi(context) {
643
645
  return "operation" in node ? OPERATIONS.indexOf(node.operation) : OperationType.Union;
644
646
  },
645
647
  nodeSetOp: (id, operation) => {
646
- const value = OPERATIONS[Math.round(finite(operation, "operation"))];
648
+ const value = OPERATIONS[finite(operation, "operation")];
647
649
  if (!value)
648
650
  throw new Error("Operation must be from 0 to 3");
649
651
  const node = requireNode(id);
@@ -701,51 +703,113 @@ export function createWompSceneApi(context) {
701
703
  },
702
704
  nodeGetLightType: (id) => LIGHT_TYPES.indexOf(requireLight(id).lightType),
703
705
  nodeSetLightType: (id, lightType) => {
704
- const value = LIGHT_TYPES[Math.round(finite(lightType, "lightType"))];
706
+ requireLight(id);
707
+ const value = LIGHT_TYPES[finite(lightType, "lightType")];
705
708
  if (!value)
706
- throw new Error("LightType must be from 0 to 2");
709
+ throw new Error("LightType must be an integer from 0 to 2");
707
710
  update(id, { lightType: value });
708
711
  },
709
712
  nodeGetPower: (id) => requireLight(id).power,
713
+ /** Linear emitted intensity before collimation; not a percentage or physical unit. */
710
714
  nodeSetPower: (id, power) => {
711
- requireLight(id);
712
- if (!Number.isFinite(power) || power < 0 || power > 100)
713
- throw new Error(`Light ${id}: power must be a finite number from 0 through 100`);
715
+ const light = requireLight(id);
716
+ const max = maxLightIntensity(light.lightType);
717
+ if (!Number.isFinite(power) || power < 0 || power > max)
718
+ throw new Error(`Light ${id} (${light.lightType}): linear intensity must be a finite number from 0 through ${max}`);
714
719
  update(id, { power });
715
720
  },
716
721
  nodeGetText: (id) => requireText(id).text,
717
- nodeSetText: (id, text) => update(id, { text: String(text) }),
722
+ /** Aim light emission or the readable text/decal face using target minus node position in parent-local coordinates. Use instead of generic lookAt for these faces. Y-up, Z-up when vertical. */
723
+ nodeSetFacing: (id, direction) => {
724
+ requireNode(id);
725
+ const value = vector(direction, "direction");
726
+ const nativeDirection = { x: -value.z, y: value.y, z: -value.x };
727
+ const up = Math.abs(value.y) / Math.hypot(value.x, value.y, value.z) > 1 - 1e-8
728
+ ? { x: -1, y: 0, z: 0 } : { x: 0, y: 1, z: 0 };
729
+ context.call("setNodeFacing", [id, nativeDirection, up], () => scene.setNodeFacing(id, nativeDirection, up));
730
+ },
731
+ /** Font em size and extrusion depth in project units, not text bounding-box dimensions. */
732
+ nodeSetTextSize: (id, size) => {
733
+ requireText(id);
734
+ const fontSize = finite(size?.fontSize, "fontSize");
735
+ const depth = finite(size?.depth, "depth");
736
+ if (fontSize <= 0 || depth <= 0)
737
+ throw new Error("Text fontSize and depth must be positive");
738
+ const factor = INTERNAL_UNITS_PER_MM / ancestorScale(id);
739
+ const nativeSize = {
740
+ fontSize: clamp(fontSize / unitMultiplier, 0.01, 1000) * factor,
741
+ depth: clamp(depth / unitMultiplier, 0.01, 1000) * factor,
742
+ };
743
+ context.call("setTextSize", [id, nativeSize], () => scene.setTextSize(id, nativeSize));
744
+ },
745
+ nodeGetTextSize: (id) => {
746
+ const node = requireText(id);
747
+ const factor = ancestorScale(id) * unitMultiplier / INTERNAL_UNITS_PER_MM;
748
+ return { fontSize: node.transform.scale.x * factor, depth: node.transform.scale.z * factor };
749
+ },
750
+ nodeSetText: (id, text) => {
751
+ requireText(id);
752
+ if (typeof text !== "string")
753
+ throw new Error("text must be a string; use an empty string to clear it");
754
+ update(id, { text });
755
+ },
718
756
  nodeGetFont: (id) => requireText(id).fontFamily,
719
757
  nodeSetFont: (id, font) => {
758
+ requireText(id);
759
+ if (typeof font !== "string" || !font.trim())
760
+ throw new Error("font must be a non-empty font family name");
761
+ if (!context.fonts.length)
762
+ throw new Error("Font catalog is unavailable; this host cannot validate a new font selection");
720
763
  const match = context.fonts.find((family) => family.name.toLowerCase() === font.toLowerCase());
721
- if (!match && context.fonts.length)
722
- throw new Error(`Unknown font "${font}"`);
764
+ if (!match)
765
+ throw new Error(`Unknown font "${font}"; choose a family from the font catalog`);
723
766
  update(id, { fontFamily: match?.name ?? font });
724
767
  },
725
768
  nodeGetWeight: (id) => requireText(id).weight,
726
- nodeSetWeight: (id, weight) => update(id, { weight: clamp(finite(weight, "weight"), 100, 900) }),
769
+ nodeSetWeight: (id, weight) => {
770
+ requireText(id);
771
+ update(id, { weight: clamp(finite(weight, "weight"), 100, 900) });
772
+ },
727
773
  nodeGetItalic: (id) => requireText(id).italic,
728
- nodeSetItalic: (id, italic) => update(id, { italic: Boolean(italic) }),
774
+ nodeSetItalic: (id, italic) => {
775
+ requireText(id);
776
+ if (typeof italic !== "boolean")
777
+ throw new Error("italic must be a boolean");
778
+ update(id, { italic });
779
+ },
729
780
  nodeGetAlign: (id) => ALIGNS.indexOf(requireText(id).align),
730
781
  nodeSetAlign: (id, align) => {
731
- const value = ALIGNS[Math.round(finite(align, "align"))];
782
+ requireText(id);
783
+ const value = ALIGNS[finite(align, "align")];
732
784
  if (!value)
733
- throw new Error("Align must be from 0 to 2");
785
+ throw new Error("Align must be an integer from 0 to 2");
734
786
  update(id, { align: value });
735
787
  },
736
788
  nodeGetWrap: (id) => WRAPS.indexOf(requireText(id).wrap),
737
789
  nodeSetWrap: (id, wrap) => {
738
- const value = WRAPS[Math.round(finite(wrap, "wrap"))];
790
+ requireText(id);
791
+ const value = WRAPS[finite(wrap, "wrap")];
739
792
  if (!value)
740
- throw new Error("Wrap must be from 0 to 2");
793
+ throw new Error("Wrap must be an integer from 0 to 2");
741
794
  update(id, { wrap: value });
742
795
  },
743
- nodeGetWidth: (id) => requireText(id).width,
744
- nodeSetWidth: (id, width) => update(id, { width: finite(width, "width") }),
745
- nodeGetSpacing: (id) => requireText(id).spacing,
746
- nodeSetSpacing: (id, spacing) => update(id, { spacing: clamp(finite(spacing, "spacing"), -1, 1) }),
796
+ /** Text layout width in project units, including owning Area scale. */
797
+ nodeGetWidth: (id) => requireText(id).width * ancestorScale(id) * unitMultiplier / INTERNAL_UNITS_PER_MM,
798
+ nodeSetWidth: (id, width) => {
799
+ requireText(id);
800
+ update(id, { width: finite(width, "width") * INTERNAL_UNITS_PER_MM / unitMultiplier / ancestorScale(id) });
801
+ },
802
+ /** Additional letter spacing in project units, including owning Area scale. */
803
+ nodeGetSpacing: (id) => requireText(id).spacing * ancestorScale(id) * unitMultiplier / INTERNAL_UNITS_PER_MM,
804
+ nodeSetSpacing: (id, spacing) => {
805
+ requireText(id);
806
+ update(id, { spacing: clamp(finite(spacing, "spacing") / unitMultiplier, -25, 25) * INTERNAL_UNITS_PER_MM / ancestorScale(id) });
807
+ },
747
808
  nodeGetLineHeight: (id) => requireText(id).lineHeight,
748
- nodeSetLineHeight: (id, lineHeight) => update(id, { lineHeight: clamp(finite(lineHeight, "lineHeight"), 0.5, 3) }),
809
+ nodeSetLineHeight: (id, lineHeight) => {
810
+ requireText(id);
811
+ update(id, { lineHeight: clamp(finite(lineHeight, "lineHeight"), 0.5, 3) });
812
+ },
749
813
  nodeGetDensity: (id) => requireCurve(id).density,
750
814
  nodeSetDensity: (id, density) => update(id, { density: clamp(Math.round(finite(density, "density")), 0, 250) }),
751
815
  nodeGetRoundness: (id) => requireCurve(id).roundness,
@@ -762,7 +826,7 @@ export function createWompSceneApi(context) {
762
826
  return value;
763
827
  },
764
828
  nodeSetPrimType: (id, primitive) => {
765
- const value = PUBLIC_PRIMITIVES.get(Math.round(finite(primitive, "primitive")));
829
+ const value = PUBLIC_PRIMITIVES.get(finite(primitive, "primitive"));
766
830
  if (!value)
767
831
  throw new Error("PrimitiveType must be Sphere, Cylinder, Cube, Cone, Torus, or Pyramid");
768
832
  const node = requireNode(id);
@@ -991,6 +1055,7 @@ export function createWompSceneApi(context) {
991
1055
  z: (box.min.z + box.max.z) / 2,
992
1056
  }),
993
1057
  aabbRadius: (box) => Math.hypot(box.max.x - box.min.x, box.max.y - box.min.y, box.max.z - box.min.z) / 2,
1058
+ /** Align local +Z from origin toward target, not a light's emission or a text/decal face; use nodeSetFacing for those. */
994
1059
  lookAt,
995
1060
  alignAxis,
996
1061
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@womp/spark-agent",
3
- "version": "4.4.0",
3
+ "version": "4.4.1",
4
4
  "description": "Portable skills-based AI agent with local and durable chat transports for Womp",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -110,7 +110,7 @@
110
110
  "@ai-sdk/openai": "4.0.63",
111
111
  "@jitl/quickjs-wasmfile-release-sync": "0.32.0",
112
112
  "@womp/flowir": "0.3.0",
113
- "@womp/kakapo-sdk": "0.5.0",
113
+ "@womp/kakapo-sdk": "0.6.0",
114
114
  "ai": "7.0.95",
115
115
  "eventsource-parser": "^3.0.6",
116
116
  "express": "^5.2.1",