@womp/spark-agent 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,239 @@
1
+ # Changelog
2
+
3
+ Notable changes to `@womp/spark-agent`, newest first. Versions follow
4
+ [Semantic Versioning](https://semver.org/). Add an entry with each version bump; describe what
5
+ changed for hosts and users, and how to migrate across breaking changes.
6
+
7
+ ## 6.1.0 — 2026-10-08
8
+
9
+ ### Fixed
10
+
11
+ - A Geometry Nodes Area that the agent copies gets its own graph and script instance. The agent's
12
+ `nodeClone` copied the Area's `scriptInstanceId`, so editing either Area's graph or parameters
13
+ changed both. Areas linked this way before the upgrade stay linked.
14
+
15
+ ### Removed
16
+
17
+ - `nodeClone` from the agent's scene API. `cloneSubtree` is the only copy operation and also copies
18
+ single nodes. Hosts need no code change.
19
+
20
+ ### Changed
21
+
22
+ - Depends on `@womp/kakapo-sdk` 0.8.0, which removes `cloneNode`. Hosts that pin the SDK move it to
23
+ 0.8.0 together with this release, because the host's `KakapoAPI` and Spark must share one SDK copy.
24
+
25
+ ## 6.0.1 — 2026-10-07
26
+
27
+ ### Fixed
28
+
29
+ - Tool results reach the model with sorted keys, and `convertSparkMessages` replays stored tool
30
+ inputs as their schema validates them. History that a host reads back from storage that reorders
31
+ keys (Swan's Postgres JSONB thread rows) now matches what the live run sent, so turn starts in
32
+ Swan and Crow keep the provider prompt cache. Hosts need no change beyond the upgrade.
33
+
34
+ ## 6.0.0 — 2026-10-07
35
+
36
+ ### Breaking
37
+
38
+ - Removed `SparkAgentOptions.context`, the `createHost` `context` result, and `wompifyContext`.
39
+ Hosts send `sparkSystemPrompt(skills)`, which stays identical across a conversation so provider
40
+ prompt caches hit.
41
+ - `wompifyPrompt` takes a single request object including `referenceNamePrefix`.
42
+
43
+ ### Added
44
+
45
+ - `data-selection` user message part (`{ nodeIds }`) for the editor selection sent with a message.
46
+
47
+ ### Migrating to 6.0
48
+
49
+ - Stop passing per-run state in `context`. Attach the editor selection to the user message as a
50
+ `data-selection` part; send other changing state in messages.
51
+ - Replace `wompifyContext(...)` and positional `wompifyPrompt(...)` calls with
52
+ `wompifyPrompt({ referenceName, referenceNamePrefix, preset, note })`.
53
+
54
+ ## 5.12.1 — 2026-10-07
55
+
56
+ ### Fixed
57
+
58
+ - Goal state, rules and evaluator feedback are sent as appended messages instead of changing the
59
+ system prompt, so goal turns keep the prompt cache.
60
+
61
+ ## 5.12.0 — 2026-10-07
62
+
63
+ ### Added
64
+
65
+ - Goal endpoint `update_budget` command edits a goal's credit cap without restarting the run.
66
+ - Wompify detail levels Simple, High res and Ultra res.
67
+
68
+ ### Changed
69
+
70
+ - A Wompify pass completes when it reaches its credit cap instead of failing the run, and can keep
71
+ refining in the same conversation with a new budget.
72
+ - Goal credit budgets are no longer included in continuation prompts.
73
+
74
+ ## 5.11.1 — 2026-10-06
75
+
76
+ ### Fixed
77
+
78
+ - Removed goal token budgets that were reintroduced in 5.11.0.
79
+
80
+ ## 5.11.0 — 2026-10-06
81
+
82
+ ### Added
83
+
84
+ - Scene API support for patterned lights, light collimation, texture imports and physical depth
85
+ of field.
86
+
87
+ ## 5.10.0 — 2026-10-05
88
+
89
+ ### Changed
90
+
91
+ - Ambiguous creative requests get an image preview before building again; turning an image into
92
+ 3D uses mesh generation.
93
+
94
+ ## 5.9.1 — 2026-10-05
95
+
96
+ ### Fixed
97
+
98
+ - Goal turns report the credits they actually used and no longer estimate costs.
99
+
100
+ ## 5.9.0 — 2026-10-05
101
+
102
+ ### Changed
103
+
104
+ - Context trimming can also shorten the earlier steps of a long current turn.
105
+
106
+ ## 5.8.0 — 2026-10-04
107
+
108
+ ### Changed
109
+
110
+ - Goal budgets are enforced with host-reported charged credits; goal token budgets were removed.
111
+
112
+ ### Fixed
113
+
114
+ - Scene access results omit undefined properties.
115
+
116
+ ## 5.7.1 — 2026-10-03
117
+
118
+ ### Fixed
119
+
120
+ - `read_skill` takes names-only requests and accepts combined skill name inputs.
121
+
122
+ ## 5.7.0 — 2026-10-02
123
+
124
+ ### Added
125
+
126
+ - Persistent server goals with `set`, `pause`, `resume` and `clear` controls.
127
+
128
+ ## 5.6.1 — 2026-10-03
129
+
130
+ Published from a maintenance branch before 5.7.1.
131
+
132
+ ### Fixed
133
+
134
+ - `read_skill` uses names-only requests.
135
+
136
+ ## 5.6.0 — 2026-10-02
137
+
138
+ ### Fixed
139
+
140
+ - Skill tool input uses an object-root schema for provider compatibility.
141
+
142
+ ## 5.5.0 — 2026-10-01
143
+
144
+ ### Added
145
+
146
+ - Mesh Wompify: the shared `mesh-wompify` skill and Wompify request helpers in
147
+ `@womp/spark-agent/ui`.
148
+
149
+ ## 5.4.0 — 2026-09-30
150
+
151
+ ### Changed
152
+
153
+ - Requires Kakapo SDK 0.7.3.
154
+
155
+ ### Fixed
156
+
157
+ - Missing procedural material node locations.
158
+
159
+ ## 5.3.0 — 2026-09-29
160
+
161
+ ### Added
162
+
163
+ - Procedural material authoring capability.
164
+ - GPT-6.1 Sol model.
165
+
166
+ ### Changed
167
+
168
+ - Required skills load in one `read_skill` call.
169
+
170
+ ## 5.2.3 — 2026-09-29
171
+
172
+ ### Added
173
+
174
+ - Shared SDK scene adapters can omit `operations` to edit and save directly, without a recovery
175
+ journal.
176
+
177
+ ## 5.2.2 — 2026-09-28
178
+
179
+ ### Fixed
180
+
181
+ - Requires Kakapo SDK 0.7.2; curve density 0 is allowed again.
182
+
183
+ ## 5.2.1 — 2026-09-28
184
+
185
+ ### Fixed
186
+
187
+ - Requires Kakapo SDK 0.7.1, so stored out-of-range values no longer block unrelated reads and edits.
188
+
189
+ ## 5.2.0 — 2026-09-28
190
+
191
+ ### Changed
192
+
193
+ - A generation that ends on `length`, `content-filter`, `error` or `other` fails the run with the
194
+ unified and provider finish reasons in its error and diagnostics.
195
+
196
+ ## 5.1.0 — 2026-09-26
197
+
198
+ ### Added
199
+
200
+ - Each model step is trimmed to fit the model's context window.
201
+
202
+ ## 5.0.2 — 2026-09-25
203
+
204
+ ### Fixed
205
+
206
+ - Restored screenshot framing guidance.
207
+
208
+ ## 5.0.1 — 2026-09-25
209
+
210
+ ### Fixed
211
+
212
+ - Restored screenshot camera controls.
213
+
214
+ ## 5.0.0 — 2026-09-25
215
+
216
+ ### Breaking
217
+
218
+ - Scene capability `read`/`edit` replaced by `access(callback)`; custom scene hosts implement
219
+ `SceneHost.access` and SDK adapters `acquireAccess`.
220
+ - Requires Kakapo SDK 0.7.0.
221
+
222
+ ### Migrating to 5.0
223
+
224
+ - Replace scene capability `read`/`edit` with `access(callback)`. Inspect the current draft
225
+ through `scene.nodes({ ids, name, type, parentId, offset, limit })`, not a `nodes` array.
226
+ Results default to 100, with a maximum page size of 1,000.
227
+ - Update custom scene hosts to `SceneHost.access` and SDK adapters to `acquireAccess`.
228
+ `onCommitted` receives the acknowledged scene; keep host access suspended until synchronization
229
+ succeeds.
230
+ - Remove scene revision arguments from Geometry/OpenSCAD writes.
231
+ - Screenshot calls without options capture the current native viewport. Explicit `camera`
232
+ position/target, projection, `horizontalFovDegrees` and `orthographicWidth` are supported;
233
+ remove `targetId` and `view` presets. Camera distances use current project units.
234
+ - Request scene health explicitly through `scene.health()`; it no longer runs after each edit.
235
+ - Native and QuickJS executors allow 100,000 host calls per execution.
236
+
237
+ ## Earlier versions
238
+
239
+ Changes before 5.0.0 are recorded in the Git history.
package/README.md CHANGED
@@ -6,25 +6,9 @@ Spark Agent uses AI SDK 7 `UIMessage` and `UIMessageChunk` as its public chat pr
6
6
  JavaScript uses the host's executor and capabilities. Native browser execution and isolated QuickJS
7
7
  execution use the same model loop. The host owns conversations, artifacts, authorization, and connections.
8
8
 
9
- ## Requirements
10
-
11
- ### Migrating to 5.0
9
+ Release notes and migration guides are in [CHANGELOG.md](CHANGELOG.md).
12
10
 
13
- - Replace scene capability `read`/`edit` with `access(callback)`. Inspect the current draft
14
- through `scene.nodes({ ids, name, type, parentId, offset, limit })`, not a `nodes` array.
15
- Results default to 100, with a maximum page size of 1,000.
16
- - Update custom scene hosts to `SceneHost.access` and SDK adapters to `acquireAccess`.
17
- `onCommitted` receives the acknowledged scene; keep host access suspended until synchronization succeeds.
18
- - Remove scene revision arguments from Geometry/OpenSCAD writes. Current parameters and overrides
19
- are prepared inside protected access. Hosts must still enforce connection/project ownership.
20
- - Screenshot calls without options capture the current native viewport. Explicit `camera`
21
- position/target, projection, `horizontalFovDegrees` and `orthographicWidth` are supported;
22
- remove `targetId` and `view` presets. Camera distances use current project units.
23
- - Scene health is explicitly requested through `scene.health()`, not automatically after each edit.
24
- - This release requires Kakapo SDK 0.7.0. Native and QuickJS executors now allow 100,000 host calls
25
- per execution. Receipts, cancellation, timeout limits and uncertain-outcome handling remain enforced.
26
-
27
- ### Runtime
11
+ ## Requirements
28
12
 
29
13
  - Node.js 22.13 or newer
30
14
  - AI SDK 7
@@ -34,77 +18,6 @@ execution use the same model loop. The host owns conversations, artifacts, autho
34
18
  npm install @womp/spark-agent
35
19
  ```
36
20
 
37
- ## Run a prompt from the command line
38
-
39
- With the Spark server already running:
40
-
41
- ```sh
42
- yarn agent-run --prompt "Make a cube" --model gpt-5.6-luna --reasoning max
43
- ```
44
-
45
- Use `--conversation <id>` to continue a thread and `--output <new-directory>` to save
46
- `result.json`, `transcript.json` and original run artifacts under `artifacts/`.
47
- For local runs, use the git-ignored `.spark/` directory, with a fresh subdirectory per run:
48
-
49
- ```sh
50
- yarn agent-run --prompt "Make rainbow-colored boxes" --output .spark/agent-runs/rainbow-boxes
51
- yarn agent-run --prompt "Model this object using both views" --image front.png --image side.jpg --output .spark/agent-runs/reference-model
52
- ```
53
-
54
- Repeat `--image <path>` for local PNG, JPEG, WebP or GIF references, in argument order.
55
- The required prompt and all images are sent in one user message. Files, format signatures,
56
- and the full JSON request size (including base64 overhead) are checked before contacting the server.
57
- The CLI uses the server's default 25 MiB request limit; a custom server or provider may impose
58
- stricter limits. Images are never resized, and remote URLs are not accepted.
59
- With `--output`, original bytes are saved under `inputs/`; `input.json` and the result's `input`
60
- field list ordered original filenames, MIME types and relative paths. The submitted message in
61
- `transcript.json` uses those paths instead of inline data. Generated artifacts stay in `artifacts/`.
62
-
63
- Without output, artifacts remain server references. The CLI never clears the scene or
64
- takes extra screenshots. Defaults are `gpt-6-astra`, `high`, and
65
- `--api http://127.0.0.1:8787/agent`; unsupported settings are rejected.
66
-
67
- Progress goes to stderr; one JSON result goes to stdout. Use `yarn --silent agent-run`
68
- or the installed `agent-run` executable when parsing stdout (Yarn otherwise adds banners).
69
- Usage comes from the provider, with per-step USD estimates; missing usage is not estimated.
70
- Exit codes: 0 completed, 1 run/transport/export failure, 2 invalid arguments,
71
- 3 requires user action (continue in the UI), 130 interrupted. Interrupts attempt to cancel
72
- only this invocation's run; a failed cancellation is reported and the run may still be active.
73
- Output directories must not already exist. Artifact manifests include IDs, media types,
74
- server URLs and relative paths; failed downloads retain their references and report errors.
75
- Legacy inline base64 uploads in transcripts are replaced with `[inline data omitted]`.
76
-
77
- ## Mesh Wompify
78
-
79
- Swan imports the reference mesh with Disjoint off, then requests reconstruction
80
- through the shared `mesh-wompify` and `scene-editing` skills. Tier and request
81
- helpers are exported from `@womp/spark-agent/ui`. Server mode requires Crow to
82
- install the updated package and be redeployed; a local Swan package link is insufficient.
83
- The Mesh Wompify function panel accepts a file and a detail level (Simple, High res,
84
- or Ultra res). Reconstruction matches the reference's shape and colors; textures
85
- are not carried over. Crow sets the initial cap for each level and bills actual
86
- usage. Wompify keeps refining across turns until the cap, even if the evaluator
87
- judges the reconstruction sufficient; insufficient credits or a blocker stop it.
88
- Reaching the cap completes the pass without a run error. Keep refining
89
- asks for a new pass budget, then continues in the same conversation with the
90
- same reference and detail level. The budget travels as structured goal data.
91
- `wompifyPrompt` writes the reference name prefix into the request message, which is
92
- also the goal objective, so every pass names the same reference.
93
-
94
- Ordinary goals support `{ action: "update_budget", goalId, creditBudget }` on
95
- the goal endpoint. This edits the total credit cap without resetting usage,
96
- restarting the run, or adding a model message. Crow reads the current cap before
97
- worker and evaluator calls; an in-flight call may finish. Raising an exhausted
98
- cap leaves the goal paused until Resume. Wompify's tier caps cannot be edited.
99
-
100
- ## System prompt and editor selection
101
-
102
- Every host sends `sparkSystemPrompt(skills)`: the shared agent prompt and the skills
103
- directory, with nothing host-specific, so it stays identical across a conversation.
104
- Hosts attach the editor selection to the user message it was sent with as a
105
- `data-selection` part (`{ nodeIds }`). It is not rendered as chat text; the model reads
106
- it as a short note on that message.
107
-
108
21
  ## Package entry points
109
22
 
110
23
  - `@womp/spark-agent` — browser-safe model loop, two tools, persistence hooks, and shared contracts
@@ -124,8 +37,17 @@ Kakapo, Express, or React at runtime.
124
37
 
125
38
  `runSparkAgent` accepts a configured model, model messages, an executor, a capability composition,
126
39
  and an artifact resolver. It exposes exactly `read_skill` and `execute_javascript` to the model.
127
- Skills carry instructions, declarations, and JavaScript examples. The native executor runs in the
128
- page realm; it is not a sandbox and cannot interrupt a synchronous infinite loop.
40
+ Skills carry instructions, declarations, and JavaScript examples. Kakapo skill declarations are
41
+ generated from its typed API at build time and packaged as JavaScript strings.
42
+
43
+ ### System prompt and editor selection
44
+
45
+ Every host sends `sparkSystemPrompt(skills)`: the shared agent prompt and the skills directory,
46
+ with nothing host-specific, so it stays identical across a conversation. Hosts attach the editor
47
+ selection to the user message it was sent with as a `data-selection` part (`{ nodeIds }`). It is
48
+ not rendered as chat text; the model reads it as a short note on that message.
49
+
50
+ ### Capabilities
129
51
 
130
52
  Compose only supported capabilities with `composeCapabilities({ scene, account, ... })`. Each
131
53
  capability supplies its skills and `createApi(context)`; the returned API is bound under `womp`.
@@ -134,34 +56,35 @@ own their transactions and must check cancellation at their commit boundary.
134
56
 
135
57
  For a real user interaction, call `context.waitForUser(label, async signal => ...)` outside mutation
136
58
  locks. The run stays active with `requires_action` progress and resumes the same invocation after
137
- input. Native and QuickJS executors exclude this wait from their execution budget; service work
138
- continues to consume time, and QuickJS guest computation still counts even if an interaction was
139
- not awaited. Abort settles the wait and late answers cannot revive it. The UI host must also reject
140
- competing requests for a shared dialog and match callbacks to the original interaction identity.
141
- Custom executors must honor the optional host-owned `userWait` argument to `execute`.
59
+ input; the wait is excluded from the execution budget. Abort settles the wait and late answers
60
+ cannot revive it. Custom executors must honor the optional host-owned `userWait` argument to `execute`.
61
+
62
+ Shared SDK scene adapters may omit `operations` to edit and save directly. Supplying `operations`
63
+ adds a durable operation journal and recovery of uncertain edits.
64
+
65
+ ### Persistence and run lifecycle
142
66
 
143
67
  Persist the user message before starting a run. Supply `persistence.beforeToolCall`,
144
68
  `persistence.recordReceipt`, and `persistence.afterToolCall` for awaited storage barriers.
145
69
  Supply `persistence.saveMessage` to save the canonical UI message at each model-step boundary and
146
- at termination, including reasoning and provider metadata. Spark awaits each checkpoint before the
147
- next model request. Consume the run's stream while awaiting its result; the result settles after
148
- the terminal checkpoint. A host run owner must keep consuming when a view detaches.
149
- A failed barrier aborts the loop. The default model-step limit is 100; a limit returns
150
- `status: "incomplete"`. A host must not automatically restart to bypass that limit.
151
- A generation that ends on any other non-`stop` reason (`length`, `content-filter`, `error`,
152
- `other`) rejects the result and ends the run `failed`: its error names the unified reason and the
153
- provider's raw one, and its diagnostics carry the unified reason as `code`.
154
-
155
- Spark does not estimate or limit input tokens or automatically shorten conversation history.
156
- The provider enforces its context limit; rejections follow the normal provider-error path.
70
+ at termination. Spark awaits each checkpoint before the next model request; a failed barrier aborts
71
+ the loop. Consume the run's stream while awaiting its result; a host run owner must keep consuming
72
+ when a view detaches.
73
+
74
+ The default model-step limit is 100; reaching it returns `status: "incomplete"`, and hosts must not
75
+ restart automatically to bypass it. A generation that ends on any other non-`stop` reason fails the
76
+ run with the unified and provider finish reasons in its error and diagnostics.
77
+
78
+ Before each model step, Spark trims older images, large tool results, and whole earlier turns to
79
+ keep the request inside the model's context window. The latest user message and the most recent
80
+ steps are never trimmed.
81
+
82
+ ### Artifacts
157
83
 
158
84
  Screenshot and file APIs return serializable artifact references. `emitImage` and `emitFile` resolve
159
85
  them through the host's artifact resolver. Keep references resolvable when reloading history, and
160
86
  pass `createSparkTools(...)` to AI SDK's `convertToModelMessages` to reconstruct multimodal results.
161
- `emitImage(artifact, { inspect: false })` displays an image without adding its bytes to model input,
162
- including restored history. Inspection is enabled by default.
163
- Kakapo skill declarations are generated from its actual typed API during the build and packaged as
164
- JavaScript strings; they do not need filesystem or Markdown loading in the browser.
87
+ `emitImage(artifact, { inspect: false })` displays an image without adding its bytes to model input.
165
88
 
166
89
  ## Local frontend
167
90
 
@@ -196,10 +119,7 @@ const chat = useChat<SparkUIMessage>({
196
119
 
197
120
  Render `message.parts`. Standard AI SDK parts represent text, reasoning, files, tool inputs, tool
198
121
  outputs, approvals, and step boundaries. Spark adds typed `data-console`, `data-artifact`,
199
- `data-run-status`, `data-step-metrics`, and `data-execution-receipt` parts. Receipts are emitted before
200
- their storage barrier, keeping known effects visible even when saving the tool result fails.
201
- Hosts can consume `data-tool-input-label` once the tool's label field is complete, while the
202
- remaining input is still streaming.
122
+ `data-run-status`, `data-step-metrics`, `data-execution-receipt`, and `data-tool-input-label` parts.
203
123
 
204
124
  An explicit Stop action must cancel the durable run before stopping local observation:
205
125
 
@@ -215,21 +135,16 @@ Closing or reloading the page only detaches the SSE subscriber. It does not canc
215
135
  `SparkChatTransport` hides the durable run lifecycle from `useChat`:
216
136
 
217
137
  ```text
218
- POST /agent/conversations/:conversationId/messages
138
+ POST /agent/conversations/:conversationId/messages
219
139
  PATCH /agent/conversations/:conversationId/settings
220
- GET /agent/runs/:runId/stream?after=0
221
- POST /agent/runs/:runId/cancel
140
+ POST /agent/conversations/:conversationId/goal
141
+ GET /agent/runs/:runId/stream?after=0
142
+ POST /agent/runs/:runId/cancel
222
143
  ```
223
144
 
224
- Conversation settings contain `modelId` and `reasoningEffort`. The standalone UI saves selector
225
- changes immediately through `transport.saveConversationSettings(id, settings)` and restores them
226
- per thread. Older threads fall back to their last recorded model (or the default) and medium effort;
227
- unsupported choices fall back to supported settings. Assistant footers show the model recorded on
228
- that turn, independently of the selector.
229
-
230
- Custom stores must implement `saveConversationSettings` as a settings-only update, and preserve
231
- stored settings during `saveConversation` so streaming history saves cannot overwrite preferences.
232
- The built-in memory and SQLite stores implement this contract.
145
+ Conversation settings contain `modelId` and `reasoningEffort`; save them with
146
+ `transport.saveConversationSettings(id, settings)`. The goal endpoint accepts `set`, `pause`,
147
+ `resume`, `clear`, and `update_budget` commands.
233
148
 
234
149
  The SSE response contains ordered persistence envelopes around standard AI SDK chunks:
235
150
 
@@ -244,8 +159,7 @@ type StoredSparkChunk = {
244
159
  ```
245
160
 
246
161
  The transport unwraps each envelope and returns the contained `UIMessageChunk` to `useChat`.
247
- Active assistant messages are replayed from sequence zero when reconnecting because `useChat`
248
- reconstructs the in-progress message from the resumed stream.
162
+ Active assistant messages are replayed from sequence zero when reconnecting.
249
163
 
250
164
  ## Embedding in an Express backend
251
165
 
@@ -276,15 +190,25 @@ app.use(
276
190
 
277
191
  `MemorySparkAgentStore` and `MemorySparkArtifactStore` are development implementations. Production
278
192
  hosts must supply durable implementations backed by their database/object storage and must preserve
279
- the ordering contract of `appendRunChunk()`.
193
+ the ordering contract of `appendRunChunk()`. Custom stores must also:
194
+
195
+ - implement `saveConversationSettings` as a settings-only update, and preserve stored settings
196
+ during `saveConversation`;
197
+ - implement `saveConversationGoal` to support goals;
198
+ - optionally implement `releaseActiveRun(conversationId, runId, updatedAt)` to clear the active run
199
+ only if its ID still matches.
200
+
201
+ The built-in memory and SQLite stores implement all of these.
280
202
 
281
203
  `SparkAgentServiceOptions.endOrphanedRuns` defaults to `false`. Enable it only when one process
282
- owns the store: a message or Stop then ends unfinished runs not held by that process. On a shared
283
- store, enabling it could end another process's live run.
204
+ owns the store: a message or Stop then ends unfinished runs not held by that process.
284
205
 
285
- Custom stores can implement `releaseActiveRun(conversationId, runId, updatedAt)` to clear the active
286
- run only if its ID still matches. Memory and SQLite stores implement it. Without it, the service
287
- serializes read-and-save release against its own submissions.
206
+ ## Mesh Wompify
207
+
208
+ Mesh Wompify reconstructs an imported reference mesh as editable primitives through the shared
209
+ `mesh-wompify` and `scene-editing` skills. `WOMPIFY_PRESETS`, `wompifyPrompt`, and
210
+ `parseWompifyCommand` are exported from `@womp/spark-agent/ui`. A Wompify run is a goal: it refines
211
+ across turns until its credit cap, and can continue in the same conversation with a new budget.
288
212
 
289
213
  ## Standalone development server
290
214
 
@@ -302,107 +226,63 @@ Configure the process with:
302
226
  - `KAKAPO_URL` (defaults to `ws://127.0.0.1:5502`)
303
227
  - `PORT` (defaults to `8787`)
304
228
  - `SPARK_STORAGE_PATH` (defaults to `.spark/spark.sqlite`)
305
- - `SPARK_SCENE_IDENTITY` (optional stable identity for the scene behind `KAKAPO_URL`)
229
+ - `SPARK_SCENE_IDENTITY` (optional; set only when the value names the same durable scene across
230
+ renderer reconnects)
306
231
 
307
- The CLI automatically loads `.env` from its working directory when the file exists. Copy
308
- `.env.example` to `.env`, then add the provider key you intend to use. Existing process environment
309
- variables take precedence over values loaded from the file.
232
+ The CLI loads `.env` from its working directory when present; copy `.env.example` to `.env` and add
233
+ the provider key you intend to use. Process environment variables take precedence.
310
234
 
311
235
  For repository development, `yarn dev` starts the Express server and Vite demo together. Open
312
- `http://127.0.0.1:5173`.
313
-
314
- Shared SDK scene adapters can omit `operations` to use direct edit/save with
315
- per-invocation outcomes and conversation receipts. This path does not persist a scene
316
- journal, recover uncertain edits, or reuse previous operation results. Validation,
317
- settlement, and the host's save policy still apply; geometry/OpenSCAD refund repair
318
- attempts only after confirmed rollback. Hosts that supply `operations` retain their
319
- existing journal and recovery behavior.
320
-
321
- Standalone scene edits use the existing `scene_state_patch` command followed by `save_scene` after
322
- the patch is acknowledged. The durable operation journal records the separate mutation and save
323
- outcomes. A failed or unknown save stops that operation with an explicit error, retaining any
324
- applied work without replay. The two commands are not an atomic transaction, and a renderer save
325
- acknowledgement proves only renderer-local history, not durable backend storage.
326
-
327
- The standalone server persists conversations, run streams, and screenshot bytes in SQLite. Only
328
- one local process can execute against a database. After a terminated process is replaced, startup
329
- preserves recorded output and marks abandoned queued/running runs incomplete without replaying
330
- scene edits. Pending approvals remain pending; startup does not resume abandoned runs.
331
- Node 22 reports an experimental warning for its built-in SQLite module.
332
-
333
- Set `SPARK_SCENE_IDENTITY` only when the host can verify that the value names the same durable
334
- scene across renderer reconnects. Without it, Spark uses a process-scoped identity and does not
335
- authorize interrupted scene mutations to continue after a server restart.
336
-
337
- `createStandaloneSparkAgentApp(options)` is asynchronous. Await it before listening, and call
338
- `await app.dispose()` on shutdown to settle active runs and release storage ownership.
339
-
340
- When using a sibling `kakapo-sdk` dependency, run `yarn build` in `../kakapo-sdk` before installing
341
- Spark dependencies. Replace local dependencies with registry versions before publishing.
342
-
343
- For the explicit fictional account profile, use `yarn dev:demo-account` or
344
- `spark-agent --profile demo-account`. It adds the `account` skill and `womp.account.read`
345
- beside the real local Kakapo scene API. Profile reads identify themselves as fictional fixtures;
346
- credits, billing, orders, and other account services report unavailable. The default composition
347
- omits account entirely. Neither profile supplies fake generation jobs, imports, or billing permission.
348
- Embedded development servers can select `developmentProfile: "demo-account"` explicitly.
349
-
350
- The same profile supplies two actual local material resources: `Development: Matte Blue` and
351
- `Development: Polished Copper`. They are bundled JSON files under `src/server/fixtures/materials`
352
- and imported through the normal SDK draft, not simulated scene effects. In `scene.edit`, await
353
- `api.materialImport(name)`, then assign its numeric ID. The default profile has no library service.
236
+ `http://127.0.0.1:5173`. When using a sibling `kakapo-sdk` dependency, run `yarn build` in
237
+ `../kakapo-sdk` before installing Spark dependencies.
238
+
239
+ The standalone server persists conversations, run streams, and screenshots in SQLite; only one
240
+ local process can execute against a database. `createStandaloneSparkAgentApp(options)` is
241
+ asynchronous: await it before listening, and call `await app.dispose()` on shutdown.
242
+
243
+ `yarn dev:demo-account` (or `spark-agent --profile demo-account`) adds a fictional `account` skill
244
+ and two development material resources beside the real local Kakapo scene API. Its account reads
245
+ identify themselves as fixtures; other account services report unavailable.
246
+
247
+ ## Run a prompt from the command line
248
+
249
+ With the Spark server already running:
250
+
251
+ ```sh
252
+ yarn agent-run --prompt "Make a cube" --model gpt-5.6-luna --reasoning max
253
+ yarn agent-run --prompt "Model this object using both views" --image front.png --image side.jpg --output .spark/agent-runs/reference-model
254
+ ```
255
+
256
+ - `--conversation <id>` continues a thread.
257
+ - `--image <path>` attaches a local PNG, JPEG, WebP or GIF reference; repeat it for more images.
258
+ - `--output <new-directory>` saves `result.json`, `transcript.json`, inputs, and run artifacts.
259
+ For local runs, use a fresh subdirectory of the git-ignored `.spark/` directory.
260
+
261
+ Progress goes to stderr; one JSON result goes to stdout. Use `yarn --silent agent-run` when parsing
262
+ stdout. Exit codes: 0 completed, 1 run/transport/export failure, 2 invalid arguments, 3 requires
263
+ user action, 130 interrupted.
354
264
 
355
265
  ## Run cost estimates
356
266
 
357
- Prompt caching is enabled for every listed model: Claude Opus 5 and Fable 5 use
358
- automatic 5-minute caching, and GPT-6 Astra uses implicit caching with a 30-minute TTL.
359
- The providers manage the cache as message history grows across tool steps; no local
360
- response cache is used. Cache hits require matching prefixes, sufficient prompt length,
361
- and an unexpired entry. Goal state stays out of the system prompt: objectives,
362
- goal rules and evaluator feedback arrive in appended goal messages. Cache writes can cost more than uncached input, while subsequent
363
- cache reads are cheaper. The UI displays actual reported reads/writes, not assumed savings.
364
- See [Claude caching](https://platform.claude.com/docs/en/build-with-claude/prompt-caching)
365
- and [OpenAI caching](https://developers.openai.com/api/docs/guides/prompt-caching).
366
- Restart the server after changing these settings; existing runs keep their original configuration.
367
-
368
- The chat displays estimated API token cost in USD, updated after every completed model step.
369
- Hover or focus the amount to inspect uncached input, cache reads/writes, and output costs. Output usage
370
- already includes reasoning tokens. Image input is included in the provider's input token count.
371
-
372
- `src/pricing.ts` contains standard direct API rates verified on September 9, 2026:
373
-
374
- | Model | Input / 1M | Cache read / 1M | Cache write / 1M | Output / 1M |
375
- | -------------- | ---------- | --------------- | --------------------- | ----------- |
376
- | GPT-6 Astra | $10 | $1 | $12.50 | $50 |
377
- | Claude Opus 5 | $5 | $0.50 | $6.25 (5m), $10 (1h) | $25 |
378
- | Claude Fable 5 | $10 | $1 | $12.50 (5m), $20 (1h) | $50 |
379
-
380
- Astra requests above 272,000 input tokens use 2x input/cache rates and 1.5x output rates.
381
- This threshold is applied to each request before summing run costs. Claude's full context uses
382
- standard rates. Sources: [Astra pricing](https://developers.openai.com/api/docs/models/gpt-6-astra),
383
- [Claude pricing](https://platform.claude.com/docs/en/about-claude/pricing).
384
-
385
- Each `data-step-metrics` part stores a `cost` snapshot with the model, rate date, source, token
386
- categories, rates, and amounts. The UI sums those stored amounts, so reconnection does not double
387
- count steps and future price changes do not reprice recorded runs. Update the rate table and its
388
- verification date when provider pricing changes.
389
-
390
- The unfinished step is excluded until its usage arrives. Cancelled/failed runs show a partial
391
- estimate. Missing usage, unknown models, missing cache TTLs, or provider sub-inferences without
392
- separate attribution are marked unavailable, never silently priced as zero. Historical runs
393
- without step pricing remain unavailable. Estimates exclude taxes, negotiated discounts, and scene
394
- hosting; the provider bill is authoritative. Spark requests OpenAI's standard service tier.
267
+ The chat displays estimated API token cost in USD after every completed model step, from the
268
+ provider-reported usage and the rates in `src/pricing.ts`. Each `data-step-metrics` part stores
269
+ its `cost` snapshot, so recorded runs are not repriced when rates change. Missing usage or unknown
270
+ models are shown as unavailable, never priced as zero. Estimates exclude taxes, discounts, and
271
+ scene hosting; the provider bill is authoritative.
272
+
273
+ Prompt caching is enabled for every listed model. It depends on an identical request prefix, which
274
+ is why per-turn state travels in messages rather than the system prompt.
395
275
 
396
276
  ## Execution security
397
277
 
398
278
  The standalone host uses a fresh QuickJS runtime for each JavaScript execution. It has no Node.js
399
279
  or browser globals and receives only the composed capability APIs. Imports, filesystem access,
400
280
  network APIs, and host environment variables are not exposed. QuickJS limits memory, stack size,
401
- execution time, source size, host calls, and data crossing the host bridge. Browser hosts can instead
402
- choose native page execution, with the page-global access and interruption limitations described above.
403
- Both executors allow 100,000 host calls per execution by default; the counter resets for each
404
- execution. QuickJS supports overriding this through `maxHostCalls`. Cancellation, timeouts,
405
- and the other execution limits still apply.
281
+ execution time, source size, host calls, and data crossing the host bridge. Both executors allow
282
+ 100,000 host calls per execution by default (`maxHostCalls` overrides this in QuickJS).
283
+
284
+ Browser hosts can instead use native page execution. It runs in the page realm: it is not a sandbox
285
+ and cannot interrupt a synchronous infinite loop.
406
286
 
407
287
  QuickJS isolates generated code from the JavaScript host API; it is not an operating-system security
408
288
  boundary. Multi-tenant deployments must additionally isolate workers, authorize every Kakapo
@@ -420,41 +300,30 @@ yarn web:build
420
300
 
421
301
  ## Release procedure
422
302
 
423
- Pushes to `main` run `.github/workflows/publish.yml`. Publication is driven by
424
- `package.json`, not Git tags: already-published versions skip; unpublished stable versions
425
- newer than npm's `latest` run release checks and publish automatically.
426
-
427
- Versions follow **MAJOR.MINOR.PATCH** (for example, `4.4.0`):
428
-
429
- - **Major:** breaking changes.
430
- - **Minor:** backward-compatible new features.
431
- - **Patch:** backward-compatible bug fixes.
303
+ Pushes to `main` run `.github/workflows/publish.yml`. Publication is driven by `package.json`, not
304
+ Git tags: already-published versions are skipped; an unpublished stable version newer than npm's
305
+ `latest` runs the release checks and is published automatically.
432
306
 
433
- ### Publishing
307
+ Versions follow **MAJOR.MINOR.PATCH**: major for breaking changes, minor for backward-compatible
308
+ features, patch for backward-compatible fixes.
434
309
 
435
310
  1. Configure npm's trusted publisher once for `@womp/spark-agent`: organization `wompxyz`,
436
311
  repository `spark-agent`, workflow filename `publish.yml`, no environment, and allow direct
437
312
  `npm publish`. GitHub-hosted runners use OIDC; no publishing token is required.
438
- 2. Deliberately bump `package.json` to an unused stable MAJOR.MINOR.PATCH version and push
439
- the release commit to `main`. Prereleases/build metadata are not published by this workflow.
440
- 3. CI installs the frozen Yarn lockfile, runs typechecks, tests and the UI build, then checks
441
- package entry files and imports every exported module from a fresh tarball installation.
442
- It rechecks npm before publishing that same archive and verifies registry integrity and `latest`,
443
- allowing up to five minutes of polling waits for npm processing and metadata propagation.
444
- A visible integrity mismatch fails immediately; missing metadata or a lagging `latest` fails
445
- if it does not converge within the polling limit.
446
- Releases are serialized; newer pending pushes may supersede older pending runs.
447
- Registry failures stop publication rather than being treated as missing versions.
448
- 4. If publication reports an uncertain result, inspect npm before rerunning the failed workflow.
449
- Published versions cannot be replaced; corrections need a new version. No tags are required.
450
- 5. In the consuming application, use `yarn add @womp/spark-agent@<version> --exact`. Commit its
451
- manifest and lockfile together, and verify a clean frozen-lockfile installation and production
452
- build. Remove the temporary archive dependency. Application deployment and merge requirements
453
- remain separate from package publication.
313
+ 2. Bump `package.json` to an unused stable version, add its entry to `CHANGELOG.md`, and push the
314
+ release commit to `main`. Prereleases are not published by this workflow.
315
+ 3. CI installs the frozen lockfile, runs typechecks, tests and the UI build, verifies the packed
316
+ tarball's entry points and imports, then publishes and verifies registry integrity and `latest`.
317
+ 4. If publication reports an uncertain result, inspect npm before rerunning the workflow. Published
318
+ versions cannot be replaced; corrections need a new version.
319
+ 5. In the consuming application, run `yarn add @womp/spark-agent@<version> --exact` and commit its
320
+ manifest and lockfile together.
454
321
 
455
322
  ## Layout
456
323
 
457
324
  - `src/agent.ts` — AI SDK stream and Spark tool orchestration
325
+ - `src/prompt.ts` — shared system prompt
326
+ - `src/context-budget.ts` — per-step context-window trimming
458
327
  - `src/ui.ts` — browser-safe protocol types and validation schemas
459
328
  - `src/client.ts` — durable `ChatTransport` implementation
460
329
  - `src/server/` — service, storage contracts, Express adapter, artifacts, and standalone composition
@@ -1,6 +1,6 @@
1
1
  import { tool } from "ai";
2
2
  import { z } from "zod";
3
- import { boundedResultText } from "./bounded-output.js";
3
+ import { boundedResultText, canonicalJsonValue } from "./bounded-output.js";
4
4
  import { completedInputString } from "./tool-input-label.js";
5
5
  import { UserWait } from "./execution-lifetime.js";
6
6
  function errorMessage(error) {
@@ -98,6 +98,8 @@ export function createSparkTools(options) {
98
98
  const skills = [...new Set(input.names)].map(read);
99
99
  return { ok: skills.every(skill => skill.ok), skills };
100
100
  }),
101
+ // Replayed from storage that may reorder keys; see canonicalJsonValue.
102
+ toModelOutput: ({ output }) => ({ type: "json", value: canonicalJsonValue(output) }),
101
103
  }),
102
104
  execute_javascript: tool({
103
105
  ...inputLabels("purpose"),
@@ -1,5 +1,13 @@
1
1
  export declare const MODEL_RESULT_BYTE_LIMIT: number;
2
2
  export declare const MODEL_ERROR_BYTE_LIMIT: number;
3
+ /**
4
+ * `value` with every object's keys sorted, recursively. Hosts store tool
5
+ * results in databases that reorder keys (Postgres JSONB puts shorter keys
6
+ * first), so a replayed result must not depend on the order it was read back
7
+ * in: the bytes the model reads have to match what the live run sent, or every
8
+ * later turn misses the provider's prompt cache from that result onward.
9
+ */
10
+ export declare function canonicalJsonValue(value: unknown): unknown;
3
11
  export declare function byteLength(text: string): number;
4
12
  /**
5
13
  * `text` cut to at most `limit` bytes on a character boundary. A cut that lands
@@ -15,8 +23,9 @@ export declare function truncateUtf8(text: string, limit: number): string;
15
23
  export declare function boundedText(text: string, limit: number, label: string): string;
16
24
  /**
17
25
  * The serialized tool result the model reads, bounded to
18
- * `MODEL_RESULT_BYTE_LIMIT`. Persistence, the UI stream and the host's own
19
- * receipts keep the full output; only model input is bounded here.
26
+ * `MODEL_RESULT_BYTE_LIMIT`, with keys in canonical order. Persistence, the UI
27
+ * stream and the host's own receipts keep the full output; only model input is
28
+ * bounded here.
20
29
  *
21
30
  * Stages, in order, so the most useful part survives: bound `error`, then bound
22
31
  * each receipt's `details`, then keep only as many receipts as the budget
@@ -4,6 +4,23 @@ const encoder = new TextEncoder();
4
4
  const decoder = new TextDecoder();
5
5
  export const MODEL_RESULT_BYTE_LIMIT = 1024 * 1024;
6
6
  export const MODEL_ERROR_BYTE_LIMIT = 8 * 1024;
7
+ /**
8
+ * `value` with every object's keys sorted, recursively. Hosts store tool
9
+ * results in databases that reorder keys (Postgres JSONB puts shorter keys
10
+ * first), so a replayed result must not depend on the order it was read back
11
+ * in: the bytes the model reads have to match what the live run sent, or every
12
+ * later turn misses the provider's prompt cache from that result onward.
13
+ */
14
+ export function canonicalJsonValue(value) {
15
+ if (Array.isArray(value))
16
+ return value.map(canonicalJsonValue);
17
+ if (value === null || typeof value !== "object")
18
+ return value;
19
+ const record = value;
20
+ return Object.fromEntries(Object.keys(record)
21
+ .sort()
22
+ .map((key) => [key, canonicalJsonValue(record[key])]));
23
+ }
7
24
  export function byteLength(text) {
8
25
  return encoder.encode(text).byteLength;
9
26
  }
@@ -33,8 +50,9 @@ export function boundedText(text, limit, label) {
33
50
  }
34
51
  /**
35
52
  * The serialized tool result the model reads, bounded to
36
- * `MODEL_RESULT_BYTE_LIMIT`. Persistence, the UI stream and the host's own
37
- * receipts keep the full output; only model input is bounded here.
53
+ * `MODEL_RESULT_BYTE_LIMIT`, with keys in canonical order. Persistence, the UI
54
+ * stream and the host's own receipts keep the full output; only model input is
55
+ * bounded here.
38
56
  *
39
57
  * Stages, in order, so the most useful part survives: bound `error`, then bound
40
58
  * each receipt's `details`, then keep only as many receipts as the budget
@@ -46,7 +64,7 @@ export function boundedResultText(output, limit = MODEL_RESULT_BYTE_LIMIT) {
46
64
  const errorBounded = typeof output.error === "string"
47
65
  ? { ...output, error: boundedText(output.error, MODEL_ERROR_BYTE_LIMIT, "Error") }
48
66
  : output;
49
- const asText = (value) => JSON.stringify(value) ?? "null";
67
+ const asText = (value) => JSON.stringify(canonicalJsonValue(value)) ?? "null";
50
68
  let text = asText(errorBounded);
51
69
  if (byteLength(text) <= limit)
52
70
  return text;
@@ -102,7 +102,7 @@ Establish a comparison view matching the reference's angle, projection, and subj
102
102
  Compare each rendered pass directly with the source. Identify the largest remaining visible shape mismatch, edit it, and verify that it improved before moving to smaller details. Use close-ups when the comparison view cannot resolve a feature; return to the comparison view afterward. Adjust sampling or resolution when visible faceting or segmentation requires it—not as a substitute for reshaping.
103
103
  Do not stop at semantic resemblance or after a fixed number of screenshots. Continue while substantial visible mismatches remain and supported edits are making progress, within the available budget. If progress stalls or the chosen representation cannot achieve the requested fidelity, explain the specific limitation and ask before changing workflows. Before finishing, compare the latest render with the reference and address the largest remaining visible mismatch; if substantial differences remain, identify the concrete stopping reason rather than treating an approximation disclaimer as completion.
104
104
 
105
- nodeClone is shallow (no children). await cloneSubtree(id, { parentId?, name?, index? }) copies the complete hierarchy with fresh IDs,
105
+ await cloneSubtree(id, { parentId?, name?, index? }) copies a node and its complete hierarchy with fresh IDs,
106
106
  preserving local transforms, order and metadata, remapping internal references and sharing external materials/assets.
107
107
  Cloning stages changes in the draft and commits them with the rest of the access.
108
108
  For primitives, nodeSetBlend joins against all accumulated preceding geometry in the Area, not only the nearest part. A Union's blend affects its outer join, not joins between its children; top-level Area blend does not smooth its contents.
@@ -1 +1 @@
1
- export declare const WOMP_SCENE_DECLARATIONS = "declare const womp: { scene: {\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\"access\": (<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\"nodeGetCollimation\": ((id: number) => number);\n\"nodeSetCollimation\": ((id: number, collimation: number) => void);\n\"nodeGetLightTextureFile\": ((id: number) => string);\n\"nodeSetLightTextureFile\": ((id: number, textureFile: string) => void);\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\"cameraReadDepthOfField\": (() => {\n\"enabled\": false | true;\n\"mode\": \"physical\" | \"post-process\";\n\"focusDistance\": number;\n\"aperturePercent\": number;\n\"projection\": \"perspective\" | \"orthographic\";\n});\n\"cameraSetDepthOfField\": ((input: {\n\"enabled\"?: undefined | false | true;\n\"mode\"?: undefined | \"physical\" | \"post-process\";\n\"focusDistance\"?: undefined | number;\n\"aperturePercent\"?: undefined | number;\n}) => void);\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\"unitMultiplier\": number;\n\"nodes\": ((options?: {\n\"ids\"?: undefined | Array<number>;\n\"type\"?: undefined | number;\n\"parentId\"?: undefined | number;\n\"name\"?: undefined | string;\n\"offset\"?: undefined | number;\n\"limit\"?: undefined | number;\n}) => Array<{\n\"id\": number;\n\"name\": string;\n\"type\": number;\n\"parentId\": number;\n}>);\n}) => T | Promise<T>)) => 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\"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\"access\": (<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\"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\"nodeGetCollimation\": ((id: number) => number);\n\"nodeSetCollimation\": ((id: number, collimation: number) => void);\n\"nodeGetLightTextureFile\": ((id: number) => string);\n\"nodeSetLightTextureFile\": ((id: number, textureFile: string) => void);\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\"cameraReadDepthOfField\": (() => {\n\"enabled\": false | true;\n\"mode\": \"physical\" | \"post-process\";\n\"focusDistance\": number;\n\"aperturePercent\": number;\n\"projection\": \"perspective\" | \"orthographic\";\n});\n\"cameraSetDepthOfField\": ((input: {\n\"enabled\"?: undefined | false | true;\n\"mode\"?: undefined | \"physical\" | \"post-process\";\n\"focusDistance\"?: undefined | number;\n\"aperturePercent\"?: undefined | number;\n}) => void);\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\"unitMultiplier\": number;\n\"nodes\": ((options?: {\n\"ids\"?: undefined | Array<number>;\n\"type\"?: undefined | number;\n\"parentId\"?: undefined | number;\n\"name\"?: undefined | string;\n\"offset\"?: undefined | number;\n\"limit\"?: undefined | number;\n}) => Array<{\n\"id\": number;\n\"name\": string;\n\"type\": number;\n\"parentId\": number;\n}>);\n}) => T | Promise<T>)) => 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\"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\"access\": (<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\"nodeGetCollimation\": ((id: number) => number);\n\"nodeSetCollimation\": ((id: number, collimation: number) => void);\n\"nodeGetLightTextureFile\": ((id: number) => string);\n\"nodeSetLightTextureFile\": ((id: number, textureFile: string) => void);\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\"cameraReadDepthOfField\": (() => {\n\"enabled\": false | true;\n\"mode\": \"physical\" | \"post-process\";\n\"focusDistance\": number;\n\"aperturePercent\": number;\n\"projection\": \"perspective\" | \"orthographic\";\n});\n\"cameraSetDepthOfField\": ((input: {\n\"enabled\"?: undefined | false | true;\n\"mode\"?: undefined | \"physical\" | \"post-process\";\n\"focusDistance\"?: undefined | number;\n\"aperturePercent\"?: undefined | number;\n}) => void);\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\"unitMultiplier\": number;\n\"nodes\": ((options?: {\n\"ids\"?: undefined | Array<number>;\n\"type\"?: undefined | number;\n\"parentId\"?: undefined | number;\n\"name\"?: undefined | string;\n\"offset\"?: undefined | number;\n\"limit\"?: undefined | number;\n}) => Array<{\n\"id\": number;\n\"name\": string;\n\"type\": number;\n\"parentId\": number;\n}>);\n}) => T | Promise<T>)) => 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\"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\"access\": (<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\"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\"nodeGetCollimation\": ((id: number) => number);\n\"nodeSetCollimation\": ((id: number, collimation: number) => void);\n\"nodeGetLightTextureFile\": ((id: number) => string);\n\"nodeSetLightTextureFile\": ((id: number, textureFile: string) => void);\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\"cameraReadDepthOfField\": (() => {\n\"enabled\": false | true;\n\"mode\": \"physical\" | \"post-process\";\n\"focusDistance\": number;\n\"aperturePercent\": number;\n\"projection\": \"perspective\" | \"orthographic\";\n});\n\"cameraSetDepthOfField\": ((input: {\n\"enabled\"?: undefined | false | true;\n\"mode\"?: undefined | \"physical\" | \"post-process\";\n\"focusDistance\"?: undefined | number;\n\"aperturePercent\"?: undefined | number;\n}) => void);\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\"unitMultiplier\": number;\n\"nodes\": ((options?: {\n\"ids\"?: undefined | Array<number>;\n\"type\"?: undefined | number;\n\"parentId\"?: undefined | number;\n\"name\"?: undefined | string;\n\"offset\"?: undefined | number;\n\"limit\"?: undefined | number;\n}) => Array<{\n\"id\": number;\n\"name\": string;\n\"type\": number;\n\"parentId\": number;\n}>);\n}) => T | Promise<T>)) => 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,13 +1,30 @@
1
- import { convertToModelMessages } from "ai";
1
+ import { asSchema, convertToModelMessages } from "ai";
2
2
  import { sparkDataPartSchemas } from "./ui.js";
3
3
  function record(value) {
4
4
  return typeof value === "object" && value !== null && !Array.isArray(value)
5
5
  ? value
6
6
  : {};
7
7
  }
8
+ /**
9
+ * A stored call's input as the live run handed it to the model: the AI SDK
10
+ * passes on the input its schema validated, in the schema's key order, while
11
+ * storage may return the keys in another order (Postgres JSONB sorts them).
12
+ * An input the schema refuses is replayed as stored.
13
+ */
14
+ async function liveInput(tools, part) {
15
+ if (part.type !== "dynamic-tool" && !part.type.startsWith("tool-"))
16
+ return part;
17
+ const name = part.type === "dynamic-tool" ? part.toolName : part.type.slice(5);
18
+ const tool = tools[name];
19
+ const input = part.input;
20
+ if (tool === undefined || input === null || typeof input !== "object" || Array.isArray(input))
21
+ return part;
22
+ const validated = await asSchema(tool.inputSchema).validate?.(input);
23
+ return validated?.success ? { ...part, input: validated.value } : part;
24
+ }
8
25
  /** UI artifact previews already represented by a tool result are not model output. */
9
- export function convertSparkMessages(messages, tools) {
10
- const history = messages.map((message) => {
26
+ export async function convertSparkMessages(messages, tools) {
27
+ const history = await Promise.all(messages.map(async (message) => {
11
28
  if (message.role !== "assistant")
12
29
  return message;
13
30
  const previews = new Set();
@@ -28,9 +45,11 @@ export function convertSparkMessages(messages, tools) {
28
45
  }
29
46
  return {
30
47
  ...message,
31
- parts: message.parts.filter((part) => part.type !== "file" || (!previews.has(part.url) && part.providerMetadata?.spark?.inspect !== false)),
48
+ parts: await Promise.all(message.parts
49
+ .filter((part) => part.type !== "file" || (!previews.has(part.url) && part.providerMetadata?.spark?.inspect !== false))
50
+ .map((part) => liveInput(tools, part))),
32
51
  };
33
- });
52
+ }));
34
53
  return convertToModelMessages(history, {
35
54
  tools,
36
55
  convertDataPart: (part) => {
@@ -88,7 +88,6 @@ export declare function createSdkSceneDraft(api: KakapoAPI, scene: SceneEdit, se
88
88
  } & Record<number, string>;
89
89
  nodeCreate: (type: number, parentId?: number) => number;
90
90
  nodeDelete: (id: number) => void;
91
- nodeClone: (id: number) => number;
92
91
  cloneSubtree: (id: number, options?: {
93
92
  parentId?: number;
94
93
  name?: string;
@@ -124,7 +124,6 @@ export declare function createWompSceneApi(context: WompSceneApiContext): {
124
124
  } & Record<number, string>;
125
125
  nodeCreate: (type: number, parentId?: number) => number;
126
126
  nodeDelete: (id: number) => void;
127
- nodeClone: (id: number) => number;
128
127
  /** Deep clone; preserves sibling order and remaps internal references. Await before other edits. */
129
128
  cloneSubtree: (id: number, options?: {
130
129
  parentId?: number;
@@ -545,12 +545,6 @@ export function createWompSceneApi(context) {
545
545
  requireNode(id);
546
546
  context.call("deleteNode", [id], () => scene.deleteNode(id));
547
547
  },
548
- nodeClone: (id) => {
549
- requireNode(id);
550
- const clone = context.call("cloneNode", [id], () => scene.cloneNode(id));
551
- context.trackNode(clone.id);
552
- return clone.id;
553
- },
554
548
  /** Deep clone; preserves sibling order and remaps internal references. Await before other edits. */
555
549
  cloneSubtree: async (id, options = {}) => {
556
550
  if (id === context.rootId)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@womp/spark-agent",
3
- "version": "6.0.0",
3
+ "version": "6.1.0",
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",
@@ -73,7 +73,8 @@
73
73
  "dist/**/*.d.ts",
74
74
  "dist/server/fixtures/**/*.json",
75
75
  "dist/geometry/schemas/**/*.json",
76
- "README.md"
76
+ "README.md",
77
+ "CHANGELOG.md"
77
78
  ],
78
79
  "sideEffects": false,
79
80
  "engines": {
@@ -111,7 +112,7 @@
111
112
  "@ai-sdk/openai": "4.0.63",
112
113
  "@jitl/quickjs-wasmfile-release-sync": "0.32.0",
113
114
  "@womp/flowir": "0.3.0",
114
- "@womp/kakapo-sdk": "0.7.3",
115
+ "@womp/kakapo-sdk": "0.8.0",
115
116
  "ai": "7.0.95",
116
117
  "eventsource-parser": "^3.0.6",
117
118
  "express": "^5.2.1",