unity-open-mcp 1.2.3 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -2
- package/dist/agent-identity.d.ts +12 -0
- package/dist/agent-identity.js +2 -0
- package/dist/agent-identity.js.map +1 -1
- package/dist/batch-spawn.d.ts +39 -0
- package/dist/batch-spawn.js +287 -69
- package/dist/batch-spawn.js.map +1 -1
- package/dist/capabilities/build-capabilities.js +2 -0
- package/dist/capabilities/build-capabilities.js.map +1 -1
- package/dist/capabilities/discovery.d.ts +51 -0
- package/dist/capabilities/discovery.js +87 -0
- package/dist/capabilities/discovery.js.map +1 -0
- package/dist/capabilities/lifecycle.d.ts +6 -0
- package/dist/capabilities/lifecycle.js +17 -1
- package/dist/capabilities/lifecycle.js.map +1 -1
- package/dist/capabilities/tool-groups.js +1 -0
- package/dist/capabilities/tool-groups.js.map +1 -1
- package/dist/child-supervision.d.ts +6 -0
- package/dist/child-supervision.js +12 -0
- package/dist/child-supervision.js.map +1 -1
- package/dist/cli/args.d.ts +24 -2
- package/dist/cli/args.js +97 -2
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/cli.js +42 -3
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/help-text.d.ts +1 -0
- package/dist/cli/help-text.js +83 -3
- package/dist/cli/help-text.js.map +1 -1
- package/dist/cli/json-guards.d.ts +2 -0
- package/dist/cli/json-guards.js +5 -0
- package/dist/cli/json-guards.js.map +1 -0
- package/dist/cli/setup-command.d.ts +116 -0
- package/dist/cli/setup-command.js +696 -0
- package/dist/cli/setup-command.js.map +1 -0
- package/dist/cli/update-command.d.ts +30 -0
- package/dist/cli/update-command.js +271 -0
- package/dist/cli/update-command.js.map +1 -0
- package/dist/compile-verify.d.ts +3 -0
- package/dist/compile-verify.js +4 -0
- package/dist/compile-verify.js.map +1 -1
- package/dist/constants.d.ts +10 -2
- package/dist/constants.js +10 -2
- package/dist/constants.js.map +1 -1
- package/dist/dialog-dismiss.d.ts +108 -12
- package/dist/dialog-dismiss.js +294 -109
- package/dist/dialog-dismiss.js.map +1 -1
- package/dist/dialog-policy.d.ts +55 -9
- package/dist/dialog-policy.js +85 -15
- package/dist/dialog-policy.js.map +1 -1
- package/dist/editor-search.d.ts +2 -0
- package/dist/editor-search.js +8 -0
- package/dist/editor-search.js.map +1 -0
- package/dist/gate-error.d.ts +3 -0
- package/dist/gate-error.js.map +1 -1
- package/dist/index.js +56 -1
- package/dist/index.js.map +1 -1
- package/dist/instance-discovery.d.ts +16 -0
- package/dist/instance-discovery.js +45 -0
- package/dist/instance-discovery.js.map +1 -1
- package/dist/jobs/adapters.d.ts +15 -0
- package/dist/jobs/adapters.js +147 -0
- package/dist/jobs/adapters.js.map +1 -0
- package/dist/jobs/handler.d.ts +3 -0
- package/dist/jobs/handler.js +29 -0
- package/dist/jobs/handler.js.map +1 -0
- package/dist/jobs/job-manager.d.ts +123 -0
- package/dist/jobs/job-manager.js +290 -0
- package/dist/jobs/job-manager.js.map +1 -0
- package/dist/live-client.d.ts +50 -2
- package/dist/live-client.js +221 -26
- package/dist/live-client.js.map +1 -1
- package/dist/local-tools.d.ts +17 -0
- package/dist/local-tools.js +47 -0
- package/dist/local-tools.js.map +1 -0
- package/dist/project-path.d.ts +99 -0
- package/dist/project-path.js +171 -0
- package/dist/project-path.js.map +1 -0
- package/dist/release-lookup.d.ts +32 -0
- package/dist/release-lookup.js +147 -0
- package/dist/release-lookup.js.map +1 -0
- package/dist/routers.d.ts +17 -3
- package/dist/routers.js +29 -8
- package/dist/routers.js.map +1 -1
- package/dist/running-unity.d.ts +21 -0
- package/dist/running-unity.js +50 -0
- package/dist/running-unity.js.map +1 -1
- package/dist/schema-defaults.d.ts +4 -3
- package/dist/schema-defaults.js +20 -6
- package/dist/schema-defaults.js.map +1 -1
- package/dist/server-instructions.js +7 -1
- package/dist/server-instructions.js.map +1 -1
- package/dist/server.d.ts +10 -3
- package/dist/server.js +24 -25
- package/dist/server.js.map +1 -1
- package/dist/setup/codex-toml.d.ts +23 -0
- package/dist/setup/codex-toml.js +514 -0
- package/dist/setup/codex-toml.js.map +1 -0
- package/dist/setup/portable-config.d.ts +59 -0
- package/dist/setup/portable-config.js +241 -0
- package/dist/setup/portable-config.js.map +1 -0
- package/dist/skill/SKILL.md +68 -0
- package/dist/skill/client-paths.js +2 -4
- package/dist/skill/client-paths.js.map +1 -1
- package/dist/skill/copy-references.d.ts +2 -0
- package/dist/skill/copy-references.js +16 -0
- package/dist/skill/copy-references.js.map +1 -0
- package/dist/skill/generate-skill.js +5 -3
- package/dist/skill/generate-skill.js.map +1 -1
- package/dist/skill/references/batch-and-gates.md +142 -0
- package/dist/skill/references/compile-and-safe-mode.md +163 -0
- package/dist/skill/references/discovery-and-groups.md +30 -0
- package/dist/skill/references/routing-and-lifecycle.md +62 -0
- package/dist/skill/references/senses-and-tests.md +41 -0
- package/dist/skill/references/yaml-and-offline-work.md +33 -0
- package/dist/templates/mcp-wrapper.sh +35 -0
- package/dist/tool-contract.d.ts +8 -0
- package/dist/tool-contract.js +253 -0
- package/dist/tool-contract.js.map +1 -0
- package/dist/tool-router.d.ts +62 -7
- package/dist/tool-router.js +455 -17
- package/dist/tool-router.js.map +1 -1
- package/dist/tool-session-state.d.ts +6 -0
- package/dist/tool-session-state.js +14 -0
- package/dist/tool-session-state.js.map +1 -1
- package/dist/tools/agent-capabilities.js +9 -0
- package/dist/tools/agent-capabilities.js.map +1 -1
- package/dist/tools/batch-execute.js +17 -14
- package/dist/tools/batch-execute.js.map +1 -1
- package/dist/tools/bridge-status.js +4 -5
- package/dist/tools/bridge-status.js.map +1 -1
- package/dist/tools/compile-check.js +6 -4
- package/dist/tools/compile-check.js.map +1 -1
- package/dist/tools/component-get.js +2 -2
- package/dist/tools/component-get.js.map +1 -1
- package/dist/tools/component-modify.js +4 -4
- package/dist/tools/component-modify.js.map +1 -1
- package/dist/tools/execute-csharp.js +8 -4
- package/dist/tools/execute-csharp.js.map +1 -1
- package/dist/tools/gameobject-modify.js +2 -1
- package/dist/tools/gameobject-modify.js.map +1 -1
- package/dist/tools/index.d.ts +2 -0
- package/dist/tools/index.js +10 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/inputsim-key.js +12 -14
- package/dist/tools/inputsim-key.js.map +1 -1
- package/dist/tools/inputsim-pointer.js +3 -3
- package/dist/tools/inputsim-pointer.js.map +1 -1
- package/dist/tools/inputsim-step.js +7 -8
- package/dist/tools/inputsim-step.js.map +1 -1
- package/dist/tools/inputsim-touch.js +9 -10
- package/dist/tools/inputsim-touch.js.map +1 -1
- package/dist/tools/jobs.d.ts +40 -0
- package/dist/tools/jobs.js +18 -0
- package/dist/tools/jobs.js.map +1 -0
- package/dist/tools/manage-tools.js +10 -5
- package/dist/tools/manage-tools.js.map +1 -1
- package/dist/tools/project-commands.d.ts +40 -0
- package/dist/tools/project-commands.js +23 -0
- package/dist/tools/project-commands.js.map +1 -0
- package/dist/tools/read-compile-errors.js +14 -93
- package/dist/tools/read-compile-errors.js.map +1 -1
- package/dist/tools/scan-paths.js +4 -4
- package/dist/tools/scan-paths.js.map +1 -1
- package/dist/tools/schema-fragments.d.ts +15 -3
- package/dist/tools/schema-fragments.js +23 -13
- package/dist/tools/schema-fragments.js.map +1 -1
- package/dist/tools/upgrade.d.ts +40 -0
- package/dist/tools/upgrade.js +55 -0
- package/dist/tools/upgrade.js.map +1 -0
- package/dist/unity-install-discovery.d.ts +24 -0
- package/dist/unity-install-discovery.js +113 -4
- package/dist/unity-install-discovery.js.map +1 -1
- package/package.json +4 -3
- package/templates/mcp-wrapper.sh +35 -0
package/dist/dialog-dismiss.d.ts
CHANGED
|
@@ -72,6 +72,8 @@ export interface DismissProbeOptions {
|
|
|
72
72
|
* the modal is blocked (audit line, no click) unless this is set.
|
|
73
73
|
*/
|
|
74
74
|
allowUnsavedSceneDismiss: boolean;
|
|
75
|
+
/** Allow continuing through a non-matching Editor warning. Off by default. */
|
|
76
|
+
allowVersionMismatch: boolean;
|
|
75
77
|
/**
|
|
76
78
|
* M12 — optional abort signal. When fired while a probe is in flight, the
|
|
77
79
|
* underlying `execFile`/`execFileSync` child is killed so the loop can exit
|
|
@@ -108,8 +110,9 @@ export declare function tryDismissDialog(opts: DismissProbeOptions): Promise<Dis
|
|
|
108
110
|
* Strategy:
|
|
109
111
|
* 1. P/Invoke `EnumWindows` to enumerate every visible top-level window
|
|
110
112
|
* owned by `Unity.exe`.
|
|
111
|
-
* 2. For each,
|
|
112
|
-
*
|
|
113
|
+
* 2. For each, skip the main Editor window ({@link isUnityEditorWindowTitle}),
|
|
114
|
+
* normalize the title (alphanumeric lowercase) and match it against the
|
|
115
|
+
* embedded per-kind fragment table to classify it.
|
|
113
116
|
* 3. If the kind is in the blocked list → emit `blocked:<kind>` and skip
|
|
114
117
|
* the click. If the kind's token list is null → skip (not-found).
|
|
115
118
|
* 4. Walk child windows with `EnumChildWindows`, find a Button whose
|
|
@@ -127,25 +130,94 @@ export declare function tryDismissDialog(opts: DismissProbeOptions): Promise<Dis
|
|
|
127
130
|
* The token table is passed via stdin (one JSON blob) so the script body
|
|
128
131
|
* stays constant and testable; embedding it inline would bloat the assertion.
|
|
129
132
|
*/
|
|
130
|
-
export declare const WINDOWS_DISMISS_PS_SCRIPT = "\n$ErrorActionPreference = 'Stop'\ntry {\n if (-not ([System.Management.Automation.PSTypeName]'UnityOpenMcp.Dialogs.Dismisser').Type) {\n Add-Type -TypeDefinition @\"\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing System.Text;\nnamespace UnityOpenMcp.Dialogs {\n public static class Dismisser {\n public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);\n [DllImport(\"user32.dll\")] static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);\n [DllImport(\"user32.dll\", CharSet=CharSet.Unicode)] static extern int GetWindowTextW(IntPtr hWnd, StringBuilder lpString, int nMaxCount);\n [DllImport(\"user32.dll\", CharSet=CharSet.Unicode)] static extern int GetClassNameW(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);\n [DllImport(\"user32.dll\")] static extern bool IsWindowVisible(IntPtr hWnd);\n [DllImport(\"user32.dll\")] static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);\n [DllImport(\"user32.dll\")] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);\n [DllImport(\"user32.dll\", CharSet=CharSet.Unicode)] static extern IntPtr SendMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);\n const uint BM_CLICK = 0x00F5;\n static string Norm(string s) {\n var sb = new StringBuilder(s.Length);\n foreach (var ch in s) {\n if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {\n sb.Append(char.ToLowerInvariant(ch));\n }\n }\n return sb.ToString();\n }\n public static string TryDismiss(int[] unityPids, string tableJson) {\n var unityPidSet = new HashSet<uint>();\n for (int i = 0; i < unityPids.Length; i++) unityPidSet.Add((uint)unityPids[i]);\n var table = System.Text.Json.JsonSerializer.Deserialize<Types.Table>(tableJson);\n var candidates = new List<IntPtr>();\n var sb = new StringBuilder(512);\n EnumWindows((hWnd, lParam) => {\n if (!IsWindowVisible(hWnd)) return true;\n uint procId; GetWindowThreadProcessId(hWnd, out procId);\n if (!unityPidSet.Contains(procId)) return true;\n sb.Length = 0;\n GetWindowTextW(hWnd, sb, sb.Capacity);\n candidates.Add(hWnd);\n return true;\n }, IntPtr.Zero);\n foreach (var hWnd in candidates) {\n sb.Length = 0;\n GetWindowTextW(hWnd, sb, sb.Capacity);\n var title = sb.ToString();\n var norm = Norm(title);\n string kind = null;\n foreach (var kv in table.kinds) {\n foreach (var frag in kv.Value.fragments) {\n if (norm.Contains(frag)) { kind = kv.Key; break; }\n }\n if (kind != null) break;\n }\n string[] tokens = null;\n if (kind != null) {\n if (table.blocked.Contains(kind)) return \"blocked:\" + kind;\n if (!table.kinds[kind].tokensSpecified) continue;\n tokens = table.kinds[kind].tokens;\n } else {\n if (table.genericTokens.Length == 0) continue;\n tokens = table.genericTokens;\n }\n IntPtr matchedButton = IntPtr.Zero;\n string matchedText = null;\n EnumChildWindows(hWnd, (hChild, lParam) => {\n sb.Length = 0;\n GetClassNameW(hChild, sb, sb.Capacity);\n if (sb.ToString() != \"Button\") return true;\n sb.Length = 0;\n GetWindowTextW(hChild, sb, sb.Capacity);\n var text = sb.ToString();\n var textNorm = Norm(text);\n foreach (var token in tokens) {\n if (textNorm.Contains(token)) { matchedButton = hChild; matchedText = text; return false; }\n }\n return true;\n }, IntPtr.Zero);\n if (matchedButton == IntPtr.Zero) continue;\n SendMessageW(matchedButton, BM_CLICK, IntPtr.Zero, IntPtr.Zero);\n return \"dismissed:\" + matchedText + \":\" + (kind ?? \"unknown\");\n }\n return \"not-found\";\n }\n }\n}\n\"@\n }\n $unityPids = @(Get-Process -Name 'Unity' -ErrorAction SilentlyContinue | ForEach-Object { [int]$_.Id })\n if ($unityPids.Count -eq 0) { Write-Output 'not-found'; return }\n $tableJson = [Console]::In.ReadToEnd();\n Write-Output ([UnityOpenMcp.Dialogs.Dismisser]::TryDismiss([int[]]$unityPids, $tableJson))\n} catch {\n Write-Output ('error:' + $_.Exception.Message)\n}\n";
|
|
133
|
+
export declare const WINDOWS_DISMISS_PS_SCRIPT = "\n$ErrorActionPreference = 'Stop'\ntry {\n if (-not ([System.Management.Automation.PSTypeName]'UnityOpenMcp.Dialogs.Dismisser').Type) {\n Add-Type -TypeDefinition @\"\nusing System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing System.Text;\nnamespace UnityOpenMcp.Dialogs {\n public static class Dismisser {\n public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);\n [DllImport(\"user32.dll\")] static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);\n [DllImport(\"user32.dll\", CharSet=CharSet.Unicode)] static extern int GetWindowTextW(IntPtr hWnd, StringBuilder lpString, int nMaxCount);\n [DllImport(\"user32.dll\", CharSet=CharSet.Unicode)] static extern int GetClassNameW(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);\n [DllImport(\"user32.dll\")] static extern bool IsWindowVisible(IntPtr hWnd);\n [DllImport(\"user32.dll\")] static extern bool EnumChildWindows(IntPtr hWndParent, EnumWindowsProc lpEnumFunc, IntPtr lParam);\n [DllImport(\"user32.dll\")] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);\n [DllImport(\"user32.dll\", CharSet=CharSet.Unicode)] static extern IntPtr SendMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);\n const uint BM_CLICK = 0x00F5;\n static string Norm(string s) {\n var sb = new StringBuilder(s.Length);\n foreach (var ch in s) {\n if ((ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')) {\n sb.Append(char.ToLowerInvariant(ch));\n }\n }\n return sb.ToString();\n }\n public static string TryDismiss(int[] unityPids, string tableJson) {\n var unityPidSet = new HashSet<uint>();\n for (int i = 0; i < unityPids.Length; i++) unityPidSet.Add((uint)unityPids[i]);\n var table = System.Text.Json.JsonSerializer.Deserialize<Types.Table>(tableJson);\n var candidates = new List<IntPtr>();\n var sb = new StringBuilder(512);\n EnumWindows((hWnd, lParam) => {\n if (!IsWindowVisible(hWnd)) return true;\n uint procId; GetWindowThreadProcessId(hWnd, out procId);\n if (!unityPidSet.Contains(procId)) return true;\n sb.Length = 0;\n GetWindowTextW(hWnd, sb, sb.Capacity);\n candidates.Add(hWnd);\n return true;\n }, IntPtr.Zero);\n foreach (var hWnd in candidates) {\n sb.Length = 0;\n GetWindowTextW(hWnd, sb, sb.Capacity);\n var title = sb.ToString();\n // The main Editor window title embeds project/scene names; never classify it.\n if (title.IndexOf(\" - Unity \", StringComparison.OrdinalIgnoreCase) >= 0) continue;\n var norm = Norm(title);\n string kind = null;\n foreach (var kv in table.kinds) {\n foreach (var frag in kv.Value.fragments) {\n if (norm.Contains(frag)) { kind = kv.Key; break; }\n }\n if (kind != null) break;\n }\n string[] tokens = null;\n if (kind != null) {\n if (table.blocked.Contains(kind)) return \"blocked:\" + kind;\n if (!table.kinds[kind].tokensSpecified) continue;\n tokens = table.kinds[kind].tokens;\n } else {\n if (table.genericTokens.Length == 0) continue;\n tokens = table.genericTokens;\n }\n IntPtr matchedButton = IntPtr.Zero;\n string matchedText = null;\n EnumChildWindows(hWnd, (hChild, lParam) => {\n sb.Length = 0;\n GetClassNameW(hChild, sb, sb.Capacity);\n if (sb.ToString() != \"Button\") return true;\n sb.Length = 0;\n GetWindowTextW(hChild, sb, sb.Capacity);\n var text = sb.ToString();\n var textNorm = Norm(text);\n foreach (var token in tokens) {\n if (textNorm.Contains(token)) { matchedButton = hChild; matchedText = text; return false; }\n }\n return true;\n }, IntPtr.Zero);\n if (matchedButton == IntPtr.Zero) continue;\n SendMessageW(matchedButton, BM_CLICK, IntPtr.Zero, IntPtr.Zero);\n return \"dismissed:\" + matchedText + \":\" + (kind ?? \"unknown\");\n }\n return \"not-found\";\n }\n }\n}\n\"@\n }\n $unityPids = @(Get-Process -Name 'Unity' -ErrorAction SilentlyContinue | ForEach-Object { [int]$_.Id })\n if ($unityPids.Count -eq 0) { Write-Output 'not-found'; return }\n $tableJson = [Console]::In.ReadToEnd();\n Write-Output ([UnityOpenMcp.Dialogs.Dismisser]::TryDismiss([int[]]$unityPids, $tableJson))\n} catch {\n Write-Output ('error:' + $_.Exception.Message)\n}\n";
|
|
131
134
|
/**
|
|
132
135
|
* The AppleScript template used for the macOS dismiss path. Exposed as a
|
|
133
|
-
* function of the
|
|
136
|
+
* function of the probe options so tests can assert the script shape without
|
|
134
137
|
* launching osascript.
|
|
135
138
|
*
|
|
136
|
-
* Strategy: iterate every window of the Unity process
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
139
|
+
* Strategy: iterate every window of the Unity process except the main Editor
|
|
140
|
+
* window (its title contains {@link UNITY_EDITOR_WINDOW_TITLE_MARKER}),
|
|
141
|
+
* classify it by its title normalized with `normLabel` (see
|
|
142
|
+
* {@link macosTitleMatch}), and act per kind as {@link focusDialogAction}
|
|
143
|
+
* decides from the shared policy table (see {@link macosDialogKindBlock}):
|
|
144
|
+
*
|
|
145
|
+
* - `focus` — the policy picks the kind's focused/default button
|
|
146
|
+
* ({@link DIALOG_FOCUSED_BUTTON_TOKENS}): press Return, but
|
|
147
|
+
* only when the window shows a button with that label.
|
|
148
|
+
* - `named` — the policy picks another button (e.g. Enter Safe Mode, or
|
|
149
|
+
* Quit/Cancel under `cancel`): click the first button whose
|
|
150
|
+
* normalized title equals a policy token, in priority order,
|
|
151
|
+
* or report `blocked:<kind>` when none is found. Return is
|
|
152
|
+
* never pressed, because it would click the focused button.
|
|
153
|
+
* - `blocked` — the policy blocks the kind: report `blocked:<kind>`.
|
|
154
|
+
* - `skip` — the policy declines the kind: no block; the window falls
|
|
155
|
+
* through to `not-found` so polling continues.
|
|
156
|
+
*
|
|
157
|
+
* Project Upgrade is always reported as `blocked` (never clicked), and
|
|
158
|
+
* unsaved scene changes have their own named-button block behind the opt-in.
|
|
159
|
+
* If Unity is not running or nothing matches, the script reports `not-found`.
|
|
160
|
+
* Any AppleScript exception (e.g. Accessibility permission not granted) is
|
|
161
|
+
* reported as `error:<msg>`.
|
|
142
162
|
*
|
|
143
163
|
* Requires the Terminal / `node` binary to have been granted Accessibility
|
|
144
164
|
* permission in System Settings → Privacy & Security → Accessibility.
|
|
145
|
-
*
|
|
146
|
-
* The token table is JSON-escaped into the script header.
|
|
147
165
|
*/
|
|
148
166
|
export declare function macosDismissAppleScript(opts: DismissProbeOptions): string;
|
|
167
|
+
/**
|
|
168
|
+
* AppleScript mirror of {@link normalizeDialogLabel}: keep ASCII letters and
|
|
169
|
+
* digits only. AppleScript string comparison (`is`, `contains`) ignores case
|
|
170
|
+
* by default, so the handler does not lowercase. Exported for tests.
|
|
171
|
+
*/
|
|
172
|
+
export declare const MACOS_NORM_LABEL_HANDLER = "\n-- Mirror of normalizeDialogLabel: keep ASCII letters and digits only.\n-- (String comparison is case-insensitive by default, so no lowercasing.)\non normLabel(s)\n set out to \"\"\n repeat with c in (characters of s)\n set ch to contents of c\n set cid to id of ch\n -- \"id of\" yields a LIST for a character made of several code points\n -- (decomposed accents, emoji); comparing a list numerically would raise\n -- and abort the whole probe, so such characters are simply dropped.\n if class of cid is integer then\n if (cid >= 48 and cid <= 57) or (cid >= 65 and cid <= 90) or (cid >= 97 and cid <= 122) then set out to out & ch\n end if\n end repeat\n return out\nend normLabel\n";
|
|
173
|
+
/**
|
|
174
|
+
* How a focus-driven platform (macOS AppleScript, Linux xdotool) may act on a
|
|
175
|
+
* dialog of the given kind under the active policy. Derived from the shared
|
|
176
|
+
* policy table so every platform agrees:
|
|
177
|
+
*
|
|
178
|
+
* - `blocked` — the policy blocks the kind (e.g. Project Upgrade without its
|
|
179
|
+
* opt-in). Report `blocked:<kind>`, never click.
|
|
180
|
+
* - `skip` — the policy declines the kind (no preference tokens). Do
|
|
181
|
+
* nothing; try the next kind.
|
|
182
|
+
* - `focus` — the policy's first choice is the kind's focused button
|
|
183
|
+
* ({@link DIALOG_FOCUSED_BUTTON_TOKENS}): pressing Return is
|
|
184
|
+
* safe.
|
|
185
|
+
* - `named` — the policy's first choice is some other button (e.g. Enter
|
|
186
|
+
* Safe Mode, Quit, Cancel). Return would press the focused
|
|
187
|
+
* button instead, so only a named-button click may act.
|
|
188
|
+
*
|
|
189
|
+
* Pure; exported for tests.
|
|
190
|
+
*/
|
|
191
|
+
export declare function focusDialogAction(kind: DialogKind, opts: Pick<DismissProbeOptions, "policy" | "allowProjectUpgrade" | "allowUnsavedSceneDismiss" | "allowVersionMismatch">): "blocked" | "skip" | "focus" | "named";
|
|
192
|
+
/**
|
|
193
|
+
* AppleScript title condition per focus-classified kind, over `wn` — the
|
|
194
|
+
* window title normalized by `normLabel`. The fragments are normalized
|
|
195
|
+
* (letters and digits only), and AppleScript `contains` ignores case but not
|
|
196
|
+
* spaces or punctuation, so matching the raw title would never fire
|
|
197
|
+
* (`"Enter Safe Mode?" contains "safemode"` is false). Non-Matching Editor
|
|
198
|
+
* matches the short `nonmatchingeditor` stem so both the hyphenated and the
|
|
199
|
+
* spaced spelling qualify. Exported for tests.
|
|
200
|
+
*/
|
|
201
|
+
export declare function macosTitleMatch(kind: DialogKind): string;
|
|
202
|
+
/**
|
|
203
|
+
* AppleScript block for one dialog kind inside the window loop (`w` / `wt`),
|
|
204
|
+
* shaped by {@link focusDialogAction}:
|
|
205
|
+
*
|
|
206
|
+
* - `blocked` → `blocked:<kind>` when the title matches.
|
|
207
|
+
* - `skip` → a comment only; the window falls through.
|
|
208
|
+
* - `focus` → press Return on the focused button, when the window has a
|
|
209
|
+
* button whose normalized title equals the kind's focused
|
|
210
|
+
* token; otherwise fall through (no press).
|
|
211
|
+
* - `named` → for each policy token in priority order, click the first
|
|
212
|
+
* button whose normalized title equals it; if none matches,
|
|
213
|
+
* report `blocked:<kind>`. Never presses Return.
|
|
214
|
+
*
|
|
215
|
+
* Exact normalized equality (not substring) keeps a short token such as `no`
|
|
216
|
+
* from matching an unrelated label such as "Ignore".
|
|
217
|
+
*
|
|
218
|
+
* Pure; exported for tests.
|
|
219
|
+
*/
|
|
220
|
+
export declare function macosDialogKindBlock(kind: DialogKind, opts: Pick<DismissProbeOptions, "policy" | "allowProjectUpgrade" | "allowUnsavedSceneDismiss" | "allowVersionMismatch">): string;
|
|
149
221
|
/**
|
|
150
222
|
* Reset the cached `xdotool` presence flag. Test-only — production code
|
|
151
223
|
* never needs to call this.
|
|
@@ -157,6 +229,26 @@ export declare function _resetXdotoolPresenceForTests(): void;
|
|
|
157
229
|
* containing metacharacters would silently change the match semantics.
|
|
158
230
|
*/
|
|
159
231
|
export declare function regexEscapeForXdotool(s: string): string;
|
|
232
|
+
/**
|
|
233
|
+
* The `xdotool search --name` pattern for a normalized title fragment.
|
|
234
|
+
* Fragments are letters and digits only ("entersafemode"), while real titles
|
|
235
|
+
* carry spaces and punctuation ("Enter Safe Mode?"), so the pattern allows any
|
|
236
|
+
* run of non-alphanumerics between consecutive characters and spells each
|
|
237
|
+
* letter in both cases. That is the regex form of "the normalized title
|
|
238
|
+
* contains the fragment" and does not depend on xdotool's case handling.
|
|
239
|
+
* Any other character is escaped literally.
|
|
240
|
+
*/
|
|
241
|
+
export declare function xdotoolTitlePattern(fragment: string): string;
|
|
242
|
+
/**
|
|
243
|
+
* What the Linux/X11 path does with a Unity-owned window of the given kind:
|
|
244
|
+
* {@link focusDialogAction} with `named` folded into `blocked`, because
|
|
245
|
+
* xdotool can only press Return on the focused (default) button — it cannot
|
|
246
|
+
* click a named one (e.g. `cancel` on the Safe Mode prompt, whose focused
|
|
247
|
+
* button is Ignore, is reported as blocked for a human).
|
|
248
|
+
*
|
|
249
|
+
* Pure; exported for tests.
|
|
250
|
+
*/
|
|
251
|
+
export declare function linuxFocusAction(kind: DialogKind, opts: Pick<DismissProbeOptions, "policy" | "allowProjectUpgrade" | "allowUnsavedSceneDismiss" | "allowVersionMismatch">): "blocked" | "skip" | "focus";
|
|
160
252
|
/**
|
|
161
253
|
* Parse the single-token contract every platform-specific dispatcher writes
|
|
162
254
|
* to stdout. Inspects the LAST non-empty line of stdout, not the whole
|
|
@@ -206,6 +298,8 @@ export declare function armSigkillEscalation(child: {
|
|
|
206
298
|
* - `UNITY_OPEN_MCP_ALLOW_UNSAVED_SCENE_DISMISS=1` opts in to auto-dismissing
|
|
207
299
|
* the "Unsaved changes to scene" modal (destructive under every policy —
|
|
208
300
|
* off by default). See isUnsavedSceneBlocked.
|
|
301
|
+
* - `UNITY_OPEN_MCP_ALLOW_VERSION_MISMATCH=1` opts in to opening a project
|
|
302
|
+
* with a different Unity Editor version. Without it the dialog is blocked.
|
|
209
303
|
* - `UNITY_OPEN_MCP_DISMISS_TIMEOUT_MS` overrides the overall timeout.
|
|
210
304
|
* - `UNITY_OPEN_MCP_DISMISS_INTERVAL_MS` overrides the poll interval.
|
|
211
305
|
*
|
|
@@ -219,6 +313,7 @@ export interface DismissConfig {
|
|
|
219
313
|
policy: DialogPolicy;
|
|
220
314
|
allowProjectUpgrade: boolean;
|
|
221
315
|
allowUnsavedSceneDismiss: boolean;
|
|
316
|
+
allowVersionMismatch: boolean;
|
|
222
317
|
}
|
|
223
318
|
export declare function readDismissConfig(env?: NodeJS.ProcessEnv): DismissConfig;
|
|
224
319
|
/**
|
|
@@ -233,6 +328,7 @@ export interface PollAndDismissOptions {
|
|
|
233
328
|
policy: DialogPolicy;
|
|
234
329
|
allowProjectUpgrade: boolean;
|
|
235
330
|
allowUnsavedSceneDismiss: boolean;
|
|
331
|
+
allowVersionMismatch: boolean;
|
|
236
332
|
/**
|
|
237
333
|
* Override the platform — exposed for tests so the polling logic can be
|
|
238
334
|
* exercised across all three OS branches without hopping process.platform.
|