Vega3D Vibe Kit — Protocol Commands
vegaExecute(cmd, params) is the unified API for controlling the Vega3D 3D viewer
from any AI (GPT, Claude, Qwen, DeepSeek, GLM, etc.) or external application.
All commands return a structured { ok, data?, error? } response.
69 Commands
Any AI · Any Origin
postMessage Bridge
Usage API
Call vegaExecute() directly in the viewer page, or use the postMessage bridge from a parent frame.
// Direct call (inside viewer page or iframe)
const result = await vegaExecute('camera.set_preset', { preset: 'iso' });
// → { ok: true, data: { preset: 'iso' } }
// Error response
// → { ok: false, error: { code: 'INVALID_PARAM', message: '...' } }
Quick Reference 69 Commands
| Command | Group | Description |
|---|---|---|
| camera.set_preset | camera | Set view to front/back/top/bottom/left/right/iso |
| camera.fit_view | camera | Fit all loaded models to view |
| camera.get | camera | Get current camera position, target, fov |
| camera.set | camera | Set camera position / target / up vector |
| camera.orbit | camera | Orbit by delta azimuth / elevation (degrees) |
| camera.zoom | camera | Zoom in/out by scale factor (>1 in, <1 out) |
| camera.save_bookmark | camera | Save current camera state as named bookmark |
| camera.load_bookmark | camera | Restore camera to a saved bookmark |
| camera.list_bookmarks | camera | List all saved camera bookmarks |
| model.list | model | List all loaded models |
| model.get_tree | model | Get scene tree structure |
| model.get_node_info | model | Get bounding box / center of a part |
| model.move | model | Move model by delta or to absolute position (mm) |
| model.rotate | model | Rotate model by Euler angles (degrees) |
| model.reset_transform | model | Reset model position/rotation to original loaded state |
| selection.by_id | selection | Select parts by name / ID |
| selection.clear | selection | Clear current selection |
| visibility.set | visibility | Show or hide parts |
| visibility.isolate | visibility | Show only specified parts |
| visibility.show_all | visibility | Show all hidden parts |
| material.apply | material | Apply color / opacity / metalness / roughness |
| section.add_plane | section | Add a clipping plane |
| section.remove | section | Remove all clipping planes |
| section.add_box | section | Apply box clipping — show only geometry inside box |
| section.get_planes | section | Get all active clipping planes and box clip state |
| scene.set_render_mode | scene | Switch render mode (shaded / wireframe / rendered …) |
| scene.explode | scene | Explode view (factor 0–2) |
| scene.set_background | scene | Set background color |
| scene.get_stats | scene | Get render statistics |
| scene.get_tree_summary | scene | Summarized tree for AI context |
| scene.fit_selected | scene | Fit camera to selected or specified part |
| scene.get_visible_parts | scene | Get list of all currently visible part names |
| scene.snapshot | scene | Save full scene state (camera, visibility, clipping) as named snapshot |
| scene.restore_snapshot | scene | Restore a previously saved scene snapshot |
| scene.list_snapshots | scene | List all saved scene snapshots |
| measure.distance | measure | Measure distance between two 3D points |
| measure.angle | measure | Measure angle at vertex |
| measure.clear | measure | Clear all measurements |
| measure.list | measure | List all placed measurements with values |
| measure.delete | measure | Delete a specific measurement by ID |
| export.screenshot | export | Capture viewport as PNG / JPG / WebP |
| export.gltf | export | Export scene as GLB file |
| export.batch_screenshot | export | Screenshots from multiple camera presets |
| part.move | part | [Heavy] Move part(s) by delta or to absolute position (mm) |
| part.rotate | part | [Heavy] Rotate part(s) by Euler angles (degrees) |
| part.reset_transform | part | [Heavy] Reset part(s) position/rotation to original state |
| part.select_by_name | part | Select parts by glob pattern |
| part.get_info | part | Get part center / bbox from FaceRange data |
| part.set_color | part | [Heavy] Override color of specific part(s) |
| part.reset_color | part | [Heavy] Restore original color of overridden part(s) |
| part.set_opacity | part | [Heavy] Set opacity of specific part(s) (0–1) |
| part.find_by_bbox | part | [Heavy] Find parts intersecting or inside a 3D box |
| part.get_neighbors | part | [Heavy] Find nearby parts within distance (mm) |
| annotation.add | annotation | Add 3D note (anchor + label_pos + text) |
| annotation.list | annotation | List all annotations with positions |
| annotation.delete | annotation | Delete annotation by ID |
| annotation.clear | annotation | Delete all annotations |
| markup.add_arrow | markup | Add arrow annotation from point to point |
| markup.add_text | markup | Add floating text label at a 3D position |
| markup.list | markup | List all markup annotations |
| markup.delete | markup | Delete markup by ID |
| markup.clear | markup | Delete all markup annotations |
| animation.list | animation | List all animation clips in loaded model |
| animation.play | animation | Play animation clip by name or index |
| animation.stop | animation | Stop all playing animations |
| clash.check | clash | [Heavy] BBox intersection check between parts |
| property.get | property | [Heavy] Get metadata attributes and geometry info for a part |
| property.search | property | [Heavy] Search parts by attribute key-value |
| events.subscribe | events | CustomEvent subscription info |
camera 9 commands
camera.set_preset
Set camera to a named view direction
▼
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| preset | string | required | 'front' | 'back' | 'top' | 'bottom' | 'left' | 'right' | 'iso' |
await vegaExecute('camera.set_preset', { preset: 'front' });
// → { ok: true, data: { preset: 'front' } }
camera.fit_view
Fit all loaded models to the viewport (ISO view)
▼
No parameters required.
await vegaExecute('camera.fit_view');
// → { ok: true }
camera.get
Get current camera state
▶
Returns
{
position: [x, y, z],
target: [x, y, z],
up: [x, y, z],
fov: 75
}
camera.set
Set camera position, target, and/or up vector
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| position | number[3] | optional | Camera position [x, y, z] |
| target | number[3] | optional | Look-at target [x, y, z] |
| up | number[3] | optional | Up vector, default [0,0,1] |
await vegaExecute('camera.set', {
position: [1000, -2000, 800],
target: [0, 0, 0]
});
camera.zoom
Zoom in or out by a scale factor (perspective + orthographic)
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| factor | number | required | Scale factor. >1 = zoom in, <1 = zoom out. e.g. 1.5 = +50%, 0.5 = -50% |
await vegaExecute('camera.zoom', { factor: 1.5 }); // zoom in
await vegaExecute('camera.zoom', { factor: 0.5 }); // zoom out
// → { ok: true, data: { distance: 1200.5 } }
camera.save_bookmark
Save current camera state as a named bookmark
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | required | Bookmark name (unique key) |
await vegaExecute('camera.save_bookmark', { name: 'overview' });
// → { ok: true, data: { name: 'overview' } }
camera.load_bookmark
Restore camera to a previously saved bookmark
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | required | Bookmark name to restore |
await vegaExecute('camera.load_bookmark', { name: 'overview' });
// → { ok: true, data: { name: 'overview' } }
camera.list_bookmarks
List all saved camera bookmarks
▶
const r = await vegaExecute('camera.list_bookmarks');
// → { ok: true, data: { bookmarks: ['overview', 'engine_detail'] } }
camera.orbit
Orbit camera by delta azimuth / elevation (degrees)
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| delta_azimuth | number | optional | Horizontal rotation in degrees |
| delta_elevation | number | optional | Vertical rotation in degrees |
await vegaExecute('camera.orbit', { delta_azimuth: 45, delta_elevation: -15 });
model 6 commands
model.list
List all currently loaded models
▶
const r = await vegaExecute('model.list');
// → { ok: true, data: { models: [{id, name, file_name, file_size_mb}], count: 2 } }
model.get_tree
Get the scene component tree (depth-limited for AI context efficiency)
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| depth | number | optional | Max tree depth (default 3) |
| max_nodes | number | optional | Max nodes returned (default 500) |
| filter | string | optional | Glob-style name filter e.g. 'FR*' |
await vegaExecute('model.get_tree', { depth: 2, max_nodes: 200 });
model.get_node_info
Get bounding box and center of a specific part
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | required | Part name (or use part_id) |
await vegaExecute('model.get_node_info', { name: 'FR14' });
// → { ok: true, data: { name: 'FR14', center: [x,y,z], bbox: { min:[], max:[] } } }
model.move
Move a loaded model by delta offset or to an absolute position (mm)
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| model_id | string | optional | Model ID from model.list. Omit to move all models. |
| delta | number[3] | optional | Relative offset [dx, dy, dz] in mm. Use this OR position. |
| position | number[3] | optional | Absolute target position [x, y, z] in mm. Use this OR delta. |
// Move by relative offset
await vegaExecute('model.move', { delta: [100, 0, 0] });
// Move specific model to absolute position
await vegaExecute('model.move', { model_id: 'm0', position: [0, 500, 0] });
// → { ok: true, data: { position: [x, y, z] } }
model.rotate
Rotate a loaded model by Euler angles (degrees) around a pivot point
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| model_id | string | optional | Model ID from model.list. Omit to rotate all models. |
| euler | number[3] | required | [rx, ry, rz] rotation in degrees (XYZ order) |
| pivot | number[3] | optional | Pivot point in mm. Defaults to model center if omitted. |
// Rotate all models 45° around Z axis
await vegaExecute('model.rotate', { euler: [0, 0, 45] });
// Rotate around custom pivot
await vegaExecute('model.rotate', { model_id: 'm0', euler: [0, 90, 0], pivot: [0, 0, 0] });
// → { ok: true, data: { euler: [rx, ry, rz] } }
model.reset_transform
Reset model position and rotation to original loaded state
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| model_id | string | optional | Model ID from model.list. Omit to reset all models. |
await vegaExecute('model.reset_transform');
// → { ok: true, data: { reset: 1 } }
selection 2 commands
selection.by_id
Select one or more parts by name / ID
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| part_ids | string[] | required | Array of part names (or single part_id) |
await vegaExecute('selection.by_id', { part_ids: ['FR14', 'FR15'] });
selection.clear
Clear all current selections / highlights
▶
await vegaExecute('selection.clear');
visibility 3 commands
visibility.set
Show or hide specified parts
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| part_ids | string[] | required | Part names array |
| visible | boolean | optional | true = show, false = hide (default true) |
await vegaExecute('visibility.set', { part_ids: ['Hull'], visible: false });
visibility.isolate
Show only specified parts, hide everything else
▶
| Name | Type | Required | Description |
|---|---|---|---|
| part_ids | string[] | required | Parts to keep visible |
await vegaExecute('visibility.isolate', { part_ids: ['Engine', 'Shaft'] });
visibility.show_all
Restore visibility of all hidden parts
▶
await vegaExecute('visibility.show_all');
material 1 command
material.apply
Apply color, opacity, metalness, roughness to parts (or entire scene)
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| part_ids | string[] | optional | If omitted, applies to entire scene |
| material.color | string | optional | CSS color e.g. '#ff0000', 'red' |
| material.opacity | number | optional | 0.0 (transparent) – 1.0 (opaque) |
| material.metalness | number | optional | 0.0 – 1.0 |
| material.roughness | number | optional | 0.0 – 1.0 |
// Make Hull semi-transparent red
await vegaExecute('material.apply', {
part_ids: ['Hull'],
material: { color: '#ff4444', opacity: 0.4 }
});
// Apply metallic look to entire scene
await vegaExecute('material.apply', {
material: { metalness: 0.8, roughness: 0.2 }
});
section 4 commands
section.add_plane
Add a clipping plane to slice the model
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| origin | number[3] | optional | Point on the plane [x, y, z] (default [0,0,0]) |
| normal | number[3] | optional | Plane normal vector (default [0,1,0]) |
// Horizontal slice at Z = 500mm
await vegaExecute('section.add_plane', {
origin: [0, 0, 500],
normal: [0, 0, 1]
});
section.remove
Remove all clipping planes
▶
await vegaExecute('section.remove');
section.add_box
[Heavy] Apply a box clipping region (6-plane section box)
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| part_id | string | optional | Fit box to this part's bounding box |
| min | number[3] | optional | Box min corner [x,y,z] in mm (overrides part fit) |
| max | number[3] | optional | Box max corner [x,y,z] in mm (overrides part fit) |
// Fit section box to a part
await vegaExecute('section.add_box', { part_id: 'FR14' });
// Custom box region
await vegaExecute('section.add_box', {
min: [-5000, -2000, 0], max: [5000, 2000, 3000]
});
// → { ok: true, data: { min: [...], max: [...] } }
section.get_planes
Get all currently active clipping plane definitions
▶
const r = await vegaExecute('section.get_planes');
// → { ok: true, data: {
// planes: [{ origin: [x,y,z], normal: [nx,ny,nz] }, ...],
// count: 2
// } }
scene 10 commands
scene.set_render_mode
Switch viewport render mode
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| mode | string | required | shaded / shaded_edges / rendered / flat / hidden / wireframe |
await vegaExecute('scene.set_render_mode', { mode: 'shaded_edges' });
await vegaExecute('scene.set_render_mode', { mode: 'wireframe' });
// → { ok: true, data: { mode: 'shaded_edges' } }
scene.explode
Explode view — spread components apart by factor
▶
| Name | Type | Required | Description |
|---|---|---|---|
| factor | number | required | 0 = no explode, 1 = normal, 2 = max. Range: 0–2 |
await vegaExecute('scene.explode', { factor: 1.2 });
// Reset:
await vegaExecute('scene.explode', { factor: 0 });
scene.set_background
Set the viewport background color
▶
| Name | Type | Required | Description |
|---|---|---|---|
| color | string | optional | CSS hex color (default '#1a1a1a') |
await vegaExecute('scene.set_background', { color: '#ffffff' });
scene.get_stats
Get current render statistics
▶
const r = await vegaExecute('scene.get_stats');
// → { triangles, draw_calls, geometries, textures, loaded_models }
scene.get_tree_summary
Summarized tree optimized for AI context (token-efficient)
▶
| Name | Type | Required | Description |
|---|---|---|---|
| depth | number | optional | Default 2 |
| max_nodes | number | optional | Default 200 |
| filter | string | optional | Glob pattern |
await vegaExecute('scene.get_tree_summary', { depth: 2, filter: 'FR*' });
scene.fit_selected
Fit camera to the currently selected/highlighted part
▶
await vegaExecute('scene.fit_selected');
// → { ok: true } — fits to selectedName or current highlight
scene.get_visible_parts
List all currently visible part names
▶
const r = await vegaExecute('scene.get_visible_parts');
// → { ok: true, data: { parts: ['FR14', 'FR15', ...], count: 42 } }
scene.snapshot
Save full scene state (visibility, camera, clipping, render mode) as a named snapshot
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | required | Snapshot key |
await vegaExecute('scene.snapshot', { name: 'review_A' });
// → { ok: true, data: { name: 'review_A', saved: true } }
scene.restore_snapshot
Restore a previously saved scene snapshot
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | required | Snapshot key to restore |
await vegaExecute('scene.restore_snapshot', { name: 'review_A' });
// → { ok: true, data: { name: 'review_A', restored: true } }
scene.list_snapshots
List all saved snapshot names
▶
const r = await vegaExecute('scene.list_snapshots');
// → { ok: true, data: { snapshots: ['review_A', 'review_B'], count: 2 } }
measure 5 commands
measure.distance
Measure straight-line distance between two 3D points
▶
| Name | Type | Required | Description |
|---|---|---|---|
| point_a | number[3] | required | [x, y, z] in mm |
| point_b | number[3] | required | [x, y, z] in mm |
const r = await vegaExecute('measure.distance', {
point_a: [0, 0, 0], point_b: [1000, 0, 0]
});
// → { value_mm: 1000.0, id: 'measure_...' }
measure.angle
Measure angle at a vertex point (degrees)
▶
| Name | Type | Required | Description |
|---|---|---|---|
| point_a | number[3] | required | First point |
| point_b | number[3] | required | Vertex (angle measured here) |
| point_c | number[3] | required | Third point |
const r = await vegaExecute('measure.angle', {
point_a: [1,0,0], point_b: [0,0,0], point_c: [0,1,0]
});
// → { value_deg: 90.0, id: 'measure_...' }
measure.clear
Clear all measurement annotations
▶
await vegaExecute('measure.clear');
measure.list
List all currently placed measurement annotations with IDs and values
▶
const r = await vegaExecute('measure.list');
// → { ok: true, data: {
// measures: [{ id: 0, span: 1234.5, label: '1234.5 mm' }, ...],
// count: 3
// } }
measure.delete
Delete a specific measurement by ID
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | number | required | Measurement ID from measure.list |
await vegaExecute('measure.delete', { id: 0 });
// → { ok: true, data: { deleted: true } }
export 3 commands
export.screenshot
Capture the current viewport as an image
▶
| Name | Type | Required | Description |
|---|---|---|---|
| format | string | optional | 'png' | 'jpg' | 'webp' (default 'png') |
| quality | number | optional | 0.0–1.0 (default 0.92) |
| download | boolean | optional | Auto-download file (default true) |
const r = await vegaExecute('export.screenshot', {
format: 'png', download: false
});
// → { data_url: 'data:image/png;base64,...', format: 'png' }
export.gltf
Export current scene as GLB file
▶
| Name | Type | Required | Description |
|---|---|---|---|
| file_name | string | optional | Output filename (default auto-generated) |
await vegaExecute('export.gltf', { file_name: 'my_model.glb' });
export.batch_screenshot
Capture screenshots from multiple camera presets at once
▶
| Name | Type | Required | Description |
|---|---|---|---|
| presets | string[] | optional | Default: all 7 directions |
| download | boolean | optional | Auto-download each file (default true) |
const r = await vegaExecute('export.batch_screenshot', {
presets: ['front', 'top', 'iso'], download: false
});
// → { screenshots: [{preset, data_url}, ...], count: 3 }
part 11 commands
part.move
[Heavy] Move specific part(s) by delta offset or to an absolute position (mm)
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| part_ids | string[] | optional | Part names to move (array) |
| part_id | string | optional | Single part name (alternative to part_ids) |
| delta | number[3] | optional | Relative offset [dx, dy, dz] in mm. Use this OR position. |
| position | number[3] | optional | Absolute target center position in mm. Use this OR delta. |
// Move single part by delta
await vegaExecute('part.move', { part_id: 'FR14', delta: [0, 0, 50] });
// Move multiple parts to absolute position
await vegaExecute('part.move', { part_ids: ['FR14', 'FR15'], position: [100, 200, 0] });
// → { ok: true, data: { moved: 2 } }
part.rotate
[Heavy] Rotate specific part(s) by Euler angles (degrees) around a pivot point
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| part_ids | string[] | optional | Part names to rotate (array) |
| part_id | string | optional | Single part name (alternative to part_ids) |
| euler | number[3] | required | [rx, ry, rz] rotation in degrees (XYZ order) |
| pivot | number[3] | optional | Pivot point in mm. Defaults to part center if omitted. |
// Rotate single part 90° around Y axis
await vegaExecute('part.rotate', { part_id: 'FR14', euler: [0, 90, 0] });
// Rotate multiple parts around custom pivot
await vegaExecute('part.rotate', { part_ids: ['FR14', 'FR15'], euler: [0, 45, 0], pivot: [0, 0, 0] });
// → { ok: true, data: { rotated: 2 } }
part.reset_transform
Reset part(s) position/rotation back to original loaded state
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| part_ids | string[] | optional | Part names to reset (omit to reset all) |
| part_id | string | optional | Single part name |
await vegaExecute('part.reset_transform', { part_id: 'FR14' });
// → { ok: true, data: { reset: 1 } }
part.set_color
Override the color of specific part(s)
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| part_ids | string[] | optional | Part names (array) |
| part_id | string | optional | Single part name |
| color | string | required | CSS hex color e.g. '#ff0000' |
await vegaExecute('part.set_color', { part_id: 'FR14', color: '#ff4400' });
// → { ok: true, data: { colored: 1 } }
part.reset_color
Restore original material color for specific part(s)
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| part_ids | string[] | optional | Part names (omit to reset all) |
| part_id | string | optional | Single part name |
await vegaExecute('part.reset_color', { part_id: 'FR14' });
// → { ok: true, data: { reset: 1 } }
part.set_opacity
Set transparency of specific part(s)
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| part_ids | string[] | optional | Part names (array) |
| part_id | string | optional | Single part name |
| opacity | number | required | 0.0 (transparent) – 1.0 (opaque) |
// Make FR14 semi-transparent
await vegaExecute('part.set_opacity', { part_id: 'FR14', opacity: 0.3 });
// Restore full opacity
await vegaExecute('part.set_opacity', { part_id: 'FR14', opacity: 1.0 });
// → { ok: true, data: { applied: 1 } }
part.find_by_bbox
Find parts whose bounding box overlaps or is contained within a given region
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| min | number[3] | required | Query box min corner [x,y,z] in mm |
| max | number[3] | required | Query box max corner [x,y,z] in mm |
| mode | string | optional | 'intersect' (default) or 'contain' |
const r = await vegaExecute('part.find_by_bbox', {
min: [-5000, -2000, 0], max: [5000, 2000, 3000], mode: 'intersect'
});
// → { ok: true, data: { parts: ['FR14', 'FR15', ...], count: 8 } }
part.get_neighbors
Find parts within a given distance from a reference part
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| part_id | string | required | Reference part name |
| distance | number | optional | Search radius in mm (default 1000) |
| max_results | number | optional | Max results to return (default 20) |
const r = await vegaExecute('part.get_neighbors', {
part_id: 'FR14', distance: 2000, max_results: 10
});
// → { ok: true, data: {
// neighbors: [{ name: 'FR15', distance: 450.2 }, ...],
// count: 5
// } }
part.select_by_name
Find and select parts using a glob-style pattern
▶
| Name | Type | Required | Description |
|---|---|---|---|
| pattern | string | required | Glob pattern e.g. 'FR14*', '*배관*' |
const r = await vegaExecute('part.select_by_name', { pattern: 'FR*' });
// → { matched_ids: ['FR14', 'FR15', ...], count: 8 }
part.get_info
Get center and bounding box of a part from FaceRange data
▶
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | required | Part name (or part_id) |
await vegaExecute('part.get_info', { name: 'FR14' });
// → { name: 'FR14', center: [x,y,z], bbox: { min: [], max: [] } }
annotation 4 commands
annotation.add
Add a 3D note annotation — anchor on model surface, label at offset position
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| anchor | number[3] | required | 3D point on model surface (mm) |
| label_pos | number[3] | required | 3D position of the label text (mm) |
| text | string | required | Annotation text content |
const r = await vegaExecute('annotation.add', {
anchor: [100, 200, 50],
label_pos: [150, 250, 100],
text: 'Check weld here'
});
// → { ok: true, data: { id: 0 } }
annotation.list
List all current 3D annotations with positions and text
▶
const r = await vegaExecute('annotation.list');
// → { ok: true, data: {
// annotations: [{ id, text, anchor: [x,y,z], label_pos: [x,y,z] }, ...],
// count: 3
// } }
annotation.delete
Delete a specific annotation by ID
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | number | required | Annotation ID from annotation.list |
await vegaExecute('annotation.delete', { id: 0 });
// → { ok: true, data: { deleted: true } }
annotation.clear
Delete all 3D annotations at once
▶
const r = await vegaExecute('annotation.clear');
// → { ok: true, data: { deleted: 3 } }
markup 5 commands
markup.add_arrow
Draw a 3D arrow line between two points, with optional text label
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| from | number[3] | required | Start point [x,y,z] in mm |
| to | number[3] | required | End point [x,y,z] in mm |
| color | string | optional | CSS hex color (default '#ffff00') |
| label | string | optional | Text label shown at midpoint |
const r = await vegaExecute('markup.add_arrow', {
from: [0, 0, 0], to: [1000, 0, 0],
color: '#ff8800', label: 'Hull gap'
});
// → { ok: true, data: { id: 0 } }
markup.add_text
Place a floating 3D text label at a world position
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| position | number[3] | required | [x,y,z] in mm |
| text | string | required | Label text content |
| color | string | optional | CSS hex color (default '#ffffff') |
const r = await vegaExecute('markup.add_text', {
position: [500, 200, 0], text: 'Review point', color: '#00ffff'
});
// → { ok: true, data: { id: 1 } }
markup.list
List all markup items (arrows and text labels) with IDs and positions
▶
const r = await vegaExecute('markup.list');
// → { ok: true, data: {
// items: [{ id, type: 'arrow'|'text', label, color }, ...],
// count: 2
// } }
markup.delete
Delete a specific markup item by ID
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| id | number | required | Markup ID from markup.list |
await vegaExecute('markup.delete', { id: 0 });
// → { ok: true, data: { deleted: true } }
markup.clear
Remove all markup items from the scene
▶
const r = await vegaExecute('markup.clear');
// → { ok: true, data: { deleted: 2 } }
animation 3 commands
animation.list
List all animation clips embedded in the loaded GLB model
▶
const r = await vegaExecute('animation.list');
// → { ok: true, data: {
// clips: [{ name: 'Open_Door', duration: 2.5 }, ...],
// count: 3
// } }
animation.play
Play a named animation clip
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | required | Animation clip name from animation.list |
| loop | boolean | optional | Loop animation (default false) |
| speed | number | optional | Playback speed multiplier (default 1.0) |
await vegaExecute('animation.play', {
name: 'Open_Door', loop: false, speed: 1.0
});
// → { ok: true, data: { clip: 'Open_Door', duration: 2.5 } }
animation.stop
Stop all currently playing animations and reset to frame 0
▶
await vegaExecute('animation.stop');
// → { ok: true }
clash 1 command
clash.check
Detect bounding-box collisions between two lists of parts
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| group_a | string[] | required | First group of part names |
| group_b | string[] | required | Second group of part names |
| tolerance | number | optional | Expand each box by this amount in mm (default 0) |
const r = await vegaExecute('clash.check', {
group_a: ['PIPE_001', 'PIPE_002'],
group_b: ['STR_FR14', 'STR_FR15'],
tolerance: 50
});
// → { ok: true, data: {
// clashes: [{ a: 'PIPE_001', b: 'STR_FR14' }, ...],
// count: 1
// } }
property 2 commands
property.get
Get all GLB attribute properties of a named part
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | required | Part name |
const r = await vegaExecute('property.get', { name: 'FR14' });
// → { ok: true, data: {
// name: 'FR14',
// properties: { Material: 'A36', Thickness: '12mm', ... }
// } }
property.search
Search parts by attribute key/value pair
▶
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
| key | string | required | Attribute key to search |
| value | string | optional | Exact value to match (omit for any) |
const r = await vegaExecute('property.search', {
key: 'Material', value: 'A36'
});
// → { ok: true, data: { parts: ['FR14', 'FR15', ...], count: 12 } }
events Push Events
Vibe Kit dispatches CustomEvents on document for real-time AI integration.
Use window.addEventListener() — no polling required.
Available Events
| Event | Triggered When | detail |
|---|---|---|
vega:selection | Part selected / highlighted | { selected: ['FR14'] } |
vega:command | Any vegaExecute() call completes | { cmd, params, result } |
// Subscribe to selection events
document.addEventListener('vega:selection', (e) => {
console.log('Selected:', e.detail.selected);
});
// Subscribe to all commands
document.addEventListener('vega:command', (e) => {
console.log(e.detail.cmd, e.detail.result);
});
postMessage Bridge iframe
Use the postMessage bridge to call vegaExecute() from a parent frame when the viewer is embedded as an <iframe>.
// Parent frame → send command to iframe
const viewer = document.getElementById('vega-iframe').contentWindow;
const reqId = 'req_001';
viewer.postMessage(JSON.stringify({
__vegaExecCall: true,
reqId,
cmd: 'camera.set_preset',
params: { preset: 'front' }
}), '*');
// Listen for result
window.addEventListener('message', (e) => {
const data = JSON.parse(e.data);
if (data.__vegaExecResult && data.reqId === reqId) {
console.log(data.result); // { ok: true, data: { preset: 'front' } }
}
});
Response Format
All commands return a consistent object:
// Success
{ ok: true, data: { /* command-specific */ } }
// Success with no data
{ ok: true }
// Failure
{ ok: false, error: { code: 'INVALID_PARAM', message: '...' } }
Error Codes
| Code | Meaning |
|---|---|
| NOT_READY | Scene or camera not yet initialized |
| INVALID_PARAM | Missing or invalid parameter |
| NOT_FOUND | Part name not found in loaded model |
| NOT_SUPPORTED | Feature not available in current build |
| CAPTURE_FAILED | Screenshot capture failed (WebGPU limitation) |
| UNKNOWN_COMMAND | Command string not recognized |
| INTERNAL | Unexpected internal error |