@womp/spark-agent 5.2.1 → 5.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +430 -423
- package/dist/capabilities/geometry.js +14 -14
- package/dist/capabilities/openscad-instructions.js +77 -77
- package/dist/capabilities/operations.js +28 -28
- package/dist/capabilities/scene.js +69 -69
- package/dist/geometry/schemas/backend-schema.json +3393 -3393
- package/dist/geometry/schemas/flowir-dialect.json +1023 -1023
- package/dist/geometry.js +6 -6
- package/dist/prompt.js +41 -41
- package/dist/scene-operations.d.ts +3 -2
- package/dist/scene-operations.js +19 -11
- package/dist/sdk-geometry-host.js +3 -1
- package/dist/sdk-openscad-host.js +3 -1
- package/dist/sdk-scene-host.d.ts +6 -1
- package/dist/sdk-scene-host.js +19 -3
- package/dist/server/fixtures/materials/matte-blue.json +14 -14
- package/dist/server/fixtures/materials/polished-copper.json +14 -14
- package/dist/server/sqlite-store.js +37 -37
- package/dist/womp-scene-api.js +3 -1
- package/package.json +139 -139
|
@@ -14,20 +14,20 @@ export function createGeometryCapability(host, reference) {
|
|
|
14
14
|
name: "geometry-nodes",
|
|
15
15
|
version: "5",
|
|
16
16
|
description: "Create and edit visual Geometry Nodes graphs with adjustable parameters and animation.",
|
|
17
|
-
instructions: `Use womp.geometry for requested Geometry Nodes, parametric organic/procedural geometry, or animation.
|
|
18
|
-
Keep follow-up edits to an existing Geometry Nodes object in its graph, preserving its adjustable parameters and instances.
|
|
19
|
-
Read the target after any scene edit this build needs. read(0) reads the scene root as a creation container.
|
|
20
|
-
write updates an existing shared graph, attaches a new graph to an Area without one, or creates a new Area beneath the root/Group target. Use the returned objectId for follow-up edits.
|
|
21
|
-
Read geometry-nodes-reference before writing source. Supply the complete FlowIR text after inspecting the target. JavaScript calls execute JavaScript; source is a FlowIR string, not JavaScript or JSON.
|
|
22
|
-
Inspect the current target before replacing its graph; preserve unrelated geometry and parameter overrides.
|
|
23
|
-
If source is null and diagnostics are present, the existing graph cannot be edited without loss. Explain the limitation; never treat it as empty or create a replacement to bypass the refusal.
|
|
24
|
-
Preserve unrelated statements, parameter names, and FlowIR node IDs from the read. Shared graph edits affect all listed instances; report the affected objects. Valid overrides migrate by parameter name and type. Removed or type-changed parameters return to graph defaults and are reported.
|
|
25
|
-
Use min/max/step for naturally bounded parameters and omit ranges for free-form positions/rotations. Meaningful parameter names become editor labels. Do not invent label fields.
|
|
26
|
-
SetMaterial assigns one scene material to every primitive it receives. Its Material input is a scene material ID, not a color; 0 selects the scene default material.
|
|
27
|
-
Obtain that ID from the scene-editing skill inside one scene.access, where those lookups live: materialList with materialGetName and materialGetColor to reuse an existing material, materialCreate with materialSetColor and materialSetName for a new one, or listSuperMaterials with materialImport for a library material. Prefer reusing a material that already matches the request over creating another, and do not recolor a shared material unless every object using it should change.
|
|
28
|
-
Create or import the material inside scene.access before writing the geometry target, all within one JavaScript call. Each call has a fresh scope and cannot read an earlier call's variables.
|
|
29
|
-
Positions and sizes are millimetres; Boolean Blend uses the conversion in geometry-nodes-reference. Coordinates are right-handed, +X right, +Y up, +Z forward. Rotations are degrees, intrinsic X-Z-Y.
|
|
30
|
-
On compiler errors, repair the source in this same conversation and retry with a fresh read. A rejected write made no change. Committed/unknown effects remain in execution receipts even if a later call fails; inspect before retrying.
|
|
17
|
+
instructions: `Use womp.geometry for requested Geometry Nodes, parametric organic/procedural geometry, or animation.
|
|
18
|
+
Keep follow-up edits to an existing Geometry Nodes object in its graph, preserving its adjustable parameters and instances.
|
|
19
|
+
Read the target after any scene edit this build needs. read(0) reads the scene root as a creation container.
|
|
20
|
+
write updates an existing shared graph, attaches a new graph to an Area without one, or creates a new Area beneath the root/Group target. Use the returned objectId for follow-up edits.
|
|
21
|
+
Read geometry-nodes-reference before writing source. Supply the complete FlowIR text after inspecting the target. JavaScript calls execute JavaScript; source is a FlowIR string, not JavaScript or JSON.
|
|
22
|
+
Inspect the current target before replacing its graph; preserve unrelated geometry and parameter overrides.
|
|
23
|
+
If source is null and diagnostics are present, the existing graph cannot be edited without loss. Explain the limitation; never treat it as empty or create a replacement to bypass the refusal.
|
|
24
|
+
Preserve unrelated statements, parameter names, and FlowIR node IDs from the read. Shared graph edits affect all listed instances; report the affected objects. Valid overrides migrate by parameter name and type. Removed or type-changed parameters return to graph defaults and are reported.
|
|
25
|
+
Use min/max/step for naturally bounded parameters and omit ranges for free-form positions/rotations. Meaningful parameter names become editor labels. Do not invent label fields.
|
|
26
|
+
SetMaterial assigns one scene material to every primitive it receives. Its Material input is a scene material ID, not a color; 0 selects the scene default material.
|
|
27
|
+
Obtain that ID from the scene-editing skill inside one scene.access, where those lookups live: materialList with materialGetName and materialGetColor to reuse an existing material, materialCreate with materialSetColor and materialSetName for a new one, or listSuperMaterials with materialImport for a library material. Prefer reusing a material that already matches the request over creating another, and do not recolor a shared material unless every object using it should change.
|
|
28
|
+
Create or import the material inside scene.access before writing the geometry target, all within one JavaScript call. Each call has a fresh scope and cannot read an earlier call's variables.
|
|
29
|
+
Positions and sizes are millimetres; Boolean Blend uses the conversion in geometry-nodes-reference. Coordinates are right-handed, +X right, +Y up, +Z forward. Rotations are degrees, intrinsic X-Z-Y.
|
|
30
|
+
On compiler errors, repair the source in this same conversation and retry with a fresh read. A rejected write made no change. Committed/unknown effects remain in execution receipts even if a later call fails; inspect before retrying.
|
|
31
31
|
After applying, read the returned object and use the scene screenshot API with emitImage to inspect the applied result.`,
|
|
32
32
|
declarations: WOMP_GEOMETRY_DECLARATIONS,
|
|
33
33
|
examples: [
|
|
@@ -1,81 +1,81 @@
|
|
|
1
|
-
export const OPENSCAD_INSTRUCTIONS = `Use womp.openscad to create or update one adjustable CAD part. Read an existing part before editing it.
|
|
2
|
-
Keep follow-up edits to an existing CAD part in that part unless the user asks to change representation.
|
|
1
|
+
export const OPENSCAD_INSTRUCTIONS = `Use womp.openscad to create or update one adjustable CAD part. Read an existing part before editing it.
|
|
2
|
+
Keep follow-up edits to an existing CAD part in that part unless the user asks to change representation.
|
|
3
3
|
read(0) returns the root container for creation. read(id) returns an existing
|
|
4
|
-
part or container. Use the scene-editing skill when available to discover other scene objects.
|
|
5
|
-
create requires a parentId (0 means the scene root); update requires the existing objectId.
|
|
6
|
-
Both methods compile the effective source and parameters, apply one undoable change, and check wall thickness.
|
|
4
|
+
part or container. Use the scene-editing skill when available to discover other scene objects.
|
|
5
|
+
create requires a parentId (0 means the scene root); update requires the existing objectId.
|
|
6
|
+
Both methods compile the effective source and parameters, apply one undoable change, and check wall thickness.
|
|
7
7
|
Preserve intervening user changes. Ask the user when the intended edits conflict or remain ambiguous.
|
|
8
8
|
Existing overrides are preserved for parameters still present;
|
|
9
|
-
params supplies overrides to merge into the current values. Keep top-level parameter names stable.
|
|
10
|
-
Return complete source on every update and preserve unrelated geometry. Never create a replacement to repair a part.
|
|
11
|
-
Compile errors return status rejected without applying. Creation requires validated placement bounds.
|
|
12
|
-
An update may apply with validation unavailable; that is a diagnostic, not proof that it compiles.
|
|
13
|
-
An applied part remains in the scene even if thickness fails or is unavailable. Use the returned objectId for repairs.
|
|
14
|
-
When thickness fails, increase thin walls and fragile connections while preserving requested dimensions and openings.
|
|
15
|
-
At most four applied printability repairs are allowed per logical build/edit in this run. Respect the returned limit;
|
|
16
|
-
do not bypass it by recreating the part. Unavailable thickness is not a pass. Report unresolved issues honestly.
|
|
17
|
-
Build connected geometry and avoid features below 1.4 mm. OpenSCAD source dimensions use millimetres,
|
|
18
|
-
independently of the scene display unit. New parts are centered and grounded from compiled bounds.
|
|
19
|
-
OpenSCAD is Z-up; the scene-editing API is Y-up. For an unrotated part at its creation-time scale and an identity parent transform,
|
|
20
|
-
a source point [x,y,z] mm maps to scene {x:y, y:z, z:-x} times the scene.unitMultiplier inside the access callback, plus nodeGetPos(partId).
|
|
21
|
-
Account for the part and parent transforms when they are not identity; source coordinates are not scene coordinates.
|
|
22
|
-
After a major change, use the scene screenshot API and emitImage to inspect the applied result.
|
|
23
|
-
A committed effect can survive later failure. Inspect receipts and the existing part before retrying.
|
|
24
|
-
Do not print source in the final answer unless requested; describe the result and any unresolved diagnostics.
|
|
25
|
-
|
|
26
|
-
RUNTIME
|
|
27
|
-
- Produce a single OpenSCAD file.
|
|
28
|
-
- Do not use imports, includes, external libraries, text, hull, minkowski, polyhedron, or extrudes.
|
|
29
|
-
- Prefer cube, sphere, cylinder, translate, rotate, color, union, difference, and intersection.
|
|
30
|
-
- Do not use $fn, $fa, or $fs; tessellation controls are ignored.
|
|
31
|
-
- Build faceted geometry by combining supported primitives with CSG operations and transforms.
|
|
32
|
-
- Do not use scale(); size primitives directly instead.
|
|
33
|
-
- Use color("#rrggbb") around distinct visible parts.
|
|
34
|
-
- Keep the model centered near the origin and use millimeter-like units consistently.
|
|
35
|
-
- For organic blending, use goop(radius_mm) { ... }. The radius is in millimetres before parent scaling, matching scene-editing; do not multiply by project unitMultiplier. It is ordered: the first child seeds with blend 0, and each later child uses radius_mm.
|
|
36
|
-
- Put core primitives first. Avoid wrapping goop children in union() when they should blend individually.
|
|
37
|
-
|
|
38
|
-
SCREWS AND THREADS
|
|
39
|
-
- Copy helical_ridge below for rounded screw threads, necks, caps, and coils. It joins spheres with cylinders; never use stacked rings or disconnected spheres.
|
|
40
|
-
- Dimensions are mm: radius = ridge centerline radius; pitch = axial travel/turn; tube_radius = half ridge thickness; handedness = 1 (right) or -1 (left).
|
|
41
|
-
- For a hand control use thread_hand = 1; // [-1:Left, 1:Right] and pass it directly. Ternary expressions (?:) are unsupported.
|
|
42
|
-
- Embed the ridge in the shaft/neck (e.g. radius = shaft_radius). Hollow fittings: subtract the bore from body + thread. Internal threads: subtract the helix from the socket wall with mating clearance. Mating parts need matching pitch and handedness.
|
|
43
|
-
- Expose diameter, pitch, thread length, and thickness in Customizer; derive sampling. Keep 2 * tube_radius < pitch and allow tube_radius beyond both path endpoints for rounded ends. This is a rounded profile, not ISO/metric V-thread; never claim standards compliance.
|
|
44
|
-
- Build heads/grips separately using cylinders, tapered cylinders, and radial ribs/cutters, not thread samples.
|
|
45
|
-
|
|
46
|
-
module helical_ridge(radius, pitch, turns, tube_radius, handedness) {
|
|
47
|
-
if (radius > 0 && pitch > 0 && turns > 0 && tube_radius > 0) {
|
|
48
|
-
// Limit chord error to 0.03 mm or 3% of the ridge radius.
|
|
49
|
-
chord_error = min(0.03, tube_radius * 0.03);
|
|
50
|
-
steps_per_turn = max(48, ceil(180 / acos(1 - min(1, chord_error / radius))));
|
|
51
|
-
steps = ceil(turns * steps_per_turn);
|
|
52
|
-
for (i = [0:steps]) {
|
|
53
|
-
angle = handedness * 360 * turns * i / steps;
|
|
54
|
-
p = [radius * cos(angle), radius * sin(angle), pitch * turns * i / steps];
|
|
55
|
-
translate(p) sphere(r = tube_radius);
|
|
56
|
-
if (i < steps) {
|
|
57
|
-
next_angle = handedness * 360 * turns * (i + 1) / steps;
|
|
58
|
-
dx = radius * cos(next_angle) - p[0];
|
|
59
|
-
dy = radius * sin(next_angle) - p[1];
|
|
60
|
-
dz = pitch * turns / steps;
|
|
61
|
-
segment_length = sqrt(dx * dx + dy * dy + dz * dz);
|
|
62
|
-
translate(p)
|
|
63
|
-
rotate([0, acos(dz / segment_length), atan2(dy, dx)])
|
|
64
|
-
cylinder(h = segment_length, r = tube_radius);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
PARAMETERS
|
|
71
|
-
- Make important top-level constants user-adjustable with OpenSCAD Customizer comments:
|
|
72
|
-
- Numbers with ranges: body_radius = 12; // [4:0.5:40]
|
|
73
|
-
- Counts: leg_count = 4; // [2:8]
|
|
74
|
-
- Booleans: show_base = true;
|
|
75
|
-
- Options: style = "round"; // [round, sharp, chunky]
|
|
76
|
-
- Prefer stable size/count/ratio/style controls; keep fragile dependent dimensions as local expressions.
|
|
77
|
-
|
|
78
|
-
SUPPORTED SUBSET
|
|
79
|
-
- Export is best-effort from a supported CSG subset: cube, sphere, cylinder, translate, rotate, color, union, difference, intersection, and goop.
|
|
80
|
-
- difference() cutters become subtractive primitives, so use clean cutters that fully pass through the target solid.
|
|
9
|
+
params supplies overrides to merge into the current values. Keep top-level parameter names stable.
|
|
10
|
+
Return complete source on every update and preserve unrelated geometry. Never create a replacement to repair a part.
|
|
11
|
+
Compile errors return status rejected without applying. Creation requires validated placement bounds.
|
|
12
|
+
An update may apply with validation unavailable; that is a diagnostic, not proof that it compiles.
|
|
13
|
+
An applied part remains in the scene even if thickness fails or is unavailable. Use the returned objectId for repairs.
|
|
14
|
+
When thickness fails, increase thin walls and fragile connections while preserving requested dimensions and openings.
|
|
15
|
+
At most four applied printability repairs are allowed per logical build/edit in this run. Respect the returned limit;
|
|
16
|
+
do not bypass it by recreating the part. Unavailable thickness is not a pass. Report unresolved issues honestly.
|
|
17
|
+
Build connected geometry and avoid features below 1.4 mm. OpenSCAD source dimensions use millimetres,
|
|
18
|
+
independently of the scene display unit. New parts are centered and grounded from compiled bounds.
|
|
19
|
+
OpenSCAD is Z-up; the scene-editing API is Y-up. For an unrotated part at its creation-time scale and an identity parent transform,
|
|
20
|
+
a source point [x,y,z] mm maps to scene {x:y, y:z, z:-x} times the scene.unitMultiplier inside the access callback, plus nodeGetPos(partId).
|
|
21
|
+
Account for the part and parent transforms when they are not identity; source coordinates are not scene coordinates.
|
|
22
|
+
After a major change, use the scene screenshot API and emitImage to inspect the applied result.
|
|
23
|
+
A committed effect can survive later failure. Inspect receipts and the existing part before retrying.
|
|
24
|
+
Do not print source in the final answer unless requested; describe the result and any unresolved diagnostics.
|
|
25
|
+
|
|
26
|
+
RUNTIME
|
|
27
|
+
- Produce a single OpenSCAD file.
|
|
28
|
+
- Do not use imports, includes, external libraries, text, hull, minkowski, polyhedron, or extrudes.
|
|
29
|
+
- Prefer cube, sphere, cylinder, translate, rotate, color, union, difference, and intersection.
|
|
30
|
+
- Do not use $fn, $fa, or $fs; tessellation controls are ignored.
|
|
31
|
+
- Build faceted geometry by combining supported primitives with CSG operations and transforms.
|
|
32
|
+
- Do not use scale(); size primitives directly instead.
|
|
33
|
+
- Use color("#rrggbb") around distinct visible parts.
|
|
34
|
+
- Keep the model centered near the origin and use millimeter-like units consistently.
|
|
35
|
+
- For organic blending, use goop(radius_mm) { ... }. The radius is in millimetres before parent scaling, matching scene-editing; do not multiply by project unitMultiplier. It is ordered: the first child seeds with blend 0, and each later child uses radius_mm.
|
|
36
|
+
- Put core primitives first. Avoid wrapping goop children in union() when they should blend individually.
|
|
37
|
+
|
|
38
|
+
SCREWS AND THREADS
|
|
39
|
+
- Copy helical_ridge below for rounded screw threads, necks, caps, and coils. It joins spheres with cylinders; never use stacked rings or disconnected spheres.
|
|
40
|
+
- Dimensions are mm: radius = ridge centerline radius; pitch = axial travel/turn; tube_radius = half ridge thickness; handedness = 1 (right) or -1 (left).
|
|
41
|
+
- For a hand control use thread_hand = 1; // [-1:Left, 1:Right] and pass it directly. Ternary expressions (?:) are unsupported.
|
|
42
|
+
- Embed the ridge in the shaft/neck (e.g. radius = shaft_radius). Hollow fittings: subtract the bore from body + thread. Internal threads: subtract the helix from the socket wall with mating clearance. Mating parts need matching pitch and handedness.
|
|
43
|
+
- Expose diameter, pitch, thread length, and thickness in Customizer; derive sampling. Keep 2 * tube_radius < pitch and allow tube_radius beyond both path endpoints for rounded ends. This is a rounded profile, not ISO/metric V-thread; never claim standards compliance.
|
|
44
|
+
- Build heads/grips separately using cylinders, tapered cylinders, and radial ribs/cutters, not thread samples.
|
|
45
|
+
|
|
46
|
+
module helical_ridge(radius, pitch, turns, tube_radius, handedness) {
|
|
47
|
+
if (radius > 0 && pitch > 0 && turns > 0 && tube_radius > 0) {
|
|
48
|
+
// Limit chord error to 0.03 mm or 3% of the ridge radius.
|
|
49
|
+
chord_error = min(0.03, tube_radius * 0.03);
|
|
50
|
+
steps_per_turn = max(48, ceil(180 / acos(1 - min(1, chord_error / radius))));
|
|
51
|
+
steps = ceil(turns * steps_per_turn);
|
|
52
|
+
for (i = [0:steps]) {
|
|
53
|
+
angle = handedness * 360 * turns * i / steps;
|
|
54
|
+
p = [radius * cos(angle), radius * sin(angle), pitch * turns * i / steps];
|
|
55
|
+
translate(p) sphere(r = tube_radius);
|
|
56
|
+
if (i < steps) {
|
|
57
|
+
next_angle = handedness * 360 * turns * (i + 1) / steps;
|
|
58
|
+
dx = radius * cos(next_angle) - p[0];
|
|
59
|
+
dy = radius * sin(next_angle) - p[1];
|
|
60
|
+
dz = pitch * turns / steps;
|
|
61
|
+
segment_length = sqrt(dx * dx + dy * dy + dz * dz);
|
|
62
|
+
translate(p)
|
|
63
|
+
rotate([0, acos(dz / segment_length), atan2(dy, dx)])
|
|
64
|
+
cylinder(h = segment_length, r = tube_radius);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
PARAMETERS
|
|
71
|
+
- Make important top-level constants user-adjustable with OpenSCAD Customizer comments:
|
|
72
|
+
- Numbers with ranges: body_radius = 12; // [4:0.5:40]
|
|
73
|
+
- Counts: leg_count = 4; // [2:8]
|
|
74
|
+
- Booleans: show_base = true;
|
|
75
|
+
- Options: style = "round"; // [round, sharp, chunky]
|
|
76
|
+
- Prefer stable size/count/ratio/style controls; keep fragile dependent dimensions as local expressions.
|
|
77
|
+
|
|
78
|
+
SUPPORTED SUBSET
|
|
79
|
+
- Export is best-effort from a supported CSG subset: cube, sphere, cylinder, translate, rotate, color, union, difference, intersection, and goop.
|
|
80
|
+
- difference() cutters become subtractive primitives, so use clean cutters that fully pass through the target solid.
|
|
81
81
|
- Unsupported OpenSCAD may validate but can warn or skip during export; prefer the supported subset above.`;
|
|
@@ -79,39 +79,39 @@ export function createOperationsCapability(host) {
|
|
|
79
79
|
name: "generation",
|
|
80
80
|
version: "7",
|
|
81
81
|
description: "Generate or edit images and meshes, inspect jobs, and wait for their outputs.",
|
|
82
|
-
instructions: `Read operations.catalog() for the currently available models and selected defaults.
|
|
82
|
+
instructions: `Read operations.catalog() for the currently available models and selected defaults.
|
|
83
83
|
Use generation for requested inline image/mesh results, not unsolicited previews of scene creations.
|
|
84
84
|
For generation explicitly requested through Flow/nodes or continued edits to that Flow workflow, use flow-graphs
|
|
85
85
|
unless the user asks for an inline result. If Flow is unavailable or closed, explain the prerequisite; do not substitute inline generation.
|
|
86
|
-
Use generate() for image/mesh generation, image editing, upscaling, or background removal. Model IDs must
|
|
87
|
-
come from the catalog and support the requested operation. An unavailable or restricted explicit choice
|
|
88
|
-
is an error; do not silently substitute another model. Omit model IDs to use the user's defaults.
|
|
89
|
-
For text-to-mesh, imageParams configures the image step and params configures the mesh step. For
|
|
90
|
-
image-to-mesh, an optional prompt requests an image-editing step first. Advanced params are JSON
|
|
91
|
-
values passed to the existing service; use documented options and do not invent provider settings.
|
|
92
|
-
Author the full text-to-mesh image prompt yourself, preserving the user's requested subject and details.
|
|
93
|
-
For a standalone object, describe a clear three-quarter view with a plain background and even lighting
|
|
94
|
-
unless the user requests otherwise. Do not rely on another model to expand or rewrite this prompt.
|
|
95
|
-
Inputs are image references returned by the available assets API or a previous completed operation.
|
|
96
|
-
Do not fabricate references, replace a missing input with another image, or pass arbitrary URLs.
|
|
97
|
-
Assign a short, distinct key to each intended job. Reuse that key when checking the same submission;
|
|
98
|
-
never choose a new key merely to retry a timeout or unknown outcome. A key cannot identify two
|
|
99
|
-
different requests. Host receipts and saved message IDs record submitted effects.
|
|
100
|
-
generate() waits for cost confirmation and then for completion, failure, or cancellation.
|
|
101
|
-
Use exactly one generation per execute_javascript call and print its result. Put follow-up work in
|
|
102
|
-
another call. Do not poll, start background work, use Promise.all, or report success before completion.
|
|
103
|
-
The host waits without consuming model steps. Stop ends agent execution; the host handles cancellation of its accepted jobs.
|
|
104
|
-
Refresh recovery reconnects the same job. It never resumes the interrupted JavaScript stack.
|
|
105
|
-
Read the recovered status and artifact references, then continue any requested remaining work in a new call; do not repeat generation.
|
|
106
|
-
generate() returns the terminal status and job.outputs artifact references directly, including after recovery.
|
|
107
|
-
Completed generations are shown automatically to the user; image bytes are intentionally omitted from your context. Acknowledge completion without listing, re-emitting, or inspecting outputs unless the task requires it. Use returned artifact references for follow-up work.
|
|
86
|
+
Use generate() for image/mesh generation, image editing, upscaling, or background removal. Model IDs must
|
|
87
|
+
come from the catalog and support the requested operation. An unavailable or restricted explicit choice
|
|
88
|
+
is an error; do not silently substitute another model. Omit model IDs to use the user's defaults.
|
|
89
|
+
For text-to-mesh, imageParams configures the image step and params configures the mesh step. For
|
|
90
|
+
image-to-mesh, an optional prompt requests an image-editing step first. Advanced params are JSON
|
|
91
|
+
values passed to the existing service; use documented options and do not invent provider settings.
|
|
92
|
+
Author the full text-to-mesh image prompt yourself, preserving the user's requested subject and details.
|
|
93
|
+
For a standalone object, describe a clear three-quarter view with a plain background and even lighting
|
|
94
|
+
unless the user requests otherwise. Do not rely on another model to expand or rewrite this prompt.
|
|
95
|
+
Inputs are image references returned by the available assets API or a previous completed operation.
|
|
96
|
+
Do not fabricate references, replace a missing input with another image, or pass arbitrary URLs.
|
|
97
|
+
Assign a short, distinct key to each intended job. Reuse that key when checking the same submission;
|
|
98
|
+
never choose a new key merely to retry a timeout or unknown outcome. A key cannot identify two
|
|
99
|
+
different requests. Host receipts and saved message IDs record submitted effects.
|
|
100
|
+
generate() waits for cost confirmation and then for completion, failure, or cancellation.
|
|
101
|
+
Use exactly one generation per execute_javascript call and print its result. Put follow-up work in
|
|
102
|
+
another call. Do not poll, start background work, use Promise.all, or report success before completion.
|
|
103
|
+
The host waits without consuming model steps. Stop ends agent execution; the host handles cancellation of its accepted jobs.
|
|
104
|
+
Refresh recovery reconnects the same job. It never resumes the interrupted JavaScript stack.
|
|
105
|
+
Read the recovered status and artifact references, then continue any requested remaining work in a new call; do not repeat generation.
|
|
106
|
+
generate() returns the terminal status and job.outputs artifact references directly, including after recovery.
|
|
107
|
+
Completed generations are shown automatically to the user; image bytes are intentionally omitted from your context. Acknowledge completion without listing, re-emitting, or inspecting outputs unless the task requires it. Use returned artifact references for follow-up work.
|
|
108
108
|
A brief, relevant follow-up suggestion is optional after completion. Offer only available actions; wait for a clear choice
|
|
109
109
|
and required confirmations before acting. Clarify ambiguous acceptance of multiple options. Reuse returned artifacts for the chosen follow-up.
|
|
110
|
-
Inspect images deliberately when needed for verification or reference comparisons; never claim visual verification without inspecting the image.
|
|
111
|
-
Omitted image bytes are expected; missing artifact references are not. If a completed job has no outputs, recover the references or report the missing result.
|
|
112
|
-
Reserve list() for older jobs or missing references. Follow nextFrom even when a page has no jobs.
|
|
113
|
-
Verify an uncertain submission's job status, never issue a replacement request.
|
|
114
|
-
Only returned outputs exist. Generating a mesh does not import it into the scene. Use the assets skill for requested imports.
|
|
110
|
+
Inspect images deliberately when needed for verification or reference comparisons; never claim visual verification without inspecting the image.
|
|
111
|
+
Omitted image bytes are expected; missing artifact references are not. If a completed job has no outputs, recover the references or report the missing result.
|
|
112
|
+
Reserve list() for older jobs or missing references. Follow nextFrom even when a page has no jobs.
|
|
113
|
+
Verify an uncertain submission's job status, never issue a replacement request.
|
|
114
|
+
Only returned outputs exist. Generating a mesh does not import it into the scene. Use the assets skill for requested imports.
|
|
115
115
|
Never resume stopped work or resubmit a job because cancellation or submission is uncertain.`,
|
|
116
116
|
declarations: WOMP_OPERATIONS_DECLARATIONS,
|
|
117
117
|
examples: [
|
|
@@ -41,73 +41,73 @@ export function createSceneCapability(host) {
|
|
|
41
41
|
version: "45",
|
|
42
42
|
description: "Inspect the open scene and edit its objects, materials, curves, and environment.",
|
|
43
43
|
instructions: `Use womp.scene.access(callback) for both inspection and edits. Inspect targets inside each callback using scene.nodes({ name, type, parentId, ids, offset, limit }) and detailed getters; filters are optional, name is a case-insensitive substring, and results default to 100 (maximum 1000). Page with offset as needed. Inspection reflects changes made in the callback. scene.unitMultiplier gives project units. Do not reuse an earlier inspection as current state.
|
|
44
|
-
Use womp.scene.health() to refresh whole-scene health or womp.scene.health(objectIds) to check specific objects (mapped to their owning Areas).
|
|
45
|
-
Health is requested only through scene.health(); access does not request it automatically. It is renderer feedback, not proof that the latest edit finished evaluating. Request it when needed to verify the result.
|
|
46
|
-
Unavailable, stale, or unverified feedback must not trigger blind regeneration or a claim that the model passed. Hosts without health services return unverified health with a reason.
|
|
47
|
-
For confirmed primitive or depth overflow, repair the same target while preserving design, dimensions, active parameter overrides, and unrelated objects. At most two geometry repairs are allowed per target in one logical run.
|
|
48
|
-
Empty Areas may be pending, intentionally empty, mesh-only, or failed. Overflow flags take precedence over possibly stale counts.
|
|
49
|
-
max_total_depth reports the engine's tier-dependent nesting allowance, not measured depth. Compiled Boolean depth includes generated grouping; organizational Groups do not add a level. Use flag_depth_overflow to detect evaluator rejection.
|
|
50
|
-
Call scene.access(callback) for one coherent change or read-only inspection. The callback receives a draft; all node/material/curve functions and enums
|
|
51
|
-
are properties of that draft. The draft expires when the callback ends. Await asynchronous methods.
|
|
52
|
-
Do not start unrelated operations from inside an access. Draft handles expire when its callback returns. An unchanged draft does not submit or save anything.
|
|
53
|
-
Preserve the existing scene unless asked to remove or replace content. Use semantic object names and reuse
|
|
54
|
-
known IDs when editing rather than creating duplicates. Distances follow the current project's units
|
|
44
|
+
Use womp.scene.health() to refresh whole-scene health or womp.scene.health(objectIds) to check specific objects (mapped to their owning Areas).
|
|
45
|
+
Health is requested only through scene.health(); access does not request it automatically. It is renderer feedback, not proof that the latest edit finished evaluating. Request it when needed to verify the result.
|
|
46
|
+
Unavailable, stale, or unverified feedback must not trigger blind regeneration or a claim that the model passed. Hosts without health services return unverified health with a reason.
|
|
47
|
+
For confirmed primitive or depth overflow, repair the same target while preserving design, dimensions, active parameter overrides, and unrelated objects. At most two geometry repairs are allowed per target in one logical run.
|
|
48
|
+
Empty Areas may be pending, intentionally empty, mesh-only, or failed. Overflow flags take precedence over possibly stale counts.
|
|
49
|
+
max_total_depth reports the engine's tier-dependent nesting allowance, not measured depth. Compiled Boolean depth includes generated grouping; organizational Groups do not add a level. Use flag_depth_overflow to detect evaluator rejection.
|
|
50
|
+
Call scene.access(callback) for one coherent change or read-only inspection. The callback receives a draft; all node/material/curve functions and enums
|
|
51
|
+
are properties of that draft. The draft expires when the callback ends. Await asynchronous methods.
|
|
52
|
+
Do not start unrelated operations from inside an access. Draft handles expire when its callback returns. An unchanged draft does not submit or save anything.
|
|
53
|
+
Preserve the existing scene unless asked to remove or replace content. Use semantic object names and reuse
|
|
54
|
+
known IDs when editing rather than creating duplicates. Distances follow the current project's units
|
|
55
55
|
(scene.unitMultiplier is 1 for millimetres, 0.1 for centimetres, approximately 0.0393701 for inches).
|
|
56
56
|
Convert a dimension in millimetres to project units by multiplying it by scene.unitMultiplier.
|
|
57
|
-
The SDK-backed draft clamps dimension writes to 0.01–1000 mm per component before converting to native units; this is an adapter limit, not a scene-wide size limit. Read back dimensions when physical size matters.
|
|
58
|
-
Area size is a dimensionless scale; Group size stays fixed at one. Lights must be created at root (parentId 0); their size has x/y dimensions.
|
|
59
|
-
Light power is linear emitted intensity before collimation, not a percentage or physical unit: doubling it doubles emission, not tone-mapped pixel brightness. Valid ranges are 0–${maxLightIntensity("rect")} for Rect/Sphere and 0–${maxLightIntensity("distant")} for Distant; these limits are not brightness targets. A light-type change preserves intensity and rejects values outside the new type's range; lower intensity first if needed. Rect size is width/height; Sphere uses x as diameter; Distant uses direction, not position or size.
|
|
60
|
-
Use nodeSetFacing(id, target - position) to aim light emission or the readable face of text/decals at a target in the same parent-local space. It keeps Y up (Z up for vertical directions); generic lookAt aligns a different axis and does not aim these faces.
|
|
61
|
-
For text, nodeSetTextSize(id, {fontSize, depth}) sets font em size and extrusion in project units, not a bounding box. Layout width and additional letter spacing also use project units; spacing clamps to ±25 mm. Line height is a multiplier clamped to 0.5–3. The origin anchors the first baseline; alignment uses the layout width. Empty text clears its geometry.
|
|
62
|
-
Decals require an existing loaded image and receiving geometry. Projection is a uniform cube: native scale.x (public size.z) controls all dimensions, not independent width/height/depth. Restriction to an Area requires that parent Area; root decals project globally. Missing image data can yield no projection even when no resource is pending.
|
|
63
|
-
nodeCreate(Curve, parentId) creates an empty curve with zero blend. curvePointAdd(curveId, point, index?) returns the new index; omit index to append or supply an integer from 0 through point count to insert before that position.
|
|
64
|
-
Point defaults: position/rotation/handles zero, profile size {x:1,y:1,z:1} in project units, the curve's material, fixed false, round 0. Pass {} for defaults.
|
|
65
|
-
Removing all points is supported. One point renders a single profile primitive, not a path.
|
|
66
|
-
Curves render sampled profiles, not a continuous sweep. For smooth curves, start with nodeSetDensity(curveId, 250) and nodeSetBlend(curveId, 3).
|
|
67
|
-
Density increases sampling and primitive cost; the 3 mm blend softens joins, not sample positions. Adjust blend to preserve thin features and the intended silhouette; these settings do not guarantee continuity.
|
|
68
|
-
nodeSetUnionResolution(unionId, resolution) sets a dimensionless detail level, clamped to 0.01–0.65: higher is finer and costs more voxels. Set the owning outermost Area, not a nested Union. Material emission ranges from 0 to 1.
|
|
69
|
-
nodeSetBlend and mirror goop take radii in millimetres before parent scaling, regardless of project units, and clamp to 0–500 mm. This does not apply to the FlowIR Boolean Blend port, which takes native units; geometry-nodes-reference gives its conversion.
|
|
70
|
-
V1/V2 curve transforms are read-only;
|
|
71
|
-
edit their points instead. Handles and closure are available only on V3 Bezier curves.
|
|
72
|
-
Typed rotations are right-handed intrinsic XYZ Euler degrees, relative to the parent (R = Rx Ry Rz), including curve points and mirrors.
|
|
73
|
-
Points and curve mirrors use the owning curve frame; primitive mirrors use the primitive's parent frame.
|
|
74
|
-
lookAt(origin, target) aligns local +Z; both points must be in the same parent-local space. For a segment along a different local axis,
|
|
75
|
-
use alignAxis(direction, 'x'|'y'|'z'); cylinders and cones extend along local Y. These return rotations, not world-space transforms.
|
|
76
|
-
Alignment chooses a deterministic roll using Y-up (Z-up fallback when parallel); coincident/non-finite directions are errors.
|
|
77
|
-
The SDK handles native XZY conversion; do not swap Euler components or convert again. Geometry Nodes source remains native XZY.
|
|
78
|
-
Colors use RGB values from 0 to 255. Use the exposed enums instead of guessing values.
|
|
79
|
-
For visible geometry color, create or clone a material, call materialSetColor, and assign it with nodeSetMaterialId only to
|
|
80
|
-
Primitive, Curve, Text, SVG, Mesh, Field, Decal or OpenSCAD nodes. Assigning a curve material recolors its existing points; use curvePointSetMaterialId for per-point overrides afterward.
|
|
81
|
-
Areas/Unions, Groups, Lights and Sockets do not accept direct materials. Color ordinary containers through their supported children.
|
|
82
|
-
Geometry Nodes materials belong in the graph: create or import the material here, then assign it inside the graph with the FlowIR SetMaterial node, passing the numeric ID this skill returns.
|
|
83
|
-
Never replace a parametric graph with ordinary primitives to color it. Ordinary Stain/CSG children do not modify graph output.
|
|
84
|
-
nodeSetColor writes the node color field (used by lights); it does not replace a geometry object's material color.
|
|
85
|
-
Do not recolor a shared material unless every object using it should change. Create and assign the material in the same edit as the scene geometry that uses it; a Geometry Nodes graph instead consumes a material ID created in an earlier edit.
|
|
86
|
-
Create primitives, curves, and text inside Areas/Unions. Respect tree order for subtraction and intersection.
|
|
87
|
-
Groups are organizational only; move and rotate their child Areas individually, not the Group.
|
|
88
|
-
An Area is an outermost Union with no Union ancestor: it has its own modeller, bounds, and volumetric resolution. Nested Unions share that Area's resolution, even through Groups.
|
|
89
|
-
Choose Area boundaries for evaluation needs, not individual editability: parts within an Area remain independently editable. Sibling Areas under a Group can overlap without blending together, while each blends internally and has independent resolution. Keep required shared smooth joins or Boolean evaluation within one Area; overlapping independent Areas are not a watertight Boolean union.
|
|
90
|
-
Prioritize requested visual fidelity over minimizing voxel use. If correctly placed thin features render fragmented or missing, increase their owning Area's resolution, up to 0.65 as needed, and compare the same camera; distinguish sampling loss from material/lighting contrast or authored gaps. A higher voxel count is acceptable when detail improves within engine limits. If resolution is insufficient or hits resource limits/downscaling, consider smaller independent Areas where shared blending or Booleans are unnecessary.
|
|
91
|
-
Sphere uses size.x as uniform diameter (y/z do not stretch it), including new or resized spherical curve points. Cylinder/Cone/Pyramid use x as base diameter/width and y as height;
|
|
92
|
-
Torus lies in local XZ (axis +Y), with x as outer diameter and y as tube thickness. For these four primitives, nodeSetSize accepts {x, y}; z follows x even when supplied. Cube uses all three dimensions. Node and curve-point round are dimensionless fractions clamped to [0, 1], not radii in project units; rounding does not set size. Cube rounding reaches half its shortest dimension at 1, so a shallow Cube retains broad flat faces rather than becoming an ellipsoid.
|
|
93
|
-
Build and verify coarse geometry and unfamiliar operations before replicating details. Check one representative result, then repeat it.
|
|
94
|
-
Construct both sides of a joint from shared attachment points and axes. Create each mounted part together with its contact or mounting geometry, derived from the supporting surface; preserve intended clearances and separate editability. If contact is uncertain, check the authored positions, dimensions, and axes in 3D: projected overlap is not a connection.
|
|
95
|
-
Fix unintended gaps, floating attachments, and fragmented geometry before decorative detail or presentation. Use inspection to identify a concrete defect and verify its correction, not merely to collect screenshots or healthy receipts.
|
|
96
|
-
Reference fidelity:
|
|
97
|
-
When recreating an image, treat its visible geometry and level of detail as the target—not merely its subject, colors, or list of parts. Preserve the user's chosen workflow and editability requirements.
|
|
98
|
-
Establish a comparison view matching the reference's angle, projection, and subject framing as closely as practical. Match silhouette, proportions, pose, and negative spaces first; then local contours, thickness, curvature, surface transitions, and defining details. Infer unseen geometry conservatively.
|
|
99
|
-
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.
|
|
100
|
-
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.
|
|
101
|
-
|
|
102
|
-
nodeClone is shallow (no children). await cloneSubtree(id, { parentId?, name?, index? }) copies the complete hierarchy with fresh IDs,
|
|
103
|
-
preserving local transforms, order and metadata, remapping internal references and sharing external materials/assets.
|
|
104
|
-
Cloning stages changes in the draft and commits them with the rest of the access.
|
|
105
|
-
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.
|
|
106
|
-
For organic joins, overlap primitives and tune blend on the joining children while preserving intended gaps.
|
|
107
|
-
Check font, HDR, and material catalogs before selecting names. A host can explicitly report a catalog as
|
|
108
|
-
unavailable. Selecting an HDR resets its intensity; apply a custom intensity after selecting it.
|
|
109
|
-
For library materials, use listSuperMaterials(), then await materialImport(name) inside scene.access and assign the returned numeric ID the way that object requires: nodeSetMaterialId or curvePointSetMaterialId for scene nodes, the FlowIR SetMaterial node for a Geometry Nodes graph. A failed import rolls back the draft.
|
|
110
|
-
Filter large read results with JavaScript and print only useful details.
|
|
57
|
+
The SDK-backed draft clamps dimension writes to 0.01–1000 mm per component before converting to native units; this is an adapter limit, not a scene-wide size limit. Read back dimensions when physical size matters.
|
|
58
|
+
Area size is a dimensionless scale; Group size stays fixed at one. Lights must be created at root (parentId 0); their size has x/y dimensions.
|
|
59
|
+
Light power is linear emitted intensity before collimation, not a percentage or physical unit: doubling it doubles emission, not tone-mapped pixel brightness. Valid ranges are 0–${maxLightIntensity("rect")} for Rect/Sphere and 0–${maxLightIntensity("distant")} for Distant; these limits are not brightness targets. A light-type change preserves intensity and rejects values outside the new type's range; lower intensity first if needed. Rect size is width/height; Sphere uses x as diameter; Distant uses direction, not position or size.
|
|
60
|
+
Use nodeSetFacing(id, target - position) to aim light emission or the readable face of text/decals at a target in the same parent-local space. It keeps Y up (Z up for vertical directions); generic lookAt aligns a different axis and does not aim these faces.
|
|
61
|
+
For text, nodeSetTextSize(id, {fontSize, depth}) sets font em size and extrusion in project units, not a bounding box. Layout width and additional letter spacing also use project units; spacing clamps to ±25 mm. Line height is a multiplier clamped to 0.5–3. The origin anchors the first baseline; alignment uses the layout width. Empty text clears its geometry.
|
|
62
|
+
Decals require an existing loaded image and receiving geometry. Projection is a uniform cube: native scale.x (public size.z) controls all dimensions, not independent width/height/depth. Restriction to an Area requires that parent Area; root decals project globally. Missing image data can yield no projection even when no resource is pending.
|
|
63
|
+
nodeCreate(Curve, parentId) creates an empty curve with zero blend. curvePointAdd(curveId, point, index?) returns the new index; omit index to append or supply an integer from 0 through point count to insert before that position.
|
|
64
|
+
Point defaults: position/rotation/handles zero, profile size {x:1,y:1,z:1} in project units, the curve's material, fixed false, round 0. Pass {} for defaults.
|
|
65
|
+
Removing all points is supported. One point renders a single profile primitive, not a path.
|
|
66
|
+
Curves render sampled profiles, not a continuous sweep. For smooth curves, start with nodeSetDensity(curveId, 250) and nodeSetBlend(curveId, 3).
|
|
67
|
+
Density increases sampling and primitive cost; the 3 mm blend softens joins, not sample positions. Adjust blend to preserve thin features and the intended silhouette; these settings do not guarantee continuity.
|
|
68
|
+
nodeSetUnionResolution(unionId, resolution) sets a dimensionless detail level, clamped to 0.01–0.65: higher is finer and costs more voxels. Set the owning outermost Area, not a nested Union. Material emission ranges from 0 to 1.
|
|
69
|
+
nodeSetBlend and mirror goop take radii in millimetres before parent scaling, regardless of project units, and clamp to 0–500 mm. This does not apply to the FlowIR Boolean Blend port, which takes native units; geometry-nodes-reference gives its conversion.
|
|
70
|
+
V1/V2 curve transforms are read-only;
|
|
71
|
+
edit their points instead. Handles and closure are available only on V3 Bezier curves.
|
|
72
|
+
Typed rotations are right-handed intrinsic XYZ Euler degrees, relative to the parent (R = Rx Ry Rz), including curve points and mirrors.
|
|
73
|
+
Points and curve mirrors use the owning curve frame; primitive mirrors use the primitive's parent frame.
|
|
74
|
+
lookAt(origin, target) aligns local +Z; both points must be in the same parent-local space. For a segment along a different local axis,
|
|
75
|
+
use alignAxis(direction, 'x'|'y'|'z'); cylinders and cones extend along local Y. These return rotations, not world-space transforms.
|
|
76
|
+
Alignment chooses a deterministic roll using Y-up (Z-up fallback when parallel); coincident/non-finite directions are errors.
|
|
77
|
+
The SDK handles native XZY conversion; do not swap Euler components or convert again. Geometry Nodes source remains native XZY.
|
|
78
|
+
Colors use RGB values from 0 to 255. Use the exposed enums instead of guessing values.
|
|
79
|
+
For visible geometry color, create or clone a material, call materialSetColor, and assign it with nodeSetMaterialId only to
|
|
80
|
+
Primitive, Curve, Text, SVG, Mesh, Field, Decal or OpenSCAD nodes. Assigning a curve material recolors its existing points; use curvePointSetMaterialId for per-point overrides afterward.
|
|
81
|
+
Areas/Unions, Groups, Lights and Sockets do not accept direct materials. Color ordinary containers through their supported children.
|
|
82
|
+
Geometry Nodes materials belong in the graph: create or import the material here, then assign it inside the graph with the FlowIR SetMaterial node, passing the numeric ID this skill returns.
|
|
83
|
+
Never replace a parametric graph with ordinary primitives to color it. Ordinary Stain/CSG children do not modify graph output.
|
|
84
|
+
nodeSetColor writes the node color field (used by lights); it does not replace a geometry object's material color.
|
|
85
|
+
Do not recolor a shared material unless every object using it should change. Create and assign the material in the same edit as the scene geometry that uses it; a Geometry Nodes graph instead consumes a material ID created in an earlier edit.
|
|
86
|
+
Create primitives, curves, and text inside Areas/Unions. Respect tree order for subtraction and intersection.
|
|
87
|
+
Groups are organizational only; move and rotate their child Areas individually, not the Group.
|
|
88
|
+
An Area is an outermost Union with no Union ancestor: it has its own modeller, bounds, and volumetric resolution. Nested Unions share that Area's resolution, even through Groups.
|
|
89
|
+
Choose Area boundaries for evaluation needs, not individual editability: parts within an Area remain independently editable. Sibling Areas under a Group can overlap without blending together, while each blends internally and has independent resolution. Keep required shared smooth joins or Boolean evaluation within one Area; overlapping independent Areas are not a watertight Boolean union.
|
|
90
|
+
Prioritize requested visual fidelity over minimizing voxel use. If correctly placed thin features render fragmented or missing, increase their owning Area's resolution, up to 0.65 as needed, and compare the same camera; distinguish sampling loss from material/lighting contrast or authored gaps. A higher voxel count is acceptable when detail improves within engine limits. If resolution is insufficient or hits resource limits/downscaling, consider smaller independent Areas where shared blending or Booleans are unnecessary.
|
|
91
|
+
Sphere uses size.x as uniform diameter (y/z do not stretch it), including new or resized spherical curve points. Cylinder/Cone/Pyramid use x as base diameter/width and y as height;
|
|
92
|
+
Torus lies in local XZ (axis +Y), with x as outer diameter and y as tube thickness. For these four primitives, nodeSetSize accepts {x, y}; z follows x even when supplied. Cube uses all three dimensions. Node and curve-point round are dimensionless fractions clamped to [0, 1], not radii in project units; rounding does not set size. Cube rounding reaches half its shortest dimension at 1, so a shallow Cube retains broad flat faces rather than becoming an ellipsoid.
|
|
93
|
+
Build and verify coarse geometry and unfamiliar operations before replicating details. Check one representative result, then repeat it.
|
|
94
|
+
Construct both sides of a joint from shared attachment points and axes. Create each mounted part together with its contact or mounting geometry, derived from the supporting surface; preserve intended clearances and separate editability. If contact is uncertain, check the authored positions, dimensions, and axes in 3D: projected overlap is not a connection.
|
|
95
|
+
Fix unintended gaps, floating attachments, and fragmented geometry before decorative detail or presentation. Use inspection to identify a concrete defect and verify its correction, not merely to collect screenshots or healthy receipts.
|
|
96
|
+
Reference fidelity:
|
|
97
|
+
When recreating an image, treat its visible geometry and level of detail as the target—not merely its subject, colors, or list of parts. Preserve the user's chosen workflow and editability requirements.
|
|
98
|
+
Establish a comparison view matching the reference's angle, projection, and subject framing as closely as practical. Match silhouette, proportions, pose, and negative spaces first; then local contours, thickness, curvature, surface transitions, and defining details. Infer unseen geometry conservatively.
|
|
99
|
+
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.
|
|
100
|
+
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.
|
|
101
|
+
|
|
102
|
+
nodeClone is shallow (no children). await cloneSubtree(id, { parentId?, name?, index? }) copies the complete hierarchy with fresh IDs,
|
|
103
|
+
preserving local transforms, order and metadata, remapping internal references and sharing external materials/assets.
|
|
104
|
+
Cloning stages changes in the draft and commits them with the rest of the access.
|
|
105
|
+
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.
|
|
106
|
+
For organic joins, overlap primitives and tune blend on the joining children while preserving intended gaps.
|
|
107
|
+
Check font, HDR, and material catalogs before selecting names. A host can explicitly report a catalog as
|
|
108
|
+
unavailable. Selecting an HDR resets its intensity; apply a custom intensity after selecting it.
|
|
109
|
+
For library materials, use listSuperMaterials(), then await materialImport(name) inside scene.access and assign the returned numeric ID the way that object requires: nodeSetMaterialId or curvePointSetMaterialId for scene nodes, the FlowIR SetMaterial node for a Geometry Nodes graph. A failed import rolls back the draft.
|
|
110
|
+
Filter large read results with JavaScript and print only useful details.
|
|
111
111
|
After a major edit, capture a screenshot outside the transaction and emitImage its reference.
|
|
112
112
|
screenshot({ camera: { position: {x,y,z}, target: {x,y,z}, projection: 'perspective', horizontalFovDegrees: 60 } })
|
|
113
113
|
sets a world-space camera in the same Womp coordinates and project units as scene positions (Y-up).
|
|
@@ -117,10 +117,10 @@ Omitted projection/lens settings come from the active camera. Pass the camera ag
|
|
|
117
117
|
For object-focused screenshots, identify the requested object and frame it using world-space bounds. Convert local bounds using the object’s and applicable ancestor transforms, including translation, rotation, and scale; do not transform world-space bounds again. Reuse established framing when appropriate and avoid clipping the subject.
|
|
118
118
|
Omitting camera captures the active viewport without auto-fit. Use it when the user asks about the current viewport or clearly refers to what is visible on screen, not on the assumption that it shows the requested object.
|
|
119
119
|
Respect the host's camera-lock restrictions. Verify silhouette,
|
|
120
|
-
connections, openings, proportions, and materials before claiming completion. Use the owning top-level Area for scene-space bounds;
|
|
121
|
-
OpenSCAD part bounds are local to the part; individual primitive and curve bounds are unsupported. Renderer bounds and resize calls
|
|
122
|
-
must finish before subsequent writes. Inside scene.access, complete renderer-backed bounds reads before the first
|
|
123
|
-
draft mutation; the SDK rejects them once the draft is dirty. Inspect committed results when renderer state has not caught up.
|
|
120
|
+
connections, openings, proportions, and materials before claiming completion. Use the owning top-level Area for scene-space bounds;
|
|
121
|
+
OpenSCAD part bounds are local to the part; individual primitive and curve bounds are unsupported. Renderer bounds and resize calls
|
|
122
|
+
must finish before subsequent writes. Inside scene.access, complete renderer-backed bounds reads before the first
|
|
123
|
+
draft mutation; the SDK rejects them once the draft is dirty. Inspect committed results when renderer state has not caught up.
|
|
124
124
|
A failed script can retain earlier committed effects. Use receipts and inspect unknown outcomes before retrying.`,
|
|
125
125
|
declarations: WOMP_SCENE_DECLARATIONS,
|
|
126
126
|
examples: [
|