@akiojin/unity-mcp-server 2.25.0 → 2.26.1
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/package.json +1 -1
- package/src/core/codeIndexDb.js +26 -10
- package/src/core/config.js +242 -242
- package/src/core/projectInfo.js +19 -10
- package/src/core/server.js +88 -65
- package/src/core/transports/HybridStdioServerTransport.js +179 -0
- package/src/core/unityConnection.js +52 -45
- package/src/handlers/addressables/AddressablesAnalyzeToolHandler.js +59 -49
- package/src/handlers/addressables/AddressablesBuildToolHandler.js +63 -62
- package/src/handlers/addressables/AddressablesManageToolHandler.js +84 -78
- package/src/handlers/base/BaseToolHandler.js +5 -5
- package/src/handlers/component/ComponentFieldSetToolHandler.js +419 -419
- package/src/handlers/console/ConsoleReadToolHandler.js +56 -66
- package/src/handlers/editor/EditorSelectionManageToolHandler.js +10 -9
- package/src/handlers/gameobject/GameObjectModifyToolHandler.js +22 -11
- package/src/handlers/index.js +437 -437
- package/src/handlers/menu/MenuItemExecuteToolHandler.js +75 -37
- package/src/handlers/screenshot/ScreenshotAnalyzeToolHandler.js +12 -10
- package/src/handlers/script/ScriptEditStructuredToolHandler.js +162 -154
- package/src/handlers/script/ScriptReadToolHandler.js +80 -85
- package/src/handlers/script/ScriptRefsFindToolHandler.js +123 -123
- package/src/handlers/script/ScriptSymbolFindToolHandler.js +125 -112
- package/src/handlers/system/SystemGetCommandStatsToolHandler.js +1 -1
- package/src/handlers/system/SystemRefreshAssetsToolHandler.js +10 -14
- package/src/handlers/video/VideoCaptureStartToolHandler.js +15 -5
- package/src/handlers/video/VideoCaptureStatusToolHandler.js +5 -9
- package/src/handlers/video/VideoCaptureStopToolHandler.js +8 -9
- package/src/lsp/LspProcessManager.js +26 -9
- package/src/tools/video/recordFor.js +13 -7
- package/src/tools/video/recordPlayMode.js +7 -6
- package/src/utils/csharpParse.js +14 -8
|
@@ -42,11 +42,11 @@ export class UnityConnection extends EventEmitter {
|
|
|
42
42
|
|
|
43
43
|
const targetHost = config.unity.mcpHost || config.unity.unityHost;
|
|
44
44
|
logger.info(`Connecting to Unity at ${targetHost}:${config.unity.port}...`);
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
this.socket = new net.Socket();
|
|
47
47
|
let connectionTimeout = null;
|
|
48
48
|
let resolved = false;
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
// Helper to clean up the connection timeout
|
|
51
51
|
const clearConnectionTimeout = () => {
|
|
52
52
|
if (connectionTimeout) {
|
|
@@ -54,7 +54,7 @@ export class UnityConnection extends EventEmitter {
|
|
|
54
54
|
connectionTimeout = null;
|
|
55
55
|
}
|
|
56
56
|
};
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
// Set up event handlers
|
|
59
59
|
this.socket.on('connect', () => {
|
|
60
60
|
logger.info('Connected to Unity Editor');
|
|
@@ -66,14 +66,14 @@ export class UnityConnection extends EventEmitter {
|
|
|
66
66
|
resolve();
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
-
this.socket.on('data',
|
|
69
|
+
this.socket.on('data', data => {
|
|
70
70
|
this.handleData(data);
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
-
this.socket.on('error',
|
|
73
|
+
this.socket.on('error', error => {
|
|
74
74
|
logger.error('Socket error:', error.message);
|
|
75
75
|
this.emit('error', error);
|
|
76
|
-
|
|
76
|
+
|
|
77
77
|
if (!this.connected && !resolved) {
|
|
78
78
|
resolved = true;
|
|
79
79
|
clearConnectionTimeout();
|
|
@@ -89,29 +89,28 @@ export class UnityConnection extends EventEmitter {
|
|
|
89
89
|
this.socket.on('close', () => {
|
|
90
90
|
// Clear the connection timeout when socket closes
|
|
91
91
|
clearConnectionTimeout();
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
// Check if we're already handling disconnection
|
|
94
94
|
if (this.isDisconnecting || !this.socket) {
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
|
-
|
|
97
|
+
|
|
98
98
|
logger.info('Disconnected from Unity Editor');
|
|
99
99
|
this.connected = false;
|
|
100
|
-
const wasSocket = this.socket;
|
|
101
100
|
this.socket = null;
|
|
102
|
-
|
|
101
|
+
|
|
103
102
|
// Clear message buffer
|
|
104
103
|
this.messageBuffer = Buffer.alloc(0);
|
|
105
|
-
|
|
104
|
+
|
|
106
105
|
// Clear pending commands
|
|
107
|
-
for (const [
|
|
106
|
+
for (const [, pending] of this.pendingCommands) {
|
|
108
107
|
pending.reject(new Error('Connection closed'));
|
|
109
108
|
}
|
|
110
109
|
this.pendingCommands.clear();
|
|
111
|
-
|
|
110
|
+
|
|
112
111
|
// Emit disconnected event
|
|
113
112
|
this.emit('disconnected');
|
|
114
|
-
|
|
113
|
+
|
|
115
114
|
// Attempt reconnection only if not intentionally disconnecting
|
|
116
115
|
if (!this.isDisconnecting && process.env.DISABLE_AUTO_RECONNECT !== 'true') {
|
|
117
116
|
this.scheduleReconnect();
|
|
@@ -120,7 +119,7 @@ export class UnityConnection extends EventEmitter {
|
|
|
120
119
|
|
|
121
120
|
// Attempt connection
|
|
122
121
|
this.socket.connect(config.unity.port, targetHost);
|
|
123
|
-
|
|
122
|
+
|
|
124
123
|
// Set timeout for initial connection
|
|
125
124
|
connectionTimeout = setTimeout(() => {
|
|
126
125
|
if (!this.connected && !resolved && this.socket) {
|
|
@@ -139,12 +138,12 @@ export class UnityConnection extends EventEmitter {
|
|
|
139
138
|
*/
|
|
140
139
|
disconnect() {
|
|
141
140
|
this.isDisconnecting = true;
|
|
142
|
-
|
|
141
|
+
|
|
143
142
|
if (this.reconnectTimer) {
|
|
144
143
|
clearTimeout(this.reconnectTimer);
|
|
145
144
|
this.reconnectTimer = null;
|
|
146
145
|
}
|
|
147
|
-
|
|
146
|
+
|
|
148
147
|
if (this.socket) {
|
|
149
148
|
try {
|
|
150
149
|
// Remove all listeners before destroying to prevent async callbacks
|
|
@@ -155,7 +154,7 @@ export class UnityConnection extends EventEmitter {
|
|
|
155
154
|
}
|
|
156
155
|
this.socket = null;
|
|
157
156
|
}
|
|
158
|
-
|
|
157
|
+
|
|
159
158
|
this.connected = false;
|
|
160
159
|
this.isDisconnecting = false;
|
|
161
160
|
}
|
|
@@ -169,7 +168,8 @@ export class UnityConnection extends EventEmitter {
|
|
|
169
168
|
}
|
|
170
169
|
|
|
171
170
|
const delay = Math.min(
|
|
172
|
-
config.unity.reconnectDelay *
|
|
171
|
+
config.unity.reconnectDelay *
|
|
172
|
+
Math.pow(config.unity.reconnectBackoffMultiplier, this.reconnectAttempts),
|
|
173
173
|
config.unity.maxReconnectDelay
|
|
174
174
|
);
|
|
175
175
|
|
|
@@ -178,7 +178,7 @@ export class UnityConnection extends EventEmitter {
|
|
|
178
178
|
this.reconnectTimer = setTimeout(() => {
|
|
179
179
|
this.reconnectTimer = null;
|
|
180
180
|
this.reconnectAttempts++;
|
|
181
|
-
this.connect().catch(
|
|
181
|
+
this.connect().catch(error => {
|
|
182
182
|
logger.error('Reconnection failed:', error.message);
|
|
183
183
|
});
|
|
184
184
|
}, delay);
|
|
@@ -198,19 +198,20 @@ export class UnityConnection extends EventEmitter {
|
|
|
198
198
|
return;
|
|
199
199
|
}
|
|
200
200
|
}
|
|
201
|
-
|
|
201
|
+
|
|
202
202
|
// Append new data to buffer
|
|
203
203
|
this.messageBuffer = Buffer.concat([this.messageBuffer, data]);
|
|
204
|
-
|
|
204
|
+
|
|
205
205
|
// Process complete messages
|
|
206
206
|
while (this.messageBuffer.length >= 4) {
|
|
207
207
|
// Read message length (first 4 bytes, big-endian)
|
|
208
208
|
const messageLength = this.messageBuffer.readInt32BE(0);
|
|
209
|
-
|
|
209
|
+
|
|
210
210
|
// Validate message length
|
|
211
|
-
if (messageLength < 0 || messageLength > 1024 * 1024) {
|
|
211
|
+
if (messageLength < 0 || messageLength > 1024 * 1024) {
|
|
212
|
+
// Max 1MB messages
|
|
212
213
|
logger.error(`[Unity] Invalid message length: ${messageLength}`);
|
|
213
|
-
|
|
214
|
+
|
|
214
215
|
// Try to recover by looking for valid framed message
|
|
215
216
|
// Look for a reasonable length value (positive, less than 10KB for typical responses)
|
|
216
217
|
let recoveryIndex = -1;
|
|
@@ -227,7 +228,7 @@ export class UnityConnection extends EventEmitter {
|
|
|
227
228
|
}
|
|
228
229
|
}
|
|
229
230
|
}
|
|
230
|
-
|
|
231
|
+
|
|
231
232
|
if (recoveryIndex > 0) {
|
|
232
233
|
logger.warn(`[Unity] Discarding ${recoveryIndex} bytes of invalid data`);
|
|
233
234
|
this.messageBuffer = this.messageBuffer.slice(recoveryIndex);
|
|
@@ -239,40 +240,42 @@ export class UnityConnection extends EventEmitter {
|
|
|
239
240
|
break;
|
|
240
241
|
}
|
|
241
242
|
}
|
|
242
|
-
|
|
243
|
+
|
|
243
244
|
// Check if we have the complete message
|
|
244
245
|
if (this.messageBuffer.length >= 4 + messageLength) {
|
|
245
246
|
// Extract message
|
|
246
247
|
const messageData = this.messageBuffer.slice(4, 4 + messageLength);
|
|
247
248
|
this.messageBuffer = this.messageBuffer.slice(4 + messageLength);
|
|
248
|
-
|
|
249
|
+
|
|
249
250
|
// Process the message
|
|
250
251
|
try {
|
|
251
252
|
const message = messageData.toString('utf8');
|
|
252
|
-
|
|
253
|
+
|
|
253
254
|
// Skip non-JSON messages (like debug logs)
|
|
254
255
|
if (!message.trim().startsWith('{')) {
|
|
255
256
|
logger.warn(`[Unity] Skipping non-JSON message: ${message.substring(0, 50)}...`);
|
|
256
257
|
continue;
|
|
257
258
|
}
|
|
258
|
-
|
|
259
|
+
|
|
259
260
|
logger.debug(`[Unity] Received framed message (length=${message.length})`);
|
|
260
|
-
|
|
261
|
+
|
|
261
262
|
const response = JSON.parse(message);
|
|
262
|
-
logger.debug(
|
|
263
|
-
|
|
263
|
+
logger.debug(
|
|
264
|
+
`[Unity] Parsed response id=${response.id || 'n/a'} status=${response.status || (response.success === false ? 'error' : 'success')}`
|
|
265
|
+
);
|
|
266
|
+
|
|
264
267
|
// Check if this is a response to a pending command
|
|
265
268
|
if (response.id && this.pendingCommands.has(response.id)) {
|
|
266
269
|
logger.info(`[Unity] Found pending command for ID ${response.id}`);
|
|
267
270
|
const pending = this.pendingCommands.get(response.id);
|
|
268
271
|
this.pendingCommands.delete(response.id);
|
|
269
|
-
|
|
272
|
+
|
|
270
273
|
// Handle both old and new response formats
|
|
271
274
|
if (response.status === 'success' || response.success === true) {
|
|
272
275
|
logger.info(`[Unity] Command ${response.id} succeeded`);
|
|
273
|
-
|
|
276
|
+
|
|
274
277
|
let result = response.result || response.data || {};
|
|
275
|
-
|
|
278
|
+
|
|
276
279
|
// If result is a string, try to parse it as JSON
|
|
277
280
|
if (typeof result === 'string') {
|
|
278
281
|
try {
|
|
@@ -283,7 +286,7 @@ export class UnityConnection extends EventEmitter {
|
|
|
283
286
|
// Keep the original string value
|
|
284
287
|
}
|
|
285
288
|
}
|
|
286
|
-
|
|
289
|
+
|
|
287
290
|
// Include version and editorState information if available
|
|
288
291
|
if (response.version) {
|
|
289
292
|
result._version = response.version;
|
|
@@ -291,7 +294,7 @@ export class UnityConnection extends EventEmitter {
|
|
|
291
294
|
if (response.editorState) {
|
|
292
295
|
result._editorState = response.editorState;
|
|
293
296
|
}
|
|
294
|
-
|
|
297
|
+
|
|
295
298
|
logger.info(`[Unity] Command ${response.id} resolved successfully`);
|
|
296
299
|
pending.resolve(result);
|
|
297
300
|
} else if (response.status === 'error' || response.success === false) {
|
|
@@ -310,7 +313,7 @@ export class UnityConnection extends EventEmitter {
|
|
|
310
313
|
} catch (error) {
|
|
311
314
|
logger.error('[Unity] Failed to parse response:', error.message);
|
|
312
315
|
logger.debug(`[Unity] Raw message: ${messageData.toString().substring(0, 200)}...`);
|
|
313
|
-
|
|
316
|
+
|
|
314
317
|
// Check if this looks like a Unity log message
|
|
315
318
|
const messageStr = messageData.toString();
|
|
316
319
|
if (messageStr.includes('[Unity Editor MCP]')) {
|
|
@@ -333,7 +336,7 @@ export class UnityConnection extends EventEmitter {
|
|
|
333
336
|
*/
|
|
334
337
|
async sendCommand(type, params = {}) {
|
|
335
338
|
logger.info(`[Unity] enqueue sendCommand: ${type}`, { connected: this.connected });
|
|
336
|
-
|
|
339
|
+
|
|
337
340
|
if (!this.connected) {
|
|
338
341
|
logger.error('[Unity] Cannot send command - not connected');
|
|
339
342
|
throw new Error('Not connected to Unity');
|
|
@@ -375,18 +378,22 @@ export class UnityConnection extends EventEmitter {
|
|
|
375
378
|
|
|
376
379
|
// Store pending with wrappers to manage queue progression
|
|
377
380
|
this.pendingCommands.set(id, {
|
|
378
|
-
resolve:
|
|
381
|
+
resolve: data => {
|
|
379
382
|
logger.info(`[Unity] Command ${id} resolved`);
|
|
380
383
|
clearTimeout(timeout);
|
|
381
|
-
try {
|
|
384
|
+
try {
|
|
385
|
+
task.outerResolve(data);
|
|
386
|
+
} finally {
|
|
382
387
|
this.inFlight = Math.max(0, this.inFlight - 1);
|
|
383
388
|
this._pumpQueue();
|
|
384
389
|
}
|
|
385
390
|
},
|
|
386
|
-
reject:
|
|
391
|
+
reject: error => {
|
|
387
392
|
logger.error(`[Unity] Command ${id} rejected: ${error.message}`);
|
|
388
393
|
clearTimeout(timeout);
|
|
389
|
-
try {
|
|
394
|
+
try {
|
|
395
|
+
task.outerReject(error);
|
|
396
|
+
} finally {
|
|
390
397
|
this.inFlight = Math.max(0, this.inFlight - 1);
|
|
391
398
|
this._pumpQueue();
|
|
392
399
|
}
|
|
@@ -394,7 +401,7 @@ export class UnityConnection extends EventEmitter {
|
|
|
394
401
|
});
|
|
395
402
|
|
|
396
403
|
// Send framed message
|
|
397
|
-
this.socket.write(framedMessage,
|
|
404
|
+
this.socket.write(framedMessage, error => {
|
|
398
405
|
if (error) {
|
|
399
406
|
logger.error(`[Unity] Failed to write command ${id}: ${error.message}`);
|
|
400
407
|
clearTimeout(timeout);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseToolHandler } from '../base/BaseToolHandler.js'
|
|
1
|
+
import { BaseToolHandler } from '../base/BaseToolHandler.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Addressables Analysis Tool Handler for Unity MCP
|
|
@@ -38,133 +38,143 @@ export default class AddressablesAnalyzeToolHandler extends BaseToolHandler {
|
|
|
38
38
|
},
|
|
39
39
|
required: ['action']
|
|
40
40
|
}
|
|
41
|
-
)
|
|
42
|
-
this.unityConnection = unityConnection
|
|
41
|
+
)
|
|
42
|
+
this.unityConnection = unityConnection
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
validate(params) {
|
|
46
|
-
const { action, assetPath } = params || {}
|
|
46
|
+
const { action, assetPath } = params || {}
|
|
47
47
|
|
|
48
48
|
if (!action) {
|
|
49
|
-
throw new Error('action is required')
|
|
49
|
+
throw new Error('action is required')
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
const validActions = ['analyze_duplicates', 'analyze_dependencies', 'analyze_unused']
|
|
52
|
+
const validActions = ['analyze_duplicates', 'analyze_dependencies', 'analyze_unused']
|
|
53
53
|
if (!validActions.includes(action)) {
|
|
54
|
-
throw new Error(`Invalid action: ${action}. Must be one of: ${validActions.join(', ')}`)
|
|
54
|
+
throw new Error(`Invalid action: ${action}. Must be one of: ${validActions.join(', ')}`)
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
// Action-specific validation
|
|
58
58
|
if (action === 'analyze_dependencies' && !assetPath) {
|
|
59
|
-
throw new Error('assetPath is required for analyze_dependencies')
|
|
59
|
+
throw new Error('assetPath is required for analyze_dependencies')
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
async execute(params) {
|
|
64
|
-
const { action, ...parameters } = params
|
|
64
|
+
const { action, ...parameters } = params
|
|
65
65
|
|
|
66
66
|
// Ensure connected
|
|
67
67
|
if (!this.unityConnection.isConnected()) {
|
|
68
|
-
await this.unityConnection.connect()
|
|
68
|
+
await this.unityConnection.connect()
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
const result = await this.unityConnection.sendCommand('addressables_analyze', {
|
|
72
72
|
action,
|
|
73
73
|
...parameters
|
|
74
|
-
})
|
|
74
|
+
})
|
|
75
75
|
|
|
76
|
-
return this.formatResponse(action, result)
|
|
76
|
+
return this.formatResponse(action, result)
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
formatResponse(action, result) {
|
|
80
80
|
if (result && result.error) {
|
|
81
|
-
throw new Error(result.error.message || result.error)
|
|
81
|
+
throw new Error(result.error.message || result.error)
|
|
82
82
|
}
|
|
83
83
|
|
|
84
84
|
if (!result || typeof result !== 'object') {
|
|
85
|
-
throw new Error('Invalid response from Unity')
|
|
85
|
+
throw new Error('Invalid response from Unity')
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
// Return formatted response
|
|
89
89
|
return {
|
|
90
|
-
content: [
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
content: [
|
|
91
|
+
{
|
|
92
|
+
type: 'text',
|
|
93
|
+
text: this.formatResultText(action, result)
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
}
|
|
95
97
|
}
|
|
96
98
|
|
|
97
99
|
formatResultText(action, result) {
|
|
98
|
-
const lines = []
|
|
100
|
+
const lines = []
|
|
99
101
|
|
|
100
102
|
switch (action) {
|
|
101
103
|
case 'analyze_duplicates':
|
|
102
|
-
lines.push(
|
|
104
|
+
lines.push('🔍 重複アセット分析結果')
|
|
103
105
|
if (result.data && result.data.duplicates) {
|
|
104
106
|
if (result.data.duplicates.length === 0) {
|
|
105
|
-
lines.push(
|
|
107
|
+
lines.push(' ✅ 重複アセットは見つかりませんでした')
|
|
106
108
|
} else {
|
|
107
|
-
lines.push(` ⚠️ 重複アセット: ${result.pagination.total}件`)
|
|
109
|
+
lines.push(` ⚠️ 重複アセット: ${result.pagination.total}件`)
|
|
108
110
|
result.data.duplicates.forEach(dup => {
|
|
109
|
-
lines.push(`\n 📁 ${dup.assetPath}`)
|
|
110
|
-
lines.push(` 使用グループ: ${dup.groups.join(', ')}`)
|
|
111
|
-
})
|
|
111
|
+
lines.push(`\n 📁 ${dup.assetPath}`)
|
|
112
|
+
lines.push(` 使用グループ: ${dup.groups.join(', ')}`)
|
|
113
|
+
})
|
|
112
114
|
if (result.pagination.hasMore) {
|
|
113
|
-
lines.push(
|
|
115
|
+
lines.push(
|
|
116
|
+
`\n ... さらに${result.pagination.total - result.pagination.offset - result.pagination.pageSize}件あります`
|
|
117
|
+
)
|
|
114
118
|
}
|
|
115
119
|
}
|
|
116
120
|
}
|
|
117
|
-
break
|
|
121
|
+
break
|
|
118
122
|
|
|
119
123
|
case 'analyze_dependencies':
|
|
120
|
-
lines.push(
|
|
124
|
+
lines.push('🔍 依存関係分析結果')
|
|
121
125
|
if (result.data && result.data.dependencies) {
|
|
122
|
-
const deps = Object.entries(result.data.dependencies)
|
|
126
|
+
const deps = Object.entries(result.data.dependencies)
|
|
123
127
|
if (deps.length === 0) {
|
|
124
|
-
lines.push(
|
|
128
|
+
lines.push(' ✅ 依存関係がありません')
|
|
125
129
|
} else {
|
|
126
130
|
deps.forEach(([assetPath, dependencies]) => {
|
|
127
|
-
lines.push(`\n 📁 ${assetPath}`)
|
|
131
|
+
lines.push(`\n 📁 ${assetPath}`)
|
|
128
132
|
if (dependencies.length === 0) {
|
|
129
|
-
lines.push(
|
|
133
|
+
lines.push(' 依存なし')
|
|
130
134
|
} else {
|
|
131
|
-
lines.push(` 依存数: ${dependencies.length}個`)
|
|
135
|
+
lines.push(` 依存数: ${dependencies.length}個`)
|
|
132
136
|
dependencies.forEach((dep, idx) => {
|
|
133
137
|
if (idx < 10) {
|
|
134
|
-
lines.push(` → ${dep}`)
|
|
138
|
+
lines.push(` → ${dep}`)
|
|
135
139
|
}
|
|
136
|
-
})
|
|
140
|
+
})
|
|
137
141
|
if (dependencies.length > 10) {
|
|
138
|
-
lines.push(` ... 他${dependencies.length - 10}件`)
|
|
142
|
+
lines.push(` ... 他${dependencies.length - 10}件`)
|
|
139
143
|
}
|
|
140
144
|
}
|
|
141
|
-
})
|
|
145
|
+
})
|
|
142
146
|
}
|
|
143
147
|
}
|
|
144
|
-
break
|
|
148
|
+
break
|
|
145
149
|
|
|
146
150
|
case 'analyze_unused':
|
|
147
|
-
lines.push(
|
|
151
|
+
lines.push('🔍 未使用アセット分析結果')
|
|
148
152
|
if (result.data && result.data.unused) {
|
|
149
153
|
if (result.data.unused.length === 0) {
|
|
150
|
-
lines.push(
|
|
154
|
+
lines.push(' ✅ すべてのアセットが使用されています')
|
|
151
155
|
} else {
|
|
152
|
-
lines.push(` ⚠️ 未使用アセット: ${result.pagination.total}件`)
|
|
156
|
+
lines.push(` ⚠️ 未使用アセット: ${result.pagination.total}件`)
|
|
153
157
|
result.data.unused.forEach(path => {
|
|
154
|
-
lines.push(` 📁 ${path}`)
|
|
155
|
-
})
|
|
158
|
+
lines.push(` 📁 ${path}`)
|
|
159
|
+
})
|
|
156
160
|
if (result.pagination.hasMore) {
|
|
157
|
-
lines.push(
|
|
161
|
+
lines.push(
|
|
162
|
+
`\n ... さらに${result.pagination.total - result.pagination.offset - result.pagination.pageSize}件あります`
|
|
163
|
+
)
|
|
158
164
|
}
|
|
159
|
-
lines.push(
|
|
165
|
+
lines.push(
|
|
166
|
+
'\n 💡 これらのアセットはAddressableとして登録されておらず、他のAddressableからも参照されていません'
|
|
167
|
+
)
|
|
160
168
|
}
|
|
161
169
|
}
|
|
162
|
-
break
|
|
170
|
+
break
|
|
163
171
|
|
|
164
172
|
default:
|
|
165
|
-
lines.push(JSON.stringify(result, null, 2))
|
|
173
|
+
lines.push(JSON.stringify(result, null, 2))
|
|
166
174
|
}
|
|
167
175
|
|
|
168
|
-
return lines.join('\n')
|
|
176
|
+
return lines.join('\n')
|
|
169
177
|
}
|
|
170
178
|
}
|
|
179
|
+
|
|
180
|
+
|