wave3d-agent-sdk 0.2.5 → 0.2.6

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
@@ -662,8 +662,8 @@ PerformanceConfigurator.MatrixTrackedMatrices = [];
662
662
 
663
663
  // ../../node_modules/@babylonjs/core/Misc/devTools.js
664
664
  var WarnedMap = {};
665
- function _WarnImport(name, warnOnce2 = false) {
666
- if (warnOnce2 && WarnedMap[name]) {
665
+ function _WarnImport(name, warnOnce = false) {
666
+ if (warnOnce && WarnedMap[name]) {
667
667
  return;
668
668
  }
669
669
  WarnedMap[name] = true;
@@ -11907,6 +11907,11 @@ var WavePlane;
11907
11907
  // ../../wave-engine/dist/src/core/coreAbstractions/objectModel/waveModelRigPose.js
11908
11908
  var DEFAULT_REVOLUTE_RANGE = Math.PI / 3;
11909
11909
 
11910
+ // ../../wave-engine/dist/src/core/coreAbstractions/geometryKernel/pathMath.js
11911
+ var PATH_FORWARD = new Vector3(0, 0, 1);
11912
+ var PATH_UP = new Vector3(0, 1, 0);
11913
+ var PATH_RIGHT = new Vector3(1, 0, 0);
11914
+
11910
11915
  // ../../node_modules/@babylonjs/core/tslib.es6.js
11911
11916
  function __decorate(decorators, target, key, desc) {
11912
11917
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -40697,63 +40702,6 @@ var Ticks = createWaveTimeUnit("tick");
40697
40702
  var Seconds = createWaveTimeUnit("second");
40698
40703
  var UnitsPerSecond = createWaveRateUnit("unitsPerSecond");
40699
40704
  var DegreesPerSecond = createWaveRateUnit("degreesPerSecond");
40700
- var LogOnceManager = class {
40701
- loggedMessages = /* @__PURE__ */ new Map();
40702
- cooldownMs = 6e4;
40703
- maxCacheSize = 500;
40704
- callsSinceCleanup = 0;
40705
- _logWithLevel(level, message) {
40706
- const now = Date.now();
40707
- const cacheKey = `${level}:${message}`;
40708
- const lastLoggedAt = this.loggedMessages.get(cacheKey);
40709
- const shouldLog = lastLoggedAt === void 0 || now - lastLoggedAt >= this.cooldownMs;
40710
- if (shouldLog) {
40711
- console[level](message);
40712
- this.loggedMessages.set(cacheKey, now);
40713
- }
40714
- this.callsSinceCleanup += 1;
40715
- if (this.callsSinceCleanup >= 100) {
40716
- this._cleanup(now);
40717
- this.callsSinceCleanup = 0;
40718
- }
40719
- }
40720
- _cleanup(now) {
40721
- const cutoff = now - this.cooldownMs;
40722
- for (const [key, timestamp] of this.loggedMessages.entries()) {
40723
- if (timestamp < cutoff) {
40724
- this.loggedMessages.delete(key);
40725
- }
40726
- }
40727
- if (this.loggedMessages.size > this.maxCacheSize) {
40728
- const entries = Array.from(this.loggedMessages.entries()).sort((a, b) => a[1] - b[1]);
40729
- const toRemove = entries.slice(0, entries.length - this.maxCacheSize);
40730
- for (const [key] of toRemove) {
40731
- this.loggedMessages.delete(key);
40732
- }
40733
- }
40734
- }
40735
- /** Log once at `console.log` level. */
40736
- logOnce(message) {
40737
- this._logWithLevel("log", message);
40738
- }
40739
- /** Log once at `console.info` level. */
40740
- infoOnce(message) {
40741
- this._logWithLevel("info", message);
40742
- }
40743
- /** Log once at `console.warn` level. */
40744
- warnOnce(message) {
40745
- this._logWithLevel("warn", message);
40746
- }
40747
- /** Log once at `console.error` level. */
40748
- errorOnce(message) {
40749
- this._logWithLevel("error", message);
40750
- }
40751
- /** Clear retained suppression state. */
40752
- clear() {
40753
- this.loggedMessages.clear();
40754
- }
40755
- };
40756
- var globalLogOnce = new LogOnceManager();
40757
40705
  function validateNonZeroFinite(label, value) {
40758
40706
  if (!Number.isFinite(value) || Math.abs(value) <= Number.EPSILON) {
40759
40707
  throw new Error(`[WaveTime] ${label} requires a finite value whose magnitude is greater than 0.`);
@@ -41467,6 +41415,7 @@ var WorldElementKind;
41467
41415
  WorldElementKind2["Entity"] = "entity";
41468
41416
  WorldElementKind2["Water"] = "water";
41469
41417
  WorldElementKind2["Surface"] = "surface";
41418
+ WorldElementKind2["GrassCarpet"] = "grassCarpet";
41470
41419
  WorldElementKind2["Custom"] = "custom";
41471
41420
  WorldElementKind2["POI"] = "poi";
41472
41421
  WorldElementKind2["Trigger"] = "trigger";
@@ -41493,6 +41442,7 @@ var SUPPORTED_WORLD_ELEMENT_KINDS = [
41493
41442
  WorldElementKind.Entity,
41494
41443
  WorldElementKind.Water,
41495
41444
  WorldElementKind.Surface,
41445
+ WorldElementKind.GrassCarpet,
41496
41446
  WorldElementKind.Custom,
41497
41447
  WorldElementKind.POI
41498
41448
  ];
@@ -42533,8 +42483,8 @@ function normalizeWaveGenieAssetUploadRequest(request) {
42533
42483
 
42534
42484
  // ../../src/lib/waveStudio/aiAssist/bridge/localAgentSdkContract.ts
42535
42485
  var WAVE3D_AGENT_SDK_PACKAGE_NAME = "wave3d-agent-sdk";
42536
- var WAVE3D_AGENT_SDK_REQUIRED_VERSION = "0.2.5";
42537
- var WAVE3D_AGENT_SDK_REQUIRED_BUILD = "agent-sdk-20260617.6";
42486
+ var WAVE3D_AGENT_SDK_REQUIRED_VERSION = "0.2.6";
42487
+ var WAVE3D_AGENT_SDK_REQUIRED_BUILD = "agent-sdk-20260620.1";
42538
42488
  var WAVE3D_AGENT_SDK_PACKAGE_SPEC = `${WAVE3D_AGENT_SDK_PACKAGE_NAME}@${WAVE3D_AGENT_SDK_REQUIRED_VERSION}`;
42539
42489
  var WAVE3D_AGENT_SDK_START_COMMAND = `npx -y ${WAVE3D_AGENT_SDK_PACKAGE_SPEC} start`;
42540
42490
  var WAVE3D_AGENT_SDK_TOKEN_ENV_VAR = "WAVE3D_MCP_TOKEN";
@@ -42808,7 +42758,7 @@ var WAVE_MCP_TOOL_CONTRACTS = {
42808
42758
  query_wave_skills: { workMode: "author", domain: "code", safety: "readOnly", targetPolicy: "none", requiresTaskRoute: false, supportsTaskRoute: true },
42809
42759
  get_wave_skill: { workMode: "author", domain: "code", safety: "readOnly", targetPolicy: "none", requiresTaskRoute: false, supportsTaskRoute: true },
42810
42760
  list_wave_projects: { workMode: "observe", domain: "project", safety: "readOnly", targetPolicy: "none", requiresTaskRoute: false, supportsTaskRoute: true },
42811
- read_wave_project: { workMode: "observe", domain: "project", safety: "readOnly", targetPolicy: "exactProjectIdRequired", requiresTaskRoute: false, supportsTaskRoute: true },
42761
+ read_wave_project: { workMode: "observe", domain: "project", safety: "readOnly", targetPolicy: "projectIdOrUrlRequired", requiresTaskRoute: false, supportsTaskRoute: true },
42812
42762
  list_wave_project_templates: { workMode: "observe", domain: "project", safety: "readOnly", targetPolicy: "none", requiresTaskRoute: false, supportsTaskRoute: true },
42813
42763
  get_wave_runtime_diagnostics: { workMode: "observe", domain: "runtime", safety: "readOnly", targetPolicy: "none", requiresTaskRoute: false, supportsTaskRoute: true },
42814
42764
  get_wave_runtime_performance_snapshot: { workMode: "observe", domain: "runtime", safety: "readOnly", targetPolicy: "none", requiresTaskRoute: false, supportsTaskRoute: true },
@@ -44442,35 +44392,35 @@ var WAVE_MCP_AGENT_BRIEF = [
44442
44392
  "0a. Do not invent MCP tool names. After onboarding, call `tools/list` (or read the returned tool catalog) and use concrete names. Common aliases and safe high-confidence typos are tolerated; destructive/write fuzzy matches require an exact follow-up call. There is no `get_wave_current_project`; use `get_wave_session` for current project/session/active-file context.",
44443
44393
  `0b. Transport rule: choose topology first. Same-machine agent + same Wave Studio browser computer -> use copied \`MCP_URL\` WaveEngine Agent SDK (\`http://127.0.0.1:47231/mcp\`). On localhost, MCP_TOKEN is a local pairing secret, not account/cloud auth. If localhost is refused/unreachable, start exact SDK \`${WAVE3D_AGENT_SDK_START_COMMAND}\` when your runtime allows shell/Node/npm. If SDK is stale, missing tools, printing secrets, or local 401 follows an SDK restart, stop it and restart while preserving MCP_TOKEN as the local pairing secret with \`${WAVE3D_AGENT_SDK_TOKEN_PRESERVING_START_COMMAND}\`; use the current MCP_TOKEN value without printing it. Then recheck /health and tools/list. Same-machine stale/missing tools/401-with-Gateway-success means repair local SDK first, do not use HTTP Gateway first. Same-machine HTTP Gateway is degraded fallback only after SDK cannot run, update, or adopt; convenience, habit, or successful Gateway auth is not a valid fallback reason. Different machine, remote container, cloud agent, sandbox without shell/Node/npm, or localhost points to the agent machine -> use \`MCP_HTTP_GATEWAY_FALLBACK_URL\` directly, where MCP_TOKEN is an HTTP Gateway bearer. Do not start WaveEngine Agent SDK on the wrong machine.`,
44444
44394
  "0b-recovery. If connection/session/onboarding/cache/mirror/timeout state is unclear, call `get_wave_mcp_health` (aliases `mcp_health`, `mcp_status`) first for status, then call `recover_wave_connection({ lastErrorCode?, failedTool?, symptom? })` and follow its `nextAction` exactly. Use recovery after `agent_onboarding_required`, `session_not_found`, `command_timeout`, `command_lease_expired`, `workspace_mirror_not_ready`, `hosted_mcp_proxy_failed`, local/HTTP Gateway fallback confusion, or sleeping-tab symptoms. If local HTTP returns 401 but HTTP Gateway accepts the same MCP_TOKEN, update/restart WaveEngine Agent SDK first. If every endpoint returns 401/bridge_auth_invalid before any tool result, ask user for fresh Copy to Agent.",
44445
- `0c. Cache priorities: Priority 1 is active role/context cache. Keep the role, coding guardrails, authoring workflow, full intent taxonomy (${WAVE_MCP_TASK_INTENT_KIND_VALUES.join(", ")}), Studio tool policy, assets/VFS/hot-reload rules, prompt version, and prompt hash in active LLM context as system-prompt-like rules. Priority 2 is WaveEngine SDK Cache. Production HTTP Gateway/local-SDK onboarding must not claim normal cached success until SDK cache is prepared or explicit accept proof passes. If cache cannot work because sandbox/no filesystem/no Node/npm/user refusal/refresh failure, accept degraded fallback explicitly with \`waveEngineSdkFallbackMode:"studio_ops_only"\` plus \`waveEngineSdkUnavailableReason\` plus \`studioOpsOnlyFallbackAccepted:true\`, and warn user HTTP Gateway is Studio-ops-only and exact API lookup requires local SDK/cache repair. Keep live transport and retrieval cache separate: \`wave3d-agent-sdk start\` is long-running MCP transport; \`wave3d-agent-sdk cache refresh\` reinstalls the package-bundled SDK locally. Never use cache refresh to switch MCP transport, and never treat cache failure as local transport failure. Use SDK Cache for unfamiliar authoring skill/API lookup when Node/npm/local cache are allowed.`,
44446
- '0d. Local parity rule: WaveEngine Agent SDK `tools/list` mirrors the HTTP Gateway catalog plus SDK session discovery extras. Live-session tools run through the paired browser. Local calls wait directly for browser results. Only call `get_wave_command_result` when a tool response actually includes `status:"pending"` and `requestId`; on local it is normally catalog parity only.',
44447
- '0e. Agent behavior harness: choose MECE work mode first. Observe = read/inspect/answer only; call read tools directly. Operate = direct Studio command with no code/design choice; call concrete tools directly without `start_wave_task` for run preview, hot reload, save/share, exact VFS create/rename/delete, asset upload/rename/delete, new project, project rename, and open project by exact projectId. Author = create/change behavior/content through code/API; call `start_wave_task`, gather evidence, optionally fast-start with `nextPhase:"execute"` and editPlan, then edit. Diagnose = find root cause first; observe/read first, then transition to Operate or Author. General = not concrete Wave work; use `agent.general`. `query_wave_api`, `edit_wave_file`, `apply_wave_patch`, and code authoring fast lanes remain route-bound. Exact target rule: never invent paths, asset paths, or project ids; list/read/ask first.',
44395
+ `0c. Cache priorities: Priority 1 is active role/context cache. Keep the role, coding guardrails, authoring workflow, full intent taxonomy (${WAVE_MCP_TASK_INTENT_KIND_VALUES.join(", ")}), Studio tool policy, assets/VFS/hot-reload rules, prompt version, and prompt hash in active LLM context as system-prompt-like rules. Priority 2 is WaveEngine SDK Cache. Production HTTP Gateway/local-SDK onboarding must not claim normal cached success until SDK cache is prepared or explicit accept proof passes. If cache cannot work because sandbox/no filesystem/no Node/npm/user refusal/refresh failure, accept degraded fallback explicitly with \`waveEngineSdkFallbackMode:"studio_ops_only"\` plus \`waveEngineSdkUnavailableReason\` plus \`studioOpsOnlyFallbackAccepted:true\`, and warn user HTTP Gateway is Studio-ops-only and skill/API lookup requires local SDK/cache repair. Keep live transport and retrieval cache separate: \`wave3d-agent-sdk start\` is long-running MCP transport; \`wave3d-agent-sdk cache refresh\` reinstalls the package-bundled SDK locally. Never use cache refresh to switch MCP transport, and never treat cache failure as local transport failure. Use SDK Cache for unfamiliar authoring skill/API lookup when Node/npm/local cache are allowed.`,
44396
+ '0d. Local parity rule: WaveEngine Agent SDK `tools/list` mirrors the HTTP Gateway Studio-operation catalog, then adds local SDK lookup/session-discovery extras. Live-session tools run through the paired browser. Local calls wait directly for browser results. Only call `get_wave_command_result` when a tool response actually includes `status:"pending"` and `requestId`; on local it is normally catalog parity only.',
44397
+ '0e. Agent behavior harness: choose MECE work mode first. Observe = read/inspect/answer only; call read tools directly. Operate = direct Studio command with no code/design choice; call concrete tools directly without `start_wave_task` for run preview, hot reload, save/share, exact VFS create/rename/delete, asset upload/rename/delete, new project, project rename, and open project by exact projectId. Author = create/change behavior/content through code/API; call `start_wave_task`, gather evidence, optionally fast-start with `nextPhase:"execute"` and editPlan, then edit. Diagnose = find root cause first; observe/read first, then transition to Operate or Author. General = not concrete Wave work; use `agent.general`. Local-SDK `query_wave_api`, `edit_wave_file`, `apply_wave_patch`, and code authoring fast lanes remain route-bound. Exact target rule: never invent paths, asset paths, or project ids; list/read/ask first.',
44448
44398
  "0f. Diagnose-only tasks use `code.debug`; bug-fix tasks use both `code.debug` and `code.author` so evidence can lead to edits.",
44449
- "0g. Skill onion rule: for normal Author work, do not use raw user prose as a skill/API query. Triage intent -> choose skill family with `list_wave_skill_families` -> call `query_wave_skills` with selected `families`/`familyId` and a small within-family phrase -> call `get_wave_skill` -> call local-SDK `query_wave_api` only for exact signature/global/value uncertainty. HTTP Gateway hides/retires cloud API lookup. Example: \u201Cturn continuously left\u201D routes to `wave.transform` plus possibly `wave.animate`, then skill query \u201Ccontinuous rotation semantic left\u201D.",
44399
+ "0g. Skill onion rule: for normal Author work, do not use raw user prose as a skill/API query. On the local SDK endpoint, triage intent -> choose skill family with `list_wave_skill_families` -> call `query_wave_skills` with selected `families`/`familyId` and a small within-family phrase -> call `get_wave_skill` -> call `query_wave_api` only for exact signature/global/value uncertainty. HTTP Gateway hides/retires cloud skill/API lookup. Example: \u201Cturn continuously left\u201D routes to `wave.transform` plus possibly `wave.animate`, then skill query \u201Ccontinuous rotation semantic left\u201D.",
44450
44400
  "Shared authoring workflow:",
44451
44401
  ...buildWaveMcpAuthoringWorkflowLines(),
44452
- "First MCP calls after transport selection: initialize the chosen endpoint, read onboarding, accept it, read the tiny ready summary, then call `tools/list`, `get_wave_session`, and `list_wave_files`; call `get_wave_tool_map` only when the tool menu is unclear. Use the package-bundled WaveEngine SDK Cache for unfamiliar authoring lookup. For each user request, choose Observe/Operate/Author/Diagnose/General. Do not route direct Operate commands just to run/save/hot-reload/create/delete exact targets. Always route before exact API lookup or code edits. Use fast-lane route kinds when the code-authoring request is already exact or visibly pattern-preserving.",
44453
- 'Code-edit loop: assess with `read_wave_file`/skills/assets as needed -> `start_wave_task`; if enough context is already read, include `nextPhase:"execute"` plus editPlan to skip a separate `advance_wave_task` call. For exact one-file line/text edits, start the route and call `edit_wave_file` directly with exact `path` plus `startLine`/`endLine`/`text`, `edits:[{startLine,endLine,text}]`, or `oldText`/`newText`; no advance call needed. Use `advance_wave_task({ nextPhase:"lookup" })` only if exact API facts are missing. On final simple edit, prefer `edit_wave_file({ ..., awaitHotReload: true })` to combine edit + hot reload + bounded diagnostics in one call; use `requestHotReload: true` only when you intentionally want fire-and-poll. Use `apply_wave_patch` only for grouped/multi-file work. Fast lane examples: \u201Ccall showDirection on Amy\u201D -> `code.direct_edit`; `cube.setColor(COLOR.RED)` plus \u201Cmake cube blue\u201D -> `code.semantic_guess_edit` with no `query_wave_api` unless uncertain/failing. \u201CPlace cubes in a line\u201D writes new layout code, so it is `code.author`, and should prefer WaveEngine-native APIs such as `myScene.placeInline(...)` over manual coordinates.',
44402
+ "First MCP calls after transport selection: initialize the chosen endpoint, read onboarding, accept it, read the tiny ready summary, then call `tools/list`, `get_wave_session`, and `list_wave_files`; call `get_wave_tool_map` only when the tool menu is unclear. Use the package-bundled WaveEngine SDK Cache for unfamiliar authoring lookup. For each user request, choose Observe/Operate/Author/Diagnose/General. Do not route direct Operate commands just to run/save/hot-reload/create/delete exact targets. Always route before local SDK exact API lookup or code edits. Use fast-lane route kinds when the code-authoring request is already exact or visibly pattern-preserving.",
44403
+ 'Code-edit loop: assess with `read_wave_file`/local-SDK skills/assets as needed -> `start_wave_task`; if enough context is already read, include `nextPhase:"execute"` plus editPlan to skip a separate `advance_wave_task` call. For exact one-file line/text edits, start the route and call `edit_wave_file` directly with exact `path` plus `startLine`/`endLine`/`text`, `edits:[{startLine,endLine,text}]`, or `oldText`/`newText`; no advance call needed. Use `advance_wave_task({ nextPhase:"lookup" })` only if exact API facts are missing. On final simple edit, prefer `edit_wave_file({ ..., awaitHotReload: true })` to combine edit + hot reload + bounded diagnostics in one call; `requestHotReload:true` also waits by default unless paired with `awaitHotReload:false`. Use `apply_wave_patch` only for grouped/multi-file work. Fast lane examples: \u201Ccall showDirection on Amy\u201D -> `code.direct_edit`; `cube.setColor(COLOR.RED)` plus \u201Cmake cube blue\u201D -> `code.semantic_guess_edit` with no local-SDK `query_wave_api` unless uncertain/failing. \u201CPlace cubes in a line\u201D writes new layout code, so it is `code.author`, and should prefer WaveEngine-native APIs such as `myScene.placeInline(...)` over manual coordinates.',
44454
44404
  "Code-edit hotreload safety: avoid raw unmanaged callback roots in authored .ts/.js files: no timers, RAF, listeners, Promise chains, observers, workers, sockets, channels, eventBus/myScene raw subscriptions, or raw event-handler property assignments. Use Wave-owned callbacks/Animate/tick/state/Director APIs. Edit tools preflight this rule and runtime bundling blocks violations before authored code runs.",
44455
44405
  "Asset-upload Operate loop: `create_wave_asset_upload` -> raw PUT with every returned header -> `get_wave_asset_upload_status` until receivedBytes matches -> `commit_wave_asset_upload` -> if the commit response is pending, poll `get_wave_command_result` -> category-first asset discovery (`find_wave_assets_by_category` or alias `list_wave_assets_by_category`) with the returned asset category before writing the ref into code. If upload is part of Author work, keep the route id; otherwise direct Operate is fine.",
44456
- "Project Operate loops: save with `save_wave_project`; share with `share_wave_project` and send returned `url`; list/read examples with `list_wave_projects` -> `read_wave_project`; rename saved project metadata with `list_wave_projects` -> `rename_wave_project`; open only when user wants workspace replacement and you have exact projectId from `list_wave_projects`; new project with `list_wave_project_templates` -> `new_wave_project`.",
44406
+ "Project Operate loops: save with `save_wave_project`; share with `share_wave_project` and send returned `url`; silently read shared/published links with `read_wave_project({ url })` without opening; list/read saved examples with `list_wave_projects` -> `read_wave_project({ projectId })`; rename saved project metadata with `list_wave_projects` -> `rename_wave_project`; open only when user wants workspace replacement and you have exact projectId from `list_wave_projects`; new project with `list_wave_project_templates` -> `new_wave_project`.",
44457
44407
  "Studio families: `studio.vfs` for files, `studio.assets` for uploads/library refs, `studio.project` for save/rename/open/new/share, `studio.preview` for hot reload/run/diagnostics, `studio.capture` for screenshot/snapshot, `studio.mcp` for session/pending commands/policy, `studio.export` for output workflows.",
44458
44408
  "Geometry skill routes: for soft custom forms such as a rounded bun, cushion, puffy/squishy toy, or organic rounded prop, route to `wave.geometry.sdf-surface`: create an SDF surface asset, compose recipe primitives, call `.apply()`, then bind the generated asset with `useModel(...)`.",
44459
44409
  "Surface skill routes: for roads, trails, highways, walkways, lanes, bridge decks, waterfalls, or other path-bound surfaces, route to `wave.geometry.surface-ribbons`: author a `wavePathSurface` with `.along(...)` or `.between(...)`, then compose material, collider, terrain attachment, center samples, and navigation on that surface as needed.",
44460
44410
  "World population route: for forests, grass, rocks, water, streamed entities, or environmental scatter tied to terrain/streaming surfaces, route to `wave.world.world-elements`: prefer `scene.world.scatter(...)` or bootstrap `world.scatter(...).renderAs(...).density(...).randomScale(...).apply()` before local placement, spawn loops, or instancing/batching.",
44461
44411
  "Obby/platform route: controlled humanoid/vehicle/flight players use `wave.physics.kinematic-controller-authoring`; static and moving platforms, sliding gates, sweepers, ferries, and hazards use `wave.physics.rigid-body-authoring` on geometry/props with static or kinematic rigid bodies, then transform/animate/current-code motion. Do not use `waveKinematicActor` for a platform unless it is itself player/controller-driven.",
44462
44412
  "Multiplicity skill route: for many local repeated model-backed objects, route to `wave.group.instancing-and-batching`: classify per-instance needs first. Use `waveThinBatch` only for visual-only mass, `waveInstanceMesh`/`InstanceMeshGroup`/`waveInstanceGroup` for selectable/interactive repeated instances, and real `Prop`/`Actor` entities for physics, AI, audio, damage state, or rich lifecycle. Count alone never chooses thin batch; terrain/world population is the world-elements route.",
44463
- "Model voxelization route: for voxelize/voxelized/volexize model requests, route to `wave.model.voxelization`. Use `source.model.voxelizing().relativeSize(0.05).surfaceOnly().onWorkerThread().usingCubes().asThinBatch().applyAsync()` only when async/worker authored code is explicitly acceptable. If code must stay synchronous, use `onMainThread().apply()` only for tiny local voxel work. Never use `.apply().then(...)` or Promise callback chains. Use `voxelBatch.detectNear(explorer).within(5)` for local proximity, `voxelBatch.batchTransform.getColorAt(index)` before highlight/restore, and `voxelBatch.whenIndexClicked(index => voxelBatch.atIndex(index).enlargeBy(1.2))` for per-index clicks. Do not use `voxelizeHeavy`, `voxelize({ voxelSize })`, `withVoxelSize`, or `sharedBox`.",
44413
+ "Model voxelization route: for voxelize/voxelized/volexize model requests, route to `wave.model.voxelization`. Use `source.model.voxelizing().relativeSize(0.05).surfaceOnly().onWorkerThread().usingCubes().asThinBatch().applyAsync()` only when async/worker authored code is explicitly acceptable. If code must stay synchronous, use `onMainThread().apply()` only for tiny local voxel work. Never use `.apply().then(...)` or Promise callback chains. Use `voxelBatch.detectNear(explorer).within(5)` for local proximity, `voxelBatch.batchTransform.getColorAt(index)` before highlight/restore, and `voxelBatch.whenIndexClicked(index => voxelBatch.at(index).enlargeBy(1.2).done().commitBuffers())` for per-index clicks. Do not use `voxelizeHeavy`, `voxelize({ voxelSize })`, `withVoxelSize`, `sharedBox`, or stale `atIndex`.",
44464
44414
  "VFS edits: primary tool is forgiving `edit_wave_file`; it infers exact-text, line-range, one-file `edits:[...]`, or whole-file replacement from arguments and tolerates common field aliases. Use `apply_wave_patch({ operations: [...] })` only for grouped/multi-file/strict diff work.",
44465
44415
  "VFS managed files: project.assetrefs.ts, project.scene.ts, project.scenes.ts, and project.execution.ts are Studio-managed read-only. 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 asset_manifest_or_loader, instrument_registry, scene_registry, or execution_manifest; Studio owns those paths.",
44466
44416
  "VFS hashes: simple edit tools auto-resolve the latest mirror `contentHash`; pass `baseHash` only when you already have it or when using advanced `apply_wave_patch`. Always inspect `changedFiles`, `changedPaths`, `partial`, and `skippedOperations` after edits.",
44467
44417
  "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.",
44468
- '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 Studio preview; do not put Mermaid in markdown fences unless user specifically wants markdown text.',
44418
+ '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.',
44469
44419
  '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. 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.',
44470
44420
  "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.",
44471
- "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 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.",
44421
+ "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.",
44472
44422
  "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.",
44473
- "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; use `requestHotReload: true` for fire-and-poll, or call `hot_reload_wave_preview` for standalone preview refresh. Standalone `run_wave_preview` / `hot_reload_wave_preview` can use `awaitRuntimeResult: true` for same-call bounded diagnostics. 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.",
44423
+ "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.",
44474
44424
  "Preview fallback: if an edit result says `hotReloadRequested: false`, the preview did not refresh; inspect `hotReloadSkippedReason`/skips, then call `hot_reload_wave_preview` or `run_wave_preview` only as appropriate. Use `run_wave_preview` only when diagnostics show no successful preview yet (`hasRunSucceeded: false`), to honor an explicit full-restart request, or as the last resort after hot reload/polling fails or gets stuck.",
44475
44425
  'Verification: never report completion immediately after edit, run, or hot reload. If a tool returns `status:"pending"` plus `requestId`, poll `get_wave_command_result`; otherwise continue to diagnostics. Poll diagnostics until `runtimeBusy` is false and `lastRuntimeOutcome` is `success` or `error`; ignore terminal outcomes older than the edit/runtime `requestedAt` or `runtimeActionRequestedAt`. `editorErrorCount > 0` means Monaco/linter/compile errors still block the code; read `editorDiagnostics` and do not report success.',
44476
44426
  'Observation: logs are history. If outcome is success, choose one relevant proof tool when needed: `capture_wave_screenshot({ resolution: "L" })` for visual changes (WaveEngine Agent SDK returns `localPath`; HTTP Gateway returns exact `dataBase64`, not `imageBase64`), `get_wave_runtime_entity_snapshot` for live transform/state, or `list_wave_runtime_markers` for clicked marker positions/rotations.',
@@ -44484,9 +44434,9 @@ var WAVE_MCP_AGENT_BRIEF = [
44484
44434
  // ../../src/lib/waveStudio/aiAssist/bridge/hosted/mcpResources/authoringGlobals.ts
44485
44435
  var WAVE_MCP_AUTHORING_GLOBALS_GUIDE = [
44486
44436
  "Wave Studio bare authoring globals, common examples only:",
44487
- "- This guide is a compact memory aid, not an exhaustive list. Engine authoring globals come from the generated `waveStudio-globals.d.ts` surface indexed by `query_wave_api`; Studio wrapper conveniences such as `waveStudio`, `waveEngine`, and live asset overlays are documented by MCP guardrails/tools and the current session asset/file tools.",
44437
+ "- This guide is a compact memory aid, not an exhaustive list. Engine authoring globals come from the generated `waveStudio-globals.d.ts` surface indexed by local-SDK `query_wave_api`; Studio wrapper conveniences such as `waveStudio`, `waveEngine`, and live asset overlays are documented by MCP guardrails/tools and the current session asset/file tools.",
44488
44438
  "- Runtime values injected into Studio-authored `main.ts` files should be used bare. Do not import them and do not qualify them with guessed namespaces. Query when unsure.",
44489
- "- Intent/loop/time values: `Apply`, `Animate`, `Snapshot`, `Repeat`, `ToTrue`, `ToFalse`, `Flips`, `FirstTime`, `EveryTime`, `PerSecond`, `PerTick`, `Ticks`, `Seconds`, `UnitsPerSecond`, `DegreesPerSecond`.",
44439
+ "- Intent/loop/time values: `Animate`, `Snapshot`, `Repeat`, `ToTrue`, `ToFalse`, `Flips`, `FirstTime`, `EveryTime`, `PerSecond`, `PerTick`, `Ticks`, `Seconds`, `UnitsPerSecond`, `DegreesPerSecond`. For immediate transform/property changes, omit the mode argument; `Apply` is internal transform plumbing, not a public authoring token.",
44490
44440
  "- Direction and input enum-style globals: `Direction.X/Y/Z`, `Direction.Left/Right/Up/Down/Forward/Backward`, `Keyboard`, `MouseButton`, `GamepadButton`, `InputPhase`, `MovementMode`, `RotationMode`.",
44491
44441
  "- Colors/materials/fx helpers: `COLOR`, `PALETTE`, `waveCOLOR`, `waveMaterial`, `shaderUniform`, `waveFx`, `waveFxPresets`, `FxAnchor`, `FxCondition`.",
44492
44442
  "- Controller movement helpers: `waveKinematicActor`, `netKinematicActor`, `KinematicHumanoidMovementState`, `KinematicVehicleMovementState`, and `KinematicFlightMovementState`. Use actor-level `.asHumanoid(...)`, `.asVehicle(...)`, or `.asFlight(...)` for player/controller movement.",
@@ -44494,8 +44444,8 @@ var WAVE_MCP_AUTHORING_GLOBALS_GUIDE = [
44494
44444
  "- Scene/runtime handles: prefer `myScene` for scene composition and `waveStudio` for Studio operations. `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.",
44495
44445
  "- Authoring systems/presets: `waveEventBus`, `waveRig`, `waveValueCurve`, `waveValueCurvePresets`, `waveMotionSignal`, `waveParam`, `WaveParam`, `WaveChoice`, `prefabModels`, `effectPrefabs`, and prefab helpers such as `rocketPrefab`.",
44496
44446
  "- Lowercase constructors: `prop`, `marker`, `sphere`, `point`, `cube`, `box`, `cylinder`, `capsule`, `cone`, `torus`, `plane`, `ground`, `line`, `arc`, `path`, and related shape helpers.",
44497
- "- Type names are not import paths. If the handbook shows a type like `TransformVerbMode` or `WaveRateUnit`, look for the matching bare runtime value such as `Animate` or `DegreesPerSecond` before writing code.",
44498
- '- If you are unsure whether an engine global exists, query it first, for example `query_wave_api({ query: "DegreesPerSecond" })`, `query_wave_api({ query: "waveMaterial createWater" })`, or `query_wave_api({ query: "Keyboard enum" })`. For asset refs, use `find_wave_assets_by_category` instead of guessing property names.',
44447
+ "- Type names are not import paths. If the handbook shows a type like `TransformVerbMode` or `WaveRateUnit`, look for the matching bare runtime value such as `Animate` or `DegreesPerSecond` before writing code. Transform `Snapshot` calls return a snapshot builder; call `.take()` before passing the pose to `transitionTo(...)`.",
44448
+ '- If you are unsure whether an engine global exists, query it first on the local SDK endpoint, for example `query_wave_api({ query: "DegreesPerSecond" })`, `query_wave_api({ query: "waveMaterial createWater" })`, or `query_wave_api({ query: "Keyboard enum" })`. HTTP Gateway hides/retires skill/API lookup. For asset refs, use `find_wave_assets_by_category` instead of guessing property names.',
44499
44449
  "- Good pattern: `cube.keepRotatingAround(Direction.Right).atRateOf(70, DegreesPerSecond).for(50, Seconds).play()`."
44500
44450
  ].join("\n");
44501
44451
 
@@ -44505,7 +44455,7 @@ var WAVE_MCP_CODING_GUARDRAIL = [
44505
44455
  "1. Author user code for Wave Studio runtime, not engine internals. Do not use sys_*, BaseEngine internals, private fields, underscored members, worker/adapter/debug/store/cache APIs, or generated implementation details.",
44506
44456
  "2. Prefer public natural names. Use `Prop`, `Actor`, `Cube`, `Sphere`, etc. instead of `waveProp`, `waveActor`, `waveCube`, `waveSphere` when aliases exist. Drop the `wave` prefix in authored examples.",
44507
44457
  "2a. MCP access policy is set by the user in chat. If the user says read-only, inspect only and avoid mutating tools. If no write intent is given, inspect first. If the user says read-write or asks you to edit, run, upload, save, open, create, rename, or delete, use the write tools needed for that task.",
44508
- '2b. MCP is an agent behavior harness with MECE work modes. Observe = read/inspect/answer only; call read tools directly (session, files, assets, diagnostics, performance, screenshot, snapshots, markers). Operate = direct Studio command with no code/design choice; call concrete tools directly without `start_wave_task` for run preview, hot reload, save/share, exact VFS create/rename/delete, asset upload/rename/delete, new project, project rename, and open project by exact projectId. Author = create/change behavior/content through code/API; call `start_wave_task`, gather evidence, optionally fast-start execute with `nextPhase:"execute"` plus editPlan, then edit. Exact one-file line/text edits can call `edit_wave_file` immediately after route start when exact path and replacement args are present, including `edits:[{startLine,endLine,text}]`; no advance call needed. Diagnose = find root cause first; observe/read first, then transition to Operate or Author when cause and action are clear. General = not concrete Wave work; classify `agent.general`. `query_wave_api`, `edit_wave_file`, `apply_wave_patch`, code.direct_edit, code.semantic_guess_edit, and code.author are route-bound Author/Diagnose work. Direct Operate still keeps safety: exact path/id/path target required for delete/rename/open; resolve project names with `list_wave_projects`, resolve vague file/asset names with list/read tools or ask. If an edit adds code, creates objects, switches API, or chooses a WaveEngine pattern such as placement/layout/material/animation, it is `code.author`, not semantic guess. Fast lanes skip broad lookup, not file safety/verification, and usually skip `query_wave_api` unless exact spelling/signature/value uncertainty remains or an edit failed.',
44458
+ '2b. MCP is an agent behavior harness with MECE work modes. Observe = read/inspect/answer only; call read tools directly (session, files, assets, diagnostics, performance, screenshot, snapshots, markers). Operate = direct Studio command with no code/design choice; call concrete tools directly without `start_wave_task` for run preview, hot reload, save/share, exact VFS create/rename/delete, asset upload/rename/delete, new project, project rename, and open project by exact projectId. Author = create/change Wave behavior/content through code/API; call `start_wave_task`, gather evidence, optionally fast-start execute with `nextPhase:"execute"` plus editPlan, then edit. Exact one-file line/text edits can call `edit_wave_file` immediately after route start when exact path and replacement args are present, including `edits:[{startLine,endLine,text}]`; no advance call needed. Diagnose = find root cause first; observe/read first, then transition to Operate or Author when cause and action are clear. General = not concrete Wave work; classify `agent.general`. Local-SDK `query_wave_api`, `edit_wave_file`, `apply_wave_patch`, code.direct_edit, code.semantic_guess_edit, and code.author are route-bound Author/Diagnose work. Direct Operate still keeps safety: exact path/id/path target required for delete/rename/open; resolve project names with `list_wave_projects`, resolve vague file/asset names with list/read tools or ask. If an edit adds code, creates objects, switches API, or chooses a WaveEngine pattern such as placement/layout/material/animation, it is `code.author`, not semantic guess. Fast lanes skip broad lookup, not file safety/verification, and usually skip local-SDK `query_wave_api` unless exact spelling/signature/value uncertainty remains or an edit failed.',
44509
44459
  '2c. Use `code.debug` alone only for diagnose/report-only tasks. For "fix this" or "make the error go away", include both `code.debug` and `code.author` so the same route can diagnose root cause and then edit code.',
44510
44460
  `2d. ${WAVE_AUTHORING_CORE_RULES.hotReloadCallbackSafety} The MCP edit tools preflight this rule and the runtime bundler blocks violations before authored code runs. Rewrite to Wave-owned callbacks instead of attempting to bypass the guard.`,
44511
44461
  "3. Wave Studio also injects lowercase call-style helpers such as `prop(...)`, `cube(...)`, `sphere(...)`, `ground(...)`. These are Studio-only authoring conveniences, not wave-engine package exports.",
@@ -44515,7 +44465,7 @@ var WAVE_MCP_CODING_GUARDRAIL = [
44515
44465
  '4c. For roads, trails, highways, walkways, lanes, bridge decks, waterfalls, or cloth/path strips, route to `wave.geometry.surface-ribbons`: author a live visible `wavePathSurface` with `.along(...)` for centerline+width or `.between(...)` for two rails, then use its methods such as `.snapTo(...)`, `.heightAboveSurface(...)`, `.withDistanceUvs(...)`, and `.withSampleSpacing(...)`. For streaming terrain elements, author a pure spec with `new WavePathSurfaceDefinition("name").along(...)` or `.between(...)` and pass it to `world.surface(name).from(surface)` or `world.water(name).course(surface).depth(...)`; streamed water courses require `.depth(...)`. Do not fake continuous roads by scattering planes/cubes or generating raw mesh buffers when `wavePathSurface` fits.',
44516
44466
  "4d. For terrain/world population such as forests, grass, rocks, water, streamed entities, or environmental scatter tied to terrain/streaming surfaces, route to `wave.world.world-elements`: use `scene.world.scatter(...)`/`myScene.world.scatter(...)` for live scene code or `world.scatter(...)` inside `scene.withWorldStreaming(...)` for bootstrap streaming declarations. Prefer fluent verbs like `.renderAs(...)`, `.density(...)`, `.randomScale(...)`, `.colors(...)`, `.linkedTo(...)`, `.usePartitionedLOD(...)`, `.distanceBands(...)`, `.lodModels(...)`, then `.apply()`. Do not hand-roll spawn loops or use local instancing/batching when declarative world scatter fits.",
44517
44467
  '4e. For many local repeated model-backed objects such as a fleet, crowd, stars, decorations, or "1000 spaceships", route to `wave.group.instancing-and-batching` and classify per-instance needs before constructors. Use `waveThinBatch` only for visual-only mass sharing one mesh with per-instance transform/color/GPU animation. Use `waveInstanceMesh`, `InstanceMeshGroup`, or scene `waveInstanceGroup` when each copy needs picking, click/hover interaction, labels/tool overlays, visibility toggles, selection, or individual identity. Use real `Prop`/`Actor` entities when each copy needs rigid bodies, gravity, audio, AI, weapons, damage state, independent lifecycle, or rich behavior. Count alone never chooses thin batch; mixed hero/background intent should use a hybrid.',
44518
- '4e1. For visual-model voxelization, route to `wave.model.voxelization`. Prefer `source.model.voxelizing().relativeSize(0.05).surfaceOnly().onWorkerThread().usingCubes().asThinBatch().applyAsync()` only when async/worker authored code is explicitly acceptable; otherwise use synchronous `onMainThread().apply()` only for tiny local voxel work where blocking is acceptable. Never use Promise chains such as `.apply().then(...)` in authored Studio code because hot-reload safety rejects `.then/.catch/.finally`. Use `relativeSize(ratio)` for model-scale-independent voxel size, `size(value)` only for absolute world units, `usingCubes()`/`usingSpheres()`/`usingCylinders()`/`usingCapsules()` for shape, and the one-shot `voxelize({ size: { mode: "relative", ratio: 0.05, basis: "longestAabbEdge" }, execution: "workerThread", shape: "cube", surfaceOnly: true })` only for serializable recipe code. For thin-batch voxel interactions, use `detectNear(target).within(radius)`, `batchTransform.getColorAt(index)` before color restore, `whenIndexClicked(index => voxelBatch.atIndex(index).enlargeBy(1.2))`, and `castToProp(index); prop.enablePhysics()` only when a full prop is needed. Do not use removed `voxelizeHeavy`, `voxelize({ voxelSize })`, `withVoxelSize`, `sharedBox`, or low-level worker/adapter internals in authored scene code.',
44468
+ '4e1. For visual-model voxelization, route to `wave.model.voxelization`. Prefer `source.model.voxelizing().relativeSize(0.05).surfaceOnly().onWorkerThread().usingCubes().asThinBatch().applyAsync()` only when async/worker authored code is explicitly acceptable; otherwise use synchronous `onMainThread().apply()` only for tiny local voxel work where blocking is acceptable. Never use Promise chains such as `.apply().then(...)` in authored Studio code because hot-reload safety rejects `.then/.catch/.finally`. Use `relativeSize(ratio)` for model-scale-independent voxel size, `size(value)` only for absolute world units, `usingCubes()`/`usingSpheres()`/`usingCylinders()`/`usingCapsules()` for shape, and the one-shot `voxelize({ size: { mode: "relative", ratio: 0.05, basis: "longestAabbEdge" }, execution: "workerThread", shape: "cube", surfaceOnly: true })` only for serializable recipe code. For thin-batch voxel interactions, use `detectNear(target).within(radius)`, `batchTransform.getColorAt(index)` before color restore, `whenIndexClicked(index => voxelBatch.at(index).enlargeBy(1.2).done().commitBuffers())`, and `castToProp(index); prop.enablePhysics()` only when a full prop is needed. Do not use removed `voxelizeHeavy`, `voxelize({ voxelSize })`, `withVoxelSize`, `sharedBox`, `atIndex`, or low-level worker/adapter internals in authored scene code.',
44519
44469
  "4f. For player/controller movement, route to `wave.physics.kinematic-controller-authoring`: use `waveKinematicActor<TState>` or `netKinematicActor` and actor-level `.asHumanoid(...)`, `.asVehicle(...)`, or `.asFlight(...)` builders. Do not start from `Actor`/`waveActor`, raw input polling, rigid-body forces, per-tick movement loops, or direct `movementController.useFlightScheme(...)` unless the user explicitly asks for low-level component tuning or nearby working code already uses that component-level pattern.",
44520
44470
  "4f1. For basic public humanoid locomotion animation, follow the kinematic-obby pattern: `new waveKinematicActor<KinematicHumanoidMovementState>().useModel(models.wave3dFemale)`, then `.asHumanoid({ baseSpeed, jumpForce }).useIdleAnimation(animations.Idle).useWalkingAnimation(animations.Walking).useJumpAnimation(animations.Jump).apply()`. Do not use `animator.addLocalAnimations()`, `getClipNames()`, or `resolveClipName(...)` as the first-choice setup when public `animations.*` refs fit.",
44521
44471
  "4g. For obbies/course obstacles, split the intent: the controlled player uses `wave.physics.kinematic-controller-authoring`; static platforms, moving platforms, sliding gates, sweepers, ferries, and hazards use `wave.physics.rigid-body-authoring` on geometry/props with static or kinematic rigid bodies, then transform/animate/current-code motion. Do not use `waveKinematicActor` for a platform unless it is itself player/controller-driven.",
@@ -44524,19 +44474,19 @@ var WAVE_MCP_CODING_GUARDRAIL = [
44524
44474
  `4j. ${WAVE_AUTHORING_CORE_RULES.terrainGroundRouting}`,
44525
44475
  "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.",
44526
44476
  `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.`,
44527
- `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 \`query_wave_api\` before inventing namespace-qualified paths such as \`TransformVerbMode.Animate\` in authored code.`,
44528
- "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 skill or API lookup. Do not use `assetManager` as the default material, asset-ref, or path-surface authoring root.",
44477
+ `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.`,
44478
+ "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.",
44529
44479
  '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.',
44530
44480
  "7a. Use `list_wave_explorer_assets` when you need uploaded asset explorer metadata such as path, URL, size, or display/ref name for rename/delete/library work. It is not a fallback for built-in/public code refs and may be empty while `find_wave_assets_by_category` has many usable refs.",
44531
44481
  "8. Wave Studio automations: `project.assetrefs.ts`, `project.scene.ts`, `project.scenes.ts`, and `project.execution.ts` are automatically managed by Wave Studio and are MCP read-only for agents. `bootstrap.ts` / scene `*/bootstrap.ts` is normally managed too. Edit bootstrap only when you can confidently pass `managedFileEditReason` as one of: `world_streaming_or_terrain_provider` (including Google Maps 3D tiles), `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_manifest_or_loader`, `instrument_registry`, `scene_registry`, or `execution_manifest`; Studio owns those. Do not edit managed files to register/preload assets, wire scenes, execution order, or force bootstrap sync; write user-authored scene code in `main.ts` or feature modules with bare refs like `models.Robot` or `textures.Grass`, then let Studio sync bootstrap/asset/scene/execution wiring. Hot reload is the normal way to see code changes. If the hot-reload path discovers new asset/bootstrap/scene-surface needs, Studio automatically upgrades the reload tier internally (`patchMain`, `preserveScene`, or hard `rebuildScene`). Only the hard rebuild tier performs a full bundled scene run.",
44532
44482
  "9. Use `waveStudio.*` only for Studio host services. Check `waveStudio.capabilities.assetSave` before save/bake calls.",
44533
- '10. Make deterministic file edits through the simplest fitting tool. Default to forgiving `edit_wave_file`: oldText infers exact replace, startLine/endLine infers line replace, `edits:[{startLine,endLine,text}]` or `edits:[{rangeOffset,rangeLength,text}]` performs one-file multi-edit, and path+text/content with no oldText infers whole-file replace. It is the primary simple edit tool and can omit `baseHash`; Studio resolves the latest hosted VFS mirror contentHash and still applies browser-side stale-write checks. Prefer canonical fields: `path` for file path, `text` for line/whole-file content, and `newText` for text replacement; `filePath`, `replacement`, and `content` are accepted as aliases where useful. Use `apply_wave_patch({ operations: [...] })` for multi-file edits, grouped cross-file edits, unified diffs, or full rewrites; a single bare operation is tolerated for mistake recovery but operations:[...] is preferred. Use `create_wave_file`, `rename_wave_file`, and `delete_wave_file` to split projects into `.ts` modules such as `/actors/player.ts`, `/systems/obstacles.ts`, and `/levels/obby.ts` instead of growing one giant `main.ts`; newly created `.ts/.tsx` files are standalone 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. These same VFS tools also create `.html` sketch files for diagrams/charts/docs, with Mermaid rendered from `<div class="mermaid">...</div>` when the HTML file is active in Studio preview. Scene-root modules and their owned helpers run inside the Studio authoring context, but helpers should stay pure or parameterized. Studio hot reload targets the active/open edited file when safe: `/main.ts` reloads the whole main graph, scene-root modules reload that root, and bootstrap/scene registry/assets/network/ambiguous helper surfaces escalate. Standalone `hot_reload_wave_preview` has no target path and follows the currently open/active Studio editor file in multi-file projects. A feature file should own the objects, callbacks, promoted GLB parts, and appearance mutations it wants to iterate on. For intentional live entity reuse across modules, the owner calls `waveStudio.exportEntity("Name", entity)` and importers call `waveStudio.importEntity<T>("Name")`; do not pass live entities through shared helper exports. Use exact VFS paths from `list_wave_files`; read target file before writing. `contentHash` is a cooperative stale-write fingerprint, not a security boundary. For advanced compact `apply_wave_patch` operations, pass the latest full-file `contentHash` as `baseHash`: one `lineEdits`, one `textEdits`, one strict `searchReplace`, or one `unifiedDiff`. Do not send multiple compact ops for the same file with the same baseHash; the first edit changes the file hash and later compact ops skip as stale. Scoped `read_wave_file` line ranges do not change the `textEdits` offset base; they do pair naturally with line-based edits. Existing-file `writeFile` requires `baseHash` unless `forceOverwrite: true`; force overwrite is only for intentional stale overwrites.',
44483
+ '10. Make deterministic file edits through the simplest fitting tool. Default to forgiving `edit_wave_file`: oldText infers exact replace, startLine/endLine infers line replace, `edits:[{startLine,endLine,text}]` or `edits:[{rangeOffset,rangeLength,text}]` performs one-file multi-edit, and path+text/content with no oldText infers whole-file replace. It is the primary simple edit tool and can omit `baseHash`; Studio resolves the latest hosted VFS mirror contentHash and still applies browser-side stale-write checks. Prefer canonical fields: `path` for file path, `text` for line/whole-file content, and `newText` for text replacement; `filePath`, `replacement`, and `content` are accepted as aliases where useful. Use `apply_wave_patch({ operations: [...] })` for multi-file edits, grouped cross-file edits, unified diffs, or full rewrites; a single bare operation is tolerated for mistake recovery but operations:[...] is preferred. Use `create_wave_file`, `rename_wave_file`, and `delete_wave_file` to split projects into `.ts` modules such as `/actors/player.ts`, `/systems/obstacles.ts`, and `/levels/obby.ts` instead of growing one giant `main.ts`; newly created `.ts/.tsx` files are standalone 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. These same VFS tools also create `.html` sketch files for diagrams/charts/docs, with Mermaid rendered from `<div class="mermaid">...</div>` when the HTML file is active in the editor/coding pane; HTML sketches must never replace the live engine preview iframe. Scene-root modules and their owned helpers run inside the Studio authoring context, but helpers should stay pure or parameterized. Studio hot reload targets the active/open edited file when safe: `/main.ts` reloads the whole main graph, scene-root modules reload that root, and bootstrap/scene registry/assets/network/ambiguous helper surfaces escalate. Standalone `hot_reload_wave_preview` has no target path and follows the currently open/active Studio editor file in multi-file projects. A feature file should own the objects, callbacks, promoted GLB parts, and appearance mutations it wants to iterate on. For intentional live entity reuse across modules, the owner calls `waveStudio.exportEntity("Name", entity)` and importers call `waveStudio.importEntity<T>("Name")`; do not pass live entities through shared helper exports. Use exact VFS paths from `list_wave_files`; read target file before writing. `contentHash` is a cooperative stale-write fingerprint, not a security boundary. For advanced compact `apply_wave_patch` operations, pass the latest full-file `contentHash` as `baseHash`: one `lineEdits`, one `textEdits`, one strict `searchReplace`, or one `unifiedDiff`. Do not send multiple compact ops for the same file with the same baseHash; the first edit changes the file hash and later compact ops skip as stale. Scoped `read_wave_file` line ranges do not change the `textEdits` offset base; they do pair naturally with line-based edits. Existing-file `writeFile` requires `baseHash` unless `forceOverwrite: true`; force overwrite is only for intentional stale overwrites.',
44534
44484
  "10a. Always inspect `changedFiles`, `changedPaths`, `partial`, `skippedOperations`, `hotReloadRequested`, `hotReloadSkippedReason`, and `runtimeVerification`; treat skipped operations, no-content-change skips, unscheduled hot reloads, runtime verification errors, and `runtimeVerification.diagnostics.editorErrorCount > 0` as work still needing attention.",
44535
- "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. Use `requestHotReload: true` for fire-and-poll, or call `hot_reload_wave_preview` as a standalone refresh; pass `awaitRuntimeResult: true` on standalone run/hot reload when you want same-call bounded diagnostics. 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. 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.",
44536
- '12. After run/hot reload, use returned `runtimeVerification` when `awaitHotReload: true` or `awaitRuntimeResult: true`; 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`.',
44485
+ "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. 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.",
44486
+ '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`.',
44537
44487
  "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.",
44538
44488
  `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.`,
44539
- "14. Project tools: use `list_wave_project_templates` before `new_wave_project({ templateId? })`; use `list_wave_projects` before `read_wave_project({ projectId })`, `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. 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.",
44489
+ "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.",
44540
44490
  "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.",
44541
44491
  "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.",
44542
44492
  "17. `rename_wave_asset` changes the uploaded asset display/ref name only; it does not move the stored blob path. Re-list assets before writing code with the new ref.",
@@ -44549,11 +44499,11 @@ var WAVE_MCP_CODING_GUARDRAIL_SUMMARY = [
44549
44499
  "Wave Studio MCP compact guardrails:",
44550
44500
  "1. Author WaveStudio user code only; avoid engine internals, private fields, generated implementation details, and low-level sys_/worker/store APIs.",
44551
44501
  "2. Use exact listed MCP tool names only. `studio.*` names are families, not tools. There is no `get_wave_current_project`; use `get_wave_session` for current project/session/active-file context.",
44552
- "3. Choose MECE work mode before tools: Observe reads directly; Operate direct Studio commands directly; Author/Diagnose route with `start_wave_task`; General avoids Wave tools. Operate examples: run project -> `run_wave_preview`, hot reload/refresh preview -> `hot_reload_wave_preview`, save/persist -> `save_wave_project`, rename saved project -> `rename_wave_project`, exact file create/delete/rename -> VFS operation, marker/FPS/screenshot reads -> Observe tools. Author examples: make/change/fix behavior, choose APIs, add scene objects, or edit existing code -> route, read context, skill/API lookup only as needed, advance, edit, verify. Diagnose-only uses `code.debug`; bug-fix uses `code.debug` plus `code.author`. Direct Operate exact-target rule: never invent paths, asset paths, or project ids; list/read/ask first.",
44502
+ "3. Choose MECE work mode before tools: Observe reads directly; Operate direct Studio commands directly; Author/Diagnose route with `start_wave_task`; General avoids Wave tools. Operate examples: run project -> `run_wave_preview`, hot reload/refresh preview -> `hot_reload_wave_preview`, save/persist -> `save_wave_project`, rename saved project -> `rename_wave_project`, exact file create/delete/rename -> VFS operation, marker/FPS/screenshot reads -> Observe tools. Author examples: make/change/fix behavior, choose APIs, add scene objects, or edit existing code -> route, read context, local SDK skill/API lookup only as needed, advance, edit, verify. Diagnose-only uses `code.debug`; bug-fix uses `code.debug` plus `code.author`. Direct Operate exact-target rule: never invent paths, asset paths, or project ids; list/read/ask first.",
44553
44503
  "3a. If the request is irrelevant or too broad for one concrete Wave milestone, classify `agent.general`, do not force Wave tools, and politely guide the user back to a scoped project/code/asset/debug/runtime/visual task.",
44554
44504
  "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.",
44555
44505
  `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.`,
44556
- "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(...enlargeBy(1.2))` for thin-batch voxel interaction. Do not use `voxelizeHeavy`, `voxelize({ voxelSize })`, `withVoxelSize`, or `sharedBox`.",
44506
+ "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`.",
44557
44507
  "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.",
44558
44508
  "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.",
44559
44509
  "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.",
@@ -44595,7 +44545,7 @@ var WAVE_MCP_EDIT_RECIPES = [
44595
44545
  "Large rewrite or generated module:",
44596
44546
  '- Existing file: `apply_wave_patch({ operations: [{ type: "writeFile", path, baseHash, content }] })` if you have the latest hash; use `forceOverwrite: true` only for intentional stale overwrite.',
44597
44547
  '- New runnable scene file: `create_wave_file({ path: "/systems/name.ts", content, awaitHotReload: true })`. New `.ts/.tsx` files are standalone runnable source roots by default, so top-level scene code in them runs on Run/hot reload without editing `project.execution.ts`. Pass `runnable:false` only for pure helper modules; then import helper functions normally from a runnable scene file.',
44598
- '- HTML sketch file: `create_wave_file({ path: "/docs/diagram.html", content })` for diagrams/charts/lightweight docs. For Mermaid, put source in `<div class="mermaid">...</div>`; Studio preview renders active `.html` files and auto-loads Mermaid when `class="mermaid"` is present.',
44548
+ '- HTML sketch file: `create_wave_file({ path: "/docs/diagram.html", content })` for diagrams/charts/lightweight docs. For Mermaid, put source in `<div class="mermaid">...</div>`; the editor/coding pane renders active `.html` files and auto-loads Mermaid when `class="mermaid"` is present. HTML sketches must never replace the live engine preview iframe.',
44599
44549
  "",
44600
44550
  "Preview verification:",
44601
44551
  "- Default after code changes: hot reload. Let Studio choose the internal reload tier. Use `run_wave_preview` only for first start/full restart or as last resort when hot reload does not complete correctly.",
@@ -44626,17 +44576,17 @@ var WAVE_MCP_FILE_CONTEXT_GUIDE = [
44626
44576
  "- Normal scene edit path: use the active `*/main.ts`, write against `myScene`, use bare asset refs, and do not edit Studio-managed generated files.",
44627
44577
  "- 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.",
44628
44578
  "- `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`.",
44629
- `- 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 \`query_wave_api\` for the complete generated authoring surface.`,
44579
+ `- 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.`,
44630
44580
  "- 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.",
44631
- '- 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, Studio preview renders it as an HTML sketch and auto-loads Mermaid if `class="mermaid"` is present.',
44581
+ '- 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.',
44632
44582
  "- `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.",
44633
44583
  "- Main-file asset refs should be bare: `models.Car`, `gaussianSplats.Room`, `textures.Grass`, `materials.Metal`, `animations.Idle`. Omit `ASSET_WAREHOUSE.` for authored code.",
44634
- "- 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 skill or API lookup, not the default place to invent new material or asset code.",
44584
+ "- 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.",
44635
44585
  "- 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.",
44636
44586
  "- 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.",
44637
44587
  '- Wave Studio auto-binds top-level VFS entity variables to runtime refs during run/hot reload. Use `get_wave_runtime_entity_snapshot({ variableName: "amy", filePath?: "/main.ts" })` to query live transform data; if ambiguous, retry with a returned `runtimeRef`.',
44638
44588
  "- Use `create_wave_asset_upload` for generated local asset files when available, upload bytes with plain HTTP PUT to the returned `uploadUrl` using every `uploadHeaders` entry exactly, keep `clientToken`/`Authorization` out of logs, verify `receivedBytes` with `get_wave_asset_upload_status`, then `commit_wave_asset_upload` with the create response metadata and use the returned bare ref like `textures.Albedo`, `cubeMaps.Studio`, `materials.Wood`, `audios.Click`, or `models.Robot` in code. If direct upload is unavailable, use `stage_wave_asset_upload_chunk` plus `commit_wave_asset_chunk_upload`: omit uploadId only on chunkIndex 0, then reuse the returned uploadId for all later chunks and commit. Use `upload_wave_asset` only for small inline base64/data URL assets. Call `abort_wave_asset_upload` only if a staged upload will not be committed. Existing names are idempotent and return `skipped: true`.",
44639
- "- Use `list_wave_project_templates()` then `new_wave_project({ templateId?, discardUnsavedChanges? })` to start a new unsaved workspace from a template. Use `list_wave_projects()` then `read_wave_project({ projectId })` to inspect bridge-readable project code without opening it, `rename_wave_project({ projectId, name })` to update saved project display metadata, or `open_wave_project({ projectId, discardUnsavedChanges? })` to replace the live workspace. If the user gives a project name, resolve the exact projectId with `list_wave_projects`; do not pass guessed names as ids. New/open replace the live workspace; save first when needed. If dirty, these tools fail with `unsaved_changes` unless discard is explicit.",
44589
+ "- Use `list_wave_project_templates()` then `new_wave_project({ templateId?, discardUnsavedChanges? })` to start a new unsaved workspace from a template. Use `read_wave_project({ url })` to silently inspect shared/published links without opening them; this supports old/new shared links and old/new published links. Use `list_wave_projects()` then `read_wave_project({ projectId })` to inspect listed project code without opening it, `rename_wave_project({ projectId, name })` to update saved project display metadata, or `open_wave_project({ projectId, discardUnsavedChanges? })` to replace the live workspace. If the user gives a project name, resolve the exact projectId with `list_wave_projects`; do not pass guessed names as ids. New/open replace the live workspace; save first when needed. If dirty, these tools fail with `unsaved_changes` unless discard is explicit.",
44640
44590
  "- Use `save_wave_project({ name?, description? })` to persist the live project. Existing saved projects quick-save with current metadata. New projects use provided metadata or generated defaults.",
44641
44591
  "- Use `share_wave_project()` to create a 30-day share link for the current live project through the same Share Project menu pipeline, then return the `url` to the user.",
44642
44592
  "- Use `list_wave_explorer_assets` to inspect the uploaded asset explorer library with paths, URLs, display names, and ref keys. `rename_wave_asset` changes the display/ref name only; it does not move the stored blob path.",
@@ -44651,7 +44601,7 @@ var WAVE_MCP_STUDIO_SKILL_MAP_GUIDE = [
44651
44601
  "Core rule: skills are the map; MCP tools are the buttons. `studio.vfs`, `studio.assets`, and friends are not callable tool names. Choose a `studio.*` family to narrow intent, then call the concrete MCP tool listed under it.",
44652
44602
  "",
44653
44603
  "Namespace split:",
44654
- "- `wave.*`: WaveEngine code-authoring knowledge: families, skill cards, public authoring objects, one-shot calls, fluent builders, callbacks, globals, and scene APIs. Use `code.direct_edit` for exact power-user code commands, `code.semantic_guess_edit` only for changing an existing visible API call/argument/literal/value, and `list_wave_skill_families` -> selected family ids -> `query_wave_skills({ families/familyId, query })` -> `get_wave_skill` for normal uncertain authoring direction; use local-SDK `query_wave_api` for exact symbols/signatures/globals after direction is known. HTTP Gateway hides/retires cloud API lookup.",
44604
+ "- `wave.*`: WaveEngine code-authoring knowledge: families, skill cards, public authoring objects, one-shot calls, fluent builders, callbacks, globals, and scene APIs. Use `code.direct_edit` for exact power-user code commands, `code.semantic_guess_edit` only for changing an existing visible API call/argument/literal/value, and local-SDK `list_wave_skill_families` -> selected family ids -> `query_wave_skills({ families/familyId, query })` -> `get_wave_skill` for normal uncertain authoring direction; use local-SDK `query_wave_api` for exact symbols/signatures/globals after direction is known. HTTP Gateway hides/retires cloud skill/API lookup.",
44655
44605
  "- `studio.*`: WaveStudio product operations around that code: sessions, VFS, assets, project state, preview, capture, export, and MCP policy.",
44656
44606
  "- Work modes: Observe reads directly, Operate calls concrete Studio commands directly, Author/Diagnose routes through `start_wave_task`, General avoids Wave tools. Direct Operate still requires exact paths/asset paths/project ids for destructive or replacing actions.",
44657
44607
  "",
@@ -44666,8 +44616,8 @@ var WAVE_MCP_STUDIO_SKILL_MAP_GUIDE = [
44666
44616
  "",
44667
44617
  "Common mixed workflow:",
44668
44618
  "1. Use `studio.vfs` tools to read/edit code.",
44669
- "2. For exact receiver/method/action commands, use `code.direct_edit`. For changing an existing visible call/value only, use `code.semantic_guess_edit`. For unseen, ambiguous, new-code, API-switching, layout/placement/material/animation, or cross-family work, use `code.author` plus `list_wave_skill_families` -> choose families -> `query_wave_skills({ families/familyId, query })` -> `get_wave_skill`. Never raw-query the skill corpus with the full user request.",
44670
- "3. Use local-SDK `query_wave_api` only after current-code or skill routing when exact method/global/API facts are uncertain. HTTP Gateway is not an API lookup path.",
44619
+ "2. For exact receiver/method/action commands, use `code.direct_edit`. For changing an existing visible call/value only, use `code.semantic_guess_edit`. For unseen, ambiguous, new-code, API-switching, layout/placement/material/animation, or cross-family work, use `code.author` plus local-SDK `list_wave_skill_families` -> choose families -> `query_wave_skills({ families/familyId, query })` -> `get_wave_skill`. Never raw-query the skill corpus with the full user request.",
44620
+ "3. Use local-SDK `query_wave_api` only after current-code or skill routing when exact method/global/API facts are uncertain. HTTP Gateway is not a skill/API lookup path.",
44671
44621
  "4. Use `studio.assets` to resolve exact refs before writing `models.X`, `textures.X`, `materials.X`, `audios.X`, or other asset-map inputs that are not already visible in current code.",
44672
44622
  "5. Use `studio.preview` to hot reload by default.",
44673
44623
  "6. Use `studio.capture` to prove the result with one relevant tool: an `L` screenshot for visual changes, runtime entity snapshot for live transform/state, or `list_wave_runtime_markers` for clickToMark/world marker poses.",
@@ -44679,23 +44629,23 @@ var WAVE_MCP_STUDIO_SKILL_MAP_GUIDE = [
44679
44629
  var WAVE_MCP_STUDIO_TOOL_GUIDE = [
44680
44630
  "Wave Studio runtime and MCP tool guide:",
44681
44631
  "- First choose a `studio.*` family for product operations, then call the concrete MCP tool. See `wave://studio-skill-map` for the concise family-to-tool router.",
44682
- "- Use MECE work modes before tools: Observe reads directly; Operate direct Studio commands directly; Author/Diagnose route with `start_wave_task`; General avoids Wave tools. Direct Operate includes run/hot reload, save/share, exact VFS create/rename/delete, asset upload/rename/delete, new project, project rename, and open project by exact projectId. Use `wave.*` skill tools for WaveEngine code-authoring decisions: `list_wave_skill_families`, `query_wave_skills`, and `get_wave_skill`. Use local-SDK `query_wave_api` only for exact API/global/signature lookup after current-code or skill routing; HTTP Gateway hides/retires cloud API lookup. For exact power-user edits use `code.direct_edit`; for changing an existing API call/argument/literal/value use `code.semantic_guess_edit`; for new code, API switching, or WaveEngine pattern choice use `code.author`. Fast lanes skip broad lookup, not edit/hot-reload/verification. Use `studio.*` labels for operating WaveStudio around that code; those labels are categories, not callable MCP tool names.",
44632
+ "- Use MECE work modes before tools: Observe reads directly; Operate direct Studio commands directly; Author/Diagnose route with `start_wave_task`; General avoids Wave tools. Direct Operate includes run/hot reload, save/share, exact VFS create/rename/delete, asset upload/rename/delete, new project, project rename, and open project by exact projectId. Use local-SDK `wave.*` lookup tools for WaveEngine code-authoring decisions: `list_wave_skill_families`, `query_wave_skills`, `get_wave_skill`, and `query_wave_api`. HTTP Gateway hides/retires cloud skill/API lookup. For exact power-user edits use `code.direct_edit`; for changing an existing API call/argument/literal/value use `code.semantic_guess_edit`; for new code, API switching, or WaveEngine pattern choice use `code.author`. Fast lanes skip broad lookup, not edit/hot-reload/verification. Use `studio.*` labels for operating WaveStudio around that code; those labels are categories, not callable MCP tool names.",
44683
44633
  "- MCP names: HTTP Gateway = Next/Vercel endpoint for remote/sandbox Studio operations; WaveEngine Agent SDK = same-machine live MCP transport from long-running `wave3d-agent-sdk start`; WaveEngine SDK Cache = package-bundled local skill/API docs retrieval; VFS Mirror = HTTP Gateway workspace snapshot. Do not confuse these modules. On same machine, HTTP Gateway is degraded fallback only after SDK cannot run/update/adopt; do not choose it because it is already reachable or easier.",
44684
44634
  "- MCP recovery: when connection/session/onboarding/cache/mirror/timeout state is unclear, call `recover_wave_connection({ lastErrorCode?, failedTool?, symptom? })` first and follow its returned `nextAction`. This is the explicit recovery path for sleeping tabs, local/HTTP Gateway confusion, mirror-not-ready, onboarding-required, command timeout/lease expiry, and hosted proxy/cache failures.",
44685
- '- Local parity rule: WaveEngine Agent SDK `tools/list` mirrors the HTTP Gateway catalog plus SDK 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.',
44635
+ '- 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.',
44686
44636
  `- 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 new SDK may be healthy but unable to authorize the copied local pairing secret. 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.`,
44687
- `- 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 exact 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.`,
44637
+ `- 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.`,
44688
44638
  "- 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.",
44689
- `- 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 \`wave.*\` skill first; for the full generated exact-global surface, call local-SDK \`query_wave_api\`.`,
44639
+ `- 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\`.`,
44690
44640
  "- 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.",
44691
44641
  `- 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.`,
44692
44642
  "- 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.",
44693
- '- 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 Studio preview as HTML sketches and auto-load Mermaid when `class="mermaid"` is present. 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.',
44643
+ '- 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.',
44694
44644
  "- 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.",
44695
- "- 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 skill or API lookup.",
44645
+ "- 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.",
44696
44646
  "- 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.",
44697
- `- 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.`,
44698
- "- MCP project tools: `list_wave_project_templates()`, `new_wave_project({ templateId?, discardUnsavedChanges? })`, `list_wave_projects()`, `read_wave_project({ projectId })`, `rename_wave_project({ projectId, name })`, `open_wave_project({ projectId, discardUnsavedChanges? })`, `save_wave_project({ name?, description? })`, and `share_wave_project()`. Save/share/rename/new/open are direct Operate tools. Use read for example packs because it does not open or replace the editor workspace. Rename updates saved project display metadata without rewriting VFS/code. New/open replace the current live workspace and require write pairing; dirty workspaces require save first or explicit discard. If the user gives a project name, resolve exact projectId with `list_wave_projects` before renaming or opening. Share returns a 30-day `url`; send that URL back to the user.",
44647
+ `- 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.`,
44648
+ "- MCP project tools: `list_wave_project_templates()`, `new_wave_project({ templateId?, discardUnsavedChanges? })`, `list_wave_projects()`, `read_wave_project({ projectId | url })`, `rename_wave_project({ projectId, name })`, `open_wave_project({ projectId, discardUnsavedChanges? })`, `save_wave_project({ name?, description? })`, and `share_wave_project()`. Save/share/rename/new/open are direct Operate tools. Use read for example packs because it does not open or replace the editor workspace. For listed/saved projects pass exact projectId from `list_wave_projects`; for shared/published links pass `url` directly. Silent URL read supports old `/waveStudio?share=<uuid>` links, new shared alias links, old/new `/p/<user>/<id>` published links, and `/waveStudio?source=published&user=<user>&id=<id>`. Rename updates saved project display metadata without rewriting VFS/code. New/open replace the current live workspace and require write pairing; dirty workspaces require save first or explicit discard. If the user gives a project name, resolve exact projectId with `list_wave_projects` before renaming or opening. Share returns a 30-day `url`; send that URL back to the user. Read `resultSummary` first: project tools report PROJECT ... OK, PROJECT ... FAILED, or PROJECT ... PENDING in the same response.",
44699
44649
  "- MCP diagnostics tool: `get_wave_runtime_diagnostics({ limit? })` reads the same embedded Wave Studio console visible in the coding IDE, structured runtime state, and Monaco/editor diagnostics. Use `runtimeBusy`, `previewExecutionPhase`, `lastRuntimeOutcome`, `editorErrorCount`, and `editorDiagnostics`; logs are history and may include old errors. `editorErrorCount > 0` blocks clean success even when runtime outcome says success.",
44700
44650
  "- MCP performance tool: direct Observe `get_wave_runtime_performance_snapshot()` (alias `get_wave_runtime_performance`) reads live FPS/performance stats, memory/RAM/heap, tick rate, tab visibility, Babylon scene counts, Wave entity/component counts, and JS heap when Chromium exposes it. It does not enable or show the debug overlay.",
44701
44651
  '- MCP runtime entity tool: direct Observe `get_wave_runtime_entity_snapshot({ runtimeRef? , variableName?, filePath?, sceneId? })` (alias `get_wave_entity_snapshot`) answers "where is Amy?" and reads the live world transform for VFS-created source variables. Prefer exact `runtimeRef` when known; otherwise pass `variableName` and add `filePath` if candidates are ambiguous.',
@@ -44712,7 +44662,7 @@ var WAVE_MCP_STUDIO_TOOL_GUIDE = [
44712
44662
  "- `waveStudio.exportEntity(name, entity)`: declare a live entity owned by the current source module for intentional modular reuse. `name` must be a static string literal and unique across runnable roots.",
44713
44663
  "- `waveStudio.importEntity<T>(name)`: import an exported live entity into the current source module; Studio restores the exporter baseline and prunes/replays importer callbacks/overlays during source hot reload. Studio orders source roots by export/import dependencies: exporter before importer; exporter before `main.ts` if main imports it; overlay importers after exporter/main baseline. Missing, duplicate, dynamic, or cyclic entity names stop run/hot reload before execution.",
44714
44664
  '- MCP command result rule: poll `get_wave_command_result({ requestId })` only when the previous tool response includes `status:"pending"` plus `requestId`. HTTP Gateway browser-backed tools may return pending and need that poll. WaveEngine Agent SDK browser-backed tools wait directly and return final results; its `get_wave_command_result` is a catalog-parity no-op unless a pending result was explicitly returned.',
44715
- "- MCP preview tools: `hot_reload_wave_preview` (alias `hotreload_wave_preview`) is the default standalone way to view code changes in an already-running preview; `run_wave_preview` (alias `run_project`) is for first start when diagnostics show `hasRunSucceeded: false`, explicit full restart requests, or last-resort recovery after hot reload/polling fails; `pause_wave_preview` / `resume_wave_preview` mirror the toolbar pause/resume buttons. All require write pairing because they mutate live Studio runtime state. Patch/runtime-action responses report that work was requested/scheduled, not that execution finished unless the edit tool used `awaitHotReload:true` or standalone run/hot reload used `awaitRuntimeResult:true`. `hot_reload_wave_preview` mirrors the Wave Studio toolbar button and has no path argument: in multi-file VFS projects it reloads the currently open/active TypeScript file when safe, not every user-created .ts module. For a specific module, make that file active in Studio before calling the standalone hot-reload tool, or use the edit tool `awaitHotReload:true` immediately after the final edit. Main entries reload the main graph, source-root modules reload that root, and bootstrap/scene registry/assets/network/ambiguous helper surfaces escalate. Agents should organize feature-owned objects, callbacks, promoted parts, and appearance mutations into the file they expect to hot reload; use `waveStudio.exportEntity`/`waveStudio.importEntity` only when a live entity intentionally crosses module boundaries. Hot reload may internally choose `patchSource`, `patchMain`, `preserveScene`, or hard `rebuildScene`; agents should inspect returned `runtimeVerification` or poll diagnostics instead of manually guessing the tier. Poll `get_wave_runtime_diagnostics` until `runtimeBusy` is false and `lastRuntimeOutcome` is `success` or `error`, require `editorErrorCount === 0`, then choose one relevant proof tool if needed: screenshot, runtime entity snapshot, markers, or performance snapshot."
44665
+ "- MCP preview tools: `hot_reload_wave_preview` (alias `hotreload_wave_preview`) is the default standalone way to view code changes in an already-running preview; `run_wave_preview` (alias `run_project`) is for first start when diagnostics show `hasRunSucceeded: false`, explicit full restart requests, or last-resort recovery after hot reload/polling fails; `pause_wave_preview` / `resume_wave_preview` mirror the toolbar pause/resume buttons. All require write pairing because they mutate live Studio runtime state. Runtime-triggering tools wait by default and return same-call `runtimeVerification`; set `awaitRuntimeResult:false` only when intentionally fire-and-polling. `hot_reload_wave_preview` mirrors the Wave Studio toolbar button and has no path argument: in multi-file VFS projects it reloads the currently open/active TypeScript file when safe, not every user-created .ts module. For a specific module, make that file active in Studio before calling the standalone hot-reload tool, or use the edit tool `awaitHotReload:true` immediately after the final edit. Main entries reload the main graph, source-root modules reload that root, and bootstrap/scene registry/assets/network/ambiguous helper surfaces escalate. Agents should organize feature-owned objects, callbacks, promoted parts, and appearance mutations into the file they expect to hot reload; use `waveStudio.exportEntity`/`waveStudio.importEntity` only when a live entity intentionally crosses module boundaries. Hot reload may internally choose `patchSource`, `patchMain`, `preserveScene`, or hard `rebuildScene`; agents should inspect returned `runtimeVerification` or poll diagnostics instead of manually guessing the tier. Poll `get_wave_runtime_diagnostics` only when `runtimeVerification` is absent, timed out, or ambiguous; require `editorErrorCount === 0`, then choose one relevant proof tool if needed: screenshot, runtime entity snapshot, markers, or performance snapshot."
44716
44666
  ].join("\n");
44717
44667
 
44718
44668
  // ../../src/lib/waveStudio/aiAssist/bridge/hosted/mcpResources/toolCatalog.ts
@@ -44720,7 +44670,7 @@ var WAVE_MCP_TOOL_CATALOG_GUIDE = [
44720
44670
  "Wave Studio MCP tool catalog:",
44721
44671
  "",
44722
44672
  "Read this as skill families first, concrete MCP tools second. The `studio.*` family names are not callable tools; they are the routing map that tells you which concrete `*_wave_*` tool to use.",
44723
- 'WaveEngine Agent SDK `tools/list` mirrors the HTTP Gateway catalog plus SDK session discovery extras. Its live-session tools run through the paired browser and wait directly for browser results. Use `get_wave_command_result` only after a response with `status:"pending"` and `requestId`; locally it normally exists only for catalog parity.',
44673
+ 'WaveEngine Agent SDK `tools/list` mirrors the HTTP Gateway Studio-operation catalog, then adds local SDK lookup/session-discovery extras. Its live-session tools run through the paired browser and wait directly for browser results. Use `get_wave_command_result` only after a response with `status:"pending"` and `requestId`; locally it normally exists only for catalog parity.',
44724
44674
  "",
44725
44675
  "studio.mcp - session, policy, pending commands:",
44726
44676
  "- `get_wave_coding_guardrails`: call after onboarding acceptance; returns policy, file context, tool catalog, and recipes.",
@@ -44728,11 +44678,11 @@ var WAVE_MCP_TOOL_CATALOG_GUIDE = [
44728
44678
  "- `get_wave_tool_map`: stable complete concrete MCP tool menu grouped by family plus policy flags. Use only when `tools/list` feels truncated or unclear.",
44729
44679
  `- Transport topology rule: 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 Copy-to-Agent, restart with \`${WAVE3D_AGENT_SDK_TOKEN_PRESERVING_START_COMMAND}\` using the current MCP_TOKEN value without printing it so the copied local pairing secret still works. After restart recheck /health and tools/list. 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; never use it because it is familiar, already authenticated, or avoids SDK repair. Different-machine/cloud/sandbox agents should use \`MCP_HTTP_GATEWAY_FALLBACK_URL\` directly. Stale SDK/cache are local setup issues, not fallback triggers; wrong-machine localhost is a topology mismatch.`,
44730
44680
  "- `recover_wave_connection`: direct Observe recovery tool. Call after onboarding required, session missing, command timeout/lease expired, mirror not ready, hosted proxy/cache failure, local/HTTP Gateway confusion, or sleeping-tab symptoms. It returns exact next action: re-onboard, get session, wake tab, update/restart SDK, wait mirror, retry, use HTTP Gateway fallback, or ask fresh Copy to Agent.",
44731
- '- WaveEngine SDK Cache: normal API/skill lookup lives inside the local `wave3d-agent-sdk` SDK package. Update/restart SDK when SDK is stale or missing. HTTP Gateway is Studio-ops-only and does not provide cloud API lookup. If local SDK 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 exact API lookup requires local SDK repair. This is retrieval cache, not WaveEngine Agent SDK transport. Never treat SDK cache failure as local transport failure. Keep Priority 1 role, guardrails, workflow, assets/VFS/hot-reload rules, prompt version, and prompt hash in active LLM context.',
44681
+ '- WaveEngine SDK Cache: normal skill/API lookup lives inside the local `wave3d-agent-sdk` SDK package. Update/restart SDK when SDK is stale or missing. HTTP Gateway is Studio-ops-only and does not provide cloud skill/API lookup. If local SDK 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 skill/API lookup requires local SDK repair. This is retrieval cache, not WaveEngine Agent SDK transport. Never treat SDK cache failure as local transport failure. Keep Priority 1 role, guardrails, workflow, assets/VFS/hot-reload rules, prompt version, and prompt hash in active LLM context.',
44732
44682
  "- Work-mode rule: Observe reads directly; Operate direct Studio commands directly; Author/Diagnose routes through `start_wave_task`; General avoids Wave tools. Operate tools include run/hot reload, save/share, VFS create/rename/delete exact files, asset upload/rename/delete exact assets, new project, project rename, and open project by exact projectId.",
44733
- "- `start_wave_task`: begin one Author/Diagnose route for code behavior/content changes, debugging, exact API lookup, semantic/direct code edits, and multi-step investigations. Use `code.direct_edit` for exact power-user receiver/method/action commands; use `code.semantic_guess_edit` only when changing an existing API call/argument/literal/value already visible in code; use `code.author` for normal/uncertain authoring and any new code/API/pattern choice. If the user request is irrelevant/too broad, use `agent.general` and guide the user toward one concrete Wave milestone.",
44683
+ "- `start_wave_task`: begin one Author/Diagnose route for code behavior/content changes, debugging, local SDK skill/API lookup, semantic/direct code edits, and multi-step investigations. Use `code.direct_edit` for exact power-user receiver/method/action commands; use `code.semantic_guess_edit` only when changing an existing API call/argument/literal/value already visible in code; use `code.author` for normal/uncertain authoring and any new code/API/pattern choice. If the user request is irrelevant/too broad, use `agent.general` and guide the user toward one concrete Wave milestone.",
44734
44684
  "- Diagnose taxonomy: `code.debug` alone means diagnose/report only. For bug-fix requests, include both `code.debug` and `code.author`; otherwise the route may correctly stay read-only/debug-only.",
44735
- '- `advance_wave_task`: move an Author/Diagnose route to lookup, execute, or verify after evidence is gathered. Required before `query_wave_api`, broad `edit_wave_file`, `apply_wave_patch`, and final route verification unless `start_wave_task` already fast-started with `nextPhase:"execute"` and editPlan. Not required for exact `edit_wave_file` line/text edits that already provide path plus startLine/endLine/text, edits:[...], or oldText/newText. Do not advance merely to run a direct Operate tool.',
44685
+ '- `advance_wave_task`: move an Author/Diagnose route to lookup, execute, or verify after evidence is gathered. Required before local-SDK `query_wave_api`, broad `edit_wave_file`, `apply_wave_patch`, and final route verification unless `start_wave_task` already fast-started with `nextPhase:"execute"` and editPlan. Not required for exact `edit_wave_file` line/text edits that already provide path plus startLine/endLine/text, edits:[...], or oldText/newText. Do not advance merely to run a direct Operate tool.',
44736
44686
  "- `get_wave_task_route`: inspect current route, phase, and evidence when you are unsure why a tool is blocked.",
44737
44687
  "- `get_wave_session`: current paired Studio tab, active file, token/session status, visible agent clients.",
44738
44688
  '- `get_wave_command_result`: use only after a tool response contains `status:"pending"` and `requestId`. On HTTP Gateway, this polls pending browser-backed command results until final. On WaveEngine Agent SDK, this is normally catalog parity because local browser-backed calls wait directly.',
@@ -44745,17 +44695,18 @@ var WAVE_MCP_TOOL_CATALOG_GUIDE = [
44745
44695
  "- `apply_wave_patch`: advanced tool for grouped edits, multi-file changes, `lineEdits`, `textEdits`, `searchReplace`, `unifiedDiff`, full rewrites, create/rename/delete in one command. Prefer an `operations` array; a single `operation` or bare operation object is tolerated for recovery. Compact edit operations should include explicit `baseHash`.",
44746
44696
  "- Bootstrap exception: `bootstrap.ts` is not a normal authoring file. `edit_wave_file`/`apply_wave_patch` require `managedFileEditReason` for bootstrap writes. Allowed reasons are world streaming/terrain provider (including Google Maps 3D tiles), render/runtime backend, media consent/capture, external AI/TTS backend, scene/template baseline, pre-main baseline setup, or stale bootstrap API update to latest. Asset manifests/loaders, instruments, scene registry, and execution manifest are blocked because Studio manages those automatically.",
44747
44697
  "- Hot-reload safety preflight: edit_wave_file/create_wave_file/apply_wave_patch reject raw unmanaged callback roots before writing, including timers, RAF, listeners, Promise chains, observers, workers, sockets, channels, eventBus/myScene raw subscriptions, and raw event-handler assignments. Use Wave-owned callbacks/Animate/tick/state/Director APIs.",
44748
- '- `create_wave_file`, `rename_wave_file`, `delete_wave_file`: direct Operate VFS file management for exact `.ts` module paths and `.html` sketch files. Prefer these for project structure changes, diagrams, Mermaid charts, and lightweight docs. For Mermaid, create `.html` with `<div class="mermaid">...</div>`; active HTML files preview in Studio and auto-load Mermaid when `class="mermaid"` is present. 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. If target is vague, call `list_wave_files` or ask before mutating.',
44698
+ '- `create_wave_file`, `rename_wave_file`, `delete_wave_file`: direct Operate VFS file management for exact `.ts` module paths and `.html` sketch files. Prefer these for project structure changes, diagrams, Mermaid charts, and lightweight docs. For Mermaid, create `.html` with `<div class="mermaid">...</div>`; active HTML files preview in the editor/coding pane and auto-load Mermaid when `class="mermaid"` is present. HTML sketches must never replace the live engine preview iframe. 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. If target is vague, call `list_wave_files` or ask before mutating.',
44749
44699
  "",
44750
- "wave.* support - code-authoring facts:",
44751
- "- `list_wave_skill_families`: complete family router for WaveEngine authoring direction after intent chunking/Core Intent Pass. Call this before skill/API lookup when current code does not already show the pattern.",
44752
- "- `query_wave_skills`: search compact generated skill cards only after family selection. Do not pass raw user prose. Call with `families`/`familyId` from `list_wave_skill_families` plus a small within-family query, or exact `skillIds`.",
44753
- "- `get_wave_skill`: read one compact skill card with routing hints, preferred APIs, supporting skills, examples, and anti-patterns.",
44754
- "- `query_wave_api`: gated exact lookup, not assessment. Search public authoring APIs for exact methods, options, enums, bare runtime globals, aliases, members, and return chains after current-code or skill routing. Fast-lane routes call this only when spelling/signature/value uncertainty remains or an edit failed.",
44700
+ "local-SDK wave.* lookup - code-authoring facts:",
44701
+ "- HTTP Gateway tools/list hides/retires `list_wave_skill_families`, `query_wave_skills`, `get_wave_skill`, and `query_wave_api`. Use these only on the local WaveEngine Agent SDK endpoint.",
44702
+ "- `list_wave_skill_families`: local SDK complete family router for WaveEngine authoring direction after intent chunking/Core Intent Pass. Call this before skill/API lookup when current code does not already show the pattern.",
44703
+ "- `query_wave_skills`: local SDK compact generated skill-card search only after family selection. Do not pass raw user prose. Call with `families`/`familyId` from `list_wave_skill_families` plus a small within-family query, or exact `skillIds`.",
44704
+ "- `get_wave_skill`: local SDK compact skill-card read with routing hints, preferred APIs, supporting skills, examples, and anti-patterns.",
44705
+ "- `query_wave_api`: local SDK gated exact lookup, not assessment. Search public authoring APIs for exact methods, options, enums, bare runtime globals, aliases, members, and return chains after current-code or skill routing. Fast-lane routes call this only when spelling/signature/value uncertainty remains or an edit failed.",
44755
44706
  "",
44756
44707
  "studio.preview - run loop and diagnostics:",
44757
- "- `hot_reload_wave_preview` (alias `hotreload_wave_preview`): direct Operate tool for hot reload, reload preview, or refresh preview after edit. It is also the default way to view code changes in an already-running preview. It mirrors the Wave Studio toolbar button and has no path argument: in multi-file VFS projects it reloads the currently open/active TypeScript file when safe, not every user-created .ts module. Studio may upgrade the internal reload tier automatically when assets/bootstrap/runtime surface changed. Pass `awaitRuntimeResult:true` for one-call request + bounded diagnostics.",
44758
- "- `run_wave_preview` (alias `run_project`): direct Operate tool for run project, start preview, or full restart. Use when diagnostics show `hasRunSucceeded: false`, the user asks for a full run/restart, or hot reload is stuck/failing and you need a last-resort restart. Pass `awaitRuntimeResult:true` for one-call request + bounded diagnostics.",
44708
+ "- `hot_reload_wave_preview` (alias `hotreload_wave_preview`): direct Operate tool for hot reload, reload preview, or refresh preview after edit. It is also the default way to view code changes in an already-running preview. It mirrors the Wave Studio toolbar button and has no path argument: in multi-file VFS projects it reloads the currently open/active TypeScript file when safe, not every user-created .ts module. Studio may upgrade the internal reload tier automatically when assets/bootstrap/runtime surface changed. It waits by default and returns one-call bounded diagnostics in `runtimeVerification`; set `awaitRuntimeResult:false` only for intentional fire-and-poll.",
44709
+ "- `run_wave_preview` (alias `run_project`): direct Operate tool for run project, start preview, or full restart. Use when diagnostics show `hasRunSucceeded: false`, the user asks for a full run/restart, or hot reload is stuck/failing and you need a last-resort restart. It waits by default and returns one-call bounded diagnostics in `runtimeVerification`; set `awaitRuntimeResult:false` only for intentional fire-and-poll.",
44759
44710
  "- `pause_wave_preview` / `resume_wave_preview` (aliases `pause_wave_engine`, `resume_wave_engine`): direct Operate tools for the Wave Studio toolbar pause/resume engine controls. No task route needed; preview must already be running.",
44760
44711
  "- `get_wave_runtime_diagnostics`: poll until `runtimeBusy` is false and `lastRuntimeOutcome` is `success` or `error`. If your edit/run tool returned `requestedAt` or `runtimeActionRequestedAt`, ignore older `lastRuntimeOutcomeAt`. Logs are history; use structured outcome first. Also inspect `editorErrorCount`/`editorDiagnostics`; editor errors mean linter/compile failure even if runtime outcome says success.",
44761
44712
  "- `get_wave_runtime_performance_snapshot` (alias `get_wave_runtime_performance`): direct Observe tool for live FPS/performance stats, memory/RAM/heap, hidden-tab throttling, scene weight, mesh/material/texture counts, Wave entity/component counts, and JS heap. No `start_wave_task` needed.",
@@ -44769,7 +44720,7 @@ var WAVE_MCP_TOOL_CATALOG_GUIDE = [
44769
44720
  "studio.assets - refs, uploads, and asset library:",
44770
44721
  "- 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
44722
  "- 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`.",
44772
- "- 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 Wave skill or API lookup.",
44723
+ "- 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
44724
  '- `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
44725
  "- `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.",
44775
44726
  "- `create_wave_asset_upload` -> raw HTTP PUT -> `get_wave_asset_upload_status` -> `commit_wave_asset_upload`: best path for local files; no local npm package required.",
@@ -44780,7 +44731,8 @@ var WAVE_MCP_TOOL_CATALOG_GUIDE = [
44780
44731
  "",
44781
44732
  "studio.project - workspace lifecycle:",
44782
44733
  "- `list_wave_project_templates` -> `new_wave_project`: start a new workspace. Save first or pass explicit discard.",
44783
- "- `list_wave_projects` -> `read_wave_project`: read a bridge-readable project VFS/code payload without opening it. Use for example packs, style learning, and pattern comparison.",
44734
+ "- `read_wave_project({ url })`: silently read shared/published project links without opening them. Supports old `/waveStudio?share=<uuid>` and new shared alias links, old/new `/p/<user>/<id>` published links, and `/waveStudio?source=published&user=<user>&id=<id>`.",
44735
+ "- `list_wave_projects` -> `read_wave_project({ projectId })`: read a listed/saved bridge-readable project VFS/code payload without opening it. Use for example packs, style learning, and pattern comparison.",
44784
44736
  "- `list_wave_projects` -> `rename_wave_project`: rename a saved project by exact projectId without opening it or rewriting VFS/code.",
44785
44737
  "- `list_wave_projects` -> `open_wave_project`: open a bridge-readable project by exact projectId and replace the live workspace. If user gives a name, resolve it through `list_wave_projects`; never pass a guessed name as projectId. Save first or pass explicit discard.",
44786
44738
  "- `save_wave_project`: quick-save existing saved projects; for new projects, pass name/description or let Studio generate defaults.",
@@ -44791,7 +44743,7 @@ var WAVE_MCP_TOOL_CATALOG_GUIDE = [
44791
44743
  "",
44792
44744
  "Cross-family rules:",
44793
44745
  "- Hosted browser-backed tools can return pending with `requestId`; poll `studio.mcp` tool `get_wave_command_result` only in that case. WaveEngine Agent SDK waits directly and normally does not use a pending-command queue.",
44794
- "- Fast-lane code routes: exact user command naming a receiver/method/action -> `code.direct_edit`; changing an existing visible API call/argument/literal/value only -> `code.semantic_guess_edit`. New lines, new objects, API switching, or WaveEngine pattern choice -> `code.author`. Fast lanes skip broad skill/API lookup, not deterministic edit tools, hot reload, or verification. They usually skip `query_wave_api` too; use exact lookup only for uncertainty/failure. For unfamiliar work, retrieve `wave.*` skills before exact API facts.",
44746
+ "- Fast-lane code routes: exact user command naming a receiver/method/action -> `code.direct_edit`; changing an existing visible API call/argument/literal/value only -> `code.semantic_guess_edit`. New lines, new objects, API switching, or WaveEngine pattern choice -> `code.author`. Fast lanes skip broad skill/API lookup, not deterministic edit tools, hot reload, or verification. They usually skip local-SDK `query_wave_api` too; use exact lookup only for uncertainty/failure. For unfamiliar work, retrieve local SDK `wave.*` skills before exact API facts.",
44795
44747
  "- After `studio.vfs` edits, inspect `changedFiles`, `changedPaths`, `partial`, `skippedOperations`, `hotReloadRequested`, and `hotReloadSkippedReason`.",
44796
44748
  "- After code changes, use `studio.preview` hot reload by default, then `studio.capture` to prove the result.",
44797
44749
  "- Proactive help rule: after meaningful progress, suggest at most one relevant Studio capability if it helps: screenshot, entity snapshot, markers, performance snapshot, asset tools, or project share/save/open. Do not dump tool menus."
@@ -44867,7 +44819,7 @@ var LOCAL_MCP_AGENT_READY_SUMMARY = {
44867
44819
  "Primary code edit tool is edit_wave_file. Use apply_wave_patch only for grouped/multi-file/strict diff work.",
44868
44820
  'VFS supports non-code files too: create `.html` sketches for diagrams/charts/docs; active HTML files preview in Studio, and Mermaid renders from `<div class="mermaid">...</div>` blocks.',
44869
44821
  "Hot-reload safety: avoid raw unmanaged callback roots such as timers/RAF/listeners/Promise chains/observers/workers/sockets/channels/event-handler assignments. Edit tools and runtime bundling block violations before authored code runs; use Wave-owned callbacks/Animate/tick/state/Director APIs.",
44870
- "After final code edit, prefer awaitHotReload:true for one-call edit + hot reload + bounded diagnostics; inspect changedFiles/changedPaths/partial/skippedOperations/hotReloadRequested/hotReloadSkippedReason/runtimeVerification.",
44822
+ "After final code edit, prefer awaitHotReload:true for one-call edit + hot reload + bounded diagnostics; requestHotReload:true also waits unless awaitHotReload:false; inspect changedFiles/changedPaths/partial/skippedOperations/hotReloadRequested/hotReloadSkippedReason/runtimeVerification.",
44871
44823
  "Studio-managed generated files are read-only; bootstrap.ts needs a confident managedFileEditReason and is never for assets/loaders/instruments/scene registry/execution manifest.",
44872
44824
  "Production/HTTP-Gateway pairing path must have WaveEngine SDK Cache prepared before onboarding accept succeeds; SDK comes bundled in the npm SDK package."
44873
44825
  ],
@@ -44913,14 +44865,14 @@ var LOCAL_MCP_AGENT_ONBOARDING_PROMPT = [
44913
44865
  "6. For code edits, use `edit_wave_file` as the primary forgiving one-file edit tool. It accepts one exact text edit, one line range, whole-file replacement, or one-file `edits:[...]` arrays. Use `apply_wave_patch` only for grouped/multi-file/strict diff work.",
44914
44866
  "7. 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` is normally Studio-managed too; edit it only with a confident `managedFileEditReason`: `world_streaming_or_terrain_provider` (including Google Maps 3D tiles), `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 assets/loaders, instruments, scene registry, or execution manifest; Studio owns those.",
44915
44867
  '7a. VFS non-code note: `.html` files are supported HTML sketches. For Mermaid diagrams/charts, create or edit an exact `.html` file containing `<div class="mermaid">...</div>`. Active HTML files preview in Studio and auto-load Mermaid when `class="mermaid"` is present.',
44916
- "8. After the final code edit, prefer `awaitHotReload:true` when the preview already ran so the edit response includes hot reload plus bounded diagnostics. Use `requestHotReload:true` only for intentional fire-and-poll. Use standalone `hot_reload_wave_preview` only for explicit preview refresh with no edit.",
44868
+ "8. After the final code edit, prefer `awaitHotReload:true` when the preview already ran so the edit response includes hot reload plus bounded diagnostics. `requestHotReload:true` also waits for diagnostics by default unless paired with `awaitHotReload:false`. Standalone `run_wave_preview` / `hot_reload_wave_preview` wait by default and return `runtimeVerification`; set `awaitRuntimeResult:false` only for intentional fire-and-poll.",
44917
44869
  "9. Always inspect mutation results: changedFiles, changedPaths, partial, skippedOperations, hotReloadRequested, and hotReloadSkippedReason.",
44918
44870
  "10. Marker waypoint workflow: when the human asks to use preview marking tools such as `clickToMark()`, route with `marker.use` plus code/project intent, then call `list_wave_runtime_markers` and write marker worldPosition/worldRotation into waypoint/path/placement code. One marker read may happen before routing only when needed to decide intent.",
44919
44871
  "11. After meaningful progress, suggest at most one relevant Studio capability when helpful: screenshot, runtime entity snapshot, runtime markers, performance snapshot, asset tools, or project save/share/open. Do not dump a menu.",
44920
44872
  "",
44921
44873
  "WaveEngine Agent SDK scope:",
44922
- 'This endpoint mirrors the HTTP Gateway tool catalog plus local SDK session-discovery extras. Live-session Studio tools for VFS, preview, capture, runtime probes, assets, uploads, project save/share/open/new/read, and file operations run through the connected browser. Local browser-backed calls wait for the browser result directly. Only call `get_wave_command_result` when a tool result actually contains `status:"pending"` plus `requestId`; otherwise local `get_wave_command_result` exists only for catalog parity and reports that no local pending-command queue is used. Skill/API/guardrail tools read the bundled WaveEngine SDK Cache prepared by the SDK package. Do not treat SDK cache miss as local transport failure.',
44923
- `Recovery rule: \`recover_wave_connection\` is the first tool after \`agent_onboarding_required\`, \`session_not_found\`, \`command_timeout\`, \`command_lease_expired\`, \`hosted_mcp_proxy_failed\`, unclear local/HTTP Gateway fallback, or sleeping-tab symptoms. If local HTTP refuses, start/restart WaveEngine Agent SDK and retry 10 seconds. If local HTTP returns 401 but HTTP Gateway accepts the same MCP_TOKEN, SDK is stale/not adopted: restart with \`${WAVE3D_AGENT_SDK_TOKEN_PRESERVING_START_COMMAND}\` using the current MCP_TOKEN value hidden, then retry local. If every endpoint rejects MCP_TOKEN before a tool result, ask user for fresh Copy to Agent.`
44874
+ 'This endpoint publishes canonical Wave MCP tools only when this Agent SDK build has a real local handler, plus local SDK session-discovery extras. Live-session Studio tools for VFS, preview, capture, runtime probes, assets, uploads, project save/share/open/new/read, and file operations run through the connected browser. Local browser-backed calls wait for the browser result directly. Only call `get_wave_command_result` when a tool result actually contains `status:"pending"` plus `requestId`; otherwise local `get_wave_command_result` exists only for catalog parity and reports that no local pending-command queue is used. Skill/API/guardrail tools read the bundled WaveEngine SDK Cache prepared by the SDK package. Do not treat SDK cache miss as local transport failure.',
44875
+ `Recovery rule: \`recover_wave_connection\` is the first tool after \`agent_onboarding_required\`, \`session_not_found\`, \`command_timeout\`, \`command_lease_expired\`, \`local_sdk_tool_not_implemented\`, \`wave_engine_sdk_cache_required\`, unclear local/HTTP Gateway fallback, or sleeping-tab symptoms. If local HTTP refuses, start/restart WaveEngine Agent SDK and retry 10 seconds. If local HTTP returns 401 but HTTP Gateway accepts the same MCP_TOKEN, SDK is stale/not adopted: restart with \`${WAVE3D_AGENT_SDK_TOKEN_PRESERVING_START_COMMAND}\` using the current MCP_TOKEN value hidden, then retry local. If every endpoint rejects MCP_TOKEN before a tool result, ask user for fresh Copy to Agent.`
44924
44876
  ].join("\n");
44925
44877
 
44926
44878
  // ../../scripts/wavegenie-sdk/mcp/referenceTools.ts
@@ -44966,6 +44918,100 @@ function summarizePaths(paths) {
44966
44918
  function readNumber(value) {
44967
44919
  return typeof value === "number" && Number.isFinite(value) ? value : null;
44968
44920
  }
44921
+ function readString(value) {
44922
+ return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
44923
+ }
44924
+ function readBoolean2(value) {
44925
+ return typeof value === "boolean" ? value : null;
44926
+ }
44927
+ function summarizeCount(count, singular, plural = `${singular}s`) {
44928
+ return `${count} ${count === 1 ? singular : plural}`;
44929
+ }
44930
+ function summarizeActionLabel(value) {
44931
+ return value.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/[_-]+/g, " ").trim().toUpperCase();
44932
+ }
44933
+ function summarizeToolFailure(value) {
44934
+ const error = readRecord(value.error);
44935
+ const message = readString(value.message) ?? readString(error?.message) ?? readString(value.error);
44936
+ return message ? `OPERATION FAILED: ${message}` : "OPERATION FAILED";
44937
+ }
44938
+ function summarizePendingToolResult(value) {
44939
+ const status = readString(value.status);
44940
+ if (!status) return null;
44941
+ const requestId = readString(value.requestId) ?? readString(value.commandId);
44942
+ const action = readString(value.action);
44943
+ const label = action ? summarizeActionLabel(action) : "OPERATION";
44944
+ if (status === "pending") {
44945
+ return `${label} PENDING${requestId ? `: requestId ${requestId}` : ""}; NEXT: poll get_wave_command_result`;
44946
+ }
44947
+ return `${label} ${status.toUpperCase()}${requestId ? `: requestId ${requestId}` : ""}`;
44948
+ }
44949
+ function summarizeProjectOrAssetOperation(value) {
44950
+ const ok = readBoolean2(value.ok);
44951
+ if (ok === false) return summarizeToolFailure(value);
44952
+ const pending = summarizePendingToolResult(value);
44953
+ if (pending) return pending;
44954
+ if (ok !== true) return null;
44955
+ const templates = Array.isArray(value.templates) ? value.templates : null;
44956
+ if (templates) return `PROJECT TEMPLATES OK: ${summarizeCount(templates.length, "template")}`;
44957
+ const projects = Array.isArray(value.projects) ? value.projects : null;
44958
+ if (projects) {
44959
+ const total = readNumber(value.total) ?? projects.length;
44960
+ return `PROJECT LIST OK: ${summarizeCount(total, "project")}`;
44961
+ }
44962
+ const assets = Array.isArray(value.assets) ? value.assets : null;
44963
+ if (assets) return `ASSET LIST OK: ${summarizeCount(assets.length, "asset")}`;
44964
+ const uploadId = readString(value.uploadId);
44965
+ if (uploadId) {
44966
+ const chunkIndex = readNumber(value.chunkIndex);
44967
+ const totalChunks = readNumber(value.totalChunks);
44968
+ if (chunkIndex !== null && totalChunks !== null) {
44969
+ return `ASSET UPLOAD CHUNK OK: chunk ${chunkIndex + 1}/${totalChunks}; uploadId ${uploadId}`;
44970
+ }
44971
+ const receivedBytes = readNumber(value.receivedBytes);
44972
+ if (receivedBytes !== null) {
44973
+ return `ASSET UPLOAD STATUS OK: ${summarizeCount(receivedBytes, "byte")} received; uploadId ${uploadId}`;
44974
+ }
44975
+ if (readNumber(value.deletedCount) !== null) {
44976
+ return `ASSET UPLOAD ABORT OK: staging cleaned for uploadId ${uploadId}`;
44977
+ }
44978
+ if (readString(value.uploadUrl)) {
44979
+ return `ASSET UPLOAD URL OK: uploadId ${uploadId}; NEXT: upload bytes, check status, then commit_wave_asset_upload`;
44980
+ }
44981
+ return `ASSET UPLOAD STEP OK: uploadId ${uploadId}`;
44982
+ }
44983
+ const action = readString(value.action);
44984
+ if (action === "shareProject" || readString(value.shareUrl) || readString(value.url)) {
44985
+ const url = readString(value.shareUrl) ?? readString(value.url);
44986
+ return url ? `PROJECT SHARE OK: ${url}` : "PROJECT SHARE OK";
44987
+ }
44988
+ if (action) {
44989
+ const label = summarizeActionLabel(action);
44990
+ const project2 = readRecord(value.project);
44991
+ const asset2 = readRecord(value.asset);
44992
+ const projectName = readString(project2?.name) ?? readString(value.name);
44993
+ const assetPath = readString(value.path);
44994
+ if (action.toLowerCase().includes("project") || project2) {
44995
+ return `${label} OK${projectName ? `: ${projectName}` : ""}`;
44996
+ }
44997
+ if (action === "rename" || action === "delete" || action === "uploadAsset" || asset2 || assetPath) {
44998
+ if (value.skipped === true) {
44999
+ const message = readString(value.message);
45000
+ return `ASSET ${label} SKIPPED${message ? `: ${message}` : ""}`;
45001
+ }
45002
+ return `ASSET ${label} OK${assetPath ? `: ${assetPath}` : ""}`;
45003
+ }
45004
+ return `${label} OK`;
45005
+ }
45006
+ const project = readRecord(value.project);
45007
+ if (project) {
45008
+ const projectName = readString(project.name);
45009
+ return `PROJECT OK${projectName ? `: ${projectName}` : ""}`;
45010
+ }
45011
+ const asset = readRecord(value.asset);
45012
+ if (asset || readString(value.assetKind)) return "ASSET OK";
45013
+ return null;
45014
+ }
44969
45015
  function readRuntimeVerificationEditorErrorCount(value) {
44970
45016
  const verification = readRecord(value.runtimeVerification);
44971
45017
  const directCount = readNumber(verification?.editorErrorCount);
@@ -45010,12 +45056,46 @@ function summarizeHotReloadVerification(value) {
45010
45056
  if (verificationOutcome === "error") return "; HOT RELOAD ERROR: read runtimeVerification.diagnostics";
45011
45057
  return null;
45012
45058
  }
45059
+ function summarizeRuntimeActionVerification(value, action) {
45060
+ const verification = readRecord(value.runtimeVerification);
45061
+ if (!verification) return null;
45062
+ const editorErrorCount = readRuntimeVerificationEditorErrorCount(value);
45063
+ if (editorErrorCount > 0) {
45064
+ return `${action} BLOCKED: ${editorErrorCount} editor/linter error${editorErrorCount === 1 ? "" : "s"}; NEXT: read runtimeVerification.diagnostics.editorDiagnostics before reporting success`;
45065
+ }
45066
+ if (verification.timedOut === true) {
45067
+ return `${action} PENDING: diagnostics timed out; poll get_wave_runtime_diagnostics`;
45068
+ }
45069
+ const verificationOutcome = verification.verificationOutcome;
45070
+ if (verificationOutcome === "success") return `${action} OK`;
45071
+ if (verificationOutcome === "error") return `${action} ERROR: read runtimeVerification.diagnostics`;
45072
+ return null;
45073
+ }
45013
45074
  function buildWaveMcpToolResultNextAction(value) {
45014
45075
  const changedPaths = readStringArray2(value.changedPaths);
45015
45076
  const changedFiles = readPathArray(value.changedFiles);
45016
45077
  const editedPaths = changedPaths.length > 0 ? changedPaths : changedFiles;
45017
45078
  const skippedReasons = readSkippedReasons(value.skippedOperations);
45018
45079
  const directEditorErrorCount = readDirectEditorErrorCount(value);
45080
+ if (value.ok === false) {
45081
+ return "Operation failed. Read the returned error/message, fix the input or session state, then retry.";
45082
+ }
45083
+ if (readString(value.status) === "pending") {
45084
+ return "Browser command is still pending. Poll get_wave_command_result with the returned requestId before reporting completion.";
45085
+ }
45086
+ if (value.action === "hotReload" || value.action === "run") {
45087
+ const editorErrorCount = readRuntimeVerificationEditorErrorCount(value);
45088
+ if (editorErrorCount > 0) {
45089
+ return "Editor/linter errors block this preview action. Read runtimeVerification.diagnostics.editorDiagnostics, fix those errors, then re-run hot reload or preview.";
45090
+ }
45091
+ const verification = readRecord(value.runtimeVerification);
45092
+ if (verification?.timedOut === true) {
45093
+ return "Runtime verification timed out. Poll get_wave_runtime_diagnostics until runtimeBusy is false and lastRuntimeOutcome is success or error.";
45094
+ }
45095
+ if (verification?.verificationOutcome === "error") {
45096
+ return "Runtime action failed. Read runtimeVerification.diagnostics.latestError and editorDiagnostics before retrying.";
45097
+ }
45098
+ }
45019
45099
  if (directEditorErrorCount !== null && directEditorErrorCount > 0) {
45020
45100
  return "Editor/linter errors block this code. Read editorDiagnostics, fix those errors, then re-run hot reload or preview.";
45021
45101
  }
@@ -45040,6 +45120,8 @@ function buildWaveMcpToolResultNextAction(value) {
45040
45120
  }
45041
45121
  function waveMcpToolResultNeedsAttention(value, nextAction) {
45042
45122
  if (nextAction) return true;
45123
+ if (value.ok === false) return true;
45124
+ if (readString(value.status) === "pending") return true;
45043
45125
  const verificationOk = readRuntimeVerificationOk(value);
45044
45126
  if (verificationOk === false) return true;
45045
45127
  const directEditorErrorCount = readDirectEditorErrorCount(value);
@@ -45071,8 +45153,10 @@ function buildWaveMcpToolResultSummary(value) {
45071
45153
  if (value.action === "hotReload" || value.action === "run") {
45072
45154
  const action = value.action === "run" ? "RUN" : "HOT RELOAD";
45073
45155
  if (value.requested === false || value.ok === false) return `${action} NOT REQUESTED`;
45074
- return `${action} REQUESTED: not proof of runtime success; poll get_wave_runtime_diagnostics until runtimeBusy is false and lastRuntimeOutcome is success or error`;
45156
+ return summarizeRuntimeActionVerification(value, action) ?? `${action} REQUESTED: not proof of runtime success; poll get_wave_runtime_diagnostics until runtimeBusy is false and lastRuntimeOutcome is success or error`;
45075
45157
  }
45158
+ const operationSummary = summarizeProjectOrAssetOperation(value);
45159
+ if (operationSummary) return operationSummary;
45076
45160
  if (changedFiles.length > 0) {
45077
45161
  return `EDIT APPLIED: ${summarizePaths(changedFiles)} changed`;
45078
45162
  }
@@ -45165,11 +45249,6 @@ function errorToolResult(code, message, details) {
45165
45249
  isError: true
45166
45250
  };
45167
45251
  }
45168
- function readToolResultErrorCode(result) {
45169
- const error = result.structuredContent?.error;
45170
- if (!isRecord2(error)) return null;
45171
- return typeof error.code === "string" ? error.code : null;
45172
- }
45173
45252
 
45174
45253
  // ../../scripts/wavegenie-sdk/mcp/referenceTools.ts
45175
45254
  function getLocalCorpusCacheRoot() {
@@ -45772,7 +45851,7 @@ async function prepareLocalCorpusForOnboarding(context) {
45772
45851
  commandTemplate: WAVE_MCP_CORPUS_CACHE_COMMAND_TEMPLATE
45773
45852
  };
45774
45853
  }
45775
- async function localReferenceTool(input) {
45854
+ async function localSdkLookupTool(input) {
45776
45855
  if (input.name === "list_wave_skill_families") return await localListWaveSkillFamilies(input.args, input.context);
45777
45856
  if (input.name === "query_wave_skills") return await localQueryWaveSkills(input.args, input.context);
45778
45857
  if (input.name === "get_wave_skill") return await localGetWaveSkill(input.args, input.context);
@@ -45780,19 +45859,16 @@ async function localReferenceTool(input) {
45780
45859
  if (input.name === "get_wave_coding_guardrails") return await localGetWaveCodingGuardrails();
45781
45860
  return null;
45782
45861
  }
45783
- async function proxyHostedReferenceTool(input) {
45784
- const localResult = await localReferenceTool({
45862
+ async function runLocalSdkLookupTool(input) {
45863
+ const localResult = await localSdkLookupTool({
45785
45864
  name: input.name,
45786
45865
  args: input.args,
45787
45866
  context: input.context
45788
45867
  });
45789
- const localErrorCode = localResult ? readToolResultErrorCode(localResult) : null;
45790
- if (localResult && localErrorCode !== "wave_engine_sdk_cache_required") {
45791
- return localResult;
45792
- }
45793
- return localResult ?? errorToolResult(
45794
- "wave_engine_sdk_cache_required",
45795
- `${input.name} needs the bundled WaveEngine SDK Cache from the local wave3d-agent-sdk package. Update/restart SDK or run the bundled SDK repair command. HTTP Gateway is not an API/skill lookup fallback.`
45868
+ if (localResult) return localResult;
45869
+ return errorToolResult(
45870
+ "local_sdk_lookup_handler_missing",
45871
+ `${input.name} is listed as a local SDK lookup tool but has no local handler. Update wave3d-agent-sdk; HTTP Gateway is not an API/skill lookup fallback.`
45796
45872
  );
45797
45873
  }
45798
45874
 
@@ -46517,7 +46593,10 @@ function normalizeEditWaveFileMode(value) {
46517
46593
  return void 0;
46518
46594
  }
46519
46595
  function shouldAwaitHotReloadDiagnostics(args) {
46520
- return args?.awaitHotReload === true || args?.awaitRuntimeDiagnostics === true || args?.returnRuntimeDiagnostics === true;
46596
+ if (args?.awaitHotReload === false || args?.awaitRuntimeDiagnostics === false || args?.returnRuntimeDiagnostics === false || args?.awaitDiagnostics === false) {
46597
+ return false;
46598
+ }
46599
+ return args?.awaitHotReload === true || args?.awaitRuntimeDiagnostics === true || args?.returnRuntimeDiagnostics === true || args?.awaitDiagnostics === true || args?.requestHotReload === true;
46521
46600
  }
46522
46601
  function runtimeVerificationArgs(args) {
46523
46602
  const awaitHotReload = shouldAwaitHotReloadDiagnostics(args);
@@ -47481,7 +47560,7 @@ var HOT_RELOAD_RUNTIME_DIAGNOSTIC_SCHEMA_PROPERTIES = {
47481
47560
  awaitHotReload: {
47482
47561
  type: "boolean",
47483
47562
  default: false,
47484
- description: "Set true on the final edit to combine edit + hot reload + bounded runtime diagnostics in one MCP call. Implies requestHotReload. Response includes runtimeVerification with latest diagnostics or timedOut:true."
47563
+ description: "Set true on the final edit to combine edit + hot reload + bounded runtime diagnostics in one MCP call. Implies requestHotReload. requestHotReload:true uses this wait behavior by default; set awaitHotReload:false only for intentional fire-and-poll."
47485
47564
  },
47486
47565
  awaitRuntimeDiagnostics: {
47487
47566
  type: "boolean",
@@ -47496,7 +47575,7 @@ var HOT_RELOAD_RUNTIME_DIAGNOSTIC_SCHEMA_PROPERTIES = {
47496
47575
  minimum: 500,
47497
47576
  maximum: 15e3,
47498
47577
  default: 6e3,
47499
- description: "Only used with awaitHotReload. Maximum wait for fresh runtime success/error diagnostics."
47578
+ description: "Maximum wait for fresh runtime success/error diagnostics when awaitHotReload is true or requestHotReload triggers the default wait behavior."
47500
47579
  },
47501
47580
  awaitTimeoutMs: {
47502
47581
  type: "integer",
@@ -47509,7 +47588,7 @@ var HOT_RELOAD_RUNTIME_DIAGNOSTIC_SCHEMA_PROPERTIES = {
47509
47588
  minimum: 1,
47510
47589
  maximum: 200,
47511
47590
  default: 80,
47512
- description: "Only used with awaitHotReload. Console/runtime log limit in returned diagnostics."
47591
+ description: "Console/runtime log limit returned with runtime diagnostics when awaitHotReload is true or requestHotReload triggers the default wait behavior."
47513
47592
  }
47514
47593
  };
47515
47594
  var ASSET_CODE_REF_DISCOVERY_INPUT_SCHEMA = {
@@ -47521,12 +47600,12 @@ var ASSET_CODE_REF_DISCOVERY_INPUT_SCHEMA = {
47521
47600
  },
47522
47601
  bucket: {
47523
47602
  type: "string",
47524
- description: "Legacy alias for category. Accepted only to tolerate older agent memory; prefer category in new calls."
47603
+ description: "Accepted synonym for category. Prefer category in new calls."
47525
47604
  },
47526
47605
  buckets: {
47527
47606
  type: "array",
47528
47607
  items: { type: "string" },
47529
- description: "Legacy alias for category; first recognized item is used. Accepted only to tolerate older agent memory; prefer category in new calls."
47608
+ description: "Accepted synonym for category; first recognized item is used. Prefer category in new calls."
47530
47609
  },
47531
47610
  query: {
47532
47611
  type: "string",
@@ -47610,7 +47689,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
47610
47689
  },
47611
47690
  {
47612
47691
  name: "accept_wave_agent_onboarding",
47613
- description: '[studio.mcp] Required acknowledgement after reading `get_wave_agent_onboarding`. Call only after keeping the role, coding guardrails, intent taxonomy, authoring workflow, and Studio tool policy in active LLM context. Requires exact promptVersion/promptHash, acceptedRole true, required cachedSections, full intentKindsCached, exact waveEngineSdkCacheCommandCached, and all context-cache booleans true. Production HTTP Gateway may also require local WaveEngine SDK cache proof before normal cached success. If SDK cache cannot work because sandbox/no filesystem/no Node/npm/user refusal/refresh failure, explicitly pass waveEngineSdkFallbackMode:"studio_ops_only", a valid waveEngineSdkUnavailableReason, and studioOpsOnlyFallbackAccepted:true, then warn user HTTP Gateway is Studio-ops-only and exact API lookup requires local SDK/cache repair. After success, stay in Wave Studio authoring-agent role and briefly confirm role accepted.',
47692
+ description: '[studio.mcp] Required acknowledgement after reading `get_wave_agent_onboarding`. Call only after keeping the role, coding guardrails, intent taxonomy, authoring workflow, and Studio tool policy in active LLM context. Requires exact promptVersion/promptHash, acceptedRole true, required cachedSections, full intentKindsCached, exact waveEngineSdkCacheCommandCached, and all context-cache booleans true. Production HTTP Gateway may also require local WaveEngine SDK cache proof before normal cached success. If SDK cache cannot work because sandbox/no filesystem/no Node/npm/user refusal/refresh failure, explicitly pass waveEngineSdkFallbackMode:"studio_ops_only", a valid waveEngineSdkUnavailableReason, and studioOpsOnlyFallbackAccepted:true, then warn user HTTP Gateway is Studio-ops-only and skill/API lookup requires local SDK/cache repair. After success, stay in Wave Studio authoring-agent role and briefly confirm role accepted.',
47614
47693
  inputSchema: {
47615
47694
  type: "object",
47616
47695
  properties: {
@@ -47677,7 +47756,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
47677
47756
  },
47678
47757
  studioOpsOnlyFallbackAccepted: {
47679
47758
  type: "boolean",
47680
- description: "Required true with waveEngineSdkFallbackMode. Agent must warn user that HTTP Gateway is Studio-ops-only without local SDK cache; exact API lookup requires local SDK/cache repair."
47759
+ description: "Required true with waveEngineSdkFallbackMode. Agent must warn user that HTTP Gateway is Studio-ops-only without local SDK cache; skill/API lookup requires local SDK/cache repair."
47681
47760
  },
47682
47761
  agentName: { type: "string" },
47683
47762
  agentProvider: { type: "string" }
@@ -47746,7 +47825,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
47746
47825
  },
47747
47826
  {
47748
47827
  name: "start_wave_task",
47749
- description: '[studio.mcp] Start the Wave Agent Behavior Harness for Author or Diagnose work: code authoring, debugging, exact API lookup, semantic edits, and multi-step investigations. Do not use this for Observe requests (read/inspect) or Operate requests (direct Studio commands such as run preview, hot reload, save, share, open project by resolved projectId, create/delete/rename exact files/assets). Classify routed intent chunks across project/code/direct-edit/semantic-guess/debug/VFS/asset/runtime/visual/marker/preview/general, then use returned taskRouteId in route-bound authoring tools. Canonical examples: run project -> preview.control direct Operate, no route; delete exact /foo.ts -> vfs.manage direct Operate, no route; call showDirection on cube -> code.direct_edit route; change existing cube color red to blue -> code.semantic_guess_edit route; add mountain or place objects in line -> code.author route; investigate runtime error -> code.debug route. Common casing/punctuation variants are normalized, but canonical kind values are preferred. Use code.direct_edit for exact power-user commands such as \u201Ccall showDirection on Amy\u201D. Use code.semantic_guess_edit only to change an existing API call/argument/literal/value such as COLOR.RED -> COLOR.BLUE; if the edit adds lines, creates objects, switches API, or chooses a WaveEngine pattern such as placement/layout, use code.author. If request is irrelevant or too broad, use agent.general and guide user toward a concrete Wave milestone instead of forcing Wave tools. Use code.debug alone for diagnose/report-only; for bug-fix requests include both code.debug and code.author. Fast start: when you already read enough context and know the edit, include nextPhase:"execute" plus editPlan/verificationPlan in this same call. Even faster: for exact line/text edits, start the route then call edit_wave_file directly with path plus exact startLine/endLine/text, edits:[...], or oldText/newText; no separate advance_wave_task needed.',
47828
+ description: '[studio.mcp] Start the Wave Agent Behavior Harness for Author or Diagnose work: code authoring, debugging, local SDK skill/API lookup, semantic edits, and multi-step investigations. Do not use this for Observe requests (read/inspect) or Operate requests (direct Studio commands such as run preview, hot reload, save, share, open project by resolved projectId, create/delete/rename exact files/assets). Classify routed intent chunks across project/code/direct-edit/semantic-guess/debug/VFS/asset/runtime/visual/marker/preview/general, then use returned taskRouteId in route-bound authoring tools. Canonical examples: run project -> preview.control direct Operate, no route; delete exact /foo.ts -> vfs.manage direct Operate, no route; call showDirection on cube -> code.direct_edit route; change existing cube color red to blue -> code.semantic_guess_edit route; add mountain or place objects in line -> code.author route; investigate runtime error -> code.debug route. Common casing/punctuation variants are normalized, but canonical kind values are preferred. Use code.direct_edit for exact power-user commands such as \u201Ccall showDirection on Amy\u201D. Use code.semantic_guess_edit only to change an existing API call/argument/literal/value such as COLOR.RED -> COLOR.BLUE; if the edit adds lines, creates objects, switches API, or chooses a WaveEngine pattern such as placement/layout, use code.author. If request is irrelevant or too broad, use agent.general and guide user toward a concrete Wave milestone instead of forcing Wave tools. Use code.debug alone for diagnose/report-only; for bug-fix requests include both code.debug and code.author. Fast start: when you already read enough context and know the edit, include nextPhase:"execute" plus editPlan/verificationPlan in this same call. Even faster: for exact line/text edits, start the route then call edit_wave_file directly with path plus exact startLine/endLine/text, edits:[...], or oldText/newText; no separate advance_wave_task needed.',
47750
47829
  inputSchema: {
47751
47830
  type: "object",
47752
47831
  properties: {
@@ -47997,7 +48076,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
47997
48076
  },
47998
48077
  {
47999
48078
  name: "advance_wave_task",
48000
- description: "[studio.mcp] Advance an Author/Diagnose task route after evidence is gathered. taskRouteId is recommended, but if omitted Studio uses this MCP session\u2019s active route and still enforces phase/intent checks; routeId and nested route.taskRouteId/id are accepted. Phase aliases targetPhase and phase are accepted. Use before query_wave_api (lookup), broad authoring edits/apply_patch (execute), and final route verification. Do not advance just to run direct Operate tools such as run_wave_preview, hot_reload_wave_preview, save_wave_project, or create_wave_file when the user asked for that operation directly. Fast-lane direct/semantic code routes can skip lookup and advance straight to execute when exact user wording or current code is enough. This is the checkpoint that prevents jump-to-API/jump-to-edit behavior.",
48079
+ description: "[studio.mcp] Advance an Author/Diagnose task route after evidence is gathered. taskRouteId is recommended, but if omitted Studio uses this MCP session\u2019s active route and still enforces phase/intent checks; routeId and nested route.taskRouteId/id are accepted. Phase aliases targetPhase and phase are accepted. Use before local-SDK query_wave_api (lookup), broad authoring edits/apply_patch (execute), and final route verification. Do not advance just to run direct Operate tools such as run_wave_preview, hot_reload_wave_preview, save_wave_project, or create_wave_file when the user asked for that operation directly. Fast-lane direct/semantic code routes can skip lookup and advance straight to execute when exact user wording or current code is enough. This is the checkpoint that prevents jump-to-API/jump-to-edit behavior.",
48001
48080
  inputSchema: {
48002
48081
  type: "object",
48003
48082
  properties: {
@@ -48116,7 +48195,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48116
48195
  },
48117
48196
  {
48118
48197
  name: "list_wave_skill_families",
48119
- description: "[wave.*] Complete family router for WaveEngine code-authoring. Use after intent chunking/Core Intent Pass and before query_wave_skills/query_wave_api. Pick one or more families from this list first, e.g. continuous left turning -> wave.transform plus possibly wave.animate. This selects authoring direction; it does not inspect exact signatures.",
48198
+ description: "[wave.*] Local WaveEngine SDK family router for code-authoring. HTTP Gateway hides/retires this lookup. Use after intent chunking/Core Intent Pass and before query_wave_skills/query_wave_api. Pick one or more families from this list first, e.g. continuous left turning -> wave.transform plus possibly wave.animate. This selects authoring direction; it does not inspect exact signatures.",
48120
48199
  inputSchema: {
48121
48200
  type: "object",
48122
48201
  properties: {
@@ -48130,7 +48209,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48130
48209
  },
48131
48210
  {
48132
48211
  name: "query_wave_skills",
48133
- description: '[wave.*] Search compact WaveEngine skill cards only after skill-family selection. Do not pass the raw user request as a broad query. First call list_wave_skill_families, choose families from intent chunks/Core Intent Pass, then call this with families/familyId plus a small within-family query such as "continuous rotation" or "semantic direction". Use skillIds only for exact known skill ids.',
48212
+ description: '[wave.*] Local WaveEngine SDK skill-card lookup. HTTP Gateway hides/retires this lookup. Search compact WaveEngine skill cards only after skill-family selection. Do not pass the raw user request as a broad query. First call list_wave_skill_families, choose families from intent chunks/Core Intent Pass, then call this with families/familyId plus a small within-family query such as "continuous rotation" or "semantic direction". Use skillIds only for exact known skill ids.',
48134
48213
  inputSchema: {
48135
48214
  type: "object",
48136
48215
  properties: {
@@ -48181,7 +48260,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48181
48260
  },
48182
48261
  {
48183
48262
  name: "get_wave_skill",
48184
- description: "[wave.*] Read one generated WaveEngine skill card by skillId, id, or name. Use after list_wave_skill_families/query_wave_skills to inspect routing, examples, supporting skills, and anti-patterns.",
48263
+ description: "[wave.*] Local WaveEngine SDK skill-card read. HTTP Gateway hides/retires this lookup. Read one generated WaveEngine skill card by skillId, id, or name. Use after list_wave_skill_families/query_wave_skills to inspect routing, examples, supporting skills, and anti-patterns.",
48185
48264
  inputSchema: {
48186
48265
  type: "object",
48187
48266
  properties: {
@@ -48545,19 +48624,27 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48545
48624
  },
48546
48625
  {
48547
48626
  name: "read_wave_project",
48548
- description: `[studio.project] Read a bridge-readable Wave Studio project's VFS/code content without opening it in the paired editor. Use this to learn from example packs or compare patterns before editing the live project. It does not replace the current workspace, does not change dirty state, and does not run preview. projectId/id/project must be an exact project id from list_wave_projects, not a fuzzy project name; resolve names by listing first. Prefer projectId; id/project are accepted aliases.${BROWSER_COMMAND_PENDING_NOTE}`,
48627
+ description: `[studio.project] Read a Wave Studio project's VFS/code content without opening it in the paired editor. Use this to learn from example packs or compare patterns before editing the live project. It does not replace the current workspace, does not change dirty state, and does not run preview. For saved/listed projects, pass exact projectId/id/project from list_wave_projects, not a fuzzy project name. For shared or published links, pass url/projectUrl/shareUrl/publishedUrl directly; silent URL reading supports old shared URLs like /waveStudio?share=<uuid>, new shared alias URLs, old/new published /p/<user>/<id> URLs, and /waveStudio?source=published&user=<user>&id=<id>. Prefer url for links and projectId for listed ids.${BROWSER_COMMAND_PENDING_NOTE}`,
48549
48628
  inputSchema: {
48550
48629
  type: "object",
48551
48630
  properties: {
48552
48631
  projectId: { type: "string" },
48553
48632
  id: { type: "string" },
48554
48633
  project: { type: "string" },
48634
+ url: { type: "string" },
48635
+ projectUrl: { type: "string" },
48636
+ shareUrl: { type: "string" },
48637
+ publishedUrl: { type: "string" },
48555
48638
  idempotencyKey: { type: "string" }
48556
48639
  },
48557
48640
  anyOf: [
48558
48641
  { required: ["projectId"] },
48559
48642
  { required: ["id"] },
48560
- { required: ["project"] }
48643
+ { required: ["project"] },
48644
+ { required: ["url"] },
48645
+ { required: ["projectUrl"] },
48646
+ { required: ["shareUrl"] },
48647
+ { required: ["publishedUrl"] }
48561
48648
  ],
48562
48649
  additionalProperties: false
48563
48650
  }
@@ -48723,7 +48810,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48723
48810
  },
48724
48811
  includeDataUrl: {
48725
48812
  type: "boolean",
48726
- description: 'Legacy alias for returnMode:"dataUrl". When true, also return dataUrl. Default false avoids duplicating large base64 output.'
48813
+ description: 'Accepted synonym for returnMode:"dataUrl". When true, also return dataUrl. Default false avoids duplicating large base64 output.'
48727
48814
  },
48728
48815
  saveToLocalFile: {
48729
48816
  type: "boolean",
@@ -48770,7 +48857,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48770
48857
  },
48771
48858
  {
48772
48859
  name: "edit_wave_file",
48773
- description: `[studio.vfs] PRIMARY forgiving one-file edit tool. Use this first for simple code edits: replace exact text, replace/delete a 1-based inclusive full-file line range, apply several one-file line/text edits through edits:[...], replace/delete a statement/fluent block by containing text, replace an inclusive fromText/toText range, or replace a whole file. For exact code.direct_edit/code.semantic_guess_edit/vfs.manage edits, this can run right after start_wave_task in context phase when args include exact path plus startLine/endLine/text, edits:[...], oldText/newText, deleteStatementContaining, replaceBlockContaining, blockContaining, or replaceBetween; no separate advance_wave_task is needed. mode is optional: oldText infers replaceText, edits:[{startLine,endLine,text}] infers multiLineEdits, edits:[{rangeOffset,rangeLength,text}] infers multiTextEdits, startLine/endLine infers replaceLines, block/between fields infer block line replacement, and path+text/content with no oldText infers whole-file replacement. Do not pass baseHash for simple edits; Studio resolves the latest file contentHash and still applies stale-write checks. Empty replacement text deletes. Prefer blockContaining/deleteStatementContaining over fragile line numbers when editing fluent Wave chains. Use ensureBlankLineAfter:true when replacing a line block that should keep one blank separator before the following code. Prefer text/newText; replacement/content are accepted aliases. Response begins with resultSummary: EDIT APPLIED or EDIT NOT APPLIED, and includes editMode/editTarget plus changedPaths/changedFiles. After the final code edit, prefer awaitHotReload:true so preview refresh and bounded diagnostics return in the same response; use requestHotReload:true only when you want fire-and-poll. Inspect changedPaths/changedFiles/partial/skippedOperations/hotReloadRequested/hotReloadSkippedReason/runtimeVerification; ok:true can still mean no content changed.${HOT_RELOAD_UNSAFE_CALLBACK_NOTE}${MANAGED_STUDIO_FILE_READONLY_NOTE}${WRITE_PAIRING_REQUIRED_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
48860
+ description: `[studio.vfs] PRIMARY forgiving one-file edit tool. Use this first for simple code edits: replace exact text, replace/delete a 1-based inclusive full-file line range, apply several one-file line/text edits through edits:[...], replace/delete a statement/fluent block by containing text, replace an inclusive fromText/toText range, or replace a whole file. For exact code.direct_edit/code.semantic_guess_edit/vfs.manage edits, this can run right after start_wave_task in context phase when args include exact path plus startLine/endLine/text, edits:[...], oldText/newText, deleteStatementContaining, replaceBlockContaining, blockContaining, or replaceBetween; no separate advance_wave_task is needed. mode is optional: oldText infers replaceText, edits:[{startLine,endLine,text}] infers multiLineEdits, edits:[{rangeOffset,rangeLength,text}] infers multiTextEdits, startLine/endLine infers replaceLines, block/between fields infer block line replacement, and path+text/content with no oldText infers whole-file replacement. Do not pass baseHash for simple edits; Studio resolves the latest file contentHash and still applies stale-write checks. Empty replacement text deletes. Prefer blockContaining/deleteStatementContaining over fragile line numbers when editing fluent Wave chains. Use ensureBlankLineAfter:true when replacing a line block that should keep one blank separator before the following code. Prefer text/newText; replacement/content are accepted aliases. Response begins with resultSummary: EDIT APPLIED or EDIT NOT APPLIED, and includes editMode/editTarget plus changedPaths/changedFiles. After the final code edit, prefer awaitHotReload:true so preview refresh and bounded diagnostics return in the same response; requestHotReload:true also waits by default unless awaitHotReload:false is passed intentionally. Inspect changedPaths/changedFiles/partial/skippedOperations/hotReloadRequested/hotReloadSkippedReason/runtimeVerification; ok:true can still mean no content changed.${HOT_RELOAD_UNSAFE_CALLBACK_NOTE}${MANAGED_STUDIO_FILE_READONLY_NOTE}${WRITE_PAIRING_REQUIRED_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
48774
48861
  inputSchema: {
48775
48862
  type: "object",
48776
48863
  properties: {
@@ -48867,7 +48954,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48867
48954
  requestHotReload: {
48868
48955
  type: "boolean",
48869
48956
  default: false,
48870
- description: "Default false. Set true on the final code edit when preview should update through hot reload. If the result returns hotReloadRequested false, no preview refresh was scheduled."
48957
+ description: "Default false. Set true on the final code edit when preview should update through hot reload. Also waits for bounded diagnostics unless awaitHotReload:false is passed intentionally. If hotReloadRequested is false, no preview refresh was scheduled."
48871
48958
  },
48872
48959
  ...HOT_RELOAD_RUNTIME_DIAGNOSTIC_SCHEMA_PROPERTIES,
48873
48960
  idempotencyKey: { type: "string" }
@@ -48879,7 +48966,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48879
48966
  },
48880
48967
  {
48881
48968
  name: "create_wave_file",
48882
- description: `[studio.vfs] Create/add one exact file path in the paired live Wave Studio browser VFS, including new TypeScript modules such as /actors/player.ts and HTML sketches such as /docs/diagram.html. Natural-language aliases: add file, create ts file, create html file, make module, make diagram, make chart. Requires exact path and full initial content; if either is missing, ask or read context instead of inventing. New .ts/.tsx files are standalone runnable source roots by default, so top-level scene code in a new file runs on Run/hot reload; set runnable:false only for pure helper modules that must not execute on their own. For Mermaid chart requests, create a .html file containing a \`<div class="mermaid">...</div>\` block; active HTML files preview in Studio and auto-load Mermaid when \`class="mermaid"\` is present. Helper modules imported by main files may not receive Studio wrapper globals; export functions that accept myScene, asset refs, or entities from main unless current code proves otherwise. Creates missing folders, refuses existing file/folder paths unless overwrite:true is explicitly supplied, and requires a write-capable pairing. Prefer awaitHotReload:true so create + hot reload + bounded diagnostics return in one response; use requestHotReload:true only for fire-and-poll.${HOT_RELOAD_UNSAFE_CALLBACK_NOTE}${MANAGED_STUDIO_FILE_READONLY_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
48969
+ description: `[studio.vfs] Create/add one exact file path in the paired live Wave Studio browser VFS, including new TypeScript modules such as /actors/player.ts and HTML sketches such as /docs/diagram.html. Natural-language aliases: add file, create ts file, create html file, make module, make diagram, make chart. Requires exact path and full initial content; if either is missing, ask or read context instead of inventing. New .ts/.tsx files are standalone runnable source roots by default, so top-level scene code in a new file runs on Run/hot reload; set runnable:false only for pure helper modules that must not execute on their own. For Mermaid chart requests, create a .html file containing a \`<div class="mermaid">...</div>\` block; active HTML files preview in the editor/coding pane and auto-load Mermaid when \`class="mermaid"\` is present. They must never replace the live engine preview iframe. Helper modules imported by main files may not receive Studio wrapper globals; export functions that accept myScene, asset refs, or entities from main unless current code proves otherwise. Creates missing folders, refuses existing file/folder paths unless overwrite:true is explicitly supplied, and requires a write-capable pairing. Prefer awaitHotReload:true so create + hot reload + bounded diagnostics return in one response; requestHotReload:true also waits by default unless awaitHotReload:false is passed intentionally.${HOT_RELOAD_UNSAFE_CALLBACK_NOTE}${MANAGED_STUDIO_FILE_READONLY_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
48883
48970
  inputSchema: {
48884
48971
  type: "object",
48885
48972
  properties: {
@@ -48913,7 +49000,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48913
49000
  },
48914
49001
  requestHotReload: {
48915
49002
  type: "boolean",
48916
- description: "Fire-and-poll hot reload flag. Prefer awaitHotReload:true when the created file is already imported by the running scene and the response should include bounded runtime diagnostics."
49003
+ description: "Set true when the created file affects the running scene and preview should refresh through hot reload. Also waits for bounded diagnostics unless awaitHotReload:false is passed intentionally."
48917
49004
  },
48918
49005
  ...HOT_RELOAD_RUNTIME_DIAGNOSTIC_SCHEMA_PROPERTIES,
48919
49006
  idempotencyKey: { type: "string" }
@@ -48944,7 +49031,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48944
49031
  to: { type: "string" },
48945
49032
  requestHotReload: {
48946
49033
  type: "boolean",
48947
- description: "Set true when the moved/renamed module affects the running scene and the preview should refresh through hot reload."
49034
+ description: "Set true when the moved/renamed module affects the running scene and preview should refresh through hot reload. Also waits for bounded diagnostics unless awaitHotReload:false is passed intentionally."
48948
49035
  },
48949
49036
  ...HOT_RELOAD_RUNTIME_DIAGNOSTIC_SCHEMA_PROPERTIES,
48950
49037
  idempotencyKey: { type: "string" }
@@ -48970,7 +49057,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48970
49057
  },
48971
49058
  requestHotReload: {
48972
49059
  type: "boolean",
48973
- description: "Set true when the deleted module affects the running scene after imports have been updated and the preview should refresh through hot reload."
49060
+ description: "Set true when the deleted module affects the running scene after imports have been updated and preview should refresh through hot reload. Also waits for bounded diagnostics unless awaitHotReload:false is passed intentionally."
48974
49061
  },
48975
49062
  ...HOT_RELOAD_RUNTIME_DIAGNOSTIC_SCHEMA_PROPERTIES,
48976
49063
  idempotencyKey: { type: "string" }
@@ -48981,7 +49068,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48981
49068
  },
48982
49069
  {
48983
49070
  name: "apply_wave_patch",
48984
- description: `[studio.vfs] ADVANCED grouped edit tool. Use only for grouped/multi-file operations, strict searchReplace, unifiedDiff, or complex stale-checked edits. For simple one-file edits use edit_wave_file. Prefer operations:[...], but a single operation object is accepted via operation or as a bare call for agent mistake recovery. Existing-file writeFile requires baseHash unless forceOverwrite is true. Do not send multiple compact ops for the same file with the same baseHash; the first edit changes the file hash and later compact ops will skip as stale. ok:true can still be a no-op or partial result; always inspect changedFiles, changedPaths, partial, skippedOperations, hotReloadRequested, hotReloadSkippedReason, and runtimeVerification. After the final grouped code edit, prefer awaitHotReload:true when preview already ran; use requestHotReload:true only when you want fire-and-poll. Studio may upgrade that hot-reload request internally to patchMain, preserveScene, or hard rebuildScene; do not edit bootstrap manually just to register assets. Use run_wave_preview only if diagnostics show hasRunSucceeded false, the user explicitly asked for a full restart, or hot reload is stuck/failing.${HOT_RELOAD_UNSAFE_CALLBACK_NOTE}${MANAGED_STUDIO_FILE_READONLY_NOTE}${WRITE_PAIRING_REQUIRED_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
49071
+ description: `[studio.vfs] ADVANCED grouped edit tool. Use only for grouped/multi-file operations, strict searchReplace, unifiedDiff, or complex stale-checked edits. For simple one-file edits use edit_wave_file. Prefer operations:[...], but a single operation object is accepted via operation or as a bare call for agent mistake recovery. Existing-file writeFile requires baseHash unless forceOverwrite is true. Do not send multiple compact ops for the same file with the same baseHash; the first edit changes the file hash and later compact ops will skip as stale. ok:true can still be a no-op or partial result; always inspect changedFiles, changedPaths, partial, skippedOperations, hotReloadRequested, hotReloadSkippedReason, and runtimeVerification. After the final grouped code edit, prefer awaitHotReload:true when preview already ran; requestHotReload:true also waits by default unless awaitHotReload:false is passed intentionally. Studio may upgrade that hot-reload request internally to patchMain, preserveScene, or hard rebuildScene; do not edit bootstrap manually just to register assets. Use run_wave_preview only if diagnostics show hasRunSucceeded false, the user explicitly asked for a full restart, or hot reload is stuck/failing.${HOT_RELOAD_UNSAFE_CALLBACK_NOTE}${MANAGED_STUDIO_FILE_READONLY_NOTE}${WRITE_PAIRING_REQUIRED_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
48985
49072
  inputSchema: {
48986
49073
  type: "object",
48987
49074
  properties: {
@@ -48989,7 +49076,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48989
49076
  requestHotReload: {
48990
49077
  type: "boolean",
48991
49078
  default: false,
48992
- description: "Default false. Set true after the final code edit when preview should update through hot reload. If the result returns hotReloadRequested false, no preview refresh was scheduled; inspect hotReloadSkippedReason/skippedOperations."
49079
+ description: "Default false. Set true after the final code edit when preview should update through hot reload. Also waits for bounded diagnostics unless awaitHotReload:false is passed intentionally. If hotReloadRequested is false, inspect hotReloadSkippedReason/skippedOperations."
48993
49080
  },
48994
49081
  ...HOT_RELOAD_RUNTIME_DIAGNOSTIC_SCHEMA_PROPERTIES,
48995
49082
  idempotencyKey: { type: "string" },
@@ -49189,14 +49276,14 @@ function buildHostedWaveStudioMcpToolDefinitions() {
49189
49276
  },
49190
49277
  {
49191
49278
  name: "hot_reload_wave_preview",
49192
- description: `[studio.preview] Default standalone tool for seeing code-change results in an already-running Wave Studio preview when no edit tool is being called. Natural-language aliases: hot reload, reload preview, refresh preview after edit, refresh scene. Trigger the same hot-reload path as Wave Studio's toolbar button through the paired browser session. In multi-file VFS projects, this tool has no file path argument and reloads the currently open/active TypeScript file when safe, not every user-created .ts module. Before calling it for a specific module, make sure that module is the active Studio editor file. For code edits, prefer the edit tool's awaitHotReload:true on the final edit to pair the change, hot reload, and bounded diagnostics in one MCP response; use requestHotReload:true only for intentional fire-and-poll. Studio may upgrade this same request internally to patchMain, preserveScene, or hard rebuildScene when asset/bootstrap/runtime-surface changes require it; agents should not manually guess the tier. This tool confirms the request was accepted, not that runtime execution has finished; use returned requestedAt and poll diagnostics until lastRuntimeOutcomeAt is newer and lastRuntimeOutcome is success or error, then inspect latestError/screenshot/entity snapshots. If hot reload gets stuck or fails, run_wave_preview is the last-resort full restart.${WRITE_PAIRING_REQUIRED_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
49279
+ description: `[studio.preview] Default standalone tool for seeing code-change results in an already-running Wave Studio preview when no edit tool is being called. Natural-language aliases: hot reload, reload preview, refresh preview after edit, refresh scene. Trigger the same hot-reload path as Wave Studio's toolbar button through the paired browser session. In multi-file VFS projects, this tool has no file path argument and reloads the currently open/active TypeScript file when safe, not every user-created .ts module. Before calling it for a specific module, make sure that module is the active Studio editor file. For code edits, prefer the edit tool's awaitHotReload:true on the final edit to pair the change, hot reload, and bounded diagnostics in one MCP response. Studio may upgrade this same request internally to patchMain, preserveScene, or hard rebuildScene when asset/bootstrap/runtime-surface changes require it; agents should not manually guess the tier. By default this tool waits for bounded runtime diagnostics and returns runtimeVerification; set awaitRuntimeResult:false only for intentional fire-and-poll. If hot reload gets stuck or fails, run_wave_preview is the last-resort full restart.${WRITE_PAIRING_REQUIRED_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
49193
49280
  inputSchema: {
49194
49281
  type: "object",
49195
49282
  properties: {
49196
49283
  idempotencyKey: { type: "string" },
49197
49284
  awaitRuntimeResult: {
49198
49285
  type: "boolean",
49199
- description: "When true, wait in the same MCP call for bounded runtime diagnostics after the hot-reload request. Response includes runtimeVerification."
49286
+ description: "Default true. Wait in the same MCP call for bounded runtime diagnostics after the hot-reload request. Set false only for intentional fire-and-poll."
49200
49287
  },
49201
49288
  awaitDiagnostics: {
49202
49289
  type: "boolean",
@@ -49210,14 +49297,14 @@ function buildHostedWaveStudioMcpToolDefinitions() {
49210
49297
  },
49211
49298
  {
49212
49299
  name: "run_wave_preview",
49213
- description: `[studio.preview] Trigger a full Wave Studio preview run/start through the paired browser session. Natural-language aliases: run project, start preview, start project, full restart, restart scene, kick the scene again. Do not use this as the normal post-edit path; use edit-tool awaitHotReload:true after edits or standalone hot_reload_wave_preview for preview refresh first. Use run only when diagnostics show hasRunSucceeded false, the user explicitly asks for a full restart, or hot reload/polling fails and a full restart is the last resort. This tool confirms the request was accepted, not that runtime execution has finished; use returned requestedAt and poll diagnostics until lastRuntimeOutcomeAt is newer and lastRuntimeOutcome is success or error, then inspect latestError/screenshot/entity snapshots.${WRITE_PAIRING_REQUIRED_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
49300
+ description: `[studio.preview] Trigger a full Wave Studio preview run/start through the paired browser session. Natural-language aliases: run project, start preview, start project, full restart, restart scene, kick the scene again. Do not use this as the normal post-edit path; use edit-tool awaitHotReload:true after edits or standalone hot_reload_wave_preview for preview refresh first. Use run only when diagnostics show hasRunSucceeded false, the user explicitly asks for a full run/restart, or hot reload/polling fails and a full restart is the last resort. By default this tool waits for bounded runtime diagnostics and returns runtimeVerification; set awaitRuntimeResult:false only for intentional fire-and-poll.${WRITE_PAIRING_REQUIRED_NOTE}${BROWSER_COMMAND_PENDING_NOTE}`,
49214
49301
  inputSchema: {
49215
49302
  type: "object",
49216
49303
  properties: {
49217
49304
  idempotencyKey: { type: "string" },
49218
49305
  awaitRuntimeResult: {
49219
49306
  type: "boolean",
49220
- description: "When true, wait in the same MCP call for bounded runtime diagnostics after the run request. Response includes runtimeVerification."
49307
+ description: "Default true. Wait in the same MCP call for bounded runtime diagnostics after the run request. Set false only for intentional fire-and-poll."
49221
49308
  },
49222
49309
  awaitDiagnostics: {
49223
49310
  type: "boolean",
@@ -49330,10 +49417,10 @@ function buildHostedWaveStudioMcpToolDefinitions() {
49330
49417
  }
49331
49418
 
49332
49419
  // ../../scripts/wavegenie-sdk/mcp/toolDefinitions.ts
49333
- var CANONICAL_HOSTED_TOOL_NAMES = new Set(
49420
+ var CANONICAL_WAVE_MCP_TOOL_NAMES = new Set(
49334
49421
  buildHostedWaveStudioMcpToolDefinitions().map((definition) => definition.name)
49335
49422
  );
49336
- var HOSTED_REFERENCE_TOOL_NAMES = /* @__PURE__ */ new Set([
49423
+ var LOCAL_SDK_LOOKUP_TOOL_NAMES = /* @__PURE__ */ new Set([
49337
49424
  "get_wave_coding_guardrails",
49338
49425
  "list_wave_skill_families",
49339
49426
  "query_wave_skills",
@@ -49399,6 +49486,28 @@ var LOCAL_OPTIONAL_SESSION_TOOL_NAMES = /* @__PURE__ */ new Set([
49399
49486
  "resume_wave_preview",
49400
49487
  "resume_wave_engine"
49401
49488
  ]);
49489
+ var LOCAL_SDK_CONTROL_TOOL_NAMES = /* @__PURE__ */ new Set([
49490
+ "get_wave_agent_onboarding",
49491
+ "accept_wave_agent_onboarding",
49492
+ "self_check_wave_mcp",
49493
+ "list_wave_sessions",
49494
+ "get_active_wave_session",
49495
+ "recover_wave_connection",
49496
+ "start_wave_task",
49497
+ "advance_wave_task",
49498
+ "get_wave_task_route",
49499
+ "get_wave_tool_map",
49500
+ "get_wave_mcp_health",
49501
+ "get_wave_command_result"
49502
+ ]);
49503
+ var LOCAL_SDK_IMPLEMENTED_CANONICAL_TOOL_NAMES = /* @__PURE__ */ new Set([
49504
+ ...LOCAL_SDK_CONTROL_TOOL_NAMES,
49505
+ ...LOCAL_SDK_LOOKUP_TOOL_NAMES,
49506
+ ...[...LOCAL_OPTIONAL_SESSION_TOOL_NAMES].map((name) => canonicalizeWaveMcpToolName(name))
49507
+ ]);
49508
+ function isLocalMcpToolImplemented(name) {
49509
+ return LOCAL_SDK_IMPLEMENTED_CANONICAL_TOOL_NAMES.has(canonicalizeWaveMcpToolName(name));
49510
+ }
49402
49511
  function getReadToolDefinitions() {
49403
49512
  return [
49404
49513
  {
@@ -49554,13 +49663,13 @@ function localizeHostedToolDefinition(definition, localOverrides) {
49554
49663
  if (definition.name === "get_wave_session") {
49555
49664
  description = "[studio.mcp] Return the Wave Studio browser session paired through the WaveEngine Agent SDK.";
49556
49665
  } else if (definition.name === "recover_wave_connection") {
49557
- description = "[studio.mcp] Direct Observe recovery tool for WaveEngine Agent SDK. Call after session_not_found, command_timeout, command_lease_expired, agent_onboarding_required, hosted_mcp_proxy_failed, or local/HTTP Gateway/cache confusion. Returns exact next action: re-onboard, get session, wake Wave Studio tab, update/restart SDK, retry same tool, use HTTP Gateway fallback, or ask fresh Copy to Agent only if token is rejected everywhere.";
49666
+ description = "[studio.mcp] Direct Observe recovery tool for WaveEngine Agent SDK. Call after session_not_found, command_timeout, command_lease_expired, agent_onboarding_required, local_sdk_tool_not_implemented, wave_engine_sdk_cache_required, or local/HTTP Gateway/cache confusion. Returns exact next action: re-onboard, get session, wake Wave Studio tab, update/restart SDK, retry same tool, use HTTP Gateway fallback, or ask fresh Copy to Agent only if token is rejected everywhere.";
49558
49667
  } else if (definition.name === "get_wave_command_result") {
49559
49668
  description = '[studio.mcp] Use only when a prior tool response includes status:"pending" plus requestId. Catalog-parity tool for agents trained on the HTTP Gateway. WaveEngine Agent SDK browser-backed tools normally wait for the Studio browser result directly, so this usually reports that no local pending-command queue is used.';
49560
49669
  } else if (definition.name === "get_wave_coding_guardrails") {
49561
49670
  description = "[studio.mcp] Return compact Wave Studio coding guardrails. WaveEngine Agent SDK answers from bundled SDK/onboarding. HTTP Gateway remains Studio-ops-only and has no cloud API lookup.";
49562
49671
  } else if (definition.name === "get_wave_tool_map") {
49563
- description = "[studio.mcp] Stable local MCP tool map. Always returns the full concrete local/hosted-parity catalog grouped by family plus policy flags.";
49672
+ description = "[studio.mcp] Stable local MCP tool map. Returns the concrete local SDK catalog grouped by family plus handler-parity and policy flags.";
49564
49673
  } else if (definition.name === "get_wave_mcp_health") {
49565
49674
  description = "[studio.mcp] Read-only WaveEngine Agent SDK health/status. Reports actual local SDK version/build, tool catalog hash/count, current transport, paired browser sessions, onboarding state, active route, and WaveEngine SDK Cache existence/version/staleness. Aliases: mcp_health, mcp_status, get_wave_mcp_status.";
49566
49675
  } else if (definition.name === "list_wave_skill_families") {
@@ -49594,25 +49703,35 @@ function localizeHostedToolDefinition(definition, localOverrides) {
49594
49703
  }
49595
49704
  function mergeLocalToolDefinitions(canonicalDefinitions) {
49596
49705
  const localOverrides = getLocalOverrideToolDefinitions();
49597
- const localizedDefinitions = canonicalDefinitions.map((definition) => localizeHostedToolDefinition(definition, localOverrides));
49706
+ const localizedDefinitions = canonicalDefinitions.filter((definition) => isLocalMcpToolImplemented(definition.name)).map((definition) => localizeHostedToolDefinition(definition, localOverrides));
49598
49707
  const byName = new Map(localizedDefinitions.map((definition) => [definition.name, definition]));
49599
49708
  for (const definition of localOverrides.values()) {
49600
49709
  byName.set(definition.name, definition);
49601
49710
  }
49602
49711
  const definitions = [...byName.values()];
49603
- assertLocalToolDefinitionParity(canonicalDefinitions, definitions);
49712
+ assertLocalToolDefinitionHandlerParity(definitions);
49604
49713
  return definitions;
49605
49714
  }
49606
- function assertLocalToolDefinitionParity(canonicalDefinitions, localDefinitions) {
49607
- const localNames = new Set(localDefinitions.map((definition) => definition.name));
49608
- const missingNames = canonicalDefinitions.map((definition) => definition.name).filter((name) => !localNames.has(name));
49609
- if (missingNames.length > 0) {
49610
- throw new Error(`Local MCP tool catalog missing canonical Hosted MCP tools: ${missingNames.join(", ")}`);
49715
+ function assertLocalToolDefinitionHandlerParity(localDefinitions) {
49716
+ const unimplementedNames = localDefinitions.map((definition) => definition.name).filter((name) => !isLocalMcpToolImplemented(name));
49717
+ if (unimplementedNames.length > 0) {
49718
+ throw new Error(`Local MCP tool catalog includes tools without local handlers: ${unimplementedNames.join(", ")}`);
49611
49719
  }
49612
49720
  }
49613
49721
  function getLocalToolDefinitions() {
49614
49722
  return mergeLocalToolDefinitions(buildHostedWaveStudioMcpToolDefinitions());
49615
49723
  }
49724
+ function getLocalToolImplementationSummary() {
49725
+ const canonicalToolNames = [...CANONICAL_WAVE_MCP_TOOL_NAMES].sort();
49726
+ const implementedCanonicalToolNames = canonicalToolNames.filter((name) => isLocalMcpToolImplemented(name));
49727
+ return {
49728
+ canonicalToolCount: canonicalToolNames.length,
49729
+ implementedCanonicalToolCount: implementedCanonicalToolNames.length,
49730
+ localExtraToolNames: [...LOCAL_EXTRA_TOOL_DEFINITION_NAMES].sort(),
49731
+ localLookupToolNames: [...LOCAL_SDK_LOOKUP_TOOL_NAMES].sort(),
49732
+ omittedCanonicalToolNames: canonicalToolNames.filter((name) => !isLocalMcpToolImplemented(name))
49733
+ };
49734
+ }
49616
49735
  function getLocalToolCatalogHash() {
49617
49736
  const tools = getLocalToolDefinitions().map((definition) => ({
49618
49737
  name: definition.name,
@@ -49626,6 +49745,16 @@ function getLocalToolCatalogHash() {
49626
49745
  function nowIso() {
49627
49746
  return (/* @__PURE__ */ new Date()).toISOString();
49628
49747
  }
49748
+ function localSdkLookupStatus(waveEngineSdkCache) {
49749
+ const corpusCacheReady = waveEngineSdkCache.ready === true;
49750
+ return {
49751
+ source: "package_bundled_wave_engine_sdk_cache",
49752
+ corpusCacheReady,
49753
+ apiAndSkillQueryAvailable: corpusCacheReady,
49754
+ cacheMissAffectsLiveStudioTransport: false,
49755
+ lookupToolNames: [...LOCAL_SDK_LOOKUP_TOOL_NAMES].sort()
49756
+ };
49757
+ }
49629
49758
  function jsonRpcToolIdempotencyKey(toolName, requestId) {
49630
49759
  if (typeof requestId !== "string" && typeof requestId !== "number") return null;
49631
49760
  return `jsonrpc:${toolName}:${String(requestId)}`;
@@ -49814,7 +49943,12 @@ function localConnectionRecoveryResult(args, context) {
49814
49943
  nextAction = "Read tools can continue. For write/run/hot reload, user must make the Studio MCP session read-write/adopt WaveEngine Agent SDK, then retry same local endpoint and MCP_TOKEN pairing secret or paste fresh Copy to Agent if the secret changed.";
49815
49944
  nextTool = "get_wave_session";
49816
49945
  requiresUserAction = true;
49817
- } else if (lastErrorCode === "hosted_mcp_proxy_failed" || lastErrorCode === "wave_engine_sdk_cache_required") {
49946
+ } else if (lastErrorCode === "local_sdk_tool_not_implemented" || lastErrorCode === "local_sdk_lookup_handler_missing") {
49947
+ state = "local_sdk_handler_missing";
49948
+ nextAction = "This SDK build lacks a local handler for the requested canonical tool. Call tools/list and use a listed tool, or update/restart the exact SDK package.";
49949
+ nextTool = "tools/list";
49950
+ steps.push("Do not treat missing local handler as WaveEngine SDK Cache failure.");
49951
+ } else if (lastErrorCode === "wave_engine_sdk_cache_required") {
49818
49952
  state = "wave_engine_sdk_cache_unavailable";
49819
49953
  nextAction = "Live Studio tools can continue. Skill/API lookup cache failed; update/restart the exact SDK package or run the bundled SDK repair command. HTTP Gateway is Studio-ops-only.";
49820
49954
  nextTool = "get_wave_session";
@@ -49869,6 +50003,24 @@ function localConnectionRecoveryResult(args, context) {
49869
50003
  ]
49870
50004
  });
49871
50005
  }
50006
+ function localSdkToolNotImplementedResult(name) {
50007
+ return errorToolResult(
50008
+ "local_sdk_tool_not_implemented",
50009
+ `${name} is a canonical Wave MCP tool, but this WaveEngine Agent SDK build has no local handler for it. It is intentionally omitted from tools/list until implemented; update wave3d-agent-sdk or use a listed tool.`,
50010
+ {
50011
+ toolName: name,
50012
+ localSdk: true,
50013
+ missingLocalHandler: true,
50014
+ affectsLiveStudioTransport: false,
50015
+ affectsWaveEngineSdkCache: false,
50016
+ recovery: [
50017
+ "Call tools/list and choose one of the listed local tools.",
50018
+ "Update/restart the exact wave3d-agent-sdk package when you need this canonical tool locally.",
50019
+ "Do not treat this as wave_engine_sdk_cache_required; SDK cache repair cannot add a missing live-tool handler."
50020
+ ]
50021
+ }
50022
+ );
50023
+ }
49872
50024
  function taskRouteToolResult(route) {
49873
50025
  return successToolResult({
49874
50026
  ok: true,
@@ -49989,6 +50141,9 @@ function normalizeRuntimeDiagnosticsTimeoutMs2(value) {
49989
50141
  if (typeof value !== "number" || !Number.isFinite(value)) return void 0;
49990
50142
  return Math.min(Math.max(500, Math.trunc(value)), 15e3);
49991
50143
  }
50144
+ function shouldAwaitRuntimeActionDiagnostics(args) {
50145
+ return args?.awaitRuntimeResult !== false && args?.awaitDiagnostics !== false && args?.returnRuntimeDiagnostics !== false;
50146
+ }
49992
50147
  function resolveAssetCategoryBucket(value) {
49993
50148
  if (typeof value !== "string" || !value.trim()) return null;
49994
50149
  return getWaveStudioAssetBucketFromCategory(value.trim());
@@ -50142,12 +50297,15 @@ async function enqueueLocalAssetUploadCommand(input) {
50142
50297
  }
50143
50298
  async function callReadTool(name, args, context) {
50144
50299
  if (name === "get_wave_agent_onboarding") {
50300
+ const waveEngineSdkCache = await inspectLocalCorpusCacheForContext(context);
50145
50301
  return successToolResult({
50146
50302
  ok: true,
50147
50303
  promptVersion: LOCAL_MCP_AGENT_ONBOARDING_VERSION,
50148
50304
  promptHash: LOCAL_MCP_AGENT_ONBOARDING_PROMPT_HASH,
50149
50305
  prompt: LOCAL_MCP_AGENT_ONBOARDING_PROMPT,
50150
50306
  localSdk: true,
50307
+ waveEngineSdkCache,
50308
+ waveEngineSdkLookup: localSdkLookupStatus(waveEngineSdkCache),
50151
50309
  onboardingPhases: [
50152
50310
  { phase: -1, required: true, action: "Treat Copy-to-Agent as bootstrap only", fallback: "Use this MCP response as the current source of truth for phased setup, recovery, routing, cache, and tool policy. If clipboard text and MCP response differ, prefer MCP response." },
50153
50311
  { phase: 0, required: false, action: "WaveEngine Agent SDK preflight", fallback: "Already satisfied because this endpoint is local." },
@@ -50302,6 +50460,8 @@ async function callReadTool(name, args, context) {
50302
50460
  }
50303
50461
  if (name === "self_check_wave_mcp") {
50304
50462
  const toolDefinitions = getLocalToolDefinitions();
50463
+ const toolImplementation = getLocalToolImplementationSummary();
50464
+ const waveEngineSdkCache = await inspectLocalCorpusCacheForContext(context);
50305
50465
  const sessions = getAuthorizedSessions(context);
50306
50466
  const activeRoute = getLocalActiveTaskRoute(context);
50307
50467
  const expectedVersion = normalizeOptionalString(args?.expectedVersion);
@@ -50331,8 +50491,12 @@ async function callReadTool(name, args, context) {
50331
50491
  hasHotReload: toolDefinitions.some((definition) => definition.name === "hot_reload_wave_preview"),
50332
50492
  hasPauseResume: toolDefinitions.some((definition) => definition.name === "pause_wave_preview") && toolDefinitions.some((definition) => definition.name === "resume_wave_preview"),
50333
50493
  hasAssetCategorySearch: toolDefinitions.some((definition) => definition.name === "find_wave_assets_by_category"),
50334
- hasProjectRename: toolDefinitions.some((definition) => definition.name === "rename_wave_project")
50494
+ hasProjectRename: toolDefinitions.some((definition) => definition.name === "rename_wave_project"),
50495
+ listedToolsHaveLocalHandlers: true,
50496
+ implementation: toolImplementation
50335
50497
  },
50498
+ waveEngineSdkCache,
50499
+ waveEngineSdkLookup: localSdkLookupStatus(waveEngineSdkCache),
50336
50500
  sessions: {
50337
50501
  pairedStudioSessionCount: sessions.length,
50338
50502
  readwriteSessionCount: sessions.filter((session) => session.accessMode === "readwrite").length
@@ -50347,6 +50511,7 @@ async function callReadTool(name, args, context) {
50347
50511
  }
50348
50512
  if (name === "get_wave_mcp_health") {
50349
50513
  const toolDefinitions = getLocalToolDefinitions();
50514
+ const toolImplementation = getLocalToolImplementationSummary();
50350
50515
  const sessions = getAuthorizedSessions(context);
50351
50516
  const activeRoute = getLocalActiveTaskRoute(context);
50352
50517
  const waveEngineSdkCache = await inspectLocalCorpusCacheForContext(context);
@@ -50388,7 +50553,9 @@ async function callReadTool(name, args, context) {
50388
50553
  hasPauseResume: toolDefinitions.some((definition) => definition.name === "pause_wave_preview") && toolDefinitions.some((definition) => definition.name === "resume_wave_preview"),
50389
50554
  hasAssetCategorySearch: toolDefinitions.some((definition) => definition.name === "find_wave_assets_by_category"),
50390
50555
  hasMcpHealth: toolDefinitions.some((definition) => definition.name === "get_wave_mcp_health"),
50391
- hasProjectRename: toolDefinitions.some((definition) => definition.name === "rename_wave_project")
50556
+ hasProjectRename: toolDefinitions.some((definition) => definition.name === "rename_wave_project"),
50557
+ listedToolsHaveLocalHandlers: true,
50558
+ implementation: toolImplementation
50392
50559
  },
50393
50560
  onboarding: {
50394
50561
  accepted: onboardingAccepted,
@@ -50396,6 +50563,7 @@ async function callReadTool(name, args, context) {
50396
50563
  promptHash: LOCAL_MCP_AGENT_ONBOARDING_PROMPT_HASH
50397
50564
  },
50398
50565
  waveEngineSdkCache,
50566
+ waveEngineSdkLookup: localSdkLookupStatus(waveEngineSdkCache),
50399
50567
  sessions: {
50400
50568
  pairedStudioSessionCount: sessions.length,
50401
50569
  readwriteSessionCount: sessions.filter((session) => session.accessMode === "readwrite").length,
@@ -50425,6 +50593,7 @@ async function callReadTool(name, args, context) {
50425
50593
  stableToolMap: true,
50426
50594
  toolCatalogHash: getLocalToolCatalogHash(),
50427
50595
  toolCount: toolDefinitions.length,
50596
+ toolImplementation: getLocalToolImplementationSummary(),
50428
50597
  toolCatalogSummary: buildWaveMcpToolCatalogSummary(toolDefinitions),
50429
50598
  studioSkillMap: [
50430
50599
  "studio.mcp: get_wave_mcp_health (aliases: mcp_health, mcp_status), get_wave_session, recover_wave_connection, get_wave_command_result, get_wave_coding_guardrails, get_wave_tool_map",
@@ -50447,8 +50616,8 @@ async function callReadTool(name, args, context) {
50447
50616
  if (name === "recover_wave_connection") {
50448
50617
  return localConnectionRecoveryResult(args, context);
50449
50618
  }
50450
- if (HOSTED_REFERENCE_TOOL_NAMES.has(name)) {
50451
- return await proxyHostedReferenceTool({
50619
+ if (LOCAL_SDK_LOOKUP_TOOL_NAMES.has(name)) {
50620
+ return await runLocalSdkLookupTool({
50452
50621
  context,
50453
50622
  name,
50454
50623
  args
@@ -50575,7 +50744,7 @@ async function callReadTool(name, args, context) {
50575
50744
  command: {
50576
50745
  type: "runtimeAction",
50577
50746
  action,
50578
- awaitRuntimeResult: args?.awaitRuntimeResult === true || args?.awaitDiagnostics === true,
50747
+ awaitRuntimeResult: shouldAwaitRuntimeActionDiagnostics(args),
50579
50748
  ...runtimeDiagnosticsTimeoutMs !== void 0 ? { runtimeDiagnosticsTimeoutMs } : {},
50580
50749
  ...runtimeDiagnosticsLimit !== void 0 ? { runtimeDiagnosticsLimit } : {}
50581
50750
  }
@@ -50982,8 +51151,8 @@ async function callReadTool(name, args, context) {
50982
51151
  if (!session) {
50983
51152
  return errorToolResult("session_not_found", LOCAL_SESSION_NOT_FOUND_MESSAGE);
50984
51153
  }
50985
- const projectId = requireNonEmptyString(stringAliasArg(args, ["projectId", "id", "project"]));
50986
- if (!projectId) return errorToolResult("invalid_arguments", "`read_wave_project` requires a non-empty `projectId`.");
51154
+ const projectId = requireNonEmptyString(stringAliasArg(args, ["projectId", "id", "project", "url", "projectUrl", "shareUrl", "publishedUrl"]));
51155
+ if (!projectId) return errorToolResult("invalid_arguments", "`read_wave_project` requires a non-empty `projectId` or shared/published project URL.");
50987
51156
  return await enqueueBrowserCommand({
50988
51157
  context,
50989
51158
  session,
@@ -51028,12 +51197,8 @@ async function callReadTool(name, args, context) {
51028
51197
  timeoutMs: 3e4
51029
51198
  });
51030
51199
  }
51031
- if (CANONICAL_HOSTED_TOOL_NAMES.has(name)) {
51032
- return await proxyHostedReferenceTool({
51033
- context,
51034
- name,
51035
- args
51036
- });
51200
+ if (CANONICAL_WAVE_MCP_TOOL_NAMES.has(name)) {
51201
+ return localSdkToolNotImplementedResult(name);
51037
51202
  }
51038
51203
  return errorToolResult("tool_not_found", `Unknown WaveEngine Agent SDK tool: ${name}.`);
51039
51204
  }
@@ -51075,7 +51240,7 @@ async function handleWaveGenieMcpRequest(request, context) {
51075
51240
  });
51076
51241
  return createJsonRpcResult(request.id ?? null, {
51077
51242
  nextRecommendedTool: onboardingAccepted ? !hasPairedStudioSession ? "recover_wave_connection" : activeRoute ? activeRoute.phase === "lookup" ? "query_wave_api" : activeRoute.phase === "execute" ? "edit_wave_file" : "get_wave_task_route" : "get_wave_session" : "get_wave_agent_onboarding",
51078
- nextRecommendedAction: onboardingAccepted ? !hasPairedStudioSession ? "Call recover_wave_connection, then follow its nextAction to pair/wake the Wave Studio tab. Reference/cache tools can still run without a tab." : activeRoute ? activeRoute.phase === "lookup" ? "Lookup is unlocked; call query_wave_api only for exact symbol/signature/global uncertainty." : activeRoute.phase === "execute" ? "Execute is unlocked; call the specific edit/operate tool now." : "Inspect get_wave_task_route, then advance when enough evidence is collected." : "Call get_wave_session, then use observe tools or start_wave_task for authoring work." : "Call get_wave_agent_onboarding, accept the returned role/guardrails, then call tools/list again.",
51243
+ nextRecommendedAction: onboardingAccepted ? !hasPairedStudioSession ? "Call recover_wave_connection, then follow its nextAction to pair/wake the Wave Studio tab. SDK lookup/cache tools can still run without a tab." : activeRoute ? activeRoute.phase === "lookup" ? "Lookup is unlocked; call query_wave_api only for exact symbol/signature/global uncertainty." : activeRoute.phase === "execute" ? "Execute is unlocked; call the specific edit/operate tool now." : "Inspect get_wave_task_route, then advance when enough evidence is collected." : "Call get_wave_session, then use observe tools or start_wave_task for authoring work." : "Call get_wave_agent_onboarding, accept the returned role/guardrails, then call tools/list again.",
51079
51244
  requiresOnboarding: !onboardingAccepted,
51080
51245
  requiresStudioSessionForLiveTools: true,
51081
51246
  hasPairedStudioSession,
@@ -51088,6 +51253,10 @@ async function handleWaveGenieMcpRequest(request, context) {
51088
51253
  preTaskEvidence: activeRoute ? null : getLocalPreTaskEvidence(context),
51089
51254
  rule: WAVE_MCP_BEHAVIOR_HARNESS_RULE
51090
51255
  },
51256
+ toolImplementation: {
51257
+ listedToolsHaveLocalHandlers: true,
51258
+ ...getLocalToolImplementationSummary()
51259
+ },
51091
51260
  toolCatalogSummary: buildWaveMcpToolCatalogSummary(tools),
51092
51261
  tools
51093
51262
  });