wave3d-agent-sdk 0.2.14 → 0.2.15

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/dist/cli.js CHANGED
@@ -531,6 +531,7 @@ var PROJECT_ASSET_ACCESSOR_BUCKETS = [
531
531
  "materials",
532
532
  "textures",
533
533
  "animations",
534
+ "vertexAnimations",
534
535
  "poses",
535
536
  "audios",
536
537
  "instruments",
@@ -555,7 +556,6 @@ var WaveModelPartScope;
555
556
  (function(WaveModelPartScope2) {
556
557
  WaveModelPartScope2["Available"] = "available";
557
558
  WaveModelPartScope2["Created"] = "created";
558
- WaveModelPartScope2["Promoted"] = "promoted";
559
559
  WaveModelPartScope2["All"] = "all";
560
560
  })(WaveModelPartScope || (WaveModelPartScope = {}));
561
561
  var WaveModelPartLifecycleState;
@@ -41609,7 +41609,7 @@ var DEFAULT_PHYSICS = {
41609
41609
  };
41610
41610
 
41611
41611
  // ../../src/lib/waveStudio/assets/contracts/waveStudioEngineAssetContracts.ts
41612
- var WAVE_STUDIO_ENGINE_ACCESSOR_BUCKET_EXTENSIONS = ["cubeMaps", "poses"];
41612
+ var WAVE_STUDIO_ENGINE_ACCESSOR_BUCKET_EXTENSIONS = ["cubeMaps", "poses", "vertexAnimations"];
41613
41613
  function withAccessorBucketExtensions(buckets) {
41614
41614
  const existingBuckets = new Set(buckets);
41615
41615
  return Object.freeze([
@@ -41996,23 +41996,36 @@ var WAVE_STUDIO_PRIMARY_ASSET_BUCKET_SPECS = Object.freeze([
41996
41996
  },
41997
41997
  {
41998
41998
  bucket: "animations",
41999
- assetTypes: ["animation", "vertexAnimation"],
41999
+ assetTypes: ["animation"],
42000
42000
  label: "Animation",
42001
42001
  pluralLabel: "Animations",
42002
42002
  defaultExtension: ".anim.json",
42003
42003
  baseCategoryAliases: [
42004
42004
  "animations",
42005
42005
  "animation",
42006
- "fbx_animation",
42006
+ "fbx_animation"
42007
+ ],
42008
+ pathFolderAliases: ["animations"],
42009
+ pathExtensions: ["anim.json", "glb", "gltf", "fbx"],
42010
+ assetManagerAlias: "animationNames",
42011
+ monaco: { interfaceName: "AnimationNames", propertyName: "animationNames" }
42012
+ },
42013
+ {
42014
+ bucket: "vertexAnimations",
42015
+ assetTypes: ["vertexAnimation"],
42016
+ label: "Vertex Animation",
42017
+ pluralLabel: "Vertex Animations",
42018
+ defaultExtension: ".vat.json",
42019
+ baseCategoryAliases: [
42007
42020
  "vertexanimation",
42008
42021
  "vertexanimations",
42009
42022
  "vertex_animation",
42010
42023
  "vat"
42011
42024
  ],
42012
- pathFolderAliases: ["animations"],
42013
- pathExtensions: ["anim.json", "vat.json", "glb", "gltf", "fbx"],
42014
- assetManagerAlias: "animationNames",
42015
- monaco: { interfaceName: "AnimationNames", propertyName: "animationNames" }
42025
+ pathFolderAliases: ["vertexAnimations", "vertexanimations"],
42026
+ pathExtensions: ["vat.json"],
42027
+ assetManagerAlias: "vertexAnimationNames",
42028
+ monaco: { interfaceName: "VertexAnimationNames", propertyName: "vertexAnimationNames" }
42016
42029
  },
42017
42030
  {
42018
42031
  bucket: "poses",
@@ -42520,8 +42533,8 @@ function normalizeWaveGenieAssetUploadRequest(request) {
42520
42533
 
42521
42534
  // ../../src/lib/waveStudio/aiAssist/bridge/localAgentSdkContract.ts
42522
42535
  var WAVE3D_AGENT_SDK_PACKAGE_NAME = "wave3d-agent-sdk";
42523
- var WAVE3D_AGENT_SDK_REQUIRED_VERSION = "0.2.14";
42524
- var WAVE3D_AGENT_SDK_REQUIRED_BUILD = "agent-sdk-20260625.2";
42536
+ var WAVE3D_AGENT_SDK_REQUIRED_VERSION = "0.2.15";
42537
+ var WAVE3D_AGENT_SDK_REQUIRED_BUILD = "agent-sdk-20260627.1";
42525
42538
  var WAVE3D_AGENT_SDK_PACKAGE_SPEC = `${WAVE3D_AGENT_SDK_PACKAGE_NAME}@${WAVE3D_AGENT_SDK_REQUIRED_VERSION}`;
42526
42539
  var WAVE3D_AGENT_SDK_START_COMMAND = `npx -y ${WAVE3D_AGENT_SDK_PACKAGE_SPEC} start`;
42527
42540
  var WAVE3D_AGENT_SDK_TOKEN_ENV_VAR = "WAVE3D_MCP_TOKEN";
@@ -43559,7 +43572,7 @@ function buildWaveMcpTaskRouteRecommendedNextToolCall(route) {
43559
43572
  if (route.editIntent === "modifyAssets") {
43560
43573
  return {
43561
43574
  tool: "find_wave_assets_by_category | upload_wave_asset | create_wave_asset_upload | rename_wave_asset | delete_wave_asset",
43562
- arguments: { category: "<models|textures|materials|audios|hdr|animations|...>" },
43575
+ arguments: { category: "<models|textures|materials|audios|hdr|animations|vertexAnimations|...>" },
43563
43576
  note: "Use category first to reduce search space."
43564
43577
  };
43565
43578
  }
@@ -44256,7 +44269,7 @@ var WAVE_AUTHORING_CORE_INTENT_STAMPS = [
44256
44269
  "Multiplicity/performance: wave.group.instancing-and-batching for local repeated model-backed objects; classify per-instance needs before choosing real entities, InstanceMeshGroup/waveInstanceGroup/waveInstanceMesh, or waveThinBatch. Count alone never chooses thin batch. Terrain/world/streamed population is a separate world-elements route.",
44257
44270
  'Soft custom geometry: wave.geometry.sdf-surface and assetManager.createSdfSurface("assetName") recipes for buns, cushions, puffy/squishy toys, and organic rounded forms before plain primitives, raw mesh buffers, or vertex editing.',
44258
44271
  "Path-bound surface geometry: wave.geometry.surface-ribbons and wavePathSurface for roads, trails, walkways, bridge decks, waterfalls, and continuous strips before asset-manager factories, scattered planes/cubes, or raw mesh buffers.",
44259
- "Asset argument vs authoring: typed refs such as models.<asset>, textures.<asset>, materials.<asset>, audios.<asset>, hdr.<asset>, cubeMaps.<asset>, and animations.<asset> for existing assets; waveMaterial for material handles; assetManager only when an exact skill/API requires a low-level generated asset factory."
44272
+ "Asset argument vs authoring: typed refs such as models.<asset>, textures.<asset>, materials.<asset>, audios.<asset>, hdr.<asset>, cubeMaps.<asset>, animations.<asset>, and vertexAnimations.<asset> for existing assets; waveMaterial for material handles; assetManager only when an exact skill/API requires a low-level generated asset factory."
44260
44273
  ];
44261
44274
  var WAVE_AUTHORING_CORE_INTENT_PASS_QUICK_GUIDE = [
44262
44275
  WAVE_AUTHORING_CORE_RULES.coreIntentPass,
@@ -44359,7 +44372,7 @@ function buildWaveMcpAuthoringReminder(kind) {
44359
44372
  ...base,
44360
44373
  nextStep: "Use exact asset refs as method inputs, then return to the authoring strategy.",
44361
44374
  checklist: [
44362
- "Use returned code refs exactly, such as models.X, textures.X, materials.X, audios.X, or animations.X.",
44375
+ "Use returned code refs exactly, such as models.X, textures.X, materials.X, audios.X, animations.X, or vertexAnimations.X.",
44363
44376
  "For authoring new materials, prefer waveMaterial; quote materials.X only for existing material assets.",
44364
44377
  "If a newly referenced asset changes bootstrap needs, let Studio hot reload escalate internally."
44365
44378
  ],
@@ -44465,7 +44478,7 @@ var WAVE_MCP_AGENT_BRIEF = [
44465
44478
  "VFS modules: scene-root modules and their owned helpers run inside the Studio authoring context, but helpers should stay pure or parameterized. Put live object ownership in scene-root/feature files, not shared helpers.",
44466
44479
  'VFS HTML sketches: for diagram/chart/doc-sketch requests, create or edit an exact `.html` file with Studio VFS tools. Mermaid renders from `<div class="mermaid">flowchart TD ...</div>` when that HTML file is active in the editor/coding pane; HTML sketches must never replace the live engine preview iframe. Do not put Mermaid in markdown fences unless user specifically wants markdown text.',
44467
44480
  'VFS hot reload ownership: Studio hot reload targets the active/open edited file when safe. Editing `/main.ts` reloads the main graph; editing a scene-root module reloads that root; bootstrap/scene registry/assets/network/ambiguous helper surfaces escalate. In multi-file projects, standalone `hot_reload_wave_preview` follows the active Studio editor file, so do not expect it to reload an arbitrary unopened module by path. Put heavy world loading in bootstrap or a coarse world module. Static VFS/package/asset-surface changes can be detected from file/package diffs and Studio may upgrade the tier automatically. Runtime-authored UI state changes cannot be inferred from files; if UI in `main.ts` changes bootstrap/world-provider/runtime-envelope state, store the state and call `waveStudio.reloadPreview({ reason, invalidates: ["world-provider"] })`. Valid invalidations are `bootstrap`, `world-provider`, and `runtime-envelope`. Do not call `myScene.hotReload(...)` from Studio-authored code because it bypasses Studio VFS/package/source-patch orchestration. For intentional cross-module live entities, the owner module calls `waveStudio.exportEntity("Name", entity)` and importer modules call `waveStudio.importEntity<T>("Name")`; Studio restores the exported baseline and replays active importer overlays during source hot reload. Source execution order is dependency-driven: exporter roots run before importer roots; an exporter root runs before `main.ts` when main imports it; importer overlays run after exporter/main baseline. Entity names must be static string literals, unique, and acyclic or run/hot reload stops before execution. Keep shared helpers pure or parameterized.',
44468
- "Assets: when quoting or passing an existing asset, use typed bare refs in main files: `models.X`, `textures.X`, `materials.X`, `audios.X`, `hdr.X`, `cubeMaps.X`, `animations.X`, etc. Do not paste raw paths or edit Studio-managed generated files just to register assets. If the exact ref is not already visible, call category-first asset discovery (`find_wave_assets_by_category`, alias `list_wave_assets_by_category`, alias `search_wave_assets_by_category`, or tolerant `list_wave_assets`) with required `category` from user intent, semantic `query`, and small `limit` before editing code; category-filtered results can still be capped/truncated, so refine query before concluding absence. Use `list_wave_explorer_assets` only for uploaded library metadata, rename/delete, URL, path, size, or display/ref-name management.",
44481
+ "Assets: when quoting or passing an existing asset, use typed bare refs in main files: `models.X`, `textures.X`, `materials.X`, `audios.X`, `hdr.X`, `cubeMaps.X`, `animations.X`, `vertexAnimations.X`, etc. Do not paste raw paths or edit Studio-managed generated files just to register assets. If the exact ref is not already visible, call category-first asset discovery (`find_wave_assets_by_category`, alias `list_wave_assets_by_category`, alias `search_wave_assets_by_category`, or tolerant `list_wave_assets`) with required `category` from user intent, semantic `query`, and small `limit` before editing code; category-filtered results can still be capped/truncated, so refine query before concluding absence. Use `list_wave_explorer_assets` only for uploaded library metadata, rename/delete, URL, path, size, or display/ref-name management.",
44469
44482
  "Asset authoring facade split: typed refs quote existing assets; `waveMaterial` authors material handles; `assetManager` is only for exact asset-pipeline/generated-asset APIs that a local SDK skill or API lookup names, such as SDF surfaces or surface ribbons. Do not treat `assetManager` as the default creative facade for materials or normal asset arguments.",
44470
44483
  "Material authoring: when creating, configuring, forking, or intentionally editing material handles, route to `wave.material.authoring` and start from `waveMaterial` (`createWater`, `createGrid`, `createSplatMaterial`, `createFromAsset`, `editAsset`). If a material handle later needs runtime sync, `assetManager` may be passed as the sync target; it is still not the authoring root.",
44471
44484
  "Preview: default to hot reload after code changes. On the final edit use `awaitHotReload: true` when you want edit + hot reload + diagnostics in one response; `requestHotReload:true` now also waits for diagnostics by default unless paired with `awaitHotReload:false`. Standalone `run_wave_preview` / `hot_reload_wave_preview` wait by default and return same-call bounded diagnostics in `runtimeVerification`; set `awaitRuntimeResult:false` only for intentional fire-and-poll. Wave Studio may upgrade the hot-reload tier internally for asset/bootstrap/runtime-surface changes, including a full scene rebuild only when required. Caveat: standalone `hot_reload_wave_preview` mirrors the toolbar button and reloads the currently open/active TypeScript file in multi-file projects; it does not take a target path or reload every user-created .ts module. Use `pause_wave_preview` / `resume_wave_preview` for toolbar-equivalent engine pause/resume.",
@@ -44488,7 +44501,7 @@ var WAVE_MCP_AUTHORING_GLOBALS_GUIDE = [
44488
44501
  "- Direction and input enum-style globals: `Direction.X/Y/Z`, `Direction.Left/Right/Up/Down/Forward/Backward`, `Keyboard`, `MouseButton`, `GamepadButton`, `InputPhase`, `MovementMode`, `RotationMode`.",
44489
44502
  "- Colors/materials/fx helpers: `COLOR`, `PALETTE`, `waveCOLOR`, `waveMaterial`, `shaderUniform`, `waveFx`, `waveFxPresets`, `FxAnchor`, `FxCondition`.",
44490
44503
  "- Controller movement helpers: `waveKinematicActor`, `netKinematicActor`, `KinematicHumanoidMovementState`, `KinematicVehicleMovementState`, and `KinematicFlightMovementState`. Use actor-level `.asHumanoid(...)`, `.asVehicle(...)`, or `.asFlight(...)` for player/controller movement.",
44491
- "- Asset maps: use category-first refs returned by `find_wave_assets_by_category`, commonly `models`, `gaussianSplats`, `animations`, `materials`, `guis`, `textures`, `audios`, `instruments`, `videos`, `hdr`, `fonts`, `serializedData`, `terrains`, `fx`, and `particles`.",
44504
+ "- Asset maps: use category-first refs returned by `find_wave_assets_by_category`, commonly `models`, `gaussianSplats`, `animations`, `vertexAnimations`, `materials`, `guis`, `textures`, `audios`, `instruments`, `videos`, `hdr`, `fonts`, `serializedData`, `terrains`, `fx`, and `particles`.",
44492
44505
  '- Scene/runtime handles: prefer `myScene` for scene composition and `waveStudio` for Studio operations. If authored UI changes bootstrap/world-provider/runtime-envelope state and needs the Studio preview package to rebuild, call `waveStudio.reloadPreview({ reason, invalidates: ["world-provider"] })`, not `myScene.hotReload(...)`. Valid invalidations are `bootstrap`, `world-provider`, and `runtime-envelope`; use the narrowest true reason. `assetManager` is available, but use it only when an exact skill/API names an asset-pipeline or generated-asset factory; do not use it as the default facade for existing asset refs or material authoring. Use lower-level `ctx`, `engine`, or `scene` only when existing code or an exact API requires them.',
44493
44506
  "- Authoring systems/presets: `waveEventBus`, `waveRig`, `waveValueCurve`, `waveValueCurvePresets`, `waveMotionSignal`, `waveParam`, `WaveParam`, `WaveChoice`, `prefabModels`, `effectPrefabs`, and prefab helpers such as `rocketPrefab`.",
44494
44507
  "- Lowercase constructors: `prop`, `marker`, `sphere`, `point`, `cube`, `box`, `cylinder`, `capsule`, `cone`, `torus`, `plane`, `ground`, `line`, `arc`, `path`, and related shape helpers.",
@@ -44521,7 +44534,7 @@ var WAVE_MCP_CODING_GUARDRAIL = [
44521
44534
  `4i. ${WAVE_AUTHORING_CORE_RULES.syncUserCode}`,
44522
44535
  `4j. ${WAVE_AUTHORING_CORE_RULES.terrainGroundRouting}`,
44523
44536
  "5. Use `get_wave_session` and `list_wave_files` to know active file context. `/main.ts` and scene `*/main.ts` get convenience globals: write against `myScene`, not a hand-created scene.",
44524
- `6. ${WAVE_AUTHORING_CORE_RULES.assetResolution} In main files, use bare asset maps like \`models.Foo\`, \`gaussianSplats.Room\`, \`textures.Grass\`, \`materials.Wood\`, \`animations.Idle\`, \`audios.Click\`, \`hdr.daylight\`, \`cubeMaps.studio\`, \`fonts.Poppins_Regular\`, \`serializedData.SomeJson\`. Do not add \`ASSET_WAREHOUSE.\` unless raw warehouse access is explicitly needed.`,
44537
+ `6. ${WAVE_AUTHORING_CORE_RULES.assetResolution} In main files, use bare asset maps like \`models.Foo\`, \`gaussianSplats.Room\`, \`textures.Grass\`, \`materials.Wood\`, \`animations.Idle\`, \`vertexAnimations.HorseGallopVat\`, \`audios.Click\`, \`hdr.daylight\`, \`cubeMaps.studio\`, \`fonts.Poppins_Regular\`, \`serializedData.SomeJson\`. Do not add \`ASSET_WAREHOUSE.\` unless raw warehouse access is explicitly needed.`,
44525
44538
  `6a. For authoring constants, prefer bare runtime globals declared by the Studio authoring environment. Common examples: ${WAVE_AUTHORING_COMMON_GLOBAL_EXAMPLES_TEXT}. The generated globals surface has many more values; use local-SDK \`query_wave_api\` before inventing namespace-qualified paths such as \`TransformVerbMode.Animate\` in authored code. HTTP Gateway hides/retires skill/API lookup.`,
44526
44539
  "6b. Asset facade split: passing an existing asset uses typed refs such as `models.X`, `textures.X`, `materials.X`, or `audios.X`; material authoring starts from `waveMaterial`; `assetManager` is reserved for exact low-level generated-asset/asset-pipeline APIs named by a local SDK skill or API lookup. Do not use `assetManager` as the default material, asset-ref, or path-surface authoring root.",
44527
44540
  '7. Use category-first asset discovery before referencing uploaded user assets, project aliases, or ambiguous built-in assets. Preferred tool: `find_wave_assets_by_category`; aliases: `list_wave_assets_by_category`, `search_wave_assets_by_category`, tolerant `list_wave_assets`. Choose category from user intent first, then query: `list_wave_assets_by_category({ category:"materials", query:"grass", limit:50 })`. For sound use `audios`, for 3D objects use `models`, for sky/HDR use `hdr`, for cube-map sky/environment use `cubeMaps`, for images use `textures`. Category-filtered responses can still be capped/truncated; absence there is not absence in the library. Only use asset refs returned by this tool. If the current code already contains the exact ref and the user asks for a small pattern-preserving edit, you may reuse that visible ref.',
@@ -44533,7 +44546,7 @@ var WAVE_MCP_CODING_GUARDRAIL = [
44533
44546
  '11. After the final code edit, default to hot reload. Prefer `awaitHotReload: true` on the edit tool when you want one MCP response with edit result + hot reload + bounded diagnostics. `requestHotReload:true` also waits for diagnostics by default unless paired with `awaitHotReload:false`. Standalone `run_wave_preview` / `hot_reload_wave_preview` also wait by default and return `runtimeVerification`; set `awaitRuntimeResult:false` only for intentional fire-and-poll. Caveat: standalone `hot_reload_wave_preview` mirrors the toolbar button and reloads the currently open/active TypeScript file in multi-file projects; it does not take a target path or reload every user-created .ts module. That hot-reload request may internally upgrade from `patchMain` to `preserveScene` or hard `rebuildScene` when assets/bootstrap/scene surface changed; do not manually force bootstrap sync. Runtime-authored UI that changes bootstrap/world-provider/runtime-envelope state must call `waveStudio.reloadPreview({ reason, invalidates: ["world-provider"] })` because Studio cannot infer that from static file diffs. Use `run_wave_preview` only when diagnostics show no successful preview yet (`hasRunSucceeded: false`), the user explicitly asks for a full run/restart, or hot reload/polling fails and a full restart is the last resort. `pause_wave_preview` and `resume_wave_preview` are direct preview controls mirroring the toolbar pause/resume buttons.',
44534
44547
  '12. After run/hot reload, use returned `runtimeVerification` when present; otherwise call `get_wave_runtime_diagnostics` repeatedly until `runtimeBusy` is false and `lastRuntimeOutcome` is `success` or `error`. Use `previewExecutionPhase` to distinguish Studio preparing work from the preview iframe executing it. `isRunning` is only the Studio scheduling flag, not the final runtime completion gate. If the edit/runtime tool returned `requestedAt` or `runtimeActionRequestedAt`, ignore diagnostics whose `lastRuntimeOutcomeAt` is older than that timestamp. Treat `latestError` as current only when `lastRuntimeOutcome` is `error`; older error lines can remain in returned logs as history. Treat `editorErrorCount > 0` as blocking Monaco/linter/compile failure and read `editorDiagnostics` before claiming success, even when `lastRuntimeOutcome` is `success`. If `lastRuntimeOutcome` is `success` and `editorErrorCount` is 0, verify visually with `capture_wave_screenshot({ resolution: "L" })` or structurally with `get_wave_runtime_entity_snapshot({ variableName, filePath? })` instead of declaring failure from old log text. Same-machine screenshots usually return `localPath`; hosted screenshots return exact field `dataBase64`, not `imageBase64`.',
44535
44548
  "12a. Marker waypoint workflow: when the human asks to use preview marking tools such as `clickToMark()`, route with `marker.use` plus the code/project intent, then call `list_wave_runtime_markers`. Treat marker records as runtime observation data, write marker `worldPosition`/`worldRotation` into the appropriate path/waypoint/placement code, hot reload, and verify with screenshot or marker re-read. One marker read may happen before routing only when needed to decide the code intent. Use path/placement skills only when current code does not reveal the marker-to-code pattern.",
44536
- `13. To use locally generated assets in code, prefer \`create_wave_asset_upload\` for local files when available: pass assetKind from the Wave Studio upload policy SSOT (${getWaveStudioBridgeAssetUploadKindHelpText()}), stat the file first, pass exact byte size, get \`uploadUrl\` + \`uploadHeaders\`, upload raw bytes with plain HTTP PUT using every returned header exactly, keep \`clientToken\`/\`uploadHeaders.Authorization\` out of logs, call \`get_wave_asset_upload_status\` until \`receivedBytes === sizeBytes\`, then call \`commit_wave_asset_upload\` with the same uploadId, assetKind, filename, contentType, and sizeBytes from the create response. No local Python, Vercel package, or Blob SDK is required. On hosted MCP this uses hosted temporary object storage; on same-machine local MCP it uses the local SDK as temporary staging. If direct upload is unavailable, use \`stage_wave_asset_upload_chunk\` plus \`commit_wave_asset_chunk_upload\`: omit uploadId only for chunkIndex 0, then reuse the returned uploadId for every later chunk and for commit. Use \`upload_wave_asset\` with exactly one of \`dataBase64\` or \`dataUrl\` only for small inline assets. If staging is abandoned before commit, call \`abort_wave_asset_upload\` with the uploadId. Do not abort after commit returns pending or completed; the Studio browser cleans committed staging after execution. Hosted MCP cannot read local filesystem paths through inline upload. All flows stage bytes outside the command queue, cap staged bytes at 300 MB, and return \`asset.bareRef\`, for example \`textures.Albedo\`, \`cubeMaps.Studio\`, \`materials.Wood\`, \`audios.Click\`, \`models.Robot\`, \`animations.Run\`, \`fonts.Title\`, or \`serializedData.Config\`. If the name already exists, the upload result returns \`skipped: true\` and the existing asset. Staged chunks/blobs are also swept lazily after about 24 hours. Model-family uploads enable meshoptimizer by default unless \`useMeshoptimizer\` is false.`,
44549
+ `13. To use locally generated assets in code, prefer \`create_wave_asset_upload\` for local files when available: pass assetKind from the Wave Studio upload policy SSOT (${getWaveStudioBridgeAssetUploadKindHelpText()}), stat the file first, pass exact byte size, get \`uploadUrl\` + \`uploadHeaders\`, upload raw bytes with plain HTTP PUT using every returned header exactly, keep \`clientToken\`/\`uploadHeaders.Authorization\` out of logs, call \`get_wave_asset_upload_status\` until \`receivedBytes === sizeBytes\`, then call \`commit_wave_asset_upload\` with the same uploadId, assetKind, filename, contentType, and sizeBytes from the create response. No local Python, Vercel package, or Blob SDK is required. On hosted MCP this uses hosted temporary object storage; on same-machine local MCP it uses the local SDK as temporary staging. If direct upload is unavailable, use \`stage_wave_asset_upload_chunk\` plus \`commit_wave_asset_chunk_upload\`: omit uploadId only for chunkIndex 0, then reuse the returned uploadId for every later chunk and for commit. Use \`upload_wave_asset\` with exactly one of \`dataBase64\` or \`dataUrl\` only for small inline assets. If staging is abandoned before commit, call \`abort_wave_asset_upload\` with the uploadId. Do not abort after commit returns pending or completed; the Studio browser cleans committed staging after execution. Hosted MCP cannot read local filesystem paths through inline upload. All flows stage bytes outside the command queue, cap staged bytes at 300 MB, and return \`asset.bareRef\`, for example \`textures.Albedo\`, \`cubeMaps.Studio\`, \`materials.Wood\`, \`audios.Click\`, \`models.Robot\`, \`animations.Run\`, \`vertexAnimations.HorseGallopVat\`, \`fonts.Title\`, or \`serializedData.Config\`. If the name already exists, the upload result returns \`skipped: true\` and the existing asset. Staged chunks/blobs are also swept lazily after about 24 hours. Model-family uploads enable meshoptimizer by default unless \`useMeshoptimizer\` is false.`,
44537
44550
  "14. Project tools: use `list_wave_project_templates` before `new_wave_project({ templateId? })`; use `list_wave_projects` before `rename_wave_project({ projectId, name })` or `open_wave_project({ projectId })`. Use `read_wave_project` to learn from example packs without replacing the current editor workspace: pass exact `projectId` from `list_wave_projects` for listed/saved projects, or pass a shared/published project `url` directly for silent URL reads. Shared URL reads support old `/waveStudio?share=<uuid>` links and new shared alias links; published URL reads support old/new `/p/<user>/<id>` links. Rename updates saved project display metadata only. New/open replace the live workspace. If there are unsaved changes they return `unsaved_changes` unless you save first or explicitly pass `discardUnsavedChanges: true`; only use exact ids returned by list tools for open/rename.",
44538
44551
  "15. `save_wave_project` quick-saves an existing saved project and ignores name/description. For a new unsaved project, pass name/description when available; otherwise Studio generates defaults and returns whether each field was defaulted.",
44539
44552
  "16. `share_wave_project` runs the same Share Project menu pipeline, returns a 30-day share `url`, and requires write pairing plus the signed-in share policy. Always send the returned `url` back to the user.",
@@ -44552,7 +44565,7 @@ var WAVE_MCP_CODING_GUARDRAIL_SUMMARY = [
44552
44565
  "4. Prefer natural, intent-preserving public APIs and aliases such as Actor, Prop, Cube, Sphere, waveMaterial, semantic directions, Animate/Seconds/DegreesPerSecond, and fluent WaveEngine DSLs.",
44553
44566
  `4a. ${WAVE_AUTHORING_CORE_RULES.hotReloadCallbackSafety} edit_wave_file/apply_wave_patch/create_wave_file preflight this rule and runtime bundling blocks violations before authored code runs.`,
44554
44567
  "4b. For model voxelization, route to `wave.model.voxelization`; use `model.voxelizing().relativeSize(0.05).surfaceOnly().onWorkerThread().usingCubes().asThinBatch().applyAsync()` only when async/worker authored code is explicitly acceptable, or `onMainThread().apply()` only for tiny local synchronous voxel work. Never use `.apply().then(...)` or Promise callback chains. Use `detectNear`, `getColorAt`, and `whenIndexClicked(index => voxelBatch.at(index).enlargeBy(1.2).done().commitBuffers())` for thin-batch voxel interaction. Do not use `voxelizeHeavy`, `voxelize({ voxelSize })`, `withVoxelSize`, `sharedBox`, or stale `atIndex`.",
44555
- "5. Resolve assets explicitly. Use category-first bare refs returned by `find_wave_assets_by_category` or alias `list_wave_assets_by_category`: models.X, textures.X, materials.X, audios.X, hdr.X, animations.X. Do not guess refs, raw paths, or infer absence from a capped list.",
44568
+ "5. Resolve assets explicitly. Use category-first bare refs returned by `find_wave_assets_by_category` or alias `list_wave_assets_by_category`: models.X, textures.X, materials.X, audios.X, hdr.X, animations.X, vertexAnimations.X. Do not guess refs, raw paths, or infer absence from a capped list.",
44556
44569
  "6. `project.assetrefs.ts`, `project.scene.ts`, `project.scenes.ts`, and `project.execution.ts` are Studio-managed read-only. `bootstrap.ts` is normally managed too; edit it only with a confident `managedFileEditReason` for world streaming/terrain provider, render/runtime backend, media consent/capture, external AI/TTS backend, scene/template baseline, pre-main baseline setup, or stale bootstrap API update to latest. Never edit bootstrap for asset loaders/manifests, instruments, scene registry, or execution manifest.",
44557
44570
  "7. Use safest VFS tool: read first, default to edit_wave_file for small one-file edits, let it auto-resolve baseHash, use apply_wave_patch({ operations }) with explicit baseHash for grouped/advanced work, and inspect skips/partials.",
44558
44571
  "8. For obby/platform tasks, controlled players use kinematic-controller authoring; moving platforms and hazards use rigid-body kinematic geometry/props plus transform/animate/current-code motion.",
@@ -44623,12 +44636,12 @@ var WAVE_MCP_FILE_CONTEXT_GUIDE = [
44623
44636
  "Wave Studio file-context rules:",
44624
44637
  "- Normal scene edit path: use the active `*/main.ts`, write against `myScene`, use bare asset refs, and do not edit Studio-managed generated files.",
44625
44638
  "- Studio-managed generated files are MCP read-only for agents: `project.assetrefs.ts`, `project.scene.ts`, `project.scenes.ts`, and `project.execution.ts`. `bootstrap.ts` / scene `*/bootstrap.ts` is normally Studio-managed too; edit it only when you can confidently pass `managedFileEditReason` as one of: `world_streaming_or_terrain_provider`, `render_profile_or_runtime_backend`, `media_consent_or_capture_plan`, `external_ai_or_tts_backend`, `scene_envelope_or_template_baseline`, `baseline_setup_before_user_main`, `stale_api_update_to_latest`. Never edit bootstrap for assets/loaders, instruments, scene registry, or execution manifest; Studio owns those.",
44626
- "- `main.ts` / scene `*/main.ts`: user scene authoring code. Prefer `myScene` for the active scene. Also available: `assetManager`, `waveEngine`, `waveStudio`, `models`, `gaussianSplats`, `fbxModels`, `animations`, `materials`, `guis`, `textures`, `audios`, `instruments`, `videos`, `hdr`, `cubeMaps`, `generatedModels`, `fonts`, `serializedData`, `terrains`, `fx`, `particles`.",
44639
+ "- `main.ts` / scene `*/main.ts`: user scene authoring code. Prefer `myScene` for the active scene. Also available: `assetManager`, `waveEngine`, `waveStudio`, `models`, `gaussianSplats`, `fbxModels`, `animations`, `vertexAnimations`, `materials`, `guis`, `textures`, `audios`, `instruments`, `videos`, `hdr`, `cubeMaps`, `generatedModels`, `fonts`, `serializedData`, `terrains`, `fx`, `particles`.",
44627
44640
  `- Studio also injects many authoring constants/functions as bare globals. ${WAVE_AUTHORING_BARE_GLOBALS_RULE} Do not add imports or guessed namespaces. Treat listed globals as examples and use local-SDK \`query_wave_api\` for the complete generated authoring surface. HTTP Gateway hides/retires skill/API lookup.`,
44628
44641
  "- Project code does not need to live in one monolith. Use `create_wave_file`, `rename_wave_file`, and `delete_wave_file` for VFS `.ts` modules and folders, for example `/actors/player.ts` or `/systems/movingPlatforms.ts`. New `.ts/.tsx` files are runnable source roots by default, so top-level scene code in them runs on Run/hot reload; pass `runnable:false` only for pure helper modules that should not execute on their own.",
44629
44642
  '- Studio VFS also supports non-code `.html` sketch files. Use `create_wave_file({ path: "/docs/diagram.html", content })` for Mermaid diagrams, charts, and lightweight docs; put Mermaid source inside `<div class="mermaid">...</div>`, not markdown fences. When that `.html` file is active, the editor/coding pane renders it as an HTML sketch and auto-loads Mermaid if `class="mermaid"` is present. HTML sketches must never replace the live engine preview iframe.',
44630
44643
  "- `list_wave_files` and `read_wave_file` return a full-file `contentHash`. Primary simple edit tool `edit_wave_file` can omit `baseHash`; Studio resolves the latest mirror hash and still performs browser-side stale-write checks. It accepts `edits:[{startLine,endLine,text}]` or `edits:[{rangeOffset,rangeLength,text}]` for one-file multi-edits. Use explicit `baseHash` for advanced `apply_wave_patch({ operations: [...] })` compact operations (`lineEdits`, `textEdits`, strict `searchReplace`, or `unifiedDiff`) and existing-file `writeFile` unless `forceOverwrite: true`. This hash is a cooperative stale-write check, not a security boundary. Prefer forgiving `edit_wave_file` over full-file `writeFile` when only a small span changes. Stale hashes and ambiguous replacements are skipped instead of guessed. `textEdits` offsets are zero-based UTF-16 offsets in the full file, even if you used a scoped line read; line edits use 1-based full-file line numbers. Scoped reads and line edits clamp oversized endLine to lineCount but still reject startLine beyond the file. If you need multiple compact changes in one file, use `edit_wave_file({ path, edits:[...] })` or combine them into one advanced patch operation; re-read between separate operations.",
44631
- "- Main-file asset refs should be bare: `models.Car`, `gaussianSplats.Room`, `textures.Grass`, `materials.Metal`, `animations.Idle`. Omit `ASSET_WAREHOUSE.` for authored code.",
44644
+ "- Main-file asset refs should be bare: `models.Car`, `gaussianSplats.Room`, `textures.Grass`, `materials.Metal`, `animations.Idle`, `vertexAnimations.HorseGallopVat`. Omit `ASSET_WAREHOUSE.` for authored code.",
44632
44645
  "- Asset facade split: existing asset inputs use typed refs; material authoring starts from `waveMaterial`; `assetManager` is for explicit generated-asset/asset-pipeline APIs named by a local SDK skill or API lookup, not the default place to invent new material or asset code.",
44633
44646
  "- Use `find_wave_assets_by_category({ category, query?, limit? })` to inspect the current live asset surface. Fill category from user intent first. It includes public assets, uploaded user assets, and project aliases, with `source` telling where each ref came from.",
44634
44647
  "- Wave Studio auto-maintains bootstrap/project asset/scene wiring for normal `main.ts` edits. Do not write or modify bootstrap or generated project registry files just to make an asset ref or scene entry available; use the returned bare refs in main code and let Studio sync boot/assets/scenes. Hot reload is the default preview path after code edits and can automatically upgrade its internal tier when new assets or bootstrap-surface changes require it.",
@@ -44683,13 +44696,13 @@ var WAVE_MCP_STUDIO_TOOL_GUIDE = [
44683
44696
  '- Local parity rule: WaveEngine Agent SDK `tools/list` mirrors the HTTP Gateway Studio-operation catalog, then adds local SDK lookup/session-discovery extras. Direct local live-session tools include VFS edits, assets/uploads, project save/open/new/read/share, preview run/hot reload/pause/resume, diagnostics, performance, screenshots, entity snapshots, and runtime markers. Local browser-backed calls wait directly for browser results. Only call `get_wave_command_result` if a tool returns `status:"pending"` plus `requestId`; on local it normally exists only for catalog parity and reports no local pending-command queue.',
44684
44697
  `- MCP topology: same-machine agents should run \`${WAVE3D_AGENT_SDK_START_COMMAND}\`, check /health, and update/restart SDK if version is stale, tools are missing, or SDK prints secrets; after restart recheck /health and tools/list. If restart happens after Copy-to-Agent, preserve MCP_TOKEN with \`${WAVE3D_AGENT_SDK_TOKEN_PRESERVING_START_COMMAND}\` using the current MCP_TOKEN value without printing it, otherwise the SDK may be healthy but unable to authorize the copied local pairing secret. Current SDK start reuses a current same-token peer, replaces verified stale/different-token SDK peers on localhost, and refuses to kill non-SDK port owners. Same-machine stale/missing tools/401-with-Gateway-success means repair local SDK first, not HTTP Gateway first. Same-machine HTTP Gateway is degraded fallback only after SDK cannot run, update, or adopt. Different-machine/cloud/sandbox agents should use \`MCP_HTTP_GATEWAY_FALLBACK_URL\` directly; starting WaveEngine Agent SDK there binds localhost beside the agent, not beside the user browser. Stale SDK/cache are not reasons to use HTTP Gateway fallback; wrong-machine localhost is a topology mismatch.`,
44685
44698
  `- MCP cache priorities: Priority 1 is active role/context cache: keep role, guardrails, authoring workflow, asset/VFS/hot-reload rules, prompt version, and prompt hash in active LLM context. Priority 2 is WaveEngine SDK Cache: production HTTP Gateway/local-SDK onboarding must not claim normal cached success until SDK cache is prepared or accept proof passes. If accept returns \`wave_engine_sdk_cache_not_ready\`, update/restart \`wave3d-agent-sdk\` or run \`${WAVE_MCP_CORPUS_CACHE_COMMAND_TEMPLATE}\`, then retry accept. If local cache cannot work because sandbox/no filesystem/no Node/npm/user refusal/refresh failure, explicitly accept degraded fallback with \`waveEngineSdkFallbackMode:"studio_ops_only"\`, a valid \`waveEngineSdkUnavailableReason\`, and \`studioOpsOnlyFallbackAccepted:true\`; warn user HTTP Gateway is Studio-ops-only and skill/API lookup requires local SDK/cache repair. This cache command reinstalls the package-bundled SDK locally; it is not WaveEngine Agent SDK transport. Never run it to switch MCP transport; never treat cache failure as local transport failure.`,
44686
- "- Main-file globals include `myScene`, `assetManager`, `waveEngine`, `waveStudio`, and direct asset maps such as `models`, `gaussianSplats`, `textures`, `materials`, `animations`, `audios`, `hdr`, `cubeMaps`, `fonts`, `serializedData`, `terrains`, `fx`, `particles`. Availability is not endorsement: choose the intent-owned facade/skill before using a global.",
44699
+ "- Main-file globals include `myScene`, `assetManager`, `waveEngine`, `waveStudio`, and direct asset maps such as `models`, `gaussianSplats`, `textures`, `materials`, `animations`, `vertexAnimations`, `audios`, `hdr`, `cubeMaps`, `fonts`, `serializedData`, `terrains`, `fx`, `particles`. Availability is not endorsement: choose the intent-owned facade/skill before using a global.",
44687
44700
  `- Bare authoring globals: common examples include ${WAVE_AUTHORING_COMMON_GLOBAL_EXAMPLES_TEXT}, \`waveMaterial\`, \`waveFx\`, \`waveValueCurve\`, and \`waveParam\`. Use them directly in \`main.ts\`; do not import or namespace-qualify them. If the task is unfamiliar, retrieve the relevant local-SDK \`wave.*\` skill first; for the full generated exact-global surface, call local-SDK \`query_wave_api\`.`,
44688
44701
  "- MCP VFS edit tools: primary tool is forgiving `edit_wave_file({ path, ... })`; it infers replaceLines from startLine/endLine, multi-edit from edits:[...], replaceText from oldText, and whole-file replace from text/content. It handles line-based edits, exact string changes, one-file edit arrays, whole-file replacement, omitted baseHash, common aliases, and oversized endLine clamping. Use `apply_wave_patch({ operations: [...] })` only for grouped/multi-file edits and advanced operations; a single operation is tolerated but operations:[...] is preferred. Simple edit tools can omit baseHash; advanced patch operations should pass it.",
44689
44702
  `- MCP hot-reload safety rule: ${WAVE_AUTHORING_CORE_RULES.hotReloadCallbackSafety} edit_wave_file, create_wave_file, and apply_wave_patch preflight this rule before writing.`,
44690
44703
  "- MCP generated-file rule: `project.assetrefs.ts`, `project.scene.ts`, `project.scenes.ts`, and `project.execution.ts` are Studio-managed read-only. `bootstrap.ts` / scene `*/bootstrap.ts` is normally managed too; edit it only when you can confidently pass `managedFileEditReason` as `world_streaming_or_terrain_provider` (Google Maps 3D tiles included), `render_profile_or_runtime_backend`, `media_consent_or_capture_plan`, `external_ai_or_tts_backend`, `scene_envelope_or_template_baseline`, `baseline_setup_before_user_main`, or `stale_api_update_to_latest`. Never edit bootstrap for asset manifests/loaders, instruments, scene registry, or execution manifest; Studio owns those.",
44691
44704
  '- MCP VFS file tools: `create_wave_file({ path, content, requestHotReload? })`, `rename_wave_file({ fromPath, toPath, requestHotReload? })`, and `delete_wave_file({ path, requestHotReload? })` are direct Operate tools for exact live VFS paths, including project `.ts` modules and `.html` sketch files. New `.ts/.tsx` files are standalone runnable source roots by default, so top-level scene code runs on Run/hot reload; pass `runnable:false` only for pure helper modules that should not execute on their own. For Mermaid/diagram/chart requests, create a `.html` file containing a block like `<div class="mermaid">flowchart TD\\n A --> B</div>`; active `.html` files render in the editor/coding pane as HTML sketches and auto-load Mermaid when `class="mermaid"` is present. HTML sketches must never replace the live engine preview iframe. On the final code edit, `awaitHotReload:true` implies hot reload and returns bounded runtime diagnostics in the same response. These tools manage VFS files, not uploaded asset-library blobs. If the user gives a vague target, call `list_wave_files`/`read_wave_file` or ask before mutating. Scene-root modules and owned helpers run in the Studio authoring context; keep shared helpers pure or parameterized, and keep live object ownership in feature files. Rename/move rewrites relative imports; delete is permanent unless you rewrite the file and refuses files still imported by other VFS code.',
44692
- "- MCP asset resolution rule: if code needs an existing asset argument, reuse an exact visible typed ref or call category-first asset discovery before editing: `find_wave_assets_by_category({ category, query?, sources?, limit? })`, alias `list_wave_assets_by_category`, alias `search_wave_assets_by_category`, or tolerant `list_wave_assets`. Fill `category` from user intent first: sound/audio -> `audios`, 3D object/character/prop -> `models`, material -> `materials`, image/texture -> `textures`, sky/HDR -> `hdr`, cube-map sky/environment -> `cubeMaps`, animation -> `animations`, JSON/CSV/YAML/XML/ROS data -> `serializedData`. It returns refs safe to use in authored code, ordered projectAlias -> user -> public. In `main.ts`, pass typed bare refs such as `models.X`, `textures.X`, `materials.X`, `audios.X`, `hdr.X`, `cubeMaps.X`, `animations.X`, `videos.X`, `fonts.X`, `serializedData.X`, or `terrains.X`; do not paste raw paths.",
44705
+ "- MCP asset resolution rule: if code needs an existing asset argument, reuse an exact visible typed ref or call category-first asset discovery before editing: `find_wave_assets_by_category({ category, query?, sources?, limit? })`, alias `list_wave_assets_by_category`, alias `search_wave_assets_by_category`, or tolerant `list_wave_assets`. Fill `category` from user intent first: sound/audio -> `audios`, 3D object/character/prop -> `models`, material -> `materials`, image/texture -> `textures`, sky/HDR -> `hdr`, cube-map sky/environment -> `cubeMaps`, skeletal animation -> `animations`, baked vertex/VAT animation -> `vertexAnimations`, JSON/CSV/YAML/XML/ROS data -> `serializedData`. It returns refs safe to use in authored code, ordered projectAlias -> user -> public. In `main.ts`, pass typed bare refs such as `models.X`, `textures.X`, `materials.X`, `audios.X`, `hdr.X`, `cubeMaps.X`, `animations.X`, `vertexAnimations.X`, `videos.X`, `fonts.X`, `serializedData.X`, or `terrains.X`; do not paste raw paths.",
44693
44706
  "- MCP asset-authoring facade rule: quoting or passing existing assets uses typed refs such as `models.X`, `textures.X`, `materials.X`, and `audios.X`; creating/configuring/forking/editing material handles starts from `waveMaterial` and `wave.material.authoring`; path-bound surfaces start from `wavePathSurface`; `assetManager` is reserved for exact low-level asset-pipeline/generated-asset APIs named by a local SDK skill or API lookup.",
44694
44707
  "- MCP material authoring rule: quoting an existing material uses `materials.X`; authoring a material handle uses `waveMaterial`. Do not call internal procedural material lifecycle methods such as `_sync(...)`, `_bindAutoSync(...)`, or `_release(...)` in authored code; apply procedural handles through `entity.useMaterial(...)`, geometry, terrain paint, or shader `.useTexture(...)`. `WaveMaterialAssetEditHandle.sync(assetManager)` remains the explicit commit step for intentional loaded-material asset edits.",
44695
44708
  `- MCP explorer asset tools: \`list_wave_explorer_assets({ query?, assetTypes?, limit? })\`, \`create_wave_asset_upload({ assetKind, filename, contentType?, sizeBytes })\`, \`commit_wave_asset_upload({ assetKind, uploadId, filename, contentType?, sizeBytes, useMeshoptimizer?, useKtx2Compression? })\`, \`get_wave_asset_upload_status({ uploadId, totalChunks? })\`, \`upload_wave_asset({ assetKind, filename, dataBase64? | dataUrl?, contentType?, useMeshoptimizer?, useKtx2Compression? })\`, \`stage_wave_asset_upload_chunk({ uploadId?, chunkIndex, totalChunks, dataBase64 })\`, \`commit_wave_asset_chunk_upload({ assetKind, uploadId, filename, contentType?, totalChunks, totalSizeBytes, useMeshoptimizer?, useKtx2Compression? })\`, \`abort_wave_asset_upload({ uploadId })\`, \`rename_wave_asset({ path, name })\`, and \`delete_wave_asset({ path })\` operate on uploaded user assets shown by the asset explorer. \`assetKind\` values come from the Wave Studio upload policy SSOT: ${getWaveStudioBridgeAssetUploadKindHelpText()}. Status and abort require the same write token, but can still run after the active Studio write grant expires. Read \`resultSummary\` first: asset tools report ASSET ... OK, ASSET ... FAILED, or ASSET ... PENDING in the same response.`,
@@ -44767,8 +44780,8 @@ var WAVE_MCP_TOOL_CATALOG_GUIDE = [
44767
44780
  "- Marker waypoint recipe: direct marker position/rotation questions are Observe and call `list_wave_runtime_markers` directly. When the user asks to use clicked/marked points in code, start a route with `marker.use` plus `code.author` or the fitting fast-lane code kind, then call `list_wave_runtime_markers`. Read the target file, use marker `worldPosition`/`worldRotation` as waypoint/path/placement inputs, and verify with screenshot or marker re-read. Retrieve a path/placement skill only when current code does not reveal the pattern.",
44768
44781
  "",
44769
44782
  "studio.assets - refs, uploads, and asset library:",
44770
- "- Asset resolution rule: before writing an asset-map input, reuse an exact ref already visible in code or call category-first asset discovery (`find_wave_assets_by_category`, alias `list_wave_assets_by_category`) with required `category`, semantic `query`, and small `limit`; do not invent `models.<asset>`, `textures.<asset>`, `materials.<asset>`, `audios.<asset>`, `hdr.<asset>`, `cubeMaps.<asset>`, or `animations.<asset>` keys from memory. Do not infer absence from a capped category list.",
44771
- "- Existing asset arguments should be typed bare refs in main files, such as `models.Robot`, `textures.Grass`, `materials.Wood`, `audios.Click`, `hdr.StudioSky`, `cubeMaps.studio`, `animations.Run`, `videos.Intro`, `fonts.Title`, `serializedData.UnitreePose`, or `terrains.Alpine`.",
44783
+ "- Asset resolution rule: before writing an asset-map input, reuse an exact ref already visible in code or call category-first asset discovery (`find_wave_assets_by_category`, alias `list_wave_assets_by_category`) with required `category`, semantic `query`, and small `limit`; do not invent `models.<asset>`, `textures.<asset>`, `materials.<asset>`, `audios.<asset>`, `hdr.<asset>`, `cubeMaps.<asset>`, `animations.<asset>`, or `vertexAnimations.<asset>` keys from memory. Do not infer absence from a capped category list.",
44784
+ "- Existing asset arguments should be typed bare refs in main files, such as `models.Robot`, `textures.Grass`, `materials.Wood`, `audios.Click`, `hdr.StudioSky`, `cubeMaps.studio`, `animations.Run`, `vertexAnimations.HorseGallopVat`, `videos.Intro`, `fonts.Title`, `serializedData.UnitreePose`, or `terrains.Alpine`.",
44772
44785
  "- Asset authoring facade split: quote existing assets as typed refs (`models.X`, `textures.X`, `materials.X`, `audios.X`, etc.); author material handles through `waveMaterial` and `wave.material.authoring`; use `assetManager` only for exact generated-asset/asset-pipeline APIs named by a local SDK Wave skill or API lookup.",
44773
44786
  '- `find_wave_assets_by_category`: category-first refs safe to write in code, such as `models.Robot`, `textures.Grass`, `materials.Wood`, `audios.Click`. Aliases: `list_wave_assets_by_category`, `search_wave_assets_by_category`, tolerant `list_wave_assets`. Examples: `{ category:"models", query:"sparrow", limit:50 }`, `{ category:"audios", query:"footstep", limit:50 }`, `{ category:"materials", query:"grass", limit:50 }`.',
44774
44787
  "- `list_wave_explorer_assets`: uploaded asset library metadata for management: path, URL, display/ref name, type, size. May be empty; not a fallback for built-in/public refs.",
@@ -45961,6 +45974,18 @@ function normalizeKnownDimensionsMm(value) {
45961
45974
  }
45962
45975
  return Object.keys(result).length > 0 ? result : null;
45963
45976
  }
45977
+ function duplicateStrings(items) {
45978
+ const seen = /* @__PURE__ */ new Set();
45979
+ const duplicates = /* @__PURE__ */ new Set();
45980
+ for (const item of items) {
45981
+ if (seen.has(item)) {
45982
+ duplicates.add(item);
45983
+ } else {
45984
+ seen.add(item);
45985
+ }
45986
+ }
45987
+ return [...duplicates];
45988
+ }
45964
45989
  function parseModelingJobArgs(args) {
45965
45990
  const sourcePrompt = normalizeOptionalString(args?.sourcePrompt) ?? normalizeOptionalString(args?.prompt) ?? normalizeOptionalString(args?.description);
45966
45991
  if (!sourcePrompt) {
@@ -45977,6 +46002,14 @@ function parseModelingJobArgs(args) {
45977
46002
  "`knownDimensionsMm` must be a JSON object with only JSON-safe values."
45978
46003
  );
45979
46004
  }
46005
+ const requiredParts = optionalStringArray(args?.requiredParts) ?? [];
46006
+ const duplicateRequiredParts = duplicateStrings(requiredParts);
46007
+ if (duplicateRequiredParts.length > 0) {
46008
+ return errorToolResult(
46009
+ "invalid_arguments",
46010
+ `\`requiredParts\` names must be unique because Wave getPart(name) requires unambiguous public part names. Duplicates: ${duplicateRequiredParts.join(", ")}.`
46011
+ );
46012
+ }
45980
46013
  return {
45981
46014
  assetName: sanitizeAssetName(rawAssetName),
45982
46015
  sourcePrompt,
@@ -45984,7 +46017,7 @@ function parseModelingJobArgs(args) {
45984
46017
  referenceImagePaths: optionalStringArray(args?.referenceImagePaths) ?? [],
45985
46018
  targetStyle: normalizeOptionalString(args?.targetStyle) ?? null,
45986
46019
  intendedUse: normalizeOptionalString(args?.intendedUse) ?? null,
45987
- requiredParts: optionalStringArray(args?.requiredParts) ?? [],
46020
+ requiredParts,
45988
46021
  knownDimensionsMm
45989
46022
  };
45990
46023
  }
@@ -45992,7 +46025,41 @@ function markdownList(items, emptyText) {
45992
46025
  if (items.length === 0) return `- ${emptyText}`;
45993
46026
  return items.map((item) => `- ${item}`).join("\n");
45994
46027
  }
46028
+ var WAVE_OBJECT_MODEL_PARTS_CONTRACT = `## WaveEngine objectModel SSOT contract
46029
+
46030
+ When requiredParts is non-empty, or the user asks for named/selectable/collidable/material-addressable parts, the GLB must carry Wave objectModel metadata. Mesh names, ordered mesh arrays, and legacy partIds metadata are not source of truth.
46031
+
46032
+ Required GLB shape for part-aware output:
46033
+
46034
+ - Add an empty/transform node named \`__wave_model_object_model\`; it must have no children.
46035
+ - Put \`waveModelObjectModel\` in that node's metadata/extras.
46036
+ - The value must be a valid WaveModelObjectModel JSON object:
46037
+ - \`version: 1\`
46038
+ - \`modelId\`: stable asset id/name
46039
+ - \`revision\`: stable revision string for this generated artifact
46040
+ - \`meshes\`: one record per render mesh with stable \`id\`, \`displayName\`, and \`order\`
46041
+ - \`parts\`: one record per user-facing part with stable \`id\`, public \`name\`, \`order\`, optional \`parentPartId\`, optional \`rotationPivot\`, optional \`visualFrame\`
46042
+ - \`meshPartBindings\`: explicit bindings from mesh id to part id with role \`visual\` or \`collision\`
46043
+ - \`parentPartId\` on child part records when parts have authored parent/child relationships
46044
+ - \`topology\`: include \`rootPartIds\` and \`joints: []\` only when a rig/joint topology is needed
46045
+ - \`materialSlots\` and \`materialBindings\`: canonical material targets when materials are meant to be changed by mesh or part
46046
+ - Mirror only projection hints on each part-owned mesh metadata:
46047
+ - \`waveModelPartId\`: canonical part id
46048
+ - \`waveModelPartName\`: public part name users pass to \`getPart()\`
46049
+ - \`waveModelPartMetadata\`: serializable part metadata when needed
46050
+ - \`waveModelPartParentId\`: only when part has parent part
46051
+
46052
+ Rules:
46053
+
46054
+ - If user did not ask for parts, do not invent parts for every mesh. Output mesh-only GLB.
46055
+ - If a visual part contains multiple meshes, bind all meshes to the same part id.
46056
+ - Preserve authored pivots/origins as objectModel \`rotationPivot\` and \`visualFrame\`, not by baking them away.
46057
+ - Do not write \`metadata.partIds\`, \`extras.partIds\`, mesh-name-derived part ids, or positional part arrays as source of truth.
46058
+ - Validate before upload: every required part name appears in \`objectModel.parts[].name\`, and every part-owned mesh has a matching \`meshPartBindings[]\` record.
46059
+ `;
45995
46060
  function buildModelingSupportFiles(input) {
46061
+ const requestedPartsText = input.requiredParts.length > 0 ? input.requiredParts.join(", ") : "none explicitly requested; keep output mesh-only unless the source request itself asks for named/selectable/collidable/material-addressable parts";
46062
+ const visiblePartsInstruction = input.requiredParts.length > 0 ? "- Named visible parts matching requiredParts exactly." : "- Mesh/object breakdown only; do not invent Wave parts unless the source request itself asks for named/selectable/collidable/material-addressable parts.";
45996
46063
  const briefJson = JSON.stringify({
45997
46064
  assetName: input.assetName,
45998
46065
  sourcePrompt: input.sourcePrompt,
@@ -46005,7 +46072,28 @@ function buildModelingSupportFiles(input) {
46005
46072
  outputContract: {
46006
46073
  preferredModelFile: `${input.assetName}.glb`,
46007
46074
  optionalCadFile: `${input.assetName}.step`,
46008
- waveStudioImport: "Use create_wave_asset_upload/upload_wave_asset after GLB exists, then author code with models.<assetName>."
46075
+ waveStudioImport: "Use create_wave_asset_upload/upload_wave_asset after GLB exists, then author code with models.<assetName>.",
46076
+ objectModelSSOT: input.requiredParts.length > 0 ? {
46077
+ required: true,
46078
+ envelopeNodeName: "__wave_model_object_model",
46079
+ envelopeMetadataKey: "waveModelObjectModel",
46080
+ perMeshProjectionKeys: [
46081
+ "waveModelPartId",
46082
+ "waveModelPartName",
46083
+ "waveModelPartMetadata",
46084
+ "waveModelPartParentId"
46085
+ ],
46086
+ forbiddenLegacyTruth: [
46087
+ "metadata.partIds",
46088
+ "extras.partIds",
46089
+ "mesh-name-derived part ids",
46090
+ "ordered mesh arrays as part truth"
46091
+ ]
46092
+ } : {
46093
+ required: false,
46094
+ conditionalRequirement: "Embed objectModel SSOT only if the source request itself asks for named/selectable/collidable/material-addressable parts.",
46095
+ rule: "Do not invent objectModel parts for raw multi-mesh GLB unless user explicitly requests parts."
46096
+ }
46009
46097
  }
46010
46098
  }, null, 2);
46011
46099
  const parameterTemplate = JSON.stringify({
@@ -46017,7 +46105,7 @@ function buildModelingSupportFiles(input) {
46017
46105
  overall_height: input.knownDimensionsMm?.overall_height ?? 500,
46018
46106
  bevel_radius: 12
46019
46107
  },
46020
- parts: input.requiredParts.length > 0 ? input.requiredParts.map((partName) => ({ name: partName, materialHint: "default" })) : [{ name: "body", materialHint: "default" }]
46108
+ parts: input.requiredParts.length > 0 ? input.requiredParts.map((partName) => ({ name: partName, materialHint: "default" })) : []
46021
46109
  }, null, 2);
46022
46110
  return [
46023
46111
  {
@@ -46045,8 +46133,9 @@ ${markdownList(input.referenceImagePaths, "No reference image paths provided.")}
46045
46133
  2. Fill \`parameters.template.json\`.
46046
46134
  3. Run \`python build_step.py parameters.template.json out\` after installing CadQuery/OCP locally.
46047
46135
  4. Convert the STEP/mesh result to GLB with your approved modeling pipeline.
46048
- 5. Upload the GLB through Wave Studio MCP asset upload tools.
46049
- 6. Author scene code with \`models.${input.assetName}\`.
46136
+ 5. If parts are requested, embed and validate the Wave objectModel SSOT contract before upload.
46137
+ 6. Upload the GLB through Wave Studio MCP asset upload tools.
46138
+ 7. Author scene code with \`models.${input.assetName}\`.
46050
46139
 
46051
46140
  ## Safety
46052
46141
 
@@ -46068,15 +46157,17 @@ Asset name: ${input.assetName}
46068
46157
  Request: ${input.sourcePrompt}
46069
46158
  Target style: ${input.targetStyle ?? "match source/reference"}
46070
46159
  Intended use: ${input.intendedUse ?? "WaveEngine scene asset"}
46071
- Required parts: ${input.requiredParts.length > 0 ? input.requiredParts.join(", ") : "infer minimal public-facing parts"}
46160
+ Required parts: ${requestedPartsText}
46161
+
46162
+ ${WAVE_OBJECT_MODEL_PARTS_CONTRACT}
46072
46163
 
46073
46164
  Use the screenshots/reference images as visual evidence. Return:
46074
46165
 
46075
46166
  - Orthographic front/side/top proportions.
46076
- - Named visible parts.
46167
+ ${visiblePartsInstruction}
46077
46168
  - Dimensions in millimeters.
46078
46169
  - Bevels, thickness, symmetry, repeating details.
46079
- - Material/color hints only. Do not invent private engine internals.
46170
+ - Material/color hints. Do not invent engine internals beyond the Wave objectModel SSOT contract.
46080
46171
  - A JSON parameter block compatible with parameters.template.json.
46081
46172
  `
46082
46173
  },
@@ -46098,7 +46189,6 @@ Use the screenshots/reference images as visual evidence. Return:
46098
46189
  },
46099
46190
  parts: {
46100
46191
  type: "array",
46101
- minItems: 1,
46102
46192
  items: {
46103
46193
  type: "object",
46104
46194
  required: ["name"],
@@ -46190,7 +46280,11 @@ if __name__ == "__main__":
46190
46280
 
46191
46281
  - Silhouette matches source screenshots from front/side/top.
46192
46282
  - Scale is correct for WaveEngine world use.
46193
- - Parts are named for future objectModel/part authoring where useful.
46283
+ - If parts were requested, GLB contains \`waveModelObjectModel\` on the \`__wave_model_object_model\` node metadata/extras.
46284
+ - If parts were requested, every required part is present in \`objectModel.parts[].name\`.
46285
+ - If parts were requested, every part mesh has explicit \`meshPartBindings[]\`; no \`metadata.partIds\` or mesh-name fallback is used.
46286
+ - If no parts were requested, raw multi-mesh GLB remains mesh-only and does not eagerly invent parts.
46287
+ - Part pivots/origins, if authored, survive as \`rotationPivot\` and \`visualFrame\`.
46194
46288
  - Material slots are clean and simple.
46195
46289
  - GLB loads in Wave Studio before code authoring.
46196
46290
  - Uploaded asset appears as \`models.${input.assetName}\`.
@@ -46223,7 +46317,9 @@ async function createWave3dModelingJobTool(args) {
46223
46317
  nextActions: [
46224
46318
  "Use cad-sheet-prompt.md plus screenshots/reference images to produce a CAD parameter spec.",
46225
46319
  "Fill parameters.template.json and run the Python scaffold only in a local modeling environment with CadQuery installed.",
46226
- "Convert generated model output to GLB, then upload with create_wave_asset_upload/upload_wave_asset.",
46320
+ "Convert generated model output to GLB.",
46321
+ "If parts are requested, embed and validate the Wave objectModel SSOT contract before upload.",
46322
+ "Upload with create_wave_asset_upload/upload_wave_asset.",
46227
46323
  `After upload, author WaveEngine scene code with models.${parsed.assetName}.`
46228
46324
  ],
46229
46325
  caveats: [
@@ -46241,7 +46337,7 @@ function buildWaveAssetListGuidance(input) {
46241
46337
  const hasFilters = hasQuery || hasBuckets || hasSources;
46242
46338
  const hasMore = input.summary.total > input.summary.returned;
46243
46339
  const guidance = [
46244
- "Use category-first asset discovery for code-safe refs such as models.X, textures.X, materials.X, audios.X, hdr.X, cubeMaps.X, and animations.X. Callable names: `find_wave_assets_by_category`, `list_wave_assets_by_category`, `search_wave_assets_by_category`, or tolerant `list_wave_assets`.",
46340
+ "Use category-first asset discovery for code-safe refs such as models.X, textures.X, materials.X, audios.X, hdr.X, cubeMaps.X, animations.X, and vertexAnimations.X. Callable names: `find_wave_assets_by_category`, `list_wave_assets_by_category`, `search_wave_assets_by_category`, or tolerant `list_wave_assets`.",
46245
46341
  "Choose category from user intent first, then search semantically with `query`; do not browse a broad slice and infer absence."
46246
46342
  ];
46247
46343
  if (hasMore && !hasQuery) {
@@ -46278,7 +46374,7 @@ function buildWaveExplorerAssetListGuidance(input) {
46278
46374
  const hasMore = input.summary.total > input.summary.returned;
46279
46375
  const guidance = [
46280
46376
  "`list_wave_explorer_assets` is for uploaded user-asset management metadata: path, URL, size, display/ref name, rename, and delete.",
46281
- "It is not the fallback for built-in/public code refs. Use category-first asset discovery (`find_wave_assets_by_category` or alias `list_wave_assets_by_category`) when code needs models.X, textures.X, materials.X, audios.X, hdr.X, cubeMaps.X, or animations.X."
46377
+ "It is not the fallback for built-in/public code refs. Use category-first asset discovery (`find_wave_assets_by_category` or alias `list_wave_assets_by_category`) when code needs models.X, textures.X, materials.X, audios.X, hdr.X, cubeMaps.X, animations.X, or vertexAnimations.X."
46282
46378
  ];
46283
46379
  if (input.summary.total === 0 && !hasQuery && !hasAssetTypes) {
46284
46380
  guidance.push("Empty explorer does not mean no code assets exist; it only means this uploaded-user library view has no returned items.");
@@ -47982,7 +48078,7 @@ var ASSET_CODE_REF_DISCOVERY_INPUT_SCHEMA = {
47982
48078
  properties: {
47983
48079
  category: {
47984
48080
  type: "string",
47985
- description: `Preferred asset category or alias. Use user intent to fill this first. Supported categories/aliases from Wave Studio asset SSOT: ${ASSET_CATEGORY_HELP}. Examples: sound/audio -> audios, 3D model/character -> models, material -> materials, texture/image -> textures, HDR sky -> hdr, cube-map sky/environment -> cubeMaps, animation -> animations.`
48081
+ description: `Preferred asset category or alias. Use user intent to fill this first. Supported categories/aliases from Wave Studio asset SSOT: ${ASSET_CATEGORY_HELP}. Examples: sound/audio -> audios, 3D model/character -> models, material -> materials, texture/image -> textures, HDR sky -> hdr, cube-map sky/environment -> cubeMaps, skeletal animation -> animations, baked vertex/VAT animation -> vertexAnimations.`
47986
48082
  },
47987
48083
  bucket: {
47988
48084
  type: "string",
@@ -48712,7 +48808,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48712
48808
  },
48713
48809
  {
48714
48810
  name: "find_wave_assets_by_category",
48715
- description: `[studio.assets] Canonical category-first discovery for code refs. Use when code needs an existing asset: choose an asset category from the user intent first (model/sound/material/texture/sky/animation/etc.), then search the paired Wave Studio asset surface: public assets, uploaded user assets, and project aliases. Preferred shape: { category:"materials", query:"grass", limit:50 }. Friendly aliases \`list_wave_assets_by_category\`, \`search_wave_assets_by_category\`, and \`list_wave_assets\` route here. Returned bare refs are safe in code, e.g. models.Car, textures.Grass, materials.Wood, audios.Click, hdr.Sky, animations.Run. The category-filtered response can still be capped; do not infer absence without semantic query refinement.${BROWSER_COMMAND_PENDING_NOTE}`,
48811
+ description: `[studio.assets] Canonical category-first discovery for code refs. Use when code needs an existing asset: choose an asset category from the user intent first (model/sound/material/texture/sky/animation/VAT/etc.), then search the paired Wave Studio asset surface: public assets, uploaded user assets, and project aliases. Preferred shape: { category:"materials", query:"grass", limit:50 }. Friendly aliases \`list_wave_assets_by_category\`, \`search_wave_assets_by_category\`, and \`list_wave_assets\` route here. Returned bare refs are safe in code, e.g. models.Car, textures.Grass, materials.Wood, audios.Click, hdr.Sky, animations.Run, vertexAnimations.HorseGallopVat. The category-filtered response can still be capped; do not infer absence without semantic query refinement.${BROWSER_COMMAND_PENDING_NOTE}`,
48716
48812
  inputSchema: ASSET_CODE_REF_DISCOVERY_INPUT_SCHEMA
48717
48813
  },
48718
48814
  {
@@ -48759,7 +48855,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48759
48855
  },
48760
48856
  {
48761
48857
  name: "upload_wave_asset",
48762
- description: `[studio.assets] Small inline upload only: upload bytes already loaded by the agent as base64/data URL. This tool does not read local paths. Upload decision tree: tiny bytes already in memory -> upload_wave_asset; local file path/normal size -> create_wave_asset_upload + raw PUT + commit_wave_asset_upload; direct_upload_unavailable or chunk-only environment -> stage_wave_asset_upload_chunk + commit_wave_asset_chunk_upload. assetKind values come from the Wave Studio upload policy SSOT: ${BRIDGE_ASSET_UPLOAD_KIND_HELP}. Meshoptimizer defaults on for model-family uploads only; useMeshoptimizer is ignored for non-model assets unless explicitly supported by the browser pipeline. Pass exactly one of dataBase64 or dataUrl. Returns typed refs such as textures.Albedo, cubeMaps.Studio, materials.Wood, audios.Click, models.Robot, animations.Run, fonts.Title, or serializedData.Config.${WRITE_PAIRING_REQUIRED_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
48858
+ description: `[studio.assets] Small inline upload only: upload bytes already loaded by the agent as base64/data URL. This tool does not read local paths. Upload decision tree: tiny bytes already in memory -> upload_wave_asset; local file path/normal size -> create_wave_asset_upload + raw PUT + commit_wave_asset_upload; direct_upload_unavailable or chunk-only environment -> stage_wave_asset_upload_chunk + commit_wave_asset_chunk_upload. assetKind values come from the Wave Studio upload policy SSOT: ${BRIDGE_ASSET_UPLOAD_KIND_HELP}. Meshoptimizer defaults on for model-family uploads only; useMeshoptimizer is ignored for non-model assets unless explicitly supported by the browser pipeline. Pass exactly one of dataBase64 or dataUrl. Returns typed refs such as textures.Albedo, cubeMaps.Studio, materials.Wood, audios.Click, models.Robot, animations.Run, vertexAnimations.HorseGallopVat, fonts.Title, or serializedData.Config.${WRITE_PAIRING_REQUIRED_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
48763
48859
  inputSchema: {
48764
48860
  type: "object",
48765
48861
  properties: {
@@ -50018,7 +50114,7 @@ function getReadToolDefinitions() {
50018
50114
  },
50019
50115
  {
50020
50116
  name: "create_wave_3d_modeling_job",
50021
- description: "[wave.modeling] Create a local SDK 3D-modeling job scaffold from a prompt and optional screenshots/reference image paths. Writes README, CAD prompt, JSON parameter template/schema, Python CadQuery STEP scaffold, and validation checklist into a temp job folder. Does not generate/upload a GLB by itself; use asset upload tools after a real model file exists. Aliases: generate_wave_3d_model, create_wave_3d_model, create_wave_3d_model_from_screenshots.",
50117
+ description: "[wave.modeling] Create a local SDK 3D-modeling job scaffold from a prompt and optional screenshots/reference image paths. Writes README, CAD prompt, JSON parameter template/schema, Python CadQuery STEP scaffold, and validation checklist into a temp job folder. Does not generate/upload a GLB by itself; use asset upload tools after a real model file exists. If requiredParts is supplied, the resulting GLB must embed Wave objectModel SSOT metadata via waveModelObjectModel on a __wave_model_object_model node plus per-mesh projection keys; raw mesh names, metadata.partIds, extras.partIds, or positional mesh arrays are not part truth. Aliases: generate_wave_3d_model, create_wave_3d_model, create_wave_3d_model_from_screenshots.",
50022
50118
  inputSchema: {
50023
50119
  type: "object",
50024
50120
  properties: {
@@ -50059,7 +50155,7 @@ function getReadToolDefinitions() {
50059
50155
  requiredParts: {
50060
50156
  type: "array",
50061
50157
  items: { type: "string" },
50062
- description: "Optional named visible parts the generated model should preserve."
50158
+ description: "Optional public part names the generated GLB must preserve in objectModel SSOT. When non-empty, model output must include waveModelObjectModel on a __wave_model_object_model node with parts, meshPartBindings, parentPartId/topology/material data as needed, and per-mesh waveModelPartId/waveModelPartName projection keys."
50063
50159
  },
50064
50160
  knownDimensionsMm: {
50065
50161
  type: "object",
@@ -51050,7 +51146,7 @@ async function callReadTool(name, args, context) {
51050
51146
  "studio.preview: hot_reload_wave_preview (alias: hotreload_wave_preview), run_wave_preview (alias: run_project), pause_wave_preview (alias: pause_wave_engine), resume_wave_preview (alias: resume_wave_engine), get_wave_runtime_diagnostics (alias: get_wave_errors), get_wave_runtime_performance_snapshot (alias: get_wave_runtime_performance)",
51051
51147
  "studio.capture: capture_wave_screenshot (alias: get_wave_screenshot), get_wave_runtime_entity_snapshot (alias: get_wave_entity_snapshot), list_wave_runtime_markers (alias: list_wave_markers)",
51052
51148
  "wave.authoring: list_wave_skill_families, query_wave_skills, get_wave_skill, query_wave_api",
51053
- "wave.modeling: create_wave_3d_modeling_job (aliases: generate_wave_3d_model, create_wave_3d_model, create_wave_3d_model_from_screenshots) creates local SDK support files; upload generated GLB later with asset tools"
51149
+ "wave.modeling: create_wave_3d_modeling_job (aliases: generate_wave_3d_model, create_wave_3d_model, create_wave_3d_model_from_screenshots) creates local SDK support files; if parts are requested the generated GLB must embed waveModelObjectModel on a __wave_model_object_model node before upload"
51054
51150
  ],
51055
51151
  rules: [
51056
51152
  "studio.* labels are categories, not callable tools.",
@@ -3,6 +3,6 @@
3
3
  Bundled public-safe WaveEngine SDK lookup cache for wave3d-agent-sdk.
4
4
  Generated from sanitized public API/skill corpus during package build.
5
5
 
6
- cacheKey: 2026-06-24.4.wMh4twvnrJPgyEgJhV6QtcSQvoZClKr3
7
- bundleHash: wMh4twvnrJPgyEgJhV6QtcSQvoZClKr3
8
- zip: wave-engine-sdk-2026-06-24.4.wMh4twvnrJPgyEgJhV6QtcSQvoZClKr3.zip
6
+ cacheKey: 2026-06-24.4._Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS
7
+ bundleHash: _Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS
8
+ zip: wave-engine-sdk-2026-06-24.4._Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS.zip
@@ -1,21 +1,21 @@
1
1
  {
2
- "version": "2026-06-24.4.wMh4twvnrJPgyEgJhV6QtcSQvoZClKr3",
2
+ "version": "2026-06-24.4._Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS",
3
3
  "formatVersion": "2026-06-24.4",
4
- "cacheKey": "2026-06-24.4.wMh4twvnrJPgyEgJhV6QtcSQvoZClKr3",
5
- "bundleFileName": "wave-engine-sdk-2026-06-24.4.wMh4twvnrJPgyEgJhV6QtcSQvoZClKr3.zip",
6
- "bundleHash": "wMh4twvnrJPgyEgJhV6QtcSQvoZClKr3",
4
+ "cacheKey": "2026-06-24.4._Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS",
5
+ "bundleFileName": "wave-engine-sdk-2026-06-24.4._Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS.zip",
6
+ "bundleHash": "_Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS",
7
7
  "generatedAt": "2026-06-06T00:00:00.000Z",
8
8
  "sourceVersions": {
9
9
  "onboarding": {
10
10
  "promptVersion": "2026-06-22.1",
11
- "promptHash": "2lzzgYNUy3U2WxPm5UY9z3ZiaUWUlh-Y"
11
+ "promptHash": "WEfGoja0WV9Aggv3jE1f_Rw3juEjFSVl"
12
12
  },
13
13
  "apiHandbook": {
14
14
  "version": "1",
15
- "contentHash": "d59512be9755b0ae"
15
+ "contentHash": "d98cea1da9b77e39"
16
16
  },
17
- "waveSkillCorpusHash": "dcHw5Ebcnx59z7qt9kfN_G23nlxvZSqi",
18
- "sdkLookupCorpusHash": "chkQiqOkodizLUk-HrdoQ1HXd428XP7k"
17
+ "waveSkillCorpusHash": "ol6UwQmeF1EZGOW3uz8NWVzESWOrkc7P",
18
+ "sdkLookupCorpusHash": "I8ZZ0nhpHnChROmUVOlTuBE2E78QynCB"
19
19
  },
20
20
  "cacheContract": {
21
21
  "llmContextCacheOnly": [
@@ -35,14 +35,14 @@
35
35
  "searchDocuments"
36
36
  ],
37
37
  "rule": "Priority 1 always-on sections must stay in LLM chat/system context. The WaveEngine SDK local cache is public-safe retrieval data, never the only memory for core policy.",
38
- "defaultRefreshCommand": "npx -y wave3d-agent-sdk@0.2.14 cache refresh",
38
+ "defaultRefreshCommand": "npx -y wave3d-agent-sdk@0.2.15 cache refresh",
39
39
  "refreshRule": "When using WaveEngine SDK local cache, compare cacheKey, bundleHash, and sourceVersions before trusting local lookup. If any value differs, update the SDK package or reinstall its bundled SDK cache and rebuild local indexes. Do not fetch a remote SDK zip.",
40
40
  "onlineFallback": "HTTP Gateway does not provide cloud API lookup. If local Node/npm or cache is refused/unavailable, use only concrete Studio operations and already-known code; repair the local WaveEngine SDK before unfamiliar API authoring."
41
41
  },
42
42
  "corpus": {
43
43
  "skillCount": 67,
44
- "apiEntryCount": 4257,
45
- "apiMethodGroupCount": 4520,
44
+ "apiEntryCount": 4260,
45
+ "apiMethodGroupCount": 4522,
46
46
  "apiInheritanceCount": 741
47
47
  },
48
48
  "files": [
@@ -51,14 +51,14 @@
51
51
  "mediaType": "application/json",
52
52
  "role": "lookup-guide",
53
53
  "bytes": 1311,
54
- "hash": "t7FXq-o34BD84aetwe5v7IFwq1V4jg9l"
54
+ "hash": "zdoaJDoRgPKXQQZYqv_2InXra-dmyYFJ"
55
55
  },
56
56
  {
57
57
  "path": "skills/wave-skills.jsonl",
58
58
  "mediaType": "application/jsonl",
59
59
  "role": "skill-corpus",
60
- "bytes": 559047,
61
- "hash": "kpe36hRxZfjMfHU5cKZvjamB0KC8DQ7K"
60
+ "bytes": 559362,
61
+ "hash": "qBYj0pNBjtFbA6NPXOeEs8JzOJeoKH4j"
62
62
  },
63
63
  {
64
64
  "path": "skills/foundations.jsonl",
@@ -78,15 +78,15 @@
78
78
  "path": "api/entries.jsonl",
79
79
  "mediaType": "application/jsonl",
80
80
  "role": "api-corpus",
81
- "bytes": 4219479,
82
- "hash": "5e3mI73T35gOyU-6ufdk317kSedy3nHi"
81
+ "bytes": 4221610,
82
+ "hash": "AVX0mRAkXs-jpLsVTwD5x8NGX5U_ApJb"
83
83
  },
84
84
  {
85
85
  "path": "api/method-groups.jsonl",
86
86
  "mediaType": "application/jsonl",
87
87
  "role": "api-corpus",
88
- "bytes": 1420068,
89
- "hash": "ZLgLqDrvbF1qO5JitaCM9j_lROa2TfZu"
88
+ "bytes": 1420909,
89
+ "hash": "zIVI7FTFXfNe6NqVJmVtqJty_ybf92A-"
90
90
  },
91
91
  {
92
92
  "path": "api/inheritance.jsonl",
@@ -100,14 +100,14 @@
100
100
  "mediaType": "application/json",
101
101
  "role": "api-corpus",
102
102
  "bytes": 219,
103
- "hash": "ENc3SeS9IYG6suD3rz4aJv0z3dfE8RaT"
103
+ "hash": "hJ62YeF9dfus0yzMzIQ0tYEUucMBNj6q"
104
104
  },
105
105
  {
106
106
  "path": "search/search-documents.jsonl",
107
107
  "mediaType": "application/jsonl",
108
108
  "role": "search-index",
109
- "bytes": 3976607,
110
- "hash": "e2h7kHS3b6nNtSpRIze7eB6j03lBddXQ"
109
+ "bytes": 3978654,
110
+ "hash": "QLsswU10LbjXeHtgS5PziZZ9sHlOBCY4"
111
111
  },
112
112
  {
113
113
  "path": "README.md",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave3d-agent-sdk",
3
- "version": "0.2.14",
3
+ "version": "0.2.15",
4
4
  "description": "WaveEngine Agent SDK for same-machine Wave Studio MCP plus bundled WaveEngine lookup.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",