@uemcp/server 1.11.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.
- package/README.md +34 -1
- package/dist/index.mjs +1138 -35
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -384,6 +384,11 @@ const TOOL_METADATA = {
|
|
|
384
384
|
add_sequence_binding: mutates("sequence", "add_sequence_binding"),
|
|
385
385
|
add_sequence_keys: mutates("sequence", "add_sequence_keys"),
|
|
386
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
|
+
]),
|
|
387
392
|
add_state_tree_component: mutates("ai", "add_state_tree_component"),
|
|
388
393
|
add_state_tree_state: mutates("ai", "add_state_tree_state"),
|
|
389
394
|
add_stimuli_source: mutates("ai", "add_stimuli_source", [
|
|
@@ -489,6 +494,12 @@ const TOOL_METADATA = {
|
|
|
489
494
|
create_landscape: mutates("level", "create_landscape"),
|
|
490
495
|
create_level_sequence: mutates("sequence", "create_level_sequence"),
|
|
491
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
|
+
]),
|
|
492
503
|
create_metasound: mutates("audio", "create_metasound"),
|
|
493
504
|
create_montage: mutates("anim", "create_montage"),
|
|
494
505
|
create_pcg_graph: mutates("fx", "create_pcg_graph"),
|
|
@@ -499,6 +510,11 @@ const TOOL_METADATA = {
|
|
|
499
510
|
"cost"
|
|
500
511
|
]),
|
|
501
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
|
+
]),
|
|
502
518
|
create_sound_cue: mutates("audio", "create_sound_cue"),
|
|
503
519
|
create_state_tree: mutates("ai", "create_state_tree"),
|
|
504
520
|
create_struct: mutates("blueprint", "create_struct"),
|
|
@@ -512,6 +528,13 @@ const TOOL_METADATA = {
|
|
|
512
528
|
delete_asset: destroys("asset", "delete_asset"),
|
|
513
529
|
delete_data_table: destroys("asset", "delete_data_table"),
|
|
514
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
|
+
]),
|
|
515
538
|
disconnect_pins: mutates("blueprint", "disconnect_pins"),
|
|
516
539
|
doctor: readOnly("core", void 0, [
|
|
517
540
|
"diagnose",
|
|
@@ -527,6 +550,12 @@ const TOOL_METADATA = {
|
|
|
527
550
|
"generator",
|
|
528
551
|
"score"
|
|
529
552
|
]),
|
|
553
|
+
edit_mass_entity_config: mutates("ai", "edit_mass_entity_config", [
|
|
554
|
+
"mass",
|
|
555
|
+
"crowd",
|
|
556
|
+
"entity config",
|
|
557
|
+
"trait"
|
|
558
|
+
]),
|
|
530
559
|
enable_toolset: idempotentMutates("core", void 0, [
|
|
531
560
|
"toolset",
|
|
532
561
|
"tools",
|
|
@@ -620,6 +649,12 @@ const TOOL_METADATA = {
|
|
|
620
649
|
get_editor_state: readOnly("core", "get_editor_state"),
|
|
621
650
|
get_eqs_query: readOnly("ai", "get_eqs_query"),
|
|
622
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
|
+
]),
|
|
623
658
|
get_net_stats: readOnly("test", "get_net_stats", [
|
|
624
659
|
"network",
|
|
625
660
|
"multiplayer",
|
|
@@ -631,6 +666,7 @@ const TOOL_METADATA = {
|
|
|
631
666
|
get_pie_status: readOnly("test", "get_pie_status"),
|
|
632
667
|
get_project_id: readOnly("core", void 0, ["projectid", "identity"]),
|
|
633
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"]),
|
|
634
670
|
get_source_control_job_status: readOnly("asset", "get_source_control_job_status"),
|
|
635
671
|
get_source_control_status: readOnly("asset", "get_source_control_status"),
|
|
636
672
|
get_state_tree: readOnly("ai", "get_state_tree"),
|
|
@@ -654,6 +690,12 @@ const TOOL_METADATA = {
|
|
|
654
690
|
"enhanced input"
|
|
655
691
|
]),
|
|
656
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
|
+
]),
|
|
657
699
|
link_state_tree_state: mutates("ai", "link_state_tree_state", ["subtree", "linked"]),
|
|
658
700
|
list_actors: readOnly("core", "list_actors"),
|
|
659
701
|
list_asset_factories: readOnly("asset", "list_asset_factories"),
|
|
@@ -699,6 +741,11 @@ const TOOL_METADATA = {
|
|
|
699
741
|
refresh_source_control_status: idempotentMutates("asset", "refresh_source_control_status"),
|
|
700
742
|
reimport_asset: reachesOutside("asset", false, "reimport_asset"),
|
|
701
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
|
+
]),
|
|
702
749
|
rename_asset: mutates("asset", "rename_asset"),
|
|
703
750
|
rename_data_table: mutates("asset", "rename_data_table"),
|
|
704
751
|
rename_data_table_row: mutates("asset", "rename_data_table_row"),
|
|
@@ -809,6 +856,17 @@ const TOOL_METADATA = {
|
|
|
809
856
|
trigger_hot_reload: mutates("build", "start_hot_reload"),
|
|
810
857
|
trigger_live_compile: mutates("build", "start_live_compile", ["live coding", "recompile"]),
|
|
811
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
|
+
]),
|
|
812
870
|
wait_for_job: readOnly("core", void 0, [
|
|
813
871
|
"poll",
|
|
814
872
|
"block",
|
|
@@ -1401,6 +1459,10 @@ const bridgeBlueprintNodeSchema = z.object({
|
|
|
1401
1459
|
nodeId: z.string(),
|
|
1402
1460
|
pinCount: z.number().int().min(0),
|
|
1403
1461
|
pins: z.array(bridgeBlueprintPinSchema),
|
|
1462
|
+
position: z.object({
|
|
1463
|
+
x: z.number().int(),
|
|
1464
|
+
y: z.number().int()
|
|
1465
|
+
}).optional(),
|
|
1404
1466
|
title: z.string()
|
|
1405
1467
|
});
|
|
1406
1468
|
const bridgeErrorResponseSchema = z.object({
|
|
@@ -2624,6 +2686,7 @@ const BRIDGE_CONNECT_PINS_REQUEST_TYPE = "connect_pins";
|
|
|
2624
2686
|
const BRIDGE_DISCONNECT_PINS_REQUEST_TYPE = "disconnect_pins";
|
|
2625
2687
|
const BRIDGE_SET_PIN_DEFAULT_REQUEST_TYPE = "set_pin_default";
|
|
2626
2688
|
const BRIDGE_LIST_AVAILABLE_NODES_REQUEST_TYPE = "list_available_nodes";
|
|
2689
|
+
const BRIDGE_LAYOUT_GRAPH_REQUEST_TYPE = "layout_graph";
|
|
2627
2690
|
const BRIDGE_GRAPH_PIN_VALUE_MAX_CHARS = 4096;
|
|
2628
2691
|
const BRIDGE_GRAPH_NODE_POSITION_LIMIT = 1e6;
|
|
2629
2692
|
const BRIDGE_GRAPH_NODE_KINDS = [
|
|
@@ -2641,6 +2704,10 @@ const graphNodePositionSchema = z.object({
|
|
|
2641
2704
|
x: z.number().int().min(-1e6).max(BRIDGE_GRAPH_NODE_POSITION_LIMIT).default(0),
|
|
2642
2705
|
y: z.number().int().min(-1e6).max(BRIDGE_GRAPH_NODE_POSITION_LIMIT).default(0)
|
|
2643
2706
|
});
|
|
2707
|
+
const graphNodePlacedPositionSchema = z.object({
|
|
2708
|
+
x: z.number().int(),
|
|
2709
|
+
y: z.number().int()
|
|
2710
|
+
});
|
|
2644
2711
|
const bridgeListGraphNodesRequestSchema = z.object({
|
|
2645
2712
|
assetPath: assetPathSchema,
|
|
2646
2713
|
cursor: assetCursorSchema.optional(),
|
|
@@ -2653,6 +2720,7 @@ const bridgeListGraphNodesRequestSchema = z.object({
|
|
|
2653
2720
|
});
|
|
2654
2721
|
const bridgeAddGraphNodeRequestFieldsSchema = z.object({
|
|
2655
2722
|
assetPath: assetPathSchema,
|
|
2723
|
+
autoLayout: z.boolean().optional(),
|
|
2656
2724
|
graphName: graphNameSchema,
|
|
2657
2725
|
nodeClass: assetPathSchema.optional(),
|
|
2658
2726
|
kind: graphNodeKindSchema,
|
|
@@ -2704,6 +2772,13 @@ const bridgeSetPinDefaultRequestSchema = z.object({
|
|
|
2704
2772
|
value: graphPinValueSchema,
|
|
2705
2773
|
version: z.literal(2)
|
|
2706
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
|
+
});
|
|
2707
2782
|
const bridgeListAvailableNodesRequestSchema = z.object({
|
|
2708
2783
|
assetPath: assetPathSchema,
|
|
2709
2784
|
cursor: assetCursorSchema.optional(),
|
|
@@ -2732,6 +2807,7 @@ const bridgeAddGraphNodeSuccessResponseSchema = z.object({
|
|
|
2732
2807
|
message: nonEmptyStringSchema.optional(),
|
|
2733
2808
|
node: bridgeBlueprintNodeSchema,
|
|
2734
2809
|
ok: z.literal(true),
|
|
2810
|
+
position: graphNodePlacedPositionSchema.optional(),
|
|
2735
2811
|
requestId: requestIdSchema,
|
|
2736
2812
|
state: creativeEditStateSchema,
|
|
2737
2813
|
type: z.literal(BRIDGE_ADD_GRAPH_NODE_REQUEST_TYPE),
|
|
@@ -2807,6 +2883,20 @@ const bridgeListAvailableNodesSuccessResponseSchema = z.object({
|
|
|
2807
2883
|
type: z.literal(BRIDGE_LIST_AVAILABLE_NODES_REQUEST_TYPE),
|
|
2808
2884
|
version: z.literal(2)
|
|
2809
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
|
+
});
|
|
2810
2900
|
const bridgeListGraphNodesResponseSchema = z.union([bridgeListGraphNodesSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2811
2901
|
const bridgeAddGraphNodeResponseSchema = z.union([bridgeAddGraphNodeSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2812
2902
|
const bridgeRemoveGraphNodeResponseSchema = z.union([bridgeRemoveGraphNodeSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
@@ -2814,6 +2904,7 @@ const bridgeConnectPinsResponseSchema = z.union([bridgeConnectPinsSuccessRespons
|
|
|
2814
2904
|
const bridgeDisconnectPinsResponseSchema = z.union([bridgeDisconnectPinsSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2815
2905
|
const bridgeSetPinDefaultResponseSchema = z.union([bridgeSetPinDefaultSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2816
2906
|
const bridgeListAvailableNodesResponseSchema = z.union([bridgeListAvailableNodesSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2907
|
+
const bridgeLayoutGraphResponseSchema = z.union([bridgeLayoutGraphSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2817
2908
|
function createBridgeListGraphNodesRequest(assetPath, graphName, options = {}, requestId = randomUUID()) {
|
|
2818
2909
|
return bridgeListGraphNodesRequestSchema.parse({
|
|
2819
2910
|
assetPath,
|
|
@@ -2829,6 +2920,7 @@ function createBridgeListGraphNodesRequest(assetPath, graphName, options = {}, r
|
|
|
2829
2920
|
function createBridgeAddGraphNodeRequest(assetPath, graphName, kind, options = {}, requestId = randomUUID()) {
|
|
2830
2921
|
return bridgeAddGraphNodeRequestSchema.parse({
|
|
2831
2922
|
assetPath,
|
|
2923
|
+
autoLayout: options.autoLayout,
|
|
2832
2924
|
graphName,
|
|
2833
2925
|
kind,
|
|
2834
2926
|
memberName: options.memberName,
|
|
@@ -2901,6 +2993,15 @@ function createBridgeListAvailableNodesRequest(assetPath, graphName, options = {
|
|
|
2901
2993
|
version: 2
|
|
2902
2994
|
});
|
|
2903
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
|
+
}
|
|
2904
3005
|
//#endregion
|
|
2905
3006
|
//#region src/protocol/debugger.ts
|
|
2906
3007
|
const BRIDGE_SET_BLUEPRINT_BREAKPOINT_REQUEST_TYPE = "set_blueprint_breakpoint";
|
|
@@ -7441,6 +7542,7 @@ const bridgeStateTreeNodeReportSchema = z.object({
|
|
|
7441
7542
|
const bridgeStateTreeTransitionReportSchema = z.object({
|
|
7442
7543
|
eventTag: z.string().optional(),
|
|
7443
7544
|
id: z.string(),
|
|
7545
|
+
targetStateId: z.string().optional(),
|
|
7444
7546
|
targetStateName: z.string().optional(),
|
|
7445
7547
|
targetType: z.string(),
|
|
7446
7548
|
trigger: z.string()
|
|
@@ -7688,6 +7790,141 @@ function createBridgeTraceStateTreeRequest(action, options = {}, requestId = ran
|
|
|
7688
7790
|
version: 2
|
|
7689
7791
|
});
|
|
7690
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
|
+
}
|
|
7691
7928
|
//#endregion
|
|
7692
7929
|
//#region src/protocol/perception.ts
|
|
7693
7930
|
const BRIDGE_CREATE_AI_CONTROLLER_REQUEST_TYPE = "create_ai_controller";
|
|
@@ -11015,9 +11252,366 @@ function createBridgeTestReachabilityRequest(pairs, options = {}, requestId = ra
|
|
|
11015
11252
|
version: 2
|
|
11016
11253
|
});
|
|
11017
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,
|
|
11601
|
+
version: 2
|
|
11602
|
+
});
|
|
11603
|
+
}
|
|
11604
|
+
function createBridgeValidateMassEntityConfigRequest(assetPath, requestId = randomUUID()) {
|
|
11605
|
+
return bridgeValidateMassEntityConfigRequestSchema.parse({
|
|
11606
|
+
assetPath,
|
|
11607
|
+
requestId,
|
|
11608
|
+
type: BRIDGE_VALIDATE_MASS_ENTITY_CONFIG_REQUEST_TYPE,
|
|
11609
|
+
version: 2
|
|
11610
|
+
});
|
|
11611
|
+
}
|
|
11018
11612
|
//#endregion
|
|
11019
11613
|
//#region src/version.ts
|
|
11020
|
-
const SERVER_VERSION = "1.
|
|
11614
|
+
const SERVER_VERSION = "1.12.0";
|
|
11021
11615
|
//#endregion
|
|
11022
11616
|
//#region src/bridgeSocketClient.ts
|
|
11023
11617
|
var BridgeSocketError = class extends Error {
|
|
@@ -11253,6 +11847,9 @@ async function sendBridgeSetPinDefaultRequest(request, options) {
|
|
|
11253
11847
|
async function sendBridgeListAvailableNodesRequest(request, options) {
|
|
11254
11848
|
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeListAvailableNodesResponseSchema, request.requestId);
|
|
11255
11849
|
}
|
|
11850
|
+
async function sendBridgeLayoutGraphRequest(request, options) {
|
|
11851
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeLayoutGraphResponseSchema, request.requestId);
|
|
11852
|
+
}
|
|
11256
11853
|
async function sendBridgeSetViewportCameraRequest(request, options) {
|
|
11257
11854
|
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeSetViewportCameraResponseSchema, request.requestId);
|
|
11258
11855
|
}
|
|
@@ -11973,6 +12570,36 @@ async function sendBridgeFindPathRequest(request, options) {
|
|
|
11973
12570
|
async function sendBridgeTestReachabilityRequest(request, options) {
|
|
11974
12571
|
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeTestReachabilityResponseSchema, request.requestId);
|
|
11975
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
|
+
}
|
|
11976
12603
|
//#endregion
|
|
11977
12604
|
//#region src/enginePing.ts
|
|
11978
12605
|
async function pingRegistryEntry$1(entry, options) {
|
|
@@ -18799,6 +19426,7 @@ const debuggerToolDomain = {
|
|
|
18799
19426
|
};
|
|
18800
19427
|
//#endregion
|
|
18801
19428
|
//#region src/traceAnalysis.ts
|
|
19429
|
+
const LLM_TAG_COUNTER_PATTERN = "STAT_*LLM";
|
|
18802
19430
|
const SECONDS_TO_MS = 1e3;
|
|
18803
19431
|
const FRAME_ROOT_TIMER_NAMES = /* @__PURE__ */ new Set(["FEngineLoop::Tick"]);
|
|
18804
19432
|
function parseCsvRows(text) {
|
|
@@ -18891,6 +19519,9 @@ function summarizeTimerStatistics(rows, maxScopes) {
|
|
|
18891
19519
|
if (count !== void 0) scope.count = count;
|
|
18892
19520
|
scopes.push(scope);
|
|
18893
19521
|
}
|
|
19522
|
+
return rankScopes(scopes, maxScopes);
|
|
19523
|
+
}
|
|
19524
|
+
function rankScopes(scopes, maxScopes) {
|
|
18894
19525
|
const byInclusiveTime = [...scopes].sort((left, right) => right.inclusiveTimeMs - left.inclusiveTimeMs);
|
|
18895
19526
|
return {
|
|
18896
19527
|
byExclusiveTime: [...scopes].sort((left, right) => right.exclusiveTimeMs - left.exclusiveTimeMs).slice(0, maxScopes),
|
|
@@ -18902,18 +19533,20 @@ function summarizeTimerStatistics(rows, maxScopes) {
|
|
|
18902
19533
|
function isGpuThread(threadName) {
|
|
18903
19534
|
return threadName.toUpperCase().includes("GPU");
|
|
18904
19535
|
}
|
|
18905
|
-
async function
|
|
19536
|
+
async function forEachTimingEvent(lines, visit) {
|
|
18906
19537
|
let headers;
|
|
18907
19538
|
let threadIndex = -1;
|
|
18908
19539
|
let timerIndex = -1;
|
|
18909
19540
|
let durationIndex = -1;
|
|
18910
19541
|
let startIndex = -1;
|
|
18911
19542
|
let depthIndex = -1;
|
|
18912
|
-
|
|
18913
|
-
|
|
18914
|
-
|
|
18915
|
-
|
|
18916
|
-
|
|
19543
|
+
const event = {
|
|
19544
|
+
depth: 0,
|
|
19545
|
+
durationMs: 0,
|
|
19546
|
+
startTimeMs: 0,
|
|
19547
|
+
threadName: "",
|
|
19548
|
+
timerName: ""
|
|
19549
|
+
};
|
|
18917
19550
|
for await (const rawLine of lines) {
|
|
18918
19551
|
const line = rawLine.trim();
|
|
18919
19552
|
if (line.length === 0) continue;
|
|
@@ -18926,36 +19559,160 @@ async function summarizeTimingEventStream(lines, options) {
|
|
|
18926
19559
|
durationIndex = columnIndex(headers, findColumn(headerRow, "Duration", "InclusiveTime"));
|
|
18927
19560
|
startIndex = columnIndex(headers, findColumn(headerRow, "StartTime", "Start"));
|
|
18928
19561
|
depthIndex = columnIndex(headers, findColumn(headerRow, "Depth"));
|
|
18929
|
-
if (threadIndex < 0 || durationIndex < 0)
|
|
19562
|
+
if (threadIndex < 0 || durationIndex < 0) return;
|
|
18930
19563
|
continue;
|
|
18931
19564
|
}
|
|
18932
19565
|
const duration = readNumber(values[durationIndex]);
|
|
18933
19566
|
const threadName = values[threadIndex];
|
|
18934
19567
|
if (duration === void 0 || threadName === void 0) continue;
|
|
18935
|
-
|
|
18936
|
-
|
|
18937
|
-
|
|
18938
|
-
|
|
18939
|
-
|
|
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;
|
|
18940
19583
|
}
|
|
18941
|
-
|
|
18942
|
-
|
|
18943
|
-
|
|
18944
|
-
|
|
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;
|
|
19606
|
+
}
|
|
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;
|
|
18945
19612
|
hitchCount += 1;
|
|
18946
19613
|
retainWorstHitch(worstHitches, options.maxHitches, {
|
|
18947
|
-
durationMs,
|
|
18948
|
-
startTimeMs:
|
|
19614
|
+
durationMs: event.durationMs,
|
|
19615
|
+
startTimeMs: event.startTimeMs,
|
|
19616
|
+
topScopes: []
|
|
18949
19617
|
});
|
|
18950
|
-
}
|
|
19618
|
+
});
|
|
18951
19619
|
return {
|
|
18952
19620
|
frames: summarizeFrameDurations(frameDurationsMs, worstHitches, hitchCount, options),
|
|
19621
|
+
gpuScopes: rankScopeTotals(gpuScopeTotals, options.maxScopes),
|
|
18953
19622
|
threads: {
|
|
18954
19623
|
cpuTimeMs,
|
|
18955
19624
|
gpuTimeMs
|
|
18956
19625
|
}
|
|
18957
19626
|
};
|
|
18958
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
|
+
}
|
|
18959
19716
|
function retainWorstHitch(worstHitches, maxHitches, hitch) {
|
|
18960
19717
|
if (worstHitches.length >= maxHitches) {
|
|
18961
19718
|
const weakest = worstHitches[worstHitches.length - 1];
|
|
@@ -18991,16 +19748,53 @@ function percentile(sortedValues, fraction) {
|
|
|
18991
19748
|
if (sortedValues.length === 0) return 0;
|
|
18992
19749
|
return sortedValues[Math.min(sortedValues.length - 1, Math.max(0, Math.ceil(fraction * sortedValues.length) - 1))] ?? 0;
|
|
18993
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
|
+
}
|
|
18994
19787
|
//#endregion
|
|
18995
19788
|
//#region src/tools/diagnostics.ts
|
|
18996
19789
|
const ANALYZE_TRACE_DEFAULT_TIMEOUT_MS = 6e5;
|
|
18997
19790
|
const ANALYZE_TRACE_DEFAULT_HITCH_THRESHOLD_MS = 33.4;
|
|
18998
19791
|
const ANALYZE_TRACE_MAX_RESPONSE_BYTES = 32768;
|
|
19792
|
+
const LLM_COUNTER_FILE_PREFIX = "llm-";
|
|
18999
19793
|
const analyzeTraceInputSchema = {
|
|
19000
19794
|
engineVersion: engineVersionSchema,
|
|
19001
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).`),
|
|
19002
19796
|
maxHitches: z.number().int().min(1).max(50).optional().describe(`Maximum worst-hitch entries to return (default ${String(10)}, max ${String(50)}).`),
|
|
19003
|
-
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)}).`),
|
|
19004
19798
|
projectPath: z.string().trim().min(1).optional().describe("Project whose EngineAssociation selects the analyzer engine. Omit when engineVersion is given."),
|
|
19005
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)}).`),
|
|
19006
19800
|
tracePath: z.string().trim().min(1).describe("Path to the .utrace file produced by stop_insights_trace.")
|
|
@@ -19016,8 +19810,10 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
|
|
|
19016
19810
|
engineVersion: engine.engineVersion,
|
|
19017
19811
|
hitchThresholdMs,
|
|
19018
19812
|
hitches: [],
|
|
19813
|
+
memoryTags: [],
|
|
19019
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.`,
|
|
19020
19815
|
state: "unsupported",
|
|
19816
|
+
topGpuScopes: [],
|
|
19021
19817
|
topScopesByExclusiveTime: [],
|
|
19022
19818
|
topScopesByInclusiveTime: [],
|
|
19023
19819
|
tracePath,
|
|
@@ -19029,7 +19825,11 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
|
|
|
19029
19825
|
const timingEventsPath = path.join(exportDirectory, "timing-events.csv");
|
|
19030
19826
|
const commandFilePath = path.join(exportDirectory, "export.rsp");
|
|
19031
19827
|
try {
|
|
19032
|
-
await context.writeFile(commandFilePath, [
|
|
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"));
|
|
19033
19833
|
dependencies.logger.info({
|
|
19034
19834
|
engineVersion: engine.engineVersion,
|
|
19035
19835
|
tracePath
|
|
@@ -19049,16 +19849,24 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
|
|
|
19049
19849
|
});
|
|
19050
19850
|
if (run.timedOut) throw new EngineToolchainError(`Unreal Insights did not finish analyzing ${tracePath} within ${String(timeoutMs)}ms; raise timeoutMs or trim the trace.`);
|
|
19051
19851
|
if (run.exitCode !== 0) throw new EngineToolchainError(`Unreal Insights exited with code ${String(run.exitCode)} while analyzing ${tracePath}: ${run.combinedOutput.slice(-1e3).trim()}`);
|
|
19052
|
-
const
|
|
19053
|
-
const
|
|
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(), {
|
|
19054
19857
|
hitchThresholdMs,
|
|
19055
|
-
maxHitches: input.maxHitches ?? 10
|
|
19858
|
+
maxHitches: input.maxHitches ?? 10,
|
|
19859
|
+
maxScopes
|
|
19056
19860
|
});
|
|
19057
19861
|
const frames = timingEvents.frames;
|
|
19058
19862
|
const threadTimes = timingEvents.threads;
|
|
19863
|
+
const hitches = await attributeHitchScopes(readTimingEventLines(), frames.hitches, 5);
|
|
19864
|
+
const memoryTags = await summarizeMemoryTags(exportDirectory, maxScopes, context);
|
|
19059
19865
|
const truncated = [];
|
|
19060
19866
|
if (scopeSummaries.truncated) truncated.push("topScopes");
|
|
19061
19867
|
if (frames.hitchesTruncated) truncated.push("hitches");
|
|
19868
|
+
if (timingEvents.gpuScopes.truncated) truncated.push("topGpuScopes");
|
|
19869
|
+
if (memoryTags.truncated) truncated.push("memoryTags");
|
|
19062
19870
|
const result = {
|
|
19063
19871
|
analyzerPath,
|
|
19064
19872
|
cpuTimeMs: threadTimes.cpuTimeMs,
|
|
@@ -19068,10 +19876,14 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
|
|
|
19068
19876
|
frameCount: frames.frameCount,
|
|
19069
19877
|
gpuTimeMs: threadTimes.gpuTimeMs,
|
|
19070
19878
|
hitchThresholdMs,
|
|
19071
|
-
hitches
|
|
19879
|
+
hitches,
|
|
19880
|
+
memoryTags: memoryTags.tags,
|
|
19072
19881
|
state: "analyzed",
|
|
19882
|
+
topGpuScopes: timingEvents.gpuScopes.byExclusiveTime,
|
|
19073
19883
|
topScopesByExclusiveTime: scopeSummaries.byExclusiveTime,
|
|
19074
19884
|
topScopesByInclusiveTime: scopeSummaries.byInclusiveTime,
|
|
19885
|
+
totalGpuScopeCount: timingEvents.gpuScopes.totalScopeCount,
|
|
19886
|
+
totalMemoryTagCount: memoryTags.totalTagCount,
|
|
19075
19887
|
totalScopeCount: scopeSummaries.totalScopeCount,
|
|
19076
19888
|
tracePath,
|
|
19077
19889
|
truncated
|
|
@@ -19117,22 +19929,42 @@ function boundAnalyzeTraceResult(result) {
|
|
|
19117
19929
|
truncated: [...result.truncated]
|
|
19118
19930
|
};
|
|
19119
19931
|
while (JSON.stringify(bounded).length > ANALYZE_TRACE_MAX_RESPONSE_BYTES) {
|
|
19120
|
-
const
|
|
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);
|
|
19121
19934
|
if (longestListLength <= 1) {
|
|
19122
19935
|
addTruncationReason(bounded, "responseBytesExceeded");
|
|
19123
19936
|
return bounded;
|
|
19124
19937
|
}
|
|
19125
|
-
if (
|
|
19938
|
+
if (topScopesLength === longestListLength) {
|
|
19126
19939
|
bounded.topScopesByInclusiveTime = bounded.topScopesByInclusiveTime.slice(0, longestListLength - 1);
|
|
19127
19940
|
bounded.topScopesByExclusiveTime = bounded.topScopesByExclusiveTime.slice(0, longestListLength - 1);
|
|
19128
19941
|
addTruncationReason(bounded, "topScopes");
|
|
19129
19942
|
continue;
|
|
19130
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
|
+
}
|
|
19131
19954
|
bounded.hitches = bounded.hitches.slice(0, bounded.hitches.length - 1);
|
|
19132
19955
|
addTruncationReason(bounded, "hitches");
|
|
19133
19956
|
}
|
|
19134
19957
|
return bounded;
|
|
19135
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
|
+
}
|
|
19136
19968
|
function addTruncationReason(result, reason) {
|
|
19137
19969
|
if (!result.truncated.includes(reason)) result.truncated.push(reason);
|
|
19138
19970
|
}
|
|
@@ -19270,7 +20102,7 @@ function registerDiagnosticsTools(server, dependencies) {
|
|
|
19270
20102
|
}, dependencies));
|
|
19271
20103
|
});
|
|
19272
20104
|
server.registerTool("analyze_trace", {
|
|
19273
|
-
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,
|
|
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.",
|
|
19274
20106
|
inputSchema: analyzeTraceInputSchema,
|
|
19275
20107
|
title: "Analyze Trace"
|
|
19276
20108
|
}, async (input) => {
|
|
@@ -20111,6 +20943,7 @@ const listGraphNodesInputSchema = {
|
|
|
20111
20943
|
};
|
|
20112
20944
|
const addGraphNodeInputSchema = {
|
|
20113
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."),
|
|
20114
20947
|
graphName: bridgeAddGraphNodeRequestFieldsSchema.shape.graphName.describe("Graph to add the node to."),
|
|
20115
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."),
|
|
20116
20949
|
memberName: bridgeAddGraphNodeRequestFieldsSchema.shape.memberName.describe("Function or variable name, required for every kind except 'class'."),
|
|
@@ -20152,6 +20985,11 @@ const setPinDefaultInputSchema = {
|
|
|
20152
20985
|
projectId: creativeProjectIdSchema,
|
|
20153
20986
|
value: bridgeSetPinDefaultRequestSchema.shape.value.describe("ExportText value, the same format get_actor_details emits and set_actor_property accepts.")
|
|
20154
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
|
+
};
|
|
20155
20993
|
const listAvailableNodesInputSchema = {
|
|
20156
20994
|
assetPath: bridgeListAvailableNodesRequestSchema.shape.assetPath.describe("Package name or object path of the asset owning the graph."),
|
|
20157
20995
|
cursor: bridgeListAvailableNodesRequestSchema.shape.cursor.describe("nextCursor from a previous response, to fetch the following page."),
|
|
@@ -20169,6 +21007,7 @@ async function listGraphNodes(input, dependencies) {
|
|
|
20169
21007
|
}
|
|
20170
21008
|
async function addGraphNode(input, dependencies) {
|
|
20171
21009
|
return await exchangeCreativeRequest(createBridgeAddGraphNodeRequest(input.assetPath, input.graphName, input.kind, {
|
|
21010
|
+
autoLayout: input.autoLayout,
|
|
20172
21011
|
memberName: input.memberName,
|
|
20173
21012
|
memberParentClass: input.memberParentClass,
|
|
20174
21013
|
nodeClass: input.nodeClass,
|
|
@@ -20207,6 +21046,9 @@ async function listAvailableNodes(input, dependencies) {
|
|
|
20207
21046
|
nameFilter: input.nameFilter
|
|
20208
21047
|
}), sendBridgeListAvailableNodesRequest, BRIDGE_LIST_AVAILABLE_NODES_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
20209
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
|
+
}
|
|
20210
21052
|
function registerGraphTools(server, dependencies) {
|
|
20211
21053
|
server.registerTool("list_graph_nodes", {
|
|
20212
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.",
|
|
@@ -20223,12 +21065,13 @@ function registerGraphTools(server, dependencies) {
|
|
|
20223
21065
|
}, dependencies));
|
|
20224
21066
|
});
|
|
20225
21067
|
server.registerTool("add_graph_node", {
|
|
20226
|
-
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.",
|
|
20227
21069
|
inputSchema: addGraphNodeInputSchema,
|
|
20228
21070
|
title: "Add Graph Node"
|
|
20229
|
-
}, async ({ assetPath, graphName, kind, memberName, memberParentClass, nodeClass, pinDefaults, position, projectId }) => {
|
|
21071
|
+
}, async ({ assetPath, autoLayout, graphName, kind, memberName, memberParentClass, nodeClass, pinDefaults, position, projectId }) => {
|
|
20230
21072
|
return toToolSuccess(await addGraphNode({
|
|
20231
21073
|
assetPath,
|
|
21074
|
+
autoLayout,
|
|
20232
21075
|
graphName,
|
|
20233
21076
|
kind,
|
|
20234
21077
|
memberName,
|
|
@@ -20309,6 +21152,17 @@ function registerGraphTools(server, dependencies) {
|
|
|
20309
21152
|
projectId
|
|
20310
21153
|
}, dependencies));
|
|
20311
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
|
+
});
|
|
20312
21166
|
}
|
|
20313
21167
|
const graphToolDomain = {
|
|
20314
21168
|
domain: "graph",
|
|
@@ -20320,7 +21174,8 @@ const graphToolDomain = {
|
|
|
20320
21174
|
"connect_pins",
|
|
20321
21175
|
"disconnect_pins",
|
|
20322
21176
|
"set_pin_default",
|
|
20323
|
-
"list_available_nodes"
|
|
21177
|
+
"list_available_nodes",
|
|
21178
|
+
"layout_graph"
|
|
20324
21179
|
]
|
|
20325
21180
|
};
|
|
20326
21181
|
//#endregion
|
|
@@ -22832,6 +23687,95 @@ const logsToolDomain = {
|
|
|
22832
23687
|
]
|
|
22833
23688
|
};
|
|
22834
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
|
|
22835
23779
|
//#region src/tools/material.ts
|
|
22836
23780
|
const createMaterialInstanceInputSchema = {
|
|
22837
23781
|
assetName: bridgeCreateMaterialInstanceRequestSchema.shape.assetName.describe("Name of the new instance, e.g. 'MI_Rock_Mossy'."),
|
|
@@ -23102,6 +24046,13 @@ const testReachabilityInputSchema = {
|
|
|
23102
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.`),
|
|
23103
24047
|
projectId: creativeProjectIdSchema
|
|
23104
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
|
+
};
|
|
23105
24056
|
async function setNavmeshSettings(input, dependencies) {
|
|
23106
24057
|
return await exchangeCreativeRequest(createBridgeSetNavmeshSettingsRequest({
|
|
23107
24058
|
agentHeight: input.agentHeight,
|
|
@@ -23172,6 +24123,14 @@ async function testReachability(input, dependencies) {
|
|
|
23172
24123
|
navMeshActorPath: input.navMeshActorPath
|
|
23173
24124
|
}), sendBridgeTestReachabilityRequest, BRIDGE_TEST_REACHABILITY_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23174
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
|
+
}
|
|
23175
24134
|
function registerNavigationTools(server, dependencies) {
|
|
23176
24135
|
server.registerTool("set_navmesh_settings", {
|
|
23177
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.",
|
|
@@ -23289,6 +24248,19 @@ function registerNavigationTools(server, dependencies) {
|
|
|
23289
24248
|
projectId
|
|
23290
24249
|
}, dependencies));
|
|
23291
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
|
+
});
|
|
23292
24264
|
}
|
|
23293
24265
|
const navigationToolDomain = {
|
|
23294
24266
|
domain: "navigation",
|
|
@@ -23301,7 +24273,8 @@ const navigationToolDomain = {
|
|
|
23301
24273
|
"add_nav_modifier_volume",
|
|
23302
24274
|
"add_nav_link",
|
|
23303
24275
|
"find_path",
|
|
23304
|
-
"test_reachability"
|
|
24276
|
+
"test_reachability",
|
|
24277
|
+
"diagnose_navmesh"
|
|
23305
24278
|
]
|
|
23306
24279
|
};
|
|
23307
24280
|
//#endregion
|
|
@@ -24218,6 +25191,90 @@ const sequencerToolDomain = {
|
|
|
24218
25191
|
]
|
|
24219
25192
|
};
|
|
24220
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
|
|
24221
25278
|
//#region src/tools/stateTree.ts
|
|
24222
25279
|
const getStateTreeInputSchema = {
|
|
24223
25280
|
assetPath: bridgeGetStateTreeRequestSchema.shape.assetPath.describe("Object path of the StateTree asset to read."),
|
|
@@ -24256,6 +25313,18 @@ const traceStateTreeInputSchema = {
|
|
|
24256
25313
|
maxEvents: bridgeTraceStateTreeRequestSchema.shape.maxEvents.describe("Maximum events to return in one poll (1-200, default 50)."),
|
|
24257
25314
|
projectId: creativeProjectIdSchema
|
|
24258
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
|
+
};
|
|
24259
25328
|
async function getStateTree(input, dependencies) {
|
|
24260
25329
|
return await exchangeCreativeRequest(createBridgeGetStateTreeRequest(input.assetPath), sendBridgeGetStateTreeRequest, BRIDGE_GET_STATE_TREE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
24261
25330
|
}
|
|
@@ -24284,6 +25353,12 @@ async function traceStateTree(input, dependencies) {
|
|
|
24284
25353
|
maxEvents: input.maxEvents
|
|
24285
25354
|
}), sendBridgeTraceStateTreeRequest, BRIDGE_TRACE_STATE_TREE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
24286
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
|
+
}
|
|
24287
25362
|
function registerStateTreeTools(server, dependencies) {
|
|
24288
25363
|
server.registerTool("get_state_tree", {
|
|
24289
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.",
|
|
@@ -24358,6 +25433,30 @@ function registerStateTreeTools(server, dependencies) {
|
|
|
24358
25433
|
projectId
|
|
24359
25434
|
}, dependencies));
|
|
24360
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
|
+
});
|
|
24361
25460
|
}
|
|
24362
25461
|
const stateTreeToolDomain = {
|
|
24363
25462
|
domain: "stateTree",
|
|
@@ -24368,7 +25467,9 @@ const stateTreeToolDomain = {
|
|
|
24368
25467
|
"set_state_tree_considerations",
|
|
24369
25468
|
"link_state_tree_state",
|
|
24370
25469
|
"add_state_tree_component",
|
|
24371
|
-
"trace_state_tree"
|
|
25470
|
+
"trace_state_tree",
|
|
25471
|
+
"update_state_tree_elements",
|
|
25472
|
+
"remove_state_tree_elements"
|
|
24372
25473
|
]
|
|
24373
25474
|
};
|
|
24374
25475
|
//#endregion
|
|
@@ -25294,7 +26395,9 @@ const TOOL_CATALOG = [
|
|
|
25294
26395
|
vfxToolDomain,
|
|
25295
26396
|
pcgToolDomain,
|
|
25296
26397
|
projectSettingsToolDomain,
|
|
25297
|
-
navigationToolDomain
|
|
26398
|
+
navigationToolDomain,
|
|
26399
|
+
smartObjectsToolDomain,
|
|
26400
|
+
massToolDomain
|
|
25298
26401
|
];
|
|
25299
26402
|
//#endregion
|
|
25300
26403
|
//#region src/mcpTools.ts
|