poker-mcp 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/README.md +241 -0
  2. package/config/mcp-manifest.json +1713 -0
  3. package/config/package-lock.json +1335 -0
  4. package/config/poker_mcp.code-workspace +8 -0
  5. package/package.json +51 -0
  6. package/src/config/ConfigManager.js +120 -0
  7. package/src/config/default.json +62 -0
  8. package/src/mcp/handlers/bodyHandlers.js +63 -0
  9. package/src/mcp/handlers/buildupFactorHandlers.js +43 -0
  10. package/src/mcp/handlers/calculationHandlers.js +265 -0
  11. package/src/mcp/handlers/detectorHandlers.js +201 -0
  12. package/src/mcp/handlers/index.js +43 -0
  13. package/src/mcp/handlers/sourceHandlers.js +25 -0
  14. package/src/mcp/handlers/transformHandlers.js +26 -0
  15. package/src/mcp/handlers/unitHandlers.js +305 -0
  16. package/src/mcp/handlers/zoneHandlers.js +83 -0
  17. package/src/mcp/middleware/errorHandler.js +49 -0
  18. package/src/mcp/middleware/requestValidator.js +129 -0
  19. package/src/mcp/server.js +76 -0
  20. package/src/mcp/tools/bodyTools.js +185 -0
  21. package/src/mcp/tools/buildupFactorTools.js +82 -0
  22. package/src/mcp/tools/calculationTools.js +58 -0
  23. package/src/mcp/tools/commonTools.js +22 -0
  24. package/src/mcp/tools/detectorTools.js +131 -0
  25. package/src/mcp/tools/index.js +34 -0
  26. package/src/mcp/tools/sourceTools.js +726 -0
  27. package/src/mcp/tools/sourceTools_fixed_part2.js +41 -0
  28. package/src/mcp/tools/transformTools.js +73 -0
  29. package/src/mcp/tools/unitTools.js +137 -0
  30. package/src/mcp/tools/zoneTools.js +65 -0
  31. package/src/mcp_server_stdio_v4.js +45 -0
  32. package/src/routes/restApi.js +184 -0
  33. package/src/services/CalculationService.js +525 -0
  34. package/src/services/DataManager.js +738 -0
  35. package/src/services/TaskManager.js +1622 -0
  36. package/src/utils/MaterialAlternatives.js +189 -0
  37. package/src/utils/errorHandler.js +68 -0
  38. package/src/utils/errors.js +37 -0
  39. package/src/utils/logger.js +24 -0
  40. package/src/utils/logger_no_color.js +28 -0
  41. package/src/utils/mcpErrors.js +225 -0
  42. package/src/validators/CMBValidator.js +191 -0
  43. package/src/validators/DetectorValidator.js +512 -0
  44. package/src/validators/ManifestValidator.js +249 -0
  45. package/src/validators/NuclideValidator.js +171 -0
  46. package/src/validators/PhysicsValidator.js +401 -0
  47. package/src/validators/PhysicsValidatorSimple.js +87 -0
  48. package/src/validators/SourceValidator.js +515 -0
  49. package/src/validators/TransformValidator.js +472 -0
  50. package/src/validators/UnitValidator.js +562 -0
@@ -0,0 +1,201 @@
1
+ // mcp/handlers/detectorHandlers.js
2
+ import { ValidationError } from '../../utils/errors.js';
3
+ import { logger } from '../../utils/logger.js';
4
+
5
+ export function createDetectorHandlers(taskManager) {
6
+ return {
7
+ // 検出器提案
8
+ async proposeDetector(args) {
9
+ try {
10
+ const { name, origin, grid = [], show_path_trace, transform = null } = args;
11
+
12
+ // show_path_trace が必須になったことを確認
13
+ if (show_path_trace === undefined) {
14
+ throw new ValidationError('show_path_trace は必須パラメータです');
15
+ }
16
+
17
+ logger.info('検出器提案開始', {
18
+ name,
19
+ origin,
20
+ gridCount: grid.length,
21
+ hasTransform: !!transform,
22
+ pathTrace: show_path_trace
23
+ });
24
+
25
+ // DetectorValidator統合のため、TaskManagerの包括的検証を利用
26
+ const result = await taskManager.proposeDetector(name, origin, grid, show_path_trace, transform);
27
+
28
+ // 検出器の分析情報を追加取得
29
+ const detectorData = { name, origin, grid, show_path_trace, transform };
30
+ const analysisResult = taskManager.analyzeDetectorStructure(detectorData);
31
+
32
+ logger.info('検出器提案完了', {
33
+ name,
34
+ dimension: analysisResult.dimension,
35
+ complexity: analysisResult.complexity
36
+ });
37
+
38
+ return {
39
+ success: true,
40
+ message: result,
41
+ detector: {
42
+ name,
43
+ type: analysisResult.type,
44
+ dimension: analysisResult.dimension,
45
+ complexity: analysisResult.complexity,
46
+ origin,
47
+ gridDimensions: grid.length,
48
+ hasTransform: !!transform,
49
+ pathTrace: show_path_trace
50
+ },
51
+ analysis: {
52
+ isOptimal: analysisResult.isOptimal,
53
+ suggestions: analysisResult.suggestions,
54
+ performance: analysisResult.performance
55
+ }
56
+ };
57
+
58
+ } catch (error) {
59
+ logger.error('検出器提案エラー', { args, error: error.message });
60
+ throw error;
61
+ }
62
+ },
63
+
64
+ // 検出器更新
65
+ async updateDetector(args) {
66
+ try {
67
+ const { name, ...updates } = args;
68
+
69
+ logger.info('検出器更新開始', { name, updates });
70
+
71
+ // 存在確認
72
+ const existingDetector = taskManager.findDetectorByName(name);
73
+ if (!existingDetector) {
74
+ throw new ValidationError(`検出器 ${name} が見つかりません`, 'name', name);
75
+ }
76
+
77
+ // TaskManagerの包括的更新処理を利用
78
+ const result = await taskManager.updateDetector(name, updates);
79
+
80
+ // 更新後の分析情報
81
+ const updatedDetectorData = { ...existingDetector, ...updates };
82
+ const analysisResult = taskManager.analyzeDetectorStructure(updatedDetectorData);
83
+
84
+ logger.info('検出器更新完了', {
85
+ name,
86
+ newComplexity: analysisResult.complexity
87
+ });
88
+
89
+ return {
90
+ success: true,
91
+ message: result,
92
+ updated: {
93
+ name,
94
+ ...updates,
95
+ analysisAfterUpdate: {
96
+ complexity: analysisResult.complexity,
97
+ dimension: analysisResult.dimension,
98
+ isOptimal: analysisResult.isOptimal
99
+ }
100
+ }
101
+ };
102
+
103
+ } catch (error) {
104
+ logger.error('検出器更新エラー', { args, error: error.message });
105
+ throw error;
106
+ }
107
+ },
108
+
109
+ // 検出器削除
110
+ async deleteDetector(args) {
111
+ try {
112
+ const { name } = args;
113
+
114
+ logger.info('検出器削除開始', { name });
115
+
116
+ // 存在確認
117
+ const existingDetector = taskManager.findDetectorByName(name);
118
+ if (!existingDetector) {
119
+ throw new ValidationError(`検出器 ${name} が見つかりません`, 'name', name);
120
+ }
121
+
122
+ // 削除前の分析情報を記録
123
+ const preDeleteAnalysis = taskManager.analyzeDetectorStructure(existingDetector);
124
+
125
+ const result = await taskManager.deleteDetector(name);
126
+
127
+ logger.info('検出器削除完了', {
128
+ name,
129
+ deletedComplexity: preDeleteAnalysis.complexity
130
+ });
131
+
132
+ return {
133
+ success: true,
134
+ message: result,
135
+ deleted: {
136
+ name,
137
+ type: preDeleteAnalysis.type,
138
+ dimension: preDeleteAnalysis.dimension,
139
+ complexity: preDeleteAnalysis.complexity
140
+ }
141
+ };
142
+
143
+ } catch (error) {
144
+ logger.error('検出器削除エラー', { args, error: error.message });
145
+ throw error;
146
+ }
147
+ },
148
+
149
+ // 検出器互換性分析
150
+ async analyzeDetectorCompatibility(args) {
151
+ try {
152
+ const { detector1Name, detector2Name } = args;
153
+
154
+ logger.info('検出器互換性分析開始', { detector1Name, detector2Name });
155
+
156
+ const result = await taskManager.analyzeDetectorCompatibility(detector1Name, detector2Name);
157
+
158
+ logger.info('検出器互換性分析完了', {
159
+ detector1Name,
160
+ detector2Name,
161
+ compatibility: result.compatibility.overall
162
+ });
163
+
164
+ return {
165
+ success: true,
166
+ message: `検出器互換性分析完了: ${result.compatibility.overall}`,
167
+ compatibility: result
168
+ };
169
+
170
+ } catch (error) {
171
+ logger.error('検出器互換性分析エラー', { args, error: error.message });
172
+ throw error;
173
+ }
174
+ },
175
+
176
+ // システム検出器性能分析
177
+ async analyzeSystemDetectorPerformance(args) {
178
+ try {
179
+ logger.info('システム検出器性能分析開始');
180
+
181
+ const result = await taskManager.analyzeSystemDetectorPerformance();
182
+
183
+ logger.info('システム検出器性能分析完了', {
184
+ totalDetectors: result.totalDetectors,
185
+ averageComplexity: result.averageComplexity,
186
+ totalMemoryMB: result.memoryEstimate.total
187
+ });
188
+
189
+ return {
190
+ success: true,
191
+ message: `システム検出器性能分析完了: ${result.totalDetectors}個の検出器を分析`,
192
+ performance: result
193
+ };
194
+
195
+ } catch (error) {
196
+ logger.error('システム検出器性能分析エラー', { error: error.message });
197
+ throw error;
198
+ }
199
+ }
200
+ };
201
+ }
@@ -0,0 +1,43 @@
1
+ // mcp/handlers/index.js
2
+ import { createBodyHandlers } from './bodyHandlers.js';
3
+ import { createZoneHandlers } from './zoneHandlers.js';
4
+ import { createTransformHandlers } from './transformHandlers.js';
5
+ import { createBuildupFactorHandlers } from './buildupFactorHandlers.js';
6
+ import { createSourceHandlers } from './sourceHandlers.js';
7
+ import { createDetectorHandlers } from './detectorHandlers.js';
8
+ import { createUnitHandlers } from './unitHandlers.js';
9
+ import { createCalculationHandlers } from './calculationHandlers.js';
10
+
11
+ export function createAllHandlers(taskManager) {
12
+ return {
13
+ // 立体操作
14
+ ...createBodyHandlers(taskManager),
15
+
16
+ // ゾーン操作
17
+ ...createZoneHandlers(taskManager),
18
+
19
+ // 変換操作
20
+ ...createTransformHandlers(taskManager),
21
+
22
+ // ビルドアップ係数操作
23
+ ...createBuildupFactorHandlers(taskManager),
24
+
25
+ // 線源操作
26
+ ...createSourceHandlers(taskManager),
27
+
28
+ // 検出器操作
29
+ ...createDetectorHandlers(taskManager),
30
+
31
+ // 単位操作
32
+ ...createUnitHandlers(taskManager),
33
+
34
+ // 計算操作
35
+ ...createCalculationHandlers(taskManager),
36
+
37
+ // 共通操作
38
+ async applyChanges(args) {
39
+ const result = await taskManager.applyChanges();
40
+ return { success: true, message: '変更を適用しました', details: result };
41
+ }
42
+ };
43
+ }
@@ -0,0 +1,25 @@
1
+ // mcp/handlers/sourceHandlers.js
2
+ import { validateSourceRequest, validateUpdateSourceRequest, validateDeleteSourceRequest } from '../middleware/requestValidator.js';
3
+
4
+ export function createSourceHandlers(taskManager) {
5
+ return {
6
+ async proposeSource(args) {
7
+ validateSourceRequest(args);
8
+ const result = await taskManager.proposeSource(args);
9
+ return { success: true, message: result };
10
+ },
11
+
12
+ async updateSource(args) {
13
+ validateUpdateSourceRequest(args);
14
+ const { name, ...updates } = args;
15
+ const result = await taskManager.updateSource(name, updates);
16
+ return { success: true, message: result };
17
+ },
18
+
19
+ async deleteSource(args) {
20
+ validateDeleteSourceRequest(args);
21
+ const result = await taskManager.deleteSource(args.name);
22
+ return { success: true, message: result };
23
+ }
24
+ };
25
+ }
@@ -0,0 +1,26 @@
1
+ // mcp/handlers/transformHandlers.js
2
+ import { validateTransformRequest } from '../middleware/requestValidator.js';
3
+ import { ValidationError } from '../../utils/errors.js';
4
+
5
+ export function createTransformHandlers(taskManager) {
6
+ return {
7
+ async proposeTransform(args) {
8
+ validateTransformRequest(args);
9
+ const result = await taskManager.proposeTransform(args.name, args.operations);
10
+ return { success: true, message: result };
11
+ },
12
+
13
+ async updateTransform(args) {
14
+ if (!args.name) throw new ValidationError('変換名は必須です', 'name', args.name);
15
+ const { name, ...updates } = args;
16
+ const result = await taskManager.updateTransform(name, updates);
17
+ return { success: true, message: result };
18
+ },
19
+
20
+ async deleteTransform(args) {
21
+ if (!args.name) throw new ValidationError('変換名は必須です', 'name', args.name);
22
+ const result = await taskManager.deleteTransform(args.name);
23
+ return { success: true, message: result };
24
+ }
25
+ };
26
+ }
@@ -0,0 +1,305 @@
1
+ // mcp/handlers/unitHandlers.js
2
+ import { ValidationError } from '../../utils/errors.js';
3
+ import { logger } from '../../utils/logger.js';
4
+
5
+ export function createUnitHandlers(taskManager) {
6
+ // ヘルパー関数をローカルスコープで定義
7
+ function generateUnitUsageStats(integrityResult) {
8
+ const stats = {
9
+ totalUsages: 0,
10
+ usagesByKey: {
11
+ length: 0,
12
+ angle: 0,
13
+ density: 0,
14
+ radioactivity: 0
15
+ },
16
+ contextTypes: {
17
+ coordinates: 0,
18
+ geometry: 0,
19
+ material_properties: 0,
20
+ radiation: 0
21
+ }
22
+ };
23
+
24
+ if (integrityResult.systemIntegrity && integrityResult.systemIntegrity.usageConsistency) {
25
+ integrityResult.systemIntegrity.usageConsistency.forEach(usage => {
26
+ stats.totalUsages += usage.usageCount;
27
+
28
+ // 使用コンテキストの分類
29
+ usage.contexts.forEach(context => {
30
+ if (context.includes('coordinates') || context.includes('position')) {
31
+ stats.contextTypes.coordinates++;
32
+ } else if (context.includes('geometry') || context.includes('edge')) {
33
+ stats.contextTypes.geometry++;
34
+ } else if (context.includes('density')) {
35
+ stats.contextTypes.material_properties++;
36
+ } else if (context.includes('radioactivity') || context.includes('inventory')) {
37
+ stats.contextTypes.radiation++;
38
+ }
39
+ });
40
+ });
41
+ }
42
+
43
+ return stats;
44
+ }
45
+
46
+ function organizeRecommendations(integrityResult) {
47
+ const recommendations = [];
48
+
49
+ // 診断レポートからの推奨事項
50
+ if (integrityResult.diagnosticReport && integrityResult.diagnosticReport.recommendations) {
51
+ integrityResult.diagnosticReport.recommendations.forEach(rec => {
52
+ recommendations.push({
53
+ type: 'system_optimization',
54
+ priority: 'medium',
55
+ category: 'unit_consistency',
56
+ message: rec,
57
+ source: 'diagnostic_report'
58
+ });
59
+ });
60
+ }
61
+
62
+ // 物理的整合性からの推奨事項
63
+ if (integrityResult.physicalConsistency && integrityResult.physicalConsistency.recommendations) {
64
+ integrityResult.physicalConsistency.recommendations.forEach(rec => {
65
+ recommendations.push({
66
+ type: 'physical_consistency',
67
+ priority: 'high',
68
+ category: 'unit_physics',
69
+ message: rec.message,
70
+ source: 'physical_consistency'
71
+ });
72
+ });
73
+ }
74
+
75
+ // 健全性に基づく一般的推奨事項
76
+ const overallHealth = integrityResult.summary.overallHealth;
77
+ if (overallHealth === 'warning' || overallHealth === 'minor_warnings') {
78
+ recommendations.push({
79
+ type: 'health_improvement',
80
+ priority: 'medium',
81
+ category: 'system_health',
82
+ message: 'Consider reviewing unit system warnings to improve overall consistency',
83
+ source: 'health_analysis'
84
+ });
85
+ } else if (overallHealth === 'excellent') {
86
+ recommendations.push({
87
+ type: 'maintenance',
88
+ priority: 'low',
89
+ category: 'system_health',
90
+ message: 'Unit system is in excellent condition. Continue current practices.',
91
+ source: 'health_analysis'
92
+ });
93
+ }
94
+
95
+ return recommendations;
96
+ }
97
+
98
+ return {
99
+ // 単位設定提案(4キー完全性保証)
100
+ async proposeUnit(args) {
101
+ try {
102
+ const { length, angle, density, radioactivity } = args;
103
+
104
+ logger.info('4キー完全単位設定提案開始', { length, angle, density, radioactivity });
105
+
106
+ // TaskManagerの4キー完全性保証機能を利用
107
+ const result = await taskManager.proposeUnit(length, angle, density, radioactivity);
108
+
109
+ logger.info('4キー完全単位設定提案完了', {
110
+ units: { length, angle, density, radioactivity }
111
+ });
112
+
113
+ return {
114
+ success: true,
115
+ message: result,
116
+ unit: {
117
+ length,
118
+ angle,
119
+ density,
120
+ radioactivity,
121
+ integrity: '4-key-complete'
122
+ }
123
+ };
124
+
125
+ } catch (error) {
126
+ logger.error('単位設定提案エラー', { args, error: error.message });
127
+ throw error;
128
+ }
129
+ },
130
+
131
+ // 単位設定取得(4キー完全性検証付き)
132
+ async getUnit(args) {
133
+ try {
134
+ logger.info('4キー完全単位設定取得開始');
135
+
136
+ // TaskManagerの4キー完全性保証取得機能を利用
137
+ const result = await taskManager.getUnit();
138
+
139
+ logger.info('4キー完全単位設定取得完了', {
140
+ unit: result.unit,
141
+ integrity: result.integrity
142
+ });
143
+
144
+ return {
145
+ success: true,
146
+ message: '4キー完全単位設定を取得しました',
147
+ ...result
148
+ };
149
+
150
+ } catch (error) {
151
+ logger.error('単位設定取得エラー', { error: error.message });
152
+ throw error;
153
+ }
154
+ },
155
+
156
+ // 単位設定更新(4キー保持保証)
157
+ async updateUnit(args) {
158
+ try {
159
+ if (!args || Object.keys(args).length === 0) {
160
+ throw new ValidationError('更新する内容が指定されていません', 'updates', args);
161
+ }
162
+
163
+ logger.info('4キー保持単位更新開始', { updates: args });
164
+
165
+ // TaskManagerの4キー保持更新機能を利用
166
+ const result = await taskManager.updateUnit(args);
167
+
168
+ logger.info('4キー保持単位更新完了', {
169
+ updates: args
170
+ });
171
+
172
+ return {
173
+ success: true,
174
+ message: result,
175
+ updated: {
176
+ ...args,
177
+ integrity: '4-key-preserved'
178
+ }
179
+ };
180
+
181
+ } catch (error) {
182
+ logger.error('単位設定更新エラー', { args, error: error.message });
183
+ throw error;
184
+ }
185
+ },
186
+
187
+ // 単位完全性検証
188
+ async validateUnitIntegrity(args) {
189
+ try {
190
+ const { includeSystemAnalysis = true, generateReport = true } = args;
191
+
192
+ logger.info('単位完全性検証開始', { includeSystemAnalysis, generateReport });
193
+
194
+ // TaskManagerの包括的完全性検証を利用
195
+ const result = await taskManager.validateUnitIntegrity(includeSystemAnalysis, generateReport);
196
+
197
+ logger.info('単位完全性検証完了', {
198
+ fourKeyComplete: result.fourKeyComplete,
199
+ overallHealth: result.summary.overallHealth
200
+ });
201
+
202
+ return {
203
+ success: true,
204
+ message: `単位完全性検証完了 - 健全性: ${result.summary.overallHealth}`,
205
+ integrity: result
206
+ };
207
+
208
+ } catch (error) {
209
+ logger.error('単位完全性検証エラー', { args, error: error.message });
210
+ throw error;
211
+ }
212
+ },
213
+
214
+ // 単位変換分析
215
+ async analyzeUnitConversion(args) {
216
+ try {
217
+ const { targetUnits, includePhysicalAnalysis = true } = args;
218
+
219
+ if (!targetUnits) {
220
+ throw new ValidationError('変換先単位系(targetUnits)は必須です', 'targetUnits', targetUnits);
221
+ }
222
+
223
+ logger.info('単位変換分析開始', { targetUnits, includePhysicalAnalysis });
224
+
225
+ // TaskManagerの変換係数分析機能を利用
226
+ const result = await taskManager.analyzeUnitConversion(targetUnits, includePhysicalAnalysis);
227
+
228
+ logger.info('単位変換分析完了', {
229
+ isIdentityConversion: result.conversion.isIdentity,
230
+ recommendationCount: result.recommendations.length
231
+ });
232
+
233
+ return {
234
+ success: true,
235
+ message: `単位変換分析完了 - ${result.conversion.isIdentity ? '変換不要' : '変換が必要'}`,
236
+ conversion: result
237
+ };
238
+
239
+ } catch (error) {
240
+ logger.error('単位変換分析エラー', { args, error: error.message });
241
+ throw error;
242
+ }
243
+ },
244
+
245
+ // システム単位使用状況分析
246
+ async analyzeUnitUsage(args) {
247
+ try {
248
+ logger.info('システム単位使用状況分析開始');
249
+
250
+ // 現在の単位設定を取得
251
+ const currentUnit = await taskManager.getUnit();
252
+
253
+ // システム全体での単位使用状況を分析
254
+ const result = await taskManager.validateUnitIntegrity(true, true);
255
+
256
+ // 使用状況統計を生成
257
+ const usageStats = generateUnitUsageStats(result);
258
+
259
+ logger.info('システム単位使用状況分析完了', usageStats);
260
+
261
+ return {
262
+ success: true,
263
+ message: `システム単位使用状況分析完了 - 使用箇所: ${usageStats.totalUsages}`,
264
+ currentUnit: currentUnit.unit,
265
+ usageAnalysis: usageStats,
266
+ systemIntegrity: result.systemIntegrity
267
+ };
268
+
269
+ } catch (error) {
270
+ logger.error('システム単位使用状況分析エラー', { error: error.message });
271
+ throw error;
272
+ }
273
+ },
274
+
275
+ // 単位推奨事項取得
276
+ async getUnitRecommendations(args) {
277
+ try {
278
+ logger.info('単位推奨事項取得開始');
279
+
280
+ // 完全性診断レポートを生成
281
+ const integrityResult = await taskManager.validateUnitIntegrity(true, true);
282
+
283
+ // 推奨事項を整理
284
+ const recommendations = organizeRecommendations(integrityResult);
285
+
286
+ logger.info('単位推奨事項取得完了', {
287
+ recommendationCount: recommendations.length
288
+ });
289
+
290
+ return {
291
+ success: true,
292
+ message: `単位推奨事項を${recommendations.length}件取得しました`,
293
+ recommendations,
294
+ overallHealth: integrityResult.summary.overallHealth,
295
+ criticalIssues: integrityResult.summary.criticalIssues,
296
+ warnings: integrityResult.summary.warnings
297
+ };
298
+
299
+ } catch (error) {
300
+ logger.error('単位推奨事項取得エラー', { error: error.message });
301
+ throw error;
302
+ }
303
+ }
304
+ };
305
+ }
@@ -0,0 +1,83 @@
1
+ // mcp/handlers/zoneHandlers.js
2
+ import { validateZoneRequest } from '../middleware/requestValidator.js';
3
+ import { ValidationError } from '../../utils/errors.js';
4
+ import { logger } from '../../utils/logger.js';
5
+
6
+ export function createZoneHandlers(taskManager) {
7
+ return {
8
+ async proposeZone(args) {
9
+ try {
10
+ validateZoneRequest(args);
11
+
12
+ // VOID材料での密度指定チェック
13
+ if (args.material === 'VOID' && args.density !== undefined) {
14
+ throw new ValidationError(
15
+ 'Density cannot be specified for VOID material',
16
+ 'density',
17
+ args.density
18
+ );
19
+ }
20
+
21
+ // 非VOID材料での密度必須チェック
22
+ if (args.material !== 'VOID' && args.density === undefined) {
23
+ throw new ValidationError(
24
+ 'Density must be specified for non-VOID materials',
25
+ 'density',
26
+ args.density
27
+ );
28
+ }
29
+
30
+ const result = await taskManager.proposeZone(args.body_name, args.material, args.density);
31
+ return { success: true, message: result };
32
+ } catch (error) {
33
+ logger.error('proposeZoneハンドラーエラー', { args, error: error.message });
34
+ throw error;
35
+ }
36
+ },
37
+
38
+ async updateZone(args) {
39
+ try {
40
+ if (!args.body_name) throw new ValidationError('立体名は必須です', 'body_name', args.body_name);
41
+
42
+ // 材料更新時の密度制約チェック
43
+ if (args.material !== undefined) {
44
+ // VOID材料での密度指定チェック
45
+ if (args.material === 'VOID' && args.density !== undefined) {
46
+ throw new ValidationError(
47
+ 'Density cannot be specified for VOID material',
48
+ 'density',
49
+ args.density
50
+ );
51
+ }
52
+
53
+ // 非VOID材料での密度必須チェック
54
+ if (args.material !== 'VOID' && args.density === undefined) {
55
+ throw new ValidationError(
56
+ 'Density must be specified for non-VOID materials',
57
+ 'density',
58
+ args.density
59
+ );
60
+ }
61
+ }
62
+
63
+ const { body_name, ...updates } = args;
64
+ const result = await taskManager.updateZone(body_name, updates);
65
+ return { success: true, message: result };
66
+ } catch (error) {
67
+ logger.error('updateZoneハンドラーエラー', { args, error: error.message });
68
+ throw error;
69
+ }
70
+ },
71
+
72
+ async deleteZone(args) {
73
+ try {
74
+ if (!args.body_name) throw new ValidationError('立体名は必須です', 'body_name', args.body_name);
75
+ const result = await taskManager.deleteZone(args.body_name);
76
+ return { success: true, message: result };
77
+ } catch (error) {
78
+ logger.error('deleteZoneハンドラーエラー', { args, error: error.message });
79
+ throw error;
80
+ }
81
+ }
82
+ };
83
+ }