blueprint-extractor-mcp 3.2.0 → 4.0.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/dist/catalogs/example-catalog.js +88 -0
- package/dist/helpers/alias-registration.d.ts +7 -0
- package/dist/helpers/alias-registration.js +36 -0
- package/dist/helpers/composite-patterns.d.ts +40 -0
- package/dist/helpers/composite-patterns.js +28 -0
- package/dist/helpers/live-coding.js +4 -0
- package/dist/helpers/subsystem.js +28 -1
- package/dist/helpers/tool-registration.d.ts +3 -2
- package/dist/helpers/tool-registration.js +6 -2
- package/dist/helpers/tool-results.js +5 -3
- package/dist/index.js +1 -1
- package/dist/project-controller.d.ts +9 -0
- package/dist/project-controller.js +19 -1
- package/dist/prompts/prompt-catalog.js +2 -2
- package/dist/register-server-tools.d.ts +2 -1
- package/dist/register-server-tools.js +14 -3
- package/dist/resources/static-doc-resources.js +2 -1
- package/dist/schemas/tool-inputs.d.ts +1125 -17
- package/dist/schemas/tool-inputs.js +19 -6
- package/dist/schemas/tool-results.d.ts +336 -0
- package/dist/schemas/tool-results.js +20 -0
- package/dist/server-config.d.ts +1 -1
- package/dist/server-config.js +34 -7
- package/dist/server-factory.d.ts +6 -1
- package/dist/server-factory.js +54 -2
- package/dist/tool-surface-manager.d.ts +28 -0
- package/dist/tool-surface-manager.js +234 -0
- package/dist/tools/blueprint-authoring.js +13 -1
- package/dist/tools/composite-tools.d.ts +10 -0
- package/dist/tools/composite-tools.js +207 -0
- package/dist/tools/extraction.d.ts +3 -1
- package/dist/tools/extraction.js +13 -33
- package/dist/tools/import-jobs.d.ts +6 -2
- package/dist/tools/import-jobs.js +92 -83
- package/dist/tools/material-authoring.d.ts +3 -1
- package/dist/tools/material-authoring.js +36 -73
- package/dist/tools/material-instance.js +8 -1
- package/dist/tools/project-control.js +47 -24
- package/dist/tools/schema-and-ai-authoring.d.ts +2 -2
- package/dist/tools/schema-and-ai-authoring.js +85 -49
- package/dist/tools/widget-extraction.js +2 -2
- package/dist/tools/widget-structure.js +392 -35
- package/dist/tools/widget-verification.js +11 -1
- package/dist/tools/window-ui.js +44 -11
- package/package.json +2 -2
|
@@ -482,4 +482,92 @@ export const exampleCatalog = {
|
|
|
482
482
|
},
|
|
483
483
|
],
|
|
484
484
|
},
|
|
485
|
+
state_tree_bindings: {
|
|
486
|
+
summary: 'Wire task outputs to task inputs using property path bindings. Extract an existing StateTree to discover structIds and property names, then use binding operations to set up data flow.',
|
|
487
|
+
recommended_flow: [
|
|
488
|
+
'extract_asset (discover structIds and property names)',
|
|
489
|
+
'modify_state_tree (add_binding / set_bindings)',
|
|
490
|
+
'extract_asset (verify bindings)',
|
|
491
|
+
'save_assets',
|
|
492
|
+
],
|
|
493
|
+
examples: [
|
|
494
|
+
{
|
|
495
|
+
title: 'add_single_binding',
|
|
496
|
+
tool: 'modify_state_tree',
|
|
497
|
+
arguments: {
|
|
498
|
+
asset_path: '/Game/AI/ST_Character',
|
|
499
|
+
operation: 'add_binding',
|
|
500
|
+
payload: {
|
|
501
|
+
sourcePath: {
|
|
502
|
+
structId: 'EAB9611F4B07D7E2C25A948AFC790A50',
|
|
503
|
+
segments: [{ name: 'SelectedGestureTag' }],
|
|
504
|
+
},
|
|
505
|
+
targetPath: {
|
|
506
|
+
structId: 'F2A3B44C4D08E6A1C25A948AFC790A50',
|
|
507
|
+
segments: [{ name: 'MontageTag' }],
|
|
508
|
+
},
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
context: { description: 'Wire SelectRandomGesture output → PlayMontage input. structIds from extract_asset output.' },
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
title: 'set_all_bindings',
|
|
515
|
+
tool: 'modify_state_tree',
|
|
516
|
+
arguments: {
|
|
517
|
+
asset_path: '/Game/AI/ST_Character',
|
|
518
|
+
operation: 'set_bindings',
|
|
519
|
+
payload: {
|
|
520
|
+
propertyBindings: [
|
|
521
|
+
{
|
|
522
|
+
sourcePath: { segments: [{ name: 'SelectedTag' }] },
|
|
523
|
+
targetPath: { segments: [{ name: 'MontageTag' }] },
|
|
524
|
+
},
|
|
525
|
+
{
|
|
526
|
+
sourcePath: { segments: [{ name: 'Duration' }] },
|
|
527
|
+
targetPath: { segments: [{ name: 'WaitTime' }] },
|
|
528
|
+
},
|
|
529
|
+
],
|
|
530
|
+
},
|
|
531
|
+
},
|
|
532
|
+
context: { description: 'Replace all bindings on the StateTree with a new set.' },
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
title: 'remove_binding_by_target',
|
|
536
|
+
tool: 'modify_state_tree',
|
|
537
|
+
arguments: {
|
|
538
|
+
asset_path: '/Game/AI/ST_Character',
|
|
539
|
+
operation: 'remove_binding',
|
|
540
|
+
payload: {
|
|
541
|
+
targetPath: { segments: [{ name: 'MontageTag' }] },
|
|
542
|
+
},
|
|
543
|
+
},
|
|
544
|
+
context: { description: 'Remove all bindings targeting the MontageTag property.' },
|
|
545
|
+
},
|
|
546
|
+
{
|
|
547
|
+
title: 'create_with_bindings',
|
|
548
|
+
tool: 'create_state_tree',
|
|
549
|
+
arguments: {
|
|
550
|
+
asset_path: '/Game/AI/ST_NewWithBindings',
|
|
551
|
+
payload: {
|
|
552
|
+
schema: '/Script/GameplayStateTreeModule.StateTreeComponentSchema',
|
|
553
|
+
states: [{
|
|
554
|
+
name: 'Root',
|
|
555
|
+
type: 'State',
|
|
556
|
+
tasks: [
|
|
557
|
+
{ nodeStructType: '/Script/MyMod.STCSelectGesture', name: 'SelectGesture' },
|
|
558
|
+
{ nodeStructType: '/Script/MyMod.STCPlayMontage', name: 'PlayMontage' },
|
|
559
|
+
],
|
|
560
|
+
}],
|
|
561
|
+
bindings: {
|
|
562
|
+
propertyBindings: [{
|
|
563
|
+
sourcePath: { segments: [{ name: 'SelectedGestureTag' }] },
|
|
564
|
+
targetPath: { segments: [{ name: 'MontageTag' }] },
|
|
565
|
+
}],
|
|
566
|
+
},
|
|
567
|
+
},
|
|
568
|
+
},
|
|
569
|
+
context: { description: 'Create a StateTree with tasks and bindings in a single call.' },
|
|
570
|
+
},
|
|
571
|
+
],
|
|
572
|
+
},
|
|
485
573
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
import type { ToolHelpEntry, ToolInputSchema } from './tool-help.js';
|
|
3
|
+
type RawToolHandler = (args: Record<string, unknown>, extra: unknown) => Promise<unknown> | unknown;
|
|
4
|
+
export declare const aliasMap: Map<string, string>;
|
|
5
|
+
export declare const rawHandlerRegistry: Map<string, RawToolHandler>;
|
|
6
|
+
export declare function registerAlias(server: McpServer, oldName: string, targetName: string, parameterMapping: (args: Record<string, unknown>) => Record<string, unknown>, deprecationMessage: string, toolHelpRegistry: Map<string, ToolHelpEntry>, aliasInputSchema?: ToolInputSchema): void;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Global alias map: old name -> new name
|
|
2
|
+
export const aliasMap = new Map();
|
|
3
|
+
// Registry for raw (pre-normalization) handlers, keyed by tool name.
|
|
4
|
+
// Populated by installNormalizedToolRegistration and used by alias delegation.
|
|
5
|
+
export const rawHandlerRegistry = new Map();
|
|
6
|
+
export function registerAlias(server, oldName, targetName, parameterMapping, deprecationMessage, toolHelpRegistry, aliasInputSchema) {
|
|
7
|
+
const targetEntry = toolHelpRegistry.get(targetName);
|
|
8
|
+
if (!targetEntry) {
|
|
9
|
+
throw new Error(`Cannot register alias '${oldName}': target tool '${targetName}' not found in registry`);
|
|
10
|
+
}
|
|
11
|
+
const targetHandler = rawHandlerRegistry.get(targetName);
|
|
12
|
+
if (!targetHandler) {
|
|
13
|
+
throw new Error(`Cannot register alias '${oldName}': no raw handler found for target tool '${targetName}'`);
|
|
14
|
+
}
|
|
15
|
+
aliasMap.set(oldName, targetName);
|
|
16
|
+
const aliasDescription = `[DEPRECATED: use ${targetName}] ${targetEntry.description}`;
|
|
17
|
+
server.registerTool(oldName, {
|
|
18
|
+
title: `${targetEntry.title} (deprecated alias)`,
|
|
19
|
+
description: aliasDescription,
|
|
20
|
+
inputSchema: aliasInputSchema ?? targetEntry.inputSchema,
|
|
21
|
+
annotations: {
|
|
22
|
+
...targetEntry.annotations,
|
|
23
|
+
},
|
|
24
|
+
}, async (args, extra) => {
|
|
25
|
+
const mappedArgs = parameterMapping(args);
|
|
26
|
+
return targetHandler(mappedArgs, extra);
|
|
27
|
+
});
|
|
28
|
+
toolHelpRegistry.set(oldName, {
|
|
29
|
+
...targetEntry,
|
|
30
|
+
title: `${targetEntry.title} (deprecated alias)`,
|
|
31
|
+
description: `Alias for ${targetName}. ${deprecationMessage} ${targetEntry.description}`,
|
|
32
|
+
annotations: {
|
|
33
|
+
...targetEntry.annotations,
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface CompositeStepResult {
|
|
2
|
+
step: string;
|
|
3
|
+
status: 'success' | 'failure' | 'skipped';
|
|
4
|
+
message?: string;
|
|
5
|
+
data?: Record<string, unknown>;
|
|
6
|
+
diagnostics?: Array<{
|
|
7
|
+
severity?: string;
|
|
8
|
+
code?: string;
|
|
9
|
+
message?: string;
|
|
10
|
+
path?: string;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
export interface CompositeToolResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
operation: string;
|
|
16
|
+
steps: CompositeStepResult[];
|
|
17
|
+
partial_state?: {
|
|
18
|
+
completed_steps: string[];
|
|
19
|
+
failed_step: string;
|
|
20
|
+
editor_state: string;
|
|
21
|
+
};
|
|
22
|
+
execution: {
|
|
23
|
+
mode: 'immediate' | 'task_aware';
|
|
24
|
+
task_support: 'optional' | 'required' | 'forbidden';
|
|
25
|
+
status?: string;
|
|
26
|
+
progress_message?: string;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
type Result<T, E> = {
|
|
30
|
+
ok: true;
|
|
31
|
+
value: T;
|
|
32
|
+
} | {
|
|
33
|
+
ok: false;
|
|
34
|
+
error: E;
|
|
35
|
+
};
|
|
36
|
+
export declare function safeCall<T>(fn: () => Promise<T>): Promise<Result<T, Error>>;
|
|
37
|
+
export declare function compositeSuccess(operation: string, steps: CompositeStepResult[], execution: CompositeToolResult['execution']): CompositeToolResult;
|
|
38
|
+
export declare function compositeError(operation: string, steps: CompositeStepResult[], failedStep: string, execution: CompositeToolResult['execution']): CompositeToolResult;
|
|
39
|
+
export declare function compositePartialFailure(operation: string, steps: CompositeStepResult[], failedStep: string, partialState: CompositeToolResult['partial_state'], execution: CompositeToolResult['execution']): CompositeToolResult;
|
|
40
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export async function safeCall(fn) {
|
|
2
|
+
try {
|
|
3
|
+
const value = await fn();
|
|
4
|
+
return { ok: true, value };
|
|
5
|
+
}
|
|
6
|
+
catch (e) {
|
|
7
|
+
return { ok: false, error: e instanceof Error ? e : new Error(String(e)) };
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function compositeSuccess(operation, steps, execution) {
|
|
11
|
+
return { success: true, operation, steps, execution };
|
|
12
|
+
}
|
|
13
|
+
export function compositeError(operation, steps, failedStep, execution) {
|
|
14
|
+
return {
|
|
15
|
+
success: false,
|
|
16
|
+
operation,
|
|
17
|
+
steps,
|
|
18
|
+
partial_state: {
|
|
19
|
+
completed_steps: steps.filter(s => s.status === 'success').map(s => s.step),
|
|
20
|
+
failed_step: failedStep,
|
|
21
|
+
editor_state: 'No mutations performed; editor state unchanged',
|
|
22
|
+
},
|
|
23
|
+
execution,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export function compositePartialFailure(operation, steps, failedStep, partialState, execution) {
|
|
27
|
+
return { success: false, operation, steps, partial_state: partialState, execution };
|
|
28
|
+
}
|
|
@@ -36,6 +36,10 @@ export function enrichLiveCodingResult(result, changedPaths = [], lastExternalBu
|
|
|
36
36
|
warnings.push('Live Coding cannot add, remove, or reorder UPROPERTYs or change class layouts. '
|
|
37
37
|
+ 'Use compile_project_code + restart_editor for class layout changes.');
|
|
38
38
|
}
|
|
39
|
+
if (result.noOp && typeof result.compileResult === 'string' && result.compileResult.toLowerCase() === 'nochanges') {
|
|
40
|
+
warnings.push('Live Coding cannot compile newly added source files — it only detects changes to already-compiled .obj files. '
|
|
41
|
+
+ 'Use compile_project_code for new files, then restart_editor to load the new module.');
|
|
42
|
+
}
|
|
39
43
|
const fallbackRecommended = canFallbackFromLiveCoding(result);
|
|
40
44
|
const reason = deriveLiveCodingFallbackReason(result);
|
|
41
45
|
return {
|
|
@@ -47,13 +47,40 @@ export async function callSubsystemJson(client, method, params, options) {
|
|
|
47
47
|
}
|
|
48
48
|
return parsed;
|
|
49
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Extracts the best available error message from a UE failure response,
|
|
52
|
+
* checking message, errorMessage, error, diagnostics[], and errors[] fields
|
|
53
|
+
* before falling back to listing the available response keys.
|
|
54
|
+
*/
|
|
55
|
+
function extractFailureMessage(parsed) {
|
|
56
|
+
if (typeof parsed.message === 'string' && parsed.message.length > 0)
|
|
57
|
+
return parsed.message;
|
|
58
|
+
if (typeof parsed.errorMessage === 'string' && parsed.errorMessage.length > 0)
|
|
59
|
+
return parsed.errorMessage;
|
|
60
|
+
if (typeof parsed.error === 'string' && parsed.error.length > 0)
|
|
61
|
+
return parsed.error;
|
|
62
|
+
if (Array.isArray(parsed.diagnostics) && parsed.diagnostics.length > 0) {
|
|
63
|
+
const messages = parsed.diagnostics
|
|
64
|
+
.filter((d) => typeof d === 'object' && d !== null && typeof d.message === 'string')
|
|
65
|
+
.map((d) => d.message);
|
|
66
|
+
if (messages.length > 0)
|
|
67
|
+
return messages.join('; ');
|
|
68
|
+
}
|
|
69
|
+
if (Array.isArray(parsed.errors) && parsed.errors.length > 0) {
|
|
70
|
+
const first = parsed.errors[0];
|
|
71
|
+
return typeof first === 'string' ? first : JSON.stringify(first);
|
|
72
|
+
}
|
|
73
|
+
const keys = Object.keys(parsed).join(', ');
|
|
74
|
+
return `Operation returned success:false with no diagnostic details. Response keys: [${keys}]`;
|
|
75
|
+
}
|
|
50
76
|
export function jsonToolSuccess(parsed, options = {}) {
|
|
51
77
|
const structuredContent = isRecord(parsed) ? parsed : { data: parsed };
|
|
52
78
|
// Guard: if the UE response indicates failure, route through error path.
|
|
53
79
|
// This prevents tool handlers from accidentally passing error payloads as successes.
|
|
54
80
|
if (isRecord(parsed) && parsed.success === false) {
|
|
81
|
+
const errorText = extractFailureMessage(parsed);
|
|
55
82
|
return {
|
|
56
|
-
content: [{ type: 'text', text: `Error: ${
|
|
83
|
+
content: [{ type: 'text', text: `Error: ${errorText}` }],
|
|
57
84
|
structuredContent,
|
|
58
85
|
isError: true,
|
|
59
86
|
};
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
1
|
+
import { McpServer, type RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import type { ToolHelpEntry } from './tool-help.js';
|
|
4
4
|
type ToolNormalizer = (...args: any[]) => unknown;
|
|
5
5
|
type InstallNormalizedToolRegistrationOptions = {
|
|
6
6
|
server: McpServer;
|
|
7
7
|
toolHelpRegistry: Map<string, ToolHelpEntry>;
|
|
8
|
+
registeredToolMap: Map<string, RegisteredTool>;
|
|
8
9
|
defaultOutputSchema: z.ZodTypeAny;
|
|
9
10
|
normalizeToolError: ToolNormalizer;
|
|
10
11
|
normalizeToolSuccess: ToolNormalizer;
|
|
11
12
|
};
|
|
12
|
-
export declare function installNormalizedToolRegistration({ server, toolHelpRegistry, defaultOutputSchema, normalizeToolError, normalizeToolSuccess, }: InstallNormalizedToolRegistrationOptions): void;
|
|
13
|
+
export declare function installNormalizedToolRegistration({ server, toolHelpRegistry, registeredToolMap, defaultOutputSchema, normalizeToolError, normalizeToolSuccess, }: InstallNormalizedToolRegistrationOptions): void;
|
|
13
14
|
export {};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { extractExtraContent, extractToolPayload, isRecord } from './formatting.js';
|
|
2
|
-
|
|
2
|
+
import { rawHandlerRegistry } from './alias-registration.js';
|
|
3
|
+
export function installNormalizedToolRegistration({ server, toolHelpRegistry, registeredToolMap, defaultOutputSchema, normalizeToolError, normalizeToolSuccess, }) {
|
|
3
4
|
const rawRegisterTool = server.registerTool.bind(server);
|
|
4
5
|
server.registerTool = ((name, config, cb) => {
|
|
5
6
|
const outputSchema = (config.outputSchema ?? defaultOutputSchema);
|
|
7
|
+
rawHandlerRegistry.set(name, cb);
|
|
6
8
|
toolHelpRegistry.set(name, {
|
|
7
9
|
title: config.title ?? name,
|
|
8
10
|
description: config.description ?? '',
|
|
@@ -10,7 +12,7 @@ export function installNormalizedToolRegistration({ server, toolHelpRegistry, de
|
|
|
10
12
|
outputSchema,
|
|
11
13
|
annotations: config.annotations,
|
|
12
14
|
});
|
|
13
|
-
|
|
15
|
+
const registered = rawRegisterTool(name, {
|
|
14
16
|
...config,
|
|
15
17
|
outputSchema,
|
|
16
18
|
}, async (args, extra) => {
|
|
@@ -25,5 +27,7 @@ export function installNormalizedToolRegistration({ server, toolHelpRegistry, de
|
|
|
25
27
|
return normalizeToolError(name, error);
|
|
26
28
|
}
|
|
27
29
|
});
|
|
30
|
+
registeredToolMap.set(name, registered);
|
|
31
|
+
return registered;
|
|
28
32
|
});
|
|
29
33
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { aliasMap } from './alias-registration.js';
|
|
1
2
|
import { isRecord } from './formatting.js';
|
|
2
3
|
export function createToolResultNormalizers({ taskAwareTools, classifyRecoverableToolFailure, }) {
|
|
3
4
|
function extractNonTextContent(existingResult) {
|
|
@@ -9,20 +10,21 @@ export function createToolResultNormalizers({ taskAwareTools, classifyRecoverabl
|
|
|
9
10
|
&& entry.type !== 'text'));
|
|
10
11
|
}
|
|
11
12
|
function defaultNextSteps(toolName, payload) {
|
|
12
|
-
|
|
13
|
+
const resolvedName = aliasMap.get(toolName) ?? toolName;
|
|
14
|
+
if (resolvedName === 'wait_for_editor') {
|
|
13
15
|
return [
|
|
14
16
|
'Retry wait_for_editor if the editor is still restarting.',
|
|
15
17
|
'Once connected=true, rerun the blocked editor-backed tool.',
|
|
16
18
|
];
|
|
17
19
|
}
|
|
18
|
-
if (
|
|
20
|
+
if (resolvedName === 'compile_widget_blueprint') {
|
|
19
21
|
return [
|
|
20
22
|
'Inspect compile.messages and diagnostics for the first failing widget or property.',
|
|
21
23
|
'Re-extract the widget blueprint before applying the next structural patch.',
|
|
22
24
|
'Check BindWidget names/types and any abstract classes referenced by the widget tree.',
|
|
23
25
|
];
|
|
24
26
|
}
|
|
25
|
-
if (taskAwareTools.has(
|
|
27
|
+
if (taskAwareTools.has(resolvedName)) {
|
|
26
28
|
return [
|
|
27
29
|
'Inspect the returned execution.status and diagnostics before retrying.',
|
|
28
30
|
'Poll the task-oriented status tool again if the operation is still running.',
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ export { createBlueprintExtractorServer } from './server-factory.js';
|
|
|
6
6
|
export { exampleCatalog } from './catalogs/example-catalog.js';
|
|
7
7
|
export { promptCatalog } from './prompts/prompt-catalog.js';
|
|
8
8
|
async function main() {
|
|
9
|
-
const server = createBlueprintExtractorServer();
|
|
9
|
+
const { server } = createBlueprintExtractorServer();
|
|
10
10
|
const transport = new StdioServerTransport();
|
|
11
11
|
await server.connect(transport);
|
|
12
12
|
}
|
|
@@ -51,6 +51,7 @@ export interface CompileProjectCodeResult {
|
|
|
51
51
|
stdout?: string;
|
|
52
52
|
stderr?: string;
|
|
53
53
|
uhtCacheFilesDeleted?: string[];
|
|
54
|
+
compilationSucceeded: boolean;
|
|
54
55
|
errorCategory?: BuildErrorCategory;
|
|
55
56
|
errorSummary?: string;
|
|
56
57
|
lockedFiles?: string[];
|
|
@@ -104,6 +105,10 @@ export interface ProjectControllerLike {
|
|
|
104
105
|
readonly liveCodingSupported: boolean;
|
|
105
106
|
classifyChangedPaths(changedPaths: string[], forceRebuild?: boolean): SyncStrategyPlan;
|
|
106
107
|
compileProjectCode(request: CompileProjectCodeRequest): Promise<CompileProjectCodeResult>;
|
|
108
|
+
killEditorProcess(): Promise<{
|
|
109
|
+
killed: boolean;
|
|
110
|
+
error?: string;
|
|
111
|
+
}>;
|
|
107
112
|
launchEditor(request: LaunchEditorRequest): Promise<LaunchEditorResult>;
|
|
108
113
|
waitForEditorRestart(probeConnection: ProbeConnection, options?: {
|
|
109
114
|
disconnectTimeoutMs?: number;
|
|
@@ -131,6 +136,10 @@ export declare class ProjectController implements ProjectControllerLike {
|
|
|
131
136
|
get liveCodingSupported(): boolean;
|
|
132
137
|
classifyChangedPaths(changedPaths: string[], forceRebuild?: boolean): SyncStrategyPlan;
|
|
133
138
|
compileProjectCode(request: CompileProjectCodeRequest): Promise<CompileProjectCodeResult>;
|
|
139
|
+
killEditorProcess(): Promise<{
|
|
140
|
+
killed: boolean;
|
|
141
|
+
error?: string;
|
|
142
|
+
}>;
|
|
134
143
|
launchEditor(request: LaunchEditorRequest): Promise<LaunchEditorResult>;
|
|
135
144
|
waitForEditorRestart(probeConnection: ProbeConnection, options?: {
|
|
136
145
|
disconnectTimeoutMs?: number;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { spawn } from 'node:child_process';
|
|
1
|
+
import { execSync, spawn } from 'node:child_process';
|
|
2
2
|
import { access, readdir, unlink } from 'node:fs/promises';
|
|
3
3
|
import { constants as fsConstants } from 'node:fs';
|
|
4
4
|
import { dirname, resolve } from 'node:path';
|
|
@@ -358,6 +358,7 @@ export class ProjectController {
|
|
|
358
358
|
},
|
|
359
359
|
durationMs: Date.now() - startedAt,
|
|
360
360
|
exitCode: completed.exitCode,
|
|
361
|
+
compilationSucceeded: completed.exitCode === 0,
|
|
361
362
|
restartRequired: true,
|
|
362
363
|
restartReasons: ['external_build_completed'],
|
|
363
364
|
outputIncluded: includeOutput,
|
|
@@ -380,9 +381,26 @@ export class ProjectController {
|
|
|
380
381
|
if (classification.lockedFiles.length > 0) {
|
|
381
382
|
result.lockedFiles = classification.lockedFiles;
|
|
382
383
|
}
|
|
384
|
+
// Compilation itself succeeded if the failure is only at the link/lock stage
|
|
385
|
+
result.compilationSucceeded = classification.errorCategory === 'locked_file'
|
|
386
|
+
|| classification.errorCategory === 'link';
|
|
383
387
|
}
|
|
384
388
|
return result;
|
|
385
389
|
}
|
|
390
|
+
async killEditorProcess() {
|
|
391
|
+
try {
|
|
392
|
+
if (this.platform === 'win32') {
|
|
393
|
+
execSync('taskkill /F /IM "UnrealEditor.exe"', { timeout: 10000 });
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
execSync('pkill -9 -f UnrealEditor', { timeout: 10000 });
|
|
397
|
+
}
|
|
398
|
+
return { killed: true };
|
|
399
|
+
}
|
|
400
|
+
catch (err) {
|
|
401
|
+
return { killed: false, error: String(err) };
|
|
402
|
+
}
|
|
403
|
+
}
|
|
386
404
|
async launchEditor(request) {
|
|
387
405
|
const engineRoot = request.engineRoot ?? this.env.UE_ENGINE_ROOT;
|
|
388
406
|
const projectPath = request.projectPath ?? this.env.UE_PROJECT_PATH;
|
|
@@ -218,7 +218,7 @@ export const promptCatalog = {
|
|
|
218
218
|
`Author widget motion for ${widget_asset_path} using animation '${animation_name}'.`,
|
|
219
219
|
formatPromptBlock('design_spec_json', design_spec_json, 'A design_spec_json with motion data is required.'),
|
|
220
220
|
formatPromptList('Compare reference paths', compare_reference_paths, 'No compare reference paths were supplied. Use checkpoint frames from the design spec if they exist.'),
|
|
221
|
-
'Use create_widget_animation or modify_widget_animation instead of overloading
|
|
221
|
+
'Use create_widget_animation or modify_widget_animation instead of overloading widget tools. Use patch_widget for property changes and replace_widget_tree for full tree replacement.',
|
|
222
222
|
'Supported track subset: render_opacity, render_transform_translation, render_transform_scale, render_transform_angle, color_and_opacity.',
|
|
223
223
|
'Prefer widget_path selectors for bindings and tracks. Accept widget_name only as a compatibility fallback when unique.',
|
|
224
224
|
'Use replace_timeline as the canonical write path. patch_metadata is only for display labels, checkpoints, playback metadata, and other non-track updates.',
|
|
@@ -263,7 +263,7 @@ export const promptCatalog = {
|
|
|
263
263
|
`Target widget class: ${widget_class_path}.`,
|
|
264
264
|
`Class default property: ${class_default_property}.`,
|
|
265
265
|
'Inspect the current Blueprint members and class defaults first.',
|
|
266
|
-
'Return the smallest set of modify_blueprint_members or
|
|
266
|
+
'Return the smallest set of modify_blueprint_members or patch_widget_class_defaults calls needed to complete the wiring.',
|
|
267
267
|
].join('\n'),
|
|
268
268
|
},
|
|
269
269
|
debug_widget_compile_errors: {
|
|
@@ -26,7 +26,8 @@ type RegisterServerToolsOptions = {
|
|
|
26
26
|
getLastExternalBuildContext: () => Record<string, unknown> | null;
|
|
27
27
|
clearProjectAutomationContext: () => void;
|
|
28
28
|
getToolHelpEntry: (toolName: string) => ToolHelpEntry | undefined;
|
|
29
|
+
toolHelpRegistry: Map<string, ToolHelpEntry>;
|
|
29
30
|
editorPollIntervalMs: number;
|
|
30
31
|
};
|
|
31
|
-
export declare function registerServerTools({ server, client, projectController, automationController, callSubsystemJson, resolveProjectInputs, getProjectAutomationContext, rememberExternalBuild, getLastExternalBuildContext, clearProjectAutomationContext, getToolHelpEntry, editorPollIntervalMs, }: RegisterServerToolsOptions): void;
|
|
32
|
+
export declare function registerServerTools({ server, client, projectController, automationController, callSubsystemJson, resolveProjectInputs, getProjectAutomationContext, rememberExternalBuild, getLastExternalBuildContext, clearProjectAutomationContext, getToolHelpEntry, toolHelpRegistry, editorPollIntervalMs, }: RegisterServerToolsOptions): void;
|
|
32
33
|
export {};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { exampleCatalog } from './catalogs/example-catalog.js';
|
|
3
3
|
import { collectRelatedResources, collectToolExampleFamilies as collectToolExampleFamiliesFromCatalog, summarizeOutputSchema, summarizeSchemaFields, } from './helpers/tool-help.js';
|
|
4
|
-
import { AnimMontageMutationOperationSchema, AnimationNotifySelectorSchema, AnimSequenceMutationOperationSchema, BehaviorTreeMutationOperationSchema, BehaviorTreeNodeSelectorSchema, BlackboardKeySchema, BlackboardMutationOperationSchema, BlendParameterSchema, BlendSpaceMutationOperationSchema, BlendSpaceSampleSchema, BlueprintGraphMutationOperationSchema, BlueprintMemberMutationOperationSchema, BuildConfigurationSchema, BuildPlatformSchema, CurveChannelSchema, CurveKeyDeleteSchema, CurveKeyUpsertSchema, CurveTableModeSchema, CurveTableRowSchema, CurveTypeSchema, DataTableRowSchema, ExtractAssetTypeSchema, EnhancedInputValueTypeSchema, FontImportItemSchema, ImportJobListSchema, ImportJobSchema, ImportPayloadSchema, InputMappingSchema, JsonObjectSchema, MaterialConnectionSelectorFieldsSchema, MaterialFontParameterSchema, MaterialFunctionAssetKindSchema, MaterialGraphOperationKindSchema, MaterialGraphOperationSchema, MaterialGraphPayloadSchema, MaterialLayerStackSchema, MaterialNodePositionSchema, MaterialScalarParameterSchema, MaterialStaticSwitchParameterSchema, MaterialTextureParameterSchema, MaterialVectorParameterSchema, MeshImportPayloadSchema, StateTreeEditorNodeSelectorSchema, StateTreeMutationOperationSchema, StateTreeStateSelectorSchema, StateTreeTransitionSelectorSchema,
|
|
4
|
+
import { AnimMontageMutationOperationSchema, AnimationNotifySelectorSchema, AnimSequenceMutationOperationSchema, BehaviorTreeMutationOperationSchema, BehaviorTreeNodeSelectorSchema, BlackboardKeySchema, BlackboardMutationOperationSchema, BlendParameterSchema, BlendSpaceMutationOperationSchema, BlendSpaceSampleSchema, BlueprintGraphMutationOperationSchema, BlueprintMemberMutationOperationSchema, BuildConfigurationSchema, BuildPlatformSchema, CurveChannelSchema, CurveKeyDeleteSchema, CurveKeyUpsertSchema, CurveTableModeSchema, CurveTableRowSchema, CurveTypeSchema, DataTableRowSchema, ExtractAssetTypeSchema, EnhancedInputValueTypeSchema, FontImportItemSchema, ImportJobListSchema, ImportJobSchema, ImportPayloadSchema, InputMappingSchema, JsonObjectSchema, MaterialConnectionSelectorFieldsSchema, MaterialFontParameterSchema, MaterialFunctionAssetKindSchema, MaterialGraphOperationKindSchema, MaterialGraphOperationSchema, MaterialGraphPayloadSchema, MaterialLayerStackSchema, MaterialNodePositionSchema, MaterialScalarParameterSchema, MaterialStaticSwitchParameterSchema, MaterialTextureParameterSchema, MaterialVectorParameterSchema, MeshImportOptionsSchema, MeshImportPayloadSchema, StateTreeEditorNodeSelectorSchema, StateTreeMutationOperationSchema, StateTreeStateSelectorSchema, StateTreeTransitionSelectorSchema, StateTreeBindingsObjectSchema, TextureImportOptionsSchema, TextureImportPayloadSchema, UserDefinedEnumEntrySchema, UserDefinedEnumMutationOperationSchema, UserDefinedStructFieldSchema, UserDefinedStructMutationOperationSchema, WidgetBlueprintMutationOperationSchema, WidgetNodeSchema, WidgetSelectorFieldsSchema, WindowFontApplicationSchema, } from './schemas/tool-inputs.js';
|
|
5
5
|
import { applyWindowUiChangesResultSchema, AutomationRunListSchema, automationRunSchema, CaptureResultSchema, CascadeResultSchema, CleanupCapturesResultSchema, CompareCaptureResultSchema, CompareMotionCaptureBundleResultSchema, CreateModifyWidgetAnimationResultSchema, ExtractWidgetAnimationResultSchema, ListCapturesResultSchema, motionCaptureModeSchema, MotionCaptureBundleResultSchema, widgetAnimationCheckpointSchema, } from './schemas/tool-results.js';
|
|
6
6
|
import { registerAnimationAuthoringTools } from './tools/animation-authoring.js';
|
|
7
7
|
import { registerAutomationRunTools } from './tools/automation-runs.js';
|
|
8
8
|
import { registerBlueprintAuthoringTools } from './tools/blueprint-authoring.js';
|
|
9
|
+
import { registerCompositeTools } from './tools/composite-tools.js';
|
|
9
10
|
import { registerCommonUIButtonStyleTools } from './tools/commonui-button-style.js';
|
|
10
11
|
import { registerDataAndInputTools } from './tools/data-and-input.js';
|
|
11
12
|
import { registerExtractionTools } from './tools/extraction.js';
|
|
@@ -29,7 +30,7 @@ const scopeEnum = z.enum([
|
|
|
29
30
|
'Full',
|
|
30
31
|
'FullWithBytecode',
|
|
31
32
|
]);
|
|
32
|
-
export function registerServerTools({ server, client, projectController, automationController, callSubsystemJson, resolveProjectInputs, getProjectAutomationContext, rememberExternalBuild, getLastExternalBuildContext, clearProjectAutomationContext, getToolHelpEntry, editorPollIntervalMs, }) {
|
|
33
|
+
export function registerServerTools({ server, client, projectController, automationController, callSubsystemJson, resolveProjectInputs, getProjectAutomationContext, rememberExternalBuild, getLastExternalBuildContext, clearProjectAutomationContext, getToolHelpEntry, toolHelpRegistry, editorPollIntervalMs, }) {
|
|
33
34
|
const collectToolExampleFamilies = (toolName) => (collectToolExampleFamiliesFromCatalog(exampleCatalog, toolName));
|
|
34
35
|
registerExtractionTools({
|
|
35
36
|
server,
|
|
@@ -37,6 +38,7 @@ export function registerServerTools({ server, client, projectController, automat
|
|
|
37
38
|
scopeEnum,
|
|
38
39
|
extractAssetTypeSchema: ExtractAssetTypeSchema,
|
|
39
40
|
cascadeResultSchema: CascadeResultSchema,
|
|
41
|
+
toolHelpRegistry,
|
|
40
42
|
});
|
|
41
43
|
registerWidgetStructureTools({
|
|
42
44
|
server,
|
|
@@ -112,6 +114,7 @@ export function registerServerTools({ server, client, projectController, automat
|
|
|
112
114
|
materialGraphOperationKindSchema: MaterialGraphOperationKindSchema,
|
|
113
115
|
materialGraphOperationSchema: MaterialGraphOperationSchema,
|
|
114
116
|
materialFunctionAssetKindSchema: MaterialFunctionAssetKindSchema,
|
|
117
|
+
toolHelpRegistry,
|
|
115
118
|
});
|
|
116
119
|
registerAutomationRunTools({
|
|
117
120
|
server,
|
|
@@ -166,7 +169,7 @@ export function registerServerTools({ server, client, projectController, automat
|
|
|
166
169
|
stateTreeStateSelectorSchema: StateTreeStateSelectorSchema,
|
|
167
170
|
stateTreeEditorNodeSelectorSchema: StateTreeEditorNodeSelectorSchema,
|
|
168
171
|
stateTreeTransitionSelectorSchema: StateTreeTransitionSelectorSchema,
|
|
169
|
-
|
|
172
|
+
stateTreeBindingsObjectSchema: StateTreeBindingsObjectSchema,
|
|
170
173
|
});
|
|
171
174
|
registerAnimationAuthoringTools({
|
|
172
175
|
server,
|
|
@@ -194,6 +197,14 @@ export function registerServerTools({ server, client, projectController, automat
|
|
|
194
197
|
importJobListSchema: ImportJobListSchema,
|
|
195
198
|
textureImportPayloadSchema: TextureImportPayloadSchema,
|
|
196
199
|
meshImportPayloadSchema: MeshImportPayloadSchema,
|
|
200
|
+
textureImportOptionsSchema: TextureImportOptionsSchema,
|
|
201
|
+
meshImportOptionsSchema: MeshImportOptionsSchema,
|
|
202
|
+
toolHelpRegistry,
|
|
203
|
+
});
|
|
204
|
+
registerCompositeTools({
|
|
205
|
+
server,
|
|
206
|
+
callSubsystemJson,
|
|
207
|
+
toolHelpRegistry,
|
|
197
208
|
});
|
|
198
209
|
registerUtilityTools({
|
|
199
210
|
server,
|
|
@@ -64,7 +64,8 @@ export function registerStaticDocResources(server) {
|
|
|
64
64
|
'- UserDefinedEnum: entry selector by name; operations replace_entries, rename_entry, remove_entry, reorder_entries.',
|
|
65
65
|
'- Blackboard: key selector by entryName; operations replace_keys, patch_key, remove_key, set_parent.',
|
|
66
66
|
'- BehaviorTree: node selector by nodePath; operations replace_tree, patch_node, patch_attachment, set_blackboard.',
|
|
67
|
-
'- StateTree: selectors by stateId/statePath, editorNodeId, or transitionId; operations replace_tree, patch_state, patch_editor_node, patch_transition, set_schema.',
|
|
67
|
+
'- StateTree: selectors by stateId/statePath, editorNodeId, or transitionId; operations replace_tree, patch_state, patch_editor_node, patch_transition, set_schema, set_bindings, add_binding, remove_binding. Blueprint-wrapped nodes (StateTreeBlueprintTaskWrapper / StateTreeBlueprintConditionWrapper) require instanceObjectClass for the backing instance to exist at runtime.',
|
|
68
|
+
'- StateTree property bindings wire task/evaluator outputs to task inputs. Use extract_asset to discover structIds and property names. Each binding has sourcePath and targetPath with segments: [{name, arrayIndex?, instanceStruct?}] and optional structId. Operations: set_bindings (replace all), add_binding (append), remove_binding (by targetPath). In replace_tree/create: include as { bindings: { propertyBindings: [...] } }.',
|
|
68
69
|
'- AnimSequence: notify selector by notifyId/notifyGuid with notifyIndex or track metadata as fallback; operations replace_notifies, patch_notify, replace_sync_markers, replace_curve_metadata.',
|
|
69
70
|
'- AnimMontage: notify selector by notifyId/notifyGuid with notifyIndex or track metadata as fallback; operations replace_notifies, patch_notify, replace_sections, replace_slots.',
|
|
70
71
|
'- BlendSpace: sample selector by sampleIndex; operations replace_samples, patch_sample, set_axes.',
|