wave3d-agent-sdk 0.2.15 → 0.2.17

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
@@ -546,10 +546,8 @@ var PROJECT_ASSET_ACCESSOR_BUCKETS = [
546
546
  ];
547
547
 
548
548
  // ../../wave-engine/dist/src/core/coreAbstractions/objectModel/waveModelMetadataKeys.js
549
- var WAVE_MODEL_PART_ID_METADATA_KEY = "waveModelPartId";
550
- var WAVE_MODEL_PART_NAME_METADATA_KEY = "waveModelPartName";
551
- var WAVE_MODEL_PART_METADATA_KEY = "waveModelPartMetadata";
552
549
  var WAVE_MODEL_RIG_GRAPH_METADATA_KEY = "waveModelRigGraphMetadata";
550
+ var WAVE_MODEL_OBJECT_MODEL_METADATA_KEY = "waveModelObjectModel";
553
551
 
554
552
  // ../../wave-engine/dist/src/core/coreAbstractions/objectModel/waveModelPartTypes.js
555
553
  var WaveModelPartScope;
@@ -41620,10 +41618,11 @@ function withAccessorBucketExtensions(buckets) {
41620
41618
  var WAVE_STUDIO_ENGINE_ASSET_TYPES = PROJECT_ASSET_TYPES;
41621
41619
  var WAVE_STUDIO_ENGINE_ACCESSOR_BUCKETS = withAccessorBucketExtensions(PROJECT_ASSET_ACCESSOR_BUCKETS);
41622
41620
  var WAVE_STUDIO_MODEL_METADATA_KEYS = Object.freeze({
41623
- partId: WAVE_MODEL_PART_ID_METADATA_KEY,
41624
- partName: WAVE_MODEL_PART_NAME_METADATA_KEY,
41625
- partMetadata: WAVE_MODEL_PART_METADATA_KEY,
41626
- rigGraph: WAVE_MODEL_RIG_GRAPH_METADATA_KEY
41621
+ objectModel: WAVE_MODEL_OBJECT_MODEL_METADATA_KEY,
41622
+ rigGraph: WAVE_MODEL_RIG_GRAPH_METADATA_KEY,
41623
+ partMetadata: "partMetadata",
41624
+ partId: "partId",
41625
+ partName: "partName"
41627
41626
  });
41628
41627
 
41629
41628
  // ../../src/lib/waveStudio/assets/contracts/waveStudioSerializedDataAssetContracts.ts
@@ -42533,8 +42532,8 @@ function normalizeWaveGenieAssetUploadRequest(request) {
42533
42532
 
42534
42533
  // ../../src/lib/waveStudio/aiAssist/bridge/localAgentSdkContract.ts
42535
42534
  var WAVE3D_AGENT_SDK_PACKAGE_NAME = "wave3d-agent-sdk";
42536
- var WAVE3D_AGENT_SDK_REQUIRED_VERSION = "0.2.15";
42537
- var WAVE3D_AGENT_SDK_REQUIRED_BUILD = "agent-sdk-20260627.1";
42535
+ var WAVE3D_AGENT_SDK_REQUIRED_VERSION = "0.2.17";
42536
+ var WAVE3D_AGENT_SDK_REQUIRED_BUILD = "agent-sdk-20260627.3";
42538
42537
  var WAVE3D_AGENT_SDK_PACKAGE_SPEC = `${WAVE3D_AGENT_SDK_PACKAGE_NAME}@${WAVE3D_AGENT_SDK_REQUIRED_VERSION}`;
42539
42538
  var WAVE3D_AGENT_SDK_START_COMMAND = `npx -y ${WAVE3D_AGENT_SDK_PACKAGE_SPEC} start`;
42540
42539
  var WAVE3D_AGENT_SDK_TOKEN_ENV_VAR = "WAVE3D_MCP_TOKEN";
@@ -44262,7 +44261,7 @@ var WAVE_AUTHORING_CORE_INTENT_STAMPS = [
44262
44261
  "State/mode/phase: entity state APIs such as enter/whenIn/onEnter/onExit/toggle/cycle/blockEnterFor before boolean flag machines.",
44263
44262
  "Reaction/observation: when(...).do(...), whenAccelerating()/whenDecelerating(), distance/speed/threshold/rate builders before manual polling or speed-delta state.",
44264
44263
  "Chance/variety: atChanceOf, cycleThrough, and choice APIs before raw Math.random gates.",
44265
- "Player/controller movement: wave.physics.kinematic-controller-authoring, waveKinematicActor<TState>, and actor-level asHumanoid/asVehicle/asFlight builders before Actor/waveActor, raw input polling, rigid-body forces, or per-tick movement loops.",
44264
+ "Player/controller movement: wave.physics.kinematic-controller-authoring, waveHumanoid for normal humanoid players, waveKinematicActor<TState> for vehicle/flight/generic controllers, and actor-level asHumanoid/asVehicle/asFlight builders before Actor/waveActor, raw input polling, rigid-body forces, or per-tick movement loops.",
44266
44265
  "Repetition/placement: repeat, placeAround, spawnAround, grid/group placement before manual spatial loops.",
44267
44266
  "Terrain/world population: wave.world.world-elements and scene.world/world bootstrap builders for forests, grass, rocks, water, entities, or custom content tied to terrain/streaming world surfaces. Prefer scene.world.scatter(...).renderAs(...).density(...).randomScale(...).apply() or world.scatter(...) before local spawn loops, scene placement, or instancing/batching.",
44268
44267
  "Terrain vs ground: myScene.terrain owns terrain recipe/controller state; myScene.ground is the camera-local live tile entity for visual overlays, callbacks, transform/tooling, and inspection only.",
@@ -44500,7 +44499,7 @@ var WAVE_MCP_AUTHORING_GLOBALS_GUIDE = [
44500
44499
  "- 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.",
44501
44500
  "- Direction and input enum-style globals: `Direction.X/Y/Z`, `Direction.Left/Right/Up/Down/Forward/Backward`, `Keyboard`, `MouseButton`, `GamepadButton`, `InputPhase`, `MovementMode`, `RotationMode`.",
44502
44501
  "- Colors/materials/fx helpers: `COLOR`, `PALETTE`, `waveCOLOR`, `waveMaterial`, `shaderUniform`, `waveFx`, `waveFxPresets`, `FxAnchor`, `FxCondition`.",
44503
- "- Controller movement helpers: `waveKinematicActor`, `netKinematicActor`, `KinematicHumanoidMovementState`, `KinematicVehicleMovementState`, and `KinematicFlightMovementState`. Use actor-level `.asHumanoid(...)`, `.asVehicle(...)`, or `.asFlight(...)` for player/controller movement.",
44502
+ "- Controller movement helpers: `waveHumanoid`, `netHumanoid`, `waveKinematicActor`, `netKinematicActor`, `KinematicHumanoidMovementState`, `KinematicVehicleMovementState`, and `KinematicFlightMovementState`. Use `waveHumanoid` plus `.useDefaultLocomotionAnimations()` for normal humanoid players; use `.asVehicle(...)` or `.asFlight(...)` on `waveKinematicActor<TState>` for vehicle/flight controllers.",
44504
44503
  "- Asset maps: use category-first refs returned by `find_wave_assets_by_category`, commonly `models`, `gaussianSplats`, `animations`, `vertexAnimations`, `materials`, `guis`, `textures`, `audios`, `instruments`, `videos`, `hdr`, `fonts`, `serializedData`, `terrains`, `fx`, and `particles`.",
44505
44504
  '- Scene/runtime handles: prefer `myScene` for scene composition and `waveStudio` for Studio operations. If authored UI changes bootstrap/world-provider/runtime-envelope state and needs the Studio preview package to rebuild, call `waveStudio.reloadPreview({ reason, invalidates: ["world-provider"] })`, not `myScene.hotReload(...)`. Valid invalidations are `bootstrap`, `world-provider`, and `runtime-envelope`; use the narrowest true reason. `assetManager` is available, but use it only when an exact skill/API names an asset-pipeline or generated-asset factory; do not use it as the default facade for existing asset refs or material authoring. Use lower-level `ctx`, `engine`, or `scene` only when existing code or an exact API requires them.',
44506
44505
  "- Authoring systems/presets: `waveEventBus`, `waveRig`, `waveValueCurve`, `waveValueCurvePresets`, `waveMotionSignal`, `waveParam`, `WaveParam`, `WaveChoice`, `prefabModels`, `effectPrefabs`, and prefab helpers such as `rocketPrefab`.",
@@ -44527,8 +44526,8 @@ var WAVE_MCP_CODING_GUARDRAIL = [
44527
44526
  "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.",
44528
44527
  '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.',
44529
44528
  '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.',
44530
- "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.",
44531
- "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.",
44529
+ "4f. For player/controller movement, route to `wave.physics.kinematic-controller-authoring`: use `waveHumanoid`/`netHumanoid` for humanoid player characters, and use `waveKinematicActor<TState>`/`netKinematicActor` with `.asVehicle(...)` or `.asFlight(...)` for vehicle/flight/generic controller movement. 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.",
44530
+ "4f1. For basic public humanoid locomotion animation, follow the kinematic-obby pattern: `new waveHumanoid().useModel(models.wave3dFemale).useDefaultLocomotionAnimations()`. For custom locomotion tuning or clip options, use `.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.",
44532
44531
  "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.",
44533
44532
  '4h. For semantic touch lifecycle such as "when contact starts/stops", "exactly once when touching begins/ends", "on hit", or projectile/target impact reactions, use `onContactBegin(...)`, `onContactContinue(...)`, `onContactEnd(...)`, or tag/target variants. Do not use removed `onCollision*` callback aliases; collision-named surfaces are for filtering, masks, groups, and actuation internals.',
44534
44533
  `4i. ${WAVE_AUTHORING_CORE_RULES.syncUserCode}`,
@@ -46027,7 +46026,7 @@ function markdownList(items, emptyText) {
46027
46026
  }
46028
46027
  var WAVE_OBJECT_MODEL_PARTS_CONTRACT = `## WaveEngine objectModel SSOT contract
46029
46028
 
46030
- When requiredParts is non-empty, or the user asks for named/selectable/collidable/material-addressable parts, the GLB must carry Wave objectModel metadata. Mesh names, ordered mesh arrays, and legacy partIds metadata are not source of truth.
46029
+ When requiredParts is non-empty, or the user asks for named/selectable/collidable/material-addressable parts, the GLB must carry Wave objectModel metadata. Mesh names, ordered mesh arrays, and per-mesh part metadata are not source of truth.
46031
46030
 
46032
46031
  Required GLB shape for part-aware output:
46033
46032
 
@@ -46043,18 +46042,13 @@ Required GLB shape for part-aware output:
46043
46042
  - \`parentPartId\` on child part records when parts have authored parent/child relationships
46044
46043
  - \`topology\`: include \`rootPartIds\` and \`joints: []\` only when a rig/joint topology is needed
46045
46044
  - \`materialSlots\` and \`materialBindings\`: canonical material targets when materials are meant to be changed by mesh or part
46046
- - Mirror only projection hints on each part-owned mesh metadata:
46047
- - \`waveModelPartId\`: canonical part id
46048
- - \`waveModelPartName\`: public part name users pass to \`getPart()\`
46049
- - \`waveModelPartMetadata\`: serializable part metadata when needed
46050
- - \`waveModelPartParentId\`: only when part has parent part
46051
46045
 
46052
46046
  Rules:
46053
46047
 
46054
46048
  - If user did not ask for parts, do not invent parts for every mesh. Output mesh-only GLB.
46055
46049
  - If a visual part contains multiple meshes, bind all meshes to the same part id.
46056
46050
  - Preserve authored pivots/origins as objectModel \`rotationPivot\` and \`visualFrame\`, not by baking them away.
46057
- - Do not write \`metadata.partIds\`, \`extras.partIds\`, mesh-name-derived part ids, or positional part arrays as source of truth.
46051
+ - Do not write old per-mesh part projection keys, legacy metadata part arrays, mesh-name-derived part ids, or positional part arrays.
46058
46052
  - Validate before upload: every required part name appears in \`objectModel.parts[].name\`, and every part-owned mesh has a matching \`meshPartBindings[]\` record.
46059
46053
  `;
46060
46054
  function buildModelingSupportFiles(input) {
@@ -46077,15 +46071,9 @@ function buildModelingSupportFiles(input) {
46077
46071
  required: true,
46078
46072
  envelopeNodeName: "__wave_model_object_model",
46079
46073
  envelopeMetadataKey: "waveModelObjectModel",
46080
- perMeshProjectionKeys: [
46081
- "waveModelPartId",
46082
- "waveModelPartName",
46083
- "waveModelPartMetadata",
46084
- "waveModelPartParentId"
46085
- ],
46086
46074
  forbiddenLegacyTruth: [
46087
- "metadata.partIds",
46088
- "extras.partIds",
46075
+ "old per-mesh part projection keys",
46076
+ "legacy metadata part arrays",
46089
46077
  "mesh-name-derived part ids",
46090
46078
  "ordered mesh arrays as part truth"
46091
46079
  ]
@@ -46282,7 +46270,7 @@ if __name__ == "__main__":
46282
46270
  - Scale is correct for WaveEngine world use.
46283
46271
  - If parts were requested, GLB contains \`waveModelObjectModel\` on the \`__wave_model_object_model\` node metadata/extras.
46284
46272
  - If parts were requested, every required part is present in \`objectModel.parts[].name\`.
46285
- - If parts were requested, every part mesh has explicit \`meshPartBindings[]\`; no \`metadata.partIds\` or mesh-name fallback is used.
46273
+ - If parts were requested, every part mesh has explicit \`meshPartBindings[]\`; no per-mesh part metadata, legacy metadata part arrays, or mesh-name fallback is used.
46286
46274
  - If no parts were requested, raw multi-mesh GLB remains mesh-only and does not eagerly invent parts.
46287
46275
  - Part pivots/origins, if authored, survive as \`rotationPivot\` and \`visualFrame\`.
46288
46276
  - Material slots are clean and simple.
@@ -48272,7 +48260,7 @@ function buildHostedWaveStudioMcpToolDefinitions() {
48272
48260
  },
48273
48261
  {
48274
48262
  name: "recover_wave_connection",
48275
- description: "[studio.mcp] Direct Observe recovery tool. Call this after disconnect, timeout, command_timeout, command_lease_expired, session_not_found, agent_onboarding_required, workspace_mirror_not_ready, hosted_mcp_proxy_failed, local SDK confusion, or any unclear MCP state. It returns one explicit next action: re-onboard, call get_wave_session/list_wave_files, wake/reopen Wave Studio tab, update/restart WaveEngine Agent SDK, wait for VFS mirror, use HTTP Gateway fallback, retry command, or ask user for fresh Copy to Agent. No start_wave_task needed. If local HTTP returns 401 but HTTP Gateway accepts the same token, treat WaveEngine Agent SDK as stale/not adopted: update/restart SDK first. If every endpoint returns 401/bridge_auth_invalid before this tool can run, token is dead: ask user for fresh Copy to Agent.",
48263
+ description: "[studio.mcp] Direct Observe recovery tool. Call this after disconnect, timeout, command_timeout, command_lease_expired, session_not_found, agent_onboarding_required, workspace_mirror_not_ready, hosted_mcp_proxy_failed, local SDK confusion, or any unclear MCP state. It returns one explicit next action: re-onboard, call get_wave_session/list_wave_files, keep/focus Wave Studio while it silently re-registers local tokens, update/restart WaveEngine Agent SDK, wait for VFS mirror, use HTTP Gateway fallback, retry command, or ask user for fresh Copy to Agent. No start_wave_task needed. If local HTTP returns 401 but HTTP Gateway accepts the same token, treat WaveEngine Agent SDK as stale/not adopted: update/restart SDK first. If every endpoint returns 401/bridge_auth_invalid before this tool can run, token is dead: ask user for fresh Copy to Agent.",
48276
48264
  inputSchema: {
48277
48265
  type: "object",
48278
48266
  properties: {
@@ -50114,7 +50102,7 @@ function getReadToolDefinitions() {
50114
50102
  },
50115
50103
  {
50116
50104
  name: "create_wave_3d_modeling_job",
50117
- description: "[wave.modeling] Create a local SDK 3D-modeling job scaffold from a prompt and optional screenshots/reference image paths. Writes README, CAD prompt, JSON parameter template/schema, Python CadQuery STEP scaffold, and validation checklist into a temp job folder. Does not generate/upload a GLB by itself; use asset upload tools after a real model file exists. If requiredParts is supplied, the resulting GLB must embed Wave objectModel SSOT metadata via waveModelObjectModel on a __wave_model_object_model node plus per-mesh projection keys; raw mesh names, metadata.partIds, extras.partIds, or positional mesh arrays are not part truth. Aliases: generate_wave_3d_model, create_wave_3d_model, create_wave_3d_model_from_screenshots.",
50105
+ description: "[wave.modeling] Create a local SDK 3D-modeling job scaffold from a prompt and optional screenshots/reference image paths. Writes README, CAD prompt, JSON parameter template/schema, Python CadQuery STEP scaffold, and validation checklist into a temp job folder. Does not generate/upload a GLB by itself; use asset upload tools after a real model file exists. If requiredParts is supplied, the resulting GLB must embed Wave objectModel SSOT metadata via waveModelObjectModel on a __wave_model_object_model node; raw mesh names, per-mesh part metadata, legacy metadata part arrays, or positional mesh arrays are not part truth. Aliases: generate_wave_3d_model, create_wave_3d_model, create_wave_3d_model_from_screenshots.",
50118
50106
  inputSchema: {
50119
50107
  type: "object",
50120
50108
  properties: {
@@ -50155,7 +50143,7 @@ function getReadToolDefinitions() {
50155
50143
  requiredParts: {
50156
50144
  type: "array",
50157
50145
  items: { type: "string" },
50158
- description: "Optional public part names the generated GLB must preserve in objectModel SSOT. When non-empty, model output must include waveModelObjectModel on a __wave_model_object_model node with parts, meshPartBindings, parentPartId/topology/material data as needed, and per-mesh waveModelPartId/waveModelPartName projection keys."
50146
+ description: "Optional public part names the generated GLB must preserve in objectModel SSOT. When non-empty, model output must include waveModelObjectModel on a __wave_model_object_model node with parts, meshPartBindings, parentPartId/topology/material data as needed, and no per-mesh part metadata projection keys."
50159
50147
  },
50160
50148
  knownDimensionsMm: {
50161
50149
  type: "object",
@@ -50471,7 +50459,7 @@ function localConnectionRecoveryResult(args, context) {
50471
50459
  steps.push("Do not ask user for new Copy to Agent unless local HTTP auth fails.");
50472
50460
  } else if (sessions.length === 0 || lastErrorCode === "session_not_found") {
50473
50461
  state = "no_paired_studio_tab";
50474
- nextAction = "WaveEngine Agent SDK HTTP is alive, but no Wave Studio tab is paired with this MCP_TOKEN local secret. Ask user to wake/reopen Wave Studio, open Room -> MCP, and let it adopt this same local session secret; then call get_wave_session again.";
50462
+ nextAction = "WaveEngine Agent SDK HTTP is alive, but no Wave Studio tab is paired with this MCP_TOKEN local secret yet. Keep Wave Studio open and focused briefly; Studio silently re-registers copied local tokens after SDK restart. Then call get_wave_session again. Ask user to reopen/start MCP only if the Studio tab is closed, sleeping, or MCP is disabled.";
50475
50463
  nextTool = "get_wave_session";
50476
50464
  requiresUserAction = true;
50477
50465
  steps.push("Do not switch to SDK cache or query tools as a transport fix.");
@@ -50541,7 +50529,7 @@ function localConnectionRecoveryResult(args, context) {
50541
50529
  hardStopRules: [
50542
50530
  "Local HTTP refused/unreachable before MCP response: start WaveEngine Agent SDK, retry localhost for up to 10 seconds.",
50543
50531
  "Local HTTP 401/bridge_auth_invalid: if HTTP Gateway accepts the same MCP_TOKEN, SDK is stale/not adopted: run the exact token-preserving WaveEngine Agent SDK command so it adopts MCP_TOKEN as the local pairing secret, then retry local. If every endpoint rejects MCP_TOKEN, ask user for fresh Copy to Agent.",
50544
- "No paired session or stale command poll: wake/reopen Wave Studio tab; keep same local endpoint and MCP_TOKEN pairing secret first.",
50532
+ "No paired session or stale command poll: keep Wave Studio tab open/focused and retry; Studio silently re-registers copied local tokens after SDK restart. Reopen/start MCP only if disabled or tab is gone.",
50545
50533
  "WaveEngine SDK Cache failure is not live transport failure."
50546
50534
  ]
50547
50535
  });
@@ -52933,7 +52921,8 @@ function readLocalSdkPeerHealth(value) {
52933
52921
  protocolVersion,
52934
52922
  buildHash: readStringProperty(data, "buildHash"),
52935
52923
  processId: readNumberProperty(data, "processId"),
52936
- tokenFingerprint: readStringProperty(data, "tokenFingerprint")
52924
+ tokenFingerprint: readStringProperty(data, "tokenFingerprint"),
52925
+ sessionCount: readNumberProperty(data, "sessionCount") ?? 0
52937
52926
  };
52938
52927
  }
52939
52928
  function parseProcessIds(output) {
@@ -53100,7 +53089,8 @@ function shouldReplaceCurrentSdkPeer(health, token) {
53100
53089
  if (!isCurrentSdkPeer(health)) return true;
53101
53090
  if (!token) return false;
53102
53091
  const expectedFingerprint = createWaveGenieBridgeTokenFingerprint(token);
53103
- return health.tokenFingerprint !== expectedFingerprint;
53092
+ if (health.tokenFingerprint === expectedFingerprint) return false;
53093
+ return (health.sessionCount ?? 0) === 0;
53104
53094
  }
53105
53095
  async function waitForSdkPeerExit(pids, deadlineMs) {
53106
53096
  const deadline = Date.now() + deadlineMs;
@@ -53169,7 +53159,7 @@ async function prepareLocalSdkPeerForStart(input) {
53169
53159
  }
53170
53160
  if (!shouldReplaceCurrentSdkPeer(probe.health, input.token)) {
53171
53161
  console.log(`[WaveEngine Agent SDK] Existing SDK on ${formatLoopbackHttpUrl(input.host, input.port, "")} is current; reusing it.`);
53172
- console.log("[WaveEngine Agent SDK] If a new Copy-to-Agent token fails later, restart with WAVE3D_MCP_TOKEN from that copy.");
53162
+ console.log("[WaveEngine Agent SDK] If a copied token is not accepted yet, keep Wave Studio open; Studio will silently re-adopt it into this live SDK.");
53173
53163
  return true;
53174
53164
  }
53175
53165
  const reason = isCurrentSdkPeer(probe.health) ? "local pairing secret does not match this start request" : `stale version/build (${probe.health.packageVersion ?? "unknown"} ${probe.health.buildHash ?? "unknown"})`;
@@ -3,6 +3,6 @@
3
3
  Bundled public-safe WaveEngine SDK lookup cache for wave3d-agent-sdk.
4
4
  Generated from sanitized public API/skill corpus during package build.
5
5
 
6
- cacheKey: 2026-06-24.4._Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS
7
- bundleHash: _Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS
8
- zip: wave-engine-sdk-2026-06-24.4._Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS.zip
6
+ cacheKey: 2026-06-24.4.Caxh_cF-78aBZP6RFsiBS_gQxZlDGO0D
7
+ bundleHash: Caxh_cF-78aBZP6RFsiBS_gQxZlDGO0D
8
+ zip: wave-engine-sdk-2026-06-24.4.Caxh_cF-78aBZP6RFsiBS_gQxZlDGO0D.zip
@@ -1,21 +1,21 @@
1
1
  {
2
- "version": "2026-06-24.4._Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS",
2
+ "version": "2026-06-24.4.Caxh_cF-78aBZP6RFsiBS_gQxZlDGO0D",
3
3
  "formatVersion": "2026-06-24.4",
4
- "cacheKey": "2026-06-24.4._Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS",
5
- "bundleFileName": "wave-engine-sdk-2026-06-24.4._Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS.zip",
6
- "bundleHash": "_Dtk7L-p5Py75MSJ1DzWkQJnZa-Y3mpS",
4
+ "cacheKey": "2026-06-24.4.Caxh_cF-78aBZP6RFsiBS_gQxZlDGO0D",
5
+ "bundleFileName": "wave-engine-sdk-2026-06-24.4.Caxh_cF-78aBZP6RFsiBS_gQxZlDGO0D.zip",
6
+ "bundleHash": "Caxh_cF-78aBZP6RFsiBS_gQxZlDGO0D",
7
7
  "generatedAt": "2026-06-06T00:00:00.000Z",
8
8
  "sourceVersions": {
9
9
  "onboarding": {
10
10
  "promptVersion": "2026-06-22.1",
11
- "promptHash": "WEfGoja0WV9Aggv3jE1f_Rw3juEjFSVl"
11
+ "promptHash": "0DLryCmrd1QIYP-32CEyNd5Heiev6_Lr"
12
12
  },
13
13
  "apiHandbook": {
14
14
  "version": "1",
15
- "contentHash": "d98cea1da9b77e39"
15
+ "contentHash": "58fdedcd747f52b9"
16
16
  },
17
17
  "waveSkillCorpusHash": "ol6UwQmeF1EZGOW3uz8NWVzESWOrkc7P",
18
- "sdkLookupCorpusHash": "I8ZZ0nhpHnChROmUVOlTuBE2E78QynCB"
18
+ "sdkLookupCorpusHash": "OFDTR_fo2zM-8iXgejSBgj0rQK12V5to"
19
19
  },
20
20
  "cacheContract": {
21
21
  "llmContextCacheOnly": [
@@ -35,7 +35,7 @@
35
35
  "searchDocuments"
36
36
  ],
37
37
  "rule": "Priority 1 always-on sections must stay in LLM chat/system context. The WaveEngine SDK local cache is public-safe retrieval data, never the only memory for core policy.",
38
- "defaultRefreshCommand": "npx -y wave3d-agent-sdk@0.2.15 cache refresh",
38
+ "defaultRefreshCommand": "npx -y wave3d-agent-sdk@0.2.17 cache refresh",
39
39
  "refreshRule": "When using WaveEngine SDK local cache, compare cacheKey, bundleHash, and sourceVersions before trusting local lookup. If any value differs, update the SDK package or reinstall its bundled SDK cache and rebuild local indexes. Do not fetch a remote SDK zip.",
40
40
  "onlineFallback": "HTTP Gateway does not provide cloud API lookup. If local Node/npm or cache is refused/unavailable, use only concrete Studio operations and already-known code; repair the local WaveEngine SDK before unfamiliar API authoring."
41
41
  },
@@ -51,7 +51,7 @@
51
51
  "mediaType": "application/json",
52
52
  "role": "lookup-guide",
53
53
  "bytes": 1311,
54
- "hash": "zdoaJDoRgPKXQQZYqv_2InXra-dmyYFJ"
54
+ "hash": "FDpb8-vDxfyK6mu1ke6-auN2h64806k1"
55
55
  },
56
56
  {
57
57
  "path": "skills/wave-skills.jsonl",
@@ -100,7 +100,7 @@
100
100
  "mediaType": "application/json",
101
101
  "role": "api-corpus",
102
102
  "bytes": 219,
103
- "hash": "hJ62YeF9dfus0yzMzIQ0tYEUucMBNj6q"
103
+ "hash": "IkwK7b__4lrVlSlDL5-M2uDiZqcLrpy_"
104
104
  },
105
105
  {
106
106
  "path": "search/search-documents.jsonl",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wave3d-agent-sdk",
3
- "version": "0.2.15",
3
+ "version": "0.2.17",
4
4
  "description": "WaveEngine Agent SDK for same-machine Wave Studio MCP plus bundled WaveEngine lookup.",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",