unity-open-mcp 0.9.0 → 1.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/asmdef-discovery.d.ts +35 -0
- package/dist/asmdef-discovery.js +171 -0
- package/dist/asmdef-discovery.js.map +1 -0
- package/dist/batch-spawn.d.ts +1 -0
- package/dist/batch-spawn.js +78 -1
- package/dist/batch-spawn.js.map +1 -1
- package/dist/capabilities/intent-groups.js +42 -0
- package/dist/capabilities/intent-groups.js.map +1 -1
- package/dist/capabilities/rule-catalog.js +7 -1
- package/dist/capabilities/rule-catalog.js.map +1 -1
- package/dist/capabilities/tool-groups.js +37 -2
- package/dist/capabilities/tool-groups.js.map +1 -1
- package/dist/constants.d.ts +21 -1
- package/dist/constants.js +21 -1
- package/dist/constants.js.map +1 -1
- package/dist/event-stream.d.ts +13 -3
- package/dist/event-stream.js +77 -12
- package/dist/event-stream.js.map +1 -1
- package/dist/live-client.d.ts +17 -0
- package/dist/live-client.js +122 -5
- package/dist/live-client.js.map +1 -1
- package/dist/offline/api.js +82 -30
- package/dist/offline/api.js.map +1 -1
- package/dist/offline/index-builders.d.ts +9 -0
- package/dist/offline/index-builders.js +58 -8
- package/dist/offline/index-builders.js.map +1 -1
- package/dist/offline/parse.js +5 -1
- package/dist/offline/parse.js.map +1 -1
- package/dist/process-diagnostics.d.ts +100 -19
- package/dist/process-diagnostics.js +167 -59
- package/dist/process-diagnostics.js.map +1 -1
- package/dist/project-settings.d.ts +36 -0
- package/dist/project-settings.js +96 -0
- package/dist/project-settings.js.map +1 -0
- package/dist/running-unity.d.ts +23 -0
- package/dist/running-unity.js +60 -0
- package/dist/running-unity.js.map +1 -1
- package/dist/stale-assembly-cache.d.ts +40 -0
- package/dist/stale-assembly-cache.js +76 -0
- package/dist/stale-assembly-cache.js.map +1 -0
- package/dist/tool-router.d.ts +39 -1
- package/dist/tool-router.js +397 -62
- package/dist/tool-router.js.map +1 -1
- package/dist/tools/capture-inline.js +4 -3
- package/dist/tools/capture-inline.js.map +1 -1
- package/dist/tools/editor-status.js +7 -2
- package/dist/tools/editor-status.js.map +1 -1
- package/dist/tools/execute-csharp.js +25 -2
- package/dist/tools/execute-csharp.js.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +34 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/inputsim-key.d.ts +40 -0
- package/dist/tools/inputsim-key.js +72 -0
- package/dist/tools/inputsim-key.js.map +1 -0
- package/dist/tools/inputsim-pointer.d.ts +40 -0
- package/dist/tools/inputsim-pointer.js +121 -0
- package/dist/tools/inputsim-pointer.js.map +1 -0
- package/dist/tools/inputsim-pointer3d.d.ts +40 -0
- package/dist/tools/inputsim-pointer3d.js +55 -0
- package/dist/tools/inputsim-pointer3d.js.map +1 -0
- package/dist/tools/inputsim-probe.d.ts +40 -0
- package/dist/tools/inputsim-probe.js +43 -0
- package/dist/tools/inputsim-probe.js.map +1 -0
- package/dist/tools/inputsim-step.d.ts +40 -0
- package/dist/tools/inputsim-step.js +50 -0
- package/dist/tools/inputsim-step.js.map +1 -0
- package/dist/tools/inputsim-touch.d.ts +40 -0
- package/dist/tools/inputsim-touch.js +83 -0
- package/dist/tools/inputsim-touch.js.map +1 -0
- package/dist/tools/memory-snapshot-capture.js +11 -5
- package/dist/tools/memory-snapshot-capture.js.map +1 -1
- package/dist/tools/pull-events.js +18 -10
- package/dist/tools/pull-events.js.map +1 -1
- package/dist/tools/read-compile-errors.js +10 -2
- package/dist/tools/read-compile-errors.js.map +1 -1
- package/dist/tools/resource-pressure.js +21 -10
- package/dist/tools/resource-pressure.js.map +1 -1
- package/dist/tools/screenshot-window.js +18 -12
- package/dist/tools/screenshot-window.js.map +1 -1
- package/dist/tools/screenshot.js +13 -6
- package/dist/tools/screenshot.js.map +1 -1
- package/dist/tools/visual-compare.d.ts +40 -0
- package/dist/tools/visual-compare.js +98 -0
- package/dist/tools/visual-compare.js.map +1 -0
- package/dist/unity-log.d.ts +51 -2
- package/dist/unity-log.js +152 -5
- package/dist/unity-log.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Input simulation — Input System touch / swipe device events.
|
|
2
|
+
//
|
|
3
|
+
// Compile-gated on com.unity.inputsystem (UNITY_OPEN_MCP_EXT_INPUTSIM_IS).
|
|
4
|
+
// Queues Touchscreen state events through the new Input System.
|
|
5
|
+
//
|
|
6
|
+
// K2 fix: `swipe` accepts `advance_frames` to advance a frame AFTER each Moved
|
|
7
|
+
// phase, so the swipe genuinely unfolds across frames for polling code (per-frame
|
|
8
|
+
// primaryTouch.delta, distance/velocity gesture recognizers). Without
|
|
9
|
+
// `advance_frames`, all Moved phases collapse into a single InputSystem.Update —
|
|
10
|
+
// documented honestly now (previously mis-advertised as "across real frames").
|
|
11
|
+
//
|
|
12
|
+
// Play-mode only. Gate-free. Requires com.unity.inputsystem.
|
|
13
|
+
import { makeTool } from "./schema-fragments.js";
|
|
14
|
+
export const inputsimTouch = makeTool("unity_open_mcp_inputsim_touch", "Queue a touch / swipe event sequence through the Input System " +
|
|
15
|
+
"(Touchscreen.current) during play mode. `tap` = press+release at a point; " +
|
|
16
|
+
"`swipe` = press at from_, move across `steps` interpolated points, release " +
|
|
17
|
+
"at to_; `press`/`release` = single-phase control. POLLING vs CALLBACK: " +
|
|
18
|
+
"without `advance_frames`, all touch phases process in a single " +
|
|
19
|
+
"InputSystem.Update — so polling code (per-frame primaryTouch.delta, gesture " +
|
|
20
|
+
"recognizers) sees a collapsed jump, not a real swipe. Pass `advance_frames` " +
|
|
21
|
+
"≥ 1 to advance a frame after each Moved phase so the swipe unfolds across " +
|
|
22
|
+
"real frames for polling code. Callback-driven InputAction.performed fires " +
|
|
23
|
+
"either way. Endpoints resolve target-first (object_id/name/path → screen " +
|
|
24
|
+
"point) or accept screen_x/screen_y directly. NOTE: target resolution here " +
|
|
25
|
+
"uses a plain GameObject.Find name/path match (no ambiguity detection or " +
|
|
26
|
+
"partial-path matching — that lives in the uGUI-gated inputsim_pointer, and " +
|
|
27
|
+
"this tool compiles against the Input System package only); prefer an " +
|
|
28
|
+
"object_id or a full unique path for the target. Play-mode only — refuses " +
|
|
29
|
+
"with `play_mode_required` otherwise. Gate-free. Requires com.unity.inputsystem.", {
|
|
30
|
+
required: ["action"],
|
|
31
|
+
properties: {
|
|
32
|
+
action: {
|
|
33
|
+
type: "string",
|
|
34
|
+
enum: ["tap", "swipe", "press", "release"],
|
|
35
|
+
description: "tap = press+release at one point; swipe = press at from_, move across " +
|
|
36
|
+
"`steps` interpolated points, release at to_; press = touch down only; " +
|
|
37
|
+
"release = touch up only.",
|
|
38
|
+
},
|
|
39
|
+
finger: {
|
|
40
|
+
type: "integer",
|
|
41
|
+
default: 0,
|
|
42
|
+
minimum: 0,
|
|
43
|
+
maximum: 9,
|
|
44
|
+
description: "Touch finger index (0–9) for multi-touch. Default 0.",
|
|
45
|
+
},
|
|
46
|
+
target: {
|
|
47
|
+
type: "string",
|
|
48
|
+
description: "GameObject to tap/press/release — name or hierarchy path. Resolved to a " +
|
|
49
|
+
"screen point via the active camera. Omit when using screen_x/screen_y.",
|
|
50
|
+
},
|
|
51
|
+
screen_x: { type: "number", description: "Screen X (pixels) for tap/press/release. Pair with screen_y." },
|
|
52
|
+
screen_y: { type: "number", description: "Screen Y (pixels) for tap/press/release. Pair with screen_x." },
|
|
53
|
+
from_target: {
|
|
54
|
+
type: "string",
|
|
55
|
+
description: "Swipe start — target name/path (alternative to from_x/from_y).",
|
|
56
|
+
},
|
|
57
|
+
from_x: { type: "number", description: "Swipe start — screen X (alternative to from_target)." },
|
|
58
|
+
from_y: { type: "number", description: "Swipe start — screen Y (alternative to from_target)." },
|
|
59
|
+
to_target: { type: "string", description: "Swipe end — target name/path (alternative to to_x/to_y)." },
|
|
60
|
+
to_x: { type: "number", description: "Swipe end — screen X (alternative to to_target)." },
|
|
61
|
+
to_y: { type: "number", description: "Swipe end — screen Y (alternative to to_target)." },
|
|
62
|
+
duration_ms: { type: "integer", default: 200, description: "Swipe total duration in milliseconds (recorded). Default 200." },
|
|
63
|
+
steps: {
|
|
64
|
+
type: "integer",
|
|
65
|
+
default: 10,
|
|
66
|
+
minimum: 1,
|
|
67
|
+
maximum: 100,
|
|
68
|
+
description: "Number of interpolated move events in a swipe. Capped at 100 to bound " +
|
|
69
|
+
"main-thread cost (each step can run advance_frames × Step). Default 10.",
|
|
70
|
+
},
|
|
71
|
+
advance_frames: {
|
|
72
|
+
type: "integer",
|
|
73
|
+
default: 0,
|
|
74
|
+
minimum: 0,
|
|
75
|
+
maximum: 60,
|
|
76
|
+
description: "Pump this many player-loop frames (EditorApplication.Step) AFTER each " +
|
|
77
|
+
"Moved phase so the swipe unfolds across real frames for polling code " +
|
|
78
|
+
"(per-frame delta, gesture recognizers). 0 (default) collapses all phases " +
|
|
79
|
+
"into one update — only callback-driven input sees it then. Cap 60.",
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
//# sourceMappingURL=inputsim-touch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inputsim-touch.js","sourceRoot":"","sources":["../../src/tools/inputsim-touch.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,EAAE;AACF,2EAA2E;AAC3E,gEAAgE;AAChE,EAAE;AACF,+EAA+E;AAC/E,kFAAkF;AAClF,sEAAsE;AACtE,iFAAiF;AACjF,+EAA+E;AAC/E,EAAE;AACF,6DAA6D;AAC7D,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CACnC,+BAA+B,EAC/B,gEAAgE;IAC9D,4EAA4E;IAC5E,6EAA6E;IAC7E,yEAAyE;IACzE,iEAAiE;IACjE,8EAA8E;IAC9E,8EAA8E;IAC9E,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,4EAA4E;IAC5E,0EAA0E;IAC1E,6EAA6E;IAC7E,uEAAuE;IACvE,2EAA2E;IAC3E,iFAAiF,EACnF;IACE,QAAQ,EAAE,CAAC,QAAQ,CAAC;IACpB,UAAU,EAAE;QACV,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,SAAS,CAAC;YAC1C,WAAW,EACT,wEAAwE;gBACxE,wEAAwE;gBACxE,0BAA0B;SAC7B;QACD,MAAM,EAAE;YACN,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;YACV,WAAW,EAAE,sDAAsD;SACpE;QACD,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,0EAA0E;gBAC1E,wEAAwE;SAC3E;QACD,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8DAA8D,EAAE;QACzG,QAAQ,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,8DAA8D,EAAE;QACzG,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EAAE,gEAAgE;SAC9E;QACD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sDAAsD,EAAE;QAC/F,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,sDAAsD,EAAE;QAC/F,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,0DAA0D,EAAE;QACtG,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kDAAkD,EAAE;QACzF,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kDAAkD,EAAE;QACzF,WAAW,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,WAAW,EAAE,+DAA+D,EAAE;QAC5H,KAAK,EAAE;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,GAAG;YACZ,WAAW,EACT,wEAAwE;gBACxE,yEAAyE;SAC5E;QACD,cAAc,EAAE;YACd,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,EAAE;YACX,WAAW,EACT,wEAAwE;gBACxE,uEAAuE;gBACvE,2EAA2E;gBAC3E,oEAAoE;SACvE;KACF;CACF,CACF,CAAC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { BRIDGE_HOST_SAFE_TIMEOUT_CAP_MS } from "../constants.js";
|
|
1
2
|
import { makeTool } from "./schema-fragments.js";
|
|
2
3
|
// M20 Plan 7 / T20.7.3 — Memory Profiler snapshot capture. Compile-gated in
|
|
3
4
|
// the bridge (UNITY_OPEN_MCP_EXT_MEMORYPROFILER on com.unity.memoryprofiler) +
|
|
@@ -44,12 +45,17 @@ export const memorySnapshotCapture = makeTool("unity_senses_memory_snapshot_capt
|
|
|
44
45
|
timeout_ms: {
|
|
45
46
|
type: "integer",
|
|
46
47
|
description: "Maximum milliseconds to wait for the callback-based capture to " +
|
|
47
|
-
"finish (default
|
|
48
|
-
"the snapshot file is written; if it times out
|
|
49
|
-
"memoryprofiler_capture_timeout."
|
|
50
|
-
|
|
48
|
+
"finish (default + maximum = the transport cap, ~55000 ms). The " +
|
|
49
|
+
"capture blocks until the snapshot file is written; if it times out " +
|
|
50
|
+
"the tool returns memoryprofiler_capture_timeout. The ceiling is the " +
|
|
51
|
+
"bridge transport cap (BRIDGE_HOST_SAFE_TIMEOUT_CAP_MS): a single " +
|
|
52
|
+
"blocking tool call cannot run longer than a typical MCP host " +
|
|
53
|
+
"request timeout, so a snapshot that needs more than ~55s cannot " +
|
|
54
|
+
"complete in one call — run it manually from the Memory Profiler " +
|
|
55
|
+
"window (Window > Analysis > Memory Profiler) for very large heaps.",
|
|
56
|
+
default: BRIDGE_HOST_SAFE_TIMEOUT_CAP_MS,
|
|
51
57
|
minimum: 1000,
|
|
52
|
-
maximum:
|
|
58
|
+
maximum: BRIDGE_HOST_SAFE_TIMEOUT_CAP_MS,
|
|
53
59
|
},
|
|
54
60
|
},
|
|
55
61
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-snapshot-capture.js","sourceRoot":"","sources":["../../src/tools/memory-snapshot-capture.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,4EAA4E;AAC5E,+EAA+E;AAC/E,8EAA8E;AAC9E,yEAAyE;AACzE,wEAAwE;AACxE,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;AAChF,gFAAgF;AAChF,kFAAkF;AAClF,+EAA+E;AAC/E,6EAA6E;AAC7E,6DAA6D;AAC7D,EAAE;AACF,6EAA6E;AAC7E,qDAAqD;AACrD,MAAM,CAAC,MAAM,qBAAqB,GAAG,QAAQ,CAC3C,sCAAsC,EACtC,+DAA+D;IAC7D,yEAAyE;IACzE,2EAA2E;IAC3E,0EAA0E;IAC1E,sEAAsE;IACtE,2EAA2E;IAC3E,wEAAwE;IACxE,0EAA0E;IAC1E,iEAAiE;IACjE,wDAAwD;IACxD,6EAA6E;IAC7E,8EAA8E;IAC9E,yEAAyE;IACzE,sEAAsE;IACtE,uEAAuE;IACvE,YAAY,EACd;IACE,UAAU,EAAE;QACN,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,uEAAuE;gBACvE,sEAAsE;gBACtE,mEAAmE;gBACnE,oEAAoE;gBACpE,oEAAoE;gBACpE,gDAAgD;SACnD;QACD,UAAU,EAAE;YACV,IAAI,EAAE,SAAS;YACf,WAAW,EACT,iEAAiE;gBACjE,sEAAsE;gBACtE,
|
|
1
|
+
{"version":3,"file":"memory-snapshot-capture.js","sourceRoot":"","sources":["../../src/tools/memory-snapshot-capture.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,+BAA+B,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,4EAA4E;AAC5E,+EAA+E;AAC/E,8EAA8E;AAC9E,yEAAyE;AACzE,wEAAwE;AACxE,EAAE;AACF,2EAA2E;AAC3E,gFAAgF;AAChF,gFAAgF;AAChF,kFAAkF;AAClF,+EAA+E;AAC/E,6EAA6E;AAC7E,6DAA6D;AAC7D,EAAE;AACF,6EAA6E;AAC7E,qDAAqD;AACrD,MAAM,CAAC,MAAM,qBAAqB,GAAG,QAAQ,CAC3C,sCAAsC,EACtC,+DAA+D;IAC7D,yEAAyE;IACzE,2EAA2E;IAC3E,0EAA0E;IAC1E,sEAAsE;IACtE,2EAA2E;IAC3E,wEAAwE;IACxE,0EAA0E;IAC1E,iEAAiE;IACjE,wDAAwD;IACxD,6EAA6E;IAC7E,8EAA8E;IAC9E,yEAAyE;IACzE,sEAAsE;IACtE,uEAAuE;IACvE,YAAY,EACd;IACE,UAAU,EAAE;QACN,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,uEAAuE;gBACvE,sEAAsE;gBACtE,mEAAmE;gBACnE,oEAAoE;gBACpE,oEAAoE;gBACpE,gDAAgD;SACnD;QACD,UAAU,EAAE;YACV,IAAI,EAAE,SAAS;YACf,WAAW,EACT,iEAAiE;gBACjE,iEAAiE;gBACjE,qEAAqE;gBACrE,sEAAsE;gBACtE,mEAAmE;gBACnE,+DAA+D;gBAC/D,kEAAkE;gBAClE,kEAAkE;gBAClE,oEAAoE;YACtE,OAAO,EAAE,+BAA+B;YACxC,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,+BAA+B;SACzC;KACF;CACN,CACF,CAAC"}
|
|
@@ -12,12 +12,15 @@ import { makeTool } from "./schema-fragments.js";
|
|
|
12
12
|
// keeps the model in the loop and lets an agent decide when to drain (e.g.
|
|
13
13
|
// right after a mutation that may produce logs).
|
|
14
14
|
export const pullEvents = makeTool("unity_senses_pull_events", "Drain incremental bridge events (console logs + editor-state transitions) since the previous call. " +
|
|
15
|
-
"The first call opens a server-side SSE subscription
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
15
|
+
"The first call opens a server-side SSE subscription and returns nothing (an empty events array with " +
|
|
16
|
+
"started:true); console history is NOT replayed. For anything that happened before the first call, " +
|
|
17
|
+
"read the Editor log via unity_open_mcp_read_compile_errors (compile errors) or call this tool BEFORE " +
|
|
18
|
+
"the operation you want to observe, then again after. Later calls return only events that arrived " +
|
|
19
|
+
"since the previous drain. Use this after execute_csharp / mutations to stream console output without " +
|
|
20
|
+
"polling /ping or re-reading the full console. Each event carries `seq`, `ts`, `type` ('log' | " +
|
|
21
|
+
"'editor_state'), and type-specific fields (logType/message/stack for logs, " +
|
|
22
|
+
"state/isCompiling/isPlaying for state). `dropped` reports events evicted from the queue before this " +
|
|
23
|
+
"pull; `connected` reports the SSE reader state. Requires a live Unity Editor connection.", {
|
|
21
24
|
properties: {
|
|
22
25
|
max_events: {
|
|
23
26
|
type: "integer",
|
|
@@ -26,12 +29,17 @@ export const pullEvents = makeTool("unity_senses_pull_events", "Drain incrementa
|
|
|
26
29
|
maximum: 1000,
|
|
27
30
|
description: "Maximum events to return per call. Additional buffered events are counted in `dropped`.",
|
|
28
31
|
},
|
|
29
|
-
//
|
|
30
|
-
//
|
|
31
|
-
//
|
|
32
|
+
// feedback #8 — an explicit subscriber id gives the caller its OWN
|
|
33
|
+
// read cursor over the shared queue: a fresh subscriber's first call
|
|
34
|
+
// returns started:true with NO events (its cursor starts at the current
|
|
35
|
+
// high-water mark, so history is not replayed). A returning subscriber
|
|
36
|
+
// resumes from its saved cursor. Omit to drain the shared queue
|
|
37
|
+
// (legacy behaviour). Use a distinct id per agent session.
|
|
32
38
|
subscriber: {
|
|
33
39
|
type: "string",
|
|
34
|
-
description: "Optional subscriber id
|
|
40
|
+
description: "Optional subscriber id. A NEW id starts a fresh read cursor at the current " +
|
|
41
|
+
"high-water mark (no backlog replay); a returning id resumes from its saved " +
|
|
42
|
+
"cursor. Omit to drain the shared queue.",
|
|
35
43
|
},
|
|
36
44
|
},
|
|
37
45
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull-events.js","sourceRoot":"","sources":["../../src/tools/pull-events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,qCAAqC;AACrC,EAAE;AACF,sEAAsE;AACtE,wEAAwE;AACxE,0EAA0E;AAC1E,yEAAyE;AACzE,0BAA0B;AAC1B,EAAE;AACF,+EAA+E;AAC/E,4EAA4E;AAC5E,2EAA2E;AAC3E,iDAAiD;AACjD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAChC,0BAA0B,EAC1B,qGAAqG;IACnG,
|
|
1
|
+
{"version":3,"file":"pull-events.js","sourceRoot":"","sources":["../../src/tools/pull-events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,qCAAqC;AACrC,EAAE;AACF,sEAAsE;AACtE,wEAAwE;AACxE,0EAA0E;AAC1E,yEAAyE;AACzE,0BAA0B;AAC1B,EAAE;AACF,+EAA+E;AAC/E,4EAA4E;AAC5E,2EAA2E;AAC3E,iDAAiD;AACjD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAChC,0BAA0B,EAC1B,qGAAqG;IACnG,sGAAsG;IACtG,oGAAoG;IACpG,uGAAuG;IACvG,mGAAmG;IACnG,uGAAuG;IACvG,gGAAgG;IAChG,6EAA6E;IAC7E,sGAAsG;IACtG,0FAA0F,EAC5F;IACE,UAAU,EAAE;QACN,UAAU,EAAE;YACV,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,IAAI;YACb,WAAW,EACT,yFAAyF;SAC5F;QACD,mEAAmE;QACnE,qEAAqE;QACrE,wEAAwE;QACxE,uEAAuE;QACvE,gEAAgE;QAChE,2DAA2D;QAC3D,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,6EAA6E;gBAC7E,6EAA6E;gBAC7E,yCAAyC;SAC5C;KACF;CACN,CACF,CAAC"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { makeTool } from "./schema-fragments.js";
|
|
2
|
+
import { TYPED_EDITOR_ACTIVATE_INSTRUCTION } from "../constants.js";
|
|
2
3
|
// Offline, filesystem-only tool: reads the tail of Unity's Editor.log and
|
|
3
4
|
// extracts BOTH C# compiler errors AND package / assembly-level red flags AND
|
|
4
5
|
// a hard Editor hang signal. The one recovery channel that works when the
|
|
@@ -68,8 +69,15 @@ export const readCompileErrors = makeTool("unity_open_mcp_read_compile_errors",
|
|
|
68
69
|
"source is newer than the newest Library/ScriptAssemblies/*.dll — the " +
|
|
69
70
|
"running assembly predates the latest source, so a no_errors_found signal " +
|
|
70
71
|
"CANNOT be trusted until the assembly is rebuilt. Call " +
|
|
71
|
-
"unity_open_mcp_recompile_scripts (deterministic force-recompile
|
|
72
|
-
|
|
72
|
+
"unity_open_mcp_recompile_scripts (deterministic force-recompile; it is in " +
|
|
73
|
+
`the typed-editor group — ${TYPED_EDITOR_ACTIVATE_INSTRUCTION} first) ` +
|
|
74
|
+
"then re-read compile errors. IMPORTANT — staged compilation: Unity compiles " +
|
|
75
|
+
"assemblies in dependency order, so when `errorCount` is small but the project " +
|
|
76
|
+
"has multiple assemblies (the response carries `partialCompileLikely: true` " +
|
|
77
|
+
"with `asmdefCount`/`assembliesWithErrors`), the reported errors may be a " +
|
|
78
|
+
"SUBSET — the failing assembly aborted the pipeline before dependent ones were " +
|
|
79
|
+
"reached. Do NOT treat `errorCount` as the complete picture; fix the reported " +
|
|
80
|
+
"errors and re-check until `errorCount` is 0.", {
|
|
73
81
|
properties: {
|
|
74
82
|
tail_bytes: {
|
|
75
83
|
type: "integer",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"read-compile-errors.js","sourceRoot":"","sources":["../../src/tools/read-compile-errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"read-compile-errors.js","sourceRoot":"","sources":["../../src/tools/read-compile-errors.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,iCAAiC,EAAE,MAAM,iBAAiB,CAAC;AAEpE,0EAA0E;AAC1E,8EAA8E;AAC9E,0EAA0E;AAC1E,+EAA+E;AAC/E,2EAA2E;AAC3E,0EAA0E;AAC1E,4EAA4E;AAC5E,yEAAyE;AACzE,+EAA+E;AAC/E,8EAA8E;AAC9E,UAAU;AACV,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,2EAA2E;AAC3E,4EAA4E;AAC5E,4EAA4E;AAC5E,2EAA2E;AAC3E,sCAAsC;AACtC,EAAE;AACF,mBAAmB;AACnB,yEAAyE;AACzE,iEAAiE;AACjE,6DAA6D;AAC7D,uEAAuE;AACvE,wEAAwE;AACxE,wEAAwE;AACxE,6EAA6E;AAC7E,iEAAiE;AACjE,sEAAsE;AACtE,8EAA8E;AAC9E,iBAAiB;AACjB,4EAA4E;AAC5E,4EAA4E;AAC5E,8EAA8E;AAC9E,wEAAwE;AACxE,uEAAuE;AACvE,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CACvC,oCAAoC,EACpC,uEAAuE;IACrE,uEAAuE;IACvE,0DAA0D;IAC1D,mEAAmE;IACnE,6DAA6D;IAC7D,+DAA+D;IAC/D,2DAA2D;IAC3D,6DAA6D;IAC7D,4DAA4D;IAC5D,mEAAmE;IACnE,yEAAyE;IACzE,kEAAkE;IAClE,qEAAqE;IACrE,uEAAuE;IACvE,uEAAuE;IACvE,yEAAyE;IACzE,qEAAqE;IACrE,mEAAmE;IACnE,qEAAqE;IACrE,wEAAwE;IACxE,yEAAyE;IACzE,oEAAoE;IACpE,qEAAqE;IACrE,kEAAkE;IAClE,qEAAqE;IACrE,iEAAiE;IACjE,qDAAqD;IACrD,oEAAoE;IACpE,sEAAsE;IACtE,uEAAuE;IACvE,2EAA2E;IAC3E,wDAAwD;IACxD,4EAA4E;IAC5E,4BAA4B,iCAAiC,UAAU;IACvE,8EAA8E;IAC9E,gFAAgF;IAChF,6EAA6E;IAC7E,2EAA2E;IAC3E,gFAAgF;IAChF,+EAA+E;IAC/E,8CAA8C,EAChD;IACE,UAAU,EAAE;QACN,UAAU,EAAE;YACV,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,OAAO;YAChB,WAAW,EACT,6DAA6D;gBAC7D,oEAAoE;gBACpE,kEAAkE;gBAClE,mEAAmE;SACtE;KACF;CACN,CACF,CAAC"}
|
|
@@ -30,16 +30,27 @@ export const resourcePressure = makeTool("unity_open_mcp_resource_pressure", "Sa
|
|
|
30
30
|
"reachable — the bridge is what dies on fd-exhaustion. Resolves the live " +
|
|
31
31
|
"Unity PID via the process scan (same as `bridge_status` cold-Safe-Mode " +
|
|
32
32
|
"detection). Response fields: `fdCount` (null when the probe failed), " +
|
|
33
|
-
"`fdMethod`, `approximate` (Windows handle count), `ceiling` (
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
33
|
+
"`fdMethod`, `approximate` (Windows handle count), `ceiling` (the resolved " +
|
|
34
|
+
"fd ceiling — default 1024, configurable per project), `ceilingSource` " +
|
|
35
|
+
"(`\"default\"` | `\"config\"` — whether `.unity-open-mcp/settings.json` " +
|
|
36
|
+
"`resourcePressure.fdCeiling` overrode the default), `headroom`, " +
|
|
37
|
+
"`pressureRatio`, `state` (`ok` | `warn` at ≥80% | `critical` at ≥90% | " +
|
|
38
|
+
"`over_ceiling` when the count already exceeds the ceiling proxy | " +
|
|
39
|
+
"`unknown` when the probe failed), `trend` (`stable` | `rising` | " +
|
|
40
|
+
"`leaking` — monotonic climb across successive samples = leak in progress; " +
|
|
41
|
+
"absolute count alone is not enough), and `samples[]` (the session-scoped " +
|
|
42
|
+
"in-memory ring of recent samples for this PID — no disk cache). " +
|
|
43
|
+
"IMPORTANT for fd-heavy projects: an asset-heavy Editor legitimately sits " +
|
|
44
|
+
"OVER the ceiling proxy on a fresh healthy process (lsof/HandleCount count " +
|
|
45
|
+
"ALL OS fds — mmap'd assets, file watchers, FileStream handles — while only " +
|
|
46
|
+
"Mono-IOSelector-registered descriptors trip the hang), so `over_ceiling` " +
|
|
47
|
+
"is INFORMATIONAL, not an alarm: when `state` is `over_ceiling` and the " +
|
|
48
|
+
"trend is stable/no-history the response carries a `pressureNote` instead " +
|
|
49
|
+
"of a `warning`, and you should watch the TREND, not the absolute. The " +
|
|
50
|
+
"agent should surface a `warning` (recommend saving scene work + planning a " +
|
|
51
|
+
"restart) when `state` is warn/critical, OR `trend.state` is " +
|
|
52
|
+
"leaking/rising — do NOT call `restart_editor` yet (the Editor is still " +
|
|
53
|
+
"healthy). Use this after heavy automation (many recompiles / domain " +
|
|
43
54
|
"reloads) to catch fd growth across reloads. No disk cache — samples live " +
|
|
44
55
|
"in the session store and are cleared on MCP-server restart.", {
|
|
45
56
|
properties: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource-pressure.js","sourceRoot":"","sources":["../../src/tools/resource-pressure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,2EAA2E;AAC3E,eAAe;AACf,EAAE;AACF,mFAAmF;AACnF,mEAAmE;AACnE,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,oDAAoD;AACpD,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,gFAAgF;AAChF,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,SAAS;AACT,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CACtC,kCAAkC,EAClC,4EAA4E;IAC1E,yEAAyE;IACzE,4EAA4E;IAC5E,4EAA4E;IAC5E,4EAA4E;IAC5E,sEAAsE;IACtE,sEAAsE;IACtE,mEAAmE;IACnE,oEAAoE;IACpE,0EAA0E;IAC1E,yEAAyE;IACzE,uEAAuE;IACvE,4EAA4E;IAC5E,2EAA2E;IAC3E,2EAA2E;IAC3E,
|
|
1
|
+
{"version":3,"file":"resource-pressure.js","sourceRoot":"","sources":["../../src/tools/resource-pressure.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,2EAA2E;AAC3E,eAAe;AACf,EAAE;AACF,mFAAmF;AACnF,mEAAmE;AACnE,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,oDAAoD;AACpD,EAAE;AACF,6EAA6E;AAC7E,6EAA6E;AAC7E,gFAAgF;AAChF,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,8EAA8E;AAC9E,+EAA+E;AAC/E,SAAS;AACT,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CACtC,kCAAkC,EAClC,4EAA4E;IAC1E,yEAAyE;IACzE,4EAA4E;IAC5E,4EAA4E;IAC5E,4EAA4E;IAC5E,sEAAsE;IACtE,sEAAsE;IACtE,mEAAmE;IACnE,oEAAoE;IACpE,0EAA0E;IAC1E,yEAAyE;IACzE,uEAAuE;IACvE,4EAA4E;IAC5E,wEAAwE;IACxE,0EAA0E;IAC1E,kEAAkE;IAClE,yEAAyE;IACzE,oEAAoE;IACpE,mEAAmE;IACnE,4EAA4E;IAC5E,2EAA2E;IAC3E,kEAAkE;IAClE,2EAA2E;IAC3E,4EAA4E;IAC5E,6EAA6E;IAC7E,2EAA2E;IAC3E,yEAAyE;IACzE,2EAA2E;IAC3E,wEAAwE;IACxE,6EAA6E;IAC7E,8DAA8D;IAC9D,yEAAyE;IACzE,sEAAsE;IACtE,2EAA2E;IAC3E,6DAA6D,EAC/D;IACE,UAAU,EAAE;QACN,GAAG,EAAE;YACH,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,CAAC;YACV,WAAW,EACT,+DAA+D;gBAC/D,mEAAmE;gBACnE,mEAAmE;gBACnE,oEAAoE;gBACpE,gBAAgB;SACnB;KACF;CACN,CACF,CAAC"}
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
import { makeTool } from "./schema-fragments.js";
|
|
2
2
|
// M20 Plan 1 / T20.1.2 — Editor window screenshot. Captures any EditorWindow
|
|
3
3
|
// (Console, Hierarchy, Inspector, Project, Scene, Game, or a custom window).
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
4
|
+
// feedback #6 (2026-08-07): on macOS/Linux the screen-readback path reads from
|
|
5
|
+
// an unbound backbuffer during bridge dispatch and produces a blank frame, so
|
|
6
|
+
// the tool now returns a structured `not_supported` error there (use the OS
|
|
7
|
+
// screen-capture tool, or screenshot {view:"composed"} for the rendered Game
|
|
8
|
+
// view). On Windows a screen-rect readback is used and a post-capture
|
|
9
|
+
// solid-color check rejects blank frames with a `blank_capture` error instead
|
|
10
|
+
// of reporting status:ok. `resolution` reports the actual capture size.
|
|
8
11
|
export const screenshotWindow = makeTool("unity_senses_screenshot_window", "Capture a Unity Editor window (Console, Hierarchy, Inspector, Project, " +
|
|
9
|
-
"Scene, Game, or any custom EditorWindow) to a PNG file.
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"(
|
|
16
|
-
"the
|
|
12
|
+
"Scene, Game, or any custom EditorWindow) to a PNG file. Windows-only: on " +
|
|
13
|
+
"macOS/Linux returns a `not_supported` error (the editor-window backbuffer " +
|
|
14
|
+
"is not bound during bridge dispatch, so a blank frame would result — use " +
|
|
15
|
+
"the OS screen-capture tool, or screenshot {view:\"composed\"} for the " +
|
|
16
|
+
"rendered Game view). On Windows a screen-rect readback is used; a blank/" +
|
|
17
|
+
"solid-color frame is rejected with a `blank_capture` error. `resolution` " +
|
|
18
|
+
"reports the ACTUAL capture size (clamped to the window's on-screen rect), " +
|
|
19
|
+
"not the requested maximum. Provide either window_title (visible tab text, " +
|
|
20
|
+
"e.g. \"Console\") or window_type (EditorWindow type name, e.g. " +
|
|
21
|
+
"\"UnityEditor.ConsoleWindow\"). Returns the saved PNG file path. Requires " +
|
|
22
|
+
"a live Unity Editor connection.", {
|
|
17
23
|
properties: {
|
|
18
24
|
window_title: {
|
|
19
25
|
type: "string",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshot-window.js","sourceRoot":"","sources":["../../src/tools/screenshot-window.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,6EAA6E;AAC7E,6EAA6E;AAC7E,
|
|
1
|
+
{"version":3,"file":"screenshot-window.js","sourceRoot":"","sources":["../../src/tools/screenshot-window.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAC/E,8EAA8E;AAC9E,4EAA4E;AAC5E,6EAA6E;AAC7E,sEAAsE;AACtE,8EAA8E;AAC9E,wEAAwE;AACxE,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CACtC,gCAAgC,EAChC,yEAAyE;IACvE,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,wEAAwE;IACxE,0EAA0E;IAC1E,2EAA2E;IAC3E,4EAA4E;IAC5E,4EAA4E;IAC5E,iEAAiE;IACjE,4EAA4E;IAC5E,iCAAiC,EACnC;IACE,UAAU,EAAE;QACN,YAAY,EAAE;YACZ,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,4DAA4D;gBAC5D,mEAAmE;gBACnE,iEAAiE;gBACjE,+CAA+C;SAClD;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,0DAA0D;gBAC1D,6DAA6D;gBAC7D,mDAAmD;SACtD;QACD,KAAK,EAAE;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,oEAAoE;gBACpE,+BAA+B;SAClC;QACD,MAAM,EAAE;YACN,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,qEAAqE;gBACrE,gCAAgC;SACnC;KACF;CACN,CACF,CAAC"}
|
package/dist/tools/screenshot.js
CHANGED
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { makeTool } from "./schema-fragments.js";
|
|
2
|
-
export const screenshot = makeTool("unity_senses_screenshot", "Capture a screenshot from the Unity Editor. Supports
|
|
3
|
-
"'scene' (the Scene view), 'game' (
|
|
2
|
+
export const screenshot = makeTool("unity_senses_screenshot", "Capture a screenshot from the Unity Editor. Supports four views: " +
|
|
3
|
+
"'scene' (the Scene view), 'game' (renders Camera.main only — NOT the full " +
|
|
4
|
+
"Game view; Screen-Space Overlay UI and multi-camera compositions are NOT " +
|
|
5
|
+
"included), 'composed' (the player's full composite frame — every camera by " +
|
|
6
|
+
"depth plus Screen-Space Overlay canvases; use this to verify UI edits), and " +
|
|
4
7
|
"'isolated' (a clean 2x2 composite — Front/Right/Back/Top — of a single " +
|
|
5
8
|
"GameObject with layer culling and background choice). " +
|
|
6
9
|
"Returns the saved PNG file path. Requires a live Unity Editor connection.", {
|
|
7
10
|
properties: {
|
|
8
11
|
view: {
|
|
9
12
|
type: "string",
|
|
10
|
-
enum: ["scene", "game", "isolated"],
|
|
13
|
+
enum: ["scene", "game", "composed", "isolated"],
|
|
11
14
|
default: "scene",
|
|
12
|
-
description: "Capture target. 'scene' = Scene view camera, 'game' = main
|
|
13
|
-
"
|
|
15
|
+
description: "Capture target. 'scene' = Scene view camera, 'game' = Camera.main only " +
|
|
16
|
+
"(Overlay canvases and other cameras are NOT rendered — prefer 'composed' " +
|
|
17
|
+
"to verify UI), 'composed' = the player's full frame (all cameras by depth + " +
|
|
18
|
+
"Screen-Space Overlay UI; in play mode uses ScreenCapture, in edit mode " +
|
|
19
|
+
"composites enabled cameras by depth), 'isolated' = clean 2x2 composite of " +
|
|
20
|
+
"one GameObject.",
|
|
14
21
|
},
|
|
15
22
|
width: {
|
|
16
23
|
type: "integer",
|
|
@@ -35,7 +42,7 @@ export const screenshot = makeTool("unity_senses_screenshot", "Capture a screens
|
|
|
35
42
|
type: "string",
|
|
36
43
|
enum: ["transparent", "solid", "skybox"],
|
|
37
44
|
default: "skybox",
|
|
38
|
-
description: "Background for 'isolated' view. Ignored for scene/game.",
|
|
45
|
+
description: "Background for 'isolated' view. Ignored for scene/game/composed.",
|
|
39
46
|
},
|
|
40
47
|
},
|
|
41
48
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/tools/screenshot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAChC,yBAAyB,EACzB,
|
|
1
|
+
{"version":3,"file":"screenshot.js","sourceRoot":"","sources":["../../src/tools/screenshot.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAChC,yBAAyB,EACzB,mEAAmE;IACjE,4EAA4E;IAC5E,2EAA2E;IAC3E,6EAA6E;IAC7E,8EAA8E;IAC9E,yEAAyE;IACzE,wDAAwD;IACxD,2EAA2E,EAC7E;IACE,UAAU,EAAE;QACN,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC;YAC/C,OAAO,EAAE,OAAO;YAChB,WAAW,EACT,yEAAyE;gBACzE,2EAA2E;gBAC3E,8EAA8E;gBAC9E,yEAAyE;gBACzE,4EAA4E;gBAC5E,iBAAiB;SACpB;QACD,KAAK,EAAE;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,mFAAmF;SACtF;QACD,MAAM,EAAE;YACN,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,oFAAoF;SACvF;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,wEAAwE;gBACxE,0CAA0C;SAC7C;QACD,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,QAAQ,CAAC;YACxC,OAAO,EAAE,QAAQ;YACjB,WAAW,EAAE,kEAAkE;SAChF;KACF;CACN,CACF,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare const visualCompare: {
|
|
2
|
+
inputSchema: {
|
|
3
|
+
[x: string]: unknown;
|
|
4
|
+
type: "object";
|
|
5
|
+
properties?: {
|
|
6
|
+
[x: string]: object;
|
|
7
|
+
} | undefined;
|
|
8
|
+
required?: string[] | undefined;
|
|
9
|
+
};
|
|
10
|
+
name: string;
|
|
11
|
+
description?: string | undefined;
|
|
12
|
+
outputSchema?: {
|
|
13
|
+
[x: string]: unknown;
|
|
14
|
+
type: "object";
|
|
15
|
+
properties?: {
|
|
16
|
+
[x: string]: object;
|
|
17
|
+
} | undefined;
|
|
18
|
+
required?: string[] | undefined;
|
|
19
|
+
} | undefined;
|
|
20
|
+
annotations?: {
|
|
21
|
+
title?: string | undefined;
|
|
22
|
+
readOnlyHint?: boolean | undefined;
|
|
23
|
+
destructiveHint?: boolean | undefined;
|
|
24
|
+
idempotentHint?: boolean | undefined;
|
|
25
|
+
openWorldHint?: boolean | undefined;
|
|
26
|
+
} | undefined;
|
|
27
|
+
execution?: {
|
|
28
|
+
taskSupport?: "optional" | "required" | "forbidden" | undefined;
|
|
29
|
+
} | undefined;
|
|
30
|
+
_meta?: {
|
|
31
|
+
[x: string]: unknown;
|
|
32
|
+
} | undefined;
|
|
33
|
+
icons?: {
|
|
34
|
+
src: string;
|
|
35
|
+
mimeType?: string | undefined;
|
|
36
|
+
sizes?: string[] | undefined;
|
|
37
|
+
theme?: "light" | "dark" | undefined;
|
|
38
|
+
}[] | undefined;
|
|
39
|
+
title?: string | undefined;
|
|
40
|
+
};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { makeTool } from "./schema-fragments.js";
|
|
2
|
+
// Visual regression compare — the one transferable idea worth taking from
|
|
3
|
+
// unity-biome-mcp's "visual baseline/diff" feature. Capture a named reference
|
|
4
|
+
// snapshot from a view (scene / game / isolated), then compare later captures
|
|
5
|
+
// against it. The bridge returns pixelDiffPercent / mismatchedPixels /
|
|
6
|
+
// perceptualDistance (8x8 aHash Hamming distance) / match, plus an inline diff
|
|
7
|
+
// image (mismatched pixels in red over the current frame) when the diff is
|
|
8
|
+
// non-zero. The diff image is carried as an `inlineImage` field the MCP server
|
|
9
|
+
// unwraps into an MCP image content block (same mechanism as capture_inline).
|
|
10
|
+
//
|
|
11
|
+
// "reference snapshot" / "visual compare" is used instead of "baseline" — that
|
|
12
|
+
// name is already taken by the verify-issue baseline tools (baseline_create,
|
|
13
|
+
// regression_check), which compare compiler-error / project-health snapshots,
|
|
14
|
+
// not images.
|
|
15
|
+
export const visualCompare = makeTool("unity_senses_visual_compare", "Visual regression compare. Capture a named reference snapshot from a view " +
|
|
16
|
+
"(scene / game / isolated), then compare later captures against it to check " +
|
|
17
|
+
"whether an edit visually broke anything. Returns pixelDiffPercent, " +
|
|
18
|
+
"mismatchedPixels, perceptualDistance (8x8 average-hash Hamming distance — " +
|
|
19
|
+
"tolerates minor anti-aliasing drift), and match (true when pixelDiffPercent " +
|
|
20
|
+
"<= sensitivity * 100). On a non-zero diff, returns an inline diff image " +
|
|
21
|
+
"(mismatched pixels highlighted red over the current frame) as an MCP image " +
|
|
22
|
+
"content block. Actions: 'save' (capture + store a named reference), " +
|
|
23
|
+
"'compare' (capture + diff vs the named reference), 'list' (enumerate saved " +
|
|
24
|
+
"references), 'delete' (remove a reference). References persist under " +
|
|
25
|
+
"~/.unity-open-mcp/screenshots/references/. Requires a live Unity Editor " +
|
|
26
|
+
"connection.", {
|
|
27
|
+
properties: {
|
|
28
|
+
action: {
|
|
29
|
+
type: "string",
|
|
30
|
+
enum: ["save", "compare", "list", "delete"],
|
|
31
|
+
description: "save: capture + store a named reference. compare: capture + diff vs " +
|
|
32
|
+
"the named reference. list: enumerate saved references. delete: remove " +
|
|
33
|
+
"a named reference.",
|
|
34
|
+
},
|
|
35
|
+
name: {
|
|
36
|
+
type: "string",
|
|
37
|
+
description: "Reference name (required for save / compare / delete). Flat filename " +
|
|
38
|
+
"only — no path separators or traversal. Stored as " +
|
|
39
|
+
"<name>.png + <name>.meta.json.",
|
|
40
|
+
},
|
|
41
|
+
view: {
|
|
42
|
+
type: "string",
|
|
43
|
+
enum: ["scene", "game", "isolated"],
|
|
44
|
+
default: "game",
|
|
45
|
+
description: "Capture target. 'scene' = Scene view camera, 'game' = main game " +
|
|
46
|
+
"camera (default — visual regression usually targets what the player " +
|
|
47
|
+
"sees), 'isolated' = clean 2x2 composite of one GameObject. Ignored " +
|
|
48
|
+
"for list / delete.",
|
|
49
|
+
},
|
|
50
|
+
width: {
|
|
51
|
+
type: "integer",
|
|
52
|
+
default: 1280,
|
|
53
|
+
minimum: 64,
|
|
54
|
+
maximum: 4096,
|
|
55
|
+
description: "Capture width in pixels. For 'isolated', this is per-quadrant. The " +
|
|
56
|
+
"compare resamples the current capture to the reference dimensions if " +
|
|
57
|
+
"they differ, so the diff is resolution-stable.",
|
|
58
|
+
},
|
|
59
|
+
height: {
|
|
60
|
+
type: "integer",
|
|
61
|
+
default: 720,
|
|
62
|
+
minimum: 64,
|
|
63
|
+
maximum: 4096,
|
|
64
|
+
description: "Capture height in pixels. For 'isolated', this is per-quadrant.",
|
|
65
|
+
},
|
|
66
|
+
object_path: {
|
|
67
|
+
type: "string",
|
|
68
|
+
description: "Required for 'isolated' view. Hierarchy path of the target " +
|
|
69
|
+
"GameObject (e.g. \"Player\" or \"Enemies/Goblin\").",
|
|
70
|
+
},
|
|
71
|
+
background: {
|
|
72
|
+
type: "string",
|
|
73
|
+
enum: ["transparent", "solid", "skybox"],
|
|
74
|
+
default: "skybox",
|
|
75
|
+
description: "Background for 'isolated' view. Ignored for scene/game.",
|
|
76
|
+
},
|
|
77
|
+
sensitivity: {
|
|
78
|
+
type: "number",
|
|
79
|
+
default: 0.01,
|
|
80
|
+
minimum: 0,
|
|
81
|
+
maximum: 1,
|
|
82
|
+
description: "[compare] Match threshold as a fraction of mismatched pixels (0–1). " +
|
|
83
|
+
"match is true when pixelDiffPercent <= sensitivity * 100. Default 0.01 " +
|
|
84
|
+
"= 1% pixel diff. Raise for noisier scenes (dynamic backgrounds, " +
|
|
85
|
+
"particle systems); 0 = require an exact match.",
|
|
86
|
+
},
|
|
87
|
+
include_diff_image: {
|
|
88
|
+
type: "boolean",
|
|
89
|
+
default: true,
|
|
90
|
+
description: "[compare] When true (default) and the diff is non-zero, return the " +
|
|
91
|
+
"diff image (current frame with mismatched pixels set to red) as an " +
|
|
92
|
+
"inline MCP image content block. Set false to skip the image and " +
|
|
93
|
+
"receive metrics only.",
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
required: ["action"],
|
|
97
|
+
});
|
|
98
|
+
//# sourceMappingURL=visual-compare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-compare.js","sourceRoot":"","sources":["../../src/tools/visual-compare.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEjD,0EAA0E;AAC1E,8EAA8E;AAC9E,8EAA8E;AAC9E,uEAAuE;AACvE,+EAA+E;AAC/E,2EAA2E;AAC3E,+EAA+E;AAC/E,8EAA8E;AAC9E,EAAE;AACF,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,cAAc;AACd,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CACnC,6BAA6B,EAC7B,4EAA4E;IAC1E,6EAA6E;IAC7E,qEAAqE;IACrE,4EAA4E;IAC5E,8EAA8E;IAC9E,0EAA0E;IAC1E,6EAA6E;IAC7E,sEAAsE;IACtE,6EAA6E;IAC7E,uEAAuE;IACvE,0EAA0E;IAC1E,aAAa,EACf;IACE,UAAU,EAAE;QACV,MAAM,EAAE;YACN,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC;YAC3C,WAAW,EACT,sEAAsE;gBACtE,wEAAwE;gBACxE,oBAAoB;SACvB;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,uEAAuE;gBACvE,oDAAoD;gBACpD,gCAAgC;SACnC;QACD,IAAI,EAAE;YACJ,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC;YACnC,OAAO,EAAE,MAAM;YACf,WAAW,EACT,kEAAkE;gBAClE,sEAAsE;gBACtE,qEAAqE;gBACrE,oBAAoB;SACvB;QACD,KAAK,EAAE;YACL,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,qEAAqE;gBACrE,uEAAuE;gBACvE,gDAAgD;SACnD;QACD,MAAM,EAAE;YACN,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,EAAE;YACX,OAAO,EAAE,IAAI;YACb,WAAW,EACT,iEAAiE;SACpE;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,WAAW,EACT,6DAA6D;gBAC7D,qDAAqD;SACxD;QACD,UAAU,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,QAAQ,CAAC;YACxC,OAAO,EAAE,QAAQ;YACjB,WAAW,EAAE,yDAAyD;SACvE;QACD,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,CAAC;YACV,OAAO,EAAE,CAAC;YACV,WAAW,EACT,sEAAsE;gBACtE,yEAAyE;gBACzE,kEAAkE;gBAClE,gDAAgD;SACnD;QACD,kBAAkB,EAAE;YAClB,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,IAAI;YACb,WAAW,EACT,qEAAqE;gBACrE,qEAAqE;gBACrE,kEAAkE;gBAClE,uBAAuB;SAC1B;KACF;IACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;CACrB,CACF,CAAC"}
|
package/dist/unity-log.d.ts
CHANGED
|
@@ -43,7 +43,7 @@ export declare function projectEditorPrevLogPath(projectPath: string | null | un
|
|
|
43
43
|
* fell back to Editor-prev.log"). */
|
|
44
44
|
export interface ResolvedEditorLog {
|
|
45
45
|
path: string;
|
|
46
|
-
reason: "project_log" | "global_log" | "prev_log_live_editor" | "prev_log_fallback";
|
|
46
|
+
reason: "project_log" | "global_log" | "global_log_fresher" | "prev_log_live_editor" | "prev_log_fallback";
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
49
|
* Pick the authoritative Editor.log to read for compile-error extraction.
|
|
@@ -70,7 +70,7 @@ export interface ResolvedEditorLog {
|
|
|
70
70
|
* rotation. `livePid` is optional; when absent the prev.log fallback only
|
|
71
71
|
* triggers on a frozen-looking log, which is conservative.
|
|
72
72
|
*/
|
|
73
|
-
export declare function resolveEditorLogPath(projectPath: string | null | undefined, platform?: UnityLogPlatform, livePid?: number): ResolvedEditorLog;
|
|
73
|
+
export declare function resolveEditorLogPath(projectPath: string | null | undefined, platform?: UnityLogPlatform, livePid?: number, globalLogPathOverride?: string): ResolvedEditorLog;
|
|
74
74
|
/** Default tail size. Bounded so a multi-MB log can't blow up the tool
|
|
75
75
|
* response; 256KB is ample for a compile-error burst (Unity writes the
|
|
76
76
|
* diagnostics in a contiguous block near the end of the log). */
|
|
@@ -149,3 +149,52 @@ export interface StaleAssemblyResult {
|
|
|
149
149
|
* Never throws; returns a clean "not stale" on any resolution failure.
|
|
150
150
|
*/
|
|
151
151
|
export declare function detectStaleAssembly(projectRoot: string | null | undefined): StaleAssemblyResult;
|
|
152
|
+
export interface LogAuthorship {
|
|
153
|
+
/** Unity version parsed from the log header's "Unity Editor version:" line,
|
|
154
|
+
* e.g. "6000.5.5f1". null when the header was not present in the tail. */
|
|
155
|
+
logUnityVersion: string | null;
|
|
156
|
+
/** True when the header's "Batch mode:" line is "YES". null when absent. */
|
|
157
|
+
logBatchMode: boolean | null;
|
|
158
|
+
/** ISO timestamp parsed from the header's "Date:" line, when present. */
|
|
159
|
+
logDate: string | null;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Parse the Unity Editor.log header fields that identify WHO wrote the log.
|
|
163
|
+
* Scans only the tail content already read by the tool (no extra disk I/O).
|
|
164
|
+
*
|
|
165
|
+
* Returns nulls (not throws) when the header lines are absent — a long-running
|
|
166
|
+
* live editor's tail starts mid-log and won't contain the header, which is the
|
|
167
|
+
* benign case (no version to compare against, so no false mismatch).
|
|
168
|
+
*/
|
|
169
|
+
export declare function parseLogAuthorship(tail: string): LogAuthorship;
|
|
170
|
+
export interface LogAuthorshipMismatch {
|
|
171
|
+
/** True when the log's Unity version differs from the live bridge's. */
|
|
172
|
+
versionMismatch: boolean;
|
|
173
|
+
/** The version that wrote the log (from the header). */
|
|
174
|
+
logUnityVersion: string | null;
|
|
175
|
+
/** The live bridge's version, when known. */
|
|
176
|
+
liveUnityVersion: string | null;
|
|
177
|
+
/** True when the log was written by a -batchmode run (not the live editor). */
|
|
178
|
+
logBatchMode: boolean | null;
|
|
179
|
+
/** One-line agent-facing warning. Empty when not a mismatch. */
|
|
180
|
+
hint: string;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Compare the log's authorship against the live bridge's Unity version. This is
|
|
184
|
+
* the cross-check feedback-04-08-opus §2 asks for: a batch run of a NEWER Unity
|
|
185
|
+
* leaves a log whose errors (e.g. a deprecation that is only an error on that
|
|
186
|
+
* version) cannot occur in the live editor, so surfacing them as "current"
|
|
187
|
+
* sends the agent chasing ghosts (or refusing to continue) for minutes.
|
|
188
|
+
*
|
|
189
|
+
* Two cheap signals, both from data already at hand:
|
|
190
|
+
* - the log's "Unity Editor version:" vs the live bridge unityVersion
|
|
191
|
+
* - the log's "Batch mode:" flag (a batch run is never the live editor)
|
|
192
|
+
*
|
|
193
|
+
* Conservative: only flags a mismatch when BOTH the log version parsed AND a
|
|
194
|
+
* live version is known, AND they differ. A null log version (header scrolled
|
|
195
|
+
* past the tail) never fires — there is nothing to compare. When the log is a
|
|
196
|
+
* batch run but the versions agree, we surface the batch-mode flag WITHOUT
|
|
197
|
+
* calling it a mismatch (the agent still benefits from knowing it is a batch
|
|
198
|
+
* log). The router decides how to fold this into the response.
|
|
199
|
+
*/
|
|
200
|
+
export declare function compareLogAuthorship(authorship: LogAuthorship, liveUnityVersion: string | null | undefined): LogAuthorshipMismatch;
|