hatch-xclam 0.7.1.dev3__py3-none-any.whl → 0.8.0.dev1__py3-none-any.whl
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.
- hatch/__init__.py +1 -1
- hatch/cli/__init__.py +71 -0
- hatch/cli/__main__.py +1035 -0
- hatch/cli/cli_env.py +865 -0
- hatch/cli/cli_mcp.py +1965 -0
- hatch/cli/cli_package.py +566 -0
- hatch/cli/cli_system.py +136 -0
- hatch/cli/cli_utils.py +1289 -0
- hatch/cli_hatch.py +160 -2838
- hatch/mcp_host_config/__init__.py +10 -10
- hatch/mcp_host_config/adapters/__init__.py +34 -0
- hatch/mcp_host_config/adapters/base.py +170 -0
- hatch/mcp_host_config/adapters/claude.py +105 -0
- hatch/mcp_host_config/adapters/codex.py +104 -0
- hatch/mcp_host_config/adapters/cursor.py +83 -0
- hatch/mcp_host_config/adapters/gemini.py +75 -0
- hatch/mcp_host_config/adapters/kiro.py +78 -0
- hatch/mcp_host_config/adapters/lmstudio.py +79 -0
- hatch/mcp_host_config/adapters/registry.py +149 -0
- hatch/mcp_host_config/adapters/vscode.py +83 -0
- hatch/mcp_host_config/backup.py +5 -3
- hatch/mcp_host_config/fields.py +126 -0
- hatch/mcp_host_config/models.py +161 -456
- hatch/mcp_host_config/reporting.py +57 -16
- hatch/mcp_host_config/strategies.py +155 -87
- hatch/template_generator.py +1 -1
- {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/METADATA +3 -2
- {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/RECORD +52 -43
- {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/WHEEL +1 -1
- hatch_xclam-0.8.0.dev1.dist-info/entry_points.txt +2 -0
- tests/cli_test_utils.py +280 -0
- tests/integration/cli/__init__.py +14 -0
- tests/integration/cli/test_cli_reporter_integration.py +2439 -0
- tests/integration/mcp/__init__.py +0 -0
- tests/integration/mcp/test_adapter_serialization.py +173 -0
- tests/regression/cli/__init__.py +16 -0
- tests/regression/cli/test_color_logic.py +268 -0
- tests/regression/cli/test_consequence_type.py +298 -0
- tests/regression/cli/test_error_formatting.py +328 -0
- tests/regression/cli/test_result_reporter.py +586 -0
- tests/regression/cli/test_table_formatter.py +211 -0
- tests/regression/mcp/__init__.py +0 -0
- tests/regression/mcp/test_field_filtering.py +162 -0
- tests/test_cli_version.py +7 -5
- tests/test_data/fixtures/cli_reporter_fixtures.py +184 -0
- tests/unit/__init__.py +0 -0
- tests/unit/mcp/__init__.py +0 -0
- tests/unit/mcp/test_adapter_protocol.py +138 -0
- tests/unit/mcp/test_adapter_registry.py +158 -0
- tests/unit/mcp/test_config_model.py +146 -0
- hatch_xclam-0.7.1.dev3.dist-info/entry_points.txt +0 -2
- tests/integration/test_mcp_kiro_integration.py +0 -153
- tests/regression/test_mcp_codex_backup_integration.py +0 -162
- tests/regression/test_mcp_codex_host_strategy.py +0 -163
- tests/regression/test_mcp_codex_model_validation.py +0 -117
- tests/regression/test_mcp_kiro_backup_integration.py +0 -241
- tests/regression/test_mcp_kiro_cli_integration.py +0 -141
- tests/regression/test_mcp_kiro_decorator_registration.py +0 -71
- tests/regression/test_mcp_kiro_host_strategy.py +0 -214
- tests/regression/test_mcp_kiro_model_validation.py +0 -116
- tests/regression/test_mcp_kiro_omni_conversion.py +0 -104
- tests/test_mcp_atomic_operations.py +0 -276
- tests/test_mcp_backup_integration.py +0 -308
- tests/test_mcp_cli_all_host_specific_args.py +0 -496
- tests/test_mcp_cli_backup_management.py +0 -295
- tests/test_mcp_cli_direct_management.py +0 -456
- tests/test_mcp_cli_discovery_listing.py +0 -582
- tests/test_mcp_cli_host_config_integration.py +0 -823
- tests/test_mcp_cli_package_management.py +0 -360
- tests/test_mcp_cli_partial_updates.py +0 -859
- tests/test_mcp_environment_integration.py +0 -520
- tests/test_mcp_host_config_backup.py +0 -257
- tests/test_mcp_host_configuration_manager.py +0 -331
- tests/test_mcp_host_registry_decorator.py +0 -348
- tests/test_mcp_pydantic_architecture_v4.py +0 -603
- tests/test_mcp_server_config_models.py +0 -242
- tests/test_mcp_server_config_type_field.py +0 -221
- tests/test_mcp_sync_functionality.py +0 -316
- tests/test_mcp_user_feedback_reporting.py +0 -359
- {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/licenses/LICENSE +0 -0
- {hatch_xclam-0.7.1.dev3.dist-info → hatch_xclam-0.8.0.dev1.dist-info}/top_level.txt +0 -0
|
@@ -1,348 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Test suite for decorator-based host registry.
|
|
3
|
-
|
|
4
|
-
This module tests the decorator-based strategy registration system
|
|
5
|
-
following Hatchling patterns with inheritance validation.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import unittest
|
|
9
|
-
import sys
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
|
|
12
|
-
# Add the parent directory to the path to import wobble
|
|
13
|
-
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
14
|
-
|
|
15
|
-
try:
|
|
16
|
-
from wobble.decorators import regression_test, integration_test
|
|
17
|
-
except ImportError:
|
|
18
|
-
# Fallback decorators if wobble is not available
|
|
19
|
-
def regression_test(func):
|
|
20
|
-
return func
|
|
21
|
-
|
|
22
|
-
def integration_test(scope="component"):
|
|
23
|
-
def decorator(func):
|
|
24
|
-
return func
|
|
25
|
-
return decorator
|
|
26
|
-
|
|
27
|
-
from hatch.mcp_host_config.host_management import MCPHostRegistry, register_host_strategy, MCPHostStrategy
|
|
28
|
-
from hatch.mcp_host_config.models import MCPHostType, MCPServerConfig, HostConfiguration
|
|
29
|
-
from pathlib import Path
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
class TestMCPHostRegistryDecorator(unittest.TestCase):
|
|
33
|
-
"""Test suite for decorator-based host registry."""
|
|
34
|
-
|
|
35
|
-
def setUp(self):
|
|
36
|
-
"""Set up test environment."""
|
|
37
|
-
# Clear registry before each test
|
|
38
|
-
MCPHostRegistry._strategies.clear()
|
|
39
|
-
MCPHostRegistry._instances.clear()
|
|
40
|
-
|
|
41
|
-
def tearDown(self):
|
|
42
|
-
"""Clean up test environment."""
|
|
43
|
-
# Clear registry after each test
|
|
44
|
-
MCPHostRegistry._strategies.clear()
|
|
45
|
-
MCPHostRegistry._instances.clear()
|
|
46
|
-
|
|
47
|
-
@regression_test
|
|
48
|
-
def test_decorator_registration_functionality(self):
|
|
49
|
-
"""Test that decorator registration works correctly."""
|
|
50
|
-
|
|
51
|
-
@register_host_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
52
|
-
class TestClaudeStrategy(MCPHostStrategy):
|
|
53
|
-
def get_config_path(self):
|
|
54
|
-
return Path("/test/path")
|
|
55
|
-
def is_host_available(self):
|
|
56
|
-
return True
|
|
57
|
-
def read_configuration(self):
|
|
58
|
-
return HostConfiguration()
|
|
59
|
-
def write_configuration(self, config, no_backup=False):
|
|
60
|
-
return True
|
|
61
|
-
def validate_server_config(self, server_config):
|
|
62
|
-
return True
|
|
63
|
-
|
|
64
|
-
# Verify registration
|
|
65
|
-
self.assertIn(MCPHostType.CLAUDE_DESKTOP, MCPHostRegistry._strategies)
|
|
66
|
-
self.assertEqual(
|
|
67
|
-
MCPHostRegistry._strategies[MCPHostType.CLAUDE_DESKTOP],
|
|
68
|
-
TestClaudeStrategy
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
# Verify instance creation
|
|
72
|
-
strategy = MCPHostRegistry.get_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
73
|
-
self.assertIsInstance(strategy, TestClaudeStrategy)
|
|
74
|
-
|
|
75
|
-
@regression_test
|
|
76
|
-
def test_decorator_registration_with_inheritance(self):
|
|
77
|
-
"""Test decorator registration with inheritance patterns."""
|
|
78
|
-
|
|
79
|
-
class TestClaudeBase(MCPHostStrategy):
|
|
80
|
-
def __init__(self):
|
|
81
|
-
self.company_origin = "Anthropic"
|
|
82
|
-
self.config_format = "claude_format"
|
|
83
|
-
|
|
84
|
-
def get_config_key(self):
|
|
85
|
-
return "mcpServers"
|
|
86
|
-
|
|
87
|
-
@register_host_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
88
|
-
class TestClaudeDesktop(TestClaudeBase):
|
|
89
|
-
def get_config_path(self):
|
|
90
|
-
return Path("/test/claude")
|
|
91
|
-
def is_host_available(self):
|
|
92
|
-
return True
|
|
93
|
-
def read_configuration(self):
|
|
94
|
-
return HostConfiguration()
|
|
95
|
-
def write_configuration(self, config, no_backup=False):
|
|
96
|
-
return True
|
|
97
|
-
def validate_server_config(self, server_config):
|
|
98
|
-
return True
|
|
99
|
-
|
|
100
|
-
strategy = MCPHostRegistry.get_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
101
|
-
|
|
102
|
-
# Verify inheritance properties
|
|
103
|
-
self.assertEqual(strategy.company_origin, "Anthropic")
|
|
104
|
-
self.assertEqual(strategy.config_format, "claude_format")
|
|
105
|
-
self.assertEqual(strategy.get_config_key(), "mcpServers")
|
|
106
|
-
self.assertIsInstance(strategy, TestClaudeBase)
|
|
107
|
-
|
|
108
|
-
@regression_test
|
|
109
|
-
def test_decorator_registration_duplicate_warning(self):
|
|
110
|
-
"""Test warning on duplicate strategy registration."""
|
|
111
|
-
import logging
|
|
112
|
-
|
|
113
|
-
class BaseTestStrategy(MCPHostStrategy):
|
|
114
|
-
def get_config_path(self):
|
|
115
|
-
return Path("/test")
|
|
116
|
-
def is_host_available(self):
|
|
117
|
-
return True
|
|
118
|
-
def read_configuration(self):
|
|
119
|
-
return HostConfiguration()
|
|
120
|
-
def write_configuration(self, config, no_backup=False):
|
|
121
|
-
return True
|
|
122
|
-
def validate_server_config(self, server_config):
|
|
123
|
-
return True
|
|
124
|
-
|
|
125
|
-
@register_host_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
126
|
-
class FirstStrategy(BaseTestStrategy):
|
|
127
|
-
pass
|
|
128
|
-
|
|
129
|
-
# Register second strategy for same host type - should log warning
|
|
130
|
-
with self.assertLogs('hatch.mcp_host_config.host_management', level='WARNING') as log:
|
|
131
|
-
@register_host_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
132
|
-
class SecondStrategy(BaseTestStrategy):
|
|
133
|
-
pass
|
|
134
|
-
|
|
135
|
-
# Verify warning was logged
|
|
136
|
-
self.assertTrue(any("Overriding existing strategy" in message for message in log.output))
|
|
137
|
-
|
|
138
|
-
# Verify second strategy is now registered
|
|
139
|
-
strategy = MCPHostRegistry.get_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
140
|
-
self.assertIsInstance(strategy, SecondStrategy)
|
|
141
|
-
|
|
142
|
-
@regression_test
|
|
143
|
-
def test_decorator_registration_inheritance_validation(self):
|
|
144
|
-
"""Test that decorator validates inheritance from MCPHostStrategy."""
|
|
145
|
-
|
|
146
|
-
# Should raise ValueError for non-MCPHostStrategy class
|
|
147
|
-
with self.assertRaises(ValueError) as context:
|
|
148
|
-
@register_host_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
149
|
-
class InvalidStrategy: # Does not inherit from MCPHostStrategy
|
|
150
|
-
pass
|
|
151
|
-
|
|
152
|
-
self.assertIn("must inherit from MCPHostStrategy", str(context.exception))
|
|
153
|
-
|
|
154
|
-
@regression_test
|
|
155
|
-
def test_registry_get_strategy_unknown_host_type(self):
|
|
156
|
-
"""Test error handling for unknown host type."""
|
|
157
|
-
# Clear registry to ensure no strategies are registered
|
|
158
|
-
MCPHostRegistry._strategies.clear()
|
|
159
|
-
|
|
160
|
-
with self.assertRaises(ValueError) as context:
|
|
161
|
-
MCPHostRegistry.get_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
162
|
-
|
|
163
|
-
self.assertIn("Unknown host type", str(context.exception))
|
|
164
|
-
self.assertIn("Available: []", str(context.exception))
|
|
165
|
-
|
|
166
|
-
@regression_test
|
|
167
|
-
def test_registry_singleton_instance_behavior(self):
|
|
168
|
-
"""Test that registry returns singleton instances."""
|
|
169
|
-
|
|
170
|
-
@register_host_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
171
|
-
class TestStrategy(MCPHostStrategy):
|
|
172
|
-
def __init__(self):
|
|
173
|
-
self.instance_id = id(self)
|
|
174
|
-
|
|
175
|
-
def get_config_path(self):
|
|
176
|
-
return Path("/test")
|
|
177
|
-
def is_host_available(self):
|
|
178
|
-
return True
|
|
179
|
-
def read_configuration(self):
|
|
180
|
-
return HostConfiguration()
|
|
181
|
-
def write_configuration(self, config, no_backup=False):
|
|
182
|
-
return True
|
|
183
|
-
def validate_server_config(self, server_config):
|
|
184
|
-
return True
|
|
185
|
-
|
|
186
|
-
# Get strategy multiple times
|
|
187
|
-
strategy1 = MCPHostRegistry.get_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
188
|
-
strategy2 = MCPHostRegistry.get_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
189
|
-
|
|
190
|
-
# Should be the same instance
|
|
191
|
-
self.assertIs(strategy1, strategy2)
|
|
192
|
-
self.assertEqual(strategy1.instance_id, strategy2.instance_id)
|
|
193
|
-
|
|
194
|
-
@regression_test
|
|
195
|
-
def test_registry_detect_available_hosts(self):
|
|
196
|
-
"""Test host detection functionality."""
|
|
197
|
-
|
|
198
|
-
@register_host_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
199
|
-
class AvailableStrategy(MCPHostStrategy):
|
|
200
|
-
def get_config_path(self):
|
|
201
|
-
return Path("/test")
|
|
202
|
-
def is_host_available(self):
|
|
203
|
-
return True # Available
|
|
204
|
-
def read_configuration(self):
|
|
205
|
-
return HostConfiguration()
|
|
206
|
-
def write_configuration(self, config, no_backup=False):
|
|
207
|
-
return True
|
|
208
|
-
def validate_server_config(self, server_config):
|
|
209
|
-
return True
|
|
210
|
-
|
|
211
|
-
@register_host_strategy(MCPHostType.CURSOR)
|
|
212
|
-
class UnavailableStrategy(MCPHostStrategy):
|
|
213
|
-
def get_config_path(self):
|
|
214
|
-
return Path("/test")
|
|
215
|
-
def is_host_available(self):
|
|
216
|
-
return False # Not available
|
|
217
|
-
def read_configuration(self):
|
|
218
|
-
return HostConfiguration()
|
|
219
|
-
def write_configuration(self, config, no_backup=False):
|
|
220
|
-
return True
|
|
221
|
-
def validate_server_config(self, server_config):
|
|
222
|
-
return True
|
|
223
|
-
|
|
224
|
-
@register_host_strategy(MCPHostType.VSCODE)
|
|
225
|
-
class ErrorStrategy(MCPHostStrategy):
|
|
226
|
-
def get_config_path(self):
|
|
227
|
-
return Path("/test")
|
|
228
|
-
def is_host_available(self):
|
|
229
|
-
raise Exception("Detection error") # Error during detection
|
|
230
|
-
def read_configuration(self):
|
|
231
|
-
return HostConfiguration()
|
|
232
|
-
def write_configuration(self, config, no_backup=False):
|
|
233
|
-
return True
|
|
234
|
-
def validate_server_config(self, server_config):
|
|
235
|
-
return True
|
|
236
|
-
|
|
237
|
-
available_hosts = MCPHostRegistry.detect_available_hosts()
|
|
238
|
-
|
|
239
|
-
# Only the available strategy should be detected
|
|
240
|
-
self.assertIn(MCPHostType.CLAUDE_DESKTOP, available_hosts)
|
|
241
|
-
self.assertNotIn(MCPHostType.CURSOR, available_hosts)
|
|
242
|
-
self.assertNotIn(MCPHostType.VSCODE, available_hosts)
|
|
243
|
-
|
|
244
|
-
@regression_test
|
|
245
|
-
def test_registry_family_mappings(self):
|
|
246
|
-
"""Test family host mappings."""
|
|
247
|
-
claude_family = MCPHostRegistry.get_family_hosts("claude")
|
|
248
|
-
cursor_family = MCPHostRegistry.get_family_hosts("cursor")
|
|
249
|
-
unknown_family = MCPHostRegistry.get_family_hosts("unknown")
|
|
250
|
-
|
|
251
|
-
# Verify family mappings
|
|
252
|
-
self.assertIn(MCPHostType.CLAUDE_DESKTOP, claude_family)
|
|
253
|
-
self.assertIn(MCPHostType.CLAUDE_CODE, claude_family)
|
|
254
|
-
self.assertIn(MCPHostType.CURSOR, cursor_family)
|
|
255
|
-
self.assertIn(MCPHostType.LMSTUDIO, cursor_family)
|
|
256
|
-
self.assertEqual(unknown_family, [])
|
|
257
|
-
|
|
258
|
-
@regression_test
|
|
259
|
-
def test_registry_get_host_config_path(self):
|
|
260
|
-
"""Test getting host configuration path through registry."""
|
|
261
|
-
|
|
262
|
-
@register_host_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
263
|
-
class TestStrategy(MCPHostStrategy):
|
|
264
|
-
def get_config_path(self):
|
|
265
|
-
return Path("/test/claude/config.json")
|
|
266
|
-
def is_host_available(self):
|
|
267
|
-
return True
|
|
268
|
-
def read_configuration(self):
|
|
269
|
-
return HostConfiguration()
|
|
270
|
-
def write_configuration(self, config, no_backup=False):
|
|
271
|
-
return True
|
|
272
|
-
def validate_server_config(self, server_config):
|
|
273
|
-
return True
|
|
274
|
-
|
|
275
|
-
config_path = MCPHostRegistry.get_host_config_path(MCPHostType.CLAUDE_DESKTOP)
|
|
276
|
-
self.assertEqual(config_path, Path("/test/claude/config.json"))
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
class TestFamilyBasedStrategyRegistration(unittest.TestCase):
|
|
280
|
-
"""Test suite for family-based strategy registration with decorators."""
|
|
281
|
-
|
|
282
|
-
def setUp(self):
|
|
283
|
-
"""Set up test environment."""
|
|
284
|
-
# Clear registry before each test
|
|
285
|
-
MCPHostRegistry._strategies.clear()
|
|
286
|
-
MCPHostRegistry._instances.clear()
|
|
287
|
-
|
|
288
|
-
def tearDown(self):
|
|
289
|
-
"""Clean up test environment."""
|
|
290
|
-
# Clear registry after each test
|
|
291
|
-
MCPHostRegistry._strategies.clear()
|
|
292
|
-
MCPHostRegistry._instances.clear()
|
|
293
|
-
|
|
294
|
-
@regression_test
|
|
295
|
-
def test_claude_family_decorator_registration(self):
|
|
296
|
-
"""Test Claude family strategies register with decorators."""
|
|
297
|
-
|
|
298
|
-
class TestClaudeBase(MCPHostStrategy):
|
|
299
|
-
def __init__(self):
|
|
300
|
-
self.company_origin = "Anthropic"
|
|
301
|
-
self.config_format = "claude_format"
|
|
302
|
-
|
|
303
|
-
def validate_server_config(self, server_config):
|
|
304
|
-
# Claude family accepts any valid command or URL
|
|
305
|
-
if server_config.command or server_config.url:
|
|
306
|
-
return True
|
|
307
|
-
return False
|
|
308
|
-
|
|
309
|
-
@register_host_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
310
|
-
class TestClaudeDesktop(TestClaudeBase):
|
|
311
|
-
def get_config_path(self):
|
|
312
|
-
return Path("/test/claude_desktop")
|
|
313
|
-
def is_host_available(self):
|
|
314
|
-
return True
|
|
315
|
-
def read_configuration(self):
|
|
316
|
-
return HostConfiguration()
|
|
317
|
-
def write_configuration(self, config, no_backup=False):
|
|
318
|
-
return True
|
|
319
|
-
|
|
320
|
-
@register_host_strategy(MCPHostType.CLAUDE_CODE)
|
|
321
|
-
class TestClaudeCode(TestClaudeBase):
|
|
322
|
-
def get_config_path(self):
|
|
323
|
-
return Path("/test/claude_code")
|
|
324
|
-
def is_host_available(self):
|
|
325
|
-
return True
|
|
326
|
-
def read_configuration(self):
|
|
327
|
-
return HostConfiguration()
|
|
328
|
-
def write_configuration(self, config, no_backup=False):
|
|
329
|
-
return True
|
|
330
|
-
|
|
331
|
-
# Verify both strategies are registered
|
|
332
|
-
claude_desktop = MCPHostRegistry.get_strategy(MCPHostType.CLAUDE_DESKTOP)
|
|
333
|
-
claude_code = MCPHostRegistry.get_strategy(MCPHostType.CLAUDE_CODE)
|
|
334
|
-
|
|
335
|
-
# Verify inheritance properties
|
|
336
|
-
self.assertEqual(claude_desktop.company_origin, "Anthropic")
|
|
337
|
-
self.assertEqual(claude_code.company_origin, "Anthropic")
|
|
338
|
-
self.assertIsInstance(claude_desktop, TestClaudeBase)
|
|
339
|
-
self.assertIsInstance(claude_code, TestClaudeBase)
|
|
340
|
-
|
|
341
|
-
# Verify family mappings
|
|
342
|
-
claude_family = MCPHostRegistry.get_family_hosts("claude")
|
|
343
|
-
self.assertIn(MCPHostType.CLAUDE_DESKTOP, claude_family)
|
|
344
|
-
self.assertIn(MCPHostType.CLAUDE_CODE, claude_family)
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
if __name__ == '__main__':
|
|
348
|
-
unittest.main()
|