unity-open-mcp 0.9.0 → 1.1.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 +27 -0
- package/dist/batch-spawn.js +218 -24
- package/dist/batch-spawn.js.map +1 -1
- package/dist/capabilities/build-capabilities.d.ts +10 -0
- package/dist/capabilities/build-capabilities.js +4 -0
- package/dist/capabilities/build-capabilities.js.map +1 -1
- package/dist/capabilities/capabilities-view.d.ts +48 -0
- package/dist/capabilities/capabilities-view.js +93 -0
- package/dist/capabilities/capabilities-view.js.map +1 -0
- 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/child-supervision.d.ts +34 -0
- package/dist/child-supervision.js +110 -0
- package/dist/child-supervision.js.map +1 -0
- package/dist/cli/cli.js +9 -0
- package/dist/cli/cli.js.map +1 -1
- package/dist/cli/commands.js +37 -4
- package/dist/cli/commands.js.map +1 -1
- package/dist/compressible-router.js +12 -1
- package/dist/compressible-router.js.map +1 -1
- package/dist/constants.d.ts +31 -1
- package/dist/constants.js +31 -1
- package/dist/constants.js.map +1 -1
- package/dist/dialog-dismiss.d.ts +11 -0
- package/dist/dialog-dismiss.js +59 -4
- package/dist/dialog-dismiss.js.map +1 -1
- package/dist/editor-wedge.d.ts +45 -0
- package/dist/editor-wedge.js +111 -0
- package/dist/editor-wedge.js.map +1 -0
- package/dist/event-stream.d.ts +19 -6
- package/dist/event-stream.js +139 -17
- package/dist/event-stream.js.map +1 -1
- package/dist/gate-error.d.ts +2 -0
- package/dist/gate-error.js +9 -0
- package/dist/gate-error.js.map +1 -1
- package/dist/instance-discovery.d.ts +23 -0
- package/dist/instance-discovery.js +47 -1
- package/dist/instance-discovery.js.map +1 -1
- package/dist/live-client.d.ts +40 -5
- package/dist/live-client.js +254 -36
- 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 +101 -19
- package/dist/process-diagnostics.js +197 -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/results.d.ts +8 -0
- package/dist/results.js +4 -1
- package/dist/results.js.map +1 -1
- package/dist/routers.js +4 -1
- package/dist/routers.js.map +1 -1
- 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/server.js +8 -2
- package/dist/server.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-hint.d.ts +36 -0
- package/dist/tool-hint.js +98 -0
- package/dist/tool-hint.js.map +1 -0
- package/dist/tool-router.d.ts +47 -2
- package/dist/tool-router.js +652 -71
- package/dist/tool-router.js.map +1 -1
- package/dist/tools/agent-capabilities.js +27 -1
- package/dist/tools/agent-capabilities.js.map +1 -1
- package/dist/tools/baseline-create.js +1 -1
- package/dist/tools/baseline-create.js.map +1 -1
- package/dist/tools/batch-execute.js +12 -1
- package/dist/tools/batch-execute.js.map +1 -1
- package/dist/tools/bridge-status.js +21 -1
- package/dist/tools/bridge-status.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 +36 -3
- package/dist/tools/execute-csharp.js.map +1 -1
- package/dist/tools/execute-menu.js +33 -2
- package/dist/tools/execute-menu.js.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +44 -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/invoke-method.js +15 -1
- package/dist/tools/invoke-method.js.map +1 -1
- 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 +36 -7
- package/dist/tools/read-compile-errors.js.map +1 -1
- package/dist/tools/regression-check.js +2 -1
- package/dist/tools/regression-check.js.map +1 -1
- package/dist/tools/resource-pressure.js +21 -10
- package/dist/tools/resource-pressure.js.map +1 -1
- package/dist/tools/run-tests.js +11 -2
- package/dist/tools/run-tests.js.map +1 -1
- package/dist/tools/scan-all.js +2 -2
- package/dist/tools/scan-all.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 +67 -2
- package/dist/unity-log.js +206 -8
- package/dist/unity-log.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,10 +6,27 @@
|
|
|
6
6
|
* misleading for a GUI-launched Unity on macOS (it inherits `launchctl limit
|
|
7
7
|
* maxfiles`, not the shell's ulimit). Documented in the tool response via
|
|
8
8
|
* `launchContextCaveat`.
|
|
9
|
+
*
|
|
10
|
+
* This is the DEFAULT used when a project has not overridden the ceiling via
|
|
11
|
+
* `.unity-open-mcp/settings.json` (`resourcePressure.fdCeiling`). The actual
|
|
12
|
+
* ceiling applied to a sample is resolved by `readFdCeiling` in
|
|
13
|
+
* `project-settings.ts` and threaded into `computeFdHeadroom` /
|
|
14
|
+
* `analyzeFdTrend` so the math scales with the configured value (relevant for
|
|
15
|
+
* Unity 6 / CoreCLR runtimes whose internal ceiling may differ from Mono's
|
|
16
|
+
* classic 1024).
|
|
17
|
+
*/
|
|
18
|
+
export declare const FD_CEILING_DEFAULT = 1024;
|
|
19
|
+
/**
|
|
20
|
+
* Absolute cap on the leak-detection threshold. The threshold is 10% of the
|
|
21
|
+
* resolved ceiling, but a very high configured ceiling (e.g. a CoreCLR runtime
|
|
22
|
+
* that legitimately sits over the Mono proxy) would otherwise push it so high
|
|
23
|
+
* that a real monotonic climb is missed — a climb of this many descriptors is a
|
|
24
|
+
* clear leak signal regardless of the ceiling. Kicks in once the ceiling exceeds
|
|
25
|
+
* ~5000 (10% of 5000 = 500).
|
|
9
26
|
*/
|
|
10
|
-
export declare const
|
|
27
|
+
export declare const FD_LEAK_DELTA_MAX = 500;
|
|
11
28
|
/**
|
|
12
|
-
* Headroom fraction (of
|
|
29
|
+
* Headroom fraction (of the resolved ceiling) at or below which the state is `warn`:
|
|
13
30
|
* the Editor is approaching the Mono ceiling and an agent should surface the
|
|
14
31
|
* trend so the operator can save + restart before the hang. ≥80% usage.
|
|
15
32
|
*/
|
|
@@ -51,15 +68,28 @@ export interface FdCountFailed {
|
|
|
51
68
|
message: string;
|
|
52
69
|
}
|
|
53
70
|
export type FdCountResult = FdCountOk | FdCountFailed;
|
|
54
|
-
/**
|
|
55
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Coarse pressure state derived from `computeFdHeadroom`.
|
|
73
|
+
*
|
|
74
|
+
* `over_ceiling` is informational, NOT an alarm: the OS-level fd count (from
|
|
75
|
+
* `lsof` / `/proc` / `HandleCount`) already exceeds the Mono-ceiling proxy, but
|
|
76
|
+
* `lsof` counts ALL OS file descriptors (mmap'd assets, file watchers, regular
|
|
77
|
+
* `FileStream` handles) while only descriptors registered with Mono's
|
|
78
|
+
* IOSelector count toward the real trip point. So an asset-heavy project can
|
|
79
|
+
* legitimately sit over the proxy ceiling on a fresh, healthy process. The
|
|
80
|
+
* actionable signal there is the TREND (`rising` / `leaking`), not the
|
|
81
|
+
* absolute. The router only raises an operator warning on `over_ceiling` when
|
|
82
|
+
* the trend is actively climbing; a stable/no-history over-ceiling process
|
|
83
|
+
* gets a `pressureNote` instead of a `warning`.
|
|
84
|
+
*/
|
|
85
|
+
export type FdPressureState = "ok" | "warn" | "critical" | "over_ceiling" | "unknown";
|
|
56
86
|
/** Headroom metric against the Mono fd ceiling. */
|
|
57
87
|
export interface FdHeadroom {
|
|
58
|
-
/** Open fds /
|
|
88
|
+
/** Open fds / ceiling, clamped to [0, 1] when count is known. */
|
|
59
89
|
pressureRatio: number;
|
|
60
|
-
/**
|
|
90
|
+
/** ceiling - count, clamped at 0. */
|
|
61
91
|
headroom: number;
|
|
62
|
-
/** The
|
|
92
|
+
/** The resolved ceiling (Mono ~1024 default, configurable per project). */
|
|
63
93
|
ceiling: number;
|
|
64
94
|
state: FdPressureState;
|
|
65
95
|
/** `false` when the underlying count was an approximation (Windows). */
|
|
@@ -73,6 +103,38 @@ export interface FdHeadroom {
|
|
|
73
103
|
export interface FdProbe {
|
|
74
104
|
count(pid: number): FdCountResult;
|
|
75
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Parse the stdout of a successful `lsof -p <pid>` run into an fd count.
|
|
108
|
+
* Pure (no I/O) so it can be unit-tested without spawning lsof. lsof prints
|
|
109
|
+
* a header line ("COMMAND PID USER FD TYPE ...") then one row per open file;
|
|
110
|
+
* only rows whose FD column is a numbered descriptor count (see
|
|
111
|
+
* {@link countLsofFdRows}). Empty stdout means the PID vanished between
|
|
112
|
+
* spawn and read.
|
|
113
|
+
*/
|
|
114
|
+
export declare function parseLsofStdout(stdout: string, pid: number): FdCountResult;
|
|
115
|
+
/**
|
|
116
|
+
* Classify a failed `lsof -p <pid>` invocation. Pure (no I/O). `lsof` exits
|
|
117
|
+
* non-zero for several reasons: the PID is gone (the common case), but also
|
|
118
|
+
* privilege boundaries / SIP-protected handles — and in those cases it still
|
|
119
|
+
* prints FD rows to stdout before exiting 1. Node's `execFileSync` attaches
|
|
120
|
+
* that captured stdout to the error object as `err.stdout`; when present and
|
|
121
|
+
* non-empty, parse it instead of reporting not_found. Only map to not_found
|
|
122
|
+
* when there is no usable stdout AND the message indicates the PID is truly
|
|
123
|
+
* absent — a bare "exit code: 1" is ambiguous (privilege errors also exit 1).
|
|
124
|
+
*
|
|
125
|
+
* Two guardrails on the captured-stdout path:
|
|
126
|
+
* - `err.stdout` is only parsed when it is genuinely a non-empty string.
|
|
127
|
+
* When execFileSync fails at spawn (ENOENT/EPERM) the property exists but
|
|
128
|
+
* is undefined/null; naive String() coercion turned that into the literal
|
|
129
|
+
* "undefined" — one "line" — which parsed as a confident count of ZERO
|
|
130
|
+
* fds, exactly the failed-probe-as-ok misreport FdCountFailed exists to
|
|
131
|
+
* prevent.
|
|
132
|
+
* - When the probe was killed by the FD_PROBE_TIMEOUT_MS timeout, any
|
|
133
|
+
* captured stdout is a PARTIAL listing (lsof was still writing). The
|
|
134
|
+
* parsed count is a lower bound, so it is flagged `approximate: true`
|
|
135
|
+
* instead of being reported as an exact count.
|
|
136
|
+
*/
|
|
137
|
+
export declare function classifyLsofError(err: unknown, pid: number): FdCountResult;
|
|
76
138
|
/** Read the active probe. Production callers use this via `countFileDescriptors`. */
|
|
77
139
|
export declare function getFdProbe(): FdProbe;
|
|
78
140
|
/**
|
|
@@ -91,7 +153,7 @@ export declare function setFdProbeForTest(fake: FdProbe | null): () => void;
|
|
|
91
153
|
*/
|
|
92
154
|
export declare function countFileDescriptors(pid: number): FdCountResult;
|
|
93
155
|
/**
|
|
94
|
-
* Pure headroom math against the
|
|
156
|
+
* Pure headroom math against the Mono fd ceiling. The OS soft limit
|
|
95
157
|
* (`ulimit -n`) is intentionally NOT used — it is a loose upper bound and is
|
|
96
158
|
* misleading for GUI-launched Unity on macOS (inherits `launchctl limit
|
|
97
159
|
* maxfiles`, not the shell ulimit).
|
|
@@ -99,8 +161,17 @@ export declare function countFileDescriptors(pid: number): FdCountResult;
|
|
|
99
161
|
* `null` count (probe failed) → `state: "unknown"` with `reliable: false`. An
|
|
100
162
|
* agent must NOT treat "unknown" as "ok"; it should surface the trend (if any
|
|
101
163
|
* prior samples exist) and tell the operator the live count could not be read.
|
|
164
|
+
*
|
|
165
|
+
* `over_ceiling` (count >= ceiling) is informational: the OS-level count
|
|
166
|
+
* exceeded the Mono-ceiling proxy, but `lsof` over-counts relative to the
|
|
167
|
+
* IOSelector-registered descriptors that actually trip the hang. The router
|
|
168
|
+
* decides whether to alarm based on the TREND, not this absolute state.
|
|
169
|
+
*
|
|
170
|
+
* @param ceiling the resolved fd ceiling (default {@link FD_CEILING_DEFAULT});
|
|
171
|
+
* passed in by the router from `readFdCeiling` so the math scales with a
|
|
172
|
+
* project-configured override.
|
|
102
173
|
*/
|
|
103
|
-
export declare function computeFdHeadroom(count: number | null, approximate?: boolean): FdHeadroom;
|
|
174
|
+
export declare function computeFdHeadroom(count: number | null, approximate?: boolean, ceiling?: number): FdHeadroom;
|
|
104
175
|
/** One fd sample recorded in the session-scoped ring. */
|
|
105
176
|
export interface FdSample {
|
|
106
177
|
/** Wall-clock timestamp (ms since epoch). */
|
|
@@ -121,9 +192,9 @@ export type FdTrendState = "no_history" | "stable" | "rising" | "leaking" | "unk
|
|
|
121
192
|
export interface FdTrend {
|
|
122
193
|
state: FdTrendState;
|
|
123
194
|
/**
|
|
124
|
-
* First-to-last delta in fd count (
|
|
125
|
-
* `null` when there are fewer than two samples
|
|
126
|
-
* same PID.
|
|
195
|
+
* First-to-last delta in fd count (positive for a leak — the count grew;
|
|
196
|
+
* negative when it shrank). `null` when there are fewer than two samples
|
|
197
|
+
* with known counts for the same PID.
|
|
127
198
|
*/
|
|
128
199
|
delta: number | null;
|
|
129
200
|
/** Number of samples used for the trend (same-PID, known-count). */
|
|
@@ -132,15 +203,26 @@ export interface FdTrend {
|
|
|
132
203
|
/**
|
|
133
204
|
* Pure trend detector over a sample list. Only considers samples with a known
|
|
134
205
|
* count for the SAME pid (a Unity restart changes the PID; the trend must not
|
|
135
|
-
* mix pre- and post-restart samples). A
|
|
136
|
-
*
|
|
137
|
-
*
|
|
206
|
+
* mix pre- and post-restart samples). A strictly non-decreasing climb of at
|
|
207
|
+
* least the leak threshold (10% of the ceiling, capped at
|
|
208
|
+
* {@link FD_LEAK_DELTA_MAX}) across ≥2 samples is `leaking`; any other
|
|
209
|
+
* net-positive first-to-last delta (a non-monotonic climb, or a monotonic climb
|
|
210
|
+
* below the threshold) is `rising`; otherwise `stable`. Fewer than two usable
|
|
211
|
+
* samples → `no_history`. `leaking` is the actionable signal; `rising` is drift.
|
|
212
|
+
*
|
|
213
|
+
* @param ceiling the resolved fd ceiling (default {@link FD_CEILING_DEFAULT});
|
|
214
|
+
* the leak threshold scales with it (capped at {@link FD_LEAK_DELTA_MAX}) so a
|
|
215
|
+
* project that configures a higher ceiling (e.g. a CoreCLR runtime) does not
|
|
216
|
+
* flag normal growth as a leak — while a very high ceiling cannot blind the
|
|
217
|
+
* detector to a real climb.
|
|
138
218
|
*/
|
|
139
|
-
export declare function analyzeFdTrend(samples: readonly FdSample[]): FdTrend;
|
|
219
|
+
export declare function analyzeFdTrend(samples: readonly FdSample[], ceiling?: number): FdTrend;
|
|
140
220
|
/**
|
|
141
221
|
* Caveat string surfaced in the resource_pressure response so an agent (and
|
|
142
|
-
* the operator) understand the launch-context nuance: the Mono ceiling, not
|
|
143
|
-
*
|
|
144
|
-
* `launchctl limit maxfiles` (macOS) rather than the shell's ulimit.
|
|
222
|
+
* the operator) understand the launch-context nuance: the Mono ceiling, not the
|
|
223
|
+
* OS soft limit, is the trip point; a GUI-launched Unity inherits
|
|
224
|
+
* `launchctl limit maxfiles` (macOS) rather than the shell's ulimit. The
|
|
225
|
+
* resolved ceiling applied to the sample is reported separately in the
|
|
226
|
+
* response's `ceiling` / `ceilingSource` fields.
|
|
145
227
|
*/
|
|
146
228
|
export declare const LAUNCH_CONTEXT_CAVEAT: string;
|
|
@@ -16,8 +16,9 @@
|
|
|
16
16
|
// that is the real trip point for the Bee build-driver hang. The OS
|
|
17
17
|
// `ulimit -n` soft limit is only a loose upper bound and is misleading on
|
|
18
18
|
// macOS: a GUI-launched Unity inherits `launchctl limit maxfiles`, not the
|
|
19
|
-
// MCP server's shell `ulimit`. So we measure headroom against the
|
|
20
|
-
//
|
|
19
|
+
// MCP server's shell `ulimit`. So we measure headroom against the Mono
|
|
20
|
+
// ceiling (default FD_CEILING_DEFAULT = 1024, configurable per project via
|
|
21
|
+
// `.unity-open-mcp/settings.json`), not the variable OS limit.
|
|
21
22
|
//
|
|
22
23
|
// Cross-platform probe:
|
|
23
24
|
// - macOS: `lsof -p <pid>` (no /proc on macOS). Bounded execFileSync
|
|
@@ -36,10 +37,27 @@ import { readdirSync } from "node:fs";
|
|
|
36
37
|
* misleading for a GUI-launched Unity on macOS (it inherits `launchctl limit
|
|
37
38
|
* maxfiles`, not the shell's ulimit). Documented in the tool response via
|
|
38
39
|
* `launchContextCaveat`.
|
|
40
|
+
*
|
|
41
|
+
* This is the DEFAULT used when a project has not overridden the ceiling via
|
|
42
|
+
* `.unity-open-mcp/settings.json` (`resourcePressure.fdCeiling`). The actual
|
|
43
|
+
* ceiling applied to a sample is resolved by `readFdCeiling` in
|
|
44
|
+
* `project-settings.ts` and threaded into `computeFdHeadroom` /
|
|
45
|
+
* `analyzeFdTrend` so the math scales with the configured value (relevant for
|
|
46
|
+
* Unity 6 / CoreCLR runtimes whose internal ceiling may differ from Mono's
|
|
47
|
+
* classic 1024).
|
|
48
|
+
*/
|
|
49
|
+
export const FD_CEILING_DEFAULT = 1024;
|
|
50
|
+
/**
|
|
51
|
+
* Absolute cap on the leak-detection threshold. The threshold is 10% of the
|
|
52
|
+
* resolved ceiling, but a very high configured ceiling (e.g. a CoreCLR runtime
|
|
53
|
+
* that legitimately sits over the Mono proxy) would otherwise push it so high
|
|
54
|
+
* that a real monotonic climb is missed — a climb of this many descriptors is a
|
|
55
|
+
* clear leak signal regardless of the ceiling. Kicks in once the ceiling exceeds
|
|
56
|
+
* ~5000 (10% of 5000 = 500).
|
|
39
57
|
*/
|
|
40
|
-
export const
|
|
58
|
+
export const FD_LEAK_DELTA_MAX = 500;
|
|
41
59
|
/**
|
|
42
|
-
* Headroom fraction (of
|
|
60
|
+
* Headroom fraction (of the resolved ceiling) at or below which the state is `warn`:
|
|
43
61
|
* the Editor is approaching the Mono ceiling and an agent should surface the
|
|
44
62
|
* trend so the operator can save + restart before the hang. ≥80% usage.
|
|
45
63
|
*/
|
|
@@ -54,54 +72,140 @@ export const FD_PROBE_TIMEOUT_MS = 3_000;
|
|
|
54
72
|
// ---------------------------------------------------------------------------
|
|
55
73
|
// Platform-specific probe implementations.
|
|
56
74
|
// ---------------------------------------------------------------------------
|
|
57
|
-
/**
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Count the actual file-descriptor rows in an `lsof -p` listing. Not every
|
|
77
|
+
* output row is an fd: `cwd` (working directory), `txt` (mapped executable and
|
|
78
|
+
* shared libraries — often dozens of rows on a loaded Editor), `rtd`, `del`,
|
|
79
|
+
* `ltz`/`ltx` rows describe directories and mmaps that Mono's IOSelector never
|
|
80
|
+
* registers. Counting every row systematically inflated the absolute fd count
|
|
81
|
+
* against the ~1024 Mono ceiling (an asset-heavy Editor maps hundreds of
|
|
82
|
+
* `txt` rows alone), skewing the warn/critical ratio states. The FD column
|
|
83
|
+
* index is located from the header; a row counts when its FD value starts with
|
|
84
|
+
* a digit (real fds are "0u"/"1w"/"255r"-style — number plus optional
|
|
85
|
+
* mode/lock letters). When no recognizable header exists (unusual), fall back
|
|
86
|
+
* to counting all rows so the probe never under-reports to zero.
|
|
87
|
+
*/
|
|
88
|
+
function countLsofFdRows(lines) {
|
|
89
|
+
if (lines.length === 0)
|
|
90
|
+
return 0;
|
|
91
|
+
const header = lines[0].trim().split(/\s+/);
|
|
92
|
+
const fdCol = header.indexOf("FD");
|
|
93
|
+
let count = 0;
|
|
94
|
+
for (let i = 1; i < lines.length; i++) {
|
|
95
|
+
if (fdCol >= 0) {
|
|
96
|
+
const fd = lines[i].trim().split(/\s+/)[fdCol];
|
|
97
|
+
if (fd !== undefined && /^\d/.test(fd))
|
|
98
|
+
count++;
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
count++;
|
|
77
102
|
}
|
|
103
|
+
}
|
|
104
|
+
return count;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Parse the stdout of a successful `lsof -p <pid>` run into an fd count.
|
|
108
|
+
* Pure (no I/O) so it can be unit-tested without spawning lsof. lsof prints
|
|
109
|
+
* a header line ("COMMAND PID USER FD TYPE ...") then one row per open file;
|
|
110
|
+
* only rows whose FD column is a numbered descriptor count (see
|
|
111
|
+
* {@link countLsofFdRows}). Empty stdout means the PID vanished between
|
|
112
|
+
* spawn and read.
|
|
113
|
+
*/
|
|
114
|
+
export function parseLsofStdout(stdout, pid) {
|
|
115
|
+
const lines = stdout.split(/\r?\n/).filter((l) => l.length > 0);
|
|
116
|
+
if (lines.length === 0) {
|
|
117
|
+
return {
|
|
118
|
+
count: null,
|
|
119
|
+
method: "lsof",
|
|
120
|
+
reason: "not_found",
|
|
121
|
+
message: `lsof produced no output for PID ${pid}.`,
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
return {
|
|
125
|
+
count: countLsofFdRows(lines),
|
|
126
|
+
method: "lsof",
|
|
127
|
+
approximate: false,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Classify a failed `lsof -p <pid>` invocation. Pure (no I/O). `lsof` exits
|
|
132
|
+
* non-zero for several reasons: the PID is gone (the common case), but also
|
|
133
|
+
* privilege boundaries / SIP-protected handles — and in those cases it still
|
|
134
|
+
* prints FD rows to stdout before exiting 1. Node's `execFileSync` attaches
|
|
135
|
+
* that captured stdout to the error object as `err.stdout`; when present and
|
|
136
|
+
* non-empty, parse it instead of reporting not_found. Only map to not_found
|
|
137
|
+
* when there is no usable stdout AND the message indicates the PID is truly
|
|
138
|
+
* absent — a bare "exit code: 1" is ambiguous (privilege errors also exit 1).
|
|
139
|
+
*
|
|
140
|
+
* Two guardrails on the captured-stdout path:
|
|
141
|
+
* - `err.stdout` is only parsed when it is genuinely a non-empty string.
|
|
142
|
+
* When execFileSync fails at spawn (ENOENT/EPERM) the property exists but
|
|
143
|
+
* is undefined/null; naive String() coercion turned that into the literal
|
|
144
|
+
* "undefined" — one "line" — which parsed as a confident count of ZERO
|
|
145
|
+
* fds, exactly the failed-probe-as-ok misreport FdCountFailed exists to
|
|
146
|
+
* prevent.
|
|
147
|
+
* - When the probe was killed by the FD_PROBE_TIMEOUT_MS timeout, any
|
|
148
|
+
* captured stdout is a PARTIAL listing (lsof was still writing). The
|
|
149
|
+
* parsed count is a lower bound, so it is flagged `approximate: true`
|
|
150
|
+
* instead of being reported as an exact count.
|
|
151
|
+
*/
|
|
152
|
+
export function classifyLsofError(err, pid) {
|
|
153
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
154
|
+
const errObj = err && typeof err === "object"
|
|
155
|
+
? err
|
|
156
|
+
: undefined;
|
|
157
|
+
const capturedStdout = typeof errObj?.stdout === "string" ? errObj.stdout : "";
|
|
158
|
+
// execFileSync timeout: Node kills the child (SIGTERM by default) and sets
|
|
159
|
+
// `code: "ETIMEDOUT"` / `killed: true` on the error. Stdout captured up to
|
|
160
|
+
// that point is a partial fd listing.
|
|
161
|
+
const timedOut = errObj?.code === "ETIMEDOUT" ||
|
|
162
|
+
(errObj?.killed === true && typeof errObj?.signal === "string");
|
|
163
|
+
const capturedLines = capturedStdout.split(/\r?\n/).filter((l) => l.length > 0);
|
|
164
|
+
if (capturedLines.length > 0) {
|
|
165
|
+
return {
|
|
166
|
+
count: countLsofFdRows(capturedLines),
|
|
167
|
+
method: "lsof",
|
|
168
|
+
approximate: timedOut,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (timedOut) {
|
|
78
172
|
return {
|
|
79
173
|
count: null,
|
|
80
174
|
method: "lsof",
|
|
81
175
|
reason: "lsof_failed",
|
|
82
|
-
message: `lsof
|
|
176
|
+
message: `lsof timed out after ${FD_PROBE_TIMEOUT_MS}ms for PID ${pid} with no output.`,
|
|
83
177
|
};
|
|
84
178
|
}
|
|
85
|
-
|
|
86
|
-
// one line per open fd. Subtract the header. An empty/blank stdout means the
|
|
87
|
-
// PID vanished between the spawn and the read — treat as not_found.
|
|
88
|
-
const lines = stdout.split(/\r?\n/).filter((l) => l.length > 0);
|
|
89
|
-
if (lines.length === 0) {
|
|
179
|
+
if (/no such file|no process|not found/i.test(message)) {
|
|
90
180
|
return {
|
|
91
181
|
count: null,
|
|
92
182
|
method: "lsof",
|
|
93
183
|
reason: "not_found",
|
|
94
|
-
message: `lsof
|
|
184
|
+
message: `lsof reported no process for PID ${pid}.`,
|
|
95
185
|
};
|
|
96
186
|
}
|
|
97
|
-
// Header is the first line; its FD column says "FD" literally. The rest are
|
|
98
|
-
// per-fd rows. Subtract 1 for the header.
|
|
99
187
|
return {
|
|
100
|
-
count:
|
|
188
|
+
count: null,
|
|
101
189
|
method: "lsof",
|
|
102
|
-
|
|
190
|
+
reason: "lsof_failed",
|
|
191
|
+
message: `lsof failed for PID ${pid}: ${message}`,
|
|
103
192
|
};
|
|
104
193
|
}
|
|
194
|
+
/** macOS `lsof -p <pid>` scanner. Returns the line count (one line per fd). */
|
|
195
|
+
function probeMacos(pid) {
|
|
196
|
+
let stdout;
|
|
197
|
+
try {
|
|
198
|
+
stdout = execFileSync("lsof", ["-p", String(pid)], {
|
|
199
|
+
encoding: "utf8",
|
|
200
|
+
timeout: FD_PROBE_TIMEOUT_MS,
|
|
201
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
catch (err) {
|
|
205
|
+
return classifyLsofError(err, pid);
|
|
206
|
+
}
|
|
207
|
+
return parseLsofStdout(stdout, pid);
|
|
208
|
+
}
|
|
105
209
|
/** Linux `/proc/<pid>/fd` directory entry count (no shell-out). */
|
|
106
210
|
function probeLinux(pid) {
|
|
107
211
|
let entries;
|
|
@@ -236,7 +340,7 @@ export function countFileDescriptors(pid) {
|
|
|
236
340
|
return currentProbe.count(pid);
|
|
237
341
|
}
|
|
238
342
|
/**
|
|
239
|
-
* Pure headroom math against the
|
|
343
|
+
* Pure headroom math against the Mono fd ceiling. The OS soft limit
|
|
240
344
|
* (`ulimit -n`) is intentionally NOT used — it is a loose upper bound and is
|
|
241
345
|
* misleading for GUI-launched Unity on macOS (inherits `launchctl limit
|
|
242
346
|
* maxfiles`, not the shell ulimit).
|
|
@@ -244,22 +348,38 @@ export function countFileDescriptors(pid) {
|
|
|
244
348
|
* `null` count (probe failed) → `state: "unknown"` with `reliable: false`. An
|
|
245
349
|
* agent must NOT treat "unknown" as "ok"; it should surface the trend (if any
|
|
246
350
|
* prior samples exist) and tell the operator the live count could not be read.
|
|
351
|
+
*
|
|
352
|
+
* `over_ceiling` (count >= ceiling) is informational: the OS-level count
|
|
353
|
+
* exceeded the Mono-ceiling proxy, but `lsof` over-counts relative to the
|
|
354
|
+
* IOSelector-registered descriptors that actually trip the hang. The router
|
|
355
|
+
* decides whether to alarm based on the TREND, not this absolute state.
|
|
356
|
+
*
|
|
357
|
+
* @param ceiling the resolved fd ceiling (default {@link FD_CEILING_DEFAULT});
|
|
358
|
+
* passed in by the router from `readFdCeiling` so the math scales with a
|
|
359
|
+
* project-configured override.
|
|
247
360
|
*/
|
|
248
|
-
export function computeFdHeadroom(count, approximate = false) {
|
|
361
|
+
export function computeFdHeadroom(count, approximate = false, ceiling = FD_CEILING_DEFAULT) {
|
|
249
362
|
if (count === null || !Number.isFinite(count)) {
|
|
250
363
|
return {
|
|
251
364
|
pressureRatio: 0,
|
|
252
|
-
headroom:
|
|
253
|
-
ceiling
|
|
365
|
+
headroom: ceiling,
|
|
366
|
+
ceiling,
|
|
254
367
|
state: "unknown",
|
|
255
368
|
reliable: false,
|
|
256
369
|
};
|
|
257
370
|
}
|
|
258
371
|
const clamped = Math.max(0, count);
|
|
259
|
-
const pressureRatio = Math.min(1, clamped /
|
|
260
|
-
const headroom = Math.max(0,
|
|
372
|
+
const pressureRatio = Math.min(1, clamped / ceiling);
|
|
373
|
+
const headroom = Math.max(0, ceiling - clamped);
|
|
261
374
|
let state;
|
|
262
|
-
if (
|
|
375
|
+
if (clamped >= ceiling) {
|
|
376
|
+
// OS-level fd count already past the Mono-ceiling proxy. Informational,
|
|
377
|
+
// not an alarm — `lsof` over-counts (mmap/assets/watchers) vs the
|
|
378
|
+
// IOSelector-registered descriptors that trip the hang. The router keys
|
|
379
|
+
// the operator warning off the TREND for this state.
|
|
380
|
+
state = "over_ceiling";
|
|
381
|
+
}
|
|
382
|
+
else if (approximate) {
|
|
263
383
|
// Windows HandleCount is naturally higher than Unix fds — only flag
|
|
264
384
|
// critical, never warn, so an agent does not over-react.
|
|
265
385
|
state = pressureRatio >= FD_CRITICAL_RATIO ? "critical" : "ok";
|
|
@@ -276,7 +396,7 @@ export function computeFdHeadroom(count, approximate = false) {
|
|
|
276
396
|
return {
|
|
277
397
|
pressureRatio,
|
|
278
398
|
headroom,
|
|
279
|
-
ceiling
|
|
399
|
+
ceiling,
|
|
280
400
|
state,
|
|
281
401
|
reliable: !approximate,
|
|
282
402
|
};
|
|
@@ -284,11 +404,20 @@ export function computeFdHeadroom(count, approximate = false) {
|
|
|
284
404
|
/**
|
|
285
405
|
* Pure trend detector over a sample list. Only considers samples with a known
|
|
286
406
|
* count for the SAME pid (a Unity restart changes the PID; the trend must not
|
|
287
|
-
* mix pre- and post-restart samples). A
|
|
288
|
-
*
|
|
289
|
-
*
|
|
407
|
+
* mix pre- and post-restart samples). A strictly non-decreasing climb of at
|
|
408
|
+
* least the leak threshold (10% of the ceiling, capped at
|
|
409
|
+
* {@link FD_LEAK_DELTA_MAX}) across ≥2 samples is `leaking`; any other
|
|
410
|
+
* net-positive first-to-last delta (a non-monotonic climb, or a monotonic climb
|
|
411
|
+
* below the threshold) is `rising`; otherwise `stable`. Fewer than two usable
|
|
412
|
+
* samples → `no_history`. `leaking` is the actionable signal; `rising` is drift.
|
|
413
|
+
*
|
|
414
|
+
* @param ceiling the resolved fd ceiling (default {@link FD_CEILING_DEFAULT});
|
|
415
|
+
* the leak threshold scales with it (capped at {@link FD_LEAK_DELTA_MAX}) so a
|
|
416
|
+
* project that configures a higher ceiling (e.g. a CoreCLR runtime) does not
|
|
417
|
+
* flag normal growth as a leak — while a very high ceiling cannot blind the
|
|
418
|
+
* detector to a real climb.
|
|
290
419
|
*/
|
|
291
|
-
export function analyzeFdTrend(samples) {
|
|
420
|
+
export function analyzeFdTrend(samples, ceiling = FD_CEILING_DEFAULT) {
|
|
292
421
|
if (samples.length === 0) {
|
|
293
422
|
return { state: "no_history", delta: null, sampleCount: 0 };
|
|
294
423
|
}
|
|
@@ -301,9 +430,11 @@ export function analyzeFdTrend(samples) {
|
|
|
301
430
|
const first = usable[0].count;
|
|
302
431
|
const last = usable[usable.length - 1].count;
|
|
303
432
|
const delta = last - first;
|
|
304
|
-
// `
|
|
305
|
-
// ≥ the
|
|
306
|
-
//
|
|
433
|
+
// `leaking` = strictly non-decreasing across all usable samples AND the total
|
|
434
|
+
// climb ≥ the leak threshold (10% of the ceiling, capped at FD_LEAK_DELTA_MAX)
|
|
435
|
+
// — a meaningful monotonic leak. `rising` = a net-positive first-to-last delta
|
|
436
|
+
// that does NOT qualify as a leak (non-monotonic, or a monotonic climb below
|
|
437
|
+
// the threshold) — drift / measurement noise, not actionable by itself.
|
|
307
438
|
let monotonic = true;
|
|
308
439
|
for (let i = 1; i < usable.length; i++) {
|
|
309
440
|
if (usable[i].count < usable[i - 1].count) {
|
|
@@ -311,7 +442,8 @@ export function analyzeFdTrend(samples) {
|
|
|
311
442
|
break;
|
|
312
443
|
}
|
|
313
444
|
}
|
|
314
|
-
|
|
445
|
+
const leakThreshold = Math.min(ceiling * 0.1, FD_LEAK_DELTA_MAX);
|
|
446
|
+
if (monotonic && delta >= leakThreshold) {
|
|
315
447
|
return { state: "leaking", delta, sampleCount: usable.length };
|
|
316
448
|
}
|
|
317
449
|
if (delta > 0) {
|
|
@@ -321,13 +453,19 @@ export function analyzeFdTrend(samples) {
|
|
|
321
453
|
}
|
|
322
454
|
/**
|
|
323
455
|
* Caveat string surfaced in the resource_pressure response so an agent (and
|
|
324
|
-
* the operator) understand the launch-context nuance: the Mono ceiling, not
|
|
325
|
-
*
|
|
326
|
-
* `launchctl limit maxfiles` (macOS) rather than the shell's ulimit.
|
|
456
|
+
* the operator) understand the launch-context nuance: the Mono ceiling, not the
|
|
457
|
+
* OS soft limit, is the trip point; a GUI-launched Unity inherits
|
|
458
|
+
* `launchctl limit maxfiles` (macOS) rather than the shell's ulimit. The
|
|
459
|
+
* resolved ceiling applied to the sample is reported separately in the
|
|
460
|
+
* response's `ceiling` / `ceilingSource` fields.
|
|
327
461
|
*/
|
|
328
|
-
export const LAUNCH_CONTEXT_CAVEAT = "Headroom is measured against Mono's internal
|
|
329
|
-
"(the real trip point for the Bee build-driver hang),
|
|
330
|
-
"(ulimit -n / launchctl limit maxfiles). A GUI-launched
|
|
331
|
-
"desktop environment's file limit, not the MCP server's
|
|
332
|
-
"OS soft limit is only a loose upper bound."
|
|
462
|
+
export const LAUNCH_CONTEXT_CAVEAT = "Headroom is measured against the Mono runtime's internal file-descriptor " +
|
|
463
|
+
"ceiling (default ~1024 — the real trip point for the Bee build-driver hang), " +
|
|
464
|
+
"NOT the OS soft limit (ulimit -n / launchctl limit maxfiles). A GUI-launched " +
|
|
465
|
+
"Unity inherits the desktop environment's file limit, not the MCP server's " +
|
|
466
|
+
"shell limit, so the OS soft limit is only a loose upper bound. The ceiling " +
|
|
467
|
+
"is configurable per project via `.unity-open-mcp/settings.json` " +
|
|
468
|
+
"(`resourcePressure.fdCeiling`) for runtimes whose internal limit differs " +
|
|
469
|
+
"from Mono's classic 1024 (e.g. Unity 6 / CoreCLR); the resolved value and " +
|
|
470
|
+
"its source are in the response's `ceiling` and `ceilingSource` fields.";
|
|
333
471
|
//# sourceMappingURL=process-diagnostics.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"process-diagnostics.js","sourceRoot":"","sources":["../src/process-diagnostics.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,eAAe;AACf,EAAE;AACF,+EAA+E;AAC/E,8EAA8E;AAC9E,6EAA6E;AAC7E,6EAA6E;AAC7E,8EAA8E;AAC9E,yEAAyE;AACzE,sBAAsB;AACtB,EAAE;AACF,4EAA4E;AAC5E,EAAE;AACF,8EAA8E;AAC9E,2EAA2E;AAC3E,sEAAsE;AACtE,4EAA4E;AAC5E,6EAA6E;AAC7E,
|
|
1
|
+
{"version":3,"file":"process-diagnostics.js","sourceRoot":"","sources":["../src/process-diagnostics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/** Below this configured ceiling the value is rejected → default. */
|
|
2
|
+
export declare const FD_CEILING_MIN = 64;
|
|
3
|
+
/** Above this configured ceiling the value is clamped down. */
|
|
4
|
+
export declare const FD_CEILING_MAX = 1000000;
|
|
5
|
+
/**
|
|
6
|
+
* The `resourcePressure` slice. `JsonUtility` on the C# side ignores it; this
|
|
7
|
+
* module is the only reader. Optional end-to-end so a missing slice falls back
|
|
8
|
+
* to the default ceiling.
|
|
9
|
+
*/
|
|
10
|
+
export interface ResourcePressureSettings {
|
|
11
|
+
fdCeiling?: number;
|
|
12
|
+
}
|
|
13
|
+
/** Result of resolving the fd ceiling for a project. */
|
|
14
|
+
export interface FdCeilingResolution {
|
|
15
|
+
/** The fd ceiling to apply (already clamped into range). */
|
|
16
|
+
ceiling: number;
|
|
17
|
+
/** `"config"` when a valid in-range value was read; `"default"` otherwise. */
|
|
18
|
+
source: "default" | "config";
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the settings file path for a project root. Exported for tests.
|
|
22
|
+
* `resolve` (not `join`) anchors a RELATIVE project path against the server's
|
|
23
|
+
* cwd instead of producing a relative path that would be re-interpreted by
|
|
24
|
+
* later read calls — matching how every other project-rooted path is resolved.
|
|
25
|
+
*/
|
|
26
|
+
export declare function settingsFilePath(projectPath: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Read the fd ceiling for a project from `.unity-open-mcp/settings.json`.
|
|
29
|
+
* Never throws: missing file, unparseable JSON, missing slice, or an invalid
|
|
30
|
+
* value all fall back to {@link FD_CEILING_DEFAULT} with `source: "default"`.
|
|
31
|
+
*
|
|
32
|
+
* Reads fresh on every call — `resource_pressure` is invoked infrequently
|
|
33
|
+
* (after heavy automation), and fresh reads let an operator change the setting
|
|
34
|
+
* without restarting the MCP server.
|
|
35
|
+
*/
|
|
36
|
+
export declare function readFdCeiling(projectPath: string): FdCeilingResolution;
|