blueprint-extractor-mcp 7.0.8 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/README.md +8 -7
  2. package/dist/active-editor-session.d.ts +0 -0
  3. package/dist/active-editor-session.js +0 -0
  4. package/dist/automation-controller.d.ts +0 -0
  5. package/dist/automation-controller.js +0 -0
  6. package/dist/catalogs/example-catalog.d.ts +0 -0
  7. package/dist/catalogs/example-catalog.js +0 -0
  8. package/dist/compactor.d.ts +0 -0
  9. package/dist/compactor.js +0 -0
  10. package/dist/editor-instance-registry.d.ts +0 -0
  11. package/dist/editor-instance-registry.js +0 -0
  12. package/dist/editor-instance-types.d.ts +0 -0
  13. package/dist/editor-instance-types.js +0 -0
  14. package/dist/execution/adapters/commandlet-adapter.d.ts +0 -0
  15. package/dist/execution/adapters/commandlet-adapter.js +0 -0
  16. package/dist/execution/adapters/editor-adapter.d.ts +0 -0
  17. package/dist/execution/adapters/editor-adapter.js +0 -0
  18. package/dist/execution/adapters/lazy-commandlet-adapter.d.ts +0 -0
  19. package/dist/execution/adapters/lazy-commandlet-adapter.js +0 -0
  20. package/dist/execution/adaptive-executor.d.ts +0 -0
  21. package/dist/execution/adaptive-executor.js +49 -1
  22. package/dist/execution/execution-adapter.d.ts +0 -0
  23. package/dist/execution/execution-adapter.js +0 -0
  24. package/dist/execution/execution-mode-detector.d.ts +0 -0
  25. package/dist/execution/execution-mode-detector.js +0 -0
  26. package/dist/execution/index.d.ts +0 -0
  27. package/dist/execution/index.js +0 -0
  28. package/dist/helpers/active-editor-utils.d.ts +0 -0
  29. package/dist/helpers/active-editor-utils.js +0 -0
  30. package/dist/helpers/alias-registration.d.ts +0 -0
  31. package/dist/helpers/alias-registration.js +0 -0
  32. package/dist/helpers/blueprint-dsl-parser.d.ts +0 -0
  33. package/dist/helpers/blueprint-dsl-parser.js +0 -0
  34. package/dist/helpers/blueprint-validation.d.ts +0 -0
  35. package/dist/helpers/blueprint-validation.js +0 -0
  36. package/dist/helpers/capture.d.ts +0 -0
  37. package/dist/helpers/capture.js +0 -0
  38. package/dist/helpers/commonui-button-style.d.ts +0 -0
  39. package/dist/helpers/commonui-button-style.js +0 -0
  40. package/dist/helpers/composite-patterns.d.ts +0 -0
  41. package/dist/helpers/composite-patterns.js +0 -0
  42. package/dist/helpers/formatting.d.ts +0 -0
  43. package/dist/helpers/formatting.js +0 -0
  44. package/dist/helpers/live-coding.d.ts +0 -0
  45. package/dist/helpers/live-coding.js +0 -0
  46. package/dist/helpers/material-dsl-parser.d.ts +0 -0
  47. package/dist/helpers/material-dsl-parser.js +0 -0
  48. package/dist/helpers/mutation-filter.d.ts +0 -0
  49. package/dist/helpers/mutation-filter.js +0 -0
  50. package/dist/helpers/next-step-hints.d.ts +0 -0
  51. package/dist/helpers/next-step-hints.js +7 -45
  52. package/dist/helpers/operation-deny-list.d.ts +0 -0
  53. package/dist/helpers/operation-deny-list.js +0 -0
  54. package/dist/helpers/package-metadata.d.ts +0 -0
  55. package/dist/helpers/package-metadata.js +0 -0
  56. package/dist/helpers/phantom-filter.d.ts +0 -0
  57. package/dist/helpers/phantom-filter.js +0 -0
  58. package/dist/helpers/project-resolution.d.ts +0 -0
  59. package/dist/helpers/project-resolution.js +40 -17
  60. package/dist/helpers/project-utils.d.ts +0 -0
  61. package/dist/helpers/project-utils.js +0 -0
  62. package/dist/helpers/property-path-parser.d.ts +0 -0
  63. package/dist/helpers/property-path-parser.js +0 -0
  64. package/dist/helpers/property-shorthand.d.ts +0 -0
  65. package/dist/helpers/property-shorthand.js +0 -0
  66. package/dist/helpers/response-summarizer.d.ts +0 -0
  67. package/dist/helpers/response-summarizer.js +0 -0
  68. package/dist/helpers/slot-presets.d.ts +0 -0
  69. package/dist/helpers/slot-presets.js +0 -0
  70. package/dist/helpers/subsystem.d.ts +0 -0
  71. package/dist/helpers/subsystem.js +0 -0
  72. package/dist/helpers/token-budget.d.ts +0 -0
  73. package/dist/helpers/token-budget.js +0 -0
  74. package/dist/helpers/tool-help.d.ts +0 -0
  75. package/dist/helpers/tool-help.js +4 -18
  76. package/dist/helpers/tool-registration.d.ts +0 -0
  77. package/dist/helpers/tool-registration.js +0 -0
  78. package/dist/helpers/tool-results.d.ts +0 -0
  79. package/dist/helpers/tool-results.js +0 -0
  80. package/dist/helpers/verification.d.ts +0 -0
  81. package/dist/helpers/verification.js +0 -0
  82. package/dist/helpers/widget-class-aliases.d.ts +0 -0
  83. package/dist/helpers/widget-class-aliases.js +0 -0
  84. package/dist/helpers/widget-diff-parser.d.ts +0 -0
  85. package/dist/helpers/widget-diff-parser.js +0 -0
  86. package/dist/helpers/widget-dsl-parser.d.ts +0 -0
  87. package/dist/helpers/widget-dsl-parser.js +0 -0
  88. package/dist/helpers/widget-recipe-formatter.d.ts +0 -0
  89. package/dist/helpers/widget-recipe-formatter.js +0 -0
  90. package/dist/helpers/widget-recipe-parser.d.ts +0 -0
  91. package/dist/helpers/widget-recipe-parser.js +0 -0
  92. package/dist/helpers/widget-utils.d.ts +0 -0
  93. package/dist/helpers/widget-utils.js +0 -0
  94. package/dist/helpers/workspace-project.d.ts +4 -0
  95. package/dist/helpers/workspace-project.js +33 -1
  96. package/dist/index.d.ts +0 -0
  97. package/dist/index.js +0 -0
  98. package/dist/project-controller.d.ts +4 -2
  99. package/dist/project-controller.js +62 -29
  100. package/dist/prompts/prompt-catalog.d.ts +0 -0
  101. package/dist/prompts/prompt-catalog.js +0 -0
  102. package/dist/register-server-resources.d.ts +0 -0
  103. package/dist/register-server-resources.js +0 -0
  104. package/dist/register-server-tools.d.ts +0 -0
  105. package/dist/register-server-tools.js +1 -2
  106. package/dist/resources/example-and-capture-resources.d.ts +0 -0
  107. package/dist/resources/example-and-capture-resources.js +0 -0
  108. package/dist/resources/static-doc-resources.d.ts +0 -0
  109. package/dist/resources/static-doc-resources.js +10 -5
  110. package/dist/schemas/tool-inputs.d.ts +24 -25
  111. package/dist/schemas/tool-inputs.js +1 -13
  112. package/dist/schemas/tool-results.d.ts +623 -2
  113. package/dist/schemas/tool-results.js +69 -0
  114. package/dist/server-config.d.ts +0 -0
  115. package/dist/server-config.js +13 -11
  116. package/dist/server-factory.d.ts +0 -0
  117. package/dist/server-factory.js +38 -3
  118. package/dist/tool-context.d.ts +0 -0
  119. package/dist/tool-context.js +0 -0
  120. package/dist/tool-surface-manager.d.ts +5 -1
  121. package/dist/tool-surface-manager.js +42 -22
  122. package/dist/tools/analysis-tools.d.ts +0 -0
  123. package/dist/tools/analysis-tools.js +0 -0
  124. package/dist/tools/animation-authoring.d.ts +0 -0
  125. package/dist/tools/animation-authoring.js +0 -0
  126. package/dist/tools/automation-runs.d.ts +0 -0
  127. package/dist/tools/automation-runs.js +0 -0
  128. package/dist/tools/blueprint-authoring.d.ts +0 -0
  129. package/dist/tools/blueprint-authoring.js +0 -0
  130. package/dist/tools/commonui-button-style.d.ts +0 -0
  131. package/dist/tools/commonui-button-style.js +0 -0
  132. package/dist/tools/composite-tools.d.ts +0 -0
  133. package/dist/tools/composite-tools.js +0 -0
  134. package/dist/tools/composite-workflows.d.ts +0 -0
  135. package/dist/tools/composite-workflows.js +0 -0
  136. package/dist/tools/data-and-input.d.ts +0 -0
  137. package/dist/tools/data-and-input.js +0 -0
  138. package/dist/tools/extraction.d.ts +0 -0
  139. package/dist/tools/extraction.js +0 -0
  140. package/dist/tools/import-jobs.d.ts +0 -0
  141. package/dist/tools/import-jobs.js +0 -0
  142. package/dist/tools/material-authoring.d.ts +0 -0
  143. package/dist/tools/material-authoring.js +0 -0
  144. package/dist/tools/material-instance.d.ts +0 -0
  145. package/dist/tools/material-instance.js +0 -0
  146. package/dist/tools/project-control.d.ts +0 -0
  147. package/dist/tools/project-control.js +112 -1
  148. package/dist/tools/project-intelligence.d.ts +0 -0
  149. package/dist/tools/project-intelligence.js +2 -1
  150. package/dist/tools/recipe-tools.d.ts +0 -0
  151. package/dist/tools/recipe-tools.js +0 -0
  152. package/dist/tools/schema-and-ai-authoring.d.ts +0 -0
  153. package/dist/tools/schema-and-ai-authoring.js +0 -0
  154. package/dist/tools/tables-and-curves.d.ts +0 -0
  155. package/dist/tools/tables-and-curves.js +0 -0
  156. package/dist/tools/utility-tools.d.ts +0 -0
  157. package/dist/tools/utility-tools.js +0 -0
  158. package/dist/tools/widget-animation-authoring.d.ts +0 -0
  159. package/dist/tools/widget-animation-authoring.js +0 -0
  160. package/dist/tools/widget-extraction.d.ts +0 -0
  161. package/dist/tools/widget-extraction.js +0 -0
  162. package/dist/tools/widget-structure.d.ts +1 -2
  163. package/dist/tools/widget-structure.js +23 -267
  164. package/dist/tools/widget-verification.d.ts +0 -0
  165. package/dist/tools/widget-verification.js +0 -0
  166. package/dist/tools/window-ui.d.ts +0 -0
  167. package/dist/tools/window-ui.js +3 -3
  168. package/dist/types.d.ts +0 -0
  169. package/dist/types.js +0 -0
  170. package/dist/ue-client.d.ts +0 -0
  171. package/dist/ue-client.js +0 -0
  172. package/package.json +1 -1
package/README.md CHANGED
@@ -23,7 +23,7 @@ Blueprint Extractor MCP is a [Model Context Protocol](https://modelcontextprotoc
23
23
  AI Assistant stdio MCP Server HTTP :30010 Unreal Editor
24
24
  ───────────── ◄────────────► ───────────────── ◄──────────────────► ─────────────────
25
25
  Claude Code Node.js process Remote Control API
26
- Codex / OpenCode 106 tools BlueprintExtractor
26
+ Codex / OpenCode 112 tools BlueprintExtractor
27
27
  ... 38 resources plugin
28
28
  4 resource templates
29
29
  12 prompts
@@ -112,22 +112,23 @@ codex mcp add --env UE_REMOTE_CONTROL_PORT=30010 \
112
112
 
113
113
  ## Tool Surface
114
114
 
115
- Only the compact core surface is visible by default to keep the context window lean. Specialized families are loaded on demand via `activate_workflow_scope`.
115
+ Use `activate_tool_profile` to switch between the compact `default` surface and the full `expert` surface. The default profile keeps the context window lean and loads specialized families on demand via `activate_workflow_scope`.
116
116
 
117
117
  | Scope | What It Unlocks |
118
118
  |:------|:----------------|
119
- | **Core** *(always on)* | Search, extraction, list/save/help, editor-session binding, and project-control entry points such as `extract_asset`, `search_assets`, `save_assets`, `get_tool_help`, and `activate_workflow_scope` |
119
+ | **Core** *(always on in `default` profile)* | Search, extraction, `find_and_extract`, list/save/help, and the profile/scope switches such as `extract_asset`, `search_assets`, `save_assets`, `get_tool_help`, `activate_tool_profile`, and `activate_workflow_scope` |
120
120
  | `widget_authoring` | Parent scope that loads `widget_authoring_structure`, `widget_authoring_visual`, and `widget_verification` together |
121
- | `widget_authoring_structure` | Widget tree structure, hierarchy edits, wrapping, moving, replacement, and batch operations |
121
+ | `widget_authoring_structure` | Recipe-first widget authoring, tree replacement, unified-diff patching, and focused structure edits without the deprecated widget aliases |
122
122
  | `widget_authoring_visual` | Widget compile flows, CommonUI styles, widget animations, and widget preview capture |
123
123
  | `widget_verification` | Widget capture, checkpoint bundles, capture listing, cleanup, and reference comparison |
124
- | `material_authoring` | Material creation, `material_graph_operation`, compile, and material-instance edits |
125
- | `blueprint_authoring` | Blueprint creation, member edits, graph edits, and Live Coding trigger |
124
+ | `material_authoring` | `create_material_setup`, `modify_material`, `material_graph_operation`, compile, and material-instance edits |
125
+ | `blueprint_authoring` | `scaffold_blueprint`, graph/member edits, Blueprint creation, and Live Coding trigger |
126
126
  | `schema_ai_authoring` | Structs, enums, Blackboards, Behavior Trees, and State Trees |
127
127
  | `animation_authoring` | Anim sequences, montages, blend spaces, and widget motion authoring |
128
128
  | `data_tables` | Data assets, data tables, curves, Input Actions, and Input Mapping Contexts |
129
129
  | `import` | Async asset import and import-job polling |
130
- | `automation_testing` | Host-side automation runs, coarse project automation context, and PIE lifecycle control |
130
+ | `project_control` | Editor-session binding, launch/wait, project automation context, Output Log and Message Log inspection, PIE lifecycle control, host build/restart/sync, and `apply_window_ui_changes` |
131
+ | `automation_testing` | Host-side automation runs and automation-run polling |
131
132
  | `analysis` | Deterministic Blueprint review and low-noise project asset audits |
132
133
  | `project_intelligence` | Bounded editor context, project indexing, freshness status, and snippet-first context search |
133
134
  | `verification` | Editor/runtime screenshots, capture comparison, motion verification, and artifact inspection |
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/dist/compactor.js CHANGED
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -2,6 +2,15 @@
2
2
  * AdaptiveExecutor routes tool calls to the best available adapter.
3
3
  * Falls back from editor to commandlet for compatible operations.
4
4
  */
5
+ const EDITOR_FALLBACK_ERROR_FRAGMENTS = [
6
+ 'UE Editor not running or Remote Control not available',
7
+ 'BlueprintExtractor subsystem not found',
8
+ 'No active editor is selected for this MCP session',
9
+ 'Multiple running editors match the workspace project',
10
+ 'Active editor mismatch',
11
+ 'previously selected active editor',
12
+ 'The selected active editor is currently unavailable on its registered Remote Control endpoint.',
13
+ ];
5
14
  export class AdaptiveExecutor {
6
15
  editorAdapter;
7
16
  commandletAdapter;
@@ -47,10 +56,42 @@ export class AdaptiveExecutor {
47
56
  async executeRouted(editorFallback, method, params, options) {
48
57
  const toolName = this._activeToolName;
49
58
  const detection = await this.detector.detect();
59
+ const tryCommandletFallback = async (error, requiredCapability) => {
60
+ if (!toolName || !this.commandletAdapter || !shouldFallbackToCommandlet(error)) {
61
+ throw error;
62
+ }
63
+ const commandletCapabilities = this.commandletAdapter.getCapabilities();
64
+ if (!commandletCapabilities.has(requiredCapability) && requiredCapability !== 'write_simple') {
65
+ throw error;
66
+ }
67
+ const available = await this.commandletAdapter.isAvailable();
68
+ if (!available) {
69
+ throw error;
70
+ }
71
+ this.detector.invalidateCache();
72
+ return this.commandletAdapter.execute('BlueprintExtractor', method, params);
73
+ };
50
74
  // If no active tool context or editor mode, use the original path
51
75
  // (preserves callSubsystemJson error-checking layer)
52
76
  if (!toolName || detection.mode === 'editor') {
53
- return editorFallback(method, params, options);
77
+ if (!toolName) {
78
+ return editorFallback(method, params, options);
79
+ }
80
+ const toolMode = this.getToolMode(toolName);
81
+ const requiredCapability = toolMode === 'read_only'
82
+ ? 'read'
83
+ : toolMode === 'both'
84
+ ? 'write_simple'
85
+ : 'write_complex';
86
+ try {
87
+ return await editorFallback(method, params, options);
88
+ }
89
+ catch (error) {
90
+ if (toolMode === 'editor_only') {
91
+ throw error;
92
+ }
93
+ return tryCommandletFallback(error, requiredCapability);
94
+ }
54
95
  }
55
96
  const toolMode = this.getToolMode(toolName);
56
97
  const requiredCapability = toolMode === 'read_only'
@@ -100,6 +141,13 @@ export class AdaptiveExecutor {
100
141
  throw new ExecutorError('MODE_UNAVAILABLE', `No execution mode available for tool '${toolName}'. ${detection.reason}`, toolName, detection.mode, requiredCapability);
101
142
  }
102
143
  }
144
+ function shouldFallbackToCommandlet(error) {
145
+ const message = error instanceof Error ? error.message : String(error);
146
+ if (message.startsWith('Failed to call ')) {
147
+ return true;
148
+ }
149
+ return EDITOR_FALLBACK_ERROR_FRAGMENTS.some((fragment) => message.includes(fragment));
150
+ }
103
151
  export class ExecutorError extends Error {
104
152
  code;
105
153
  toolName;
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -254,7 +254,7 @@ export const NEXT_STEP_HINTS_REGISTRY = new Map([
254
254
  ['extract_widget_blueprint', extractionHints('extract_widget_blueprint', {
255
255
  on_success: [
256
256
  'Use patch_widget or replace_widget_tree to modify the widget.',
257
- 'Use compile_widget_blueprint to check for errors.',
257
+ 'Use compile_widget to check for errors.',
258
258
  'Use capture_widget_preview for visual verification.',
259
259
  ],
260
260
  scope_suggestion: 'widget_authoring',
@@ -276,25 +276,17 @@ export const NEXT_STEP_HINTS_REGISTRY = new Map([
276
276
  // =========================================================================
277
277
  // Widget structure tools
278
278
  // =========================================================================
279
- ['create_widget_blueprint', creationHints('extract_widget_blueprint', 'build_widget_tree', {
279
+ ['create_widget_blueprint', creationHints('extract_widget_blueprint', 'replace_widget_tree', {
280
280
  on_success: [
281
- 'Use build_widget_tree to populate the widget tree.',
281
+ 'Use replace_widget_tree to populate the widget tree.',
282
282
  'Use extract_widget_blueprint to verify.',
283
283
  'Use save_assets to persist.',
284
284
  ],
285
285
  scope_suggestion: 'widget_authoring',
286
286
  })],
287
- ['build_widget_tree', modificationHints('extract_widget_blueprint', {
288
- on_success: [
289
- 'Use compile_widget_blueprint to verify the tree compiles.',
290
- 'Use extract_widget_blueprint to inspect the result.',
291
- 'Use save_assets to persist.',
292
- ],
293
- scope_suggestion: 'widget_authoring',
294
- })],
295
287
  ['replace_widget_tree', modificationHints('extract_widget_blueprint', {
296
288
  on_success: [
297
- 'Use compile_widget_blueprint to verify the new tree.',
289
+ 'Use compile_widget to verify the new tree.',
298
290
  'Use extract_widget_blueprint to inspect the result.',
299
291
  'Use save_assets to persist.',
300
292
  ],
@@ -344,7 +336,7 @@ export const NEXT_STEP_HINTS_REGISTRY = new Map([
344
336
  })],
345
337
  ['replace_widget_class', modificationHints('extract_widget_blueprint', {
346
338
  on_success: [
347
- 'Use compile_widget_blueprint to verify the class change.',
339
+ 'Use compile_widget to verify the class change.',
348
340
  'Use extract_widget_blueprint to inspect the result.',
349
341
  'Use save_assets to persist.',
350
342
  ],
@@ -352,7 +344,7 @@ export const NEXT_STEP_HINTS_REGISTRY = new Map([
352
344
  })],
353
345
  ['batch_widget_operations', modificationHints('extract_widget_blueprint', {
354
346
  on_success: [
355
- 'Use compile_widget_blueprint to verify the batch result.',
347
+ 'Use compile_widget to verify the batch result.',
356
348
  'Use extract_widget_blueprint to inspect changes.',
357
349
  'Use save_assets to persist.',
358
350
  ],
@@ -370,36 +362,6 @@ export const NEXT_STEP_HINTS_REGISTRY = new Map([
370
362
  ],
371
363
  scope_suggestion: 'widget_authoring',
372
364
  }],
373
- ['modify_widget_blueprint', modificationHints('extract_widget_blueprint', {
374
- on_success: [
375
- 'Use operation-specific tools (patch_widget, replace_widget_tree, etc.) instead.',
376
- 'Use save_assets to persist changes.',
377
- ],
378
- on_error: [
379
- 'Use extract_widget_blueprint to inspect current state.',
380
- 'Consider using operation-specific tools for clearer errors.',
381
- ],
382
- scope_suggestion: 'widget_authoring',
383
- })],
384
- ['modify_widget', modificationHints('extract_widget_blueprint', {
385
- on_success: [
386
- 'Use save_assets to persist changes.',
387
- 'Use extract_widget_blueprint to verify.',
388
- ],
389
- scope_suggestion: 'widget_authoring',
390
- })],
391
- ['compile_widget_blueprint', {
392
- on_success: [
393
- 'Inspect compile.messages and diagnostics for warnings.',
394
- 'Re-extract the widget blueprint before applying the next patch.',
395
- 'Check BindWidget names/types if there are abstract class references.',
396
- ],
397
- on_error: [
398
- 'Use extract_widget_blueprint to inspect the current state.',
399
- 'Fix reported issues and recompile.',
400
- ],
401
- scope_suggestion: 'widget_authoring',
402
- }],
403
365
  // =========================================================================
404
366
  // Widget verification tools
405
367
  // =========================================================================
@@ -464,7 +426,7 @@ export const NEXT_STEP_HINTS_REGISTRY = new Map([
464
426
  ['apply_commonui_button_style', {
465
427
  on_success: [
466
428
  'Use extract_widget_blueprint to verify the style was applied.',
467
- 'Use compile_widget_blueprint to verify compilation.',
429
+ 'Use compile_widget to verify compilation.',
468
430
  'Use save_assets to persist.',
469
431
  ],
470
432
  on_error: [
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -1,7 +1,7 @@
1
1
  import { access } from 'node:fs/promises';
2
2
  import { constants as fsConstants } from 'node:fs';
3
- import path, { resolve } from 'node:path';
4
- import { buildEngineAssociationCandidates, readProjectEngineAssociation } from './workspace-project.js';
3
+ import path, { posix as posixPath, win32 as win32Path } from 'node:path';
4
+ import { buildEngineAssociationCandidates, isWindowsStylePath, isWslMountedWindowsPath, readProjectEngineAssociation, toHostFilesystemPath, toWindowsStylePath, } from './workspace-project.js';
5
5
  export function rememberExternalBuild(result) {
6
6
  return {
7
7
  success: result.success === true,
@@ -32,6 +32,9 @@ export async function getProjectAutomationContext(deps) {
32
32
  return nextContext;
33
33
  }
34
34
  const cachedHeuristicEngineRoots = new Map();
35
+ function getPathModule(platform) {
36
+ return platform === 'win32' ? win32Path : posixPath;
37
+ }
35
38
  export function getHeuristicEngineCandidates(platform = process.platform) {
36
39
  if (platform === 'win32') {
37
40
  return [
@@ -74,10 +77,13 @@ function getEngineMarkers(platform) {
74
77
  'Engine/Build/BatchFiles/Build.sh',
75
78
  ];
76
79
  }
77
- async function accessFirstMatchingMarker(root, markers) {
80
+ async function accessFirstMatchingMarker(root, markers, targetPlatform, hostPlatform) {
81
+ const pathModule = getPathModule(targetPlatform);
82
+ const normalizedRoot = targetPlatform === 'win32' ? toWindowsStylePath(root) : root;
78
83
  for (const marker of markers) {
79
84
  try {
80
- await access(resolve(root, marker), fsConstants.F_OK);
85
+ const candidate = pathModule.resolve(normalizedRoot, marker);
86
+ await access(toHostFilesystemPath(candidate, targetPlatform, hostPlatform), fsConstants.F_OK);
81
87
  return true;
82
88
  }
83
89
  catch {
@@ -86,24 +92,24 @@ async function accessFirstMatchingMarker(root, markers) {
86
92
  }
87
93
  return false;
88
94
  }
89
- async function probeEngineRootHeuristic(platform) {
90
- if (cachedHeuristicEngineRoots.has(platform)) {
91
- return cachedHeuristicEngineRoots.get(platform) || undefined;
95
+ async function probeEngineRootHeuristic(targetPlatform, hostPlatform) {
96
+ const cacheKey = `${hostPlatform}:${targetPlatform}`;
97
+ if (cachedHeuristicEngineRoots.has(cacheKey)) {
98
+ return cachedHeuristicEngineRoots.get(cacheKey) || undefined;
92
99
  }
93
- for (const candidate of getHeuristicEngineCandidates(platform)) {
94
- if (await accessFirstMatchingMarker(candidate, getEngineMarkers(platform))) {
95
- cachedHeuristicEngineRoots.set(platform, candidate);
100
+ for (const candidate of getHeuristicEngineCandidates(targetPlatform)) {
101
+ if (await accessFirstMatchingMarker(candidate, getEngineMarkers(targetPlatform), targetPlatform, hostPlatform)) {
102
+ cachedHeuristicEngineRoots.set(cacheKey, candidate);
96
103
  return candidate;
97
104
  }
98
105
  }
99
- cachedHeuristicEngineRoots.set(platform, '');
106
+ cachedHeuristicEngineRoots.set(cacheKey, '');
100
107
  return undefined;
101
108
  }
102
- async function probePreferredEngineRoot(candidates, platform) {
103
- const markers = getEngineMarkers(platform);
109
+ async function probePreferredEngineRoot(candidates, hostPlatform) {
104
110
  for (const candidate of candidates) {
105
- if (await accessFirstMatchingMarker(candidate, markers)) {
106
- return candidate;
111
+ if (await accessFirstMatchingMarker(candidate.path, getEngineMarkers(candidate.platform), candidate.platform, hostPlatform)) {
112
+ return candidate.path;
107
113
  }
108
114
  }
109
115
  return undefined;
@@ -133,7 +139,16 @@ export async function resolveProjectInputs(request, deps) {
133
139
  const projectPath = firstDefinedString(request.project_path, projectPathFromContext, projectPathFromWorkspace, projectPathFromEnv);
134
140
  const target = firstDefinedString(request.target, targetFromContext, targetFromWorkspace, targetFromEnv);
135
141
  const engineAssociation = projectPath ? await readProjectEngineAssociation(projectPath) : undefined;
136
- const associationCandidates = buildEngineAssociationCandidates(engineAssociation, platform);
142
+ const windowsWorkspaceHint = [request.engine_root, request.project_path, projectPathFromWorkspace, projectPathFromEnv]
143
+ .filter((value) => typeof value === 'string' && value.length > 0)
144
+ .some((value) => isWindowsStylePath(value) || isWslMountedWindowsPath(value));
145
+ const heuristicPlatforms = windowsWorkspaceHint && platform !== 'win32'
146
+ ? ['win32', platform]
147
+ : [platform];
148
+ const associationCandidates = heuristicPlatforms.flatMap((candidatePlatform) => (buildEngineAssociationCandidates(engineAssociation, candidatePlatform).map((candidate) => ({
149
+ path: candidate,
150
+ platform: candidatePlatform,
151
+ }))));
137
152
  let engineRoot = firstDefinedString(request.engine_root, engineRootFromContext, engineRootFromEnv);
138
153
  let engineRootSource;
139
154
  if (request.engine_root) {
@@ -147,7 +162,15 @@ export async function resolveProjectInputs(request, deps) {
147
162
  }
148
163
  else {
149
164
  const preferredCandidate = await probePreferredEngineRoot(associationCandidates, platform);
150
- const heuristicRoot = preferredCandidate ?? await probeEngineRootHeuristic(platform);
165
+ let heuristicRoot = preferredCandidate;
166
+ if (!heuristicRoot) {
167
+ for (const candidatePlatform of heuristicPlatforms) {
168
+ heuristicRoot = await probeEngineRootHeuristic(candidatePlatform, platform);
169
+ if (heuristicRoot) {
170
+ break;
171
+ }
172
+ }
173
+ }
151
174
  if (heuristicRoot) {
152
175
  engineRoot = heuristicRoot;
153
176
  engineRootSource = 'filesystem_heuristic';
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -102,22 +102,6 @@ export function summarizeOutputSchema(schema) {
102
102
  }
103
103
  export function collectToolExampleFamilies(exampleCatalog, toolName) {
104
104
  const equivalentToolNames = new Set([toolName]);
105
- if (toolName === 'modify_widget_blueprint') {
106
- [
107
- 'patch_widget',
108
- 'patch_widget_class_defaults',
109
- 'insert_widget_child',
110
- 'remove_widget',
111
- 'move_widget',
112
- 'wrap_widget',
113
- 'replace_widget_class',
114
- 'replace_widget_tree',
115
- 'batch_widget_operations',
116
- ].forEach((name) => equivalentToolNames.add(name));
117
- }
118
- if (toolName === 'compile_widget_blueprint') {
119
- equivalentToolNames.add('compile_widget');
120
- }
121
105
  return Object.entries(exampleCatalog)
122
106
  .flatMap(([family, entry]) => {
123
107
  const exampleTitles = entry.examples
@@ -143,7 +127,6 @@ export function collectRelatedResources(toolName) {
143
127
  if (toolName.startsWith('create_')
144
128
  || toolName.startsWith('modify_')
145
129
  || toolName.startsWith('apply_')
146
- || toolName === 'build_widget_tree'
147
130
  || toolName === 'save_assets') {
148
131
  resources.add('blueprint://write-capabilities');
149
132
  resources.add('blueprint://authoring-conventions');
@@ -175,7 +158,10 @@ export function collectRelatedResources(toolName) {
175
158
  || toolName === 'sync_project_code'
176
159
  || toolName === 'start_pie'
177
160
  || toolName === 'stop_pie'
178
- || toolName === 'relaunch_pie') {
161
+ || toolName === 'relaunch_pie'
162
+ || toolName === 'read_output_log'
163
+ || toolName === 'list_message_log_listings'
164
+ || toolName === 'read_message_log') {
179
165
  resources.add('blueprint://project-automation');
180
166
  }
181
167
  if (toolName === 'review_blueprint' || toolName === 'audit_project_assets') {
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -3,6 +3,10 @@ export type WorkspaceProjectResolution = {
3
3
  ambiguous: boolean;
4
4
  searchedFrom: string;
5
5
  };
6
+ export declare function isWindowsStylePath(input: string): boolean;
7
+ export declare function isWslMountedWindowsPath(input: string): boolean;
8
+ export declare function toWindowsStylePath(input: string): string;
9
+ export declare function toHostFilesystemPath(input: string, targetPlatform: NodeJS.Platform, hostPlatform?: NodeJS.Platform): string;
6
10
  export declare function normalizeFilesystemPath(input: string | undefined): string | undefined;
7
11
  export declare function filesystemPathsEqual(left: string | undefined, right: string | undefined): boolean;
8
12
  export declare function findNearestWorkspaceProject(startDir?: string): Promise<WorkspaceProjectResolution>;