claude-mpm 4.13.1__py3-none-any.whl → 4.14.0__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.

Potentially problematic release.


This version of claude-mpm might be problematic. Click here for more details.

Files changed (50) hide show
  1. claude_mpm/VERSION +1 -1
  2. claude_mpm/agents/PM_INSTRUCTIONS.md +68 -0
  3. claude_mpm/cli/__init__.py +10 -0
  4. claude_mpm/cli/commands/local_deploy.py +536 -0
  5. claude_mpm/cli/parsers/base_parser.py +7 -0
  6. claude_mpm/cli/parsers/local_deploy_parser.py +227 -0
  7. claude_mpm/commands/mpm-agents-detect.md +168 -0
  8. claude_mpm/commands/mpm-agents-recommend.md +214 -0
  9. claude_mpm/commands/mpm-agents.md +75 -1
  10. claude_mpm/commands/mpm-auto-configure.md +217 -0
  11. claude_mpm/commands/mpm-help.md +160 -0
  12. claude_mpm/config/model_config.py +428 -0
  13. claude_mpm/core/interactive_session.py +3 -0
  14. claude_mpm/services/core/interfaces/__init__.py +74 -2
  15. claude_mpm/services/core/interfaces/health.py +172 -0
  16. claude_mpm/services/core/interfaces/model.py +281 -0
  17. claude_mpm/services/core/interfaces/process.py +372 -0
  18. claude_mpm/services/core/interfaces/restart.py +307 -0
  19. claude_mpm/services/core/interfaces/stability.py +260 -0
  20. claude_mpm/services/core/models/__init__.py +35 -0
  21. claude_mpm/services/core/models/health.py +189 -0
  22. claude_mpm/services/core/models/process.py +258 -0
  23. claude_mpm/services/core/models/restart.py +302 -0
  24. claude_mpm/services/core/models/stability.py +264 -0
  25. claude_mpm/services/local_ops/__init__.py +163 -0
  26. claude_mpm/services/local_ops/crash_detector.py +257 -0
  27. claude_mpm/services/local_ops/health_checks/__init__.py +28 -0
  28. claude_mpm/services/local_ops/health_checks/http_check.py +223 -0
  29. claude_mpm/services/local_ops/health_checks/process_check.py +235 -0
  30. claude_mpm/services/local_ops/health_checks/resource_check.py +254 -0
  31. claude_mpm/services/local_ops/health_manager.py +430 -0
  32. claude_mpm/services/local_ops/log_monitor.py +396 -0
  33. claude_mpm/services/local_ops/memory_leak_detector.py +294 -0
  34. claude_mpm/services/local_ops/process_manager.py +595 -0
  35. claude_mpm/services/local_ops/resource_monitor.py +331 -0
  36. claude_mpm/services/local_ops/restart_manager.py +401 -0
  37. claude_mpm/services/local_ops/restart_policy.py +387 -0
  38. claude_mpm/services/local_ops/state_manager.py +371 -0
  39. claude_mpm/services/local_ops/unified_manager.py +600 -0
  40. claude_mpm/services/model/__init__.py +147 -0
  41. claude_mpm/services/model/base_provider.py +365 -0
  42. claude_mpm/services/model/claude_provider.py +412 -0
  43. claude_mpm/services/model/model_router.py +453 -0
  44. claude_mpm/services/model/ollama_provider.py +415 -0
  45. {claude_mpm-4.13.1.dist-info → claude_mpm-4.14.0.dist-info}/METADATA +1 -1
  46. {claude_mpm-4.13.1.dist-info → claude_mpm-4.14.0.dist-info}/RECORD +50 -15
  47. {claude_mpm-4.13.1.dist-info → claude_mpm-4.14.0.dist-info}/WHEEL +0 -0
  48. {claude_mpm-4.13.1.dist-info → claude_mpm-4.14.0.dist-info}/entry_points.txt +0 -0
  49. {claude_mpm-4.13.1.dist-info → claude_mpm-4.14.0.dist-info}/licenses/LICENSE +0 -0
  50. {claude_mpm-4.13.1.dist-info → claude_mpm-4.14.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,428 @@
1
+ """
2
+ Model Configuration Management for Claude MPM Framework
3
+ =======================================================
4
+
5
+ WHY: Centralizes configuration for model providers, routing strategy, and
6
+ model selection. Supports configuration files, environment variables, and
7
+ programmatic configuration.
8
+
9
+ DESIGN DECISION: Uses Pydantic for configuration validation and type safety.
10
+ Supports loading from YAML files and environment variables with sensible defaults.
11
+
12
+ CONFIGURATION STRUCTURE:
13
+ ```yaml
14
+ content_agent:
15
+ model_provider: auto # auto|ollama|claude|privacy
16
+
17
+ ollama:
18
+ enabled: true
19
+ host: http://localhost:11434
20
+ fallback_to_cloud: true
21
+ timeout: 30
22
+ models:
23
+ seo_analysis: llama3.3:70b
24
+ readability: gemma2:9b
25
+ grammar: qwen3:14b
26
+ summarization: mistral:7b
27
+ keyword_extraction: seoassistant
28
+
29
+ claude:
30
+ enabled: true
31
+ model: claude-3-5-sonnet-20241022
32
+ max_tokens: 4096
33
+ temperature: 0.7
34
+ ```
35
+
36
+ ENVIRONMENT VARIABLES:
37
+ - MODEL_PROVIDER: Override provider strategy
38
+ - OLLAMA_HOST: Override Ollama endpoint
39
+ - OLLAMA_ENABLED: Enable/disable Ollama
40
+ - CLAUDE_ENABLED: Enable/disable Claude
41
+ - ANTHROPIC_API_KEY: Claude API key
42
+ """
43
+
44
+ import os
45
+ from pathlib import Path
46
+ from typing import Any, Dict, Optional
47
+
48
+ from pydantic import BaseModel, Field
49
+
50
+ try:
51
+ import yaml
52
+ except ImportError:
53
+ yaml = None # type: ignore
54
+
55
+
56
+ class OllamaConfig(BaseModel):
57
+ """
58
+ Configuration for Ollama provider.
59
+
60
+ WHY: Separates Ollama-specific settings for better organization
61
+ and validation.
62
+ """
63
+
64
+ enabled: bool = Field(default=True, description="Enable Ollama provider")
65
+ host: str = Field(
66
+ default="http://localhost:11434",
67
+ description="Ollama API endpoint",
68
+ )
69
+ fallback_to_cloud: bool = Field(
70
+ default=True,
71
+ description="Allow fallback to cloud on Ollama failure",
72
+ )
73
+ timeout: int = Field(default=30, description="Request timeout in seconds")
74
+ models: Dict[str, str] = Field(
75
+ default_factory=dict,
76
+ description="Task-specific model mappings",
77
+ )
78
+
79
+ class Config:
80
+ """Pydantic config."""
81
+
82
+ extra = "allow"
83
+
84
+
85
+ class ClaudeConfig(BaseModel):
86
+ """
87
+ Configuration for Claude provider.
88
+
89
+ WHY: Separates Claude-specific settings for better organization
90
+ and validation.
91
+ """
92
+
93
+ enabled: bool = Field(default=True, description="Enable Claude provider")
94
+ model: str = Field(
95
+ default="claude-3-5-sonnet-20241022",
96
+ description="Default Claude model",
97
+ )
98
+ max_tokens: int = Field(
99
+ default=4096,
100
+ description="Maximum response tokens",
101
+ )
102
+ temperature: float = Field(
103
+ default=0.7,
104
+ description="Sampling temperature (0.0-1.0)",
105
+ )
106
+ api_key: Optional[str] = Field(
107
+ default=None,
108
+ description="Anthropic API key (can use env var)",
109
+ )
110
+
111
+ class Config:
112
+ """Pydantic config."""
113
+
114
+ extra = "allow"
115
+
116
+
117
+ class ModelProviderConfig(BaseModel):
118
+ """
119
+ Main model provider configuration.
120
+
121
+ WHY: Top-level configuration containing all model-related settings.
122
+ Validates configuration at load time to catch errors early.
123
+ """
124
+
125
+ provider: str = Field(
126
+ default="auto",
127
+ description="Provider strategy: auto|ollama|claude|privacy",
128
+ )
129
+ ollama: OllamaConfig = Field(
130
+ default_factory=OllamaConfig,
131
+ description="Ollama provider configuration",
132
+ )
133
+ claude: ClaudeConfig = Field(
134
+ default_factory=ClaudeConfig,
135
+ description="Claude provider configuration",
136
+ )
137
+
138
+ class Config:
139
+ """Pydantic config."""
140
+
141
+ extra = "allow"
142
+
143
+
144
+ class ModelConfigManager:
145
+ """
146
+ Manager for model configuration.
147
+
148
+ WHY: Provides centralized configuration loading with support for
149
+ multiple sources (files, env vars, defaults) and validation.
150
+
151
+ Usage:
152
+ manager = ModelConfigManager()
153
+ config = manager.load_config()
154
+
155
+ # Get router config
156
+ router_config = manager.get_router_config(config)
157
+
158
+ # Get provider configs
159
+ ollama_config = manager.get_ollama_config(config)
160
+ claude_config = manager.get_claude_config(config)
161
+ """
162
+
163
+ DEFAULT_CONFIG_PATHS = [
164
+ ".claude/configuration.yaml",
165
+ "configuration.yaml",
166
+ ".claude-mpm/configuration.yaml",
167
+ str(Path("~/.claude-mpm/configuration.yaml").expanduser()),
168
+ ]
169
+
170
+ @staticmethod
171
+ def load_config(
172
+ config_path: Optional[str] = None,
173
+ ) -> ModelProviderConfig:
174
+ """
175
+ Load model configuration from file and environment.
176
+
177
+ WHY: Supports multiple configuration sources with priority:
178
+ 1. Explicit config_path parameter
179
+ 2. Environment variables
180
+ 3. Configuration file
181
+ 4. Default values
182
+
183
+ Args:
184
+ config_path: Optional path to configuration file
185
+
186
+ Returns:
187
+ ModelProviderConfig with merged settings
188
+ """
189
+ config_data: Dict[str, Any] = {}
190
+
191
+ # Try to load from file
192
+ if config_path and Path(config_path).exists():
193
+ config_data = ModelConfigManager._load_yaml_file(config_path)
194
+ else:
195
+ # Try default paths
196
+ for default_path in ModelConfigManager.DEFAULT_CONFIG_PATHS:
197
+ if Path(default_path).exists():
198
+ config_data = ModelConfigManager._load_yaml_file(default_path)
199
+ break
200
+
201
+ # Extract content_agent section if present
202
+ if "content_agent" in config_data:
203
+ config_data = config_data["content_agent"]
204
+
205
+ # Override with environment variables
206
+ config_data = ModelConfigManager._apply_env_overrides(config_data)
207
+
208
+ # Create and validate config
209
+ try:
210
+ return ModelProviderConfig(**config_data)
211
+ except Exception as e:
212
+ # If validation fails, return default config
213
+ print(f"Warning: Failed to load config: {e}. Using defaults.")
214
+ return ModelProviderConfig()
215
+
216
+ @staticmethod
217
+ def _load_yaml_file(path: str) -> Dict[str, Any]:
218
+ """
219
+ Load YAML configuration file.
220
+
221
+ Args:
222
+ path: Path to YAML file
223
+
224
+ Returns:
225
+ Dictionary of configuration
226
+ """
227
+ if yaml is None:
228
+ return {}
229
+
230
+ try:
231
+ path_obj = Path(path)
232
+ with path_obj.open() as f:
233
+ data = yaml.safe_load(f)
234
+ return data or {}
235
+ except Exception as e:
236
+ print(f"Warning: Failed to load {path}: {e}")
237
+ return {}
238
+
239
+ @staticmethod
240
+ def _apply_env_overrides(config: Dict[str, Any]) -> Dict[str, Any]:
241
+ """
242
+ Apply environment variable overrides.
243
+
244
+ WHY: Allows runtime configuration without modifying files.
245
+ Useful for containerized deployments and CI/CD.
246
+
247
+ Args:
248
+ config: Base configuration
249
+
250
+ Returns:
251
+ Configuration with env overrides applied
252
+ """
253
+ # Provider strategy
254
+ if "MODEL_PROVIDER" in os.environ:
255
+ config["provider"] = os.environ["MODEL_PROVIDER"]
256
+
257
+ # Ollama settings
258
+ if "ollama" not in config:
259
+ config["ollama"] = {}
260
+
261
+ if "OLLAMA_ENABLED" in os.environ:
262
+ config["ollama"]["enabled"] = os.environ["OLLAMA_ENABLED"].lower() == "true"
263
+
264
+ if "OLLAMA_HOST" in os.environ:
265
+ config["ollama"]["host"] = os.environ["OLLAMA_HOST"]
266
+
267
+ if "OLLAMA_TIMEOUT" in os.environ:
268
+ try:
269
+ config["ollama"]["timeout"] = int(os.environ["OLLAMA_TIMEOUT"])
270
+ except ValueError:
271
+ pass
272
+
273
+ if "OLLAMA_FALLBACK_TO_CLOUD" in os.environ:
274
+ config["ollama"]["fallback_to_cloud"] = (
275
+ os.environ["OLLAMA_FALLBACK_TO_CLOUD"].lower() == "true"
276
+ )
277
+
278
+ # Claude settings
279
+ if "claude" not in config:
280
+ config["claude"] = {}
281
+
282
+ if "CLAUDE_ENABLED" in os.environ:
283
+ config["claude"]["enabled"] = os.environ["CLAUDE_ENABLED"].lower() == "true"
284
+
285
+ if "ANTHROPIC_API_KEY" in os.environ:
286
+ config["claude"]["api_key"] = os.environ["ANTHROPIC_API_KEY"]
287
+
288
+ if "CLAUDE_MODEL" in os.environ:
289
+ config["claude"]["model"] = os.environ["CLAUDE_MODEL"]
290
+
291
+ if "CLAUDE_MAX_TOKENS" in os.environ:
292
+ try:
293
+ config["claude"]["max_tokens"] = int(os.environ["CLAUDE_MAX_TOKENS"])
294
+ except ValueError:
295
+ pass
296
+
297
+ if "CLAUDE_TEMPERATURE" in os.environ:
298
+ try:
299
+ config["claude"]["temperature"] = float(
300
+ os.environ["CLAUDE_TEMPERATURE"]
301
+ )
302
+ except ValueError:
303
+ pass
304
+
305
+ return config
306
+
307
+ @staticmethod
308
+ def get_router_config(config: ModelProviderConfig) -> Dict[str, Any]:
309
+ """
310
+ Get router configuration from model config.
311
+
312
+ Args:
313
+ config: Model provider configuration
314
+
315
+ Returns:
316
+ Dictionary suitable for ModelRouter initialization
317
+ """
318
+ return {
319
+ "strategy": config.provider,
320
+ "fallback_enabled": config.ollama.fallback_to_cloud,
321
+ "ollama_config": ModelConfigManager.get_ollama_config(config),
322
+ "claude_config": ModelConfigManager.get_claude_config(config),
323
+ }
324
+
325
+ @staticmethod
326
+ def get_ollama_config(config: ModelProviderConfig) -> Dict[str, Any]:
327
+ """
328
+ Get Ollama provider configuration.
329
+
330
+ Args:
331
+ config: Model provider configuration
332
+
333
+ Returns:
334
+ Dictionary suitable for OllamaProvider initialization
335
+ """
336
+ return {
337
+ "host": config.ollama.host,
338
+ "timeout": config.ollama.timeout,
339
+ "models": config.ollama.models,
340
+ }
341
+
342
+ @staticmethod
343
+ def get_claude_config(config: ModelProviderConfig) -> Dict[str, Any]:
344
+ """
345
+ Get Claude provider configuration.
346
+
347
+ Args:
348
+ config: Model provider configuration
349
+
350
+ Returns:
351
+ Dictionary suitable for ClaudeProvider initialization
352
+ """
353
+ return {
354
+ "api_key": config.claude.api_key,
355
+ "model": config.claude.model,
356
+ "max_tokens": config.claude.max_tokens,
357
+ "temperature": config.claude.temperature,
358
+ }
359
+
360
+ @staticmethod
361
+ def create_sample_config(output_path: str) -> None:
362
+ """
363
+ Create sample configuration file.
364
+
365
+ WHY: Helps users get started with proper configuration.
366
+
367
+ Args:
368
+ output_path: Path where to write sample config
369
+ """
370
+ sample_config = """# Claude MPM Model Provider Configuration
371
+ # ==========================================
372
+
373
+ content_agent:
374
+ # Provider strategy: auto|ollama|claude|privacy
375
+ # - auto: Try Ollama first, fallback to Claude
376
+ # - ollama: Local-only, fail if unavailable
377
+ # - claude: Cloud-only, always use Claude
378
+ # - privacy: Like ollama but with privacy-focused error messages
379
+ model_provider: auto
380
+
381
+ # Ollama Configuration (local models)
382
+ ollama:
383
+ enabled: true
384
+ host: http://localhost:11434
385
+ fallback_to_cloud: true # Allow fallback to Claude on error
386
+ timeout: 30 # Request timeout in seconds
387
+
388
+ # Task-specific model mappings (optional)
389
+ # Defaults are provided if not specified
390
+ models:
391
+ seo_analysis: llama3.3:70b
392
+ readability: gemma2:9b
393
+ grammar: qwen3:14b
394
+ summarization: mistral:7b
395
+ keyword_extraction: seoassistant
396
+ accessibility: gemma2:9b
397
+ sentiment: gemma2:9b
398
+ general: gemma2:9b
399
+
400
+ # Claude Configuration (cloud models)
401
+ claude:
402
+ enabled: true
403
+ model: claude-3-5-sonnet-20241022
404
+ max_tokens: 4096
405
+ temperature: 0.7
406
+ # api_key: sk-ant-... # Or use ANTHROPIC_API_KEY env var
407
+
408
+ # Environment Variable Overrides:
409
+ # - MODEL_PROVIDER: Override provider strategy
410
+ # - OLLAMA_HOST: Override Ollama endpoint
411
+ # - OLLAMA_ENABLED: Enable/disable Ollama (true/false)
412
+ # - CLAUDE_ENABLED: Enable/disable Claude (true/false)
413
+ # - ANTHROPIC_API_KEY: Claude API key
414
+ # - CLAUDE_MODEL: Override Claude model
415
+ """
416
+
417
+ output_path_obj = Path(output_path)
418
+ output_path_obj.parent.mkdir(parents=True, exist_ok=True)
419
+ with output_path_obj.open("w") as f:
420
+ f.write(sample_config)
421
+
422
+
423
+ __all__ = [
424
+ "ClaudeConfig",
425
+ "ModelConfigManager",
426
+ "ModelProviderConfig",
427
+ "OllamaConfig",
428
+ ]
@@ -311,6 +311,9 @@ class InteractiveSession:
311
311
  print(
312
312
  "\033[32m│\033[0m /mpm - MPM overview and help \033[32m│\033[0m"
313
313
  )
314
+ print(
315
+ "\033[32m│\033[0m /mpm-init - Initialize or update project \033[32m│\033[0m"
316
+ )
314
317
  print(
315
318
  "\033[32m│\033[0m /mpm-agents - Show available agents \033[32m│\033[0m"
316
319
  )
@@ -43,6 +43,12 @@ from .communication import ( # WebSocket/SocketIO; Project analysis; Ticket man
43
43
  TicketManagerInterface,
44
44
  )
45
45
 
46
+ # Health interfaces (health monitoring)
47
+ from .health import ( # Health checks; Health monitoring
48
+ IHealthCheck,
49
+ IHealthCheckManager,
50
+ )
51
+
46
52
  # Infrastructure interfaces (core framework services)
47
53
  from .infrastructure import ( # Type variables; Core dependency injection; Configuration management; Caching; Health monitoring; Template management; Service factory; Logging; Service lifecycle; Error handling; Performance monitoring; Event system
48
54
  CacheEntry,
@@ -65,11 +71,33 @@ from .infrastructure import ( # Type variables; Core dependency injection; Conf
65
71
  TemplateRenderContext,
66
72
  )
67
73
 
74
+ # Model interfaces (content processing and model providers)
75
+ from .model import ( # Model providers; Routing
76
+ IModelProvider,
77
+ IModelRouter,
78
+ ModelCapability,
79
+ ModelProvider,
80
+ ModelResponse,
81
+ )
82
+
83
+ # Process interfaces (local process management)
84
+ from .process import ( # Process lifecycle; State persistence
85
+ IDeploymentStateManager,
86
+ ILocalProcessManager,
87
+ )
88
+
68
89
  # Project interfaces (project analysis and toolchain detection)
69
90
  from .project import ( # Toolchain analysis
70
91
  IToolchainAnalyzer,
71
92
  )
72
93
 
94
+ # Restart interfaces (auto-restart management)
95
+ from .restart import ( # Crash detection; Restart policy; Restart orchestration
96
+ ICrashDetector,
97
+ IRestartManager,
98
+ IRestartPolicy,
99
+ )
100
+
73
101
  # Service interfaces (business services)
74
102
  from .service import ( # Version service; Command handling; Memory management; Session management; Utilities; Hook service
75
103
  CommandHandlerInterface,
@@ -81,6 +109,13 @@ from .service import ( # Version service; Command handling; Memory management;
81
109
  VersionServiceInterface,
82
110
  )
83
111
 
112
+ # Stability interfaces (proactive monitoring and crash prevention)
113
+ from .stability import ( # Memory leak detection; Log monitoring; Resource monitoring
114
+ ILogMonitor,
115
+ IMemoryLeakDetector,
116
+ IResourceMonitor,
117
+ )
118
+
84
119
 
85
120
  # Interface registry for dependency injection discovery
86
121
  class InterfaceRegistry:
@@ -129,6 +164,23 @@ class InterfaceRegistry:
129
164
  "toolchain_analyzer": IToolchainAnalyzer,
130
165
  "agent_recommender": IAgentRecommender,
131
166
  "auto_config_manager": IAutoConfigManager,
167
+ # Model interfaces
168
+ "model_provider": IModelProvider,
169
+ "model_router": IModelRouter,
170
+ # Process interfaces
171
+ "deployment_state_manager": IDeploymentStateManager,
172
+ "local_process_manager": ILocalProcessManager,
173
+ # Health interfaces
174
+ "health_check": IHealthCheck,
175
+ "health_check_manager": IHealthCheckManager,
176
+ # Restart interfaces
177
+ "crash_detector": ICrashDetector,
178
+ "restart_policy": IRestartPolicy,
179
+ "restart_manager": IRestartManager,
180
+ # Stability interfaces
181
+ "memory_leak_detector": IMemoryLeakDetector,
182
+ "log_monitor": ILogMonitor,
183
+ "resource_monitor": IResourceMonitor,
132
184
  }
133
185
 
134
186
  @classmethod
@@ -153,7 +205,7 @@ class InterfaceRegistry:
153
205
 
154
206
 
155
207
  # Re-export everything for backward compatibility
156
- __all__ = [
208
+ __all__ = [ # noqa: RUF022 - Semantic grouping by domain preferred over alphabetical
157
209
  "AgentCapabilitiesInterface",
158
210
  "AgentDeploymentInterface",
159
211
  "AgentMetadata",
@@ -168,12 +220,29 @@ __all__ = [
168
220
  "ICacheService",
169
221
  "IConfigurationManager",
170
222
  "IConfigurationService",
223
+ # Process interfaces
224
+ "IDeploymentStateManager",
171
225
  "IErrorHandler",
172
226
  "IEventBus",
227
+ # Health interfaces
228
+ "IHealthCheck",
229
+ "IHealthCheckManager",
173
230
  "IHealthMonitor",
231
+ # Infrastructure interfaces
232
+ "ILocalProcessManager",
233
+ # Restart interfaces
234
+ "ICrashDetector",
235
+ "IRestartManager",
236
+ "IRestartPolicy",
237
+ # Stability interfaces
238
+ "IMemoryLeakDetector",
239
+ "ILogMonitor",
240
+ "IResourceMonitor",
241
+ # Model interfaces
242
+ "IModelProvider",
243
+ "IModelRouter",
174
244
  "IPerformanceMonitor",
175
245
  "IPromptCache",
176
- # Infrastructure interfaces
177
246
  "IServiceContainer",
178
247
  "IServiceFactory",
179
248
  "IServiceLifecycle",
@@ -183,6 +252,9 @@ __all__ = [
183
252
  "IToolchainAnalyzer",
184
253
  # Registry
185
254
  "InterfaceRegistry",
255
+ "ModelCapability",
256
+ "ModelProvider",
257
+ "ModelResponse",
186
258
  "MemoryHookInterface",
187
259
  "MemoryServiceInterface",
188
260
  "ProjectAnalyzerInterface",