unity-open-mcp 1.4.0 → 1.6.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.
Files changed (102) hide show
  1. package/dist/capabilities/cost-hints.js +73 -0
  2. package/dist/capabilities/cost-hints.js.map +1 -1
  3. package/dist/capabilities/intent-groups.js +76 -4
  4. package/dist/capabilities/intent-groups.js.map +1 -1
  5. package/dist/capabilities/lifecycle.js +9 -0
  6. package/dist/capabilities/lifecycle.js.map +1 -1
  7. package/dist/capabilities/tool-groups.js +75 -17
  8. package/dist/capabilities/tool-groups.js.map +1 -1
  9. package/dist/compressible-router.d.ts +4 -1
  10. package/dist/compressible-router.js +27 -11
  11. package/dist/compressible-router.js.map +1 -1
  12. package/dist/constants.d.ts +2 -2
  13. package/dist/constants.js +2 -2
  14. package/dist/event-stream.d.ts +10 -0
  15. package/dist/event-stream.js +29 -0
  16. package/dist/event-stream.js.map +1 -1
  17. package/dist/game-view-settle.d.ts +18 -0
  18. package/dist/game-view-settle.js +81 -0
  19. package/dist/game-view-settle.js.map +1 -0
  20. package/dist/jobs/adapters.d.ts +59 -0
  21. package/dist/jobs/adapters.js +226 -0
  22. package/dist/jobs/adapters.js.map +1 -1
  23. package/dist/live-client.d.ts +17 -60
  24. package/dist/live-client.js +52 -87
  25. package/dist/live-client.js.map +1 -1
  26. package/dist/local-tools.js +3 -0
  27. package/dist/local-tools.js.map +1 -1
  28. package/dist/offline/api.d.ts +2 -0
  29. package/dist/offline/api.js +4 -2
  30. package/dist/offline/api.js.map +1 -1
  31. package/dist/offline/model.js +1 -1
  32. package/dist/offline/model.js.map +1 -1
  33. package/dist/offline/parse.d.ts +1 -1
  34. package/dist/offline/parse.js +20 -8
  35. package/dist/offline/parse.js.map +1 -1
  36. package/dist/playmode-routes.d.ts +17 -0
  37. package/dist/playmode-routes.js +50 -0
  38. package/dist/playmode-routes.js.map +1 -0
  39. package/dist/playtest/png.d.ts +27 -0
  40. package/dist/playtest/png.js +248 -0
  41. package/dist/playtest/png.js.map +1 -0
  42. package/dist/playtest/recorder.d.ts +203 -0
  43. package/dist/playtest/recorder.js +945 -0
  44. package/dist/playtest/recorder.js.map +1 -0
  45. package/dist/playtest/redact.d.ts +16 -0
  46. package/dist/playtest/redact.js +124 -0
  47. package/dist/playtest/redact.js.map +1 -0
  48. package/dist/playtest/report.d.ts +73 -0
  49. package/dist/playtest/report.js +477 -0
  50. package/dist/playtest/report.js.map +1 -0
  51. package/dist/playtest/session-store.d.ts +78 -0
  52. package/dist/playtest/session-store.js +224 -0
  53. package/dist/playtest/session-store.js.map +1 -0
  54. package/dist/skill/SKILL.md +22 -3
  55. package/dist/skill/references/senses-and-tests.md +3 -0
  56. package/dist/skill/references/yaml-and-offline-work.md +1 -1
  57. package/dist/tool-router.d.ts +44 -0
  58. package/dist/tool-router.js +249 -7
  59. package/dist/tool-router.js.map +1 -1
  60. package/dist/tools/batch-execute.js +5 -1
  61. package/dist/tools/batch-execute.js.map +1 -1
  62. package/dist/tools/capture-inline.js +30 -12
  63. package/dist/tools/capture-inline.js.map +1 -1
  64. package/dist/tools/capture-series.d.ts +46 -0
  65. package/dist/tools/capture-series.js +116 -0
  66. package/dist/tools/capture-series.js.map +1 -0
  67. package/dist/tools/game-view.d.ts +44 -0
  68. package/dist/tools/game-view.js +103 -0
  69. package/dist/tools/game-view.js.map +1 -0
  70. package/dist/tools/index.d.ts +1 -0
  71. package/dist/tools/index.js +34 -7
  72. package/dist/tools/index.js.map +1 -1
  73. package/dist/tools/inputsim-gesture.d.ts +46 -0
  74. package/dist/tools/inputsim-gesture.js +123 -0
  75. package/dist/tools/inputsim-gesture.js.map +1 -0
  76. package/dist/tools/inputsim-pointer.js +35 -2
  77. package/dist/tools/inputsim-pointer.js.map +1 -1
  78. package/dist/tools/inputsim-touch.js +42 -22
  79. package/dist/tools/inputsim-touch.js.map +1 -1
  80. package/dist/tools/jobs.js +1 -1
  81. package/dist/tools/jobs.js.map +1 -1
  82. package/dist/tools/player-state.d.ts +42 -0
  83. package/dist/tools/player-state.js +142 -0
  84. package/dist/tools/player-state.js.map +1 -0
  85. package/dist/tools/playtest-conditions.d.ts +334 -0
  86. package/dist/tools/playtest-conditions.js +99 -0
  87. package/dist/tools/playtest-conditions.js.map +1 -0
  88. package/dist/tools/playtest-session.d.ts +45 -0
  89. package/dist/tools/playtest-session.js +105 -0
  90. package/dist/tools/playtest-session.js.map +1 -0
  91. package/dist/tools/playtest-wait.d.ts +46 -0
  92. package/dist/tools/playtest-wait.js +86 -0
  93. package/dist/tools/playtest-wait.js.map +1 -0
  94. package/dist/tools/screenshot.js +31 -8
  95. package/dist/tools/screenshot.js.map +1 -1
  96. package/dist/tools/text-target.d.ts +22 -0
  97. package/dist/tools/text-target.js +39 -0
  98. package/dist/tools/text-target.js.map +1 -0
  99. package/dist/tools/ui-snapshot.d.ts +41 -0
  100. package/dist/tools/ui-snapshot.js +87 -0
  101. package/dist/tools/ui-snapshot.js.map +1 -0
  102. package/package.json +1 -1
@@ -0,0 +1,123 @@
1
+ // Input simulation — keyframed touch gestures over real play-mode frames.
2
+ //
3
+ // The bridge starts the gesture on its shared play-mode scheduler (a player-loop
4
+ // tick at the start of EarlyUpdate) and returns an operation id at once; this
5
+ // server turns that into the terminal trace by polling POST /playmode-operations
6
+ // (tool-router `routeInputsimGesture`). A gesture longer than the inline budget
7
+ // runs as a `jobs` play-mode operation instead and the call returns its job id.
8
+ //
9
+ // Routing matches inputsim_touch: legacy Input Manager touches (+ emulated
10
+ // legacy mouse) and/or Input System Touchscreen events, `backend` reported as an
11
+ // array. Legacy is single-finger (id 0). Cancel / exit play / reload release
12
+ // every held finger. `capture_at_ms` captures the composed game frame at those
13
+ // offsets in the same scheduled operation (a tap and the frames after it).
14
+ import { makeTool } from "./schema-fragments.js";
15
+ import { textTargetProps } from "./text-target.js";
16
+ /** Longest gesture (ms) the direct call waits for inline; longer ones become a job. */
17
+ export const INPUTSIM_GESTURE_INLINE_LIMIT_MS = 40_000;
18
+ /** Hard cap on a gesture's last keyframe (mirrors the bridge's GesturePlan.MaxDurationMs). */
19
+ export const INPUTSIM_GESTURE_MAX_DURATION_MS = 300_000;
20
+ /** Mirrors the bridge's GestureTools.MaxCaptures. */
21
+ export const INPUTSIM_GESTURE_MAX_CAPTURES = 30;
22
+ const keyframe = {
23
+ type: "object",
24
+ required: ["at_ms"],
25
+ properties: {
26
+ at_ms: {
27
+ type: "number",
28
+ minimum: 0,
29
+ maximum: INPUTSIM_GESTURE_MAX_DURATION_MS,
30
+ description: "Time of this keyframe from the gesture start, in ms (strictly increasing per finger).",
31
+ },
32
+ x: { type: "number", description: "Screen X (coords: screen = pixels, bottom-left origin; normalized = 0..1; target = pixel offset from the target center)." },
33
+ y: { type: "number", description: "Screen Y, same space as x." },
34
+ target: { type: "string", description: "coords: target only — GameObject name or hierarchy path whose visual center is the point." },
35
+ ...textTargetProps("coords: target only — the keyframe point (instead of `target`; x/y stay pixel offsets)"),
36
+ phase: {
37
+ type: "string",
38
+ enum: ["down", "move", "hold", "up"],
39
+ description: "down = first keyframe (default there): finger touches. move = default in between: " +
40
+ "interpolate from the previous keyframe. hold = stay at the previous point until at_ms " +
41
+ "(x/y may be omitted). up = last keyframe (default there): move to this point and lift.",
42
+ },
43
+ },
44
+ additionalProperties: false,
45
+ };
46
+ export const inputsimGesture = makeTool("unity_open_mcp_inputsim_gesture", "Play a touch gesture across REAL play-mode frames: per-finger keyframed paths " +
47
+ "(down → move/hold → up) interpolated every frame, so polled gameplay input " +
48
+ "(Input.GetTouch / Input.mousePosition / Touchscreen.current) follows the finger " +
49
+ "for seconds — hold, drag, trace a curve. `time: gameplay` follows Time.timeScale. " +
50
+ "Routing like inputsim_touch: legacy Input Manager touches (legacy_touch, also " +
51
+ "driving the legacy mouse API and StandaloneInputModule) and/or Input System " +
52
+ "Touchscreen events (input_system); `backend` in the result is an array. Legacy is " +
53
+ "single-finger (id 0) — more fingers refuse with legacy_multitouch_unsupported; " +
54
+ "no reachable backend refuses with input_backend_unavailable (with the detected " +
55
+ "configuration), an unverified Editor with unsupported_editor_version. The call " +
56
+ "waits for the terminal result: a bounded trace (per keyframe: frame, screen point, " +
57
+ "uGUI top hit) plus console errors raised meanwhile. capture_at_ms [0, 100, 300, …] also captures the " +
58
+ "composed game frame at those offsets from the gesture start inside the same operation (the " +
59
+ "capture_series recorder: native size, files + per-frame frame / play_time under `captures`), so a tap " +
60
+ "and its follow-up frames come back from one call. Gestures longer than " +
61
+ `${INPUTSIM_GESTURE_INLINE_LIMIT_MS / 1000}s return a job_id instead — wait on it with ` +
62
+ "unity_open_mcp_jobs (you can also start one there directly). Cancel, exiting play " +
63
+ "mode and a domain reload release every held finger. One input gesture at a time " +
64
+ "(playmode_operation_busy). Play-mode only; gate-free. Not allowed inside batch_execute.", {
65
+ required: ["fingers"],
66
+ properties: {
67
+ fingers: {
68
+ type: "array",
69
+ minItems: 1,
70
+ maxItems: 10,
71
+ description: "One entry per finger: { id (0-9, default = index), path: [keyframes] }.",
72
+ items: {
73
+ type: "object",
74
+ required: ["path"],
75
+ properties: {
76
+ id: { type: "integer", minimum: 0, maximum: 9 },
77
+ path: { type: "array", minItems: 2, maxItems: 256, items: keyframe },
78
+ },
79
+ additionalProperties: false,
80
+ },
81
+ },
82
+ coords: {
83
+ type: "string",
84
+ enum: ["screen", "normalized", "target"],
85
+ default: "screen",
86
+ description: "screen = Screen pixels (bottom-left origin, same as Input.mousePosition); normalized = " +
87
+ "0..1 of the Game view size; target = each keyframe names a target or a target_text " +
88
+ "(on-screen label, like inputsim_touch), x/y are pixel offsets.",
89
+ },
90
+ time: {
91
+ type: "string",
92
+ enum: ["realtime", "gameplay"],
93
+ default: "realtime",
94
+ description: "realtime = unscaled wall time; gameplay = scaled by Time.timeScale (a paused game never advances).",
95
+ },
96
+ backend: {
97
+ type: "string",
98
+ enum: ["auto", "legacy_touch", "input_system"],
99
+ default: "auto",
100
+ description: "auto = every enabled, reachable backend (legacy_touch when the legacy Input Manager is " +
101
+ "on; input_system when a Touchscreen device exists). Force one with legacy_touch / input_system.",
102
+ },
103
+ capture_at_ms: {
104
+ type: "array",
105
+ minItems: 1,
106
+ maxItems: INPUTSIM_GESTURE_MAX_CAPTURES,
107
+ items: { type: "number", minimum: 0, maximum: INPUTSIM_GESTURE_MAX_DURATION_MS },
108
+ description: "Capture the composed game frame at these offsets (ms, the gesture's `time` base) from the gesture " +
109
+ "start — the call returns when the gesture and the last capture are done. Result `captures.frames[]`: " +
110
+ "frame, play_time, elapsed_ms, file, `unchanged`. Needs a rendering Game view / Simulator (Unity 6). " +
111
+ "In gameplay time a paused game (timeScale 0) ends the gesture after a wall-clock limit (error_code " +
112
+ "timed_out); captured frames are kept.",
113
+ },
114
+ operation_id: {
115
+ type: "string",
116
+ pattern: "^[A-Za-z0-9-]{8,64}$",
117
+ description: "Optional idempotency handle for the bridge operation (8-64 letters, digits, dashes). A retried " +
118
+ "call with the same id returns the same operation instead of starting another. Omit it normally " +
119
+ "(the server generates one); jobs always set it to the job id.",
120
+ },
121
+ },
122
+ });
123
+ //# sourceMappingURL=inputsim-gesture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputsim-gesture.js","sourceRoot":"","sources":["../../src/tools/inputsim-gesture.ts"],"names":[],"mappings":"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"}
@@ -18,10 +18,17 @@
18
18
  // feature for reaching things a raycast would miss); the fields let the agent
19
19
  // judge whether the interaction was actually possible.
20
20
  //
21
+ // routing: "raycast_real" skips ExecuteEvents and injects a real touch through
22
+ // the project's input backend (legacy touches and/or Input System Touchscreen),
23
+ // so the scene's own EventSystem input module raycasts and decides what is hit —
24
+ // a cover graphic absorbs the tap like it would a finger. The response reports
25
+ // the top hit, whether it is the target, the input module and the backend.
26
+ //
21
27
  // Play-mode only (play_mode_required otherwise). Gate-free (writes no assets).
22
28
  // Pair with inputsim_step to advance frames between the interaction and a
23
29
  // screenshot so tweens/animations settle before you look.
24
30
  import { makeTool } from "./schema-fragments.js";
31
+ import { textTargetProps } from "./text-target.js";
25
32
  export const inputsimPointer = makeTool("unity_open_mcp_inputsim_pointer", "Simulate a uGUI pointer interaction on a named GameObject or screen point " +
26
33
  "during play mode, via the EventSystem + ExecuteEvents. Resolution precedence: " +
27
34
  "object_id (a handle from scene_get_data / inputsim_probe) > target (name or " +
@@ -30,8 +37,19 @@ export const inputsimPointer = makeTool("unity_open_mcp_inputsim_pointer", "Simu
30
37
  "`blockedBy`, and (for drag) `dropTarget`/`dropLanded` so a click on a disabled " +
31
38
  "button or behind a modal is never a silent ok. Play-mode only — refuses with " +
32
39
  "`play_mode_required` otherwise; pair with editor_set_state to enter play mode " +
33
- "and inputsim_step to advance frames before a screenshot. Gate-free. Requires " +
34
- "com.unity.ugui.", {
40
+ "and inputsim_step to advance frames before a screenshot. ROUTING: `dispatch` " +
41
+ "(default) is the ExecuteEvents path above (reaches IPointer*/IDrag handlers only, " +
42
+ "bypasses occlusion). `raycast_real` instead injects a real touch at the point " +
43
+ "through the project's input backend (`backend`: auto | legacy_touch | input_system, " +
44
+ "reported as an array) so the scene's own EventSystem input module raycasts and " +
45
+ "dispatches it — whatever is on top receives it; the response reports `topHit`, " +
46
+ "`targetHit`, `blockedBy`, `inputModule` and `notes` (e.g. module/backend mismatch). " +
47
+ "raycast_real supports click, double_click, press, release, drag with the left " +
48
+ "button only and refuses like inputsim_touch (input_backend_unavailable, " +
49
+ "unsupported_editor_version). TARGET BY LABEL: `target_text` (+ under, index, text_match) picks " +
50
+ "the visible element whose text matches (see ui_snapshot) — exclusive with object_id/target/" +
51
+ "screen_x/screen_y (conflicting_targets); ambiguous labels refuse with ambiguous_target. " +
52
+ "Gate-free. Requires com.unity.ugui.", {
35
53
  required: ["action"],
36
54
  properties: {
37
55
  action: {
@@ -116,6 +134,21 @@ export const inputsimPointer = makeTool("unity_open_mcp_inputsim_pointer", "Simu
116
134
  },
117
135
  to_x: { type: "number", description: "Drag end — screen X (alternative to to_target)." },
118
136
  to_y: { type: "number", description: "Drag end — screen Y (alternative to to_target)." },
137
+ routing: {
138
+ type: "string",
139
+ enum: ["dispatch", "raycast_real"],
140
+ default: "dispatch",
141
+ description: "dispatch = ExecuteEvents on the resolved object (default). raycast_real = inject a real " +
142
+ "touch at its screen point so the project's input module decides what is hit (a cover " +
143
+ "graphic absorbs it); the response still reports the top hit.",
144
+ },
145
+ backend: {
146
+ type: "string",
147
+ enum: ["auto", "legacy_touch", "input_system"],
148
+ default: "auto",
149
+ description: "Input backend for routing: raycast_real (ignored by dispatch; must stay auto there).",
150
+ },
151
+ ...textTargetProps("Element to act on (the drag start for drag)"),
119
152
  },
120
153
  });
121
154
  //# sourceMappingURL=inputsim-pointer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"inputsim-pointer.js","sourceRoot":"","sources":["../../src/tools/inputsim-pointer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"inputsim-pointer.js","sourceRoot":"","sources":["../../src/tools/inputsim-pointer.ts"],"names":[],"mappings":"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"}
@@ -1,31 +1,42 @@
1
- // Input simulation — Input System touch / swipe device events.
1
+ // Input simulation — backend-aware touch / swipe.
2
2
  //
3
- // Compile-gated on com.unity.inputsystem (UNITY_OPEN_MCP_EXT_INPUTSIM_IS).
4
- // Queues Touchscreen state events through the new Input System.
3
+ // The bridge routes each call to the project's real input backend(s) and reports
4
+ // them as `backend` (an array): legacy Input Manager touches (`legacy_touch`,
5
+ // which also drive the legacy mouse API through Input.simulateMouseWithTouches
6
+ // and therefore StandaloneInputModule) and/or Input System Touchscreen state
7
+ // events (`input_system`). With activeInputHandler Both, `auto` injects into both.
8
+ // The tool compiles in every project (no com.unity.inputsystem requirement).
5
9
  //
6
10
  // 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 dispatch —
10
- // documented honestly now (previously mis-advertised as "across real frames").
11
+ // phase, so the swipe genuinely unfolds across frames for polling code. The
12
+ // legacy backend always advances at least one frame between phases (its phases
13
+ // collapse otherwise). Real-time gestures that last seconds: inputsim_gesture.
11
14
  //
12
- // Play-mode only. Gate-free. Requires com.unity.inputsystem.
15
+ // Play-mode only. Gate-free.
13
16
  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 within one " +
19
- "dispatch — 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. The Began phase also advances before the first move. Endpoints " +
17
+ import { textTargetProps } from "./text-target.js";
18
+ export const inputsimTouch = makeTool("unity_open_mcp_inputsim_touch", "Simulate a touch / swipe during play mode through the project's REAL input " +
19
+ "backend, reported as `backend` (array): legacy Input Manager touches (legacy_touch — " +
20
+ "Input.GetTouch, plus the legacy mouse API via Input.simulateMouseWithTouches, which " +
21
+ "StandaloneInputModule reads) and/or Input System Touchscreen events (input_system). " +
22
+ "`backend: auto` (default) injects into every enabled, reachable backend " +
23
+ "(activeInputHandler Both → both when a Touchscreen device exists; skipped backends are " +
24
+ "listed). Refusals: input_backend_unavailable (with the detected configuration and next " +
25
+ "steps), legacy_multitouch_unsupported (legacy is finger 0 only), " +
26
+ "unsupported_editor_version, no_device (explicit input_system without a Touchscreen). " +
27
+ "`tap` = press+release at a point; `swipe` = press at from_, move across `steps` " +
28
+ "interpolated points, release at to_; `press`/`release` = single-phase control. " +
29
+ "POLLING vs CALLBACK: with input_system only and no `advance_frames`, all phases process " +
30
+ "within one dispatch — polling code sees a collapsed jump. Pass `advance_frames` ≥ 1 to " +
31
+ "advance frames after Began and each Moved phase; legacy_touch always advances at least " +
32
+ "one frame between phases. For seconds-long holds/drags use inputsim_gesture. Endpoints " +
24
33
  "resolve target-first (name/path to visual center) or accept screen coordinates. " +
25
34
  "Root-anchored paths win over suffix matches; ambiguous names/paths return " +
26
35
  "ambiguous_target with candidate paths. This tool has no object_id parameter; " +
27
- "use a unique path or screen coordinates. Play-mode only — refuses " +
28
- "with `play_mode_required` otherwise. Gate-free. Requires com.unity.inputsystem.", {
36
+ "use a unique path, screen coordinates, or `target_text` — the visible uGUI element whose " +
37
+ "text matches (exclusive with target/screen_x/screen_y; for swipe it is the start, exclusive with " +
38
+ "from_target/from_x/from_y — conflicting_targets). Play-mode only — refuses " +
39
+ "with `play_mode_required` otherwise. Gate-free.", {
29
40
  required: ["action"],
30
41
  properties: {
31
42
  action: {
@@ -40,7 +51,7 @@ export const inputsimTouch = makeTool("unity_open_mcp_inputsim_touch", "Queue a
40
51
  default: 0,
41
52
  minimum: 0,
42
53
  maximum: 9,
43
- description: "Touch finger index (0–9) for multi-touch. Default 0.",
54
+ description: "Touch finger index (0–9). The legacy_touch backend supports finger 0 only. Default 0.",
44
55
  },
45
56
  target: {
46
57
  type: "string",
@@ -75,8 +86,17 @@ export const inputsimTouch = makeTool("unity_open_mcp_inputsim_touch", "Queue a
75
86
  description: "Pump this many player-loop frames (EditorApplication.Step) AFTER each " +
76
87
  "Moved phase so the swipe unfolds across real frames for polling code " +
77
88
  "(per-frame delta, gesture recognizers). 0 (default) collapses all phases " +
78
- "into one dispatch — only callback-driven input sees it then. Also advances after Began. Cap 60.",
89
+ "into one dispatch — only callback-driven input sees it then. Also advances after Began. " +
90
+ "The legacy_touch backend uses at least 1. Cap 60.",
79
91
  },
92
+ backend: {
93
+ type: "string",
94
+ enum: ["auto", "legacy_touch", "input_system"],
95
+ default: "auto",
96
+ description: "auto = every enabled, reachable backend; legacy_touch = legacy Input Manager only; " +
97
+ "input_system = Input System Touchscreen only (allows fingers 1–9).",
98
+ },
99
+ ...textTargetProps("Point to tap/press/release (the swipe start for swipe)"),
80
100
  },
81
101
  });
82
102
  //# sourceMappingURL=inputsim-touch.js.map
@@ -1 +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,uEAAuE;AACvE,+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,gEAAgE;IAChE,oEAAoE;IACpE,8EAA8E;IAC9E,4EAA4E;IAC5E,4EAA4E;IAC5E,6EAA6E;IAC7E,kFAAkF;IAClF,4EAA4E;IAC5E,+EAA+E;IAC/E,oEAAoE;IACpE,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,iGAAiG;SACpG;KACF;CACF,CACF,CAAC"}
1
+ {"version":3,"file":"inputsim-touch.js","sourceRoot":"","sources":["../../src/tools/inputsim-touch.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { makeTool } from "./schema-fragments.js";
2
2
  import { JOB_STATES } from "../jobs/job-manager.js";
3
- export const jobs = makeTool("unity_open_mcp_jobs", "Observe session-owned asynchronous jobs: start, status, bounded wait, cooperative cancel, and paged list. Supported targets: unity_senses_run_tests and available async project commands. Other tools are unsupported. Test args are ordinary filters without run_id; project args contain nested args plus scope/gate options. Mutating starts require idempotency_key. Records expire 30 minutes after completion; server restart loses all records. Never blindly retry an orphaned job.", {
3
+ export const jobs = makeTool("unity_open_mcp_jobs", "Observe session-owned asynchronous jobs: start, status, bounded wait, cooperative cancel, and paged list. Supported targets: unity_senses_run_tests, available async project commands, and play-mode operations (unity_open_mcp_inputsim_gesture, unity_open_mcp_playtest_wait, unity_senses_capture_series; cancellable — cancel releases held input and restores a wait's time scale). Other tools are unsupported. Test args are ordinary filters without run_id; project args contain nested args plus scope/gate options; play-mode operation args are the tool's own arguments (the job owns operation_id). Mutating starts require idempotency_key. Records expire 30 minutes after completion; server restart loses all records. Never blindly retry an orphaned job.", {
4
4
  required: ["action"],
5
5
  properties: {
6
6
  action: { type: "string", enum: ["start", "status", "wait", "cancel", "list"] },
@@ -1 +1 @@
1
- {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/tools/jobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,MAAM,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAC,qBAAqB,EAChD,6dAA6d,EAAE;IAC7d,QAAQ,EAAE,CAAC,QAAQ,CAAC;IACpB,UAAU,EAAE;QACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE;QAC/E,eAAe,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;QACjE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kEAAkE,EAAE;QACzG,eAAe,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;QACjE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;QACxD,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;QAC3D,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,GAAG,UAAU,CAAC,EAAE;QAChD,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE;QAC7C,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE;QAC3C,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE;KACrD;CACF,CAAC,CAAC"}
1
+ {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../src/tools/jobs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD,MAAM,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAC,qBAAqB,EAChD,+uBAA+uB,EAAE;IAC/uB,QAAQ,EAAE,CAAC,QAAQ,CAAC;IACpB,UAAU,EAAE;QACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE;QAC/E,eAAe,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;QACjE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,kEAAkE,EAAE;QACzG,eAAe,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;QACjE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE;QACxD,UAAU,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE;QAC3D,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,GAAG,UAAU,CAAC,EAAE;QAChD,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE;QAC7C,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE;QAC3C,KAAK,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE;KACrD;CACF,CAAC,CAAC"}
@@ -0,0 +1,42 @@
1
+ export declare const PLAYER_STATE_ACTIONS: readonly ["snapshot", "diff", "restore", "list", "delete"];
2
+ export declare const PLAYER_STATE_RESTORE_SCOPE = "ProjectSettings/ProjectSettings.asset";
3
+ export declare const playerState: {
4
+ inputSchema: {
5
+ [x: string]: unknown;
6
+ type: "object";
7
+ properties?: {
8
+ [x: string]: object;
9
+ } | undefined;
10
+ required?: string[] | undefined;
11
+ };
12
+ name: string;
13
+ description?: string | undefined;
14
+ outputSchema?: {
15
+ [x: string]: unknown;
16
+ type: "object";
17
+ properties?: {
18
+ [x: string]: object;
19
+ } | undefined;
20
+ required?: string[] | undefined;
21
+ } | undefined;
22
+ annotations?: {
23
+ title?: string | undefined;
24
+ readOnlyHint?: boolean | undefined;
25
+ destructiveHint?: boolean | undefined;
26
+ idempotentHint?: boolean | undefined;
27
+ openWorldHint?: boolean | undefined;
28
+ } | undefined;
29
+ execution?: {
30
+ taskSupport?: "optional" | "required" | "forbidden" | undefined;
31
+ } | undefined;
32
+ _meta?: {
33
+ [x: string]: unknown;
34
+ } | undefined;
35
+ icons?: {
36
+ src: string;
37
+ mimeType?: string | undefined;
38
+ sizes?: string[] | undefined;
39
+ theme?: "light" | "dark" | undefined;
40
+ }[] | undefined;
41
+ title?: string | undefined;
42
+ };
@@ -0,0 +1,142 @@
1
+ // Playtest — player-state sandbox for a live playtest.
2
+ //
3
+ // snapshot / diff / restore / list / delete over the state a play session
4
+ // changes: PlayerPrefs (all keys, typed — read from the platform store after the
5
+ // bridge flushes PlayerPrefs.Save, since Unity has no enumeration API), opt-in
6
+ // EditorPrefs by key prefix, and the files under persistentDataPath. Snapshots
7
+ // live in the platform app-data folder outside the project
8
+ // (`…/unity-open-mcp/player-state/<company>/<product>/<name>/`). Only `restore`
9
+ // with `confirm: true` writes state: the bridge classifies it as a mutation per
10
+ // request, so it runs the normal gate + audit path; its `paths_hint` defaults to
11
+ // ProjectSettings/ProjectSettings.asset (the company / product identity the
12
+ // snapshot is bound to — restore writes no project asset). Group `playtest`.
13
+ import { GATE_PROP, makeTool } from "./schema-fragments.js";
14
+ export const PLAYER_STATE_ACTIONS = ["snapshot", "diff", "restore", "list", "delete"];
15
+ export const PLAYER_STATE_RESTORE_SCOPE = "ProjectSettings/ProjectSettings.asset";
16
+ // No "..", no trailing "." (the bridge refuses both).
17
+ const SNAPSHOT_NAME_PATTERN = "^(?!.*\\.\\.)(?!.*\\.$)[A-Za-z0-9][A-Za-z0-9._-]{0,63}$";
18
+ export const playerState = makeTool("unity_open_mcp_player_state", "Isolate the player state a live playtest changes: snapshot it, see what a session changed, put it back. " +
19
+ "STATE = PlayerPrefs (every key with its type, read from the platform store after PlayerPrefs.Save so it " +
20
+ "is what the game wrote, even unsaved), persistentDataPath files (size + sha256; default excludes " +
21
+ "Unity/** and TestResults.xml, cap max_files_mb), and EditorPrefs only under editor_prefs_prefixes " +
22
+ "(opt-in; EditorPrefs are shared by every project on the machine). Unity's own session keys " +
23
+ "(unity.player_session*, unity_connect.*) are excluded by default; excluded keys and paths are never " +
24
+ "captured, diffed or touched. Snapshots are stored outside the project in the app-data folder " +
25
+ "(…/unity-open-mcp/player-state/<company>/<product>/<name>/). ACTIONS: snapshot = capture into `name` " +
26
+ "(snapshot_exists unless overwrite); diff = `name` vs the current state (or vs snapshot `against`): " +
27
+ "prefs / editor_prefs / files added, removed, changed — small values shown, long strings and files as " +
28
+ "size + sha256; restore = EDIT MODE ONLY; without confirm a dry run returning the diff it would apply " +
29
+ "(current → snapshot) with EVERY removal and overwrite listed and a `plan` id; with confirm:true + that " +
30
+ "plan it OVERWRITES the current state (plan_changed when the state moved since the dry run) — " +
31
+ "PlayerPrefs.DeleteAll + the snapshot's keys + Save (so the Editor's in-memory cache and the store agree), " +
32
+ "EditorPrefs only under the snapshot's prefixes, persistentDataPath mirrored exactly (files not in the " +
33
+ "snapshot are DELETED) — then re-reads and reports verified; it is the only gated action (paths_hint " +
34
+ "defaults to ProjectSettings/ProjectSettings.asset) and refuses edit_mode_required in play mode and " +
35
+ "snapshot_project_mismatch for another project's snapshot; list / delete = the snapshots of this " +
36
+ "project (company + product address another project's store). Prefer a project's own isolated-save " +
37
+ "hook (project_commands playtest.begin / playtest.end) when it exists; otherwise snapshot → play → diff " +
38
+ "→ stop → restore (dry run, then confirm with its plan). macOS verified; Windows registry and Linux readers are " +
39
+ "untested in the field.", {
40
+ required: ["action"],
41
+ properties: {
42
+ action: {
43
+ type: "string",
44
+ enum: [...PLAYER_STATE_ACTIONS],
45
+ description: "snapshot: capture into name. diff: name vs current (or against). restore: dry run, or apply with " +
46
+ "confirm:true (edit mode). list: snapshots of this project. delete: remove snapshot name.",
47
+ },
48
+ name: {
49
+ type: "string",
50
+ pattern: SNAPSHOT_NAME_PATTERN,
51
+ description: "[snapshot / diff / restore / delete] Snapshot name: 1-64 of [A-Za-z0-9._-], starting with a letter or digit.",
52
+ },
53
+ against: {
54
+ type: "string",
55
+ pattern: SNAPSHOT_NAME_PATTERN,
56
+ description: "[diff] Compare `name` with this other snapshot instead of the current state.",
57
+ },
58
+ confirm: {
59
+ type: "boolean",
60
+ default: false,
61
+ description: "[restore] false (default) = dry run: returns the diff restore would apply and its plan id, nothing " +
62
+ "changes. true = apply (needs `plan`): overwrites PlayerPrefs, opted-in EditorPrefs and persistentDataPath " +
63
+ "(removing files not in the snapshot). Review the dry run's removals and overwrites first.",
64
+ },
65
+ plan: {
66
+ type: "string",
67
+ pattern: "^[0-9a-f]{16}$",
68
+ description: "[restore confirm:true] The `plan` id the dry run returned. Required with confirm:true: restore applies " +
69
+ "only the plan that was reviewed and refuses plan_changed when the current state moved since (a new " +
70
+ "save file, a changed key) — run the dry run again then.",
71
+ },
72
+ editor_prefs_prefixes: {
73
+ type: "array",
74
+ items: { type: "string", minLength: 3 },
75
+ minItems: 1,
76
+ maxItems: 16,
77
+ description: "[snapshot] Also capture EditorPrefs whose key starts with one of these prefixes (≥ 3 characters each). " +
78
+ "Off by default: EditorPrefs are shared by all projects on this machine. restore touches only keys " +
79
+ "under the snapshot's prefixes (never EditorPrefs.DeleteAll).",
80
+ },
81
+ exclude: {
82
+ type: "array",
83
+ items: { type: "string", minLength: 1 },
84
+ maxItems: 32,
85
+ description: "[snapshot] Extra glob patterns of persistentDataPath paths to leave out (added to the defaults " +
86
+ "Unity/** and TestResults.xml): '**' any depth, '*' / '?' within a name; a pattern without '/' " +
87
+ "matches a file or folder name at any depth (e.g. '*.log', 'Cache/**'). Excluded paths are never " +
88
+ "restored or removed.",
89
+ },
90
+ exclude_keys: {
91
+ type: "array",
92
+ items: { type: "string", minLength: 1 },
93
+ maxItems: 32,
94
+ description: "[snapshot] Extra PlayerPrefs key patterns to leave out ('*' any run, '?' one character), added to " +
95
+ "the defaults unity.player_session* and unity_connect.* (Unity's per-session bookkeeping). Excluded " +
96
+ "keys keep their current values on restore.",
97
+ },
98
+ max_files_mb: {
99
+ type: "integer",
100
+ minimum: 1,
101
+ maximum: 1024,
102
+ description: "[snapshot] Size cap for the persistentDataPath copy after excludes (default 64; at most 5000 files). " +
103
+ "Over the cap → persistent_data_too_large with the largest files, nothing written.",
104
+ },
105
+ overwrite: {
106
+ type: "boolean",
107
+ description: "[snapshot] Replace an existing snapshot of the same name (default false → snapshot_exists).",
108
+ },
109
+ company: {
110
+ type: "string",
111
+ minLength: 1,
112
+ description: "[diff / restore / list / delete] Company name of another project's snapshot store (default: the open " +
113
+ "project's). restore refuses a snapshot whose company / product differ from the open project.",
114
+ },
115
+ product: {
116
+ type: "string",
117
+ minLength: 1,
118
+ description: "[diff / restore / list / delete] Product name of another project's snapshot store (default: the open project's).",
119
+ },
120
+ limit: {
121
+ type: "integer",
122
+ minimum: 1,
123
+ maximum: 1000,
124
+ description: "[diff / restore] Entries listed per list (default 100; counts are always complete, `truncated` says " +
125
+ "how many were left out). diff bounds added / removed / changed; restore bounds only added and always " +
126
+ "lists every removal and overwrite.",
127
+ },
128
+ paths_hint: {
129
+ type: "array",
130
+ items: { type: "string" },
131
+ default: [PLAYER_STATE_RESTORE_SCOPE],
132
+ description: "Audit / gate scope for restore with confirm:true, materialized automatically: restore writes no " +
133
+ "project asset; ProjectSettings.asset holds the company / product the snapshot is bound to. Ignored " +
134
+ "by every other action.",
135
+ },
136
+ gate: {
137
+ ...GATE_PROP,
138
+ description: "[restore confirm:true] Gate mode for the applied restore. Other actions are not gated.",
139
+ },
140
+ },
141
+ });
142
+ //# sourceMappingURL=player-state.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"player-state.js","sourceRoot":"","sources":["../../src/tools/player-state.ts"],"names":[],"mappings":"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"}