@uemcp/server 1.10.0 → 1.12.0

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.
Files changed (3) hide show
  1. package/README.md +63 -1
  2. package/dist/index.mjs +1983 -50
  3. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -362,6 +362,18 @@ const TOOL_METADATA = {
362
362
  "source",
363
363
  "build.cs"
364
364
  ]),
365
+ add_nav_link: mutates("level", "add_nav_link", [
366
+ "navmesh",
367
+ "navigation",
368
+ "nav link",
369
+ "jump"
370
+ ]),
371
+ add_nav_modifier_volume: mutates("level", "add_nav_modifier_volume", [
372
+ "navmesh",
373
+ "navigation",
374
+ "nav area",
375
+ "block"
376
+ ]),
365
377
  add_post_process_material: mutates("fx", "add_post_process_material"),
366
378
  add_reflected_member: mutates("build", void 0, [
367
379
  "uproperty",
@@ -372,6 +384,11 @@ const TOOL_METADATA = {
372
384
  add_sequence_binding: mutates("sequence", "add_sequence_binding"),
373
385
  add_sequence_keys: mutates("sequence", "add_sequence_keys"),
374
386
  add_sequence_track: mutates("sequence", "add_sequence_track"),
387
+ add_smart_object_component: idempotentMutates("ai", "add_smart_object_component", [
388
+ "smart object",
389
+ "slot",
390
+ "claim"
391
+ ]),
375
392
  add_state_tree_component: mutates("ai", "add_state_tree_component"),
376
393
  add_state_tree_state: mutates("ai", "add_state_tree_state"),
377
394
  add_stimuli_source: mutates("ai", "add_stimuli_source", [
@@ -477,10 +494,27 @@ const TOOL_METADATA = {
477
494
  create_landscape: mutates("level", "create_landscape"),
478
495
  create_level_sequence: mutates("sequence", "create_level_sequence"),
479
496
  create_material_instance: mutates("fx", "create_material_instance"),
497
+ create_mass_entity_config: mutates("ai", "create_mass_entity_config", [
498
+ "mass",
499
+ "crowd",
500
+ "entity config",
501
+ "trait"
502
+ ]),
480
503
  create_metasound: mutates("audio", "create_metasound"),
481
504
  create_montage: mutates("anim", "create_montage"),
482
505
  create_pcg_graph: mutates("fx", "create_pcg_graph"),
506
+ create_nav_area: mutates("level", "create_nav_area", [
507
+ "navmesh",
508
+ "navigation",
509
+ "nav area",
510
+ "cost"
511
+ ]),
483
512
  create_post_process_volume: mutates("fx", "create_post_process_volume"),
513
+ create_smart_object_definition: mutates("ai", "create_smart_object_definition", [
514
+ "smart object",
515
+ "slot",
516
+ "activity"
517
+ ]),
484
518
  create_sound_cue: mutates("audio", "create_sound_cue"),
485
519
  create_state_tree: mutates("ai", "create_state_tree"),
486
520
  create_struct: mutates("blueprint", "create_struct"),
@@ -494,6 +528,13 @@ const TOOL_METADATA = {
494
528
  delete_asset: destroys("asset", "delete_asset"),
495
529
  delete_data_table: destroys("asset", "delete_data_table"),
496
530
  destroy_actor: destroys("level", "destroy_actor"),
531
+ diagnose_navmesh: readOnly("level", "diagnose_navmesh", [
532
+ "navmesh",
533
+ "navigation",
534
+ "island",
535
+ "spawn",
536
+ "reachable"
537
+ ]),
497
538
  disconnect_pins: mutates("blueprint", "disconnect_pins"),
498
539
  doctor: readOnly("core", void 0, [
499
540
  "diagnose",
@@ -509,6 +550,12 @@ const TOOL_METADATA = {
509
550
  "generator",
510
551
  "score"
511
552
  ]),
553
+ edit_mass_entity_config: mutates("ai", "edit_mass_entity_config", [
554
+ "mass",
555
+ "crowd",
556
+ "entity config",
557
+ "trait"
558
+ ]),
512
559
  enable_toolset: idempotentMutates("core", void 0, [
513
560
  "toolset",
514
561
  "tools",
@@ -532,6 +579,13 @@ const TOOL_METADATA = {
532
579
  "registry"
533
580
  ]),
534
581
  find_blueprint_references: readOnly("blueprint", "find_blueprint_references"),
582
+ find_path: readOnly("level", "find_path", [
583
+ "navmesh",
584
+ "navigation",
585
+ "path",
586
+ "pathfinding",
587
+ "reachable"
588
+ ]),
535
589
  find_symbol: readOnly("build", void 0, [
536
590
  "symbol",
537
591
  "definition",
@@ -595,6 +649,12 @@ const TOOL_METADATA = {
595
649
  get_editor_state: readOnly("core", "get_editor_state"),
596
650
  get_eqs_query: readOnly("ai", "get_eqs_query"),
597
651
  get_import_job_status: readOnly("asset", "get_import_job_status"),
652
+ get_mass_entity_config: readOnly("ai", "get_mass_entity_config", [
653
+ "mass",
654
+ "crowd",
655
+ "entity config",
656
+ "trait"
657
+ ]),
598
658
  get_net_stats: readOnly("test", "get_net_stats", [
599
659
  "network",
600
660
  "multiplayer",
@@ -606,6 +666,7 @@ const TOOL_METADATA = {
606
666
  get_pie_status: readOnly("test", "get_pie_status"),
607
667
  get_project_id: readOnly("core", void 0, ["projectid", "identity"]),
608
668
  get_render_job_status: readOnly("sequence", "get_render_job_status"),
669
+ get_smart_object_definition: readOnly("ai", "get_smart_object_definition", ["smart object", "slot"]),
609
670
  get_source_control_job_status: readOnly("asset", "get_source_control_job_status"),
610
671
  get_source_control_status: readOnly("asset", "get_source_control_status"),
611
672
  get_state_tree: readOnly("ai", "get_state_tree"),
@@ -629,6 +690,12 @@ const TOOL_METADATA = {
629
690
  "enhanced input"
630
691
  ]),
631
692
  launch_on_device: reachesOutside("test", false, "launch_on_device"),
693
+ layout_graph: idempotentMutates("blueprint", "layout_graph", [
694
+ "arrange",
695
+ "tidy",
696
+ "overlap",
697
+ "format"
698
+ ]),
632
699
  link_state_tree_state: mutates("ai", "link_state_tree_state", ["subtree", "linked"]),
633
700
  list_actors: readOnly("core", "list_actors"),
634
701
  list_asset_factories: readOnly("asset", "list_asset_factories"),
@@ -674,6 +741,11 @@ const TOOL_METADATA = {
674
741
  refresh_source_control_status: idempotentMutates("asset", "refresh_source_control_status"),
675
742
  reimport_asset: reachesOutside("asset", false, "reimport_asset"),
676
743
  remove_graph_node: destroys("blueprint", "remove_graph_node"),
744
+ remove_state_tree_elements: destroys("ai", "remove_state_tree_elements", [
745
+ "delete",
746
+ "state",
747
+ "transition"
748
+ ]),
677
749
  rename_asset: mutates("asset", "rename_asset"),
678
750
  rename_data_table: mutates("asset", "rename_data_table"),
679
751
  rename_data_table_row: mutates("asset", "rename_data_table_row"),
@@ -720,7 +792,25 @@ const TOOL_METADATA = {
720
792
  set_import_settings: idempotentMutates("asset", "set_import_settings"),
721
793
  set_material_params: idempotentMutates("fx", "set_material_params"),
722
794
  set_metasound_graph: idempotentMutates("audio", "set_metasound_graph"),
795
+ set_crowd_settings: idempotentMutates("level", "set_crowd_settings", [
796
+ "crowd",
797
+ "avoidance",
798
+ "rvo",
799
+ "detour"
800
+ ]),
723
801
  set_montage_sections: idempotentMutates("anim", "set_montage_sections"),
802
+ set_nav_agents: idempotentMutates("level", "set_nav_agents", [
803
+ "navmesh",
804
+ "navigation",
805
+ "agent",
806
+ "radius"
807
+ ]),
808
+ set_navmesh_settings: idempotentMutates("level", "set_navmesh_settings", [
809
+ "navmesh",
810
+ "navigation",
811
+ "recast",
812
+ "cell size"
813
+ ]),
724
814
  set_niagara_params: idempotentMutates("fx", "set_niagara_params"),
725
815
  set_pin_default: idempotentMutates("blueprint", "set_pin_default"),
726
816
  set_post_process_settings: idempotentMutates("fx", "set_post_process_settings"),
@@ -751,6 +841,12 @@ const TOOL_METADATA = {
751
841
  "output",
752
842
  "tail"
753
843
  ]),
844
+ test_reachability: readOnly("level", "test_reachability", [
845
+ "navmesh",
846
+ "navigation",
847
+ "reachable",
848
+ "sweep"
849
+ ]),
754
850
  toggle_show_flags: idempotentMutates("level", "toggle_show_flags"),
755
851
  trace_state_tree: mutates("ai", "trace_state_tree", [
756
852
  "pie",
@@ -760,6 +856,17 @@ const TOOL_METADATA = {
760
856
  trigger_hot_reload: mutates("build", "start_hot_reload"),
761
857
  trigger_live_compile: mutates("build", "start_live_compile", ["live coding", "recompile"]),
762
858
  undo: mutates("core", "undo"),
859
+ validate_mass_entity_config: readOnly("ai", "validate_mass_entity_config", [
860
+ "mass",
861
+ "crowd",
862
+ "entity config",
863
+ "trait"
864
+ ]),
865
+ update_state_tree_elements: mutates("ai", "update_state_tree_elements", [
866
+ "edit",
867
+ "rename",
868
+ "retarget"
869
+ ]),
763
870
  wait_for_job: readOnly("core", void 0, [
764
871
  "poll",
765
872
  "block",
@@ -1352,6 +1459,10 @@ const bridgeBlueprintNodeSchema = z.object({
1352
1459
  nodeId: z.string(),
1353
1460
  pinCount: z.number().int().min(0),
1354
1461
  pins: z.array(bridgeBlueprintPinSchema),
1462
+ position: z.object({
1463
+ x: z.number().int(),
1464
+ y: z.number().int()
1465
+ }).optional(),
1355
1466
  title: z.string()
1356
1467
  });
1357
1468
  const bridgeErrorResponseSchema = z.object({
@@ -2575,6 +2686,7 @@ const BRIDGE_CONNECT_PINS_REQUEST_TYPE = "connect_pins";
2575
2686
  const BRIDGE_DISCONNECT_PINS_REQUEST_TYPE = "disconnect_pins";
2576
2687
  const BRIDGE_SET_PIN_DEFAULT_REQUEST_TYPE = "set_pin_default";
2577
2688
  const BRIDGE_LIST_AVAILABLE_NODES_REQUEST_TYPE = "list_available_nodes";
2689
+ const BRIDGE_LAYOUT_GRAPH_REQUEST_TYPE = "layout_graph";
2578
2690
  const BRIDGE_GRAPH_PIN_VALUE_MAX_CHARS = 4096;
2579
2691
  const BRIDGE_GRAPH_NODE_POSITION_LIMIT = 1e6;
2580
2692
  const BRIDGE_GRAPH_NODE_KINDS = [
@@ -2592,6 +2704,10 @@ const graphNodePositionSchema = z.object({
2592
2704
  x: z.number().int().min(-1e6).max(BRIDGE_GRAPH_NODE_POSITION_LIMIT).default(0),
2593
2705
  y: z.number().int().min(-1e6).max(BRIDGE_GRAPH_NODE_POSITION_LIMIT).default(0)
2594
2706
  });
2707
+ const graphNodePlacedPositionSchema = z.object({
2708
+ x: z.number().int(),
2709
+ y: z.number().int()
2710
+ });
2595
2711
  const bridgeListGraphNodesRequestSchema = z.object({
2596
2712
  assetPath: assetPathSchema,
2597
2713
  cursor: assetCursorSchema.optional(),
@@ -2604,6 +2720,7 @@ const bridgeListGraphNodesRequestSchema = z.object({
2604
2720
  });
2605
2721
  const bridgeAddGraphNodeRequestFieldsSchema = z.object({
2606
2722
  assetPath: assetPathSchema,
2723
+ autoLayout: z.boolean().optional(),
2607
2724
  graphName: graphNameSchema,
2608
2725
  nodeClass: assetPathSchema.optional(),
2609
2726
  kind: graphNodeKindSchema,
@@ -2655,6 +2772,13 @@ const bridgeSetPinDefaultRequestSchema = z.object({
2655
2772
  value: graphPinValueSchema,
2656
2773
  version: z.literal(2)
2657
2774
  });
2775
+ const bridgeLayoutGraphRequestSchema = z.object({
2776
+ assetPath: assetPathSchema,
2777
+ graphName: graphNameSchema,
2778
+ requestId: requestIdSchema,
2779
+ type: z.literal(BRIDGE_LAYOUT_GRAPH_REQUEST_TYPE),
2780
+ version: z.literal(2)
2781
+ });
2658
2782
  const bridgeListAvailableNodesRequestSchema = z.object({
2659
2783
  assetPath: assetPathSchema,
2660
2784
  cursor: assetCursorSchema.optional(),
@@ -2683,6 +2807,7 @@ const bridgeAddGraphNodeSuccessResponseSchema = z.object({
2683
2807
  message: nonEmptyStringSchema.optional(),
2684
2808
  node: bridgeBlueprintNodeSchema,
2685
2809
  ok: z.literal(true),
2810
+ position: graphNodePlacedPositionSchema.optional(),
2686
2811
  requestId: requestIdSchema,
2687
2812
  state: creativeEditStateSchema,
2688
2813
  type: z.literal(BRIDGE_ADD_GRAPH_NODE_REQUEST_TYPE),
@@ -2758,6 +2883,20 @@ const bridgeListAvailableNodesSuccessResponseSchema = z.object({
2758
2883
  type: z.literal(BRIDGE_LIST_AVAILABLE_NODES_REQUEST_TYPE),
2759
2884
  version: z.literal(2)
2760
2885
  });
2886
+ const bridgeLayoutGraphSuccessResponseSchema = z.object({
2887
+ assetPath: z.string(),
2888
+ graphName: z.string(),
2889
+ layerCount: z.number().int().min(0),
2890
+ message: nonEmptyStringSchema.optional(),
2891
+ movedCount: z.number().int().min(0),
2892
+ nodeCount: z.number().int().min(0),
2893
+ ok: z.literal(true),
2894
+ requestId: requestIdSchema,
2895
+ skippedCount: z.number().int().min(0),
2896
+ state: creativeEditStateSchema,
2897
+ type: z.literal(BRIDGE_LAYOUT_GRAPH_REQUEST_TYPE),
2898
+ version: z.literal(2)
2899
+ });
2761
2900
  const bridgeListGraphNodesResponseSchema = z.union([bridgeListGraphNodesSuccessResponseSchema, bridgeErrorResponseSchema]);
2762
2901
  const bridgeAddGraphNodeResponseSchema = z.union([bridgeAddGraphNodeSuccessResponseSchema, bridgeErrorResponseSchema]);
2763
2902
  const bridgeRemoveGraphNodeResponseSchema = z.union([bridgeRemoveGraphNodeSuccessResponseSchema, bridgeErrorResponseSchema]);
@@ -2765,6 +2904,7 @@ const bridgeConnectPinsResponseSchema = z.union([bridgeConnectPinsSuccessRespons
2765
2904
  const bridgeDisconnectPinsResponseSchema = z.union([bridgeDisconnectPinsSuccessResponseSchema, bridgeErrorResponseSchema]);
2766
2905
  const bridgeSetPinDefaultResponseSchema = z.union([bridgeSetPinDefaultSuccessResponseSchema, bridgeErrorResponseSchema]);
2767
2906
  const bridgeListAvailableNodesResponseSchema = z.union([bridgeListAvailableNodesSuccessResponseSchema, bridgeErrorResponseSchema]);
2907
+ const bridgeLayoutGraphResponseSchema = z.union([bridgeLayoutGraphSuccessResponseSchema, bridgeErrorResponseSchema]);
2768
2908
  function createBridgeListGraphNodesRequest(assetPath, graphName, options = {}, requestId = randomUUID()) {
2769
2909
  return bridgeListGraphNodesRequestSchema.parse({
2770
2910
  assetPath,
@@ -2780,6 +2920,7 @@ function createBridgeListGraphNodesRequest(assetPath, graphName, options = {}, r
2780
2920
  function createBridgeAddGraphNodeRequest(assetPath, graphName, kind, options = {}, requestId = randomUUID()) {
2781
2921
  return bridgeAddGraphNodeRequestSchema.parse({
2782
2922
  assetPath,
2923
+ autoLayout: options.autoLayout,
2783
2924
  graphName,
2784
2925
  kind,
2785
2926
  memberName: options.memberName,
@@ -2852,6 +2993,15 @@ function createBridgeListAvailableNodesRequest(assetPath, graphName, options = {
2852
2993
  version: 2
2853
2994
  });
2854
2995
  }
2996
+ function createBridgeLayoutGraphRequest(assetPath, graphName, requestId = randomUUID()) {
2997
+ return bridgeLayoutGraphRequestSchema.parse({
2998
+ assetPath,
2999
+ graphName,
3000
+ requestId,
3001
+ type: BRIDGE_LAYOUT_GRAPH_REQUEST_TYPE,
3002
+ version: 2
3003
+ });
3004
+ }
2855
3005
  //#endregion
2856
3006
  //#region src/protocol/debugger.ts
2857
3007
  const BRIDGE_SET_BLUEPRINT_BREAKPOINT_REQUEST_TYPE = "set_blueprint_breakpoint";
@@ -3300,11 +3450,11 @@ const createClassJobIdSchema = z.string().trim().min(1);
3300
3450
  const classNameSchema = z.string().trim().min(1).max(128).regex(/^[A-Za-z_][A-Za-z0-9_]*$/);
3301
3451
  const parentClassSchema = z.string().trim().min(1).max(128);
3302
3452
  const moduleNameSchema = z.string().trim().min(1).max(128);
3303
- const classPathSchema = z.string().trim().min(1).max(512);
3453
+ const classPathSchema$1 = z.string().trim().min(1).max(512);
3304
3454
  const sourceFilePathSchema = z.string().trim().min(1);
3305
3455
  const bridgeCreateCppClassRequestSchema = z.object({
3306
3456
  className: classNameSchema,
3307
- classPath: classPathSchema.optional(),
3457
+ classPath: classPathSchema$1.optional(),
3308
3458
  moduleName: moduleNameSchema.optional(),
3309
3459
  parentClass: parentClassSchema,
3310
3460
  requestId: requestIdSchema,
@@ -7392,6 +7542,7 @@ const bridgeStateTreeNodeReportSchema = z.object({
7392
7542
  const bridgeStateTreeTransitionReportSchema = z.object({
7393
7543
  eventTag: z.string().optional(),
7394
7544
  id: z.string(),
7545
+ targetStateId: z.string().optional(),
7395
7546
  targetStateName: z.string().optional(),
7396
7547
  targetType: z.string(),
7397
7548
  trigger: z.string()
@@ -7639,6 +7790,141 @@ function createBridgeTraceStateTreeRequest(action, options = {}, requestId = ran
7639
7790
  version: 2
7640
7791
  });
7641
7792
  }
7793
+ const BRIDGE_UPDATE_STATE_TREE_ELEMENTS_REQUEST_TYPE = "update_state_tree_elements";
7794
+ const BRIDGE_REMOVE_STATE_TREE_ELEMENTS_REQUEST_TYPE = "remove_state_tree_elements";
7795
+ const BRIDGE_STATE_TREE_ELEMENT_KINDS = [
7796
+ "state",
7797
+ "task",
7798
+ "transition"
7799
+ ];
7800
+ const BRIDGE_STATE_TREE_EDITABLE_STATE_TYPES = [
7801
+ "state",
7802
+ "group",
7803
+ "subtree"
7804
+ ];
7805
+ const BRIDGE_STATE_TREE_TRANSITION_TARGET_TYPES = [
7806
+ "none",
7807
+ "succeeded",
7808
+ "failed",
7809
+ "next_state",
7810
+ "goto_state"
7811
+ ];
7812
+ const stateTreeElementIdSchema = z.string().trim().regex(/^[{(]?[0-9A-Fa-f]{8}-?[0-9A-Fa-f]{4}-?[0-9A-Fa-f]{4}-?[0-9A-Fa-f]{4}-?[0-9A-Fa-f]{12}[)}]?$/);
7813
+ const stateTreeElementKindSchema = z.enum(BRIDGE_STATE_TREE_ELEMENT_KINDS);
7814
+ const stateTreeEditableStateTypeSchema = z.enum(BRIDGE_STATE_TREE_EDITABLE_STATE_TYPES);
7815
+ const stateTreeTransitionTargetTypeSchema = z.enum(BRIDGE_STATE_TREE_TRANSITION_TARGET_TYPES);
7816
+ const stateTreeEditableTriggerSchema = z.enum(BRIDGE_STATE_TREE_TRANSITION_TRIGGERS);
7817
+ const bridgeStateTreeElementUpdateSchema = z.discriminatedUnion("kind", [
7818
+ z.object({
7819
+ enabled: z.boolean().optional(),
7820
+ id: stateTreeElementIdSchema,
7821
+ kind: z.literal("state"),
7822
+ name: userTypeIdentifierSchema.optional(),
7823
+ selectionBehavior: stateTreeSelectionBehaviorSchema.optional(),
7824
+ stateType: stateTreeEditableStateTypeSchema.optional()
7825
+ }),
7826
+ z.object({
7827
+ id: stateTreeElementIdSchema,
7828
+ kind: z.literal("task"),
7829
+ params: eqsParamsSchema
7830
+ }),
7831
+ z.object({
7832
+ enabled: z.boolean().optional(),
7833
+ eventTag: boundedStringSchema.optional(),
7834
+ id: stateTreeElementIdSchema,
7835
+ kind: z.literal("transition"),
7836
+ targetStateId: stateTreeElementIdSchema.optional(),
7837
+ targetType: stateTreeTransitionTargetTypeSchema.optional(),
7838
+ trigger: stateTreeEditableTriggerSchema.optional()
7839
+ })
7840
+ ]).superRefine((update, ctx) => {
7841
+ if (update.kind === "task") {
7842
+ if (Object.keys(update.params).length === 0) ctx.addIssue({
7843
+ code: z.ZodIssueCode.custom,
7844
+ message: "A task update must set at least one param.",
7845
+ path: ["params"]
7846
+ });
7847
+ return;
7848
+ }
7849
+ const { id: _id, kind: _kind, ...fields } = update;
7850
+ if (Object.values(fields).every((value) => value === void 0)) ctx.addIssue({
7851
+ code: z.ZodIssueCode.custom,
7852
+ message: `A ${update.kind} update must change at least one field.`
7853
+ });
7854
+ if (update.kind !== "transition") return;
7855
+ if (update.targetType === "goto_state" && update.targetStateId === void 0) ctx.addIssue({
7856
+ code: z.ZodIssueCode.custom,
7857
+ message: "A 'goto_state' transition must name its targetStateId.",
7858
+ path: ["targetStateId"]
7859
+ });
7860
+ if (update.targetStateId !== void 0 && update.targetType !== void 0 && update.targetType !== "goto_state") ctx.addIssue({
7861
+ code: z.ZodIssueCode.custom,
7862
+ message: "Only a 'goto_state' transition names a targetStateId.",
7863
+ path: ["targetStateId"]
7864
+ });
7865
+ });
7866
+ const bridgeUpdateStateTreeElementsRequestSchema = z.object({
7867
+ assetPath: assetPathSchema,
7868
+ compile: z.boolean().default(true),
7869
+ requestId: requestIdSchema,
7870
+ type: z.literal(BRIDGE_UPDATE_STATE_TREE_ELEMENTS_REQUEST_TYPE),
7871
+ updates: z.array(bridgeStateTreeElementUpdateSchema).min(1).max(32),
7872
+ version: z.literal(2)
7873
+ });
7874
+ const bridgeUpdateStateTreeElementsSuccessResponseSchema = z.object({
7875
+ ...authoringBatchResponseFields,
7876
+ compileMessages: z.array(z.string()).max(25),
7877
+ compiled: z.boolean(),
7878
+ type: z.literal(BRIDGE_UPDATE_STATE_TREE_ELEMENTS_REQUEST_TYPE)
7879
+ });
7880
+ const bridgeStateTreeElementRemovalSchema = z.object({
7881
+ id: stateTreeElementIdSchema,
7882
+ kind: stateTreeElementKindSchema
7883
+ });
7884
+ const bridgeRemoveStateTreeElementsRequestSchema = z.object({
7885
+ assetPath: assetPathSchema,
7886
+ compile: z.boolean().default(true),
7887
+ removals: z.array(bridgeStateTreeElementRemovalSchema).min(1).max(32),
7888
+ requestId: requestIdSchema,
7889
+ type: z.literal(BRIDGE_REMOVE_STATE_TREE_ELEMENTS_REQUEST_TYPE),
7890
+ version: z.literal(2)
7891
+ });
7892
+ const bridgeStateTreeRemovedTransitionSchema = z.object({
7893
+ id: z.string(),
7894
+ ownerStateId: z.string(),
7895
+ ownerStateName: z.string(),
7896
+ targetStateName: z.string()
7897
+ });
7898
+ const bridgeRemoveStateTreeElementsSuccessResponseSchema = z.object({
7899
+ ...authoringBatchResponseFields,
7900
+ compileMessages: z.array(z.string()).max(25),
7901
+ compiled: z.boolean(),
7902
+ removedTransitionCount: z.number().int().min(0),
7903
+ removedTransitions: z.array(bridgeStateTreeRemovedTransitionSchema).max(128),
7904
+ type: z.literal(BRIDGE_REMOVE_STATE_TREE_ELEMENTS_REQUEST_TYPE)
7905
+ });
7906
+ const bridgeUpdateStateTreeElementsResponseSchema = z.union([bridgeUpdateStateTreeElementsSuccessResponseSchema, bridgeErrorResponseSchema]);
7907
+ const bridgeRemoveStateTreeElementsResponseSchema = z.union([bridgeRemoveStateTreeElementsSuccessResponseSchema, bridgeErrorResponseSchema]);
7908
+ function createBridgeUpdateStateTreeElementsRequest(assetPath, updates, options = {}, requestId = randomUUID()) {
7909
+ return bridgeUpdateStateTreeElementsRequestSchema.parse({
7910
+ assetPath,
7911
+ compile: options.compile,
7912
+ requestId,
7913
+ type: BRIDGE_UPDATE_STATE_TREE_ELEMENTS_REQUEST_TYPE,
7914
+ updates,
7915
+ version: 2
7916
+ });
7917
+ }
7918
+ function createBridgeRemoveStateTreeElementsRequest(assetPath, removals, options = {}, requestId = randomUUID()) {
7919
+ return bridgeRemoveStateTreeElementsRequestSchema.parse({
7920
+ assetPath,
7921
+ compile: options.compile,
7922
+ removals,
7923
+ requestId,
7924
+ type: BRIDGE_REMOVE_STATE_TREE_ELEMENTS_REQUEST_TYPE,
7925
+ version: 2
7926
+ });
7927
+ }
7642
7928
  //#endregion
7643
7929
  //#region src/protocol/perception.ts
7644
7930
  const BRIDGE_CREATE_AI_CONTROLLER_REQUEST_TYPE = "create_ai_controller";
@@ -10461,30 +10747,871 @@ function createBridgeSetProjectSettingsRequest(options = {}, requestId = randomU
10461
10747
  return bridgeSetProjectSettingsRequestSchema.parse({
10462
10748
  properties: options.properties,
10463
10749
  requestId,
10464
- sectionName: options.sectionName,
10465
- type: BRIDGE_SET_PROJECT_SETTINGS_REQUEST_TYPE,
10750
+ sectionName: options.sectionName,
10751
+ type: BRIDGE_SET_PROJECT_SETTINGS_REQUEST_TYPE,
10752
+ version: 2
10753
+ });
10754
+ }
10755
+ function createBridgeSetDefaultGamemodeRequest(scope, gameModePath, options = {}, requestId = randomUUID()) {
10756
+ return bridgeSetDefaultGamemodeRequestSchema.parse({
10757
+ defaultPawnClassPath: options.defaultPawnClassPath,
10758
+ gameModePath,
10759
+ gameStateClassPath: options.gameStateClassPath,
10760
+ hudClassPath: options.hudClassPath,
10761
+ levelPath: options.levelPath,
10762
+ playerControllerClassPath: options.playerControllerClassPath,
10763
+ playerStateClassPath: options.playerStateClassPath,
10764
+ requestId,
10765
+ scope,
10766
+ startupMapPath: options.startupMapPath,
10767
+ type: BRIDGE_SET_DEFAULT_GAMEMODE_REQUEST_TYPE,
10768
+ version: 2
10769
+ });
10770
+ }
10771
+ //#endregion
10772
+ //#region src/protocol/navigation.ts
10773
+ const classPathSchema = z.string().trim().min(1).max(512);
10774
+ const BRIDGE_SET_NAVMESH_SETTINGS_REQUEST_TYPE = "set_navmesh_settings";
10775
+ const BRIDGE_SET_NAV_AGENTS_REQUEST_TYPE = "set_nav_agents";
10776
+ const BRIDGE_SET_CROWD_SETTINGS_REQUEST_TYPE = "set_crowd_settings";
10777
+ const BRIDGE_CREATE_NAV_AREA_REQUEST_TYPE = "create_nav_area";
10778
+ const BRIDGE_ADD_NAV_MODIFIER_VOLUME_REQUEST_TYPE = "add_nav_modifier_volume";
10779
+ const BRIDGE_ADD_NAV_LINK_REQUEST_TYPE = "add_nav_link";
10780
+ const BRIDGE_FIND_PATH_REQUEST_TYPE = "find_path";
10781
+ const BRIDGE_TEST_REACHABILITY_REQUEST_TYPE = "test_reachability";
10782
+ const BRIDGE_NAV_RUNTIME_GENERATION_MODES = [
10783
+ "static",
10784
+ "dynamic_modifiers_only",
10785
+ "dynamic"
10786
+ ];
10787
+ const BRIDGE_NAV_DATA_RESOLUTIONS = [
10788
+ "low",
10789
+ "default",
10790
+ "high"
10791
+ ];
10792
+ const BRIDGE_NAV_LINK_DIRECTIONS = [
10793
+ "both_ways",
10794
+ "left_to_right",
10795
+ "right_to_left"
10796
+ ];
10797
+ const BRIDGE_NAV_QUERY_RESULTS = [
10798
+ "invalid",
10799
+ "error",
10800
+ "fail",
10801
+ "success"
10802
+ ];
10803
+ const BRIDGE_NAV_QUERY_STATES = ["reported", "unsupported"];
10804
+ const BRIDGE_NAV_MAX_AGENT_SIZE = 1e5;
10805
+ const BRIDGE_NAV_MAX_CELL_SIZE = 1024;
10806
+ const BRIDGE_NAV_MAX_TILE_SIZE = 1e5;
10807
+ const BRIDGE_NAV_MAX_REGION_SIZE = 1e7;
10808
+ const BRIDGE_NAV_MAX_AREA_COST = 1e6;
10809
+ const navRuntimeGenerationSchema = z.enum(BRIDGE_NAV_RUNTIME_GENERATION_MODES);
10810
+ const navDataResolutionSchema = z.enum(BRIDGE_NAV_DATA_RESOLUTIONS);
10811
+ const navLinkDirectionSchema = z.enum(BRIDGE_NAV_LINK_DIRECTIONS);
10812
+ const navQueryResultSchema = z.enum(BRIDGE_NAV_QUERY_RESULTS);
10813
+ const navQueryStateSchema = z.enum(BRIDGE_NAV_QUERY_STATES);
10814
+ const navPointSchema = z.object({
10815
+ x: z.number(),
10816
+ y: z.number(),
10817
+ z: z.number()
10818
+ });
10819
+ const navAgentSizeSchema = z.number().min(0).max(BRIDGE_NAV_MAX_AGENT_SIZE);
10820
+ const navCellSchema = z.number().min(1).max(BRIDGE_NAV_MAX_CELL_SIZE);
10821
+ const navRegionSizeSchema = z.number().min(0).max(BRIDGE_NAV_MAX_REGION_SIZE);
10822
+ const navAreaCostSchema = z.number().min(0).max(BRIDGE_NAV_MAX_AREA_COST);
10823
+ const navStepHeightSchema = z.number().min(0).max(1e4);
10824
+ const navColorChannelSchema = z.number().int().min(0).max(255);
10825
+ const navColorSchema = z.object({
10826
+ a: navColorChannelSchema.default(255),
10827
+ b: navColorChannelSchema,
10828
+ g: navColorChannelSchema,
10829
+ r: navColorChannelSchema
10830
+ });
10831
+ const navColorResponseSchema = z.object({
10832
+ a: navColorChannelSchema,
10833
+ b: navColorChannelSchema,
10834
+ g: navColorChannelSchema,
10835
+ r: navColorChannelSchema
10836
+ });
10837
+ const navExtentSchema = z.object({
10838
+ x: z.number().positive().default(200),
10839
+ y: z.number().positive().default(200),
10840
+ z: z.number().positive().default(200)
10841
+ });
10842
+ const bridgeSetNavmeshSettingsRequestFieldsSchema = z.object({
10843
+ agentHeight: navAgentSizeSchema.optional(),
10844
+ agentMaxSlope: z.number().min(0).max(89).optional(),
10845
+ agentMaxStepHeight: navStepHeightSchema.optional(),
10846
+ agentRadius: navAgentSizeSchema.optional(),
10847
+ cellHeight: navCellSchema.optional(),
10848
+ cellSize: navCellSchema.optional(),
10849
+ mergeRegionSize: navRegionSizeSchema.optional(),
10850
+ minRegionArea: navRegionSizeSchema.optional(),
10851
+ navMeshActorPath: actorPathSchema.optional(),
10852
+ requestId: requestIdSchema,
10853
+ resolution: navDataResolutionSchema.default("default"),
10854
+ runtimeGeneration: navRuntimeGenerationSchema.optional(),
10855
+ tileSizeUU: z.number().min(300).max(BRIDGE_NAV_MAX_TILE_SIZE).optional(),
10856
+ type: z.literal(BRIDGE_SET_NAVMESH_SETTINGS_REQUEST_TYPE),
10857
+ version: z.literal(2)
10858
+ });
10859
+ const bridgeSetNavmeshSettingsRequestSchema = bridgeSetNavmeshSettingsRequestFieldsSchema.refine((request) => request.agentHeight !== void 0 || request.agentMaxSlope !== void 0 || request.agentMaxStepHeight !== void 0 || request.agentRadius !== void 0 || request.cellHeight !== void 0 || request.cellSize !== void 0 || request.mergeRegionSize !== void 0 || request.minRegionArea !== void 0 || request.runtimeGeneration !== void 0 || request.tileSizeUU !== void 0, { message: "A set_navmesh_settings request must carry at least one setting to write." });
10860
+ const bridgeNavAgentSchema = z.object({
10861
+ height: navAgentSizeSchema,
10862
+ maxStepHeight: navStepHeightSchema.optional(),
10863
+ name: requiredBoundedStringSchema,
10864
+ navDataClass: classPathSchema.optional(),
10865
+ radius: navAgentSizeSchema
10866
+ });
10867
+ const bridgeSetNavAgentsRequestSchema = z.object({
10868
+ agents: z.array(bridgeNavAgentSchema).min(1).max(16),
10869
+ requestId: requestIdSchema,
10870
+ type: z.literal(BRIDGE_SET_NAV_AGENTS_REQUEST_TYPE),
10871
+ version: z.literal(2)
10872
+ });
10873
+ const bridgeCrowdSettingsSchema = z.object({
10874
+ maxAgentRadius: z.number().min(0).max(1e4).optional(),
10875
+ maxAgents: z.number().int().min(1).max(1e4).optional(),
10876
+ maxAvoidedAgents: z.number().int().min(0).max(64).optional(),
10877
+ maxAvoidedWalls: z.number().int().min(0).max(64).optional(),
10878
+ navmeshCheckInterval: z.number().min(0).max(60).optional(),
10879
+ pathOffsetRadiusMultiplier: z.number().min(0).max(100).optional(),
10880
+ pathOptimizationInterval: z.number().min(0).max(60).optional(),
10881
+ resolveCollisions: z.boolean().optional(),
10882
+ separationDirClamp: z.number().min(-1).max(1).optional()
10883
+ });
10884
+ const bridgeRvoSettingsSchema = z.object({
10885
+ artificialRadiusExpansion: z.number().min(0).max(100).optional(),
10886
+ defaultTimeToLive: z.number().min(0).max(600).optional(),
10887
+ deltaTimeToPredict: z.number().min(0).max(60).optional(),
10888
+ heightCheckMargin: z.number().min(0).max(1e3).optional(),
10889
+ lockTimeAfterAvoid: z.number().min(0).max(60).optional(),
10890
+ lockTimeAfterClean: z.number().min(0).max(60).optional()
10891
+ });
10892
+ const bridgeSetCrowdSettingsRequestFieldsSchema = z.object({
10893
+ crowd: bridgeCrowdSettingsSchema.optional(),
10894
+ requestId: requestIdSchema,
10895
+ rvo: bridgeRvoSettingsSchema.optional(),
10896
+ type: z.literal(BRIDGE_SET_CROWD_SETTINGS_REQUEST_TYPE),
10897
+ version: z.literal(2)
10898
+ });
10899
+ const bridgeSetCrowdSettingsRequestSchema = bridgeSetCrowdSettingsRequestFieldsSchema.refine((request) => Object.values(request.crowd ?? {}).some((value) => value !== void 0) || Object.values(request.rvo ?? {}).some((value) => value !== void 0), { message: "A set_crowd_settings request must carry at least one crowd or rvo setting." });
10900
+ const bridgeCreateNavAreaRequestSchema = z.object({
10901
+ assetName: requiredBoundedStringSchema,
10902
+ defaultCost: navAreaCostSchema.optional(),
10903
+ drawColor: navColorSchema.optional(),
10904
+ fixedAreaEnteringCost: navAreaCostSchema.optional(),
10905
+ packagePath: requiredBoundedStringSchema,
10906
+ parentClass: classPathSchema.default("NavArea"),
10907
+ requestId: requestIdSchema,
10908
+ type: z.literal(BRIDGE_CREATE_NAV_AREA_REQUEST_TYPE),
10909
+ version: z.literal(2)
10910
+ });
10911
+ const bridgeAddNavModifierVolumeRequestSchema = z.object({
10912
+ actorLabel: boundedStringSchema.optional(),
10913
+ areaClass: classPathSchema,
10914
+ areaClassToReplace: classPathSchema.optional(),
10915
+ extent: navExtentSchema.default({
10916
+ x: 200,
10917
+ y: 200,
10918
+ z: 200
10919
+ }),
10920
+ folderPath: boundedStringSchema.optional(),
10921
+ location: vectorInputSchema.default({
10922
+ x: 0,
10923
+ y: 0,
10924
+ z: 0
10925
+ }),
10926
+ requestId: requestIdSchema,
10927
+ rotation: rotatorInputSchema.default({
10928
+ pitch: 0,
10929
+ roll: 0,
10930
+ yaw: 0
10931
+ }),
10932
+ type: z.literal(BRIDGE_ADD_NAV_MODIFIER_VOLUME_REQUEST_TYPE),
10933
+ version: z.literal(2)
10934
+ });
10935
+ const bridgeNavLinkSchema = z.object({
10936
+ areaClass: classPathSchema.optional(),
10937
+ description: boundedStringSchema.optional(),
10938
+ direction: navLinkDirectionSchema.default("both_ways"),
10939
+ left: vectorInputSchema.default({
10940
+ x: 0,
10941
+ y: -50,
10942
+ z: 0
10943
+ }),
10944
+ leftProjectHeight: z.number().min(0).max(1e4).optional(),
10945
+ maxFallDownLength: z.number().min(0).max(1e4).optional(),
10946
+ right: vectorInputSchema.default({
10947
+ x: 0,
10948
+ y: 50,
10949
+ z: 0
10950
+ }),
10951
+ snapHeight: z.number().min(1).max(1e4).optional(),
10952
+ snapRadius: z.number().min(1).max(1e4).optional()
10953
+ });
10954
+ const bridgeAddNavLinkRequestSchema = z.object({
10955
+ actorLabel: boundedStringSchema.optional(),
10956
+ folderPath: boundedStringSchema.optional(),
10957
+ links: z.array(bridgeNavLinkSchema).min(1).max(16),
10958
+ location: vectorInputSchema.default({
10959
+ x: 0,
10960
+ y: 0,
10961
+ z: 0
10962
+ }),
10963
+ requestId: requestIdSchema,
10964
+ rotation: rotatorInputSchema.default({
10965
+ pitch: 0,
10966
+ roll: 0,
10967
+ yaw: 0
10968
+ }),
10969
+ smartLinkEnabled: z.boolean().default(false),
10970
+ type: z.literal(BRIDGE_ADD_NAV_LINK_REQUEST_TYPE),
10971
+ version: z.literal(2)
10972
+ });
10973
+ const navEndpointFields = {
10974
+ end: navPointSchema.optional(),
10975
+ endActorPath: actorPathSchema.optional(),
10976
+ start: navPointSchema.optional(),
10977
+ startActorPath: actorPathSchema.optional()
10978
+ };
10979
+ const addNavEndpointIssues = (endpoints, ctx, pathPrefix) => {
10980
+ if (endpoints.start === void 0 === (endpoints.startActorPath === void 0)) ctx.addIssue({
10981
+ code: z.ZodIssueCode.custom,
10982
+ message: "Give exactly one of start or startActorPath.",
10983
+ path: [...pathPrefix, "start"]
10984
+ });
10985
+ if (endpoints.end === void 0 === (endpoints.endActorPath === void 0)) ctx.addIssue({
10986
+ code: z.ZodIssueCode.custom,
10987
+ message: "Give exactly one of end or endActorPath.",
10988
+ path: [...pathPrefix, "end"]
10989
+ });
10990
+ };
10991
+ const bridgeFindPathRequestFieldsSchema = z.object({
10992
+ ...navEndpointFields,
10993
+ allowPartial: z.boolean().default(true),
10994
+ maxPathPoints: z.number().int().min(1).max(256).default(64),
10995
+ navMeshActorPath: actorPathSchema.optional(),
10996
+ requestId: requestIdSchema,
10997
+ type: z.literal(BRIDGE_FIND_PATH_REQUEST_TYPE),
10998
+ version: z.literal(2)
10999
+ });
11000
+ const bridgeFindPathRequestSchema = bridgeFindPathRequestFieldsSchema.superRefine((request, ctx) => {
11001
+ addNavEndpointIssues(request, ctx, []);
11002
+ });
11003
+ const bridgeReachabilityPairSchema = z.object(navEndpointFields);
11004
+ const bridgeTestReachabilityRequestFieldsSchema = z.object({
11005
+ allowPartial: z.boolean().default(false),
11006
+ navMeshActorPath: actorPathSchema.optional(),
11007
+ pairs: z.array(bridgeReachabilityPairSchema).min(1).max(64),
11008
+ requestId: requestIdSchema,
11009
+ type: z.literal(BRIDGE_TEST_REACHABILITY_REQUEST_TYPE),
11010
+ version: z.literal(2)
11011
+ });
11012
+ const bridgeTestReachabilityRequestSchema = bridgeTestReachabilityRequestFieldsSchema.superRefine((request, ctx) => {
11013
+ request.pairs.forEach((pair, index) => {
11014
+ addNavEndpointIssues(pair, ctx, ["pairs", index]);
11015
+ });
11016
+ });
11017
+ const bridgeSetNavmeshSettingsSuccessResponseSchema = z.object({
11018
+ agentHeight: z.number(),
11019
+ agentMaxSlope: z.number(),
11020
+ agentMaxStepHeight: z.number(),
11021
+ agentRadius: z.number(),
11022
+ appliedSettings: z.array(z.string()).max(32),
11023
+ cellHeight: z.number(),
11024
+ cellSize: z.number(),
11025
+ mergeRegionSize: z.number(),
11026
+ message: nonEmptyStringSchema.optional(),
11027
+ minRegionArea: z.number(),
11028
+ navMeshActorPath: z.string(),
11029
+ ok: z.literal(true),
11030
+ packageDirty: z.boolean(),
11031
+ rebuildRequired: z.boolean(),
11032
+ requestId: requestIdSchema,
11033
+ resolution: navDataResolutionSchema,
11034
+ runtimeGeneration: navRuntimeGenerationSchema,
11035
+ state: creativeEditStateSchema,
11036
+ tileSizeUU: z.number(),
11037
+ type: z.literal(BRIDGE_SET_NAVMESH_SETTINGS_REQUEST_TYPE),
11038
+ version: z.literal(2)
11039
+ });
11040
+ const bridgeSetNavAgentsSuccessResponseSchema = z.object({
11041
+ agentCount: z.number().int().min(0),
11042
+ agents: z.array(z.object({
11043
+ height: z.number(),
11044
+ name: z.string(),
11045
+ radius: z.number()
11046
+ })).max(16),
11047
+ configFilePath: z.string(),
11048
+ message: nonEmptyStringSchema.optional(),
11049
+ ok: z.literal(true),
11050
+ requestId: requestIdSchema,
11051
+ restartRequired: z.boolean(),
11052
+ state: creativeEditStateSchema,
11053
+ type: z.literal(BRIDGE_SET_NAV_AGENTS_REQUEST_TYPE),
11054
+ version: z.literal(2)
11055
+ });
11056
+ const bridgeSetCrowdSettingsSuccessResponseSchema = z.object({
11057
+ appliedCount: z.number().int().min(0),
11058
+ configFilePaths: z.array(z.string()).max(2),
11059
+ failureCount: z.number().int().min(0),
11060
+ items: z.array(bridgeAuthoringItemResultSchema).max(32),
11061
+ message: nonEmptyStringSchema.optional(),
11062
+ ok: z.literal(true),
11063
+ packageDirty: z.boolean(),
11064
+ requestId: requestIdSchema,
11065
+ restartRequired: z.boolean(),
11066
+ state: creativeEditStateSchema,
11067
+ type: z.literal(BRIDGE_SET_CROWD_SETTINGS_REQUEST_TYPE),
11068
+ version: z.literal(2)
11069
+ });
11070
+ const bridgeCreateNavAreaSuccessResponseSchema = z.object({
11071
+ ...createdUserAssetResponseFields,
11072
+ defaultCost: z.number(),
11073
+ drawColor: navColorResponseSchema,
11074
+ fixedAreaEnteringCost: z.number(),
11075
+ generatedClassPath: z.string(),
11076
+ parentClass: z.string(),
11077
+ type: z.literal(BRIDGE_CREATE_NAV_AREA_REQUEST_TYPE)
11078
+ });
11079
+ const bridgeAddNavModifierVolumeSuccessResponseSchema = z.object({
11080
+ actorPath: z.string(),
11081
+ areaClass: z.string(),
11082
+ areaClassToReplace: z.string().optional(),
11083
+ extent: navPointSchema,
11084
+ location: navPointSchema,
11085
+ message: nonEmptyStringSchema.optional(),
11086
+ ok: z.literal(true),
11087
+ packageDirty: z.boolean(),
11088
+ rebuildRequired: z.boolean(),
11089
+ requestId: requestIdSchema,
11090
+ state: creativeEditStateSchema,
11091
+ type: z.literal(BRIDGE_ADD_NAV_MODIFIER_VOLUME_REQUEST_TYPE),
11092
+ version: z.literal(2)
11093
+ });
11094
+ const bridgeAddNavLinkSuccessResponseSchema = z.object({
11095
+ actorPath: z.string(),
11096
+ linkCount: z.number().int().min(0),
11097
+ links: z.array(z.object({
11098
+ direction: navLinkDirectionSchema,
11099
+ left: navPointSchema,
11100
+ right: navPointSchema
11101
+ })).max(16),
11102
+ message: nonEmptyStringSchema.optional(),
11103
+ ok: z.literal(true),
11104
+ packageDirty: z.boolean(),
11105
+ rebuildRequired: z.boolean(),
11106
+ requestId: requestIdSchema,
11107
+ smartLinkEnabled: z.boolean(),
11108
+ state: creativeEditStateSchema,
11109
+ type: z.literal(BRIDGE_ADD_NAV_LINK_REQUEST_TYPE),
11110
+ version: z.literal(2)
11111
+ });
11112
+ const bridgeFindPathSuccessResponseSchema = z.object({
11113
+ endLocation: navPointSchema,
11114
+ message: nonEmptyStringSchema.optional(),
11115
+ ok: z.literal(true),
11116
+ partial: z.boolean(),
11117
+ pathCost: z.number(),
11118
+ pathLength: z.number(),
11119
+ pathPointCount: z.number().int().min(0),
11120
+ pathPoints: z.array(navPointSchema).max(256),
11121
+ queryResult: navQueryResultSchema,
11122
+ reachable: z.boolean(),
11123
+ requestId: requestIdSchema,
11124
+ startLocation: navPointSchema,
11125
+ state: navQueryStateSchema,
11126
+ truncated: z.boolean(),
11127
+ type: z.literal(BRIDGE_FIND_PATH_REQUEST_TYPE),
11128
+ version: z.literal(2)
11129
+ });
11130
+ const bridgeTestReachabilitySuccessResponseSchema = z.object({
11131
+ message: nonEmptyStringSchema.optional(),
11132
+ ok: z.literal(true),
11133
+ pairs: z.array(z.object({
11134
+ error: z.string().optional(),
11135
+ index: z.number().int().min(0),
11136
+ partial: z.boolean(),
11137
+ pathLength: z.number(),
11138
+ reachable: z.boolean()
11139
+ })).max(64),
11140
+ reachableCount: z.number().int().min(0),
11141
+ requestId: requestIdSchema,
11142
+ state: navQueryStateSchema,
11143
+ type: z.literal(BRIDGE_TEST_REACHABILITY_REQUEST_TYPE),
11144
+ unreachableCount: z.number().int().min(0),
11145
+ version: z.literal(2)
11146
+ });
11147
+ const bridgeSetNavmeshSettingsResponseSchema = z.union([bridgeSetNavmeshSettingsSuccessResponseSchema, bridgeErrorResponseSchema]);
11148
+ const bridgeSetNavAgentsResponseSchema = z.union([bridgeSetNavAgentsSuccessResponseSchema, bridgeErrorResponseSchema]);
11149
+ const bridgeSetCrowdSettingsResponseSchema = z.union([bridgeSetCrowdSettingsSuccessResponseSchema, bridgeErrorResponseSchema]);
11150
+ const bridgeCreateNavAreaResponseSchema = z.union([bridgeCreateNavAreaSuccessResponseSchema, bridgeErrorResponseSchema]);
11151
+ const bridgeAddNavModifierVolumeResponseSchema = z.union([bridgeAddNavModifierVolumeSuccessResponseSchema, bridgeErrorResponseSchema]);
11152
+ const bridgeAddNavLinkResponseSchema = z.union([bridgeAddNavLinkSuccessResponseSchema, bridgeErrorResponseSchema]);
11153
+ const bridgeFindPathResponseSchema = z.union([bridgeFindPathSuccessResponseSchema, bridgeErrorResponseSchema]);
11154
+ const bridgeTestReachabilityResponseSchema = z.union([bridgeTestReachabilitySuccessResponseSchema, bridgeErrorResponseSchema]);
11155
+ function createBridgeSetNavmeshSettingsRequest(options = {}, requestId = randomUUID()) {
11156
+ return bridgeSetNavmeshSettingsRequestSchema.parse({
11157
+ agentHeight: options.agentHeight,
11158
+ agentMaxSlope: options.agentMaxSlope,
11159
+ agentMaxStepHeight: options.agentMaxStepHeight,
11160
+ agentRadius: options.agentRadius,
11161
+ cellHeight: options.cellHeight,
11162
+ cellSize: options.cellSize,
11163
+ mergeRegionSize: options.mergeRegionSize,
11164
+ minRegionArea: options.minRegionArea,
11165
+ navMeshActorPath: options.navMeshActorPath,
11166
+ requestId,
11167
+ resolution: options.resolution,
11168
+ runtimeGeneration: options.runtimeGeneration,
11169
+ tileSizeUU: options.tileSizeUU,
11170
+ type: BRIDGE_SET_NAVMESH_SETTINGS_REQUEST_TYPE,
11171
+ version: 2
11172
+ });
11173
+ }
11174
+ function createBridgeSetNavAgentsRequest(agents, requestId = randomUUID()) {
11175
+ return bridgeSetNavAgentsRequestSchema.parse({
11176
+ agents,
11177
+ requestId,
11178
+ type: BRIDGE_SET_NAV_AGENTS_REQUEST_TYPE,
11179
+ version: 2
11180
+ });
11181
+ }
11182
+ function createBridgeSetCrowdSettingsRequest(options = {}, requestId = randomUUID()) {
11183
+ return bridgeSetCrowdSettingsRequestSchema.parse({
11184
+ crowd: options.crowd,
11185
+ requestId,
11186
+ rvo: options.rvo,
11187
+ type: BRIDGE_SET_CROWD_SETTINGS_REQUEST_TYPE,
11188
+ version: 2
11189
+ });
11190
+ }
11191
+ function createBridgeCreateNavAreaRequest(assetName, packagePath, options = {}, requestId = randomUUID()) {
11192
+ return bridgeCreateNavAreaRequestSchema.parse({
11193
+ assetName,
11194
+ defaultCost: options.defaultCost,
11195
+ drawColor: options.drawColor,
11196
+ fixedAreaEnteringCost: options.fixedAreaEnteringCost,
11197
+ packagePath,
11198
+ parentClass: options.parentClass,
11199
+ requestId,
11200
+ type: BRIDGE_CREATE_NAV_AREA_REQUEST_TYPE,
11201
+ version: 2
11202
+ });
11203
+ }
11204
+ function createBridgeAddNavModifierVolumeRequest(areaClass, options = {}, requestId = randomUUID()) {
11205
+ return bridgeAddNavModifierVolumeRequestSchema.parse({
11206
+ actorLabel: options.actorLabel,
11207
+ areaClass,
11208
+ areaClassToReplace: options.areaClassToReplace,
11209
+ extent: options.extent,
11210
+ folderPath: options.folderPath,
11211
+ location: options.location,
11212
+ requestId,
11213
+ rotation: options.rotation,
11214
+ type: BRIDGE_ADD_NAV_MODIFIER_VOLUME_REQUEST_TYPE,
11215
+ version: 2
11216
+ });
11217
+ }
11218
+ function createBridgeAddNavLinkRequest(links, options = {}, requestId = randomUUID()) {
11219
+ return bridgeAddNavLinkRequestSchema.parse({
11220
+ actorLabel: options.actorLabel,
11221
+ folderPath: options.folderPath,
11222
+ links,
11223
+ location: options.location,
11224
+ requestId,
11225
+ rotation: options.rotation,
11226
+ smartLinkEnabled: options.smartLinkEnabled,
11227
+ type: BRIDGE_ADD_NAV_LINK_REQUEST_TYPE,
11228
+ version: 2
11229
+ });
11230
+ }
11231
+ function createBridgeFindPathRequest(endpoints, options = {}, requestId = randomUUID()) {
11232
+ return bridgeFindPathRequestSchema.parse({
11233
+ allowPartial: options.allowPartial,
11234
+ end: endpoints.end,
11235
+ endActorPath: endpoints.endActorPath,
11236
+ maxPathPoints: options.maxPathPoints,
11237
+ navMeshActorPath: options.navMeshActorPath,
11238
+ requestId,
11239
+ start: endpoints.start,
11240
+ startActorPath: endpoints.startActorPath,
11241
+ type: BRIDGE_FIND_PATH_REQUEST_TYPE,
11242
+ version: 2
11243
+ });
11244
+ }
11245
+ function createBridgeTestReachabilityRequest(pairs, options = {}, requestId = randomUUID()) {
11246
+ return bridgeTestReachabilityRequestSchema.parse({
11247
+ allowPartial: options.allowPartial,
11248
+ navMeshActorPath: options.navMeshActorPath,
11249
+ pairs,
11250
+ requestId,
11251
+ type: BRIDGE_TEST_REACHABILITY_REQUEST_TYPE,
11252
+ version: 2
11253
+ });
11254
+ }
11255
+ const BRIDGE_DIAGNOSE_NAVMESH_REQUEST_TYPE = "diagnose_navmesh";
11256
+ const BRIDGE_NAV_DIAGNOSTIC_ISSUE_CODES = [
11257
+ "missing_nav_bounds",
11258
+ "nav_bounds_empty",
11259
+ "no_navigation_data",
11260
+ "navmesh_empty",
11261
+ "no_spawn_points",
11262
+ "island_without_spawn",
11263
+ "spawn_not_found",
11264
+ "spawn_off_navmesh",
11265
+ "spawn_unreachable"
11266
+ ];
11267
+ const BRIDGE_NAV_SPAWN_POINT_KINDS = ["player_start", "actor"];
11268
+ const bridgeDiagnoseNavmeshRequestSchema = z.object({
11269
+ includePlayerStarts: z.boolean().default(true),
11270
+ maxIslands: z.number().int().min(1).max(64).default(16),
11271
+ navMeshActorPath: actorPathSchema.optional(),
11272
+ requestId: requestIdSchema,
11273
+ spawnActorPaths: z.array(actorPathSchema).max(64).default([]),
11274
+ type: z.literal(BRIDGE_DIAGNOSE_NAVMESH_REQUEST_TYPE),
11275
+ version: z.literal(2)
11276
+ });
11277
+ const navDiagnosticIslandSchema = z.object({
11278
+ area: z.number().min(0),
11279
+ bounds: z.object({
11280
+ max: navPointSchema,
11281
+ min: navPointSchema
11282
+ }),
11283
+ index: z.number().int().min(0),
11284
+ polyCount: z.number().int().min(0),
11285
+ spawnPointCount: z.number().int().min(0)
11286
+ });
11287
+ const navDiagnosticSpawnPointSchema = z.object({
11288
+ actorPath: z.string(),
11289
+ error: z.string().optional(),
11290
+ islandIndex: z.number().int().min(0).optional(),
11291
+ kind: z.enum(BRIDGE_NAV_SPAWN_POINT_KINDS),
11292
+ location: navPointSchema,
11293
+ onNavMesh: z.boolean(),
11294
+ pathLength: z.number().optional(),
11295
+ projectedLocation: navPointSchema.optional(),
11296
+ reachableFromAnchor: z.boolean()
11297
+ });
11298
+ const navDiagnosticIssueSchema = z.object({
11299
+ actorPath: z.string().optional(),
11300
+ code: z.enum(BRIDGE_NAV_DIAGNOSTIC_ISSUE_CODES),
11301
+ islandIndex: z.number().int().min(0).optional(),
11302
+ message: z.string()
11303
+ });
11304
+ const bridgeDiagnoseNavmeshSuccessResponseSchema = z.object({
11305
+ anchorActorPath: z.string().optional(),
11306
+ healthy: z.boolean(),
11307
+ islandCount: z.number().int().min(0),
11308
+ islands: z.array(navDiagnosticIslandSchema).max(64),
11309
+ islandsTruncated: z.boolean(),
11310
+ issueCount: z.number().int().min(0),
11311
+ issues: z.array(navDiagnosticIssueSchema).max(64),
11312
+ issuesTruncated: z.boolean(),
11313
+ message: nonEmptyStringSchema.optional(),
11314
+ navBoundsVolumeCount: z.number().int().min(0),
11315
+ navMeshActorPath: z.string(),
11316
+ ok: z.literal(true),
11317
+ polyCount: z.number().int().min(0),
11318
+ requestId: requestIdSchema,
11319
+ spawnPointCount: z.number().int().min(0),
11320
+ spawnPoints: z.array(navDiagnosticSpawnPointSchema).max(64),
11321
+ spawnPointsTruncated: z.boolean(),
11322
+ state: navQueryStateSchema,
11323
+ type: z.literal(BRIDGE_DIAGNOSE_NAVMESH_REQUEST_TYPE),
11324
+ version: z.literal(2)
11325
+ });
11326
+ const bridgeDiagnoseNavmeshResponseSchema = z.union([bridgeDiagnoseNavmeshSuccessResponseSchema, bridgeErrorResponseSchema]);
11327
+ function createBridgeDiagnoseNavmeshRequest(options = {}, requestId = randomUUID()) {
11328
+ return bridgeDiagnoseNavmeshRequestSchema.parse({
11329
+ includePlayerStarts: options.includePlayerStarts,
11330
+ maxIslands: options.maxIslands,
11331
+ navMeshActorPath: options.navMeshActorPath,
11332
+ requestId,
11333
+ spawnActorPaths: options.spawnActorPaths,
11334
+ type: BRIDGE_DIAGNOSE_NAVMESH_REQUEST_TYPE,
11335
+ version: 2
11336
+ });
11337
+ }
11338
+ //#endregion
11339
+ //#region src/protocol/smartObjects.ts
11340
+ const BRIDGE_CREATE_SMART_OBJECT_DEFINITION_REQUEST_TYPE = "create_smart_object_definition";
11341
+ const BRIDGE_GET_SMART_OBJECT_DEFINITION_REQUEST_TYPE = "get_smart_object_definition";
11342
+ const BRIDGE_ADD_SMART_OBJECT_COMPONENT_REQUEST_TYPE = "add_smart_object_component";
11343
+ const BRIDGE_SMART_OBJECT_COMPONENT_TARGETS = ["blueprint", "actor"];
11344
+ const bridgeSmartObjectBehaviorDefinitionSchema = z.object({
11345
+ behaviorClass: assetPathSchema,
11346
+ params: instancedObjectParamsSchema
11347
+ });
11348
+ const activityTagsSchema = z.array(gameplayTagNameSchema).max(16).default([]);
11349
+ const behaviorDefinitionsSchema = z.array(bridgeSmartObjectBehaviorDefinitionSchema).max(8).default([]);
11350
+ const bridgeSmartObjectSlotSchema = z.object({
11351
+ activityTags: activityTagsSchema,
11352
+ behaviorDefinitions: behaviorDefinitionsSchema,
11353
+ enabled: z.boolean().default(true),
11354
+ name: requiredBoundedStringSchema.optional(),
11355
+ offset: bridgeVectorSchema.optional(),
11356
+ rotation: bridgeRotatorSchema.optional()
11357
+ });
11358
+ const bridgeCreateSmartObjectDefinitionRequestSchema = z.object({
11359
+ activityTags: activityTagsSchema,
11360
+ assetName: assetNameSchema,
11361
+ defaultBehaviorDefinitions: behaviorDefinitionsSchema,
11362
+ packagePath: contentPathSchema,
11363
+ requestId: requestIdSchema,
11364
+ slots: z.array(bridgeSmartObjectSlotSchema).min(1).max(32),
11365
+ type: z.literal(BRIDGE_CREATE_SMART_OBJECT_DEFINITION_REQUEST_TYPE),
11366
+ version: z.literal(2)
11367
+ });
11368
+ const bridgeGetSmartObjectDefinitionRequestSchema = z.object({
11369
+ assetPath: assetPathSchema,
11370
+ requestId: requestIdSchema,
11371
+ type: z.literal(BRIDGE_GET_SMART_OBJECT_DEFINITION_REQUEST_TYPE),
11372
+ version: z.literal(2)
11373
+ });
11374
+ const bridgeAddSmartObjectComponentRequestFieldsSchema = z.object({
11375
+ actorPath: actorPathSchema.optional(),
11376
+ blueprintPath: assetPathSchema.optional(),
11377
+ componentName: requiredBoundedStringSchema.optional(),
11378
+ definitionPath: assetPathSchema,
11379
+ requestId: requestIdSchema,
11380
+ type: z.literal(BRIDGE_ADD_SMART_OBJECT_COMPONENT_REQUEST_TYPE),
11381
+ version: z.literal(2)
11382
+ });
11383
+ const bridgeAddSmartObjectComponentRequestSchema = bridgeAddSmartObjectComponentRequestFieldsSchema.refine((request) => request.actorPath === void 0 !== (request.blueprintPath === void 0), {
11384
+ message: "An add_smart_object_component request names exactly one of blueprintPath or actorPath.",
11385
+ path: ["blueprintPath"]
11386
+ });
11387
+ const bridgeSmartObjectSlotReportSchema = z.object({
11388
+ activityTags: z.array(z.string()).max(16),
11389
+ behaviorDefinitions: z.array(z.string()).max(8),
11390
+ enabled: z.boolean(),
11391
+ index: z.number().int().min(0),
11392
+ name: z.string(),
11393
+ offset: bridgeVectorSchema,
11394
+ rotation: bridgeRotatorSchema
11395
+ });
11396
+ const smartObjectDefinitionReportFields = {
11397
+ activityTags: z.array(z.string()).max(16),
11398
+ defaultBehaviorDefinitions: z.array(z.string()).max(8),
11399
+ slots: z.array(bridgeSmartObjectSlotReportSchema).max(32),
11400
+ valid: z.boolean(),
11401
+ validationMessages: z.array(z.string()).max(32)
11402
+ };
11403
+ const bridgeCreateSmartObjectDefinitionSuccessResponseSchema = z.object({
11404
+ ...createdUserAssetResponseFields,
11405
+ ...smartObjectDefinitionReportFields,
11406
+ type: z.literal(BRIDGE_CREATE_SMART_OBJECT_DEFINITION_REQUEST_TYPE)
11407
+ });
11408
+ const bridgeGetSmartObjectDefinitionSuccessResponseSchema = z.object({
11409
+ ...smartObjectDefinitionReportFields,
11410
+ assetPath: z.string(),
11411
+ message: nonEmptyStringSchema.optional(),
11412
+ ok: z.literal(true),
11413
+ requestId: requestIdSchema,
11414
+ state: aiReportStateSchema,
11415
+ type: z.literal(BRIDGE_GET_SMART_OBJECT_DEFINITION_REQUEST_TYPE),
11416
+ version: z.literal(2)
11417
+ });
11418
+ const bridgeAddSmartObjectComponentSuccessResponseSchema = z.object({
11419
+ componentName: z.string(),
11420
+ created: z.boolean(),
11421
+ definitionPath: z.string(),
11422
+ definitionValid: z.boolean(),
11423
+ message: nonEmptyStringSchema.optional(),
11424
+ ok: z.literal(true),
11425
+ packageDirty: z.boolean(),
11426
+ requestId: requestIdSchema,
11427
+ state: creativeEditStateSchema,
11428
+ target: z.enum(BRIDGE_SMART_OBJECT_COMPONENT_TARGETS),
11429
+ targetPath: z.string(),
11430
+ type: z.literal(BRIDGE_ADD_SMART_OBJECT_COMPONENT_REQUEST_TYPE),
11431
+ version: z.literal(2)
11432
+ });
11433
+ const bridgeCreateSmartObjectDefinitionResponseSchema = z.union([bridgeCreateSmartObjectDefinitionSuccessResponseSchema, bridgeErrorResponseSchema]);
11434
+ const bridgeGetSmartObjectDefinitionResponseSchema = z.union([bridgeGetSmartObjectDefinitionSuccessResponseSchema, bridgeErrorResponseSchema]);
11435
+ const bridgeAddSmartObjectComponentResponseSchema = z.union([bridgeAddSmartObjectComponentSuccessResponseSchema, bridgeErrorResponseSchema]);
11436
+ function createBridgeCreateSmartObjectDefinitionRequest(assetName, packagePath, slots, options = {}, requestId = randomUUID()) {
11437
+ return bridgeCreateSmartObjectDefinitionRequestSchema.parse({
11438
+ activityTags: options.activityTags,
11439
+ assetName,
11440
+ defaultBehaviorDefinitions: options.defaultBehaviorDefinitions,
11441
+ packagePath,
11442
+ requestId,
11443
+ slots,
11444
+ type: BRIDGE_CREATE_SMART_OBJECT_DEFINITION_REQUEST_TYPE,
11445
+ version: 2
11446
+ });
11447
+ }
11448
+ function createBridgeGetSmartObjectDefinitionRequest(assetPath, requestId = randomUUID()) {
11449
+ return bridgeGetSmartObjectDefinitionRequestSchema.parse({
11450
+ assetPath,
11451
+ requestId,
11452
+ type: BRIDGE_GET_SMART_OBJECT_DEFINITION_REQUEST_TYPE,
11453
+ version: 2
11454
+ });
11455
+ }
11456
+ function createBridgeAddSmartObjectComponentRequest(definitionPath, target, options = {}, requestId = randomUUID()) {
11457
+ return bridgeAddSmartObjectComponentRequestSchema.parse({
11458
+ actorPath: target.actorPath,
11459
+ blueprintPath: target.blueprintPath,
11460
+ componentName: options.componentName,
11461
+ definitionPath,
11462
+ requestId,
11463
+ type: BRIDGE_ADD_SMART_OBJECT_COMPONENT_REQUEST_TYPE,
11464
+ version: 2
11465
+ });
11466
+ }
11467
+ //#endregion
11468
+ //#region src/protocol/mass.ts
11469
+ const BRIDGE_CREATE_MASS_ENTITY_CONFIG_REQUEST_TYPE = "create_mass_entity_config";
11470
+ const BRIDGE_EDIT_MASS_ENTITY_CONFIG_REQUEST_TYPE = "edit_mass_entity_config";
11471
+ const BRIDGE_GET_MASS_ENTITY_CONFIG_REQUEST_TYPE = "get_mass_entity_config";
11472
+ const BRIDGE_VALIDATE_MASS_ENTITY_CONFIG_REQUEST_TYPE = "validate_mass_entity_config";
11473
+ const BRIDGE_MASS_TRAIT_OPERATIONS = [
11474
+ "add",
11475
+ "remove",
11476
+ "set"
11477
+ ];
11478
+ const BRIDGE_MASS_READ_STATES = ["reported", "unsupported"];
11479
+ const BRIDGE_MASS_VALIDATION_SEVERITIES = ["error", "warning"];
11480
+ const massReadStateSchema = z.enum(BRIDGE_MASS_READ_STATES);
11481
+ const traitClassSchema = z.string().trim().min(1).max(512);
11482
+ const bridgeMassTraitEditSchema = z.object({
11483
+ operation: z.enum(BRIDGE_MASS_TRAIT_OPERATIONS),
11484
+ properties: z.array(bridgeAssetPropertyEntrySchema).max(32).optional(),
11485
+ traitClass: traitClassSchema
11486
+ }).superRefine((edit, context) => {
11487
+ const count = edit.properties?.length ?? 0;
11488
+ if (edit.operation === "set" && count === 0) context.addIssue({
11489
+ code: z.ZodIssueCode.custom,
11490
+ message: "A 'set' trait edit must carry at least one property.",
11491
+ path: ["properties"]
11492
+ });
11493
+ if (edit.operation === "remove" && count > 0) context.addIssue({
11494
+ code: z.ZodIssueCode.custom,
11495
+ message: "A 'remove' trait edit cannot carry properties.",
11496
+ path: ["properties"]
11497
+ });
11498
+ });
11499
+ const bridgeCreateMassEntityConfigRequestSchema = z.object({
11500
+ assetName: assetNameSchema,
11501
+ packagePath: contentPathSchema,
11502
+ parentConfigPath: assetPathSchema.optional(),
11503
+ requestId: requestIdSchema,
11504
+ type: z.literal(BRIDGE_CREATE_MASS_ENTITY_CONFIG_REQUEST_TYPE),
11505
+ version: z.literal(2)
11506
+ });
11507
+ const bridgeEditMassEntityConfigRequestSchema = z.object({
11508
+ assetPath: assetPathSchema,
11509
+ edits: z.array(bridgeMassTraitEditSchema).min(1).max(16),
11510
+ requestId: requestIdSchema,
11511
+ type: z.literal(BRIDGE_EDIT_MASS_ENTITY_CONFIG_REQUEST_TYPE),
11512
+ version: z.literal(2)
11513
+ });
11514
+ const bridgeGetMassEntityConfigRequestSchema = z.object({
11515
+ assetPath: assetPathSchema,
11516
+ requestId: requestIdSchema,
11517
+ type: z.literal(BRIDGE_GET_MASS_ENTITY_CONFIG_REQUEST_TYPE),
11518
+ version: z.literal(2)
11519
+ });
11520
+ const bridgeValidateMassEntityConfigRequestSchema = z.object({
11521
+ assetPath: assetPathSchema,
11522
+ requestId: requestIdSchema,
11523
+ type: z.literal(BRIDGE_VALIDATE_MASS_ENTITY_CONFIG_REQUEST_TYPE),
11524
+ version: z.literal(2)
11525
+ });
11526
+ const bridgeCreateMassEntityConfigSuccessResponseSchema = z.object({
11527
+ ...createdUserAssetResponseFields,
11528
+ parentConfigPath: z.string().optional(),
11529
+ type: z.literal(BRIDGE_CREATE_MASS_ENTITY_CONFIG_REQUEST_TYPE)
11530
+ });
11531
+ const bridgeEditMassEntityConfigSuccessResponseSchema = z.object({
11532
+ ...authoringBatchResponseFields,
11533
+ traits: z.array(z.string()).max(64),
11534
+ type: z.literal(BRIDGE_EDIT_MASS_ENTITY_CONFIG_REQUEST_TYPE)
11535
+ });
11536
+ const bridgeMassTraitReportSchema = z.object({
11537
+ index: z.number().int().min(0),
11538
+ properties: z.record(z.string(), z.string()),
11539
+ traitClass: z.string(),
11540
+ traitName: z.string()
11541
+ });
11542
+ const bridgeGetMassEntityConfigSuccessResponseSchema = z.object({
11543
+ assetPath: z.string(),
11544
+ message: nonEmptyStringSchema.optional(),
11545
+ ok: z.literal(true),
11546
+ parentConfigPath: z.string().optional(),
11547
+ requestId: requestIdSchema,
11548
+ state: massReadStateSchema,
11549
+ traits: z.array(bridgeMassTraitReportSchema).max(64),
11550
+ truncated: z.boolean(),
11551
+ type: z.literal(BRIDGE_GET_MASS_ENTITY_CONFIG_REQUEST_TYPE),
11552
+ version: z.literal(2)
11553
+ });
11554
+ const bridgeMassValidationMessageSchema = z.object({
11555
+ category: z.string(),
11556
+ severity: z.enum(BRIDGE_MASS_VALIDATION_SEVERITIES),
11557
+ text: z.string()
11558
+ });
11559
+ const bridgeValidateMassEntityConfigSuccessResponseSchema = z.object({
11560
+ assetPath: z.string(),
11561
+ errorCount: z.number().int().min(0),
11562
+ message: nonEmptyStringSchema.optional(),
11563
+ messages: z.array(bridgeMassValidationMessageSchema).max(32),
11564
+ ok: z.literal(true),
11565
+ requestId: requestIdSchema,
11566
+ state: massReadStateSchema,
11567
+ truncated: z.boolean(),
11568
+ type: z.literal(BRIDGE_VALIDATE_MASS_ENTITY_CONFIG_REQUEST_TYPE),
11569
+ valid: z.boolean(),
11570
+ version: z.literal(2),
11571
+ warningCount: z.number().int().min(0)
11572
+ });
11573
+ const bridgeCreateMassEntityConfigResponseSchema = z.union([bridgeCreateMassEntityConfigSuccessResponseSchema, bridgeErrorResponseSchema]);
11574
+ const bridgeEditMassEntityConfigResponseSchema = z.union([bridgeEditMassEntityConfigSuccessResponseSchema, bridgeErrorResponseSchema]);
11575
+ const bridgeGetMassEntityConfigResponseSchema = z.union([bridgeGetMassEntityConfigSuccessResponseSchema, bridgeErrorResponseSchema]);
11576
+ const bridgeValidateMassEntityConfigResponseSchema = z.union([bridgeValidateMassEntityConfigSuccessResponseSchema, bridgeErrorResponseSchema]);
11577
+ function createBridgeCreateMassEntityConfigRequest(assetName, packagePath, options = {}, requestId = randomUUID()) {
11578
+ return bridgeCreateMassEntityConfigRequestSchema.parse({
11579
+ assetName,
11580
+ packagePath,
11581
+ parentConfigPath: options.parentConfigPath,
11582
+ requestId,
11583
+ type: BRIDGE_CREATE_MASS_ENTITY_CONFIG_REQUEST_TYPE,
11584
+ version: 2
11585
+ });
11586
+ }
11587
+ function createBridgeEditMassEntityConfigRequest(assetPath, edits, requestId = randomUUID()) {
11588
+ return bridgeEditMassEntityConfigRequestSchema.parse({
11589
+ assetPath,
11590
+ edits,
11591
+ requestId,
11592
+ type: BRIDGE_EDIT_MASS_ENTITY_CONFIG_REQUEST_TYPE,
11593
+ version: 2
11594
+ });
11595
+ }
11596
+ function createBridgeGetMassEntityConfigRequest(assetPath, requestId = randomUUID()) {
11597
+ return bridgeGetMassEntityConfigRequestSchema.parse({
11598
+ assetPath,
11599
+ requestId,
11600
+ type: BRIDGE_GET_MASS_ENTITY_CONFIG_REQUEST_TYPE,
10466
11601
  version: 2
10467
11602
  });
10468
11603
  }
10469
- function createBridgeSetDefaultGamemodeRequest(scope, gameModePath, options = {}, requestId = randomUUID()) {
10470
- return bridgeSetDefaultGamemodeRequestSchema.parse({
10471
- defaultPawnClassPath: options.defaultPawnClassPath,
10472
- gameModePath,
10473
- gameStateClassPath: options.gameStateClassPath,
10474
- hudClassPath: options.hudClassPath,
10475
- levelPath: options.levelPath,
10476
- playerControllerClassPath: options.playerControllerClassPath,
10477
- playerStateClassPath: options.playerStateClassPath,
11604
+ function createBridgeValidateMassEntityConfigRequest(assetPath, requestId = randomUUID()) {
11605
+ return bridgeValidateMassEntityConfigRequestSchema.parse({
11606
+ assetPath,
10478
11607
  requestId,
10479
- scope,
10480
- startupMapPath: options.startupMapPath,
10481
- type: BRIDGE_SET_DEFAULT_GAMEMODE_REQUEST_TYPE,
11608
+ type: BRIDGE_VALIDATE_MASS_ENTITY_CONFIG_REQUEST_TYPE,
10482
11609
  version: 2
10483
11610
  });
10484
11611
  }
10485
11612
  //#endregion
10486
11613
  //#region src/version.ts
10487
- const SERVER_VERSION = "1.10.0";
11614
+ const SERVER_VERSION = "1.12.0";
10488
11615
  //#endregion
10489
11616
  //#region src/bridgeSocketClient.ts
10490
11617
  var BridgeSocketError = class extends Error {
@@ -10720,6 +11847,9 @@ async function sendBridgeSetPinDefaultRequest(request, options) {
10720
11847
  async function sendBridgeListAvailableNodesRequest(request, options) {
10721
11848
  return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeListAvailableNodesResponseSchema, request.requestId);
10722
11849
  }
11850
+ async function sendBridgeLayoutGraphRequest(request, options) {
11851
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeLayoutGraphResponseSchema, request.requestId);
11852
+ }
10723
11853
  async function sendBridgeSetViewportCameraRequest(request, options) {
10724
11854
  return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeSetViewportCameraResponseSchema, request.requestId);
10725
11855
  }
@@ -11416,6 +12546,60 @@ async function sendBridgeSetStateTreeGlobalsRequest(request, options) {
11416
12546
  async function sendBridgeTraceStateTreeRequest(request, options) {
11417
12547
  return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeTraceStateTreeResponseSchema, request.requestId);
11418
12548
  }
12549
+ async function sendBridgeSetNavmeshSettingsRequest(request, options) {
12550
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeSetNavmeshSettingsResponseSchema, request.requestId);
12551
+ }
12552
+ async function sendBridgeSetNavAgentsRequest(request, options) {
12553
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeSetNavAgentsResponseSchema, request.requestId);
12554
+ }
12555
+ async function sendBridgeSetCrowdSettingsRequest(request, options) {
12556
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeSetCrowdSettingsResponseSchema, request.requestId);
12557
+ }
12558
+ async function sendBridgeCreateNavAreaRequest(request, options) {
12559
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeCreateNavAreaResponseSchema, request.requestId);
12560
+ }
12561
+ async function sendBridgeAddNavModifierVolumeRequest(request, options) {
12562
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeAddNavModifierVolumeResponseSchema, request.requestId);
12563
+ }
12564
+ async function sendBridgeAddNavLinkRequest(request, options) {
12565
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeAddNavLinkResponseSchema, request.requestId);
12566
+ }
12567
+ async function sendBridgeFindPathRequest(request, options) {
12568
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeFindPathResponseSchema, request.requestId);
12569
+ }
12570
+ async function sendBridgeTestReachabilityRequest(request, options) {
12571
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeTestReachabilityResponseSchema, request.requestId);
12572
+ }
12573
+ async function sendBridgeCreateSmartObjectDefinitionRequest(request, options) {
12574
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeCreateSmartObjectDefinitionResponseSchema, request.requestId);
12575
+ }
12576
+ async function sendBridgeGetSmartObjectDefinitionRequest(request, options) {
12577
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetSmartObjectDefinitionResponseSchema, request.requestId);
12578
+ }
12579
+ async function sendBridgeAddSmartObjectComponentRequest(request, options) {
12580
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeAddSmartObjectComponentResponseSchema, request.requestId);
12581
+ }
12582
+ async function sendBridgeCreateMassEntityConfigRequest(request, options) {
12583
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeCreateMassEntityConfigResponseSchema, request.requestId);
12584
+ }
12585
+ async function sendBridgeEditMassEntityConfigRequest(request, options) {
12586
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeEditMassEntityConfigResponseSchema, request.requestId);
12587
+ }
12588
+ async function sendBridgeGetMassEntityConfigRequest(request, options) {
12589
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetMassEntityConfigResponseSchema, request.requestId);
12590
+ }
12591
+ async function sendBridgeValidateMassEntityConfigRequest(request, options) {
12592
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeValidateMassEntityConfigResponseSchema, request.requestId);
12593
+ }
12594
+ async function sendBridgeDiagnoseNavmeshRequest(request, options) {
12595
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeDiagnoseNavmeshResponseSchema, request.requestId);
12596
+ }
12597
+ async function sendBridgeUpdateStateTreeElementsRequest(request, options) {
12598
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeUpdateStateTreeElementsResponseSchema, request.requestId);
12599
+ }
12600
+ async function sendBridgeRemoveStateTreeElementsRequest(request, options) {
12601
+ return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeRemoveStateTreeElementsResponseSchema, request.requestId);
12602
+ }
11419
12603
  //#endregion
11420
12604
  //#region src/enginePing.ts
11421
12605
  async function pingRegistryEntry$1(entry, options) {
@@ -18242,6 +19426,7 @@ const debuggerToolDomain = {
18242
19426
  };
18243
19427
  //#endregion
18244
19428
  //#region src/traceAnalysis.ts
19429
+ const LLM_TAG_COUNTER_PATTERN = "STAT_*LLM";
18245
19430
  const SECONDS_TO_MS = 1e3;
18246
19431
  const FRAME_ROOT_TIMER_NAMES = /* @__PURE__ */ new Set(["FEngineLoop::Tick"]);
18247
19432
  function parseCsvRows(text) {
@@ -18334,6 +19519,9 @@ function summarizeTimerStatistics(rows, maxScopes) {
18334
19519
  if (count !== void 0) scope.count = count;
18335
19520
  scopes.push(scope);
18336
19521
  }
19522
+ return rankScopes(scopes, maxScopes);
19523
+ }
19524
+ function rankScopes(scopes, maxScopes) {
18337
19525
  const byInclusiveTime = [...scopes].sort((left, right) => right.inclusiveTimeMs - left.inclusiveTimeMs);
18338
19526
  return {
18339
19527
  byExclusiveTime: [...scopes].sort((left, right) => right.exclusiveTimeMs - left.exclusiveTimeMs).slice(0, maxScopes),
@@ -18345,18 +19533,20 @@ function summarizeTimerStatistics(rows, maxScopes) {
18345
19533
  function isGpuThread(threadName) {
18346
19534
  return threadName.toUpperCase().includes("GPU");
18347
19535
  }
18348
- async function summarizeTimingEventStream(lines, options) {
19536
+ async function forEachTimingEvent(lines, visit) {
18349
19537
  let headers;
18350
19538
  let threadIndex = -1;
18351
19539
  let timerIndex = -1;
18352
19540
  let durationIndex = -1;
18353
19541
  let startIndex = -1;
18354
19542
  let depthIndex = -1;
18355
- let cpuTimeMs = 0;
18356
- let gpuTimeMs = 0;
18357
- const frameDurationsMs = [];
18358
- const worstHitches = [];
18359
- let hitchCount = 0;
19543
+ const event = {
19544
+ depth: 0,
19545
+ durationMs: 0,
19546
+ startTimeMs: 0,
19547
+ threadName: "",
19548
+ timerName: ""
19549
+ };
18360
19550
  for await (const rawLine of lines) {
18361
19551
  const line = rawLine.trim();
18362
19552
  if (line.length === 0) continue;
@@ -18369,36 +19559,160 @@ async function summarizeTimingEventStream(lines, options) {
18369
19559
  durationIndex = columnIndex(headers, findColumn(headerRow, "Duration", "InclusiveTime"));
18370
19560
  startIndex = columnIndex(headers, findColumn(headerRow, "StartTime", "Start"));
18371
19561
  depthIndex = columnIndex(headers, findColumn(headerRow, "Depth"));
18372
- if (threadIndex < 0 || durationIndex < 0) break;
19562
+ if (threadIndex < 0 || durationIndex < 0) return;
18373
19563
  continue;
18374
19564
  }
18375
19565
  const duration = readNumber(values[durationIndex]);
18376
19566
  const threadName = values[threadIndex];
18377
19567
  if (duration === void 0 || threadName === void 0) continue;
18378
- if ((depthIndex < 0 ? 0 : readNumber(values[depthIndex]) ?? 0) !== 0) continue;
18379
- const durationMs = duration * SECONDS_TO_MS;
18380
- if (isGpuThread(threadName)) {
18381
- gpuTimeMs += durationMs;
18382
- continue;
19568
+ event.depth = depthIndex < 0 ? 0 : readNumber(values[depthIndex]) ?? 0;
19569
+ event.durationMs = duration * SECONDS_TO_MS;
19570
+ event.startTimeMs = (startIndex < 0 ? 0 : readNumber(values[startIndex]) ?? 0) * SECONDS_TO_MS;
19571
+ event.threadName = threadName;
19572
+ event.timerName = timerIndex < 0 ? "" : values[timerIndex] ?? "";
19573
+ visit(event);
19574
+ }
19575
+ }
19576
+ var ScopeAncestry = class {
19577
+ names = [];
19578
+ threadName;
19579
+ enter(event) {
19580
+ if (event.threadName !== this.threadName) {
19581
+ this.threadName = event.threadName;
19582
+ this.names.length = 0;
19583
+ }
19584
+ this.names.length = Math.min(this.names.length, event.depth);
19585
+ const parentName = event.depth > 0 ? this.names[event.depth - 1] : void 0;
19586
+ this.names[event.depth] = event.timerName;
19587
+ return parentName;
19588
+ }
19589
+ hasOpenAncestorNamed(event) {
19590
+ return this.names.slice(0, event.depth).includes(event.timerName);
19591
+ }
19592
+ };
19593
+ async function summarizeTimingEventStream(lines, options) {
19594
+ let cpuTimeMs = 0;
19595
+ let gpuTimeMs = 0;
19596
+ const frameDurationsMs = [];
19597
+ const worstHitches = [];
19598
+ let hitchCount = 0;
19599
+ const gpuScopeTotals = /* @__PURE__ */ new Map();
19600
+ const gpuAncestry = new ScopeAncestry();
19601
+ await forEachTimingEvent(lines, (event) => {
19602
+ if (isGpuThread(event.threadName)) {
19603
+ accumulateGpuScope(gpuScopeTotals, gpuAncestry, event);
19604
+ if (event.depth === 0) gpuTimeMs += event.durationMs;
19605
+ return;
18383
19606
  }
18384
- cpuTimeMs += durationMs;
18385
- if (timerIndex < 0 || !FRAME_ROOT_TIMER_NAMES.has(values[timerIndex] ?? "")) continue;
18386
- frameDurationsMs.push(durationMs);
18387
- if (durationMs < options.hitchThresholdMs) continue;
19607
+ if (event.depth !== 0) return;
19608
+ cpuTimeMs += event.durationMs;
19609
+ if (!FRAME_ROOT_TIMER_NAMES.has(event.timerName)) return;
19610
+ frameDurationsMs.push(event.durationMs);
19611
+ if (event.durationMs < options.hitchThresholdMs) return;
18388
19612
  hitchCount += 1;
18389
19613
  retainWorstHitch(worstHitches, options.maxHitches, {
18390
- durationMs,
18391
- startTimeMs: (startIndex < 0 ? 0 : readNumber(values[startIndex]) ?? 0) * SECONDS_TO_MS
19614
+ durationMs: event.durationMs,
19615
+ startTimeMs: event.startTimeMs,
19616
+ topScopes: []
18392
19617
  });
18393
- }
19618
+ });
18394
19619
  return {
18395
19620
  frames: summarizeFrameDurations(frameDurationsMs, worstHitches, hitchCount, options),
19621
+ gpuScopes: rankScopeTotals(gpuScopeTotals, options.maxScopes),
18396
19622
  threads: {
18397
19623
  cpuTimeMs,
18398
19624
  gpuTimeMs
18399
19625
  }
18400
19626
  };
18401
19627
  }
19628
+ function accumulateGpuScope(totals, ancestry, event) {
19629
+ const parentName = ancestry.enter(event);
19630
+ const scope = scopeTotalsFor(totals, event.timerName);
19631
+ scope.count += 1;
19632
+ scope.exclusiveTimeMs += event.durationMs;
19633
+ if (!ancestry.hasOpenAncestorNamed(event)) scope.inclusiveTimeMs += event.durationMs;
19634
+ if (parentName !== void 0) scopeTotalsFor(totals, parentName).exclusiveTimeMs -= event.durationMs;
19635
+ }
19636
+ function scopeTotalsFor(totals, name) {
19637
+ const existing = totals.get(name);
19638
+ if (existing !== void 0) return existing;
19639
+ const created = {
19640
+ count: 0,
19641
+ exclusiveTimeMs: 0,
19642
+ inclusiveTimeMs: 0
19643
+ };
19644
+ totals.set(name, created);
19645
+ return created;
19646
+ }
19647
+ function rankScopeTotals(totals, maxScopes) {
19648
+ return rankScopes([...totals].map(([name, scope]) => ({
19649
+ count: scope.count,
19650
+ exclusiveTimeMs: scope.exclusiveTimeMs,
19651
+ inclusiveTimeMs: scope.inclusiveTimeMs,
19652
+ name
19653
+ })), maxScopes);
19654
+ }
19655
+ const SCOPE_KEY_SEPARATOR = "\0";
19656
+ const IDLE_TIMER_NAMES = /* @__PURE__ */ new Set(["TaskWorkerIsLookingForWork", "WaitForTasks"]);
19657
+ async function attributeHitchScopes(lines, hitches, maxScopesPerHitch) {
19658
+ if (hitches.length === 0) return [];
19659
+ const windows = hitches.map((hitch) => ({
19660
+ endTimeMs: hitch.startTimeMs + hitch.durationMs,
19661
+ exclusiveByScope: /* @__PURE__ */ new Map(),
19662
+ hitch,
19663
+ startTimeMs: hitch.startTimeMs
19664
+ })).sort((left, right) => left.startTimeMs - right.startTimeMs);
19665
+ const ancestry = new ScopeAncestry();
19666
+ await forEachTimingEvent(lines, (event) => {
19667
+ if (isGpuThread(event.threadName)) return;
19668
+ const parentName = ancestry.enter(event);
19669
+ const eventEndMs = event.startTimeMs + event.durationMs;
19670
+ for (let index = firstWindowEndingAfter(windows, event.startTimeMs); index < windows.length && (windows[index]?.startTimeMs ?? Number.POSITIVE_INFINITY) < eventEndMs; index += 1) {
19671
+ const window = windows[index];
19672
+ if (window === void 0) break;
19673
+ const overlapMs = Math.min(eventEndMs, window.endTimeMs) - Math.max(event.startTimeMs, window.startTimeMs);
19674
+ if (overlapMs <= 0) continue;
19675
+ addScopeTime(window.exclusiveByScope, event.threadName, event.timerName, overlapMs);
19676
+ if (parentName !== void 0) addScopeTime(window.exclusiveByScope, event.threadName, parentName, -overlapMs);
19677
+ }
19678
+ });
19679
+ return hitches.map((hitch) => {
19680
+ const window = windows.find((candidate) => candidate.hitch === hitch);
19681
+ return {
19682
+ ...hitch,
19683
+ topScopes: window === void 0 ? [] : topHitchScopes(window, maxScopesPerHitch)
19684
+ };
19685
+ });
19686
+ }
19687
+ function firstWindowEndingAfter(windows, timeMs) {
19688
+ let low = 0;
19689
+ let high = windows.length;
19690
+ while (low < high) {
19691
+ const middle = low + high >>> 1;
19692
+ if ((windows[middle]?.endTimeMs ?? Number.POSITIVE_INFINITY) <= timeMs) low = middle + 1;
19693
+ else high = middle;
19694
+ }
19695
+ return low;
19696
+ }
19697
+ function addScopeTime(exclusiveByScope, threadName, timerName, ms) {
19698
+ const key = `${threadName}${SCOPE_KEY_SEPARATOR}${timerName}`;
19699
+ exclusiveByScope.set(key, (exclusiveByScope.get(key) ?? 0) + ms);
19700
+ }
19701
+ function topHitchScopes(window, maxScopes) {
19702
+ const scopes = [];
19703
+ for (const [key, exclusiveTimeMs] of window.exclusiveByScope) {
19704
+ if (exclusiveTimeMs <= 1e-6) continue;
19705
+ const separatorAt = key.indexOf(SCOPE_KEY_SEPARATOR);
19706
+ const name = key.slice(separatorAt + 1);
19707
+ if (IDLE_TIMER_NAMES.has(name)) continue;
19708
+ scopes.push({
19709
+ exclusiveTimeMs,
19710
+ name,
19711
+ threadName: key.slice(0, separatorAt)
19712
+ });
19713
+ }
19714
+ return scopes.sort((left, right) => right.exclusiveTimeMs - left.exclusiveTimeMs).slice(0, maxScopes);
19715
+ }
18402
19716
  function retainWorstHitch(worstHitches, maxHitches, hitch) {
18403
19717
  if (worstHitches.length >= maxHitches) {
18404
19718
  const weakest = worstHitches[worstHitches.length - 1];
@@ -18434,16 +19748,53 @@ function percentile(sortedValues, fraction) {
18434
19748
  if (sortedValues.length === 0) return 0;
18435
19749
  return sortedValues[Math.min(sortedValues.length - 1, Math.max(0, Math.ceil(fraction * sortedValues.length) - 1))] ?? 0;
18436
19750
  }
19751
+ function llmTagNameFromCounter(counterName) {
19752
+ return counterName.replace(/^STAT_/u, "").replace(/LLM$/u, "");
19753
+ }
19754
+ async function summarizeMemoryTagCounter(name, lines) {
19755
+ let valueIndex = -1;
19756
+ let finalBytes;
19757
+ let peakBytes = Number.NEGATIVE_INFINITY;
19758
+ let sawHeader = false;
19759
+ for await (const rawLine of lines) {
19760
+ const line = rawLine.trim();
19761
+ if (line.length === 0) continue;
19762
+ const values = parseCsvLine(line);
19763
+ if (!sawHeader) {
19764
+ sawHeader = true;
19765
+ valueIndex = values.findIndex((header) => header.toLowerCase() === "value");
19766
+ if (valueIndex < 0) return;
19767
+ continue;
19768
+ }
19769
+ const value = readNumber(values[valueIndex]);
19770
+ if (value === void 0) continue;
19771
+ finalBytes = value;
19772
+ peakBytes = Math.max(peakBytes, value);
19773
+ }
19774
+ return finalBytes === void 0 ? void 0 : {
19775
+ finalBytes,
19776
+ name,
19777
+ peakBytes
19778
+ };
19779
+ }
19780
+ function rankMemoryTags(tags, maxTags) {
19781
+ return {
19782
+ tags: [...tags].sort((left, right) => right.peakBytes - left.peakBytes).slice(0, maxTags),
19783
+ totalTagCount: tags.length,
19784
+ truncated: tags.length > maxTags
19785
+ };
19786
+ }
18437
19787
  //#endregion
18438
19788
  //#region src/tools/diagnostics.ts
18439
19789
  const ANALYZE_TRACE_DEFAULT_TIMEOUT_MS = 6e5;
18440
19790
  const ANALYZE_TRACE_DEFAULT_HITCH_THRESHOLD_MS = 33.4;
18441
19791
  const ANALYZE_TRACE_MAX_RESPONSE_BYTES = 32768;
19792
+ const LLM_COUNTER_FILE_PREFIX = "llm-";
18442
19793
  const analyzeTraceInputSchema = {
18443
19794
  engineVersion: engineVersionSchema,
18444
19795
  hitchThresholdMs: z.number().min(1).max(1e4).optional().describe(`Frame duration at or above which a frame counts as a hitch (default ${String(ANALYZE_TRACE_DEFAULT_HITCH_THRESHOLD_MS)}ms, about two frames at 60Hz).`),
18445
19796
  maxHitches: z.number().int().min(1).max(50).optional().describe(`Maximum worst-hitch entries to return (default ${String(10)}, max ${String(50)}).`),
18446
- maxScopes: z.number().int().min(1).max(100).optional().describe(`Maximum timing scopes to return per ranking (default ${String(20)}, max ${String(100)}).`),
19797
+ maxScopes: z.number().int().min(1).max(100).optional().describe(`Maximum timing scopes, GPU scopes and memory tags to return per ranking (default ${String(20)}, max ${String(100)}).`),
18447
19798
  projectPath: z.string().trim().min(1).optional().describe("Project whose EngineAssociation selects the analyzer engine. Omit when engineVersion is given."),
18448
19799
  timeoutMs: z.number().int().min(1e3).max(MAX_PROCESS_TIMEOUT_MS).optional().describe(`Hard timeout in milliseconds for the analyzer run (default ${String(ANALYZE_TRACE_DEFAULT_TIMEOUT_MS)}).`),
18449
19800
  tracePath: z.string().trim().min(1).describe("Path to the .utrace file produced by stop_insights_trace.")
@@ -18459,8 +19810,10 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
18459
19810
  engineVersion: engine.engineVersion,
18460
19811
  hitchThresholdMs,
18461
19812
  hitches: [],
19813
+ memoryTags: [],
18462
19814
  reason: `UnrealInsights was not found under ${path.join(engine.engineRoot, "Engine", "Binaries")}; the installed UE ${engine.engineVersion} does not ship the trace analyzer for this host.`,
18463
19815
  state: "unsupported",
19816
+ topGpuScopes: [],
18464
19817
  topScopesByExclusiveTime: [],
18465
19818
  topScopesByInclusiveTime: [],
18466
19819
  tracePath,
@@ -18472,7 +19825,11 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
18472
19825
  const timingEventsPath = path.join(exportDirectory, "timing-events.csv");
18473
19826
  const commandFilePath = path.join(exportDirectory, "export.rsp");
18474
19827
  try {
18475
- await context.writeFile(commandFilePath, [`TimingInsights.ExportTimerStatistics ${quoteConsoleArgument(timerStatisticsPath)}`, `TimingInsights.ExportTimingEvents ${quoteConsoleArgument(timingEventsPath)} -columns=ThreadName,TimerName,StartTime,Duration,Depth`].join("\n"));
19828
+ await context.writeFile(commandFilePath, [
19829
+ `TimingInsights.ExportTimerStatistics ${quoteConsoleArgument(timerStatisticsPath)}`,
19830
+ `TimingInsights.ExportTimingEvents ${quoteConsoleArgument(timingEventsPath)} -columns=ThreadName,TimerName,StartTime,Duration,Depth`,
19831
+ `TimingInsights.ExportCounterValues ${quoteConsoleArgument(path.join(exportDirectory, `${LLM_COUNTER_FILE_PREFIX}{counter}.csv`))} -counter=${LLM_TAG_COUNTER_PATTERN}`
19832
+ ].join("\n"));
18476
19833
  dependencies.logger.info({
18477
19834
  engineVersion: engine.engineVersion,
18478
19835
  tracePath
@@ -18492,16 +19849,24 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
18492
19849
  });
18493
19850
  if (run.timedOut) throw new EngineToolchainError(`Unreal Insights did not finish analyzing ${tracePath} within ${String(timeoutMs)}ms; raise timeoutMs or trim the trace.`);
18494
19851
  if (run.exitCode !== 0) throw new EngineToolchainError(`Unreal Insights exited with code ${String(run.exitCode)} while analyzing ${tracePath}: ${run.combinedOutput.slice(-1e3).trim()}`);
18495
- const scopeSummaries = summarizeTimerStatistics(await readCsvRows(timerStatisticsPath, context), input.maxScopes ?? 20);
18496
- const timingEvents = await summarizeTimingEventStream(await context.fileExists(timingEventsPath) ? context.readTextLines(timingEventsPath) : emptyTextLines(), {
19852
+ const maxScopes = input.maxScopes ?? 20;
19853
+ const scopeSummaries = summarizeTimerStatistics(await readCsvRows(timerStatisticsPath, context), maxScopes);
19854
+ const hasTimingEvents = await context.fileExists(timingEventsPath);
19855
+ const readTimingEventLines = () => hasTimingEvents ? context.readTextLines(timingEventsPath) : emptyTextLines();
19856
+ const timingEvents = await summarizeTimingEventStream(readTimingEventLines(), {
18497
19857
  hitchThresholdMs,
18498
- maxHitches: input.maxHitches ?? 10
19858
+ maxHitches: input.maxHitches ?? 10,
19859
+ maxScopes
18499
19860
  });
18500
19861
  const frames = timingEvents.frames;
18501
19862
  const threadTimes = timingEvents.threads;
19863
+ const hitches = await attributeHitchScopes(readTimingEventLines(), frames.hitches, 5);
19864
+ const memoryTags = await summarizeMemoryTags(exportDirectory, maxScopes, context);
18502
19865
  const truncated = [];
18503
19866
  if (scopeSummaries.truncated) truncated.push("topScopes");
18504
19867
  if (frames.hitchesTruncated) truncated.push("hitches");
19868
+ if (timingEvents.gpuScopes.truncated) truncated.push("topGpuScopes");
19869
+ if (memoryTags.truncated) truncated.push("memoryTags");
18505
19870
  const result = {
18506
19871
  analyzerPath,
18507
19872
  cpuTimeMs: threadTimes.cpuTimeMs,
@@ -18511,10 +19876,14 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
18511
19876
  frameCount: frames.frameCount,
18512
19877
  gpuTimeMs: threadTimes.gpuTimeMs,
18513
19878
  hitchThresholdMs,
18514
- hitches: frames.hitches,
19879
+ hitches,
19880
+ memoryTags: memoryTags.tags,
18515
19881
  state: "analyzed",
19882
+ topGpuScopes: timingEvents.gpuScopes.byExclusiveTime,
18516
19883
  topScopesByExclusiveTime: scopeSummaries.byExclusiveTime,
18517
19884
  topScopesByInclusiveTime: scopeSummaries.byInclusiveTime,
19885
+ totalGpuScopeCount: timingEvents.gpuScopes.totalScopeCount,
19886
+ totalMemoryTagCount: memoryTags.totalTagCount,
18518
19887
  totalScopeCount: scopeSummaries.totalScopeCount,
18519
19888
  tracePath,
18520
19889
  truncated
@@ -18560,22 +19929,42 @@ function boundAnalyzeTraceResult(result) {
18560
19929
  truncated: [...result.truncated]
18561
19930
  };
18562
19931
  while (JSON.stringify(bounded).length > ANALYZE_TRACE_MAX_RESPONSE_BYTES) {
18563
- const longestListLength = Math.max(bounded.topScopesByInclusiveTime.length, bounded.topScopesByExclusiveTime.length, bounded.hitches.length);
19932
+ const topScopesLength = Math.max(bounded.topScopesByInclusiveTime.length, bounded.topScopesByExclusiveTime.length);
19933
+ const longestListLength = Math.max(topScopesLength, bounded.hitches.length, bounded.topGpuScopes.length, bounded.memoryTags.length);
18564
19934
  if (longestListLength <= 1) {
18565
19935
  addTruncationReason(bounded, "responseBytesExceeded");
18566
19936
  return bounded;
18567
19937
  }
18568
- if (bounded.topScopesByInclusiveTime.length === longestListLength) {
19938
+ if (topScopesLength === longestListLength) {
18569
19939
  bounded.topScopesByInclusiveTime = bounded.topScopesByInclusiveTime.slice(0, longestListLength - 1);
18570
19940
  bounded.topScopesByExclusiveTime = bounded.topScopesByExclusiveTime.slice(0, longestListLength - 1);
18571
19941
  addTruncationReason(bounded, "topScopes");
18572
19942
  continue;
18573
19943
  }
19944
+ if (bounded.topGpuScopes.length === longestListLength) {
19945
+ bounded.topGpuScopes = bounded.topGpuScopes.slice(0, longestListLength - 1);
19946
+ addTruncationReason(bounded, "topGpuScopes");
19947
+ continue;
19948
+ }
19949
+ if (bounded.memoryTags.length === longestListLength) {
19950
+ bounded.memoryTags = bounded.memoryTags.slice(0, longestListLength - 1);
19951
+ addTruncationReason(bounded, "memoryTags");
19952
+ continue;
19953
+ }
18574
19954
  bounded.hitches = bounded.hitches.slice(0, bounded.hitches.length - 1);
18575
19955
  addTruncationReason(bounded, "hitches");
18576
19956
  }
18577
19957
  return bounded;
18578
19958
  }
19959
+ async function summarizeMemoryTags(exportDirectory, maxTags, context) {
19960
+ const counterFiles = (await context.listDirectory(exportDirectory)).filter((fileName) => fileName.startsWith(LLM_COUNTER_FILE_PREFIX) && fileName.endsWith(".csv"));
19961
+ const tags = [];
19962
+ for (const fileName of counterFiles) {
19963
+ const tag = await summarizeMemoryTagCounter(llmTagNameFromCounter(fileName.slice(4, -4)), context.readTextLines(path.join(exportDirectory, fileName)));
19964
+ if (tag !== void 0) tags.push(tag);
19965
+ }
19966
+ return rankMemoryTags(tags, maxTags);
19967
+ }
18579
19968
  function addTruncationReason(result, reason) {
18580
19969
  if (!result.truncated.includes(reason)) result.truncated.push(reason);
18581
19970
  }
@@ -18713,7 +20102,7 @@ function registerDiagnosticsTools(server, dependencies) {
18713
20102
  }, dependencies));
18714
20103
  });
18715
20104
  server.registerTool("analyze_trace", {
18716
- description: "Analyze a completed .utrace (the path stop_insights_trace returns) headlessly with the engine's Unreal Insights analyzer and return a bounded, readable summary: frame-time p50/p90/p99, the worst N hitches with timestamps, a CPU vs GPU time split, and top-N timing scopes by inclusive and exclusive time. Memory and LLM-tag totals are deliberately not reported — they need a separate analysis pass. Resolve the engine with engineVersion or projectPath. Every list is top-N and the response is byte-capped, with truncated naming what was shortened. Returns state 'unsupported' when the installed engine ships no Insights analyzer for this host.",
20105
+ description: "Analyze a completed .utrace (the path stop_insights_trace returns) headlessly with the engine's Unreal Insights analyzer and return a bounded, readable summary: frame-time p50/p90/p99, the worst N hitches with timestamps and each hitch's top 5 CPU scopes by exclusive time inside its window (with thread names, task-system idle waits left out), a CPU vs GPU time split, top-N timing scopes by inclusive and exclusive time, top-N GPU scopes by exclusive time, and LLM memory tags with their final and peak bytes. Memory tags are only present when the trace was captured with LLM enabled (-llm) and the stats channel. Resolve the engine with engineVersion or projectPath. Every list is top-N and the response is byte-capped, with truncated naming what was shortened. Returns state 'unsupported' when the installed engine ships no Insights analyzer for this host.",
18717
20106
  inputSchema: analyzeTraceInputSchema,
18718
20107
  title: "Analyze Trace"
18719
20108
  }, async (input) => {
@@ -19554,6 +20943,7 @@ const listGraphNodesInputSchema = {
19554
20943
  };
19555
20944
  const addGraphNodeInputSchema = {
19556
20945
  assetPath: bridgeAddGraphNodeRequestFieldsSchema.shape.assetPath.describe("Package name or object path of the asset owning the graph."),
20946
+ autoLayout: bridgeAddGraphNodeRequestFieldsSchema.shape.autoLayout.describe("Move the new node clear of the graph's existing nodes. Starts from position when given (sliding down until it overlaps nothing), otherwise from just right of the graph's current nodes. Only the new node moves; call layout_graph to rearrange the whole graph."),
19557
20947
  graphName: bridgeAddGraphNodeRequestFieldsSchema.shape.graphName.describe("Graph to add the node to."),
19558
20948
  kind: bridgeAddGraphNodeRequestFieldsSchema.shape.kind.describe("How the node is named: 'class' places a node type directly, 'function' places a call, 'variable_get' / 'variable_set' place a variable accessor."),
19559
20949
  memberName: bridgeAddGraphNodeRequestFieldsSchema.shape.memberName.describe("Function or variable name, required for every kind except 'class'."),
@@ -19595,6 +20985,11 @@ const setPinDefaultInputSchema = {
19595
20985
  projectId: creativeProjectIdSchema,
19596
20986
  value: bridgeSetPinDefaultRequestSchema.shape.value.describe("ExportText value, the same format get_actor_details emits and set_actor_property accepts.")
19597
20987
  };
20988
+ const layoutGraphInputSchema = {
20989
+ assetPath: bridgeLayoutGraphRequestSchema.shape.assetPath.describe("Package name or object path of the Blueprint owning the graph."),
20990
+ graphName: bridgeLayoutGraphRequestSchema.shape.graphName.describe("Graph to arrange, as get_blueprint_summary reports it (e.g. 'EventGraph')."),
20991
+ projectId: creativeProjectIdSchema
20992
+ };
19598
20993
  const listAvailableNodesInputSchema = {
19599
20994
  assetPath: bridgeListAvailableNodesRequestSchema.shape.assetPath.describe("Package name or object path of the asset owning the graph."),
19600
20995
  cursor: bridgeListAvailableNodesRequestSchema.shape.cursor.describe("nextCursor from a previous response, to fetch the following page."),
@@ -19612,6 +21007,7 @@ async function listGraphNodes(input, dependencies) {
19612
21007
  }
19613
21008
  async function addGraphNode(input, dependencies) {
19614
21009
  return await exchangeCreativeRequest(createBridgeAddGraphNodeRequest(input.assetPath, input.graphName, input.kind, {
21010
+ autoLayout: input.autoLayout,
19615
21011
  memberName: input.memberName,
19616
21012
  memberParentClass: input.memberParentClass,
19617
21013
  nodeClass: input.nodeClass,
@@ -19650,6 +21046,9 @@ async function listAvailableNodes(input, dependencies) {
19650
21046
  nameFilter: input.nameFilter
19651
21047
  }), sendBridgeListAvailableNodesRequest, BRIDGE_LIST_AVAILABLE_NODES_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
19652
21048
  }
21049
+ async function layoutGraph(input, dependencies) {
21050
+ return await exchangeCreativeRequest(createBridgeLayoutGraphRequest(input.assetPath, input.graphName), sendBridgeLayoutGraphRequest, BRIDGE_LAYOUT_GRAPH_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
21051
+ }
19653
21052
  function registerGraphTools(server, dependencies) {
19654
21053
  server.registerTool("list_graph_nodes", {
19655
21054
  description: "List the nodes in any UEdGraph — a Blueprint event graph or function, an Animation Blueprint AnimGraph, a Material graph, a Behavior Tree — with each node's GUID, class, title and pins. The GUID is what every other graph tool addresses a node by; it survives adding and removing other nodes, which an index does not. Results are paged by nextCursor.",
@@ -19666,12 +21065,13 @@ function registerGraphTools(server, dependencies) {
19666
21065
  }, dependencies));
19667
21066
  });
19668
21067
  server.registerTool("add_graph_node", {
19669
- description: "Add a node to a UEdGraph and return it with its pins, so it can be wired without a follow-up read. kind 'class' places a node type directly (K2Node_IfThenElse for a Branch); 'function' places a call to memberName on memberParentClass; 'variable_get' / 'variable_set' place a variable accessor. Use list_available_nodes to discover what this graph's schema accepts rather than guessing class names. pinDefaults configures the node in the same call. The Blueprint is marked structurally modified, so compile_blueprint afterwards picks the change up.",
21068
+ description: "Add a node to a UEdGraph and return it with its pins, so it can be wired without a follow-up read. kind 'class' places a node type directly (K2Node_IfThenElse for a Branch); 'function' places a call to memberName on memberParentClass; 'variable_get' / 'variable_set' place a variable accessor. Use list_available_nodes to discover what this graph's schema accepts rather than guessing class names. pinDefaults configures the node in the same call. autoLayout moves only the new node clear of the existing ones and reports where it landed in position; layout_graph rearranges the whole graph. The Blueprint is marked structurally modified, so compile_blueprint afterwards picks the change up.",
19670
21069
  inputSchema: addGraphNodeInputSchema,
19671
21070
  title: "Add Graph Node"
19672
- }, async ({ assetPath, graphName, kind, memberName, memberParentClass, nodeClass, pinDefaults, position, projectId }) => {
21071
+ }, async ({ assetPath, autoLayout, graphName, kind, memberName, memberParentClass, nodeClass, pinDefaults, position, projectId }) => {
19673
21072
  return toToolSuccess(await addGraphNode({
19674
21073
  assetPath,
21074
+ autoLayout,
19675
21075
  graphName,
19676
21076
  kind,
19677
21077
  memberName,
@@ -19752,6 +21152,17 @@ function registerGraphTools(server, dependencies) {
19752
21152
  projectId
19753
21153
  }, dependencies));
19754
21154
  });
21155
+ server.registerTool("layout_graph", {
21156
+ description: "Auto-arrange a Blueprint graph so no two nodes overlap: exec flow is layered left to right from each event, branches fan out downward, and pure (data) nodes sit in the column left of the node that consumes them. Comment boxes stay where they are. Node sizes are estimated from title and pin count, since an editor without the graph open has no rendered widget to measure. The whole rearrangement is one undo step. Use it after building a graph with add_graph_node; Material graphs are not supported.",
21157
+ inputSchema: layoutGraphInputSchema,
21158
+ title: "Layout Graph"
21159
+ }, async ({ assetPath, graphName, projectId }) => {
21160
+ return toToolSuccess(await layoutGraph({
21161
+ assetPath,
21162
+ graphName,
21163
+ projectId
21164
+ }, dependencies));
21165
+ });
19755
21166
  }
19756
21167
  const graphToolDomain = {
19757
21168
  domain: "graph",
@@ -19763,7 +21174,8 @@ const graphToolDomain = {
19763
21174
  "connect_pins",
19764
21175
  "disconnect_pins",
19765
21176
  "set_pin_default",
19766
- "list_available_nodes"
21177
+ "list_available_nodes",
21178
+ "layout_graph"
19767
21179
  ]
19768
21180
  };
19769
21181
  //#endregion
@@ -22275,6 +23687,95 @@ const logsToolDomain = {
22275
23687
  ]
22276
23688
  };
22277
23689
  //#endregion
23690
+ //#region src/tools/mass.ts
23691
+ const MASS_TRAIT_HINT = "Traits are named by class: 'MassMovementTrait' or 'MassSimpleMovementTrait' (movement), 'MassLODCollectorTrait' or 'MassSimulationLODTrait' (LOD), 'MassVisualizationTrait' or 'MassMovableVisualizationTrait' (representation), 'MassStateTreeTrait' (StateTree behaviour, needs the MassAI plugin), or a '/Script/Module.Class' path.";
23692
+ const createMassEntityConfigInputSchema = {
23693
+ assetName: bridgeCreateMassEntityConfigRequestSchema.shape.assetName.describe("Name of the new MassEntityConfig asset, e.g. 'DA_CrowdAgent'."),
23694
+ packagePath: bridgeCreateMassEntityConfigRequestSchema.shape.packagePath.describe("Content folder to create the config in, e.g. /Game/Mass."),
23695
+ parentConfigPath: bridgeCreateMassEntityConfigRequestSchema.shape.parentConfigPath.describe("Optional MassEntityConfig to inherit traits from; this config overrides any trait of the same class."),
23696
+ projectId: creativeProjectIdSchema
23697
+ };
23698
+ const editMassEntityConfigInputSchema = {
23699
+ assetPath: bridgeEditMassEntityConfigRequestSchema.shape.assetPath.describe("MassEntityConfig asset to edit."),
23700
+ edits: bridgeEditMassEntityConfigRequestSchema.shape.edits.describe(`Trait edits applied in order. 'add' adds the trait (or configures the existing one of that class) and may carry properties; 'set' writes properties on a trait the config owns; 'remove' drops it. properties are { propertyPath, value } pairs in exported-text form, e.g. { propertyPath: 'Movement.MaxSpeed', value: '300' }. ${MASS_TRAIT_HINT}`),
23701
+ projectId: creativeProjectIdSchema
23702
+ };
23703
+ const getMassEntityConfigInputSchema = {
23704
+ assetPath: bridgeGetMassEntityConfigRequestSchema.shape.assetPath.describe("MassEntityConfig asset to read."),
23705
+ projectId: creativeProjectIdSchema
23706
+ };
23707
+ const validateMassEntityConfigInputSchema = {
23708
+ assetPath: bridgeValidateMassEntityConfigRequestSchema.shape.assetPath.describe("MassEntityConfig asset to validate."),
23709
+ projectId: creativeProjectIdSchema
23710
+ };
23711
+ async function createMassEntityConfig(input, dependencies) {
23712
+ return await exchangeCreativeRequest(createBridgeCreateMassEntityConfigRequest(input.assetName, input.packagePath, { parentConfigPath: input.parentConfigPath }), sendBridgeCreateMassEntityConfigRequest, BRIDGE_CREATE_MASS_ENTITY_CONFIG_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
23713
+ }
23714
+ async function editMassEntityConfig(input, dependencies) {
23715
+ return await exchangeCreativeRequest(createBridgeEditMassEntityConfigRequest(input.assetPath, input.edits), sendBridgeEditMassEntityConfigRequest, BRIDGE_EDIT_MASS_ENTITY_CONFIG_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
23716
+ }
23717
+ async function getMassEntityConfig(input, dependencies) {
23718
+ return await exchangeCreativeRequest(createBridgeGetMassEntityConfigRequest(input.assetPath), sendBridgeGetMassEntityConfigRequest, BRIDGE_GET_MASS_ENTITY_CONFIG_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
23719
+ }
23720
+ async function validateMassEntityConfig(input, dependencies) {
23721
+ return await exchangeCreativeRequest(createBridgeValidateMassEntityConfigRequest(input.assetPath), sendBridgeValidateMassEntityConfigRequest, BRIDGE_VALIDATE_MASS_ENTITY_CONFIG_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
23722
+ }
23723
+ function registerMassTools(server, dependencies) {
23724
+ server.registerTool("create_mass_entity_config", {
23725
+ description: "Create a MassEntityConfig data asset — the trait list a Mass crowd agent is spawned from — optionally inheriting from a parent config. Add traits with edit_mass_entity_config. Returns state 'unsupported' with a reason when the Mass plugins are not loaded.",
23726
+ inputSchema: createMassEntityConfigInputSchema,
23727
+ title: "Create Mass Entity Config"
23728
+ }, async ({ assetName, packagePath, parentConfigPath, projectId }) => {
23729
+ return toToolSuccess(await createMassEntityConfig({
23730
+ assetName,
23731
+ packagePath,
23732
+ parentConfigPath,
23733
+ projectId
23734
+ }, dependencies));
23735
+ });
23736
+ server.registerTool("edit_mass_entity_config", {
23737
+ description: "Add, remove and configure the traits of a MassEntityConfig (movement, LOD, representation, StateTree and any other Mass trait). Each edit reports its own outcome, and traits lists the config's own trait classes afterwards. The package is left dirty; save it with save_dirty_packages. Run validate_mass_entity_config to check the result.",
23738
+ inputSchema: editMassEntityConfigInputSchema,
23739
+ title: "Edit Mass Entity Config"
23740
+ }, async ({ assetPath, edits, projectId }) => {
23741
+ return toToolSuccess(await editMassEntityConfig({
23742
+ assetPath,
23743
+ edits,
23744
+ projectId
23745
+ }, dependencies));
23746
+ });
23747
+ server.registerTool("get_mass_entity_config", {
23748
+ description: "Read a MassEntityConfig back: its parent config and each of its own traits with the trait's editable properties as exported text, which edit_mass_entity_config accepts unchanged.",
23749
+ inputSchema: getMassEntityConfigInputSchema,
23750
+ title: "Get Mass Entity Config"
23751
+ }, async ({ assetPath, projectId }) => {
23752
+ return toToolSuccess(await getMassEntityConfig({
23753
+ assetPath,
23754
+ projectId
23755
+ }, dependencies));
23756
+ });
23757
+ server.registerTool("validate_mass_entity_config", {
23758
+ description: "Build the config's entity template the way the asset editor's Validate button does and report whether it is valid, with the engine's own error and warning lines verbatim (for example a trait missing a fragment another trait must provide).",
23759
+ inputSchema: validateMassEntityConfigInputSchema,
23760
+ title: "Validate Mass Entity Config"
23761
+ }, async ({ assetPath, projectId }) => {
23762
+ return toToolSuccess(await validateMassEntityConfig({
23763
+ assetPath,
23764
+ projectId
23765
+ }, dependencies));
23766
+ });
23767
+ }
23768
+ const massToolDomain = {
23769
+ domain: "mass",
23770
+ register: registerMassTools,
23771
+ toolNames: [
23772
+ "create_mass_entity_config",
23773
+ "edit_mass_entity_config",
23774
+ "get_mass_entity_config",
23775
+ "validate_mass_entity_config"
23776
+ ]
23777
+ };
23778
+ //#endregion
22278
23779
  //#region src/tools/material.ts
22279
23780
  const createMaterialInstanceInputSchema = {
22280
23781
  assetName: bridgeCreateMaterialInstanceRequestSchema.shape.assetName.describe("Name of the new instance, e.g. 'MI_Rock_Mossy'."),
@@ -22476,6 +23977,307 @@ const meshToolDomain = {
22476
23977
  ]
22477
23978
  };
22478
23979
  //#endregion
23980
+ //#region src/tools/navigation.ts
23981
+ const setNavmeshSettingsInputSchema = {
23982
+ agentHeight: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.agentHeight.describe("Height of the tallest agent that will path on this navmesh, in cm."),
23983
+ agentMaxSlope: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.agentMaxSlope.describe("Steepest ground an agent can walk, in degrees from horizontal (0-89)."),
23984
+ agentMaxStepHeight: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.agentMaxStepHeight.describe("Tallest step an agent can climb, in cm. Written into the resolution named by resolution."),
23985
+ agentRadius: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.agentRadius.describe("Radius of the smallest agent that will path on this navmesh, in cm. Widening it pulls the navmesh further from every wall."),
23986
+ cellHeight: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.cellHeight.describe("Vertical voxel size, in cm. Written into the resolution named by resolution."),
23987
+ cellSize: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.cellSize.describe("Horizontal voxel size, in cm. Smaller is more precise and much slower to build."),
23988
+ mergeRegionSize: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.mergeRegionSize.describe("Regions up to this size are merged into a bigger neighbour (watershed partitioning only)."),
23989
+ minRegionArea: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.minRegionArea.describe("Islands smaller than this are discarded instead of becoming unreachable navmesh."),
23990
+ navMeshActorPath: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.navMeshActorPath.describe("Actor path of the RecastNavMesh to write. Omit to use the level's main navigation data."),
23991
+ projectId: creativeProjectIdSchema,
23992
+ resolution: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.resolution.describe("Which resolution's voxel parameters cellSize, cellHeight and agentMaxStepHeight are written into. Defaults to 'default'."),
23993
+ runtimeGeneration: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.runtimeGeneration.describe("'static' bakes once, 'dynamic_modifiers_only' rebuilds for nav modifiers, 'dynamic' rebuilds for geometry changes too."),
23994
+ tileSizeUU: bridgeSetNavmeshSettingsRequestFieldsSchema.shape.tileSizeUU.describe("Side of one navmesh tile, in cm. Smaller tiles rebuild faster but cost more memory.")
23995
+ };
23996
+ const setNavAgentsInputSchema = {
23997
+ agents: bridgeSetNavAgentsRequestSchema.shape.agents.describe(`Supported agent types, each { name, radius, height, maxStepHeight?, navDataClass? } (max ${String(16)}). This replaces the project's whole list.`),
23998
+ projectId: creativeProjectIdSchema
23999
+ };
24000
+ const setCrowdSettingsInputSchema = {
24001
+ crowd: bridgeSetCrowdSettingsRequestFieldsSchema.shape.crowd.describe("Detour crowd manager settings: maxAgents, maxAgentRadius, maxAvoidedAgents, maxAvoidedWalls, navmeshCheckInterval, pathOptimizationInterval, separationDirClamp, pathOffsetRadiusMultiplier, resolveCollisions."),
24002
+ projectId: creativeProjectIdSchema,
24003
+ rvo: bridgeSetCrowdSettingsRequestFieldsSchema.shape.rvo.describe("RVO avoidance manager settings: defaultTimeToLive, lockTimeAfterAvoid, lockTimeAfterClean, deltaTimeToPredict, artificialRadiusExpansion, heightCheckMargin.")
24004
+ };
24005
+ const createNavAreaInputSchema = {
24006
+ assetName: bridgeCreateNavAreaRequestSchema.shape.assetName.describe("Name of the new nav area, e.g. 'NA_Mud'."),
24007
+ defaultCost: bridgeCreateNavAreaRequestSchema.shape.defaultCost.describe("Travel cost multiplier for distance through this area. 1 is neutral; higher makes pathfinding avoid it."),
24008
+ drawColor: bridgeCreateNavAreaRequestSchema.shape.drawColor.describe("Colour this area is drawn in the navigation view, as { r, g, b, a? } 0-255."),
24009
+ fixedAreaEnteringCost: bridgeCreateNavAreaRequestSchema.shape.fixedAreaEnteringCost.describe("Flat cost paid once on entering the area, independent of how far the path runs through it."),
24010
+ packagePath: bridgeCreateNavAreaRequestSchema.shape.packagePath.describe("Content folder to create the nav area Blueprint in."),
24011
+ parentClass: bridgeCreateNavAreaRequestSchema.shape.parentClass.describe("Nav area class to derive from: 'NavArea' (default), 'NavArea_Null', 'NavArea_Obstacle', 'NavArea_LowHeight', or the class path of another one."),
24012
+ projectId: creativeProjectIdSchema
24013
+ };
24014
+ const addNavModifierVolumeInputSchema = {
24015
+ actorLabel: bridgeAddNavModifierVolumeRequestSchema.shape.actorLabel.describe("Display label for the placed volume."),
24016
+ areaClass: bridgeAddNavModifierVolumeRequestSchema.shape.areaClass.describe("Nav area to apply inside the volume — 'NavArea_Null' to cut the navmesh away, 'NavArea_Obstacle' to make it expensive, or a class path from create_nav_area."),
24017
+ areaClassToReplace: bridgeAddNavModifierVolumeRequestSchema.shape.areaClassToReplace.describe("When given, only surfaces already marked with this area are replaced by areaClass instead of everything inside the volume."),
24018
+ extent: bridgeAddNavModifierVolumeRequestSchema.shape.extent.describe("Box half-extent of the volume in cm. Every axis must be positive."),
24019
+ folderPath: bridgeAddNavModifierVolumeRequestSchema.shape.folderPath.describe("World Outliner folder to place the volume in."),
24020
+ location: bridgeAddNavModifierVolumeRequestSchema.shape.location.describe("World location of the volume centre."),
24021
+ projectId: creativeProjectIdSchema,
24022
+ rotation: bridgeAddNavModifierVolumeRequestSchema.shape.rotation.describe("World rotation of the volume.")
24023
+ };
24024
+ const addNavLinkInputSchema = {
24025
+ actorLabel: bridgeAddNavLinkRequestSchema.shape.actorLabel.describe("Display label for the placed link actor."),
24026
+ folderPath: bridgeAddNavLinkRequestSchema.shape.folderPath.describe("World Outliner folder to place the link actor in."),
24027
+ links: bridgeAddNavLinkRequestSchema.shape.links.describe(`Point links carried by this actor (max ${String(16)}), each { left, right, direction?, snapRadius?, snapHeight?, leftProjectHeight?, maxFallDownLength?, areaClass?, description? }. left and right are offsets from the actor, not world positions.`),
24028
+ location: bridgeAddNavLinkRequestSchema.shape.location.describe("World location of the link actor."),
24029
+ projectId: creativeProjectIdSchema,
24030
+ rotation: bridgeAddNavLinkRequestSchema.shape.rotation.describe("World rotation of the link actor."),
24031
+ smartLinkEnabled: bridgeAddNavLinkRequestSchema.shape.smartLinkEnabled.describe("Mark the smart link component on this actor navigation-relevant, so it can be toggled at runtime without a rebuild.")
24032
+ };
24033
+ const findPathInputSchema = {
24034
+ allowPartial: bridgeFindPathRequestFieldsSchema.shape.allowPartial.describe("Accept a path that stops short of the goal. Defaults to true, so a blocked destination reports partial rather than nothing."),
24035
+ end: bridgeFindPathRequestFieldsSchema.shape.end.describe("World location to path to. Give this or endActorPath."),
24036
+ endActorPath: bridgeFindPathRequestFieldsSchema.shape.endActorPath.describe("Actor whose location is the goal. Give this or end."),
24037
+ maxPathPoints: bridgeFindPathRequestFieldsSchema.shape.maxPathPoints.describe(`Maximum path points to return (1-${String(256)}). pathPointCount stays the full count and truncated says whether the list was cut.`),
24038
+ navMeshActorPath: bridgeFindPathRequestFieldsSchema.shape.navMeshActorPath.describe("Actor path of the RecastNavMesh to query. Omit to use the level's main navigation data."),
24039
+ projectId: creativeProjectIdSchema,
24040
+ start: bridgeFindPathRequestFieldsSchema.shape.start.describe("World location to path from. Give this or startActorPath."),
24041
+ startActorPath: bridgeFindPathRequestFieldsSchema.shape.startActorPath.describe("Actor whose location is the start. Give this or start.")
24042
+ };
24043
+ const testReachabilityInputSchema = {
24044
+ allowPartial: bridgeTestReachabilityRequestFieldsSchema.shape.allowPartial.describe("Report how far an unreachable pair got, as pathLength on a partial path. Defaults to false. A partial path is reported unreachable either way."),
24045
+ navMeshActorPath: bridgeTestReachabilityRequestFieldsSchema.shape.navMeshActorPath.describe("Actor path of the RecastNavMesh to query. Omit to use the level's main navigation data."),
24046
+ pairs: bridgeTestReachabilityRequestFieldsSchema.shape.pairs.describe(`Start/end pairs to test (max ${String(64)}), each naming exactly one of start/startActorPath and one of end/endActorPath.`),
24047
+ projectId: creativeProjectIdSchema
24048
+ };
24049
+ const diagnoseNavmeshInputSchema = {
24050
+ includePlayerStarts: bridgeDiagnoseNavmeshRequestSchema.shape.includePlayerStarts.describe("Check every PlayerStart in the level as a spawn point. Defaults to true."),
24051
+ maxIslands: bridgeDiagnoseNavmeshRequestSchema.shape.maxIslands.describe(`Most islands to list, largest area first (1-${String(64)}). islandCount stays the full count.`),
24052
+ navMeshActorPath: bridgeDiagnoseNavmeshRequestSchema.shape.navMeshActorPath.describe("Actor path of the RecastNavMesh to inspect. Omit to use the level's main navigation data."),
24053
+ projectId: creativeProjectIdSchema,
24054
+ spawnActorPaths: bridgeDiagnoseNavmeshRequestSchema.shape.spawnActorPaths.describe(`Extra spawn actors to check alongside the player starts, such as AI spawners (max ${String(64)}).`)
24055
+ };
24056
+ async function setNavmeshSettings(input, dependencies) {
24057
+ return await exchangeCreativeRequest(createBridgeSetNavmeshSettingsRequest({
24058
+ agentHeight: input.agentHeight,
24059
+ agentMaxSlope: input.agentMaxSlope,
24060
+ agentMaxStepHeight: input.agentMaxStepHeight,
24061
+ agentRadius: input.agentRadius,
24062
+ cellHeight: input.cellHeight,
24063
+ cellSize: input.cellSize,
24064
+ mergeRegionSize: input.mergeRegionSize,
24065
+ minRegionArea: input.minRegionArea,
24066
+ navMeshActorPath: input.navMeshActorPath,
24067
+ resolution: input.resolution,
24068
+ runtimeGeneration: input.runtimeGeneration,
24069
+ tileSizeUU: input.tileSizeUU
24070
+ }), sendBridgeSetNavmeshSettingsRequest, BRIDGE_SET_NAVMESH_SETTINGS_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
24071
+ }
24072
+ async function setNavAgents(input, dependencies) {
24073
+ return await exchangeCreativeRequest(createBridgeSetNavAgentsRequest(input.agents), sendBridgeSetNavAgentsRequest, BRIDGE_SET_NAV_AGENTS_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
24074
+ }
24075
+ async function setCrowdSettings(input, dependencies) {
24076
+ return await exchangeCreativeRequest(createBridgeSetCrowdSettingsRequest({
24077
+ crowd: input.crowd,
24078
+ rvo: input.rvo
24079
+ }), sendBridgeSetCrowdSettingsRequest, BRIDGE_SET_CROWD_SETTINGS_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
24080
+ }
24081
+ async function createNavArea(input, dependencies) {
24082
+ return await exchangeCreativeRequest(createBridgeCreateNavAreaRequest(input.assetName, input.packagePath, {
24083
+ defaultCost: input.defaultCost,
24084
+ drawColor: input.drawColor,
24085
+ fixedAreaEnteringCost: input.fixedAreaEnteringCost,
24086
+ parentClass: input.parentClass
24087
+ }), sendBridgeCreateNavAreaRequest, BRIDGE_CREATE_NAV_AREA_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
24088
+ }
24089
+ async function addNavModifierVolume(input, dependencies) {
24090
+ return await exchangeCreativeRequest(createBridgeAddNavModifierVolumeRequest(input.areaClass, {
24091
+ actorLabel: input.actorLabel,
24092
+ areaClassToReplace: input.areaClassToReplace,
24093
+ extent: input.extent,
24094
+ folderPath: input.folderPath,
24095
+ location: input.location,
24096
+ rotation: input.rotation
24097
+ }), sendBridgeAddNavModifierVolumeRequest, BRIDGE_ADD_NAV_MODIFIER_VOLUME_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
24098
+ }
24099
+ async function addNavLink(input, dependencies) {
24100
+ return await exchangeCreativeRequest(createBridgeAddNavLinkRequest(input.links, {
24101
+ actorLabel: input.actorLabel,
24102
+ folderPath: input.folderPath,
24103
+ location: input.location,
24104
+ rotation: input.rotation,
24105
+ smartLinkEnabled: input.smartLinkEnabled
24106
+ }), sendBridgeAddNavLinkRequest, BRIDGE_ADD_NAV_LINK_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
24107
+ }
24108
+ async function findPath(input, dependencies) {
24109
+ return await exchangeCreativeRequest(createBridgeFindPathRequest({
24110
+ end: input.end,
24111
+ endActorPath: input.endActorPath,
24112
+ start: input.start,
24113
+ startActorPath: input.startActorPath
24114
+ }, {
24115
+ allowPartial: input.allowPartial,
24116
+ maxPathPoints: input.maxPathPoints,
24117
+ navMeshActorPath: input.navMeshActorPath
24118
+ }), sendBridgeFindPathRequest, BRIDGE_FIND_PATH_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
24119
+ }
24120
+ async function testReachability(input, dependencies) {
24121
+ return await exchangeCreativeRequest(createBridgeTestReachabilityRequest(input.pairs, {
24122
+ allowPartial: input.allowPartial,
24123
+ navMeshActorPath: input.navMeshActorPath
24124
+ }), sendBridgeTestReachabilityRequest, BRIDGE_TEST_REACHABILITY_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
24125
+ }
24126
+ async function diagnoseNavmesh(input, dependencies) {
24127
+ return await exchangeCreativeRequest(createBridgeDiagnoseNavmeshRequest({
24128
+ includePlayerStarts: input.includePlayerStarts,
24129
+ maxIslands: input.maxIslands,
24130
+ navMeshActorPath: input.navMeshActorPath,
24131
+ spawnActorPaths: input.spawnActorPaths
24132
+ }), sendBridgeDiagnoseNavmeshRequest, BRIDGE_DIAGNOSE_NAVMESH_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
24133
+ }
24134
+ function registerNavigationTools(server, dependencies) {
24135
+ server.registerTool("set_navmesh_settings", {
24136
+ description: "Write the level's navmesh generation settings — agent radius and height, max slope and step height, voxel cell size, tile size and runtime generation mode. The values only reach the navmesh on the next build, so follow this with build_navigation. Returns every setting as it stands after the write, so a clamped value is visible.",
24137
+ inputSchema: setNavmeshSettingsInputSchema,
24138
+ title: "Set Navmesh Settings"
24139
+ }, async ({ agentHeight, agentMaxSlope, agentMaxStepHeight, agentRadius, cellHeight, cellSize, mergeRegionSize, minRegionArea, navMeshActorPath, projectId, resolution, runtimeGeneration, tileSizeUU }) => {
24140
+ return toToolSuccess(await setNavmeshSettings({
24141
+ agentHeight,
24142
+ agentMaxSlope,
24143
+ agentMaxStepHeight,
24144
+ agentRadius,
24145
+ cellHeight,
24146
+ cellSize,
24147
+ mergeRegionSize,
24148
+ minRegionArea,
24149
+ navMeshActorPath,
24150
+ projectId,
24151
+ resolution,
24152
+ runtimeGeneration,
24153
+ tileSizeUU
24154
+ }, dependencies));
24155
+ });
24156
+ server.registerTool("set_nav_agents", {
24157
+ description: "Replace the project's list of supported navigation agents, each with its own radius, height and step height. One navmesh is generated per agent type, so this is how a level gets separate navigation for, say, a human and a vehicle. Written to DefaultEngine.ini and read once at startup, so it reports restartRequired.",
24158
+ inputSchema: setNavAgentsInputSchema,
24159
+ title: "Set Nav Agents"
24160
+ }, async ({ agents, projectId }) => {
24161
+ return toToolSuccess(await setNavAgents({
24162
+ agents,
24163
+ projectId
24164
+ }, dependencies));
24165
+ });
24166
+ server.registerTool("set_crowd_settings", {
24167
+ description: "Write the project-wide Detour crowd manager and RVO avoidance settings that decide how AI agents steer around each other. Both are config defaults read at startup, so the response reports restartRequired rather than pretending a running crowd picked them up.",
24168
+ inputSchema: setCrowdSettingsInputSchema,
24169
+ title: "Set Crowd Settings"
24170
+ }, async ({ crowd, projectId, rvo }) => {
24171
+ return toToolSuccess(await setCrowdSettings({
24172
+ crowd,
24173
+ projectId,
24174
+ rvo
24175
+ }, dependencies));
24176
+ });
24177
+ server.registerTool("create_nav_area", {
24178
+ description: "Create a nav area Blueprint with its own travel cost, entering cost and debug colour. Returns generatedClassPath, which is what add_nav_modifier_volume and add_nav_link take to reference the area.",
24179
+ inputSchema: createNavAreaInputSchema,
24180
+ title: "Create Nav Area"
24181
+ }, async ({ assetName, defaultCost, drawColor, fixedAreaEnteringCost, packagePath, parentClass, projectId }) => {
24182
+ return toToolSuccess(await createNavArea({
24183
+ assetName,
24184
+ defaultCost,
24185
+ drawColor,
24186
+ fixedAreaEnteringCost,
24187
+ packagePath,
24188
+ parentClass,
24189
+ projectId
24190
+ }, dependencies));
24191
+ });
24192
+ server.registerTool("add_nav_modifier_volume", {
24193
+ description: "Place a nav modifier volume that applies a nav area to whatever navmesh falls inside it — NavArea_Null to carve a hole an agent will never path through, or a custom area to make the ground expensive rather than impassable. Takes effect on the next build_navigation.",
24194
+ inputSchema: addNavModifierVolumeInputSchema,
24195
+ title: "Add Nav Modifier Volume"
24196
+ }, async ({ actorLabel, areaClass, areaClassToReplace, extent, folderPath, location, projectId, rotation }) => {
24197
+ return toToolSuccess(await addNavModifierVolume({
24198
+ actorLabel,
24199
+ areaClass,
24200
+ areaClassToReplace,
24201
+ extent,
24202
+ folderPath,
24203
+ location,
24204
+ projectId,
24205
+ rotation
24206
+ }, dependencies));
24207
+ });
24208
+ server.registerTool("add_nav_link", {
24209
+ description: "Place a nav link proxy carrying one or more point links, which is what lets an agent jump or drop between navmesh islands that do not touch. Each link names its two ends as offsets from the actor plus a direction; the response reports them in world space. Takes effect on the next build_navigation.",
24210
+ inputSchema: addNavLinkInputSchema,
24211
+ title: "Add Nav Link"
24212
+ }, async ({ actorLabel, folderPath, links, location, projectId, rotation, smartLinkEnabled }) => {
24213
+ return toToolSuccess(await addNavLink({
24214
+ actorLabel,
24215
+ folderPath,
24216
+ links,
24217
+ location,
24218
+ projectId,
24219
+ rotation,
24220
+ smartLinkEnabled
24221
+ }, dependencies));
24222
+ });
24223
+ server.registerTool("find_path", {
24224
+ description: "Run a synchronous navmesh path query in the editor world between two points or actors, returning the path points, its length and cost, and whether it reached the goal. A destination nothing can reach comes back with reachable false and a partial path rather than an error, so this is the way to prove a level is traversable before shipping it.",
24225
+ inputSchema: findPathInputSchema,
24226
+ title: "Find Path"
24227
+ }, async ({ allowPartial, end, endActorPath, maxPathPoints, navMeshActorPath, projectId, start, startActorPath }) => {
24228
+ return toToolSuccess(await findPath({
24229
+ allowPartial,
24230
+ end,
24231
+ endActorPath,
24232
+ maxPathPoints,
24233
+ navMeshActorPath,
24234
+ projectId,
24235
+ start,
24236
+ startActorPath
24237
+ }, dependencies));
24238
+ });
24239
+ server.registerTool("test_reachability", {
24240
+ description: "Answer reachable / not reachable for a batch of start-end pairs in one call, without returning any path geometry. Use it to sweep spawn points against objectives; use find_path when the route itself matters.",
24241
+ inputSchema: testReachabilityInputSchema,
24242
+ title: "Test Reachability"
24243
+ }, async ({ allowPartial, navMeshActorPath, pairs, projectId }) => {
24244
+ return toToolSuccess(await testReachability({
24245
+ allowPartial,
24246
+ navMeshActorPath,
24247
+ pairs,
24248
+ projectId
24249
+ }, dependencies));
24250
+ });
24251
+ server.registerTool("diagnose_navmesh", {
24252
+ description: "Audit the editor level's navmesh without changing it: missing nav bounds, an empty navmesh, disconnected islands (poly count, area and bounds, largest area first), and player starts or named AI spawn actors that sit off the navmesh or cannot path to the first spawn point. Each finding is listed in issues with a code; healthy is true when there are none.",
24253
+ inputSchema: diagnoseNavmeshInputSchema,
24254
+ title: "Diagnose Navmesh"
24255
+ }, async ({ includePlayerStarts, maxIslands, navMeshActorPath, projectId, spawnActorPaths }) => {
24256
+ return toToolSuccess(await diagnoseNavmesh({
24257
+ includePlayerStarts,
24258
+ maxIslands,
24259
+ navMeshActorPath,
24260
+ projectId,
24261
+ spawnActorPaths
24262
+ }, dependencies));
24263
+ });
24264
+ }
24265
+ const navigationToolDomain = {
24266
+ domain: "navigation",
24267
+ register: registerNavigationTools,
24268
+ toolNames: [
24269
+ "set_navmesh_settings",
24270
+ "set_nav_agents",
24271
+ "set_crowd_settings",
24272
+ "create_nav_area",
24273
+ "add_nav_modifier_volume",
24274
+ "add_nav_link",
24275
+ "find_path",
24276
+ "test_reachability",
24277
+ "diagnose_navmesh"
24278
+ ]
24279
+ };
24280
+ //#endregion
22479
24281
  //#region src/tools/pcg.ts
22480
24282
  const createPcgGraphInputSchema = {
22481
24283
  assetName: bridgeCreatePcgGraphRequestFieldsSchema.shape.assetName.describe("Name of the new PCG graph, e.g. 'PCG_Forest'."),
@@ -23389,6 +25191,90 @@ const sequencerToolDomain = {
23389
25191
  ]
23390
25192
  };
23391
25193
  //#endregion
25194
+ //#region src/tools/smartObjects.ts
25195
+ const createSmartObjectDefinitionInputSchema = {
25196
+ activityTags: bridgeCreateSmartObjectDefinitionRequestSchema.shape.activityTags.describe("Gameplay tags describing what the whole object offers, e.g. 'Activity.Sit'. Every tag must already be registered."),
25197
+ assetName: bridgeCreateSmartObjectDefinitionRequestSchema.shape.assetName.describe("Name of the new Smart Object definition, e.g. 'SOD_Bench'."),
25198
+ defaultBehaviorDefinitions: bridgeCreateSmartObjectDefinitionRequestSchema.shape.defaultBehaviorDefinitions.describe("Behavior definitions every slot without its own falls back to, each { behaviorClass, params? }. behaviorClass names a concrete USmartObjectBehaviorDefinition subclass, e.g. '/Script/GameplayBehaviorSmartObjectsModule.GameplayBehaviorSmartObjectBehaviorDefinition'. A slot with no behavior and no default leaves the definition invalid, and an invalid definition never registers."),
25199
+ packagePath: bridgeCreateSmartObjectDefinitionRequestSchema.shape.packagePath.describe("Content folder to create the definition in."),
25200
+ projectId: creativeProjectIdSchema,
25201
+ slots: bridgeCreateSmartObjectDefinitionRequestSchema.shape.slots.describe("Slots users claim, each { name?, offset?: {x,y,z}, rotation?: {pitch,yaw,roll}, enabled?, activityTags?, behaviorDefinitions? }. Offset and rotation are relative to the owning actor.")
25202
+ };
25203
+ const getSmartObjectDefinitionInputSchema = {
25204
+ assetPath: bridgeGetSmartObjectDefinitionRequestSchema.shape.assetPath.describe("Object path of the Smart Object definition to read."),
25205
+ projectId: creativeProjectIdSchema
25206
+ };
25207
+ const addSmartObjectComponentInputSchema = {
25208
+ actorPath: bridgeAddSmartObjectComponentRequestFieldsSchema.shape.actorPath.describe("Placed actor in the editor level to add the component to. Give this or blueprintPath, not both."),
25209
+ blueprintPath: bridgeAddSmartObjectComponentRequestFieldsSchema.shape.blueprintPath.describe("Actor Blueprint to add the component to; the Blueprint is recompiled. Give this or actorPath, not both."),
25210
+ componentName: bridgeAddSmartObjectComponentRequestFieldsSchema.shape.componentName.describe("Name of the component. Omitted reuses the existing Smart Object component, or names a new one SmartObject."),
25211
+ definitionPath: bridgeAddSmartObjectComponentRequestFieldsSchema.shape.definitionPath.describe("Smart Object definition the component points at."),
25212
+ projectId: creativeProjectIdSchema
25213
+ };
25214
+ async function createSmartObjectDefinition(input, dependencies) {
25215
+ return await exchangeCreativeRequest(createBridgeCreateSmartObjectDefinitionRequest(input.assetName, input.packagePath, input.slots, {
25216
+ activityTags: input.activityTags,
25217
+ defaultBehaviorDefinitions: input.defaultBehaviorDefinitions
25218
+ }), sendBridgeCreateSmartObjectDefinitionRequest, BRIDGE_CREATE_SMART_OBJECT_DEFINITION_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
25219
+ }
25220
+ async function getSmartObjectDefinition(input, dependencies) {
25221
+ return await exchangeCreativeRequest(createBridgeGetSmartObjectDefinitionRequest(input.assetPath), sendBridgeGetSmartObjectDefinitionRequest, BRIDGE_GET_SMART_OBJECT_DEFINITION_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
25222
+ }
25223
+ async function addSmartObjectComponent(input, dependencies) {
25224
+ return await exchangeCreativeRequest(createBridgeAddSmartObjectComponentRequest(input.definitionPath, {
25225
+ actorPath: input.actorPath,
25226
+ blueprintPath: input.blueprintPath
25227
+ }, { componentName: input.componentName }), sendBridgeAddSmartObjectComponentRequest, BRIDGE_ADD_SMART_OBJECT_COMPONENT_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
25228
+ }
25229
+ function registerSmartObjectsTools(server, dependencies) {
25230
+ server.registerTool("create_smart_object_definition", {
25231
+ description: "Create a Smart Object definition with its slots — offsets, rotations, activity tags and behavior definitions — and read back what the asset holds, including whether it passes the engine's validation. An invalid definition never registers, so check 'valid' before placing it. Returns state 'unsupported' when the SmartObjects plugin is not loaded.",
25232
+ inputSchema: createSmartObjectDefinitionInputSchema,
25233
+ title: "Create Smart Object Definition"
25234
+ }, async ({ activityTags, assetName, defaultBehaviorDefinitions, packagePath, projectId, slots }) => {
25235
+ return toToolSuccess(await createSmartObjectDefinition({
25236
+ activityTags,
25237
+ assetName,
25238
+ defaultBehaviorDefinitions,
25239
+ packagePath,
25240
+ projectId,
25241
+ slots
25242
+ }, dependencies));
25243
+ });
25244
+ server.registerTool("get_smart_object_definition", {
25245
+ description: "Read a Smart Object definition: its slots, activity tags, behavior definitions and validation result. Returns state 'unsupported' when the SmartObjects plugin is not loaded.",
25246
+ inputSchema: getSmartObjectDefinitionInputSchema,
25247
+ title: "Get Smart Object Definition"
25248
+ }, async ({ assetPath, projectId }) => {
25249
+ return toToolSuccess(await getSmartObjectDefinition({
25250
+ assetPath,
25251
+ projectId
25252
+ }, dependencies));
25253
+ });
25254
+ server.registerTool("add_smart_object_component", {
25255
+ description: "Add a Smart Object component pointing at a definition to an actor Blueprint or a placed actor, or repoint the one already there. The component registers with the Smart Object subsystem when play begins, which needs a valid definition — 'definitionValid' says whether it will. Returns state 'unsupported' when the SmartObjects plugin is not loaded.",
25256
+ inputSchema: addSmartObjectComponentInputSchema,
25257
+ title: "Add Smart Object Component"
25258
+ }, async ({ actorPath, blueprintPath, componentName, definitionPath, projectId }) => {
25259
+ return toToolSuccess(await addSmartObjectComponent({
25260
+ actorPath,
25261
+ blueprintPath,
25262
+ componentName,
25263
+ definitionPath,
25264
+ projectId
25265
+ }, dependencies));
25266
+ });
25267
+ }
25268
+ const smartObjectsToolDomain = {
25269
+ domain: "smartObjects",
25270
+ register: registerSmartObjectsTools,
25271
+ toolNames: [
25272
+ "create_smart_object_definition",
25273
+ "get_smart_object_definition",
25274
+ "add_smart_object_component"
25275
+ ]
25276
+ };
25277
+ //#endregion
23392
25278
  //#region src/tools/stateTree.ts
23393
25279
  const getStateTreeInputSchema = {
23394
25280
  assetPath: bridgeGetStateTreeRequestSchema.shape.assetPath.describe("Object path of the StateTree asset to read."),
@@ -23427,6 +25313,18 @@ const traceStateTreeInputSchema = {
23427
25313
  maxEvents: bridgeTraceStateTreeRequestSchema.shape.maxEvents.describe("Maximum events to return in one poll (1-200, default 50)."),
23428
25314
  projectId: creativeProjectIdSchema
23429
25315
  };
25316
+ const updateStateTreeElementsInputSchema = {
25317
+ assetPath: bridgeUpdateStateTreeElementsRequestSchema.shape.assetPath.describe("Object path of the StateTree asset to edit."),
25318
+ compile: bridgeUpdateStateTreeElementsRequestSchema.shape.compile.describe("Run the StateTree compiler after the edits. Defaults true; its messages come back verbatim in compileMessages."),
25319
+ projectId: creativeProjectIdSchema,
25320
+ updates: bridgeUpdateStateTreeElementsRequestSchema.shape.updates.describe("Edits addressed by the ids get_state_tree reports. { kind: 'state', id, name?, stateType?, selectionBehavior?, enabled? } renames or retypes a state (renaming keeps transitions pointing at it); { kind: 'task', id, params } writes ExportText values onto a task; { kind: 'transition', id, trigger?, targetType?, targetStateId?, eventTag?, enabled? } points a transition at a new target or trigger. A targetStateId alone implies targetType 'goto_state'.")
25321
+ };
25322
+ const removeStateTreeElementsInputSchema = {
25323
+ assetPath: bridgeRemoveStateTreeElementsRequestSchema.shape.assetPath.describe("Object path of the StateTree asset to edit."),
25324
+ compile: bridgeRemoveStateTreeElementsRequestSchema.shape.compile.describe("Run the StateTree compiler after the removals. Defaults true; its messages come back verbatim in compileMessages."),
25325
+ projectId: creativeProjectIdSchema,
25326
+ removals: bridgeRemoveStateTreeElementsRequestSchema.shape.removals.describe("Elements to remove, each { kind, id } with kind 'state', 'task' or 'transition' and the id get_state_tree reports. Removing a state removes its children too.")
25327
+ };
23430
25328
  async function getStateTree(input, dependencies) {
23431
25329
  return await exchangeCreativeRequest(createBridgeGetStateTreeRequest(input.assetPath), sendBridgeGetStateTreeRequest, BRIDGE_GET_STATE_TREE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
23432
25330
  }
@@ -23455,6 +25353,12 @@ async function traceStateTree(input, dependencies) {
23455
25353
  maxEvents: input.maxEvents
23456
25354
  }), sendBridgeTraceStateTreeRequest, BRIDGE_TRACE_STATE_TREE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
23457
25355
  }
25356
+ async function updateStateTreeElements(input, dependencies) {
25357
+ return await exchangeCreativeRequest(createBridgeUpdateStateTreeElementsRequest(input.assetPath, input.updates, { compile: input.compile }), sendBridgeUpdateStateTreeElementsRequest, BRIDGE_UPDATE_STATE_TREE_ELEMENTS_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
25358
+ }
25359
+ async function removeStateTreeElements(input, dependencies) {
25360
+ return await exchangeCreativeRequest(createBridgeRemoveStateTreeElementsRequest(input.assetPath, input.removals, { compile: input.compile }), sendBridgeRemoveStateTreeElementsRequest, BRIDGE_REMOVE_STATE_TREE_ELEMENTS_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
25361
+ }
23458
25362
  function registerStateTreeTools(server, dependencies) {
23459
25363
  server.registerTool("get_state_tree", {
23460
25364
  description: "Read a StateTree back: its schema, parameters, evaluators, global tasks and the full state hierarchy with each state's tasks, enter conditions and transitions. Every state and node carries the id the edit tools address it by, so this is the call to make before editing a tree you did not author. compiled reports whether the asset carries runtime data — a tree that reads back correctly with compiled false is authored but will not run.",
@@ -23529,6 +25433,30 @@ function registerStateTreeTools(server, dependencies) {
23529
25433
  projectId
23530
25434
  }, dependencies));
23531
25435
  });
25436
+ server.registerTool("update_state_tree_elements", {
25437
+ description: "Edit existing StateTree states, tasks and transitions by the ids get_state_tree reports: rename or retype a state, toggle it, change its selection behaviour; set a task's params; retarget, retrigger or toggle a transition. Each edit is reported per item, and the tree is recompiled by default with the compiler's own messages returned verbatim.",
25438
+ inputSchema: updateStateTreeElementsInputSchema,
25439
+ title: "Update StateTree Elements"
25440
+ }, async ({ assetPath, compile, projectId, updates }) => {
25441
+ return toToolSuccess(await updateStateTreeElements({
25442
+ assetPath,
25443
+ compile,
25444
+ projectId,
25445
+ updates
25446
+ }, dependencies));
25447
+ });
25448
+ server.registerTool("remove_state_tree_elements", {
25449
+ description: "Remove StateTree states, tasks and transitions by the ids get_state_tree reports. Removing a state removes its children and every transition elsewhere in the tree that targeted it; those transitions are listed in removedTransitions. The tree is recompiled by default with the compiler's own messages returned verbatim.",
25450
+ inputSchema: removeStateTreeElementsInputSchema,
25451
+ title: "Remove StateTree Elements"
25452
+ }, async ({ assetPath, compile, projectId, removals }) => {
25453
+ return toToolSuccess(await removeStateTreeElements({
25454
+ assetPath,
25455
+ compile,
25456
+ projectId,
25457
+ removals
25458
+ }, dependencies));
25459
+ });
23532
25460
  }
23533
25461
  const stateTreeToolDomain = {
23534
25462
  domain: "stateTree",
@@ -23539,7 +25467,9 @@ const stateTreeToolDomain = {
23539
25467
  "set_state_tree_considerations",
23540
25468
  "link_state_tree_state",
23541
25469
  "add_state_tree_component",
23542
- "trace_state_tree"
25470
+ "trace_state_tree",
25471
+ "update_state_tree_elements",
25472
+ "remove_state_tree_elements"
23543
25473
  ]
23544
25474
  };
23545
25475
  //#endregion
@@ -24464,7 +26394,10 @@ const TOOL_CATALOG = [
24464
26394
  renderToolDomain,
24465
26395
  vfxToolDomain,
24466
26396
  pcgToolDomain,
24467
- projectSettingsToolDomain
26397
+ projectSettingsToolDomain,
26398
+ navigationToolDomain,
26399
+ smartObjectsToolDomain,
26400
+ massToolDomain
24468
26401
  ];
24469
26402
  //#endregion
24470
26403
  //#region src/mcpTools.ts