@uemcp/server 1.11.0 → 1.12.1
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 +35 -1
- package/dist/index.mjs +1140 -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,368 @@ 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
|
+
"spawn_cannot_return"
|
|
11267
|
+
];
|
|
11268
|
+
const BRIDGE_NAV_SPAWN_POINT_KINDS = ["player_start", "actor"];
|
|
11269
|
+
const bridgeDiagnoseNavmeshRequestSchema = z.object({
|
|
11270
|
+
includePlayerStarts: z.boolean().default(true),
|
|
11271
|
+
maxIslands: z.number().int().min(1).max(64).default(16),
|
|
11272
|
+
navMeshActorPath: actorPathSchema.optional(),
|
|
11273
|
+
requestId: requestIdSchema,
|
|
11274
|
+
spawnActorPaths: z.array(actorPathSchema).max(64).default([]),
|
|
11275
|
+
type: z.literal(BRIDGE_DIAGNOSE_NAVMESH_REQUEST_TYPE),
|
|
11276
|
+
version: z.literal(2)
|
|
11277
|
+
});
|
|
11278
|
+
const navDiagnosticIslandSchema = z.object({
|
|
11279
|
+
area: z.number().min(0),
|
|
11280
|
+
bounds: z.object({
|
|
11281
|
+
max: navPointSchema,
|
|
11282
|
+
min: navPointSchema
|
|
11283
|
+
}),
|
|
11284
|
+
index: z.number().int().min(0),
|
|
11285
|
+
polyCount: z.number().int().min(0),
|
|
11286
|
+
spawnPointCount: z.number().int().min(0)
|
|
11287
|
+
});
|
|
11288
|
+
const navDiagnosticSpawnPointSchema = z.object({
|
|
11289
|
+
actorPath: z.string(),
|
|
11290
|
+
error: z.string().optional(),
|
|
11291
|
+
islandIndex: z.number().int().min(0).optional(),
|
|
11292
|
+
kind: z.enum(BRIDGE_NAV_SPAWN_POINT_KINDS),
|
|
11293
|
+
location: navPointSchema,
|
|
11294
|
+
onNavMesh: z.boolean(),
|
|
11295
|
+
pathLength: z.number().optional(),
|
|
11296
|
+
projectedLocation: navPointSchema.optional(),
|
|
11297
|
+
reachableFromAnchor: z.boolean(),
|
|
11298
|
+
returnsToAnchor: z.boolean()
|
|
11299
|
+
});
|
|
11300
|
+
const navDiagnosticIssueSchema = z.object({
|
|
11301
|
+
actorPath: z.string().optional(),
|
|
11302
|
+
code: z.enum(BRIDGE_NAV_DIAGNOSTIC_ISSUE_CODES),
|
|
11303
|
+
islandIndex: z.number().int().min(0).optional(),
|
|
11304
|
+
message: z.string()
|
|
11305
|
+
});
|
|
11306
|
+
const bridgeDiagnoseNavmeshSuccessResponseSchema = z.object({
|
|
11307
|
+
anchorActorPath: z.string().optional(),
|
|
11308
|
+
healthy: z.boolean(),
|
|
11309
|
+
islandCount: z.number().int().min(0),
|
|
11310
|
+
islands: z.array(navDiagnosticIslandSchema).max(64),
|
|
11311
|
+
islandsTruncated: z.boolean(),
|
|
11312
|
+
issueCount: z.number().int().min(0),
|
|
11313
|
+
issues: z.array(navDiagnosticIssueSchema).max(64),
|
|
11314
|
+
issuesTruncated: z.boolean(),
|
|
11315
|
+
message: nonEmptyStringSchema.optional(),
|
|
11316
|
+
navBoundsVolumeCount: z.number().int().min(0),
|
|
11317
|
+
navMeshActorPath: z.string(),
|
|
11318
|
+
ok: z.literal(true),
|
|
11319
|
+
polyCount: z.number().int().min(0),
|
|
11320
|
+
requestId: requestIdSchema,
|
|
11321
|
+
spawnPointCount: z.number().int().min(0),
|
|
11322
|
+
spawnPoints: z.array(navDiagnosticSpawnPointSchema).max(64),
|
|
11323
|
+
spawnPointsTruncated: z.boolean(),
|
|
11324
|
+
state: navQueryStateSchema,
|
|
11325
|
+
type: z.literal(BRIDGE_DIAGNOSE_NAVMESH_REQUEST_TYPE),
|
|
11326
|
+
version: z.literal(2)
|
|
11327
|
+
});
|
|
11328
|
+
const bridgeDiagnoseNavmeshResponseSchema = z.union([bridgeDiagnoseNavmeshSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
11329
|
+
function createBridgeDiagnoseNavmeshRequest(options = {}, requestId = randomUUID()) {
|
|
11330
|
+
return bridgeDiagnoseNavmeshRequestSchema.parse({
|
|
11331
|
+
includePlayerStarts: options.includePlayerStarts,
|
|
11332
|
+
maxIslands: options.maxIslands,
|
|
11333
|
+
navMeshActorPath: options.navMeshActorPath,
|
|
11334
|
+
requestId,
|
|
11335
|
+
spawnActorPaths: options.spawnActorPaths,
|
|
11336
|
+
type: BRIDGE_DIAGNOSE_NAVMESH_REQUEST_TYPE,
|
|
11337
|
+
version: 2
|
|
11338
|
+
});
|
|
11339
|
+
}
|
|
11340
|
+
//#endregion
|
|
11341
|
+
//#region src/protocol/smartObjects.ts
|
|
11342
|
+
const BRIDGE_CREATE_SMART_OBJECT_DEFINITION_REQUEST_TYPE = "create_smart_object_definition";
|
|
11343
|
+
const BRIDGE_GET_SMART_OBJECT_DEFINITION_REQUEST_TYPE = "get_smart_object_definition";
|
|
11344
|
+
const BRIDGE_ADD_SMART_OBJECT_COMPONENT_REQUEST_TYPE = "add_smart_object_component";
|
|
11345
|
+
const BRIDGE_SMART_OBJECT_COMPONENT_TARGETS = ["blueprint", "actor"];
|
|
11346
|
+
const bridgeSmartObjectBehaviorDefinitionSchema = z.object({
|
|
11347
|
+
behaviorClass: assetPathSchema,
|
|
11348
|
+
params: instancedObjectParamsSchema
|
|
11349
|
+
});
|
|
11350
|
+
const activityTagsSchema = z.array(gameplayTagNameSchema).max(16).default([]);
|
|
11351
|
+
const behaviorDefinitionsSchema = z.array(bridgeSmartObjectBehaviorDefinitionSchema).max(8).default([]);
|
|
11352
|
+
const bridgeSmartObjectSlotSchema = z.object({
|
|
11353
|
+
activityTags: activityTagsSchema,
|
|
11354
|
+
behaviorDefinitions: behaviorDefinitionsSchema,
|
|
11355
|
+
enabled: z.boolean().default(true),
|
|
11356
|
+
name: requiredBoundedStringSchema.optional(),
|
|
11357
|
+
offset: bridgeVectorSchema.optional(),
|
|
11358
|
+
rotation: bridgeRotatorSchema.optional()
|
|
11359
|
+
});
|
|
11360
|
+
const bridgeCreateSmartObjectDefinitionRequestSchema = z.object({
|
|
11361
|
+
activityTags: activityTagsSchema,
|
|
11362
|
+
assetName: assetNameSchema,
|
|
11363
|
+
defaultBehaviorDefinitions: behaviorDefinitionsSchema,
|
|
11364
|
+
packagePath: contentPathSchema,
|
|
11365
|
+
requestId: requestIdSchema,
|
|
11366
|
+
slots: z.array(bridgeSmartObjectSlotSchema).min(1).max(32),
|
|
11367
|
+
type: z.literal(BRIDGE_CREATE_SMART_OBJECT_DEFINITION_REQUEST_TYPE),
|
|
11368
|
+
version: z.literal(2)
|
|
11369
|
+
});
|
|
11370
|
+
const bridgeGetSmartObjectDefinitionRequestSchema = z.object({
|
|
11371
|
+
assetPath: assetPathSchema,
|
|
11372
|
+
requestId: requestIdSchema,
|
|
11373
|
+
type: z.literal(BRIDGE_GET_SMART_OBJECT_DEFINITION_REQUEST_TYPE),
|
|
11374
|
+
version: z.literal(2)
|
|
11375
|
+
});
|
|
11376
|
+
const bridgeAddSmartObjectComponentRequestFieldsSchema = z.object({
|
|
11377
|
+
actorPath: actorPathSchema.optional(),
|
|
11378
|
+
blueprintPath: assetPathSchema.optional(),
|
|
11379
|
+
componentName: requiredBoundedStringSchema.optional(),
|
|
11380
|
+
definitionPath: assetPathSchema,
|
|
11381
|
+
requestId: requestIdSchema,
|
|
11382
|
+
type: z.literal(BRIDGE_ADD_SMART_OBJECT_COMPONENT_REQUEST_TYPE),
|
|
11383
|
+
version: z.literal(2)
|
|
11384
|
+
});
|
|
11385
|
+
const bridgeAddSmartObjectComponentRequestSchema = bridgeAddSmartObjectComponentRequestFieldsSchema.refine((request) => request.actorPath === void 0 !== (request.blueprintPath === void 0), {
|
|
11386
|
+
message: "An add_smart_object_component request names exactly one of blueprintPath or actorPath.",
|
|
11387
|
+
path: ["blueprintPath"]
|
|
11388
|
+
});
|
|
11389
|
+
const bridgeSmartObjectSlotReportSchema = z.object({
|
|
11390
|
+
activityTags: z.array(z.string()),
|
|
11391
|
+
behaviorDefinitions: z.array(z.string()),
|
|
11392
|
+
enabled: z.boolean(),
|
|
11393
|
+
index: z.number().int().min(0),
|
|
11394
|
+
name: z.string(),
|
|
11395
|
+
offset: bridgeVectorSchema,
|
|
11396
|
+
rotation: bridgeRotatorSchema
|
|
11397
|
+
});
|
|
11398
|
+
const smartObjectDefinitionReportFields = {
|
|
11399
|
+
activityTags: z.array(z.string()),
|
|
11400
|
+
defaultBehaviorDefinitions: z.array(z.string()),
|
|
11401
|
+
slots: z.array(bridgeSmartObjectSlotReportSchema),
|
|
11402
|
+
valid: z.boolean(),
|
|
11403
|
+
validationMessages: z.array(z.string()).max(32)
|
|
11404
|
+
};
|
|
11405
|
+
const bridgeCreateSmartObjectDefinitionSuccessResponseSchema = z.object({
|
|
11406
|
+
...createdUserAssetResponseFields,
|
|
11407
|
+
...smartObjectDefinitionReportFields,
|
|
11408
|
+
type: z.literal(BRIDGE_CREATE_SMART_OBJECT_DEFINITION_REQUEST_TYPE)
|
|
11409
|
+
});
|
|
11410
|
+
const bridgeGetSmartObjectDefinitionSuccessResponseSchema = z.object({
|
|
11411
|
+
...smartObjectDefinitionReportFields,
|
|
11412
|
+
assetPath: z.string(),
|
|
11413
|
+
message: nonEmptyStringSchema.optional(),
|
|
11414
|
+
ok: z.literal(true),
|
|
11415
|
+
requestId: requestIdSchema,
|
|
11416
|
+
state: aiReportStateSchema,
|
|
11417
|
+
type: z.literal(BRIDGE_GET_SMART_OBJECT_DEFINITION_REQUEST_TYPE),
|
|
11418
|
+
version: z.literal(2)
|
|
11419
|
+
});
|
|
11420
|
+
const bridgeAddSmartObjectComponentSuccessResponseSchema = z.object({
|
|
11421
|
+
componentName: z.string(),
|
|
11422
|
+
created: z.boolean(),
|
|
11423
|
+
definitionPath: z.string(),
|
|
11424
|
+
definitionValid: z.boolean(),
|
|
11425
|
+
message: nonEmptyStringSchema.optional(),
|
|
11426
|
+
ok: z.literal(true),
|
|
11427
|
+
packageDirty: z.boolean(),
|
|
11428
|
+
requestId: requestIdSchema,
|
|
11429
|
+
state: creativeEditStateSchema,
|
|
11430
|
+
target: z.enum(BRIDGE_SMART_OBJECT_COMPONENT_TARGETS),
|
|
11431
|
+
targetPath: z.string(),
|
|
11432
|
+
type: z.literal(BRIDGE_ADD_SMART_OBJECT_COMPONENT_REQUEST_TYPE),
|
|
11433
|
+
version: z.literal(2)
|
|
11434
|
+
});
|
|
11435
|
+
const bridgeCreateSmartObjectDefinitionResponseSchema = z.union([bridgeCreateSmartObjectDefinitionSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
11436
|
+
const bridgeGetSmartObjectDefinitionResponseSchema = z.union([bridgeGetSmartObjectDefinitionSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
11437
|
+
const bridgeAddSmartObjectComponentResponseSchema = z.union([bridgeAddSmartObjectComponentSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
11438
|
+
function createBridgeCreateSmartObjectDefinitionRequest(assetName, packagePath, slots, options = {}, requestId = randomUUID()) {
|
|
11439
|
+
return bridgeCreateSmartObjectDefinitionRequestSchema.parse({
|
|
11440
|
+
activityTags: options.activityTags,
|
|
11441
|
+
assetName,
|
|
11442
|
+
defaultBehaviorDefinitions: options.defaultBehaviorDefinitions,
|
|
11443
|
+
packagePath,
|
|
11444
|
+
requestId,
|
|
11445
|
+
slots,
|
|
11446
|
+
type: BRIDGE_CREATE_SMART_OBJECT_DEFINITION_REQUEST_TYPE,
|
|
11447
|
+
version: 2
|
|
11448
|
+
});
|
|
11449
|
+
}
|
|
11450
|
+
function createBridgeGetSmartObjectDefinitionRequest(assetPath, requestId = randomUUID()) {
|
|
11451
|
+
return bridgeGetSmartObjectDefinitionRequestSchema.parse({
|
|
11452
|
+
assetPath,
|
|
11453
|
+
requestId,
|
|
11454
|
+
type: BRIDGE_GET_SMART_OBJECT_DEFINITION_REQUEST_TYPE,
|
|
11455
|
+
version: 2
|
|
11456
|
+
});
|
|
11457
|
+
}
|
|
11458
|
+
function createBridgeAddSmartObjectComponentRequest(definitionPath, target, options = {}, requestId = randomUUID()) {
|
|
11459
|
+
return bridgeAddSmartObjectComponentRequestSchema.parse({
|
|
11460
|
+
actorPath: target.actorPath,
|
|
11461
|
+
blueprintPath: target.blueprintPath,
|
|
11462
|
+
componentName: options.componentName,
|
|
11463
|
+
definitionPath,
|
|
11464
|
+
requestId,
|
|
11465
|
+
type: BRIDGE_ADD_SMART_OBJECT_COMPONENT_REQUEST_TYPE,
|
|
11466
|
+
version: 2
|
|
11467
|
+
});
|
|
11468
|
+
}
|
|
11469
|
+
//#endregion
|
|
11470
|
+
//#region src/protocol/mass.ts
|
|
11471
|
+
const BRIDGE_CREATE_MASS_ENTITY_CONFIG_REQUEST_TYPE = "create_mass_entity_config";
|
|
11472
|
+
const BRIDGE_EDIT_MASS_ENTITY_CONFIG_REQUEST_TYPE = "edit_mass_entity_config";
|
|
11473
|
+
const BRIDGE_GET_MASS_ENTITY_CONFIG_REQUEST_TYPE = "get_mass_entity_config";
|
|
11474
|
+
const BRIDGE_VALIDATE_MASS_ENTITY_CONFIG_REQUEST_TYPE = "validate_mass_entity_config";
|
|
11475
|
+
const BRIDGE_MASS_TRAIT_OPERATIONS = [
|
|
11476
|
+
"add",
|
|
11477
|
+
"remove",
|
|
11478
|
+
"set"
|
|
11479
|
+
];
|
|
11480
|
+
const BRIDGE_MASS_READ_STATES = ["reported", "unsupported"];
|
|
11481
|
+
const BRIDGE_MASS_VALIDATION_SEVERITIES = ["error", "warning"];
|
|
11482
|
+
const massReadStateSchema = z.enum(BRIDGE_MASS_READ_STATES);
|
|
11483
|
+
const traitClassSchema = z.string().trim().min(1).max(512);
|
|
11484
|
+
const bridgeMassTraitEditSchema = z.object({
|
|
11485
|
+
operation: z.enum(BRIDGE_MASS_TRAIT_OPERATIONS),
|
|
11486
|
+
properties: z.array(bridgeAssetPropertyEntrySchema).max(32).optional(),
|
|
11487
|
+
traitClass: traitClassSchema
|
|
11488
|
+
}).superRefine((edit, context) => {
|
|
11489
|
+
const count = edit.properties?.length ?? 0;
|
|
11490
|
+
if (edit.operation === "set" && count === 0) context.addIssue({
|
|
11491
|
+
code: z.ZodIssueCode.custom,
|
|
11492
|
+
message: "A 'set' trait edit must carry at least one property.",
|
|
11493
|
+
path: ["properties"]
|
|
11494
|
+
});
|
|
11495
|
+
if (edit.operation === "remove" && count > 0) context.addIssue({
|
|
11496
|
+
code: z.ZodIssueCode.custom,
|
|
11497
|
+
message: "A 'remove' trait edit cannot carry properties.",
|
|
11498
|
+
path: ["properties"]
|
|
11499
|
+
});
|
|
11500
|
+
});
|
|
11501
|
+
const bridgeCreateMassEntityConfigRequestSchema = z.object({
|
|
11502
|
+
assetName: assetNameSchema,
|
|
11503
|
+
packagePath: contentPathSchema,
|
|
11504
|
+
parentConfigPath: assetPathSchema.optional(),
|
|
11505
|
+
requestId: requestIdSchema,
|
|
11506
|
+
type: z.literal(BRIDGE_CREATE_MASS_ENTITY_CONFIG_REQUEST_TYPE),
|
|
11507
|
+
version: z.literal(2)
|
|
11508
|
+
});
|
|
11509
|
+
const bridgeEditMassEntityConfigRequestSchema = z.object({
|
|
11510
|
+
assetPath: assetPathSchema,
|
|
11511
|
+
edits: z.array(bridgeMassTraitEditSchema).min(1).max(16),
|
|
11512
|
+
requestId: requestIdSchema,
|
|
11513
|
+
type: z.literal(BRIDGE_EDIT_MASS_ENTITY_CONFIG_REQUEST_TYPE),
|
|
11514
|
+
version: z.literal(2)
|
|
11515
|
+
});
|
|
11516
|
+
const bridgeGetMassEntityConfigRequestSchema = z.object({
|
|
11517
|
+
assetPath: assetPathSchema,
|
|
11518
|
+
requestId: requestIdSchema,
|
|
11519
|
+
type: z.literal(BRIDGE_GET_MASS_ENTITY_CONFIG_REQUEST_TYPE),
|
|
11520
|
+
version: z.literal(2)
|
|
11521
|
+
});
|
|
11522
|
+
const bridgeValidateMassEntityConfigRequestSchema = z.object({
|
|
11523
|
+
assetPath: assetPathSchema,
|
|
11524
|
+
requestId: requestIdSchema,
|
|
11525
|
+
type: z.literal(BRIDGE_VALIDATE_MASS_ENTITY_CONFIG_REQUEST_TYPE),
|
|
11526
|
+
version: z.literal(2)
|
|
11527
|
+
});
|
|
11528
|
+
const bridgeCreateMassEntityConfigSuccessResponseSchema = z.object({
|
|
11529
|
+
...createdUserAssetResponseFields,
|
|
11530
|
+
parentConfigPath: z.string().optional(),
|
|
11531
|
+
type: z.literal(BRIDGE_CREATE_MASS_ENTITY_CONFIG_REQUEST_TYPE)
|
|
11532
|
+
});
|
|
11533
|
+
const bridgeEditMassEntityConfigSuccessResponseSchema = z.object({
|
|
11534
|
+
...authoringBatchResponseFields,
|
|
11535
|
+
traits: z.array(z.string()).max(64),
|
|
11536
|
+
type: z.literal(BRIDGE_EDIT_MASS_ENTITY_CONFIG_REQUEST_TYPE)
|
|
11537
|
+
});
|
|
11538
|
+
const bridgeMassTraitReportSchema = z.object({
|
|
11539
|
+
index: z.number().int().min(0),
|
|
11540
|
+
properties: z.record(z.string(), z.string()),
|
|
11541
|
+
traitClass: z.string(),
|
|
11542
|
+
traitName: z.string()
|
|
11543
|
+
});
|
|
11544
|
+
const bridgeGetMassEntityConfigSuccessResponseSchema = z.object({
|
|
11545
|
+
assetPath: z.string(),
|
|
11546
|
+
message: nonEmptyStringSchema.optional(),
|
|
11547
|
+
ok: z.literal(true),
|
|
11548
|
+
parentConfigPath: z.string().optional(),
|
|
11549
|
+
requestId: requestIdSchema,
|
|
11550
|
+
state: massReadStateSchema,
|
|
11551
|
+
traits: z.array(bridgeMassTraitReportSchema).max(64),
|
|
11552
|
+
truncated: z.boolean(),
|
|
11553
|
+
type: z.literal(BRIDGE_GET_MASS_ENTITY_CONFIG_REQUEST_TYPE),
|
|
11554
|
+
version: z.literal(2)
|
|
11555
|
+
});
|
|
11556
|
+
const bridgeMassValidationMessageSchema = z.object({
|
|
11557
|
+
category: z.string(),
|
|
11558
|
+
severity: z.enum(BRIDGE_MASS_VALIDATION_SEVERITIES),
|
|
11559
|
+
text: z.string()
|
|
11560
|
+
});
|
|
11561
|
+
const bridgeValidateMassEntityConfigSuccessResponseSchema = z.object({
|
|
11562
|
+
assetPath: z.string(),
|
|
11563
|
+
errorCount: z.number().int().min(0),
|
|
11564
|
+
message: nonEmptyStringSchema.optional(),
|
|
11565
|
+
messages: z.array(bridgeMassValidationMessageSchema).max(32),
|
|
11566
|
+
ok: z.literal(true),
|
|
11567
|
+
requestId: requestIdSchema,
|
|
11568
|
+
state: massReadStateSchema,
|
|
11569
|
+
truncated: z.boolean(),
|
|
11570
|
+
type: z.literal(BRIDGE_VALIDATE_MASS_ENTITY_CONFIG_REQUEST_TYPE),
|
|
11571
|
+
valid: z.boolean(),
|
|
11572
|
+
version: z.literal(2),
|
|
11573
|
+
warningCount: z.number().int().min(0)
|
|
11574
|
+
});
|
|
11575
|
+
const bridgeCreateMassEntityConfigResponseSchema = z.union([bridgeCreateMassEntityConfigSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
11576
|
+
const bridgeEditMassEntityConfigResponseSchema = z.union([bridgeEditMassEntityConfigSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
11577
|
+
const bridgeGetMassEntityConfigResponseSchema = z.union([bridgeGetMassEntityConfigSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
11578
|
+
const bridgeValidateMassEntityConfigResponseSchema = z.union([bridgeValidateMassEntityConfigSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
11579
|
+
function createBridgeCreateMassEntityConfigRequest(assetName, packagePath, options = {}, requestId = randomUUID()) {
|
|
11580
|
+
return bridgeCreateMassEntityConfigRequestSchema.parse({
|
|
11581
|
+
assetName,
|
|
11582
|
+
packagePath,
|
|
11583
|
+
parentConfigPath: options.parentConfigPath,
|
|
11584
|
+
requestId,
|
|
11585
|
+
type: BRIDGE_CREATE_MASS_ENTITY_CONFIG_REQUEST_TYPE,
|
|
11586
|
+
version: 2
|
|
11587
|
+
});
|
|
11588
|
+
}
|
|
11589
|
+
function createBridgeEditMassEntityConfigRequest(assetPath, edits, requestId = randomUUID()) {
|
|
11590
|
+
return bridgeEditMassEntityConfigRequestSchema.parse({
|
|
11591
|
+
assetPath,
|
|
11592
|
+
edits,
|
|
11593
|
+
requestId,
|
|
11594
|
+
type: BRIDGE_EDIT_MASS_ENTITY_CONFIG_REQUEST_TYPE,
|
|
11595
|
+
version: 2
|
|
11596
|
+
});
|
|
11597
|
+
}
|
|
11598
|
+
function createBridgeGetMassEntityConfigRequest(assetPath, requestId = randomUUID()) {
|
|
11599
|
+
return bridgeGetMassEntityConfigRequestSchema.parse({
|
|
11600
|
+
assetPath,
|
|
11601
|
+
requestId,
|
|
11602
|
+
type: BRIDGE_GET_MASS_ENTITY_CONFIG_REQUEST_TYPE,
|
|
11603
|
+
version: 2
|
|
11604
|
+
});
|
|
11605
|
+
}
|
|
11606
|
+
function createBridgeValidateMassEntityConfigRequest(assetPath, requestId = randomUUID()) {
|
|
11607
|
+
return bridgeValidateMassEntityConfigRequestSchema.parse({
|
|
11608
|
+
assetPath,
|
|
11609
|
+
requestId,
|
|
11610
|
+
type: BRIDGE_VALIDATE_MASS_ENTITY_CONFIG_REQUEST_TYPE,
|
|
11611
|
+
version: 2
|
|
11612
|
+
});
|
|
11613
|
+
}
|
|
11018
11614
|
//#endregion
|
|
11019
11615
|
//#region src/version.ts
|
|
11020
|
-
const SERVER_VERSION = "1.
|
|
11616
|
+
const SERVER_VERSION = "1.12.1";
|
|
11021
11617
|
//#endregion
|
|
11022
11618
|
//#region src/bridgeSocketClient.ts
|
|
11023
11619
|
var BridgeSocketError = class extends Error {
|
|
@@ -11253,6 +11849,9 @@ async function sendBridgeSetPinDefaultRequest(request, options) {
|
|
|
11253
11849
|
async function sendBridgeListAvailableNodesRequest(request, options) {
|
|
11254
11850
|
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeListAvailableNodesResponseSchema, request.requestId);
|
|
11255
11851
|
}
|
|
11852
|
+
async function sendBridgeLayoutGraphRequest(request, options) {
|
|
11853
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeLayoutGraphResponseSchema, request.requestId);
|
|
11854
|
+
}
|
|
11256
11855
|
async function sendBridgeSetViewportCameraRequest(request, options) {
|
|
11257
11856
|
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeSetViewportCameraResponseSchema, request.requestId);
|
|
11258
11857
|
}
|
|
@@ -11973,6 +12572,36 @@ async function sendBridgeFindPathRequest(request, options) {
|
|
|
11973
12572
|
async function sendBridgeTestReachabilityRequest(request, options) {
|
|
11974
12573
|
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeTestReachabilityResponseSchema, request.requestId);
|
|
11975
12574
|
}
|
|
12575
|
+
async function sendBridgeCreateSmartObjectDefinitionRequest(request, options) {
|
|
12576
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeCreateSmartObjectDefinitionResponseSchema, request.requestId);
|
|
12577
|
+
}
|
|
12578
|
+
async function sendBridgeGetSmartObjectDefinitionRequest(request, options) {
|
|
12579
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetSmartObjectDefinitionResponseSchema, request.requestId);
|
|
12580
|
+
}
|
|
12581
|
+
async function sendBridgeAddSmartObjectComponentRequest(request, options) {
|
|
12582
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeAddSmartObjectComponentResponseSchema, request.requestId);
|
|
12583
|
+
}
|
|
12584
|
+
async function sendBridgeCreateMassEntityConfigRequest(request, options) {
|
|
12585
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeCreateMassEntityConfigResponseSchema, request.requestId);
|
|
12586
|
+
}
|
|
12587
|
+
async function sendBridgeEditMassEntityConfigRequest(request, options) {
|
|
12588
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeEditMassEntityConfigResponseSchema, request.requestId);
|
|
12589
|
+
}
|
|
12590
|
+
async function sendBridgeGetMassEntityConfigRequest(request, options) {
|
|
12591
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetMassEntityConfigResponseSchema, request.requestId);
|
|
12592
|
+
}
|
|
12593
|
+
async function sendBridgeValidateMassEntityConfigRequest(request, options) {
|
|
12594
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeValidateMassEntityConfigResponseSchema, request.requestId);
|
|
12595
|
+
}
|
|
12596
|
+
async function sendBridgeDiagnoseNavmeshRequest(request, options) {
|
|
12597
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeDiagnoseNavmeshResponseSchema, request.requestId);
|
|
12598
|
+
}
|
|
12599
|
+
async function sendBridgeUpdateStateTreeElementsRequest(request, options) {
|
|
12600
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeUpdateStateTreeElementsResponseSchema, request.requestId);
|
|
12601
|
+
}
|
|
12602
|
+
async function sendBridgeRemoveStateTreeElementsRequest(request, options) {
|
|
12603
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeRemoveStateTreeElementsResponseSchema, request.requestId);
|
|
12604
|
+
}
|
|
11976
12605
|
//#endregion
|
|
11977
12606
|
//#region src/enginePing.ts
|
|
11978
12607
|
async function pingRegistryEntry$1(entry, options) {
|
|
@@ -18799,6 +19428,7 @@ const debuggerToolDomain = {
|
|
|
18799
19428
|
};
|
|
18800
19429
|
//#endregion
|
|
18801
19430
|
//#region src/traceAnalysis.ts
|
|
19431
|
+
const LLM_TAG_COUNTER_PATTERN = "STAT_*LLM";
|
|
18802
19432
|
const SECONDS_TO_MS = 1e3;
|
|
18803
19433
|
const FRAME_ROOT_TIMER_NAMES = /* @__PURE__ */ new Set(["FEngineLoop::Tick"]);
|
|
18804
19434
|
function parseCsvRows(text) {
|
|
@@ -18891,6 +19521,9 @@ function summarizeTimerStatistics(rows, maxScopes) {
|
|
|
18891
19521
|
if (count !== void 0) scope.count = count;
|
|
18892
19522
|
scopes.push(scope);
|
|
18893
19523
|
}
|
|
19524
|
+
return rankScopes(scopes, maxScopes);
|
|
19525
|
+
}
|
|
19526
|
+
function rankScopes(scopes, maxScopes) {
|
|
18894
19527
|
const byInclusiveTime = [...scopes].sort((left, right) => right.inclusiveTimeMs - left.inclusiveTimeMs);
|
|
18895
19528
|
return {
|
|
18896
19529
|
byExclusiveTime: [...scopes].sort((left, right) => right.exclusiveTimeMs - left.exclusiveTimeMs).slice(0, maxScopes),
|
|
@@ -18902,18 +19535,20 @@ function summarizeTimerStatistics(rows, maxScopes) {
|
|
|
18902
19535
|
function isGpuThread(threadName) {
|
|
18903
19536
|
return threadName.toUpperCase().includes("GPU");
|
|
18904
19537
|
}
|
|
18905
|
-
async function
|
|
19538
|
+
async function forEachTimingEvent(lines, visit) {
|
|
18906
19539
|
let headers;
|
|
18907
19540
|
let threadIndex = -1;
|
|
18908
19541
|
let timerIndex = -1;
|
|
18909
19542
|
let durationIndex = -1;
|
|
18910
19543
|
let startIndex = -1;
|
|
18911
19544
|
let depthIndex = -1;
|
|
18912
|
-
|
|
18913
|
-
|
|
18914
|
-
|
|
18915
|
-
|
|
18916
|
-
|
|
19545
|
+
const event = {
|
|
19546
|
+
depth: 0,
|
|
19547
|
+
durationMs: 0,
|
|
19548
|
+
startTimeMs: 0,
|
|
19549
|
+
threadName: "",
|
|
19550
|
+
timerName: ""
|
|
19551
|
+
};
|
|
18917
19552
|
for await (const rawLine of lines) {
|
|
18918
19553
|
const line = rawLine.trim();
|
|
18919
19554
|
if (line.length === 0) continue;
|
|
@@ -18926,36 +19561,160 @@ async function summarizeTimingEventStream(lines, options) {
|
|
|
18926
19561
|
durationIndex = columnIndex(headers, findColumn(headerRow, "Duration", "InclusiveTime"));
|
|
18927
19562
|
startIndex = columnIndex(headers, findColumn(headerRow, "StartTime", "Start"));
|
|
18928
19563
|
depthIndex = columnIndex(headers, findColumn(headerRow, "Depth"));
|
|
18929
|
-
if (threadIndex < 0 || durationIndex < 0)
|
|
19564
|
+
if (threadIndex < 0 || durationIndex < 0) return;
|
|
18930
19565
|
continue;
|
|
18931
19566
|
}
|
|
18932
19567
|
const duration = readNumber(values[durationIndex]);
|
|
18933
19568
|
const threadName = values[threadIndex];
|
|
18934
19569
|
if (duration === void 0 || threadName === void 0) continue;
|
|
18935
|
-
|
|
18936
|
-
|
|
18937
|
-
|
|
18938
|
-
|
|
18939
|
-
|
|
19570
|
+
event.depth = depthIndex < 0 ? 0 : readNumber(values[depthIndex]) ?? 0;
|
|
19571
|
+
event.durationMs = duration * SECONDS_TO_MS;
|
|
19572
|
+
event.startTimeMs = (startIndex < 0 ? 0 : readNumber(values[startIndex]) ?? 0) * SECONDS_TO_MS;
|
|
19573
|
+
event.threadName = threadName;
|
|
19574
|
+
event.timerName = timerIndex < 0 ? "" : values[timerIndex] ?? "";
|
|
19575
|
+
visit(event);
|
|
19576
|
+
}
|
|
19577
|
+
}
|
|
19578
|
+
var ScopeAncestry = class {
|
|
19579
|
+
names = [];
|
|
19580
|
+
threadName;
|
|
19581
|
+
enter(event) {
|
|
19582
|
+
if (event.threadName !== this.threadName) {
|
|
19583
|
+
this.threadName = event.threadName;
|
|
19584
|
+
this.names.length = 0;
|
|
18940
19585
|
}
|
|
18941
|
-
|
|
18942
|
-
|
|
18943
|
-
|
|
18944
|
-
|
|
19586
|
+
this.names.length = Math.min(this.names.length, event.depth);
|
|
19587
|
+
const parentName = event.depth > 0 ? this.names[event.depth - 1] : void 0;
|
|
19588
|
+
this.names[event.depth] = event.timerName;
|
|
19589
|
+
return parentName;
|
|
19590
|
+
}
|
|
19591
|
+
hasOpenAncestorNamed(event) {
|
|
19592
|
+
return this.names.slice(0, event.depth).includes(event.timerName);
|
|
19593
|
+
}
|
|
19594
|
+
};
|
|
19595
|
+
async function summarizeTimingEventStream(lines, options) {
|
|
19596
|
+
let cpuTimeMs = 0;
|
|
19597
|
+
let gpuTimeMs = 0;
|
|
19598
|
+
const frameDurationsMs = [];
|
|
19599
|
+
const worstHitches = [];
|
|
19600
|
+
let hitchCount = 0;
|
|
19601
|
+
const gpuScopeTotals = /* @__PURE__ */ new Map();
|
|
19602
|
+
const gpuAncestry = new ScopeAncestry();
|
|
19603
|
+
await forEachTimingEvent(lines, (event) => {
|
|
19604
|
+
if (isGpuThread(event.threadName)) {
|
|
19605
|
+
accumulateGpuScope(gpuScopeTotals, gpuAncestry, event);
|
|
19606
|
+
if (event.depth === 0) gpuTimeMs += event.durationMs;
|
|
19607
|
+
return;
|
|
19608
|
+
}
|
|
19609
|
+
if (event.depth !== 0) return;
|
|
19610
|
+
cpuTimeMs += event.durationMs;
|
|
19611
|
+
if (!FRAME_ROOT_TIMER_NAMES.has(event.timerName)) return;
|
|
19612
|
+
frameDurationsMs.push(event.durationMs);
|
|
19613
|
+
if (event.durationMs < options.hitchThresholdMs) return;
|
|
18945
19614
|
hitchCount += 1;
|
|
18946
19615
|
retainWorstHitch(worstHitches, options.maxHitches, {
|
|
18947
|
-
durationMs,
|
|
18948
|
-
startTimeMs:
|
|
19616
|
+
durationMs: event.durationMs,
|
|
19617
|
+
startTimeMs: event.startTimeMs,
|
|
19618
|
+
topScopes: []
|
|
18949
19619
|
});
|
|
18950
|
-
}
|
|
19620
|
+
});
|
|
18951
19621
|
return {
|
|
18952
19622
|
frames: summarizeFrameDurations(frameDurationsMs, worstHitches, hitchCount, options),
|
|
19623
|
+
gpuScopes: rankScopeTotals(gpuScopeTotals, options.maxScopes),
|
|
18953
19624
|
threads: {
|
|
18954
19625
|
cpuTimeMs,
|
|
18955
19626
|
gpuTimeMs
|
|
18956
19627
|
}
|
|
18957
19628
|
};
|
|
18958
19629
|
}
|
|
19630
|
+
function accumulateGpuScope(totals, ancestry, event) {
|
|
19631
|
+
const parentName = ancestry.enter(event);
|
|
19632
|
+
const scope = scopeTotalsFor(totals, event.timerName);
|
|
19633
|
+
scope.count += 1;
|
|
19634
|
+
scope.exclusiveTimeMs += event.durationMs;
|
|
19635
|
+
if (!ancestry.hasOpenAncestorNamed(event)) scope.inclusiveTimeMs += event.durationMs;
|
|
19636
|
+
if (parentName !== void 0) scopeTotalsFor(totals, parentName).exclusiveTimeMs -= event.durationMs;
|
|
19637
|
+
}
|
|
19638
|
+
function scopeTotalsFor(totals, name) {
|
|
19639
|
+
const existing = totals.get(name);
|
|
19640
|
+
if (existing !== void 0) return existing;
|
|
19641
|
+
const created = {
|
|
19642
|
+
count: 0,
|
|
19643
|
+
exclusiveTimeMs: 0,
|
|
19644
|
+
inclusiveTimeMs: 0
|
|
19645
|
+
};
|
|
19646
|
+
totals.set(name, created);
|
|
19647
|
+
return created;
|
|
19648
|
+
}
|
|
19649
|
+
function rankScopeTotals(totals, maxScopes) {
|
|
19650
|
+
return rankScopes([...totals].map(([name, scope]) => ({
|
|
19651
|
+
count: scope.count,
|
|
19652
|
+
exclusiveTimeMs: scope.exclusiveTimeMs,
|
|
19653
|
+
inclusiveTimeMs: scope.inclusiveTimeMs,
|
|
19654
|
+
name
|
|
19655
|
+
})), maxScopes);
|
|
19656
|
+
}
|
|
19657
|
+
const SCOPE_KEY_SEPARATOR = "\0";
|
|
19658
|
+
const IDLE_TIMER_NAMES = /* @__PURE__ */ new Set(["TaskWorkerIsLookingForWork", "WaitForTasks"]);
|
|
19659
|
+
async function attributeHitchScopes(lines, hitches, maxScopesPerHitch) {
|
|
19660
|
+
if (hitches.length === 0) return [];
|
|
19661
|
+
const windows = hitches.map((hitch) => ({
|
|
19662
|
+
endTimeMs: hitch.startTimeMs + hitch.durationMs,
|
|
19663
|
+
exclusiveByScope: /* @__PURE__ */ new Map(),
|
|
19664
|
+
hitch,
|
|
19665
|
+
startTimeMs: hitch.startTimeMs
|
|
19666
|
+
})).sort((left, right) => left.startTimeMs - right.startTimeMs);
|
|
19667
|
+
const ancestry = new ScopeAncestry();
|
|
19668
|
+
await forEachTimingEvent(lines, (event) => {
|
|
19669
|
+
if (isGpuThread(event.threadName)) return;
|
|
19670
|
+
const parentName = ancestry.enter(event);
|
|
19671
|
+
const eventEndMs = event.startTimeMs + event.durationMs;
|
|
19672
|
+
for (let index = firstWindowEndingAfter(windows, event.startTimeMs); index < windows.length && (windows[index]?.startTimeMs ?? Number.POSITIVE_INFINITY) < eventEndMs; index += 1) {
|
|
19673
|
+
const window = windows[index];
|
|
19674
|
+
if (window === void 0) break;
|
|
19675
|
+
const overlapMs = Math.min(eventEndMs, window.endTimeMs) - Math.max(event.startTimeMs, window.startTimeMs);
|
|
19676
|
+
if (overlapMs <= 0) continue;
|
|
19677
|
+
addScopeTime(window.exclusiveByScope, event.threadName, event.timerName, overlapMs);
|
|
19678
|
+
if (parentName !== void 0) addScopeTime(window.exclusiveByScope, event.threadName, parentName, -overlapMs);
|
|
19679
|
+
}
|
|
19680
|
+
});
|
|
19681
|
+
return hitches.map((hitch) => {
|
|
19682
|
+
const window = windows.find((candidate) => candidate.hitch === hitch);
|
|
19683
|
+
return {
|
|
19684
|
+
...hitch,
|
|
19685
|
+
topScopes: window === void 0 ? [] : topHitchScopes(window, maxScopesPerHitch)
|
|
19686
|
+
};
|
|
19687
|
+
});
|
|
19688
|
+
}
|
|
19689
|
+
function firstWindowEndingAfter(windows, timeMs) {
|
|
19690
|
+
let low = 0;
|
|
19691
|
+
let high = windows.length;
|
|
19692
|
+
while (low < high) {
|
|
19693
|
+
const middle = low + high >>> 1;
|
|
19694
|
+
if ((windows[middle]?.endTimeMs ?? Number.POSITIVE_INFINITY) <= timeMs) low = middle + 1;
|
|
19695
|
+
else high = middle;
|
|
19696
|
+
}
|
|
19697
|
+
return low;
|
|
19698
|
+
}
|
|
19699
|
+
function addScopeTime(exclusiveByScope, threadName, timerName, ms) {
|
|
19700
|
+
const key = `${threadName}${SCOPE_KEY_SEPARATOR}${timerName}`;
|
|
19701
|
+
exclusiveByScope.set(key, (exclusiveByScope.get(key) ?? 0) + ms);
|
|
19702
|
+
}
|
|
19703
|
+
function topHitchScopes(window, maxScopes) {
|
|
19704
|
+
const scopes = [];
|
|
19705
|
+
for (const [key, exclusiveTimeMs] of window.exclusiveByScope) {
|
|
19706
|
+
if (exclusiveTimeMs <= 1e-6) continue;
|
|
19707
|
+
const separatorAt = key.indexOf(SCOPE_KEY_SEPARATOR);
|
|
19708
|
+
const name = key.slice(separatorAt + 1);
|
|
19709
|
+
if (IDLE_TIMER_NAMES.has(name)) continue;
|
|
19710
|
+
scopes.push({
|
|
19711
|
+
exclusiveTimeMs,
|
|
19712
|
+
name,
|
|
19713
|
+
threadName: key.slice(0, separatorAt)
|
|
19714
|
+
});
|
|
19715
|
+
}
|
|
19716
|
+
return scopes.sort((left, right) => right.exclusiveTimeMs - left.exclusiveTimeMs).slice(0, maxScopes);
|
|
19717
|
+
}
|
|
18959
19718
|
function retainWorstHitch(worstHitches, maxHitches, hitch) {
|
|
18960
19719
|
if (worstHitches.length >= maxHitches) {
|
|
18961
19720
|
const weakest = worstHitches[worstHitches.length - 1];
|
|
@@ -18991,16 +19750,53 @@ function percentile(sortedValues, fraction) {
|
|
|
18991
19750
|
if (sortedValues.length === 0) return 0;
|
|
18992
19751
|
return sortedValues[Math.min(sortedValues.length - 1, Math.max(0, Math.ceil(fraction * sortedValues.length) - 1))] ?? 0;
|
|
18993
19752
|
}
|
|
19753
|
+
function llmTagNameFromCounter(counterName) {
|
|
19754
|
+
return counterName.replace(/^STAT_/u, "").replace(/LLM$/u, "");
|
|
19755
|
+
}
|
|
19756
|
+
async function summarizeMemoryTagCounter(name, lines) {
|
|
19757
|
+
let valueIndex = -1;
|
|
19758
|
+
let finalBytes;
|
|
19759
|
+
let peakBytes = Number.NEGATIVE_INFINITY;
|
|
19760
|
+
let sawHeader = false;
|
|
19761
|
+
for await (const rawLine of lines) {
|
|
19762
|
+
const line = rawLine.trim();
|
|
19763
|
+
if (line.length === 0) continue;
|
|
19764
|
+
const values = parseCsvLine(line);
|
|
19765
|
+
if (!sawHeader) {
|
|
19766
|
+
sawHeader = true;
|
|
19767
|
+
valueIndex = values.findIndex((header) => header.toLowerCase() === "value");
|
|
19768
|
+
if (valueIndex < 0) return;
|
|
19769
|
+
continue;
|
|
19770
|
+
}
|
|
19771
|
+
const value = readNumber(values[valueIndex]);
|
|
19772
|
+
if (value === void 0) continue;
|
|
19773
|
+
finalBytes = value;
|
|
19774
|
+
peakBytes = Math.max(peakBytes, value);
|
|
19775
|
+
}
|
|
19776
|
+
return finalBytes === void 0 ? void 0 : {
|
|
19777
|
+
finalBytes,
|
|
19778
|
+
name,
|
|
19779
|
+
peakBytes
|
|
19780
|
+
};
|
|
19781
|
+
}
|
|
19782
|
+
function rankMemoryTags(tags, maxTags) {
|
|
19783
|
+
return {
|
|
19784
|
+
tags: [...tags].sort((left, right) => right.peakBytes - left.peakBytes).slice(0, maxTags),
|
|
19785
|
+
totalTagCount: tags.length,
|
|
19786
|
+
truncated: tags.length > maxTags
|
|
19787
|
+
};
|
|
19788
|
+
}
|
|
18994
19789
|
//#endregion
|
|
18995
19790
|
//#region src/tools/diagnostics.ts
|
|
18996
19791
|
const ANALYZE_TRACE_DEFAULT_TIMEOUT_MS = 6e5;
|
|
18997
19792
|
const ANALYZE_TRACE_DEFAULT_HITCH_THRESHOLD_MS = 33.4;
|
|
18998
19793
|
const ANALYZE_TRACE_MAX_RESPONSE_BYTES = 32768;
|
|
19794
|
+
const LLM_COUNTER_FILE_PREFIX = "llm-";
|
|
18999
19795
|
const analyzeTraceInputSchema = {
|
|
19000
19796
|
engineVersion: engineVersionSchema,
|
|
19001
19797
|
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
19798
|
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)}).`),
|
|
19799
|
+
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
19800
|
projectPath: z.string().trim().min(1).optional().describe("Project whose EngineAssociation selects the analyzer engine. Omit when engineVersion is given."),
|
|
19005
19801
|
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
19802
|
tracePath: z.string().trim().min(1).describe("Path to the .utrace file produced by stop_insights_trace.")
|
|
@@ -19016,8 +19812,10 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
|
|
|
19016
19812
|
engineVersion: engine.engineVersion,
|
|
19017
19813
|
hitchThresholdMs,
|
|
19018
19814
|
hitches: [],
|
|
19815
|
+
memoryTags: [],
|
|
19019
19816
|
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
19817
|
state: "unsupported",
|
|
19818
|
+
topGpuScopes: [],
|
|
19021
19819
|
topScopesByExclusiveTime: [],
|
|
19022
19820
|
topScopesByInclusiveTime: [],
|
|
19023
19821
|
tracePath,
|
|
@@ -19029,7 +19827,11 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
|
|
|
19029
19827
|
const timingEventsPath = path.join(exportDirectory, "timing-events.csv");
|
|
19030
19828
|
const commandFilePath = path.join(exportDirectory, "export.rsp");
|
|
19031
19829
|
try {
|
|
19032
|
-
await context.writeFile(commandFilePath, [
|
|
19830
|
+
await context.writeFile(commandFilePath, [
|
|
19831
|
+
`TimingInsights.ExportTimerStatistics ${quoteConsoleArgument(timerStatisticsPath)}`,
|
|
19832
|
+
`TimingInsights.ExportTimingEvents ${quoteConsoleArgument(timingEventsPath)} -columns=ThreadName,TimerName,StartTime,Duration,Depth`,
|
|
19833
|
+
`TimingInsights.ExportCounterValues ${quoteConsoleArgument(path.join(exportDirectory, `${LLM_COUNTER_FILE_PREFIX}{counter}.csv`))} -counter=${LLM_TAG_COUNTER_PATTERN}`
|
|
19834
|
+
].join("\n"));
|
|
19033
19835
|
dependencies.logger.info({
|
|
19034
19836
|
engineVersion: engine.engineVersion,
|
|
19035
19837
|
tracePath
|
|
@@ -19049,16 +19851,24 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
|
|
|
19049
19851
|
});
|
|
19050
19852
|
if (run.timedOut) throw new EngineToolchainError(`Unreal Insights did not finish analyzing ${tracePath} within ${String(timeoutMs)}ms; raise timeoutMs or trim the trace.`);
|
|
19051
19853
|
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
|
|
19854
|
+
const maxScopes = input.maxScopes ?? 20;
|
|
19855
|
+
const scopeSummaries = summarizeTimerStatistics(await readCsvRows(timerStatisticsPath, context), maxScopes);
|
|
19856
|
+
const hasTimingEvents = await context.fileExists(timingEventsPath);
|
|
19857
|
+
const readTimingEventLines = () => hasTimingEvents ? context.readTextLines(timingEventsPath) : emptyTextLines();
|
|
19858
|
+
const timingEvents = await summarizeTimingEventStream(readTimingEventLines(), {
|
|
19054
19859
|
hitchThresholdMs,
|
|
19055
|
-
maxHitches: input.maxHitches ?? 10
|
|
19860
|
+
maxHitches: input.maxHitches ?? 10,
|
|
19861
|
+
maxScopes
|
|
19056
19862
|
});
|
|
19057
19863
|
const frames = timingEvents.frames;
|
|
19058
19864
|
const threadTimes = timingEvents.threads;
|
|
19865
|
+
const hitches = await attributeHitchScopes(readTimingEventLines(), frames.hitches, 5);
|
|
19866
|
+
const memoryTags = await summarizeMemoryTags(exportDirectory, maxScopes, context);
|
|
19059
19867
|
const truncated = [];
|
|
19060
19868
|
if (scopeSummaries.truncated) truncated.push("topScopes");
|
|
19061
19869
|
if (frames.hitchesTruncated) truncated.push("hitches");
|
|
19870
|
+
if (timingEvents.gpuScopes.truncated) truncated.push("topGpuScopes");
|
|
19871
|
+
if (memoryTags.truncated) truncated.push("memoryTags");
|
|
19062
19872
|
const result = {
|
|
19063
19873
|
analyzerPath,
|
|
19064
19874
|
cpuTimeMs: threadTimes.cpuTimeMs,
|
|
@@ -19068,10 +19878,14 @@ async function analyzeTrace(input, dependencies, context = createEngineToolchain
|
|
|
19068
19878
|
frameCount: frames.frameCount,
|
|
19069
19879
|
gpuTimeMs: threadTimes.gpuTimeMs,
|
|
19070
19880
|
hitchThresholdMs,
|
|
19071
|
-
hitches
|
|
19881
|
+
hitches,
|
|
19882
|
+
memoryTags: memoryTags.tags,
|
|
19072
19883
|
state: "analyzed",
|
|
19884
|
+
topGpuScopes: timingEvents.gpuScopes.byExclusiveTime,
|
|
19073
19885
|
topScopesByExclusiveTime: scopeSummaries.byExclusiveTime,
|
|
19074
19886
|
topScopesByInclusiveTime: scopeSummaries.byInclusiveTime,
|
|
19887
|
+
totalGpuScopeCount: timingEvents.gpuScopes.totalScopeCount,
|
|
19888
|
+
totalMemoryTagCount: memoryTags.totalTagCount,
|
|
19075
19889
|
totalScopeCount: scopeSummaries.totalScopeCount,
|
|
19076
19890
|
tracePath,
|
|
19077
19891
|
truncated
|
|
@@ -19117,22 +19931,42 @@ function boundAnalyzeTraceResult(result) {
|
|
|
19117
19931
|
truncated: [...result.truncated]
|
|
19118
19932
|
};
|
|
19119
19933
|
while (JSON.stringify(bounded).length > ANALYZE_TRACE_MAX_RESPONSE_BYTES) {
|
|
19120
|
-
const
|
|
19934
|
+
const topScopesLength = Math.max(bounded.topScopesByInclusiveTime.length, bounded.topScopesByExclusiveTime.length);
|
|
19935
|
+
const longestListLength = Math.max(topScopesLength, bounded.hitches.length, bounded.topGpuScopes.length, bounded.memoryTags.length);
|
|
19121
19936
|
if (longestListLength <= 1) {
|
|
19122
19937
|
addTruncationReason(bounded, "responseBytesExceeded");
|
|
19123
19938
|
return bounded;
|
|
19124
19939
|
}
|
|
19125
|
-
if (
|
|
19940
|
+
if (topScopesLength === longestListLength) {
|
|
19126
19941
|
bounded.topScopesByInclusiveTime = bounded.topScopesByInclusiveTime.slice(0, longestListLength - 1);
|
|
19127
19942
|
bounded.topScopesByExclusiveTime = bounded.topScopesByExclusiveTime.slice(0, longestListLength - 1);
|
|
19128
19943
|
addTruncationReason(bounded, "topScopes");
|
|
19129
19944
|
continue;
|
|
19130
19945
|
}
|
|
19946
|
+
if (bounded.topGpuScopes.length === longestListLength) {
|
|
19947
|
+
bounded.topGpuScopes = bounded.topGpuScopes.slice(0, longestListLength - 1);
|
|
19948
|
+
addTruncationReason(bounded, "topGpuScopes");
|
|
19949
|
+
continue;
|
|
19950
|
+
}
|
|
19951
|
+
if (bounded.memoryTags.length === longestListLength) {
|
|
19952
|
+
bounded.memoryTags = bounded.memoryTags.slice(0, longestListLength - 1);
|
|
19953
|
+
addTruncationReason(bounded, "memoryTags");
|
|
19954
|
+
continue;
|
|
19955
|
+
}
|
|
19131
19956
|
bounded.hitches = bounded.hitches.slice(0, bounded.hitches.length - 1);
|
|
19132
19957
|
addTruncationReason(bounded, "hitches");
|
|
19133
19958
|
}
|
|
19134
19959
|
return bounded;
|
|
19135
19960
|
}
|
|
19961
|
+
async function summarizeMemoryTags(exportDirectory, maxTags, context) {
|
|
19962
|
+
const counterFiles = (await context.listDirectory(exportDirectory)).filter((fileName) => fileName.startsWith(LLM_COUNTER_FILE_PREFIX) && fileName.endsWith(".csv"));
|
|
19963
|
+
const tags = [];
|
|
19964
|
+
for (const fileName of counterFiles) {
|
|
19965
|
+
const tag = await summarizeMemoryTagCounter(llmTagNameFromCounter(fileName.slice(4, -4)), context.readTextLines(path.join(exportDirectory, fileName)));
|
|
19966
|
+
if (tag !== void 0) tags.push(tag);
|
|
19967
|
+
}
|
|
19968
|
+
return rankMemoryTags(tags, maxTags);
|
|
19969
|
+
}
|
|
19136
19970
|
function addTruncationReason(result, reason) {
|
|
19137
19971
|
if (!result.truncated.includes(reason)) result.truncated.push(reason);
|
|
19138
19972
|
}
|
|
@@ -19270,7 +20104,7 @@ function registerDiagnosticsTools(server, dependencies) {
|
|
|
19270
20104
|
}, dependencies));
|
|
19271
20105
|
});
|
|
19272
20106
|
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,
|
|
20107
|
+
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
20108
|
inputSchema: analyzeTraceInputSchema,
|
|
19275
20109
|
title: "Analyze Trace"
|
|
19276
20110
|
}, async (input) => {
|
|
@@ -20111,6 +20945,7 @@ const listGraphNodesInputSchema = {
|
|
|
20111
20945
|
};
|
|
20112
20946
|
const addGraphNodeInputSchema = {
|
|
20113
20947
|
assetPath: bridgeAddGraphNodeRequestFieldsSchema.shape.assetPath.describe("Package name or object path of the asset owning the graph."),
|
|
20948
|
+
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
20949
|
graphName: bridgeAddGraphNodeRequestFieldsSchema.shape.graphName.describe("Graph to add the node to."),
|
|
20115
20950
|
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
20951
|
memberName: bridgeAddGraphNodeRequestFieldsSchema.shape.memberName.describe("Function or variable name, required for every kind except 'class'."),
|
|
@@ -20152,6 +20987,11 @@ const setPinDefaultInputSchema = {
|
|
|
20152
20987
|
projectId: creativeProjectIdSchema,
|
|
20153
20988
|
value: bridgeSetPinDefaultRequestSchema.shape.value.describe("ExportText value, the same format get_actor_details emits and set_actor_property accepts.")
|
|
20154
20989
|
};
|
|
20990
|
+
const layoutGraphInputSchema = {
|
|
20991
|
+
assetPath: bridgeLayoutGraphRequestSchema.shape.assetPath.describe("Package name or object path of the Blueprint owning the graph."),
|
|
20992
|
+
graphName: bridgeLayoutGraphRequestSchema.shape.graphName.describe("Graph to arrange, as get_blueprint_summary reports it (e.g. 'EventGraph')."),
|
|
20993
|
+
projectId: creativeProjectIdSchema
|
|
20994
|
+
};
|
|
20155
20995
|
const listAvailableNodesInputSchema = {
|
|
20156
20996
|
assetPath: bridgeListAvailableNodesRequestSchema.shape.assetPath.describe("Package name or object path of the asset owning the graph."),
|
|
20157
20997
|
cursor: bridgeListAvailableNodesRequestSchema.shape.cursor.describe("nextCursor from a previous response, to fetch the following page."),
|
|
@@ -20169,6 +21009,7 @@ async function listGraphNodes(input, dependencies) {
|
|
|
20169
21009
|
}
|
|
20170
21010
|
async function addGraphNode(input, dependencies) {
|
|
20171
21011
|
return await exchangeCreativeRequest(createBridgeAddGraphNodeRequest(input.assetPath, input.graphName, input.kind, {
|
|
21012
|
+
autoLayout: input.autoLayout,
|
|
20172
21013
|
memberName: input.memberName,
|
|
20173
21014
|
memberParentClass: input.memberParentClass,
|
|
20174
21015
|
nodeClass: input.nodeClass,
|
|
@@ -20207,6 +21048,9 @@ async function listAvailableNodes(input, dependencies) {
|
|
|
20207
21048
|
nameFilter: input.nameFilter
|
|
20208
21049
|
}), sendBridgeListAvailableNodesRequest, BRIDGE_LIST_AVAILABLE_NODES_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
20209
21050
|
}
|
|
21051
|
+
async function layoutGraph(input, dependencies) {
|
|
21052
|
+
return await exchangeCreativeRequest(createBridgeLayoutGraphRequest(input.assetPath, input.graphName), sendBridgeLayoutGraphRequest, BRIDGE_LAYOUT_GRAPH_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
21053
|
+
}
|
|
20210
21054
|
function registerGraphTools(server, dependencies) {
|
|
20211
21055
|
server.registerTool("list_graph_nodes", {
|
|
20212
21056
|
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 +21067,13 @@ function registerGraphTools(server, dependencies) {
|
|
|
20223
21067
|
}, dependencies));
|
|
20224
21068
|
});
|
|
20225
21069
|
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.",
|
|
21070
|
+
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
21071
|
inputSchema: addGraphNodeInputSchema,
|
|
20228
21072
|
title: "Add Graph Node"
|
|
20229
|
-
}, async ({ assetPath, graphName, kind, memberName, memberParentClass, nodeClass, pinDefaults, position, projectId }) => {
|
|
21073
|
+
}, async ({ assetPath, autoLayout, graphName, kind, memberName, memberParentClass, nodeClass, pinDefaults, position, projectId }) => {
|
|
20230
21074
|
return toToolSuccess(await addGraphNode({
|
|
20231
21075
|
assetPath,
|
|
21076
|
+
autoLayout,
|
|
20232
21077
|
graphName,
|
|
20233
21078
|
kind,
|
|
20234
21079
|
memberName,
|
|
@@ -20309,6 +21154,17 @@ function registerGraphTools(server, dependencies) {
|
|
|
20309
21154
|
projectId
|
|
20310
21155
|
}, dependencies));
|
|
20311
21156
|
});
|
|
21157
|
+
server.registerTool("layout_graph", {
|
|
21158
|
+
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.",
|
|
21159
|
+
inputSchema: layoutGraphInputSchema,
|
|
21160
|
+
title: "Layout Graph"
|
|
21161
|
+
}, async ({ assetPath, graphName, projectId }) => {
|
|
21162
|
+
return toToolSuccess(await layoutGraph({
|
|
21163
|
+
assetPath,
|
|
21164
|
+
graphName,
|
|
21165
|
+
projectId
|
|
21166
|
+
}, dependencies));
|
|
21167
|
+
});
|
|
20312
21168
|
}
|
|
20313
21169
|
const graphToolDomain = {
|
|
20314
21170
|
domain: "graph",
|
|
@@ -20320,7 +21176,8 @@ const graphToolDomain = {
|
|
|
20320
21176
|
"connect_pins",
|
|
20321
21177
|
"disconnect_pins",
|
|
20322
21178
|
"set_pin_default",
|
|
20323
|
-
"list_available_nodes"
|
|
21179
|
+
"list_available_nodes",
|
|
21180
|
+
"layout_graph"
|
|
20324
21181
|
]
|
|
20325
21182
|
};
|
|
20326
21183
|
//#endregion
|
|
@@ -22832,6 +23689,95 @@ const logsToolDomain = {
|
|
|
22832
23689
|
]
|
|
22833
23690
|
};
|
|
22834
23691
|
//#endregion
|
|
23692
|
+
//#region src/tools/mass.ts
|
|
23693
|
+
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.";
|
|
23694
|
+
const createMassEntityConfigInputSchema = {
|
|
23695
|
+
assetName: bridgeCreateMassEntityConfigRequestSchema.shape.assetName.describe("Name of the new MassEntityConfig asset, e.g. 'DA_CrowdAgent'."),
|
|
23696
|
+
packagePath: bridgeCreateMassEntityConfigRequestSchema.shape.packagePath.describe("Content folder to create the config in, e.g. /Game/Mass."),
|
|
23697
|
+
parentConfigPath: bridgeCreateMassEntityConfigRequestSchema.shape.parentConfigPath.describe("Optional MassEntityConfig to inherit traits from; this config overrides any trait of the same class."),
|
|
23698
|
+
projectId: creativeProjectIdSchema
|
|
23699
|
+
};
|
|
23700
|
+
const editMassEntityConfigInputSchema = {
|
|
23701
|
+
assetPath: bridgeEditMassEntityConfigRequestSchema.shape.assetPath.describe("MassEntityConfig asset to edit."),
|
|
23702
|
+
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}`),
|
|
23703
|
+
projectId: creativeProjectIdSchema
|
|
23704
|
+
};
|
|
23705
|
+
const getMassEntityConfigInputSchema = {
|
|
23706
|
+
assetPath: bridgeGetMassEntityConfigRequestSchema.shape.assetPath.describe("MassEntityConfig asset to read."),
|
|
23707
|
+
projectId: creativeProjectIdSchema
|
|
23708
|
+
};
|
|
23709
|
+
const validateMassEntityConfigInputSchema = {
|
|
23710
|
+
assetPath: bridgeValidateMassEntityConfigRequestSchema.shape.assetPath.describe("MassEntityConfig asset to validate."),
|
|
23711
|
+
projectId: creativeProjectIdSchema
|
|
23712
|
+
};
|
|
23713
|
+
async function createMassEntityConfig(input, dependencies) {
|
|
23714
|
+
return await exchangeCreativeRequest(createBridgeCreateMassEntityConfigRequest(input.assetName, input.packagePath, { parentConfigPath: input.parentConfigPath }), sendBridgeCreateMassEntityConfigRequest, BRIDGE_CREATE_MASS_ENTITY_CONFIG_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23715
|
+
}
|
|
23716
|
+
async function editMassEntityConfig(input, dependencies) {
|
|
23717
|
+
return await exchangeCreativeRequest(createBridgeEditMassEntityConfigRequest(input.assetPath, input.edits), sendBridgeEditMassEntityConfigRequest, BRIDGE_EDIT_MASS_ENTITY_CONFIG_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23718
|
+
}
|
|
23719
|
+
async function getMassEntityConfig(input, dependencies) {
|
|
23720
|
+
return await exchangeCreativeRequest(createBridgeGetMassEntityConfigRequest(input.assetPath), sendBridgeGetMassEntityConfigRequest, BRIDGE_GET_MASS_ENTITY_CONFIG_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23721
|
+
}
|
|
23722
|
+
async function validateMassEntityConfig(input, dependencies) {
|
|
23723
|
+
return await exchangeCreativeRequest(createBridgeValidateMassEntityConfigRequest(input.assetPath), sendBridgeValidateMassEntityConfigRequest, BRIDGE_VALIDATE_MASS_ENTITY_CONFIG_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23724
|
+
}
|
|
23725
|
+
function registerMassTools(server, dependencies) {
|
|
23726
|
+
server.registerTool("create_mass_entity_config", {
|
|
23727
|
+
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.",
|
|
23728
|
+
inputSchema: createMassEntityConfigInputSchema,
|
|
23729
|
+
title: "Create Mass Entity Config"
|
|
23730
|
+
}, async ({ assetName, packagePath, parentConfigPath, projectId }) => {
|
|
23731
|
+
return toToolSuccess(await createMassEntityConfig({
|
|
23732
|
+
assetName,
|
|
23733
|
+
packagePath,
|
|
23734
|
+
parentConfigPath,
|
|
23735
|
+
projectId
|
|
23736
|
+
}, dependencies));
|
|
23737
|
+
});
|
|
23738
|
+
server.registerTool("edit_mass_entity_config", {
|
|
23739
|
+
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.",
|
|
23740
|
+
inputSchema: editMassEntityConfigInputSchema,
|
|
23741
|
+
title: "Edit Mass Entity Config"
|
|
23742
|
+
}, async ({ assetPath, edits, projectId }) => {
|
|
23743
|
+
return toToolSuccess(await editMassEntityConfig({
|
|
23744
|
+
assetPath,
|
|
23745
|
+
edits,
|
|
23746
|
+
projectId
|
|
23747
|
+
}, dependencies));
|
|
23748
|
+
});
|
|
23749
|
+
server.registerTool("get_mass_entity_config", {
|
|
23750
|
+
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.",
|
|
23751
|
+
inputSchema: getMassEntityConfigInputSchema,
|
|
23752
|
+
title: "Get Mass Entity Config"
|
|
23753
|
+
}, async ({ assetPath, projectId }) => {
|
|
23754
|
+
return toToolSuccess(await getMassEntityConfig({
|
|
23755
|
+
assetPath,
|
|
23756
|
+
projectId
|
|
23757
|
+
}, dependencies));
|
|
23758
|
+
});
|
|
23759
|
+
server.registerTool("validate_mass_entity_config", {
|
|
23760
|
+
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).",
|
|
23761
|
+
inputSchema: validateMassEntityConfigInputSchema,
|
|
23762
|
+
title: "Validate Mass Entity Config"
|
|
23763
|
+
}, async ({ assetPath, projectId }) => {
|
|
23764
|
+
return toToolSuccess(await validateMassEntityConfig({
|
|
23765
|
+
assetPath,
|
|
23766
|
+
projectId
|
|
23767
|
+
}, dependencies));
|
|
23768
|
+
});
|
|
23769
|
+
}
|
|
23770
|
+
const massToolDomain = {
|
|
23771
|
+
domain: "mass",
|
|
23772
|
+
register: registerMassTools,
|
|
23773
|
+
toolNames: [
|
|
23774
|
+
"create_mass_entity_config",
|
|
23775
|
+
"edit_mass_entity_config",
|
|
23776
|
+
"get_mass_entity_config",
|
|
23777
|
+
"validate_mass_entity_config"
|
|
23778
|
+
]
|
|
23779
|
+
};
|
|
23780
|
+
//#endregion
|
|
22835
23781
|
//#region src/tools/material.ts
|
|
22836
23782
|
const createMaterialInstanceInputSchema = {
|
|
22837
23783
|
assetName: bridgeCreateMaterialInstanceRequestSchema.shape.assetName.describe("Name of the new instance, e.g. 'MI_Rock_Mossy'."),
|
|
@@ -23102,6 +24048,13 @@ const testReachabilityInputSchema = {
|
|
|
23102
24048
|
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
24049
|
projectId: creativeProjectIdSchema
|
|
23104
24050
|
};
|
|
24051
|
+
const diagnoseNavmeshInputSchema = {
|
|
24052
|
+
includePlayerStarts: bridgeDiagnoseNavmeshRequestSchema.shape.includePlayerStarts.describe("Check every PlayerStart in the level as a spawn point. Defaults to true."),
|
|
24053
|
+
maxIslands: bridgeDiagnoseNavmeshRequestSchema.shape.maxIslands.describe(`Most islands to list, largest area first (1-${String(64)}). islandCount stays the full count.`),
|
|
24054
|
+
navMeshActorPath: bridgeDiagnoseNavmeshRequestSchema.shape.navMeshActorPath.describe("Actor path of the RecastNavMesh to inspect. Omit to use the level's main navigation data."),
|
|
24055
|
+
projectId: creativeProjectIdSchema,
|
|
24056
|
+
spawnActorPaths: bridgeDiagnoseNavmeshRequestSchema.shape.spawnActorPaths.describe(`Extra spawn actors to check alongside the player starts, such as AI spawners (max ${String(64)}).`)
|
|
24057
|
+
};
|
|
23105
24058
|
async function setNavmeshSettings(input, dependencies) {
|
|
23106
24059
|
return await exchangeCreativeRequest(createBridgeSetNavmeshSettingsRequest({
|
|
23107
24060
|
agentHeight: input.agentHeight,
|
|
@@ -23172,6 +24125,14 @@ async function testReachability(input, dependencies) {
|
|
|
23172
24125
|
navMeshActorPath: input.navMeshActorPath
|
|
23173
24126
|
}), sendBridgeTestReachabilityRequest, BRIDGE_TEST_REACHABILITY_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
23174
24127
|
}
|
|
24128
|
+
async function diagnoseNavmesh(input, dependencies) {
|
|
24129
|
+
return await exchangeCreativeRequest(createBridgeDiagnoseNavmeshRequest({
|
|
24130
|
+
includePlayerStarts: input.includePlayerStarts,
|
|
24131
|
+
maxIslands: input.maxIslands,
|
|
24132
|
+
navMeshActorPath: input.navMeshActorPath,
|
|
24133
|
+
spawnActorPaths: input.spawnActorPaths
|
|
24134
|
+
}), sendBridgeDiagnoseNavmeshRequest, BRIDGE_DIAGNOSE_NAVMESH_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
24135
|
+
}
|
|
23175
24136
|
function registerNavigationTools(server, dependencies) {
|
|
23176
24137
|
server.registerTool("set_navmesh_settings", {
|
|
23177
24138
|
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 +24250,19 @@ function registerNavigationTools(server, dependencies) {
|
|
|
23289
24250
|
projectId
|
|
23290
24251
|
}, dependencies));
|
|
23291
24252
|
});
|
|
24253
|
+
server.registerTool("diagnose_navmesh", {
|
|
24254
|
+
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.",
|
|
24255
|
+
inputSchema: diagnoseNavmeshInputSchema,
|
|
24256
|
+
title: "Diagnose Navmesh"
|
|
24257
|
+
}, async ({ includePlayerStarts, maxIslands, navMeshActorPath, projectId, spawnActorPaths }) => {
|
|
24258
|
+
return toToolSuccess(await diagnoseNavmesh({
|
|
24259
|
+
includePlayerStarts,
|
|
24260
|
+
maxIslands,
|
|
24261
|
+
navMeshActorPath,
|
|
24262
|
+
projectId,
|
|
24263
|
+
spawnActorPaths
|
|
24264
|
+
}, dependencies));
|
|
24265
|
+
});
|
|
23292
24266
|
}
|
|
23293
24267
|
const navigationToolDomain = {
|
|
23294
24268
|
domain: "navigation",
|
|
@@ -23301,7 +24275,8 @@ const navigationToolDomain = {
|
|
|
23301
24275
|
"add_nav_modifier_volume",
|
|
23302
24276
|
"add_nav_link",
|
|
23303
24277
|
"find_path",
|
|
23304
|
-
"test_reachability"
|
|
24278
|
+
"test_reachability",
|
|
24279
|
+
"diagnose_navmesh"
|
|
23305
24280
|
]
|
|
23306
24281
|
};
|
|
23307
24282
|
//#endregion
|
|
@@ -24218,6 +25193,90 @@ const sequencerToolDomain = {
|
|
|
24218
25193
|
]
|
|
24219
25194
|
};
|
|
24220
25195
|
//#endregion
|
|
25196
|
+
//#region src/tools/smartObjects.ts
|
|
25197
|
+
const createSmartObjectDefinitionInputSchema = {
|
|
25198
|
+
activityTags: bridgeCreateSmartObjectDefinitionRequestSchema.shape.activityTags.describe("Gameplay tags describing what the whole object offers, e.g. 'Activity.Sit'. Every tag must already be registered."),
|
|
25199
|
+
assetName: bridgeCreateSmartObjectDefinitionRequestSchema.shape.assetName.describe("Name of the new Smart Object definition, e.g. 'SOD_Bench'."),
|
|
25200
|
+
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."),
|
|
25201
|
+
packagePath: bridgeCreateSmartObjectDefinitionRequestSchema.shape.packagePath.describe("Content folder to create the definition in."),
|
|
25202
|
+
projectId: creativeProjectIdSchema,
|
|
25203
|
+
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.")
|
|
25204
|
+
};
|
|
25205
|
+
const getSmartObjectDefinitionInputSchema = {
|
|
25206
|
+
assetPath: bridgeGetSmartObjectDefinitionRequestSchema.shape.assetPath.describe("Object path of the Smart Object definition to read."),
|
|
25207
|
+
projectId: creativeProjectIdSchema
|
|
25208
|
+
};
|
|
25209
|
+
const addSmartObjectComponentInputSchema = {
|
|
25210
|
+
actorPath: bridgeAddSmartObjectComponentRequestFieldsSchema.shape.actorPath.describe("Placed actor in the editor level to add the component to. Give this or blueprintPath, not both."),
|
|
25211
|
+
blueprintPath: bridgeAddSmartObjectComponentRequestFieldsSchema.shape.blueprintPath.describe("Actor Blueprint to add the component to; the Blueprint is recompiled. Give this or actorPath, not both."),
|
|
25212
|
+
componentName: bridgeAddSmartObjectComponentRequestFieldsSchema.shape.componentName.describe("Name of the component. Omitted reuses the existing Smart Object component, or names a new one SmartObject."),
|
|
25213
|
+
definitionPath: bridgeAddSmartObjectComponentRequestFieldsSchema.shape.definitionPath.describe("Smart Object definition the component points at."),
|
|
25214
|
+
projectId: creativeProjectIdSchema
|
|
25215
|
+
};
|
|
25216
|
+
async function createSmartObjectDefinition(input, dependencies) {
|
|
25217
|
+
return await exchangeCreativeRequest(createBridgeCreateSmartObjectDefinitionRequest(input.assetName, input.packagePath, input.slots, {
|
|
25218
|
+
activityTags: input.activityTags,
|
|
25219
|
+
defaultBehaviorDefinitions: input.defaultBehaviorDefinitions
|
|
25220
|
+
}), sendBridgeCreateSmartObjectDefinitionRequest, BRIDGE_CREATE_SMART_OBJECT_DEFINITION_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
25221
|
+
}
|
|
25222
|
+
async function getSmartObjectDefinition(input, dependencies) {
|
|
25223
|
+
return await exchangeCreativeRequest(createBridgeGetSmartObjectDefinitionRequest(input.assetPath), sendBridgeGetSmartObjectDefinitionRequest, BRIDGE_GET_SMART_OBJECT_DEFINITION_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
25224
|
+
}
|
|
25225
|
+
async function addSmartObjectComponent(input, dependencies) {
|
|
25226
|
+
return await exchangeCreativeRequest(createBridgeAddSmartObjectComponentRequest(input.definitionPath, {
|
|
25227
|
+
actorPath: input.actorPath,
|
|
25228
|
+
blueprintPath: input.blueprintPath
|
|
25229
|
+
}, { componentName: input.componentName }), sendBridgeAddSmartObjectComponentRequest, BRIDGE_ADD_SMART_OBJECT_COMPONENT_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
25230
|
+
}
|
|
25231
|
+
function registerSmartObjectsTools(server, dependencies) {
|
|
25232
|
+
server.registerTool("create_smart_object_definition", {
|
|
25233
|
+
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.",
|
|
25234
|
+
inputSchema: createSmartObjectDefinitionInputSchema,
|
|
25235
|
+
title: "Create Smart Object Definition"
|
|
25236
|
+
}, async ({ activityTags, assetName, defaultBehaviorDefinitions, packagePath, projectId, slots }) => {
|
|
25237
|
+
return toToolSuccess(await createSmartObjectDefinition({
|
|
25238
|
+
activityTags,
|
|
25239
|
+
assetName,
|
|
25240
|
+
defaultBehaviorDefinitions,
|
|
25241
|
+
packagePath,
|
|
25242
|
+
projectId,
|
|
25243
|
+
slots
|
|
25244
|
+
}, dependencies));
|
|
25245
|
+
});
|
|
25246
|
+
server.registerTool("get_smart_object_definition", {
|
|
25247
|
+
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.",
|
|
25248
|
+
inputSchema: getSmartObjectDefinitionInputSchema,
|
|
25249
|
+
title: "Get Smart Object Definition"
|
|
25250
|
+
}, async ({ assetPath, projectId }) => {
|
|
25251
|
+
return toToolSuccess(await getSmartObjectDefinition({
|
|
25252
|
+
assetPath,
|
|
25253
|
+
projectId
|
|
25254
|
+
}, dependencies));
|
|
25255
|
+
});
|
|
25256
|
+
server.registerTool("add_smart_object_component", {
|
|
25257
|
+
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.",
|
|
25258
|
+
inputSchema: addSmartObjectComponentInputSchema,
|
|
25259
|
+
title: "Add Smart Object Component"
|
|
25260
|
+
}, async ({ actorPath, blueprintPath, componentName, definitionPath, projectId }) => {
|
|
25261
|
+
return toToolSuccess(await addSmartObjectComponent({
|
|
25262
|
+
actorPath,
|
|
25263
|
+
blueprintPath,
|
|
25264
|
+
componentName,
|
|
25265
|
+
definitionPath,
|
|
25266
|
+
projectId
|
|
25267
|
+
}, dependencies));
|
|
25268
|
+
});
|
|
25269
|
+
}
|
|
25270
|
+
const smartObjectsToolDomain = {
|
|
25271
|
+
domain: "smartObjects",
|
|
25272
|
+
register: registerSmartObjectsTools,
|
|
25273
|
+
toolNames: [
|
|
25274
|
+
"create_smart_object_definition",
|
|
25275
|
+
"get_smart_object_definition",
|
|
25276
|
+
"add_smart_object_component"
|
|
25277
|
+
]
|
|
25278
|
+
};
|
|
25279
|
+
//#endregion
|
|
24221
25280
|
//#region src/tools/stateTree.ts
|
|
24222
25281
|
const getStateTreeInputSchema = {
|
|
24223
25282
|
assetPath: bridgeGetStateTreeRequestSchema.shape.assetPath.describe("Object path of the StateTree asset to read."),
|
|
@@ -24256,6 +25315,18 @@ const traceStateTreeInputSchema = {
|
|
|
24256
25315
|
maxEvents: bridgeTraceStateTreeRequestSchema.shape.maxEvents.describe("Maximum events to return in one poll (1-200, default 50)."),
|
|
24257
25316
|
projectId: creativeProjectIdSchema
|
|
24258
25317
|
};
|
|
25318
|
+
const updateStateTreeElementsInputSchema = {
|
|
25319
|
+
assetPath: bridgeUpdateStateTreeElementsRequestSchema.shape.assetPath.describe("Object path of the StateTree asset to edit."),
|
|
25320
|
+
compile: bridgeUpdateStateTreeElementsRequestSchema.shape.compile.describe("Run the StateTree compiler after the edits. Defaults true; its messages come back verbatim in compileMessages."),
|
|
25321
|
+
projectId: creativeProjectIdSchema,
|
|
25322
|
+
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'.")
|
|
25323
|
+
};
|
|
25324
|
+
const removeStateTreeElementsInputSchema = {
|
|
25325
|
+
assetPath: bridgeRemoveStateTreeElementsRequestSchema.shape.assetPath.describe("Object path of the StateTree asset to edit."),
|
|
25326
|
+
compile: bridgeRemoveStateTreeElementsRequestSchema.shape.compile.describe("Run the StateTree compiler after the removals. Defaults true; its messages come back verbatim in compileMessages."),
|
|
25327
|
+
projectId: creativeProjectIdSchema,
|
|
25328
|
+
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.")
|
|
25329
|
+
};
|
|
24259
25330
|
async function getStateTree(input, dependencies) {
|
|
24260
25331
|
return await exchangeCreativeRequest(createBridgeGetStateTreeRequest(input.assetPath), sendBridgeGetStateTreeRequest, BRIDGE_GET_STATE_TREE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
24261
25332
|
}
|
|
@@ -24284,6 +25355,12 @@ async function traceStateTree(input, dependencies) {
|
|
|
24284
25355
|
maxEvents: input.maxEvents
|
|
24285
25356
|
}), sendBridgeTraceStateTreeRequest, BRIDGE_TRACE_STATE_TREE_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
24286
25357
|
}
|
|
25358
|
+
async function updateStateTreeElements(input, dependencies) {
|
|
25359
|
+
return await exchangeCreativeRequest(createBridgeUpdateStateTreeElementsRequest(input.assetPath, input.updates, { compile: input.compile }), sendBridgeUpdateStateTreeElementsRequest, BRIDGE_UPDATE_STATE_TREE_ELEMENTS_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
25360
|
+
}
|
|
25361
|
+
async function removeStateTreeElements(input, dependencies) {
|
|
25362
|
+
return await exchangeCreativeRequest(createBridgeRemoveStateTreeElementsRequest(input.assetPath, input.removals, { compile: input.compile }), sendBridgeRemoveStateTreeElementsRequest, BRIDGE_REMOVE_STATE_TREE_ELEMENTS_REQUEST_TYPE, projectIdSchema.parse(input.projectId), dependencies);
|
|
25363
|
+
}
|
|
24287
25364
|
function registerStateTreeTools(server, dependencies) {
|
|
24288
25365
|
server.registerTool("get_state_tree", {
|
|
24289
25366
|
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 +25435,30 @@ function registerStateTreeTools(server, dependencies) {
|
|
|
24358
25435
|
projectId
|
|
24359
25436
|
}, dependencies));
|
|
24360
25437
|
});
|
|
25438
|
+
server.registerTool("update_state_tree_elements", {
|
|
25439
|
+
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.",
|
|
25440
|
+
inputSchema: updateStateTreeElementsInputSchema,
|
|
25441
|
+
title: "Update StateTree Elements"
|
|
25442
|
+
}, async ({ assetPath, compile, projectId, updates }) => {
|
|
25443
|
+
return toToolSuccess(await updateStateTreeElements({
|
|
25444
|
+
assetPath,
|
|
25445
|
+
compile,
|
|
25446
|
+
projectId,
|
|
25447
|
+
updates
|
|
25448
|
+
}, dependencies));
|
|
25449
|
+
});
|
|
25450
|
+
server.registerTool("remove_state_tree_elements", {
|
|
25451
|
+
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.",
|
|
25452
|
+
inputSchema: removeStateTreeElementsInputSchema,
|
|
25453
|
+
title: "Remove StateTree Elements"
|
|
25454
|
+
}, async ({ assetPath, compile, projectId, removals }) => {
|
|
25455
|
+
return toToolSuccess(await removeStateTreeElements({
|
|
25456
|
+
assetPath,
|
|
25457
|
+
compile,
|
|
25458
|
+
projectId,
|
|
25459
|
+
removals
|
|
25460
|
+
}, dependencies));
|
|
25461
|
+
});
|
|
24361
25462
|
}
|
|
24362
25463
|
const stateTreeToolDomain = {
|
|
24363
25464
|
domain: "stateTree",
|
|
@@ -24368,7 +25469,9 @@ const stateTreeToolDomain = {
|
|
|
24368
25469
|
"set_state_tree_considerations",
|
|
24369
25470
|
"link_state_tree_state",
|
|
24370
25471
|
"add_state_tree_component",
|
|
24371
|
-
"trace_state_tree"
|
|
25472
|
+
"trace_state_tree",
|
|
25473
|
+
"update_state_tree_elements",
|
|
25474
|
+
"remove_state_tree_elements"
|
|
24372
25475
|
]
|
|
24373
25476
|
};
|
|
24374
25477
|
//#endregion
|
|
@@ -25294,7 +26397,9 @@ const TOOL_CATALOG = [
|
|
|
25294
26397
|
vfxToolDomain,
|
|
25295
26398
|
pcgToolDomain,
|
|
25296
26399
|
projectSettingsToolDomain,
|
|
25297
|
-
navigationToolDomain
|
|
26400
|
+
navigationToolDomain,
|
|
26401
|
+
smartObjectsToolDomain,
|
|
26402
|
+
massToolDomain
|
|
25298
26403
|
];
|
|
25299
26404
|
//#endregion
|
|
25300
26405
|
//#region src/mcpTools.ts
|