@uemcp/server 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -2
- package/dist/index.mjs +1054 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -44,6 +44,10 @@ The MCP tool surface currently exposes:
|
|
|
44
44
|
- `redo`
|
|
45
45
|
- `open_level`
|
|
46
46
|
- `get_open_level_status`
|
|
47
|
+
- `get_source_control_status`
|
|
48
|
+
- `refresh_source_control_status`
|
|
49
|
+
- `checkout_assets`
|
|
50
|
+
- `get_source_control_job_status`
|
|
47
51
|
|
|
48
52
|
## Project Identity
|
|
49
53
|
|
|
@@ -101,9 +105,9 @@ This is intended to let an MCP client resolve the canonical Unreal project ident
|
|
|
101
105
|
### `wait_for_job`
|
|
102
106
|
|
|
103
107
|
- Blocks server-side until an async job reaches a terminal state, then returns the payload the matching `get_*_status` tool would have returned under `status`
|
|
104
|
-
- Replaces a client-side poll loop for `kind` `compile` (`trigger_live_compile` / `trigger_hot_reload`), `create_class`, `test_run`, and `
|
|
108
|
+
- Replaces a client-side poll loop for `kind` `compile` (`trigger_live_compile` / `trigger_hot_reload`), `create_class`, `test_run`, `pie`, and `source_control` (`checkout_assets` / `refresh_source_control_status`); `kind` is required because job ids are bare GUIDs
|
|
105
109
|
- `outcome` is `completed`, `timed_out` (last observed status still returned), or `unknown_job` (unknown/expired/cancelled id, returned on the first poll)
|
|
106
|
-
- Per-kind default budgets (compile 120s, create_class 60s, pie 30s, test_run 300s), clamped to 600s; polls back off from 250ms (1s for test runs) and a transient bridge read timeout or dropped socket is retried rather than failing the wait
|
|
110
|
+
- Per-kind default budgets (compile 120s, create_class 60s, pie 30s, source_control 60s, test_run 300s), clamped to 600s; polls back off from 250ms (1s for test runs) and a transient bridge read timeout or dropped socket is retried rather than failing the wait
|
|
107
111
|
- For `test_run`, `status.results` is the first page — page the rest with `get_test_run_status` and `nextCursor`
|
|
108
112
|
|
|
109
113
|
### `build_target` / `generate_project_files` / `clean_build`
|
|
@@ -182,6 +186,48 @@ This is intended to let an MCP client resolve the canonical Unreal project ident
|
|
|
182
186
|
- Actor paths do not survive a load: re-run `list_actors` against the new world rather than reusing paths from the old one
|
|
183
187
|
- One load at a time per editor; a second request while one is running is refused with `open_level_in_progress` rather than queued
|
|
184
188
|
|
|
189
|
+
### `get_source_control_status` / `refresh_source_control_status` / `checkout_assets` / `get_source_control_job_status`
|
|
190
|
+
|
|
191
|
+
- The prerequisite for every asset write on a team project. Under Perforce or Git-LFS file locking a `.uasset` stays read-only until it is checked out, so a write that skips this fails later at save time — several tool calls away from its cause
|
|
192
|
+
- `get_source_control_status` answers **inline**: it reads the provider's own state cache, which is a memory lookup rather than a server round trip. It reports the `provider` name, `enabled` (is source control configured at all), `available` (is it currently connected), and one entry per requested path with a `state` of `checked_out_by_me`, `checked_out_by_other` (plus `checkedOutBy` naming the holder), `marked_for_add`, `not_checked_out`, `not_in_depot`, or `unknown`
|
|
193
|
+
- `enabled` is what separates "no source control configured" from "configured, and this file is simply not checked out". Those are never collapsed into one answer
|
|
194
|
+
- A file the editor has never asked the server about reports `unknown`, **not** a guess. `refresh_source_control_status` is how it becomes a real answer. A path that resolves to no package on disk also reports `unknown`, but carries an `error` saying so — an unresolvable path never passes as a depot answer
|
|
195
|
+
- `refresh_source_control_status` and `checkout_assets` talk to the source control server over the network, which runs far past the plugin's 5 s game-thread budget, so neither runs inline: each returns `state: 'accepted'` with a `sourceControlJobId`. Poll it with `get_source_control_job_status`, or wait with `wait_for_job` using `kind: 'source_control'`
|
|
196
|
+
- The poll reports `successCount` / `failureCount` and one result per file with its post-operation `state`, so a checkout is confirmed without a second query. One asset the provider refuses does not abort the rest — it reports `ok: false` with its own `error`
|
|
197
|
+
- Checkout only. Submitting is never done for you, and a checked-out asset stays checked out until a human submits or reverts it
|
|
198
|
+
- A request against an editor with no provider configured is refused with `source_control_disabled`, and one against a configured-but-offline provider with `source_control_unavailable`. Neither degrades into a filesystem check
|
|
199
|
+
- In a non-editor plugin build all four report `state: 'unsupported'` and schedule nothing
|
|
200
|
+
|
|
201
|
+
### `read_data_table` / `write_data_table_row`
|
|
202
|
+
|
|
203
|
+
- A DataTable is where a project keeps its tuning data, and it is a binary `.uasset` — `find_assets` can locate one but nothing can read it off disk, so these are the only way in. `read_data_table` loads the asset and reports the row struct it is typed on, an ordered column list (`{ name, type }`, using the same type rendering `get_class_reflection` emits), and each row as a column-name-to-value map
|
|
204
|
+
- Values are `ExportText`, the same format `get_actor_details` and `get_cdo_defaults` emit and `set_actor_property` accepts, so a value read here writes straight back with no translation. Column names are the **authored** names, so a Blueprint (user-defined) row struct reports the names the editor shows rather than its mangled internal ones
|
|
205
|
+
- Rows page in **name order** — `RowMap` iteration follows hashing, which shifts as rows are added, so a cursor over it would skip or repeat rows between pages. Pages are trimmed by encoded bytes as well as by `maxRows`, because one row of a wide tuning struct can cost more than a whole page of asset entries; `totalRowCount` stays authoritative when a page truncates
|
|
206
|
+
- `loadIfNeeded: false` refuses to load an unloaded table and reports `asset_not_loaded`. Unlike `get_blueprint_summary` there is no metadata-only fallback: a DataTable carries no Asset Registry tags describing its rows
|
|
207
|
+
- `write_data_table_row` upserts or deletes one row. **Every column name and value is validated against the row struct before anything is written**, into scratch memory that is only copied in once the whole row imports, so a rejected write leaves the table byte-identical — there is no partial application. An unknown column reports `unknown_column` and lists the valid ones; a value that will not parse reports `invalid_row_value` and names the field and its type
|
|
208
|
+
- Numeric and boolean values are range-checked **before** `ImportText` rather than after: the engine's importer takes `not-a-number` as `0` and reports success, and silent coercion is exactly the failure a tuning-data write cannot afford
|
|
209
|
+
- The write runs inside a single `FScopedTransaction` (Ctrl+Z reverses it) and marks the package dirty **without saving** — compose with `save_dirty_packages`. `dryRun: true` validates everything and reports `state: 'validated'`, opening no transaction
|
|
210
|
+
- Deleting a row that does not exist is **not** a failure: it reports `rowExisted: false` with an explanatory message, because the table is already in the requested state
|
|
211
|
+
- A `.uasset` sits read-only on disk until it is checked out under Perforce or Git-LFS file locking. That case is detected before anything is mutated rather than surfacing later as an unexplained save error. Where a provider is configured the answer comes from the provider itself — `source_control_checkout_required` for a file that is simply not checked out, `source_control_checked_out_by_other` naming the holder when someone else has it — and only where none is does it fall back to the on-disk read-only check. Fix either with `checkout_assets`
|
|
212
|
+
- In a non-editor plugin build `read_data_table` fails with `unsupported` and `write_data_table_row` returns `state: 'unsupported'`
|
|
213
|
+
|
|
214
|
+
### `export_data_table` / `import_data_table`
|
|
215
|
+
|
|
216
|
+
- The bulk half, built on the engine's own JSON and CSV serializers rather than the per-row walk above
|
|
217
|
+
- `export_data_table` returns the serialized table in **chunks by character offset**, because the engine produces one string rather than anything row-addressable. Concatenate chunks in `nextCursor` order to reassemble; a single chunk is not valid JSON or CSV on its own. Chunks are cut by encoded byte cost and never inside a surrogate pair
|
|
218
|
+
- `import_data_table` **replaces every row** — that is what the engine's importer does, so a row absent from the content is a row deleted. Use `write_data_table_row` to change one value. It runs in one transaction and dirties the package without saving, exactly like the per-row write
|
|
219
|
+
- Rows the importer rejects come back in `problems` while the rest still apply, so check `problemCount` even on success. `dryRun: true` runs the import against a transient duplicate and reports the resulting row count and problems without touching the real table
|
|
220
|
+
- The whole payload travels in one 64 KiB bridge frame, so `content` is capped at `BRIDGE_DATA_TABLE_MAX_IMPORT_CHARS` (16 K characters, sized so worst-case UTF-8 expansion still fits). A table larger than that cannot be imported this way
|
|
221
|
+
|
|
222
|
+
### `create_data_table` / `rename_data_table` / `delete_data_table` / `rename_data_table_row`
|
|
223
|
+
|
|
224
|
+
- The lifecycle half: the tools above all require a table that already exists, and until these landed nothing could make one over the bridge
|
|
225
|
+
- `create_data_table` binds a row struct at creation and never after — `UDataTable::RowStruct` can be reassigned, but that reinterprets existing row memory through the new layout, so the bridge does not expose it. Native structs are addressed as `/Script/<Module>.<Struct>`, a Blueprint struct by its object path; anything that is neither an `FTableRowBase` child nor a user-defined struct reports `invalid_row_struct` rather than producing a table that accepts no rows. The new table is dirty and **unsaved**, like every other DataTable write
|
|
226
|
+
- `rename_data_table` renames, moves, or both — one operation to the asset tools. References from other assets are fixed up and a redirector is left at the old path, so existing hard references keep resolving. `newName` must be a bare asset name: one carrying a path separator is refused rather than silently relocating the asset somewhere the caller never named
|
|
227
|
+
- `delete_data_table` is **the one DataTable tool with no transaction behind it** — asset deletion is not undoable, and there is no dirty-package step to reconsider at. A table other assets reference is refused with `asset_referenced` and its referencers reported; `force` deletes anyway and breaks them
|
|
228
|
+
- `rename_data_table_row` keeps the row's position and values, which an upsert-under-the-new-name plus a delete-of-the-old does not: that pair costs two transactions and moves the row to the end. It refuses a missing row (`row_not_found`) and a name already taken (`row_already_exists`), since renaming onto an existing row would discard that row's values. **Row names are how other assets address rows**, so a rename breaks any `FDataTableRowHandle` pointing at the old name — nothing fixes those up
|
|
229
|
+
- Rename and delete both need referencer data, which is only trustworthy once the Asset Registry's initial gather has finished — mid-scan `GetReferencers` returns a short list that reads as "nothing depends on this". Both drive the scan to completion first (starting it when a headless editor never did), and report `asset_registry_scanning` only if it is still incomplete afterwards. On a large project that wait can be long enough to hit the bridge read timeout
|
|
230
|
+
|
|
185
231
|
## MCP Resources
|
|
186
232
|
|
|
187
233
|
Resources carry context a client can attach without spending a tool call and a model turn. Every one of them is served from in-memory state or the local filesystem: **a resource read never opens a bridge socket and never waits on the editor**, so an unreachable or absent editor produces a structured payload rather than a timeout.
|
package/dist/index.mjs
CHANGED
|
@@ -459,6 +459,45 @@ const BRIDGE_OPEN_LEVEL_STATUS_STATES = [
|
|
|
459
459
|
"failed",
|
|
460
460
|
"unknown_job"
|
|
461
461
|
];
|
|
462
|
+
const BRIDGE_READ_DATA_TABLE_REQUEST_TYPE = "read_data_table";
|
|
463
|
+
const BRIDGE_WRITE_DATA_TABLE_ROW_REQUEST_TYPE = "write_data_table_row";
|
|
464
|
+
const BRIDGE_EXPORT_DATA_TABLE_REQUEST_TYPE = "export_data_table";
|
|
465
|
+
const BRIDGE_IMPORT_DATA_TABLE_REQUEST_TYPE = "import_data_table";
|
|
466
|
+
const BRIDGE_CREATE_DATA_TABLE_REQUEST_TYPE = "create_data_table";
|
|
467
|
+
const BRIDGE_RENAME_DATA_TABLE_REQUEST_TYPE = "rename_data_table";
|
|
468
|
+
const BRIDGE_DELETE_DATA_TABLE_REQUEST_TYPE = "delete_data_table";
|
|
469
|
+
const BRIDGE_RENAME_DATA_TABLE_ROW_REQUEST_TYPE = "rename_data_table_row";
|
|
470
|
+
const BRIDGE_DATA_TABLE_VALUE_MAX_CHARS = 4096;
|
|
471
|
+
const BRIDGE_DATA_TABLE_ROW_OPERATIONS = ["upsert", "delete"];
|
|
472
|
+
const BRIDGE_DATA_TABLE_WRITE_STATES = [
|
|
473
|
+
"applied",
|
|
474
|
+
"validated",
|
|
475
|
+
"unsupported"
|
|
476
|
+
];
|
|
477
|
+
const BRIDGE_DATA_TABLE_FORMATS = ["json", "csv"];
|
|
478
|
+
const BRIDGE_DATA_TABLE_MAX_EXPORT_CHARS = 24576;
|
|
479
|
+
const BRIDGE_DATA_TABLE_MAX_IMPORT_CHARS = 16384;
|
|
480
|
+
const BRIDGE_GET_SOURCE_CONTROL_STATUS_REQUEST_TYPE = "get_source_control_status";
|
|
481
|
+
const BRIDGE_REFRESH_SOURCE_CONTROL_STATUS_REQUEST_TYPE = "refresh_source_control_status";
|
|
482
|
+
const BRIDGE_CHECKOUT_ASSETS_REQUEST_TYPE = "checkout_assets";
|
|
483
|
+
const BRIDGE_GET_SOURCE_CONTROL_JOB_STATUS_REQUEST_TYPE = "get_source_control_job_status";
|
|
484
|
+
const BRIDGE_SOURCE_CONTROL_FILE_STATES = [
|
|
485
|
+
"checked_out_by_me",
|
|
486
|
+
"checked_out_by_other",
|
|
487
|
+
"marked_for_add",
|
|
488
|
+
"not_checked_out",
|
|
489
|
+
"not_in_depot",
|
|
490
|
+
"unknown"
|
|
491
|
+
];
|
|
492
|
+
const BRIDGE_SOURCE_CONTROL_STATUS_STATES = ["reported", "unsupported"];
|
|
493
|
+
const BRIDGE_SOURCE_CONTROL_JOB_ACCEPT_STATES = ["accepted", "unsupported"];
|
|
494
|
+
const BRIDGE_SOURCE_CONTROL_JOB_STATES = [
|
|
495
|
+
"running",
|
|
496
|
+
"succeeded",
|
|
497
|
+
"failed",
|
|
498
|
+
"unknown_job"
|
|
499
|
+
];
|
|
500
|
+
const BRIDGE_SOURCE_CONTROL_OPERATIONS = ["checkout", "refresh"];
|
|
462
501
|
const requestIdSchema = z.string().trim().min(1);
|
|
463
502
|
const nonEmptyStringSchema = z.string().trim().min(1);
|
|
464
503
|
const boundedStringSchema = z.string().trim().max(512);
|
|
@@ -568,6 +607,22 @@ const openLevelJobIdSchema = z.string().trim().min(1);
|
|
|
568
607
|
const levelPathSchema = z.string().trim().min(1).max(512);
|
|
569
608
|
const actorPathBatchSchema = z.array(actorPathSchema).min(1).max(64);
|
|
570
609
|
const actorTagArraySchema = z.array(boundedStringSchema).max(16);
|
|
610
|
+
const dataTableCursorSchema = z.number().int().min(0);
|
|
611
|
+
const dataTableMaxRowsSchema = z.number().int().min(1).max(100);
|
|
612
|
+
const dataTableRowNameSchema = z.string().trim().min(1).max(256);
|
|
613
|
+
const dataTableRowOperationSchema = z.enum(BRIDGE_DATA_TABLE_ROW_OPERATIONS);
|
|
614
|
+
const dataTableWriteStateSchema = z.enum(BRIDGE_DATA_TABLE_WRITE_STATES);
|
|
615
|
+
const dataTableFormatSchema = z.enum(BRIDGE_DATA_TABLE_FORMATS);
|
|
616
|
+
const dataTableValueMapSchema = z.record(z.string().trim().min(1).max(256), z.string().max(BRIDGE_DATA_TABLE_VALUE_MAX_CHARS)).refine((value) => Object.keys(value).length <= 200, { message: `A write carries at most ${String(200)} columns.` });
|
|
617
|
+
const dataTableImportContentSchema = z.string().min(1).max(BRIDGE_DATA_TABLE_MAX_IMPORT_CHARS);
|
|
618
|
+
const dataTableAssetNameSchema = z.string().trim().min(1).max(256).refine((value) => !value.includes("/") && !value.includes("."), { message: "An asset name must not contain a path separator; use destinationPath to move the asset." });
|
|
619
|
+
const sourceControlAssetPathBatchSchema = z.array(assetPathSchema).min(1).max(64);
|
|
620
|
+
const sourceControlFileStateSchema = z.enum(BRIDGE_SOURCE_CONTROL_FILE_STATES);
|
|
621
|
+
const sourceControlStatusStateSchema = z.enum(BRIDGE_SOURCE_CONTROL_STATUS_STATES);
|
|
622
|
+
const sourceControlJobAcceptStateSchema = z.enum(BRIDGE_SOURCE_CONTROL_JOB_ACCEPT_STATES);
|
|
623
|
+
const sourceControlJobStateSchema = z.enum(BRIDGE_SOURCE_CONTROL_JOB_STATES);
|
|
624
|
+
const sourceControlOperationSchema = z.enum(BRIDGE_SOURCE_CONTROL_OPERATIONS);
|
|
625
|
+
const sourceControlJobIdSchema = z.string().trim().min(1);
|
|
571
626
|
const vectorInputSchema = z.object({
|
|
572
627
|
x: z.number().default(0),
|
|
573
628
|
y: z.number().default(0),
|
|
@@ -972,6 +1027,111 @@ const bridgeGetOpenLevelStatusRequestSchema = z.object({
|
|
|
972
1027
|
type: z.literal(BRIDGE_GET_OPEN_LEVEL_STATUS_REQUEST_TYPE),
|
|
973
1028
|
version: z.literal(2)
|
|
974
1029
|
});
|
|
1030
|
+
const bridgeReadDataTableRequestSchema = z.object({
|
|
1031
|
+
assetPath: assetPathSchema,
|
|
1032
|
+
cursor: dataTableCursorSchema.default(0),
|
|
1033
|
+
loadIfNeeded: z.boolean().default(true),
|
|
1034
|
+
maxRows: dataTableMaxRowsSchema,
|
|
1035
|
+
rowNameFilter: boundedStringSchema.optional(),
|
|
1036
|
+
requestId: requestIdSchema,
|
|
1037
|
+
type: z.literal(BRIDGE_READ_DATA_TABLE_REQUEST_TYPE),
|
|
1038
|
+
version: z.literal(2)
|
|
1039
|
+
});
|
|
1040
|
+
const bridgeWriteDataTableRowRequestSchema = z.object({
|
|
1041
|
+
assetPath: assetPathSchema,
|
|
1042
|
+
dryRun: z.boolean().default(false),
|
|
1043
|
+
operation: dataTableRowOperationSchema,
|
|
1044
|
+
rowName: dataTableRowNameSchema,
|
|
1045
|
+
values: dataTableValueMapSchema.optional(),
|
|
1046
|
+
requestId: requestIdSchema,
|
|
1047
|
+
type: z.literal(BRIDGE_WRITE_DATA_TABLE_ROW_REQUEST_TYPE),
|
|
1048
|
+
version: z.literal(2)
|
|
1049
|
+
}).refine((value) => value.operation !== "upsert" || value.values !== void 0, {
|
|
1050
|
+
message: "A write_data_table_row upsert requires values.",
|
|
1051
|
+
path: ["values"]
|
|
1052
|
+
}).refine((value) => value.operation !== "delete" || value.values === void 0, {
|
|
1053
|
+
message: "A write_data_table_row delete must not carry values.",
|
|
1054
|
+
path: ["values"]
|
|
1055
|
+
});
|
|
1056
|
+
const bridgeExportDataTableRequestSchema = z.object({
|
|
1057
|
+
assetPath: assetPathSchema,
|
|
1058
|
+
cursor: dataTableCursorSchema.default(0),
|
|
1059
|
+
format: dataTableFormatSchema.default("json"),
|
|
1060
|
+
loadIfNeeded: z.boolean().default(true),
|
|
1061
|
+
requestId: requestIdSchema,
|
|
1062
|
+
type: z.literal(BRIDGE_EXPORT_DATA_TABLE_REQUEST_TYPE),
|
|
1063
|
+
version: z.literal(2)
|
|
1064
|
+
});
|
|
1065
|
+
const bridgeImportDataTableRequestSchema = z.object({
|
|
1066
|
+
assetPath: assetPathSchema,
|
|
1067
|
+
content: dataTableImportContentSchema,
|
|
1068
|
+
dryRun: z.boolean().default(false),
|
|
1069
|
+
format: dataTableFormatSchema.default("json"),
|
|
1070
|
+
requestId: requestIdSchema,
|
|
1071
|
+
type: z.literal(BRIDGE_IMPORT_DATA_TABLE_REQUEST_TYPE),
|
|
1072
|
+
version: z.literal(2)
|
|
1073
|
+
});
|
|
1074
|
+
const bridgeCreateDataTableRequestSchema = z.object({
|
|
1075
|
+
assetPath: assetPathSchema,
|
|
1076
|
+
dryRun: z.boolean().default(false),
|
|
1077
|
+
rowStructPath: assetPathSchema,
|
|
1078
|
+
requestId: requestIdSchema,
|
|
1079
|
+
type: z.literal(BRIDGE_CREATE_DATA_TABLE_REQUEST_TYPE),
|
|
1080
|
+
version: z.literal(2)
|
|
1081
|
+
});
|
|
1082
|
+
const bridgeRenameDataTableRequestSchema = z.object({
|
|
1083
|
+
assetPath: assetPathSchema,
|
|
1084
|
+
destinationPath: assetPathSchema.optional(),
|
|
1085
|
+
dryRun: z.boolean().default(false),
|
|
1086
|
+
newName: dataTableAssetNameSchema.optional(),
|
|
1087
|
+
requestId: requestIdSchema,
|
|
1088
|
+
type: z.literal(BRIDGE_RENAME_DATA_TABLE_REQUEST_TYPE),
|
|
1089
|
+
version: z.literal(2)
|
|
1090
|
+
}).refine((value) => value.newName !== void 0 || value.destinationPath !== void 0, {
|
|
1091
|
+
message: "A rename_data_table requires a newName, a destinationPath, or both.",
|
|
1092
|
+
path: ["newName"]
|
|
1093
|
+
});
|
|
1094
|
+
const bridgeDeleteDataTableRequestSchema = z.object({
|
|
1095
|
+
assetPath: assetPathSchema,
|
|
1096
|
+
dryRun: z.boolean().default(false),
|
|
1097
|
+
force: z.boolean().default(false),
|
|
1098
|
+
requestId: requestIdSchema,
|
|
1099
|
+
type: z.literal(BRIDGE_DELETE_DATA_TABLE_REQUEST_TYPE),
|
|
1100
|
+
version: z.literal(2)
|
|
1101
|
+
});
|
|
1102
|
+
const bridgeRenameDataTableRowRequestSchema = z.object({
|
|
1103
|
+
assetPath: assetPathSchema,
|
|
1104
|
+
dryRun: z.boolean().default(false),
|
|
1105
|
+
newRowName: dataTableRowNameSchema,
|
|
1106
|
+
rowName: dataTableRowNameSchema,
|
|
1107
|
+
requestId: requestIdSchema,
|
|
1108
|
+
type: z.literal(BRIDGE_RENAME_DATA_TABLE_ROW_REQUEST_TYPE),
|
|
1109
|
+
version: z.literal(2)
|
|
1110
|
+
});
|
|
1111
|
+
const bridgeGetSourceControlStatusRequestSchema = z.object({
|
|
1112
|
+
assetPaths: sourceControlAssetPathBatchSchema,
|
|
1113
|
+
requestId: requestIdSchema,
|
|
1114
|
+
type: z.literal(BRIDGE_GET_SOURCE_CONTROL_STATUS_REQUEST_TYPE),
|
|
1115
|
+
version: z.literal(2)
|
|
1116
|
+
});
|
|
1117
|
+
const bridgeRefreshSourceControlStatusRequestSchema = z.object({
|
|
1118
|
+
assetPaths: sourceControlAssetPathBatchSchema,
|
|
1119
|
+
requestId: requestIdSchema,
|
|
1120
|
+
type: z.literal(BRIDGE_REFRESH_SOURCE_CONTROL_STATUS_REQUEST_TYPE),
|
|
1121
|
+
version: z.literal(2)
|
|
1122
|
+
});
|
|
1123
|
+
const bridgeCheckoutAssetsRequestSchema = z.object({
|
|
1124
|
+
assetPaths: sourceControlAssetPathBatchSchema,
|
|
1125
|
+
requestId: requestIdSchema,
|
|
1126
|
+
type: z.literal(BRIDGE_CHECKOUT_ASSETS_REQUEST_TYPE),
|
|
1127
|
+
version: z.literal(2)
|
|
1128
|
+
});
|
|
1129
|
+
const bridgeGetSourceControlJobStatusRequestSchema = z.object({
|
|
1130
|
+
requestId: requestIdSchema,
|
|
1131
|
+
sourceControlJobId: sourceControlJobIdSchema,
|
|
1132
|
+
type: z.literal(BRIDGE_GET_SOURCE_CONTROL_JOB_STATUS_REQUEST_TYPE),
|
|
1133
|
+
version: z.literal(2)
|
|
1134
|
+
});
|
|
975
1135
|
const bridgeGetAssetDependenciesRequestSchema = z.object({
|
|
976
1136
|
assetPath: assetPathSchema,
|
|
977
1137
|
categories: z.array(assetDependencyCategorySchema).max(BRIDGE_ASSET_DEPENDENCY_CATEGORIES.length).default(["package"]),
|
|
@@ -1714,6 +1874,211 @@ const bridgeGetOpenLevelStatusSuccessResponseSchema = z.object({
|
|
|
1714
1874
|
path: ["finishedAt"]
|
|
1715
1875
|
});
|
|
1716
1876
|
});
|
|
1877
|
+
const bridgeDataTableColumnSchema = z.object({
|
|
1878
|
+
name: z.string(),
|
|
1879
|
+
type: z.string()
|
|
1880
|
+
});
|
|
1881
|
+
const bridgeDataTableRowSchema = z.object({
|
|
1882
|
+
rowName: z.string(),
|
|
1883
|
+
values: z.record(z.string(), z.string())
|
|
1884
|
+
});
|
|
1885
|
+
const bridgeReadDataTableSuccessResponseSchema = z.object({
|
|
1886
|
+
assetPath: z.string(),
|
|
1887
|
+
columns: z.array(bridgeDataTableColumnSchema).max(200),
|
|
1888
|
+
columnsTruncated: z.boolean(),
|
|
1889
|
+
nextCursor: dataTableCursorSchema.optional(),
|
|
1890
|
+
ok: z.literal(true),
|
|
1891
|
+
requestId: requestIdSchema,
|
|
1892
|
+
rows: z.array(bridgeDataTableRowSchema).max(100),
|
|
1893
|
+
rowStructName: z.string(),
|
|
1894
|
+
rowStructPath: z.string(),
|
|
1895
|
+
totalRowCount: z.number().int().min(0),
|
|
1896
|
+
truncated: z.boolean(),
|
|
1897
|
+
type: z.literal(BRIDGE_READ_DATA_TABLE_REQUEST_TYPE),
|
|
1898
|
+
valueTruncated: z.boolean(),
|
|
1899
|
+
version: z.literal(2)
|
|
1900
|
+
});
|
|
1901
|
+
const bridgeWriteDataTableRowSuccessResponseSchema = z.object({
|
|
1902
|
+
applied: dataTableRowOperationSchema,
|
|
1903
|
+
assetPath: z.string(),
|
|
1904
|
+
created: z.boolean(),
|
|
1905
|
+
dryRun: z.boolean(),
|
|
1906
|
+
message: z.string().trim().min(1).optional(),
|
|
1907
|
+
ok: z.literal(true),
|
|
1908
|
+
packageDirty: z.boolean(),
|
|
1909
|
+
requestId: requestIdSchema,
|
|
1910
|
+
rowExisted: z.boolean(),
|
|
1911
|
+
rowName: z.string(),
|
|
1912
|
+
state: dataTableWriteStateSchema,
|
|
1913
|
+
transactionTitle: z.string().trim().min(1).optional(),
|
|
1914
|
+
type: z.literal(BRIDGE_WRITE_DATA_TABLE_ROW_REQUEST_TYPE),
|
|
1915
|
+
version: z.literal(2)
|
|
1916
|
+
}).refine(isLevelEditStateConsistent, levelEditStateRefinement);
|
|
1917
|
+
const bridgeExportDataTableSuccessResponseSchema = z.object({
|
|
1918
|
+
assetPath: z.string(),
|
|
1919
|
+
content: z.string().max(BRIDGE_DATA_TABLE_MAX_EXPORT_CHARS),
|
|
1920
|
+
format: dataTableFormatSchema,
|
|
1921
|
+
nextCursor: dataTableCursorSchema.optional(),
|
|
1922
|
+
ok: z.literal(true),
|
|
1923
|
+
requestId: requestIdSchema,
|
|
1924
|
+
rowCount: z.number().int().min(0),
|
|
1925
|
+
totalChars: z.number().int().min(0),
|
|
1926
|
+
truncated: z.boolean(),
|
|
1927
|
+
type: z.literal(BRIDGE_EXPORT_DATA_TABLE_REQUEST_TYPE),
|
|
1928
|
+
version: z.literal(2)
|
|
1929
|
+
});
|
|
1930
|
+
const bridgeImportDataTableSuccessResponseSchema = z.object({
|
|
1931
|
+
assetPath: z.string(),
|
|
1932
|
+
dryRun: z.boolean(),
|
|
1933
|
+
message: z.string().trim().min(1).optional(),
|
|
1934
|
+
ok: z.literal(true),
|
|
1935
|
+
packageDirty: z.boolean(),
|
|
1936
|
+
problemCount: z.number().int().min(0),
|
|
1937
|
+
problems: z.array(z.string()).max(50),
|
|
1938
|
+
replacedRowCount: z.number().int().min(0),
|
|
1939
|
+
requestId: requestIdSchema,
|
|
1940
|
+
rowCount: z.number().int().min(0),
|
|
1941
|
+
state: dataTableWriteStateSchema,
|
|
1942
|
+
transactionTitle: z.string().trim().min(1).optional(),
|
|
1943
|
+
type: z.literal(BRIDGE_IMPORT_DATA_TABLE_REQUEST_TYPE),
|
|
1944
|
+
version: z.literal(2)
|
|
1945
|
+
}).refine(isLevelEditStateConsistent, levelEditStateRefinement);
|
|
1946
|
+
const bridgeCreateDataTableSuccessResponseSchema = z.object({
|
|
1947
|
+
assetPath: z.string(),
|
|
1948
|
+
created: z.boolean(),
|
|
1949
|
+
dryRun: z.boolean(),
|
|
1950
|
+
ok: z.literal(true),
|
|
1951
|
+
packageDirty: z.boolean(),
|
|
1952
|
+
requestId: requestIdSchema,
|
|
1953
|
+
rowStructPath: z.string(),
|
|
1954
|
+
state: dataTableWriteStateSchema,
|
|
1955
|
+
type: z.literal(BRIDGE_CREATE_DATA_TABLE_REQUEST_TYPE),
|
|
1956
|
+
version: z.literal(2)
|
|
1957
|
+
}).refine(isLevelEditStateConsistent, levelEditStateRefinement);
|
|
1958
|
+
const bridgeRenameDataTableSuccessResponseSchema = z.object({
|
|
1959
|
+
assetPath: z.string(),
|
|
1960
|
+
dryRun: z.boolean(),
|
|
1961
|
+
leftRedirector: z.boolean().optional(),
|
|
1962
|
+
newAssetPath: z.string(),
|
|
1963
|
+
ok: z.literal(true),
|
|
1964
|
+
packageDirty: z.boolean(),
|
|
1965
|
+
renamed: z.boolean(),
|
|
1966
|
+
requestId: requestIdSchema,
|
|
1967
|
+
state: dataTableWriteStateSchema,
|
|
1968
|
+
type: z.literal(BRIDGE_RENAME_DATA_TABLE_REQUEST_TYPE),
|
|
1969
|
+
version: z.literal(2)
|
|
1970
|
+
}).refine(isLevelEditStateConsistent, levelEditStateRefinement);
|
|
1971
|
+
const bridgeDeleteDataTableSuccessResponseSchema = z.object({
|
|
1972
|
+
assetPath: z.string(),
|
|
1973
|
+
deleted: z.boolean(),
|
|
1974
|
+
dryRun: z.boolean(),
|
|
1975
|
+
forced: z.boolean(),
|
|
1976
|
+
ok: z.literal(true),
|
|
1977
|
+
referencerCount: z.number().int().min(0),
|
|
1978
|
+
referencers: z.array(z.string()).max(25),
|
|
1979
|
+
requestId: requestIdSchema,
|
|
1980
|
+
state: dataTableWriteStateSchema,
|
|
1981
|
+
type: z.literal(BRIDGE_DELETE_DATA_TABLE_REQUEST_TYPE),
|
|
1982
|
+
version: z.literal(2)
|
|
1983
|
+
}).refine(isLevelEditStateConsistent, levelEditStateRefinement);
|
|
1984
|
+
const bridgeRenameDataTableRowSuccessResponseSchema = z.object({
|
|
1985
|
+
assetPath: z.string(),
|
|
1986
|
+
dryRun: z.boolean(),
|
|
1987
|
+
newRowName: z.string(),
|
|
1988
|
+
ok: z.literal(true),
|
|
1989
|
+
packageDirty: z.boolean(),
|
|
1990
|
+
renamed: z.boolean(),
|
|
1991
|
+
requestId: requestIdSchema,
|
|
1992
|
+
rowName: z.string(),
|
|
1993
|
+
state: dataTableWriteStateSchema,
|
|
1994
|
+
transactionTitle: z.string().trim().min(1).optional(),
|
|
1995
|
+
type: z.literal(BRIDGE_RENAME_DATA_TABLE_ROW_REQUEST_TYPE),
|
|
1996
|
+
version: z.literal(2)
|
|
1997
|
+
}).refine(isLevelEditStateConsistent, levelEditStateRefinement);
|
|
1998
|
+
const bridgeSourceControlFileStateSchema = z.object({
|
|
1999
|
+
assetPath: z.string(),
|
|
2000
|
+
checkedOutBy: z.string().trim().min(1).optional(),
|
|
2001
|
+
error: z.string().optional(),
|
|
2002
|
+
index: z.number().int().min(0),
|
|
2003
|
+
state: sourceControlFileStateSchema
|
|
2004
|
+
});
|
|
2005
|
+
const bridgeGetSourceControlStatusSuccessResponseSchema = z.object({
|
|
2006
|
+
available: z.boolean(),
|
|
2007
|
+
enabled: z.boolean(),
|
|
2008
|
+
files: z.array(bridgeSourceControlFileStateSchema).max(64),
|
|
2009
|
+
message: nonEmptyStringSchema.optional(),
|
|
2010
|
+
ok: z.literal(true),
|
|
2011
|
+
provider: z.string().trim().min(1),
|
|
2012
|
+
requestId: requestIdSchema,
|
|
2013
|
+
state: sourceControlStatusStateSchema,
|
|
2014
|
+
type: z.literal(BRIDGE_GET_SOURCE_CONTROL_STATUS_REQUEST_TYPE),
|
|
2015
|
+
version: z.literal(2)
|
|
2016
|
+
}).refine((value) => value.state === "reported" || value.files.length === 0, {
|
|
2017
|
+
message: "An unsupported get_source_control_status response must carry no file entries.",
|
|
2018
|
+
path: ["files"]
|
|
2019
|
+
});
|
|
2020
|
+
const sourceControlJobAcceptFields = {
|
|
2021
|
+
message: nonEmptyStringSchema.optional(),
|
|
2022
|
+
ok: z.literal(true),
|
|
2023
|
+
requestId: requestIdSchema,
|
|
2024
|
+
sourceControlJobId: sourceControlJobIdSchema.optional(),
|
|
2025
|
+
state: sourceControlJobAcceptStateSchema,
|
|
2026
|
+
version: z.literal(2)
|
|
2027
|
+
};
|
|
2028
|
+
const sourceControlJobAcceptRefinement = {
|
|
2029
|
+
message: "A source control response must carry sourceControlJobId exactly when state is 'accepted'.",
|
|
2030
|
+
path: ["sourceControlJobId"]
|
|
2031
|
+
};
|
|
2032
|
+
function isSourceControlJobAcceptConsistent(value) {
|
|
2033
|
+
return value.state === "accepted" === (value.sourceControlJobId !== void 0);
|
|
2034
|
+
}
|
|
2035
|
+
const bridgeRefreshSourceControlStatusSuccessResponseSchema = z.object({
|
|
2036
|
+
...sourceControlJobAcceptFields,
|
|
2037
|
+
type: z.literal(BRIDGE_REFRESH_SOURCE_CONTROL_STATUS_REQUEST_TYPE)
|
|
2038
|
+
}).refine(isSourceControlJobAcceptConsistent, sourceControlJobAcceptRefinement);
|
|
2039
|
+
const bridgeCheckoutAssetsSuccessResponseSchema = z.object({
|
|
2040
|
+
...sourceControlJobAcceptFields,
|
|
2041
|
+
type: z.literal(BRIDGE_CHECKOUT_ASSETS_REQUEST_TYPE)
|
|
2042
|
+
}).refine(isSourceControlJobAcceptConsistent, sourceControlJobAcceptRefinement);
|
|
2043
|
+
const bridgeSourceControlJobItemResultSchema = z.object({
|
|
2044
|
+
assetPath: z.string(),
|
|
2045
|
+
error: z.string().optional(),
|
|
2046
|
+
index: z.number().int().min(0),
|
|
2047
|
+
ok: z.boolean(),
|
|
2048
|
+
state: sourceControlFileStateSchema
|
|
2049
|
+
});
|
|
2050
|
+
const bridgeGetSourceControlJobStatusSuccessResponseSchema = z.object({
|
|
2051
|
+
durationMs: z.number().int().min(0).optional(),
|
|
2052
|
+
failureCount: z.number().int().min(0),
|
|
2053
|
+
finishedAt: nonEmptyStringSchema.optional(),
|
|
2054
|
+
message: nonEmptyStringSchema.optional(),
|
|
2055
|
+
ok: z.literal(true),
|
|
2056
|
+
operation: sourceControlOperationSchema.optional(),
|
|
2057
|
+
requestId: requestIdSchema,
|
|
2058
|
+
results: z.array(bridgeSourceControlJobItemResultSchema).max(64),
|
|
2059
|
+
sourceControlJobId: sourceControlJobIdSchema,
|
|
2060
|
+
state: sourceControlJobStateSchema,
|
|
2061
|
+
successCount: z.number().int().min(0),
|
|
2062
|
+
type: z.literal(BRIDGE_GET_SOURCE_CONTROL_JOB_STATUS_REQUEST_TYPE),
|
|
2063
|
+
version: z.literal(2)
|
|
2064
|
+
}).superRefine((value, ctx) => {
|
|
2065
|
+
if (value.state === "succeeded" || value.state === "failed") return;
|
|
2066
|
+
if (value.durationMs !== void 0) ctx.addIssue({
|
|
2067
|
+
code: z.ZodIssueCode.custom,
|
|
2068
|
+
message: "durationMs must be absent until the job finishes",
|
|
2069
|
+
path: ["durationMs"]
|
|
2070
|
+
});
|
|
2071
|
+
if (value.finishedAt !== void 0) ctx.addIssue({
|
|
2072
|
+
code: z.ZodIssueCode.custom,
|
|
2073
|
+
message: "finishedAt must be absent until the job finishes",
|
|
2074
|
+
path: ["finishedAt"]
|
|
2075
|
+
});
|
|
2076
|
+
if (value.results.length > 0) ctx.addIssue({
|
|
2077
|
+
code: z.ZodIssueCode.custom,
|
|
2078
|
+
message: "results must be empty until the job finishes",
|
|
2079
|
+
path: ["results"]
|
|
2080
|
+
});
|
|
2081
|
+
});
|
|
1717
2082
|
const bridgeAssetDependencySchema = z.object({
|
|
1718
2083
|
category: assetDependencyCategorySchema,
|
|
1719
2084
|
isHard: z.boolean(),
|
|
@@ -1991,6 +2356,18 @@ const bridgeUndoResponseSchema = z.union([bridgeUndoSuccessResponseSchema, bridg
|
|
|
1991
2356
|
const bridgeRedoResponseSchema = z.union([bridgeRedoSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
1992
2357
|
const bridgeOpenLevelResponseSchema = z.union([bridgeOpenLevelSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
1993
2358
|
const bridgeGetOpenLevelStatusResponseSchema = z.union([bridgeGetOpenLevelStatusSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2359
|
+
const bridgeReadDataTableResponseSchema = z.union([bridgeReadDataTableSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2360
|
+
const bridgeWriteDataTableRowResponseSchema = z.union([bridgeWriteDataTableRowSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2361
|
+
const bridgeExportDataTableResponseSchema = z.union([bridgeExportDataTableSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2362
|
+
const bridgeImportDataTableResponseSchema = z.union([bridgeImportDataTableSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2363
|
+
const bridgeCreateDataTableResponseSchema = z.union([bridgeCreateDataTableSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2364
|
+
const bridgeRenameDataTableResponseSchema = z.union([bridgeRenameDataTableSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2365
|
+
const bridgeDeleteDataTableResponseSchema = z.union([bridgeDeleteDataTableSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2366
|
+
const bridgeRenameDataTableRowResponseSchema = z.union([bridgeRenameDataTableRowSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2367
|
+
const bridgeGetSourceControlStatusResponseSchema = z.union([bridgeGetSourceControlStatusSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2368
|
+
const bridgeRefreshSourceControlStatusResponseSchema = z.union([bridgeRefreshSourceControlStatusSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2369
|
+
const bridgeCheckoutAssetsResponseSchema = z.union([bridgeCheckoutAssetsSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2370
|
+
const bridgeGetSourceControlJobStatusResponseSchema = z.union([bridgeGetSourceControlJobStatusSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
1994
2371
|
const bridgeFindAssetsResponseSchema = z.union([bridgeFindAssetsSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
1995
2372
|
const bridgeGetAssetDependenciesResponseSchema = z.union([bridgeGetAssetDependenciesSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
1996
2373
|
const bridgeFindBlueprintReferencesResponseSchema = z.union([bridgeFindBlueprintReferencesSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
@@ -2002,6 +2379,126 @@ const bridgeGetBlueprintCompileStatusResponseSchema = z.union([bridgeGetBlueprin
|
|
|
2002
2379
|
const bridgeGetConfigValueResponseSchema = z.union([bridgeGetConfigValueSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2003
2380
|
const bridgeSetConfigValueResponseSchema = z.union([bridgeSetConfigValueSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2004
2381
|
const bridgeListConfigSectionResponseSchema = z.union([bridgeListConfigSectionSuccessResponseSchema, bridgeErrorResponseSchema]);
|
|
2382
|
+
function createBridgeReadDataTableRequest(assetPath, options = {}, requestId = randomUUID()) {
|
|
2383
|
+
return bridgeReadDataTableRequestSchema.parse({
|
|
2384
|
+
assetPath,
|
|
2385
|
+
cursor: options.cursor,
|
|
2386
|
+
loadIfNeeded: options.loadIfNeeded,
|
|
2387
|
+
maxRows: options.maxRows ?? 25,
|
|
2388
|
+
requestId,
|
|
2389
|
+
rowNameFilter: options.rowNameFilter,
|
|
2390
|
+
type: BRIDGE_READ_DATA_TABLE_REQUEST_TYPE,
|
|
2391
|
+
version: 2
|
|
2392
|
+
});
|
|
2393
|
+
}
|
|
2394
|
+
function createBridgeWriteDataTableRowRequest(assetPath, rowName, operation, options = {}, requestId = randomUUID()) {
|
|
2395
|
+
return bridgeWriteDataTableRowRequestSchema.parse({
|
|
2396
|
+
assetPath,
|
|
2397
|
+
dryRun: options.dryRun,
|
|
2398
|
+
operation,
|
|
2399
|
+
requestId,
|
|
2400
|
+
rowName,
|
|
2401
|
+
type: BRIDGE_WRITE_DATA_TABLE_ROW_REQUEST_TYPE,
|
|
2402
|
+
values: options.values,
|
|
2403
|
+
version: 2
|
|
2404
|
+
});
|
|
2405
|
+
}
|
|
2406
|
+
function createBridgeExportDataTableRequest(assetPath, options = {}, requestId = randomUUID()) {
|
|
2407
|
+
return bridgeExportDataTableRequestSchema.parse({
|
|
2408
|
+
assetPath,
|
|
2409
|
+
cursor: options.cursor,
|
|
2410
|
+
format: options.format,
|
|
2411
|
+
loadIfNeeded: options.loadIfNeeded,
|
|
2412
|
+
requestId,
|
|
2413
|
+
type: BRIDGE_EXPORT_DATA_TABLE_REQUEST_TYPE,
|
|
2414
|
+
version: 2
|
|
2415
|
+
});
|
|
2416
|
+
}
|
|
2417
|
+
function createBridgeImportDataTableRequest(assetPath, content, options = {}, requestId = randomUUID()) {
|
|
2418
|
+
return bridgeImportDataTableRequestSchema.parse({
|
|
2419
|
+
assetPath,
|
|
2420
|
+
content,
|
|
2421
|
+
dryRun: options.dryRun,
|
|
2422
|
+
format: options.format,
|
|
2423
|
+
requestId,
|
|
2424
|
+
type: BRIDGE_IMPORT_DATA_TABLE_REQUEST_TYPE,
|
|
2425
|
+
version: 2
|
|
2426
|
+
});
|
|
2427
|
+
}
|
|
2428
|
+
function createBridgeCreateDataTableRequest(assetPath, rowStructPath, options = {}, requestId = randomUUID()) {
|
|
2429
|
+
return bridgeCreateDataTableRequestSchema.parse({
|
|
2430
|
+
assetPath,
|
|
2431
|
+
dryRun: options.dryRun,
|
|
2432
|
+
requestId,
|
|
2433
|
+
rowStructPath,
|
|
2434
|
+
type: BRIDGE_CREATE_DATA_TABLE_REQUEST_TYPE,
|
|
2435
|
+
version: 2
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
2438
|
+
function createBridgeRenameDataTableRequest(assetPath, options = {}, requestId = randomUUID()) {
|
|
2439
|
+
return bridgeRenameDataTableRequestSchema.parse({
|
|
2440
|
+
assetPath,
|
|
2441
|
+
destinationPath: options.destinationPath,
|
|
2442
|
+
dryRun: options.dryRun,
|
|
2443
|
+
newName: options.newName,
|
|
2444
|
+
requestId,
|
|
2445
|
+
type: BRIDGE_RENAME_DATA_TABLE_REQUEST_TYPE,
|
|
2446
|
+
version: 2
|
|
2447
|
+
});
|
|
2448
|
+
}
|
|
2449
|
+
function createBridgeDeleteDataTableRequest(assetPath, options = {}, requestId = randomUUID()) {
|
|
2450
|
+
return bridgeDeleteDataTableRequestSchema.parse({
|
|
2451
|
+
assetPath,
|
|
2452
|
+
dryRun: options.dryRun,
|
|
2453
|
+
force: options.force,
|
|
2454
|
+
requestId,
|
|
2455
|
+
type: BRIDGE_DELETE_DATA_TABLE_REQUEST_TYPE,
|
|
2456
|
+
version: 2
|
|
2457
|
+
});
|
|
2458
|
+
}
|
|
2459
|
+
function createBridgeRenameDataTableRowRequest(assetPath, rowName, newRowName, options = {}, requestId = randomUUID()) {
|
|
2460
|
+
return bridgeRenameDataTableRowRequestSchema.parse({
|
|
2461
|
+
assetPath,
|
|
2462
|
+
dryRun: options.dryRun,
|
|
2463
|
+
newRowName,
|
|
2464
|
+
requestId,
|
|
2465
|
+
rowName,
|
|
2466
|
+
type: BRIDGE_RENAME_DATA_TABLE_ROW_REQUEST_TYPE,
|
|
2467
|
+
version: 2
|
|
2468
|
+
});
|
|
2469
|
+
}
|
|
2470
|
+
function createBridgeGetSourceControlStatusRequest(assetPaths, requestId = randomUUID()) {
|
|
2471
|
+
return bridgeGetSourceControlStatusRequestSchema.parse({
|
|
2472
|
+
assetPaths,
|
|
2473
|
+
requestId,
|
|
2474
|
+
type: BRIDGE_GET_SOURCE_CONTROL_STATUS_REQUEST_TYPE,
|
|
2475
|
+
version: 2
|
|
2476
|
+
});
|
|
2477
|
+
}
|
|
2478
|
+
function createBridgeRefreshSourceControlStatusRequest(assetPaths, requestId = randomUUID()) {
|
|
2479
|
+
return bridgeRefreshSourceControlStatusRequestSchema.parse({
|
|
2480
|
+
assetPaths,
|
|
2481
|
+
requestId,
|
|
2482
|
+
type: BRIDGE_REFRESH_SOURCE_CONTROL_STATUS_REQUEST_TYPE,
|
|
2483
|
+
version: 2
|
|
2484
|
+
});
|
|
2485
|
+
}
|
|
2486
|
+
function createBridgeCheckoutAssetsRequest(assetPaths, requestId = randomUUID()) {
|
|
2487
|
+
return bridgeCheckoutAssetsRequestSchema.parse({
|
|
2488
|
+
assetPaths,
|
|
2489
|
+
requestId,
|
|
2490
|
+
type: BRIDGE_CHECKOUT_ASSETS_REQUEST_TYPE,
|
|
2491
|
+
version: 2
|
|
2492
|
+
});
|
|
2493
|
+
}
|
|
2494
|
+
function createBridgeGetSourceControlJobStatusRequest(sourceControlJobId, requestId = randomUUID()) {
|
|
2495
|
+
return bridgeGetSourceControlJobStatusRequestSchema.parse({
|
|
2496
|
+
requestId,
|
|
2497
|
+
sourceControlJobId,
|
|
2498
|
+
type: BRIDGE_GET_SOURCE_CONTROL_JOB_STATUS_REQUEST_TYPE,
|
|
2499
|
+
version: 2
|
|
2500
|
+
});
|
|
2501
|
+
}
|
|
2005
2502
|
function createBridgeFindAssetsRequest(options = {}, requestId = randomUUID()) {
|
|
2006
2503
|
return bridgeFindAssetsRequestSchema.parse({
|
|
2007
2504
|
classNames: options.classNames,
|
|
@@ -2569,6 +3066,30 @@ async function sendBridgeStartTraceRequest(request, options) {
|
|
|
2569
3066
|
async function sendBridgeStopTraceRequest(request, options) {
|
|
2570
3067
|
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeStopTraceResponseSchema, request.requestId);
|
|
2571
3068
|
}
|
|
3069
|
+
async function sendBridgeReadDataTableRequest(request, options) {
|
|
3070
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeReadDataTableResponseSchema, request.requestId);
|
|
3071
|
+
}
|
|
3072
|
+
async function sendBridgeWriteDataTableRowRequest(request, options) {
|
|
3073
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeWriteDataTableRowResponseSchema, request.requestId);
|
|
3074
|
+
}
|
|
3075
|
+
async function sendBridgeExportDataTableRequest(request, options) {
|
|
3076
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeExportDataTableResponseSchema, request.requestId);
|
|
3077
|
+
}
|
|
3078
|
+
async function sendBridgeImportDataTableRequest(request, options) {
|
|
3079
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeImportDataTableResponseSchema, request.requestId);
|
|
3080
|
+
}
|
|
3081
|
+
async function sendBridgeCreateDataTableRequest(request, options) {
|
|
3082
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeCreateDataTableResponseSchema, request.requestId);
|
|
3083
|
+
}
|
|
3084
|
+
async function sendBridgeRenameDataTableRequest(request, options) {
|
|
3085
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeRenameDataTableResponseSchema, request.requestId);
|
|
3086
|
+
}
|
|
3087
|
+
async function sendBridgeDeleteDataTableRequest(request, options) {
|
|
3088
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeDeleteDataTableResponseSchema, request.requestId);
|
|
3089
|
+
}
|
|
3090
|
+
async function sendBridgeRenameDataTableRowRequest(request, options) {
|
|
3091
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeRenameDataTableRowResponseSchema, request.requestId);
|
|
3092
|
+
}
|
|
2572
3093
|
async function sendBridgeFindAssetsRequest(request, options) {
|
|
2573
3094
|
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeFindAssetsResponseSchema, request.requestId);
|
|
2574
3095
|
}
|
|
@@ -2608,6 +3129,18 @@ async function sendBridgeOpenLevelRequest(request, options) {
|
|
|
2608
3129
|
async function sendBridgeGetOpenLevelStatusRequest(request, options) {
|
|
2609
3130
|
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetOpenLevelStatusResponseSchema, request.requestId);
|
|
2610
3131
|
}
|
|
3132
|
+
async function sendBridgeGetSourceControlStatusRequest(request, options) {
|
|
3133
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetSourceControlStatusResponseSchema, request.requestId);
|
|
3134
|
+
}
|
|
3135
|
+
async function sendBridgeRefreshSourceControlStatusRequest(request, options) {
|
|
3136
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeRefreshSourceControlStatusResponseSchema, request.requestId);
|
|
3137
|
+
}
|
|
3138
|
+
async function sendBridgeCheckoutAssetsRequest(request, options) {
|
|
3139
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeCheckoutAssetsResponseSchema, request.requestId);
|
|
3140
|
+
}
|
|
3141
|
+
async function sendBridgeGetSourceControlJobStatusRequest(request, options) {
|
|
3142
|
+
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetSourceControlJobStatusResponseSchema, request.requestId);
|
|
3143
|
+
}
|
|
2611
3144
|
async function sendBridgeGetAssetDependenciesRequest(request, options) {
|
|
2612
3145
|
return parseBridgeResponse(await exchangeBridgeMessage(encodeBridgeFrame(request), options), bridgeGetAssetDependenciesResponseSchema, request.requestId);
|
|
2613
3146
|
}
|
|
@@ -4915,6 +5448,7 @@ const WAIT_FOR_JOB_KINDS = [
|
|
|
4915
5448
|
"compile",
|
|
4916
5449
|
"create_class",
|
|
4917
5450
|
"pie",
|
|
5451
|
+
"source_control",
|
|
4918
5452
|
"test_run"
|
|
4919
5453
|
];
|
|
4920
5454
|
const WAIT_FOR_JOB_MAX_TIMEOUT_MS = 6e5;
|
|
@@ -4922,6 +5456,7 @@ const WAIT_FOR_JOB_DEFAULT_TIMEOUT_MS = {
|
|
|
4922
5456
|
compile: 12e4,
|
|
4923
5457
|
create_class: 6e4,
|
|
4924
5458
|
pie: 3e4,
|
|
5459
|
+
source_control: 6e4,
|
|
4925
5460
|
test_run: 3e5
|
|
4926
5461
|
};
|
|
4927
5462
|
const WAIT_FOR_JOB_POLL_CADENCE_MS = {
|
|
@@ -4937,6 +5472,10 @@ const WAIT_FOR_JOB_POLL_CADENCE_MS = {
|
|
|
4937
5472
|
capMs: 2e3,
|
|
4938
5473
|
initialMs: 250
|
|
4939
5474
|
},
|
|
5475
|
+
source_control: {
|
|
5476
|
+
capMs: 2e3,
|
|
5477
|
+
initialMs: 250
|
|
5478
|
+
},
|
|
4940
5479
|
test_run: {
|
|
4941
5480
|
capMs: 5e3,
|
|
4942
5481
|
initialMs: 1e3
|
|
@@ -5044,7 +5583,7 @@ const waitForJobInputSchema = {
|
|
|
5044
5583
|
jobId: z.string().trim().min(1).max(512).describe("Job identifier to wait on: compileJobId (compile), createClassJobId (create_class), testRunId (test_run), or pieSessionId (pie)."),
|
|
5045
5584
|
kind: z.enum(WAIT_FOR_JOB_KINDS).describe("Which async job the id belongs to. Required — job ids are bare GUIDs and carry no type tag, so the kind cannot be inferred."),
|
|
5046
5585
|
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor owns the job."),
|
|
5047
|
-
timeoutMs: z.number().int().min(1).optional().describe(`Wall-clock budget for the wait, clamped to ${String(WAIT_FOR_JOB_MAX_TIMEOUT_MS)}ms. Defaults per kind: compile ${String(WAIT_FOR_JOB_DEFAULT_TIMEOUT_MS.compile)}ms, create_class ${String(WAIT_FOR_JOB_DEFAULT_TIMEOUT_MS.create_class)}ms, pie ${String(WAIT_FOR_JOB_DEFAULT_TIMEOUT_MS.pie)}ms, test_run ${String(WAIT_FOR_JOB_DEFAULT_TIMEOUT_MS.test_run)}ms.`)
|
|
5586
|
+
timeoutMs: z.number().int().min(1).optional().describe(`Wall-clock budget for the wait, clamped to ${String(WAIT_FOR_JOB_MAX_TIMEOUT_MS)}ms. Defaults per kind: compile ${String(WAIT_FOR_JOB_DEFAULT_TIMEOUT_MS.compile)}ms, create_class ${String(WAIT_FOR_JOB_DEFAULT_TIMEOUT_MS.create_class)}ms, pie ${String(WAIT_FOR_JOB_DEFAULT_TIMEOUT_MS.pie)}ms, source_control ${String(WAIT_FOR_JOB_DEFAULT_TIMEOUT_MS.source_control)}ms, test_run ${String(WAIT_FOR_JOB_DEFAULT_TIMEOUT_MS.test_run)}ms.`)
|
|
5048
5587
|
};
|
|
5049
5588
|
const getEditorStateInputSchema = { projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor should report its state.") };
|
|
5050
5589
|
const saveDirtyPackagesInputSchema = {
|
|
@@ -5747,6 +6286,62 @@ const findAssetsInputSchema = {
|
|
|
5747
6286
|
recursiveClasses: bridgeFindAssetsRequestSchema.shape.recursiveClasses.describe("Whether classNames also match subclasses (default true)."),
|
|
5748
6287
|
recursivePaths: bridgeFindAssetsRequestSchema.shape.recursivePaths.describe("Whether packagePaths also match sub-folders (default true).")
|
|
5749
6288
|
};
|
|
6289
|
+
const readDataTableInputSchema = {
|
|
6290
|
+
assetPath: bridgeReadDataTableRequestSchema.shape.assetPath.describe("Object path of the DataTable asset, as find_assets reports it (e.g. /Game/Data/DT_Weapons.DT_Weapons)."),
|
|
6291
|
+
cursor: bridgeReadDataTableRequestSchema.shape.cursor.describe("Offset into the name-ordered row list (default 0). Pass the previous response nextCursor to fetch the next page."),
|
|
6292
|
+
loadIfNeeded: bridgeReadDataTableRequestSchema.shape.loadIfNeeded.describe("Whether to load the asset when the editor does not already have it in memory (default true). A DataTable carries no Asset Registry tags describing its rows, so with this false an unloaded table reports asset_not_loaded rather than an empty table."),
|
|
6293
|
+
maxRows: bridgeReadDataTableRequestSchema.shape.maxRows.default(25).describe("Maximum number of rows to return per page (1-100, default 25). totalRowCount still reports the unbounded row count."),
|
|
6294
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor holds the DataTable."),
|
|
6295
|
+
rowNameFilter: bridgeReadDataTableRequestSchema.shape.rowNameFilter.describe("Optional case-insensitive substring matched against each row name, applied before paging.")
|
|
6296
|
+
};
|
|
6297
|
+
const writeDataTableRowInputSchema = {
|
|
6298
|
+
assetPath: bridgeWriteDataTableRowRequestSchema.shape.assetPath.describe("Object path of the DataTable asset to write (e.g. /Game/Data/DT_Weapons.DT_Weapons)."),
|
|
6299
|
+
dryRun: bridgeWriteDataTableRowRequestSchema.shape.dryRun.describe("When true, resolve the row struct and validate every column and value without opening a transaction or dirtying the package (default false)."),
|
|
6300
|
+
operation: bridgeWriteDataTableRowRequestSchema.shape.operation.describe("'upsert' inserts the row or replaces it if it already exists; 'delete' removes it by name. Deleting a row that is not there is reported through rowExisted=false, not as an error."),
|
|
6301
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor holds the DataTable."),
|
|
6302
|
+
rowName: bridgeWriteDataTableRowRequestSchema.shape.rowName.describe("Name of the row to write or delete, as read_data_table reports it."),
|
|
6303
|
+
values: bridgeWriteDataTableRowRequestSchema.shape.values.describe("Column name to value, in the same ExportText format read_data_table emits (required for upsert, forbidden for delete). Every column and value is validated against the row struct before anything is written: an unknown column or a value that will not parse rejects the whole write, so a row is never partially applied. Columns omitted on an upsert of an existing row keep their current value.")
|
|
6304
|
+
};
|
|
6305
|
+
const exportDataTableInputSchema = {
|
|
6306
|
+
assetPath: bridgeExportDataTableRequestSchema.shape.assetPath.describe("Object path of the DataTable asset to export (e.g. /Game/Data/DT_Weapons.DT_Weapons)."),
|
|
6307
|
+
cursor: bridgeExportDataTableRequestSchema.shape.cursor.describe("Character offset into the serialized table (default 0). Pass the previous response nextCursor to fetch the next chunk."),
|
|
6308
|
+
format: bridgeExportDataTableRequestSchema.shape.format.describe("Serialization to use: 'json' (default) or 'csv'. Both come from the engine's own DataTable exporters."),
|
|
6309
|
+
loadIfNeeded: bridgeExportDataTableRequestSchema.shape.loadIfNeeded.describe("Whether to load the asset when the editor does not already have it in memory (default true)."),
|
|
6310
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor holds the DataTable.")
|
|
6311
|
+
};
|
|
6312
|
+
const importDataTableInputSchema = {
|
|
6313
|
+
assetPath: bridgeImportDataTableRequestSchema.shape.assetPath.describe("Object path of the DataTable asset to overwrite (e.g. /Game/Data/DT_Weapons.DT_Weapons)."),
|
|
6314
|
+
content: bridgeImportDataTableRequestSchema.shape.content.describe(`Complete serialized table in the chosen format, up to ${String(BRIDGE_DATA_TABLE_MAX_IMPORT_CHARS)} characters — the whole payload travels in one bridge frame, so a table larger than that cannot be imported this way. This REPLACES every row: a row absent from the content is deleted.`),
|
|
6315
|
+
dryRun: bridgeImportDataTableRequestSchema.shape.dryRun.describe("When true, parse the content and report the row count and problems without replacing anything (default false)."),
|
|
6316
|
+
format: bridgeImportDataTableRequestSchema.shape.format.describe("Serialization the content is in: 'json' (default) or 'csv'."),
|
|
6317
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor holds the DataTable.")
|
|
6318
|
+
};
|
|
6319
|
+
const createDataTableInputSchema = {
|
|
6320
|
+
assetPath: bridgeCreateDataTableRequestSchema.shape.assetPath.describe("Object path for the new DataTable, e.g. /Game/Data/DT_Weapons. Fails if an asset already exists there."),
|
|
6321
|
+
dryRun: bridgeCreateDataTableRequestSchema.shape.dryRun.describe("When true, resolve and validate the row struct and destination without creating anything (default false)."),
|
|
6322
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor should create the table."),
|
|
6323
|
+
rowStructPath: bridgeCreateDataTableRequestSchema.shape.rowStructPath.describe("Struct backing every row. Native structs use /Script/<Module>.<Struct>; a Blueprint struct uses its object path. Must derive FTableRowBase. Cannot be changed after creation.")
|
|
6324
|
+
};
|
|
6325
|
+
const renameDataTableInputSchema = {
|
|
6326
|
+
assetPath: bridgeRenameDataTableRequestSchema.shape.assetPath.describe("Object path of the DataTable to rename or move (e.g. /Game/Data/DT_Weapons.DT_Weapons)."),
|
|
6327
|
+
destinationPath: bridgeRenameDataTableRequestSchema.shape.destinationPath.describe("Package path to move the asset into, e.g. /Game/Data/Archive. Omit to keep it where it is."),
|
|
6328
|
+
dryRun: bridgeRenameDataTableRequestSchema.shape.dryRun.describe("When true, validate the destination without moving anything (default false)."),
|
|
6329
|
+
newName: bridgeRenameDataTableRequestSchema.shape.newName.describe("New asset name without any path, e.g. DT_WeaponsLegacy. Omit to keep the current name."),
|
|
6330
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor holds the DataTable.")
|
|
6331
|
+
};
|
|
6332
|
+
const deleteDataTableInputSchema = {
|
|
6333
|
+
assetPath: bridgeDeleteDataTableRequestSchema.shape.assetPath.describe("Object path of the DataTable to delete (e.g. /Game/Data/DT_Weapons.DT_Weapons)."),
|
|
6334
|
+
dryRun: bridgeDeleteDataTableRequestSchema.shape.dryRun.describe("When true, report what would be deleted and what still references it, without deleting (default false)."),
|
|
6335
|
+
force: bridgeDeleteDataTableRequestSchema.shape.force.describe("Delete even when other assets reference the table, breaking those references (default false). Without it a referenced table is refused and its referencers are reported."),
|
|
6336
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor holds the DataTable.")
|
|
6337
|
+
};
|
|
6338
|
+
const renameDataTableRowInputSchema = {
|
|
6339
|
+
assetPath: bridgeRenameDataTableRowRequestSchema.shape.assetPath.describe("Object path of the DataTable holding the row (e.g. /Game/Data/DT_Weapons.DT_Weapons)."),
|
|
6340
|
+
dryRun: bridgeRenameDataTableRowRequestSchema.shape.dryRun.describe("When true, validate both names without renaming anything (default false)."),
|
|
6341
|
+
newRowName: bridgeRenameDataTableRowRequestSchema.shape.newRowName.describe("Name to rename the row to. Fails if a row already uses it."),
|
|
6342
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor holds the DataTable."),
|
|
6343
|
+
rowName: bridgeRenameDataTableRowRequestSchema.shape.rowName.describe("Current name of the row to rename.")
|
|
6344
|
+
};
|
|
5750
6345
|
const listActorsInputSchema = {
|
|
5751
6346
|
classNames: bridgeListActorsRequestSchema.shape.classNames.describe("Actor class names to match, either short (StaticMeshActor, PointLight) or full class paths (/Script/Engine.StaticMeshActor, /Game/BP/BP_Foo.BP_Foo_C). Subclasses match too. Empty means every class."),
|
|
5752
6347
|
cursor: bridgeListActorsRequestSchema.shape.cursor.describe("Offset into the stable-ordered matched list (default 0). Pass the previous response nextCursor to fetch the next page."),
|
|
@@ -5803,6 +6398,22 @@ const getOpenLevelStatusInputSchema = {
|
|
|
5803
6398
|
openLevelJobId: bridgeGetOpenLevelStatusRequestSchema.shape.openLevelJobId.describe("openLevelJobId returned by open_level identifying the load job to poll."),
|
|
5804
6399
|
projectId: projectIdSchema
|
|
5805
6400
|
};
|
|
6401
|
+
const getSourceControlStatusInputSchema = {
|
|
6402
|
+
assetPaths: bridgeGetSourceControlStatusRequestSchema.shape.assetPaths.describe("Package names or object paths of the assets to report on (1-64), e.g. /Game/Data/DT_Weapons."),
|
|
6403
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor should query its source control provider.")
|
|
6404
|
+
};
|
|
6405
|
+
const refreshSourceControlStatusInputSchema = {
|
|
6406
|
+
assetPaths: bridgeRefreshSourceControlStatusRequestSchema.shape.assetPaths.describe("Package names or object paths of the assets whose depot state should be re-read (1-64)."),
|
|
6407
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor should refresh its source control state.")
|
|
6408
|
+
};
|
|
6409
|
+
const checkoutAssetsInputSchema = {
|
|
6410
|
+
assetPaths: bridgeCheckoutAssetsRequestSchema.shape.assetPaths.describe("Package names or object paths of the assets to check out (1-64), e.g. /Game/Data/DT_Weapons."),
|
|
6411
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor should check the assets out.")
|
|
6412
|
+
};
|
|
6413
|
+
const getSourceControlJobStatusInputSchema = {
|
|
6414
|
+
projectId: projectIdSchema.describe("Canonical Unreal ProjectID whose registered editor owns the job."),
|
|
6415
|
+
sourceControlJobId: bridgeGetSourceControlJobStatusRequestSchema.shape.sourceControlJobId.describe("sourceControlJobId returned by checkout_assets or refresh_source_control_status.")
|
|
6416
|
+
};
|
|
5806
6417
|
const getAssetDependenciesInputSchema = {
|
|
5807
6418
|
assetPath: bridgeGetAssetDependenciesRequestSchema.shape.assetPath.describe("Package name or object path of the asset to inspect (e.g. /Game/BP/BP_Player or /Game/BP/BP_Player.BP_Player)."),
|
|
5808
6419
|
categories: bridgeGetAssetDependenciesRequestSchema.shape.categories.describe("Dependency categories to include: 'package' (default), 'searchable_name', 'manage'."),
|
|
@@ -6448,6 +7059,46 @@ function registerMcpTools(server, dependencies) {
|
|
|
6448
7059
|
projectId
|
|
6449
7060
|
}, dependencies));
|
|
6450
7061
|
});
|
|
7062
|
+
server.registerTool("get_source_control_status", {
|
|
7063
|
+
description: "Report the editor's source control provider and the per-file state of up to 64 assets. Answered from the provider's state cache, so it costs no network round trip and returns inline. enabled distinguishes 'no source control configured' from 'configured, and this file is simply not checked out'; per-file state is one of checked_out_by_me, checked_out_by_other (with checkedOutBy naming the holder), marked_for_add, not_checked_out, not_in_depot, unknown. A file the editor has never queried reports 'unknown' — call refresh_source_control_status to fetch its real state from the server. Call this before any asset write on a team project: under Perforce or Git-LFS file locking a .uasset stays read-only until checked out, and the write otherwise fails later at save time.",
|
|
7064
|
+
inputSchema: getSourceControlStatusInputSchema,
|
|
7065
|
+
title: "Get Source Control Status"
|
|
7066
|
+
}, async ({ assetPaths, projectId }) => {
|
|
7067
|
+
return toToolSuccess(await getSourceControlStatus({
|
|
7068
|
+
assetPaths,
|
|
7069
|
+
projectId
|
|
7070
|
+
}, dependencies));
|
|
7071
|
+
});
|
|
7072
|
+
server.registerTool("refresh_source_control_status", {
|
|
7073
|
+
description: "Re-read the depot state of up to 64 assets from the source control server, so a later get_source_control_status reports something better than 'unknown'. This is a network round trip to the provider and runs far past what a bridge request can wait for, so it only accepts the job: it returns state 'accepted' with a sourceControlJobId to poll with get_source_control_job_status (or wait_for_job with kind source_control).",
|
|
7074
|
+
inputSchema: refreshSourceControlStatusInputSchema,
|
|
7075
|
+
title: "Refresh Source Control Status"
|
|
7076
|
+
}, async ({ assetPaths, projectId }) => {
|
|
7077
|
+
return toToolSuccess(await refreshSourceControlStatus({
|
|
7078
|
+
assetPaths,
|
|
7079
|
+
projectId
|
|
7080
|
+
}, dependencies));
|
|
7081
|
+
});
|
|
7082
|
+
server.registerTool("checkout_assets", {
|
|
7083
|
+
description: "Check up to 64 assets out of source control so they become writable. This is a network round trip to the provider and runs far past what a bridge request can wait for, so it only accepts the job: it returns state 'accepted' with a sourceControlJobId to poll with get_source_control_job_status (or wait_for_job with kind source_control). The poll reports per-item results with successCount / failureCount — one asset the provider refuses does not abort the rest. This checks out only; it never submits, and a checked-out asset stays checked out until a human submits or reverts it.",
|
|
7084
|
+
inputSchema: checkoutAssetsInputSchema,
|
|
7085
|
+
title: "Checkout Assets"
|
|
7086
|
+
}, async ({ assetPaths, projectId }) => {
|
|
7087
|
+
return toToolSuccess(await checkoutAssets({
|
|
7088
|
+
assetPaths,
|
|
7089
|
+
projectId
|
|
7090
|
+
}, dependencies));
|
|
7091
|
+
});
|
|
7092
|
+
server.registerTool("get_source_control_job_status", {
|
|
7093
|
+
description: "Poll a source control job started by checkout_assets or refresh_source_control_status for a projectId; returns state (running, succeeded, failed, unknown_job), which operation it was, and once finished the per-file results with successCount / failureCount and timing. Poll until the state leaves 'running' before writing to any asset in the batch.",
|
|
7094
|
+
inputSchema: getSourceControlJobStatusInputSchema,
|
|
7095
|
+
title: "Get Source Control Job Status"
|
|
7096
|
+
}, async ({ projectId, sourceControlJobId }) => {
|
|
7097
|
+
return toToolSuccess(await getSourceControlJobStatus({
|
|
7098
|
+
projectId,
|
|
7099
|
+
sourceControlJobId
|
|
7100
|
+
}, dependencies));
|
|
7101
|
+
});
|
|
6451
7102
|
server.registerTool("find_assets", {
|
|
6452
7103
|
description: "Query a project's Unreal Asset Registry for assets by class and/or content path, without loading them; returns each match's name, class, package name, package path, and object path. Requires at least one of classNames or packagePaths — an unfiltered query would stall the editor enumerating every asset. Results are paged: pass the previous response nextCursor to fetch the next page (totalCount reports the full match count). scanning=true means the registry is still indexing, so an empty result does not prove the asset is absent.",
|
|
6453
7104
|
inputSchema: findAssetsInputSchema,
|
|
@@ -6464,6 +7115,110 @@ function registerMcpTools(server, dependencies) {
|
|
|
6464
7115
|
recursivePaths
|
|
6465
7116
|
}, dependencies));
|
|
6466
7117
|
});
|
|
7118
|
+
server.registerTool("read_data_table", {
|
|
7119
|
+
description: "Read a DataTable asset's contents: the row struct it is typed on, its ordered column list (name plus the same type rendering get_class_reflection emits), and its rows as column-name-to-value maps. Values are ExportText, the format write_data_table_row accepts back, so a value read here round-trips. Rows are paged by name order: pass the previous response nextCursor to fetch the next page (totalRowCount reports the full count). A DataTable is a binary .uasset with no Asset Registry tags describing its rows, so there is no way to read one off disk instead — this tool loads it.",
|
|
7120
|
+
inputSchema: readDataTableInputSchema,
|
|
7121
|
+
title: "Read Data Table"
|
|
7122
|
+
}, async ({ assetPath, cursor, loadIfNeeded, maxRows, projectId, rowNameFilter }) => {
|
|
7123
|
+
return toToolSuccess(await readDataTable({
|
|
7124
|
+
assetPath,
|
|
7125
|
+
cursor,
|
|
7126
|
+
loadIfNeeded,
|
|
7127
|
+
maxRows,
|
|
7128
|
+
projectId,
|
|
7129
|
+
rowNameFilter
|
|
7130
|
+
}, dependencies));
|
|
7131
|
+
});
|
|
7132
|
+
server.registerTool("write_data_table_row", {
|
|
7133
|
+
description: "Insert, update, or delete a single DataTable row. Every column name and value is validated against the row struct before anything is written — an unknown column or a value that will not parse rejects the whole write with an error naming the field, so a row is never partially applied and there is no silent coercion. The write runs inside one transaction, so a human at the editor can Ctrl+Z it, and it marks the package dirty without saving: call save_dirty_packages to persist. Deleting a row that does not exist reports rowExisted=false rather than failing. Use dryRun to validate first. For a whole-table replace use import_data_table instead.",
|
|
7134
|
+
inputSchema: writeDataTableRowInputSchema,
|
|
7135
|
+
title: "Write Data Table Row"
|
|
7136
|
+
}, async ({ assetPath, dryRun, operation, projectId, rowName, values }) => {
|
|
7137
|
+
return toToolSuccess(await writeDataTableRow({
|
|
7138
|
+
assetPath,
|
|
7139
|
+
dryRun,
|
|
7140
|
+
operation,
|
|
7141
|
+
projectId,
|
|
7142
|
+
rowName,
|
|
7143
|
+
values
|
|
7144
|
+
}, dependencies));
|
|
7145
|
+
});
|
|
7146
|
+
server.registerTool("export_data_table", {
|
|
7147
|
+
description: "Serialize a whole DataTable through the engine's own JSON or CSV exporter. Returned in chunks by character offset because the engine produces one string rather than something row-addressable: concatenate the chunks in cursor order to reassemble, and note a single chunk is not valid JSON or CSV on its own. Use read_data_table when you want structured, per-row access; use this when you want the table in the same text form the editor's own export produces.",
|
|
7148
|
+
inputSchema: exportDataTableInputSchema,
|
|
7149
|
+
title: "Export Data Table"
|
|
7150
|
+
}, async ({ assetPath, cursor, format, loadIfNeeded, projectId }) => {
|
|
7151
|
+
return toToolSuccess(await exportDataTable({
|
|
7152
|
+
assetPath,
|
|
7153
|
+
cursor,
|
|
7154
|
+
format,
|
|
7155
|
+
loadIfNeeded,
|
|
7156
|
+
projectId
|
|
7157
|
+
}, dependencies));
|
|
7158
|
+
});
|
|
7159
|
+
server.registerTool("import_data_table", {
|
|
7160
|
+
description: "REPLACE every row of a DataTable from a JSON or CSV payload, using the engine's own importer. This is destructive: any row not present in the content is deleted, so it is the wrong tool for changing one value — use write_data_table_row for that. The whole payload travels in one bridge frame, so a table beyond the content character bound cannot be imported this way. Runs inside one transaction (Ctrl+Z reverses it) and marks the package dirty without saving. Rows the importer rejects come back in problems while the rest still apply, so check problemCount even on success; dryRun reports the row count and problems without replacing anything.",
|
|
7161
|
+
inputSchema: importDataTableInputSchema,
|
|
7162
|
+
title: "Import Data Table"
|
|
7163
|
+
}, async ({ assetPath, content, dryRun, format, projectId }) => {
|
|
7164
|
+
return toToolSuccess(await importDataTable({
|
|
7165
|
+
assetPath,
|
|
7166
|
+
content,
|
|
7167
|
+
dryRun,
|
|
7168
|
+
format,
|
|
7169
|
+
projectId
|
|
7170
|
+
}, dependencies));
|
|
7171
|
+
});
|
|
7172
|
+
server.registerTool("create_data_table", {
|
|
7173
|
+
description: "Create a new empty DataTable asset backed by a row struct. The struct is fixed at creation — UDataTable can have its RowStruct swapped later, but that reinterprets existing rows through the new layout, so the bridge does not expose it; create a new table instead. The struct must derive FTableRowBase, and creation fails if an asset already exists at the path. The new table is marked dirty but not written to disk: call save_dirty_packages to persist it, or it disappears when the editor closes. Use read_data_table to confirm the column set the struct produced.",
|
|
7174
|
+
inputSchema: createDataTableInputSchema,
|
|
7175
|
+
title: "Create Data Table"
|
|
7176
|
+
}, async ({ assetPath, dryRun, projectId, rowStructPath }) => {
|
|
7177
|
+
return toToolSuccess(await createDataTable({
|
|
7178
|
+
assetPath,
|
|
7179
|
+
dryRun,
|
|
7180
|
+
projectId,
|
|
7181
|
+
rowStructPath
|
|
7182
|
+
}, dependencies));
|
|
7183
|
+
});
|
|
7184
|
+
server.registerTool("rename_data_table", {
|
|
7185
|
+
description: "Rename a DataTable, move it to another package path, or both. Goes through the editor's asset tools, so references from other assets are fixed up and a redirector is left at the old path to keep hard references resolving. Renaming is not a transaction the editor can Ctrl+Z — it rewrites packages on disk. Use dryRun to check the destination is free first.",
|
|
7186
|
+
inputSchema: renameDataTableInputSchema,
|
|
7187
|
+
title: "Rename Data Table"
|
|
7188
|
+
}, async ({ assetPath, destinationPath, dryRun, newName, projectId }) => {
|
|
7189
|
+
return toToolSuccess(await renameDataTable({
|
|
7190
|
+
assetPath,
|
|
7191
|
+
destinationPath,
|
|
7192
|
+
dryRun,
|
|
7193
|
+
newName,
|
|
7194
|
+
projectId
|
|
7195
|
+
}, dependencies));
|
|
7196
|
+
});
|
|
7197
|
+
server.registerTool("delete_data_table", {
|
|
7198
|
+
description: "Delete a DataTable asset from the project. This is the one DataTable tool that cannot be undone — asset deletion is not a transaction, so there is no Ctrl+Z and no dirty-package step to reconsider at. A table other assets still reference is refused, and those referencers are reported; force deletes anyway and breaks them. Always dryRun first on a table you did not create: it reports the referencers without touching anything.",
|
|
7199
|
+
inputSchema: deleteDataTableInputSchema,
|
|
7200
|
+
title: "Delete Data Table"
|
|
7201
|
+
}, async ({ assetPath, dryRun, force, projectId }) => {
|
|
7202
|
+
return toToolSuccess(await deleteDataTable({
|
|
7203
|
+
assetPath,
|
|
7204
|
+
dryRun,
|
|
7205
|
+
force,
|
|
7206
|
+
projectId
|
|
7207
|
+
}, dependencies));
|
|
7208
|
+
});
|
|
7209
|
+
server.registerTool("rename_data_table_row", {
|
|
7210
|
+
description: "Rename a single row, keeping its position in the table and its values intact. Not the same as an upsert under the new name followed by a delete of the old one: that pair costs two transactions and moves the row to the end. Fails if the row does not exist or the new name is already taken. Runs inside one transaction (Ctrl+Z reverses it) and marks the package dirty without saving. Note that row names are how other assets address rows, so a rename breaks any FDataTableRowHandle pointing at the old name — nothing fixes those up.",
|
|
7211
|
+
inputSchema: renameDataTableRowInputSchema,
|
|
7212
|
+
title: "Rename Data Table Row"
|
|
7213
|
+
}, async ({ assetPath, dryRun, newRowName, projectId, rowName }) => {
|
|
7214
|
+
return toToolSuccess(await renameDataTableRow({
|
|
7215
|
+
assetPath,
|
|
7216
|
+
dryRun,
|
|
7217
|
+
newRowName,
|
|
7218
|
+
projectId,
|
|
7219
|
+
rowName
|
|
7220
|
+
}, dependencies));
|
|
7221
|
+
});
|
|
6467
7222
|
server.registerTool("get_asset_dependencies", {
|
|
6468
7223
|
description: "Report an asset's package-level dependencies (what it needs) and referencers (what needs it) from the Unreal Asset Registry — the Reference Viewer data — so you can judge the blast radius before changing it. Depth is 1: transitive links are not walked. Each list pages independently via nextDependencyCursor / nextReferencerCursor.",
|
|
6469
7224
|
inputSchema: getAssetDependenciesInputSchema,
|
|
@@ -6836,6 +7591,91 @@ async function getOpenLevelStatus(input, dependencies) {
|
|
|
6836
7591
|
if (response.durationMs !== void 0) result.durationMs = response.durationMs;
|
|
6837
7592
|
return result;
|
|
6838
7593
|
}
|
|
7594
|
+
async function getSourceControlStatus(input, dependencies) {
|
|
7595
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7596
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7597
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7598
|
+
const response = await sendBridgeGetSourceControlStatusRequest(createBridgeGetSourceControlStatusRequest(input.assetPaths), {
|
|
7599
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7600
|
+
host: BRIDGE_LOOPBACK_HOST,
|
|
7601
|
+
port: entry.port,
|
|
7602
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7603
|
+
});
|
|
7604
|
+
if (!response.ok) throw new Error(`Bridge get_source_control_status failed (${response.error.code}): ${response.error.message}`);
|
|
7605
|
+
const result = {
|
|
7606
|
+
available: response.available,
|
|
7607
|
+
enabled: response.enabled,
|
|
7608
|
+
files: response.files,
|
|
7609
|
+
projectId: entry.projectId,
|
|
7610
|
+
provider: response.provider,
|
|
7611
|
+
state: response.state
|
|
7612
|
+
};
|
|
7613
|
+
if (response.message !== void 0) result.message = response.message;
|
|
7614
|
+
return result;
|
|
7615
|
+
}
|
|
7616
|
+
async function refreshSourceControlStatus(input, dependencies) {
|
|
7617
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7618
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7619
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7620
|
+
const request = createBridgeRefreshSourceControlStatusRequest(input.assetPaths);
|
|
7621
|
+
const response = await sendBridgeRefreshSourceControlStatusRequest(request, {
|
|
7622
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7623
|
+
host: BRIDGE_LOOPBACK_HOST,
|
|
7624
|
+
port: entry.port,
|
|
7625
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7626
|
+
});
|
|
7627
|
+
if (!response.ok) throw new Error(`Bridge refresh_source_control_status failed (${response.error.code}): ${response.error.message}`);
|
|
7628
|
+
return buildSourceControlJobAcceptResult(response, request.assetPaths, entry.projectId);
|
|
7629
|
+
}
|
|
7630
|
+
async function checkoutAssets(input, dependencies) {
|
|
7631
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7632
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7633
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7634
|
+
const request = createBridgeCheckoutAssetsRequest(input.assetPaths);
|
|
7635
|
+
const response = await sendBridgeCheckoutAssetsRequest(request, {
|
|
7636
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7637
|
+
host: BRIDGE_LOOPBACK_HOST,
|
|
7638
|
+
port: entry.port,
|
|
7639
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7640
|
+
});
|
|
7641
|
+
if (!response.ok) throw new Error(`Bridge checkout_assets failed (${response.error.code}): ${response.error.message}`);
|
|
7642
|
+
return buildSourceControlJobAcceptResult(response, request.assetPaths, entry.projectId);
|
|
7643
|
+
}
|
|
7644
|
+
function buildSourceControlJobAcceptResult(response, assetPaths, projectId) {
|
|
7645
|
+
const result = {
|
|
7646
|
+
assetPaths,
|
|
7647
|
+
projectId,
|
|
7648
|
+
state: response.state
|
|
7649
|
+
};
|
|
7650
|
+
if (response.sourceControlJobId !== void 0) result.sourceControlJobId = response.sourceControlJobId;
|
|
7651
|
+
if (response.message !== void 0) result.message = response.message;
|
|
7652
|
+
return result;
|
|
7653
|
+
}
|
|
7654
|
+
async function getSourceControlJobStatus(input, dependencies) {
|
|
7655
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7656
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7657
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7658
|
+
const response = await sendBridgeGetSourceControlJobStatusRequest(createBridgeGetSourceControlJobStatusRequest(input.sourceControlJobId), {
|
|
7659
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7660
|
+
host: BRIDGE_LOOPBACK_HOST,
|
|
7661
|
+
port: entry.port,
|
|
7662
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7663
|
+
});
|
|
7664
|
+
if (!response.ok) throw new Error(`Bridge get_source_control_job_status failed (${response.error.code}): ${response.error.message}`);
|
|
7665
|
+
const result = {
|
|
7666
|
+
failureCount: response.failureCount,
|
|
7667
|
+
projectId: entry.projectId,
|
|
7668
|
+
results: response.results,
|
|
7669
|
+
sourceControlJobId: response.sourceControlJobId,
|
|
7670
|
+
state: response.state,
|
|
7671
|
+
successCount: response.successCount
|
|
7672
|
+
};
|
|
7673
|
+
if (response.operation !== void 0) result.operation = response.operation;
|
|
7674
|
+
if (response.message !== void 0) result.message = response.message;
|
|
7675
|
+
if (response.finishedAt !== void 0) result.finishedAt = response.finishedAt;
|
|
7676
|
+
if (response.durationMs !== void 0) result.durationMs = response.durationMs;
|
|
7677
|
+
return result;
|
|
7678
|
+
}
|
|
6839
7679
|
async function findAssets(input, dependencies) {
|
|
6840
7680
|
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
6841
7681
|
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
@@ -6864,6 +7704,213 @@ async function findAssets(input, dependencies) {
|
|
|
6864
7704
|
truncated: response.truncated
|
|
6865
7705
|
};
|
|
6866
7706
|
}
|
|
7707
|
+
async function readDataTable(input, dependencies) {
|
|
7708
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7709
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7710
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7711
|
+
const response = await sendBridgeReadDataTableRequest(createBridgeReadDataTableRequest(input.assetPath, {
|
|
7712
|
+
cursor: input.cursor,
|
|
7713
|
+
loadIfNeeded: input.loadIfNeeded,
|
|
7714
|
+
maxRows: input.maxRows,
|
|
7715
|
+
rowNameFilter: input.rowNameFilter
|
|
7716
|
+
}), {
|
|
7717
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7718
|
+
host: "127.0.0.1",
|
|
7719
|
+
port: entry.port,
|
|
7720
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7721
|
+
});
|
|
7722
|
+
if (!response.ok) throw new Error(`Bridge read_data_table failed (${response.error.code}): ${response.error.message}`);
|
|
7723
|
+
return {
|
|
7724
|
+
assetPath: response.assetPath,
|
|
7725
|
+
columns: response.columns,
|
|
7726
|
+
columnsTruncated: response.columnsTruncated,
|
|
7727
|
+
nextCursor: response.nextCursor,
|
|
7728
|
+
projectId: entry.projectId,
|
|
7729
|
+
rows: response.rows,
|
|
7730
|
+
rowStructName: response.rowStructName,
|
|
7731
|
+
rowStructPath: response.rowStructPath,
|
|
7732
|
+
totalRowCount: response.totalRowCount,
|
|
7733
|
+
truncated: response.truncated,
|
|
7734
|
+
valueTruncated: response.valueTruncated
|
|
7735
|
+
};
|
|
7736
|
+
}
|
|
7737
|
+
async function writeDataTableRow(input, dependencies) {
|
|
7738
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7739
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7740
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7741
|
+
const response = await sendBridgeWriteDataTableRowRequest(createBridgeWriteDataTableRowRequest(input.assetPath, input.rowName, input.operation, {
|
|
7742
|
+
dryRun: input.dryRun,
|
|
7743
|
+
values: input.values
|
|
7744
|
+
}), {
|
|
7745
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7746
|
+
host: "127.0.0.1",
|
|
7747
|
+
port: entry.port,
|
|
7748
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7749
|
+
});
|
|
7750
|
+
if (!response.ok) throw new Error(`Bridge write_data_table_row failed (${response.error.code}): ${response.error.message}`);
|
|
7751
|
+
return {
|
|
7752
|
+
applied: response.applied,
|
|
7753
|
+
assetPath: response.assetPath,
|
|
7754
|
+
created: response.created,
|
|
7755
|
+
dryRun: response.dryRun,
|
|
7756
|
+
message: response.message,
|
|
7757
|
+
packageDirty: response.packageDirty,
|
|
7758
|
+
projectId: entry.projectId,
|
|
7759
|
+
rowExisted: response.rowExisted,
|
|
7760
|
+
rowName: response.rowName,
|
|
7761
|
+
state: response.state,
|
|
7762
|
+
transactionTitle: response.transactionTitle
|
|
7763
|
+
};
|
|
7764
|
+
}
|
|
7765
|
+
async function exportDataTable(input, dependencies) {
|
|
7766
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7767
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7768
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7769
|
+
const response = await sendBridgeExportDataTableRequest(createBridgeExportDataTableRequest(input.assetPath, {
|
|
7770
|
+
cursor: input.cursor,
|
|
7771
|
+
format: input.format,
|
|
7772
|
+
loadIfNeeded: input.loadIfNeeded
|
|
7773
|
+
}), {
|
|
7774
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7775
|
+
host: "127.0.0.1",
|
|
7776
|
+
port: entry.port,
|
|
7777
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7778
|
+
});
|
|
7779
|
+
if (!response.ok) throw new Error(`Bridge export_data_table failed (${response.error.code}): ${response.error.message}`);
|
|
7780
|
+
return {
|
|
7781
|
+
assetPath: response.assetPath,
|
|
7782
|
+
content: response.content,
|
|
7783
|
+
format: response.format,
|
|
7784
|
+
nextCursor: response.nextCursor,
|
|
7785
|
+
projectId: entry.projectId,
|
|
7786
|
+
rowCount: response.rowCount,
|
|
7787
|
+
totalChars: response.totalChars,
|
|
7788
|
+
truncated: response.truncated
|
|
7789
|
+
};
|
|
7790
|
+
}
|
|
7791
|
+
async function importDataTable(input, dependencies) {
|
|
7792
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7793
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7794
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7795
|
+
const response = await sendBridgeImportDataTableRequest(createBridgeImportDataTableRequest(input.assetPath, input.content, {
|
|
7796
|
+
dryRun: input.dryRun,
|
|
7797
|
+
format: input.format
|
|
7798
|
+
}), {
|
|
7799
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7800
|
+
host: "127.0.0.1",
|
|
7801
|
+
port: entry.port,
|
|
7802
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7803
|
+
});
|
|
7804
|
+
if (!response.ok) throw new Error(`Bridge import_data_table failed (${response.error.code}): ${response.error.message}`);
|
|
7805
|
+
return {
|
|
7806
|
+
assetPath: response.assetPath,
|
|
7807
|
+
dryRun: response.dryRun,
|
|
7808
|
+
message: response.message,
|
|
7809
|
+
packageDirty: response.packageDirty,
|
|
7810
|
+
problemCount: response.problemCount,
|
|
7811
|
+
problems: response.problems,
|
|
7812
|
+
projectId: entry.projectId,
|
|
7813
|
+
replacedRowCount: response.replacedRowCount,
|
|
7814
|
+
rowCount: response.rowCount,
|
|
7815
|
+
state: response.state,
|
|
7816
|
+
transactionTitle: response.transactionTitle
|
|
7817
|
+
};
|
|
7818
|
+
}
|
|
7819
|
+
async function createDataTable(input, dependencies) {
|
|
7820
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7821
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7822
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7823
|
+
const response = await sendBridgeCreateDataTableRequest(createBridgeCreateDataTableRequest(input.assetPath, input.rowStructPath, { dryRun: input.dryRun }), {
|
|
7824
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7825
|
+
host: "127.0.0.1",
|
|
7826
|
+
port: entry.port,
|
|
7827
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7828
|
+
});
|
|
7829
|
+
if (!response.ok) throw new Error(`Bridge create_data_table failed (${response.error.code}): ${response.error.message}`);
|
|
7830
|
+
return {
|
|
7831
|
+
assetPath: response.assetPath,
|
|
7832
|
+
created: response.created,
|
|
7833
|
+
dryRun: response.dryRun,
|
|
7834
|
+
packageDirty: response.packageDirty,
|
|
7835
|
+
projectId: entry.projectId,
|
|
7836
|
+
rowStructPath: response.rowStructPath,
|
|
7837
|
+
state: response.state
|
|
7838
|
+
};
|
|
7839
|
+
}
|
|
7840
|
+
async function renameDataTable(input, dependencies) {
|
|
7841
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7842
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7843
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7844
|
+
const response = await sendBridgeRenameDataTableRequest(createBridgeRenameDataTableRequest(input.assetPath, {
|
|
7845
|
+
destinationPath: input.destinationPath,
|
|
7846
|
+
dryRun: input.dryRun,
|
|
7847
|
+
newName: input.newName
|
|
7848
|
+
}), {
|
|
7849
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7850
|
+
host: "127.0.0.1",
|
|
7851
|
+
port: entry.port,
|
|
7852
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7853
|
+
});
|
|
7854
|
+
if (!response.ok) throw new Error(`Bridge rename_data_table failed (${response.error.code}): ${response.error.message}`);
|
|
7855
|
+
return {
|
|
7856
|
+
assetPath: response.assetPath,
|
|
7857
|
+
dryRun: response.dryRun,
|
|
7858
|
+
leftRedirector: response.leftRedirector,
|
|
7859
|
+
newAssetPath: response.newAssetPath,
|
|
7860
|
+
packageDirty: response.packageDirty,
|
|
7861
|
+
projectId: entry.projectId,
|
|
7862
|
+
renamed: response.renamed,
|
|
7863
|
+
state: response.state
|
|
7864
|
+
};
|
|
7865
|
+
}
|
|
7866
|
+
async function deleteDataTable(input, dependencies) {
|
|
7867
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7868
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7869
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7870
|
+
const response = await sendBridgeDeleteDataTableRequest(createBridgeDeleteDataTableRequest(input.assetPath, {
|
|
7871
|
+
dryRun: input.dryRun,
|
|
7872
|
+
force: input.force
|
|
7873
|
+
}), {
|
|
7874
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7875
|
+
host: "127.0.0.1",
|
|
7876
|
+
port: entry.port,
|
|
7877
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7878
|
+
});
|
|
7879
|
+
if (!response.ok) throw new Error(`Bridge delete_data_table failed (${response.error.code}): ${response.error.message}`);
|
|
7880
|
+
return {
|
|
7881
|
+
assetPath: response.assetPath,
|
|
7882
|
+
deleted: response.deleted,
|
|
7883
|
+
dryRun: response.dryRun,
|
|
7884
|
+
forced: response.forced,
|
|
7885
|
+
projectId: entry.projectId,
|
|
7886
|
+
referencerCount: response.referencerCount,
|
|
7887
|
+
referencers: response.referencers,
|
|
7888
|
+
state: response.state
|
|
7889
|
+
};
|
|
7890
|
+
}
|
|
7891
|
+
async function renameDataTableRow(input, dependencies) {
|
|
7892
|
+
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
7893
|
+
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
7894
|
+
if (!entry) throw new Error(`No registered Unreal engine was found for projectId '${normalizedProjectId}'.`);
|
|
7895
|
+
const response = await sendBridgeRenameDataTableRowRequest(createBridgeRenameDataTableRowRequest(input.assetPath, input.rowName, input.newRowName, { dryRun: input.dryRun }), {
|
|
7896
|
+
connectTimeoutMs: deriveBridgeConnectTimeoutMs$1(dependencies.pingTimeoutMs),
|
|
7897
|
+
host: "127.0.0.1",
|
|
7898
|
+
port: entry.port,
|
|
7899
|
+
readTimeoutMs: deriveEditorWorkTimeoutMs(dependencies.pingTimeoutMs)
|
|
7900
|
+
});
|
|
7901
|
+
if (!response.ok) throw new Error(`Bridge rename_data_table_row failed (${response.error.code}): ${response.error.message}`);
|
|
7902
|
+
return {
|
|
7903
|
+
assetPath: response.assetPath,
|
|
7904
|
+
dryRun: response.dryRun,
|
|
7905
|
+
newRowName: response.newRowName,
|
|
7906
|
+
packageDirty: response.packageDirty,
|
|
7907
|
+
projectId: entry.projectId,
|
|
7908
|
+
renamed: response.renamed,
|
|
7909
|
+
rowName: response.rowName,
|
|
7910
|
+
state: response.state,
|
|
7911
|
+
transactionTitle: response.transactionTitle
|
|
7912
|
+
};
|
|
7913
|
+
}
|
|
6867
7914
|
async function getAssetDependencies(input, dependencies) {
|
|
6868
7915
|
const normalizedProjectId = projectIdSchema.parse(input.projectId);
|
|
6869
7916
|
const entry = dependencies.registry.getProject(normalizedProjectId);
|
|
@@ -7962,6 +9009,10 @@ async function pollJobStatus(kind, jobId, projectId, dependencies) {
|
|
|
7962
9009
|
pieSessionId: jobId,
|
|
7963
9010
|
projectId
|
|
7964
9011
|
}, dependencies);
|
|
9012
|
+
case "source_control": return await getSourceControlJobStatus({
|
|
9013
|
+
projectId,
|
|
9014
|
+
sourceControlJobId: jobId
|
|
9015
|
+
}, dependencies);
|
|
7965
9016
|
case "test_run": return await getTestRunStatus({
|
|
7966
9017
|
projectId,
|
|
7967
9018
|
testRunId: jobId
|
|
@@ -7973,6 +9024,7 @@ function classifyJobStatus(kind, status) {
|
|
|
7973
9024
|
case "compile": return status.state === "compiling" ? "pending" : toTerminalOutcome(status.state === "unknown_job");
|
|
7974
9025
|
case "create_class": return status.state === "creating" ? "pending" : toTerminalOutcome(status.state === "unknown_job");
|
|
7975
9026
|
case "pie": return status.state === "starting" ? "pending" : "completed";
|
|
9027
|
+
case "source_control": return status.state === "running" ? "pending" : toTerminalOutcome(status.state === "unknown_job");
|
|
7976
9028
|
case "test_run": return status.state === "running" ? "pending" : toTerminalOutcome(status.state === "unknown_run");
|
|
7977
9029
|
}
|
|
7978
9030
|
}
|
|
@@ -8229,7 +9281,7 @@ function isMissingFileError(error) {
|
|
|
8229
9281
|
//#endregion
|
|
8230
9282
|
//#region src/server.ts
|
|
8231
9283
|
const SERVER_NAME = "ue-mcp-server";
|
|
8232
|
-
const SERVER_VERSION = "1.
|
|
9284
|
+
const SERVER_VERSION = "1.2.0";
|
|
8233
9285
|
const logger = createModuleLogger("bootstrap");
|
|
8234
9286
|
const enginePingLogger = createModuleLogger("engine-ping");
|
|
8235
9287
|
const httpApiLogger = createModuleLogger("http-api");
|