@akiojin/unity-mcp-server 5.2.1 → 5.3.2
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 +1 -0
- package/package.json +28 -40
- package/src/core/codeIndex.js +54 -7
- package/src/core/config.js +15 -1
- package/src/core/httpServer.js +30 -6
- package/src/core/indexBuildWorkerPool.js +57 -3
- package/src/core/indexWatcher.js +10 -4
- package/src/core/projectInfo.js +34 -12
- package/src/core/server.js +58 -27
- package/src/core/toolManifest.json +145 -629
- package/src/handlers/addressables/AddressablesAnalyzeToolHandler.js +14 -6
- package/src/handlers/addressables/AddressablesBuildToolHandler.js +6 -3
- package/src/handlers/addressables/AddressablesManageToolHandler.js +6 -3
- package/src/handlers/input/InputSystemControlToolHandler.js +1 -1
- package/src/handlers/input/InputTouchToolHandler.js +7 -3
- package/src/handlers/package/PackageManagerToolHandler.js +6 -3
- package/src/handlers/script/CodeIndexStatusToolHandler.js +37 -1
- package/src/handlers/script/CodeIndexUpdateToolHandler.js +1 -1
- package/src/handlers/script/ScriptEditSnippetToolHandler.js +1 -2
- package/src/handlers/script/ScriptEditStructuredToolHandler.js +6 -1
- package/src/handlers/script/ScriptRefactorRenameToolHandler.js +3 -1
- package/src/handlers/script/ScriptRefsFindToolHandler.js +22 -4
- package/src/handlers/script/ScriptRemoveSymbolToolHandler.js +6 -1
- package/src/handlers/script/ScriptSymbolsGetToolHandler.js +1 -1
- package/src/lsp/CSharpLspUtils.js +11 -3
- package/src/lsp/LspProcessManager.js +24 -5
- package/src/lsp/LspRpcClient.js +115 -23
- package/src/lsp/LspRpcClientSingleton.js +79 -2
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LspRpcClient } from './LspRpcClient.js';
|
|
2
|
+
import { LspProcessManager } from './LspProcessManager.js';
|
|
2
3
|
import { logger } from '../core/config.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -8,6 +9,9 @@ import { logger } from '../core/config.js';
|
|
|
8
9
|
|
|
9
10
|
let instance = null;
|
|
10
11
|
let currentProjectRoot = null;
|
|
12
|
+
let validationInstance = null;
|
|
13
|
+
let validationProjectRoot = null;
|
|
14
|
+
const isolatedInstances = new Map();
|
|
11
15
|
let heartbeatTimer = null;
|
|
12
16
|
|
|
13
17
|
export class LspRpcClientSingleton {
|
|
@@ -33,6 +37,50 @@ export class LspRpcClientSingleton {
|
|
|
33
37
|
return instance;
|
|
34
38
|
}
|
|
35
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Get or create an isolated LspRpcClient instance for validation.
|
|
42
|
+
* Uses a separate LSP process to avoid blocking on long-running requests.
|
|
43
|
+
* @param {string} projectRoot - Project root path
|
|
44
|
+
* @returns {Promise<LspRpcClient>} Isolated client instance
|
|
45
|
+
*/
|
|
46
|
+
static async getValidationInstance(projectRoot) {
|
|
47
|
+
if (validationInstance && validationProjectRoot !== projectRoot) {
|
|
48
|
+
logger.info('[LspRpcClientSingleton] validation projectRoot changed, resetting instance');
|
|
49
|
+
await LspRpcClientSingleton.#resetValidation();
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!validationInstance) {
|
|
53
|
+
const manager = new LspProcessManager({ shared: false });
|
|
54
|
+
validationInstance = new LspRpcClient(projectRoot, manager);
|
|
55
|
+
validationProjectRoot = projectRoot;
|
|
56
|
+
logger.info(`[LspRpcClientSingleton] created validation instance for ${projectRoot}`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return validationInstance;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Get or create an isolated LspRpcClient instance for a specific purpose.
|
|
64
|
+
* Each kind is backed by its own LSP process to avoid cross-tool blocking.
|
|
65
|
+
* @param {string} projectRoot - Project root path
|
|
66
|
+
* @param {string} kind - Purpose key (e.g., "symbols", "rename")
|
|
67
|
+
* @returns {Promise<LspRpcClient>} Isolated client instance
|
|
68
|
+
*/
|
|
69
|
+
static async getIsolatedInstance(projectRoot, kind) {
|
|
70
|
+
if (!kind) {
|
|
71
|
+
throw new Error('kind is required for isolated LSP instance');
|
|
72
|
+
}
|
|
73
|
+
const key = `${projectRoot}::${kind}`;
|
|
74
|
+
const existing = isolatedInstances.get(key);
|
|
75
|
+
if (existing) return existing;
|
|
76
|
+
|
|
77
|
+
const manager = new LspProcessManager({ shared: false });
|
|
78
|
+
const client = new LspRpcClient(projectRoot, manager);
|
|
79
|
+
isolatedInstances.set(key, client);
|
|
80
|
+
logger.info(`[LspRpcClientSingleton] created isolated instance (${kind}) for ${projectRoot}`);
|
|
81
|
+
return client;
|
|
82
|
+
}
|
|
83
|
+
|
|
36
84
|
/**
|
|
37
85
|
* Reset the singleton instance and stop the process.
|
|
38
86
|
*/
|
|
@@ -48,6 +96,35 @@ export class LspRpcClientSingleton {
|
|
|
48
96
|
currentProjectRoot = null;
|
|
49
97
|
logger.info('[LspRpcClientSingleton] instance reset');
|
|
50
98
|
}
|
|
99
|
+
await LspRpcClientSingleton.#resetValidation();
|
|
100
|
+
await LspRpcClientSingleton.#resetIsolated();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
static async #resetValidation() {
|
|
104
|
+
if (validationInstance) {
|
|
105
|
+
try {
|
|
106
|
+
await validationInstance.mgr.stop();
|
|
107
|
+
} catch (e) {
|
|
108
|
+
logger.warning(`[LspRpcClientSingleton] validation stop error: ${e.message}`);
|
|
109
|
+
}
|
|
110
|
+
validationInstance = null;
|
|
111
|
+
validationProjectRoot = null;
|
|
112
|
+
logger.info('[LspRpcClientSingleton] validation instance reset');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
static async #resetIsolated() {
|
|
117
|
+
if (isolatedInstances.size === 0) return;
|
|
118
|
+
const entries = Array.from(isolatedInstances.entries());
|
|
119
|
+
isolatedInstances.clear();
|
|
120
|
+
for (const [key, client] of entries) {
|
|
121
|
+
try {
|
|
122
|
+
await client.mgr.stop();
|
|
123
|
+
} catch (e) {
|
|
124
|
+
logger.warning(`[LspRpcClientSingleton] isolated stop error (${key}): ${e.message}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
logger.info('[LspRpcClientSingleton] isolated instances reset');
|
|
51
128
|
}
|
|
52
129
|
|
|
53
130
|
/**
|
|
@@ -66,8 +143,8 @@ export class LspRpcClientSingleton {
|
|
|
66
143
|
return;
|
|
67
144
|
}
|
|
68
145
|
try {
|
|
69
|
-
//
|
|
70
|
-
await instance.request('
|
|
146
|
+
// Lightweight ping to avoid heavy workspace scans
|
|
147
|
+
await instance.request('mcp/ping', {});
|
|
71
148
|
} catch (e) {
|
|
72
149
|
logger.warning(`[LspRpcClientSingleton] heartbeat failed: ${e.message}, resetting...`);
|
|
73
150
|
// Process is dead, reset instance for next request
|