sirchmunk 0.0.1.post1__py3-none-any.whl → 0.0.2__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.
- sirchmunk/api/__init__.py +1 -0
- sirchmunk/api/chat.py +1123 -0
- sirchmunk/api/components/__init__.py +0 -0
- sirchmunk/api/components/history_storage.py +402 -0
- sirchmunk/api/components/monitor_tracker.py +518 -0
- sirchmunk/api/components/settings_storage.py +353 -0
- sirchmunk/api/history.py +254 -0
- sirchmunk/api/knowledge.py +411 -0
- sirchmunk/api/main.py +120 -0
- sirchmunk/api/monitor.py +219 -0
- sirchmunk/api/run_server.py +54 -0
- sirchmunk/api/search.py +230 -0
- sirchmunk/api/settings.py +309 -0
- sirchmunk/api/tools.py +315 -0
- sirchmunk/cli/__init__.py +11 -0
- sirchmunk/cli/cli.py +789 -0
- sirchmunk/learnings/knowledge_base.py +5 -2
- sirchmunk/llm/prompts.py +12 -1
- sirchmunk/retrieve/text_retriever.py +186 -2
- sirchmunk/scan/file_scanner.py +2 -2
- sirchmunk/schema/knowledge.py +119 -35
- sirchmunk/search.py +384 -26
- sirchmunk/storage/__init__.py +2 -2
- sirchmunk/storage/{knowledge_manager.py → knowledge_storage.py} +265 -60
- sirchmunk/utils/constants.py +7 -5
- sirchmunk/utils/embedding_util.py +217 -0
- sirchmunk/utils/tokenizer_util.py +36 -1
- sirchmunk/version.py +1 -1
- {sirchmunk-0.0.1.post1.dist-info → sirchmunk-0.0.2.dist-info}/METADATA +124 -9
- sirchmunk-0.0.2.dist-info/RECORD +69 -0
- {sirchmunk-0.0.1.post1.dist-info → sirchmunk-0.0.2.dist-info}/WHEEL +1 -1
- sirchmunk-0.0.2.dist-info/top_level.txt +2 -0
- sirchmunk_mcp/__init__.py +25 -0
- sirchmunk_mcp/cli.py +478 -0
- sirchmunk_mcp/config.py +276 -0
- sirchmunk_mcp/server.py +355 -0
- sirchmunk_mcp/service.py +327 -0
- sirchmunk_mcp/setup.py +15 -0
- sirchmunk_mcp/tools.py +410 -0
- sirchmunk-0.0.1.post1.dist-info/RECORD +0 -45
- sirchmunk-0.0.1.post1.dist-info/top_level.txt +0 -1
- {sirchmunk-0.0.1.post1.dist-info → sirchmunk-0.0.2.dist-info}/entry_points.txt +0 -0
- {sirchmunk-0.0.1.post1.dist-info → sirchmunk-0.0.2.dist-info}/licenses/LICENSE +0 -0
sirchmunk_mcp/cli.py
ADDED
|
@@ -0,0 +1,478 @@
|
|
|
1
|
+
# Copyright (c) ModelScope Contributors. All rights reserved.
|
|
2
|
+
"""
|
|
3
|
+
Command-line interface for Sirchmunk MCP Server.
|
|
4
|
+
|
|
5
|
+
Provides commands for server management, initialization, and diagnostics.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import argparse
|
|
9
|
+
import asyncio
|
|
10
|
+
import logging
|
|
11
|
+
import os
|
|
12
|
+
import shutil
|
|
13
|
+
import sys
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from . import __version__
|
|
17
|
+
from .config import Config
|
|
18
|
+
from .server import run_stdio_server, run_http_server
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
logger = logging.getLogger(__name__)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_mcp_version():
|
|
25
|
+
try:
|
|
26
|
+
import importlib.metadata
|
|
27
|
+
return importlib.metadata.version("mcp")
|
|
28
|
+
except ImportError:
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _setup_stdio_safe_environment():
|
|
33
|
+
"""Configure environment for safe stdio MCP communication.
|
|
34
|
+
|
|
35
|
+
In MCP stdio mode, stdout is reserved exclusively for JSON-RPC messages.
|
|
36
|
+
Any non-JSON output to stdout will break the protocol. This function
|
|
37
|
+
sets environment variables to suppress verbose output from third-party
|
|
38
|
+
libraries (ModelScope, transformers, tqdm, etc.) that might print to stdout.
|
|
39
|
+
"""
|
|
40
|
+
# Set environment variables to suppress third-party library outputs
|
|
41
|
+
# These must be set BEFORE importing the libraries
|
|
42
|
+
os.environ["MODELSCOPE_LOG_LEVEL"] = "ERROR"
|
|
43
|
+
os.environ["MODELSCOPE_CACHE"] = os.path.expanduser("~/.sirchmunk/.cache/models")
|
|
44
|
+
os.environ["TRANSFORMERS_VERBOSITY"] = "error"
|
|
45
|
+
os.environ["TRANSFORMERS_NO_ADVISORY_WARNINGS"] = "1"
|
|
46
|
+
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
|
47
|
+
|
|
48
|
+
# Suppress warnings
|
|
49
|
+
import warnings
|
|
50
|
+
warnings.filterwarnings("ignore")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def cmd_serve(args: argparse.Namespace) -> int:
|
|
54
|
+
"""Run MCP server.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
args: Command-line arguments
|
|
58
|
+
|
|
59
|
+
Returns:
|
|
60
|
+
Exit code
|
|
61
|
+
"""
|
|
62
|
+
try:
|
|
63
|
+
# Override transport from command-line if specified
|
|
64
|
+
if args.transport:
|
|
65
|
+
os.environ["MCP_TRANSPORT"] = args.transport
|
|
66
|
+
|
|
67
|
+
if args.host:
|
|
68
|
+
os.environ["MCP_HOST"] = args.host
|
|
69
|
+
|
|
70
|
+
if args.port:
|
|
71
|
+
os.environ["MCP_PORT"] = str(args.port)
|
|
72
|
+
|
|
73
|
+
# Determine transport mode early (before loading config triggers imports)
|
|
74
|
+
transport = args.transport or os.environ.get("MCP_TRANSPORT", "stdio")
|
|
75
|
+
|
|
76
|
+
# Set up safe environment BEFORE any sirchmunk imports for stdio mode
|
|
77
|
+
# This prevents ModelScope/transformers from printing to stdout
|
|
78
|
+
if transport == "stdio":
|
|
79
|
+
os.environ["MCP_TRANSPORT"] = "stdio" # Signal to service.py
|
|
80
|
+
_setup_stdio_safe_environment()
|
|
81
|
+
|
|
82
|
+
# Load configuration (may trigger sirchmunk imports)
|
|
83
|
+
config = Config.from_env()
|
|
84
|
+
|
|
85
|
+
# Configure logging - MUST use stderr for stdio transport
|
|
86
|
+
# stdout is reserved for JSON-RPC messages in MCP stdio mode
|
|
87
|
+
log_level = args.log_level or config.mcp.log_level
|
|
88
|
+
logging.basicConfig(
|
|
89
|
+
level=getattr(logging, log_level.upper()),
|
|
90
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
91
|
+
stream=sys.stderr, # Critical: logs must go to stderr, not stdout
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
logger.info(f"Sirchmunk MCP Server v{__version__}")
|
|
95
|
+
logger.info(f"Transport: {config.mcp.transport}")
|
|
96
|
+
|
|
97
|
+
# Run server
|
|
98
|
+
if config.mcp.transport == "stdio":
|
|
99
|
+
# Check if running in interactive terminal
|
|
100
|
+
if sys.stdin.isatty():
|
|
101
|
+
print()
|
|
102
|
+
print("=" * 60)
|
|
103
|
+
print(" ⚠️ Sirchmunk MCP Server - STDIO Mode")
|
|
104
|
+
print("=" * 60)
|
|
105
|
+
print()
|
|
106
|
+
print(" STDIO mode is designed to be launched by an MCP client")
|
|
107
|
+
print(" (e.g., Claude Desktop, Cursor IDE), not run directly")
|
|
108
|
+
print(" in an interactive terminal.")
|
|
109
|
+
print()
|
|
110
|
+
print(" The server expects JSON-RPC messages from an MCP client.")
|
|
111
|
+
print(" Running in a terminal will cause errors.")
|
|
112
|
+
print()
|
|
113
|
+
print(" Options:")
|
|
114
|
+
print(" 1. Configure your MCP client to launch this server")
|
|
115
|
+
print(" 2. Use HTTP mode: sirchmunk-mcp serve --transport http")
|
|
116
|
+
print()
|
|
117
|
+
print("=" * 60)
|
|
118
|
+
print()
|
|
119
|
+
|
|
120
|
+
# Ask user if they want to continue anyway
|
|
121
|
+
try:
|
|
122
|
+
response = input("Continue anyway? (y/N): ").strip().lower()
|
|
123
|
+
if response != 'y':
|
|
124
|
+
print("Server not started. Use an MCP client to launch this server.")
|
|
125
|
+
return 0
|
|
126
|
+
print()
|
|
127
|
+
print("Starting server... Press Ctrl+C to stop.")
|
|
128
|
+
print("(Any input you type will cause errors)")
|
|
129
|
+
print()
|
|
130
|
+
except (EOFError, KeyboardInterrupt):
|
|
131
|
+
print("\nServer not started.")
|
|
132
|
+
return 0
|
|
133
|
+
|
|
134
|
+
asyncio.run(run_stdio_server(config))
|
|
135
|
+
elif config.mcp.transport == "http":
|
|
136
|
+
asyncio.run(run_http_server(config))
|
|
137
|
+
else:
|
|
138
|
+
logger.error(f"Unknown transport: {config.mcp.transport}")
|
|
139
|
+
return 1
|
|
140
|
+
|
|
141
|
+
return 0
|
|
142
|
+
|
|
143
|
+
except KeyboardInterrupt:
|
|
144
|
+
logger.info("Server stopped by user")
|
|
145
|
+
return 0
|
|
146
|
+
|
|
147
|
+
except Exception as e:
|
|
148
|
+
logger.error(f"Server error: {e}", exc_info=True)
|
|
149
|
+
return 1
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def cmd_init(args: argparse.Namespace) -> int:
|
|
153
|
+
"""Initialize Sirchmunk environment.
|
|
154
|
+
|
|
155
|
+
Creates working directory, configuration files, and performs
|
|
156
|
+
dependency checks.
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
args: Command-line arguments
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
Exit code
|
|
163
|
+
"""
|
|
164
|
+
try:
|
|
165
|
+
print(f"Initializing Sirchmunk MCP v{__version__}")
|
|
166
|
+
print()
|
|
167
|
+
|
|
168
|
+
# Determine work path
|
|
169
|
+
if args.work_path:
|
|
170
|
+
work_path = Path(args.work_path)
|
|
171
|
+
else:
|
|
172
|
+
work_path = Path(os.getenv("SIRCHMUNK_WORK_PATH", str(Path.home() / ".sirchmunk")))
|
|
173
|
+
|
|
174
|
+
work_path = work_path.expanduser().resolve()
|
|
175
|
+
|
|
176
|
+
print(f"Work path: {work_path}")
|
|
177
|
+
|
|
178
|
+
# Create work directory
|
|
179
|
+
work_path.mkdir(parents=True, exist_ok=True)
|
|
180
|
+
print(f"✓ Created work directory")
|
|
181
|
+
|
|
182
|
+
# Create subdirectories
|
|
183
|
+
(work_path / ".cache").mkdir(exist_ok=True)
|
|
184
|
+
(work_path / ".cache" / "models").mkdir(exist_ok=True)
|
|
185
|
+
(work_path / "data").mkdir(exist_ok=True)
|
|
186
|
+
print(f"✓ Created subdirectories")
|
|
187
|
+
|
|
188
|
+
# Check dependencies
|
|
189
|
+
print()
|
|
190
|
+
print("Checking dependencies...")
|
|
191
|
+
|
|
192
|
+
# Check ripgrep-all
|
|
193
|
+
if shutil.which("rga"):
|
|
194
|
+
print("✓ ripgrep-all (rga) is installed")
|
|
195
|
+
else:
|
|
196
|
+
print("✗ ripgrep-all (rga) is not installed")
|
|
197
|
+
print(" Installing ripgrep-all...")
|
|
198
|
+
try:
|
|
199
|
+
from sirchmunk.utils.install_rga import install_rga
|
|
200
|
+
install_rga()
|
|
201
|
+
print("✓ ripgrep-all installed successfully")
|
|
202
|
+
except Exception as e:
|
|
203
|
+
print(f"✗ Failed to install ripgrep-all: {e}")
|
|
204
|
+
print(" Please install manually: https://github.com/phiresky/ripgrep-all")
|
|
205
|
+
|
|
206
|
+
# Check Python packages
|
|
207
|
+
mcp_version = get_mcp_version()
|
|
208
|
+
if mcp_version:
|
|
209
|
+
print(f"✓ MCP package installed (v{mcp_version})")
|
|
210
|
+
else:
|
|
211
|
+
print("✗ MCP package not found")
|
|
212
|
+
print(" Install with: pip install mcp")
|
|
213
|
+
|
|
214
|
+
try:
|
|
215
|
+
import sirchmunk
|
|
216
|
+
print(f"✓ sirchmunk package installed")
|
|
217
|
+
except ImportError:
|
|
218
|
+
print("✗ sirchmunk package not found")
|
|
219
|
+
print(" Install with: pip install sirchmunk")
|
|
220
|
+
|
|
221
|
+
# Check environment variables
|
|
222
|
+
print()
|
|
223
|
+
print("Checking environment variables...")
|
|
224
|
+
|
|
225
|
+
llm_api_key = os.getenv("LLM_API_KEY")
|
|
226
|
+
if llm_api_key:
|
|
227
|
+
print(f"✓ LLM_API_KEY is set ({llm_api_key[:8]}...)")
|
|
228
|
+
else:
|
|
229
|
+
print("✗ LLM_API_KEY is not set")
|
|
230
|
+
print(" Set it in your .mcp_env file or environment")
|
|
231
|
+
|
|
232
|
+
print()
|
|
233
|
+
print("Initialization complete!")
|
|
234
|
+
print()
|
|
235
|
+
print("Next steps:")
|
|
236
|
+
print("1. Configure LLM_API_KEY in .mcp_env file")
|
|
237
|
+
print("2. Run 'sirchmunk-mcp serve' to start the server")
|
|
238
|
+
print("3. Configure your MCP client (e.g., Claude Desktop)")
|
|
239
|
+
|
|
240
|
+
return 0
|
|
241
|
+
|
|
242
|
+
except Exception as e:
|
|
243
|
+
logger.error(f"Initialization failed: {e}", exc_info=True)
|
|
244
|
+
return 1
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def cmd_config(args: argparse.Namespace) -> int:
|
|
248
|
+
"""Show or generate configuration.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
args: Command-line arguments
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
Exit code
|
|
255
|
+
"""
|
|
256
|
+
try:
|
|
257
|
+
if args.generate:
|
|
258
|
+
# Determine work path
|
|
259
|
+
work_path = Path(os.getenv("SIRCHMUNK_WORK_PATH", str(Path.home() / ".sirchmunk")))
|
|
260
|
+
work_path = work_path.expanduser().resolve()
|
|
261
|
+
work_path.mkdir(parents=True, exist_ok=True)
|
|
262
|
+
|
|
263
|
+
# Generate .mcp_env file in work_path
|
|
264
|
+
env_file = work_path / ".mcp_env"
|
|
265
|
+
|
|
266
|
+
env_content = """# ===== LLM Configuration =====
|
|
267
|
+
LLM_BASE_URL=https://api.openai.com/v1
|
|
268
|
+
LLM_API_KEY=your-api-key
|
|
269
|
+
LLM_MODEL_NAME=gpt-5.2
|
|
270
|
+
|
|
271
|
+
# ===== Sirchmunk Settings =====
|
|
272
|
+
SIRCHMUNK_WORK_PATH=~/.sirchmunk
|
|
273
|
+
SIRCHMUNK_VERBOSE=false
|
|
274
|
+
SIRCHMUNK_ENABLE_CLUSTER_REUSE=true
|
|
275
|
+
|
|
276
|
+
# ===== Cluster Similarity Settings =====
|
|
277
|
+
CLUSTER_SIM_THRESHOLD=0.85
|
|
278
|
+
CLUSTER_SIM_TOP_K=3
|
|
279
|
+
MAX_QUERIES_PER_CLUSTER=5
|
|
280
|
+
|
|
281
|
+
# ===== Search Settings =====
|
|
282
|
+
DEFAULT_MAX_DEPTH=5
|
|
283
|
+
DEFAULT_TOP_K_FILES=3
|
|
284
|
+
DEFAULT_KEYWORD_LEVELS=3
|
|
285
|
+
GREP_TIMEOUT=60.0
|
|
286
|
+
|
|
287
|
+
# ===== MCP Server Settings =====
|
|
288
|
+
MCP_SERVER_NAME=sirchmunk
|
|
289
|
+
MCP_SERVER_VERSION=0.1.0
|
|
290
|
+
MCP_LOG_LEVEL=INFO
|
|
291
|
+
MCP_TRANSPORT=stdio
|
|
292
|
+
"""
|
|
293
|
+
|
|
294
|
+
env_file.write_text(env_content)
|
|
295
|
+
print(f"Generated {env_file}")
|
|
296
|
+
|
|
297
|
+
# Generate MCP client config
|
|
298
|
+
if args.output:
|
|
299
|
+
output_path = Path(args.output)
|
|
300
|
+
else:
|
|
301
|
+
output_path = Path.cwd() / "mcp_config.json"
|
|
302
|
+
|
|
303
|
+
mcp_config = """{
|
|
304
|
+
"mcpServers": {
|
|
305
|
+
"sirchmunk": {
|
|
306
|
+
"command": "sirchmunk-mcp",
|
|
307
|
+
"args": ["serve"],
|
|
308
|
+
"env": {
|
|
309
|
+
"LLM_BASE_URL": "https://api.openai.com/v1",
|
|
310
|
+
"LLM_API_KEY": "your-api-key",
|
|
311
|
+
"LLM_MODEL_NAME": "gpt-5.2",
|
|
312
|
+
"SIRCHMUNK_WORK_PATH": "~/.sirchmunk",
|
|
313
|
+
"SIRCHMUNK_VERBOSE": "false"
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
"""
|
|
319
|
+
|
|
320
|
+
output_path.write_text(mcp_config)
|
|
321
|
+
print(f"Generated {output_path}")
|
|
322
|
+
|
|
323
|
+
print()
|
|
324
|
+
print("Configuration files generated successfully!")
|
|
325
|
+
print()
|
|
326
|
+
print(f"⚠️ Please edit {env_file} to set your LLM_API_KEY")
|
|
327
|
+
print()
|
|
328
|
+
print("To use with Claude Desktop:")
|
|
329
|
+
print("1. Edit mcp_config.json with your API key")
|
|
330
|
+
if sys.platform == "darwin":
|
|
331
|
+
config_dir = Path.home() / "Library/Application Support/Claude"
|
|
332
|
+
elif sys.platform == "linux":
|
|
333
|
+
config_dir = Path.home() / ".config/Claude"
|
|
334
|
+
else:
|
|
335
|
+
config_dir = Path(os.getenv("APPDATA", "")) / "Claude"
|
|
336
|
+
|
|
337
|
+
print(f"2. Copy to: {config_dir}/claude_desktop_config.json")
|
|
338
|
+
print("3. Restart Claude Desktop")
|
|
339
|
+
|
|
340
|
+
else:
|
|
341
|
+
# Show current configuration
|
|
342
|
+
config = Config.from_env()
|
|
343
|
+
print("Current Configuration:")
|
|
344
|
+
print()
|
|
345
|
+
print(f"LLM:")
|
|
346
|
+
print(f" Base URL: {config.llm.base_url}")
|
|
347
|
+
print(f" Model: {config.llm.model_name}")
|
|
348
|
+
print(f" API Key: {config.llm.api_key[:8]}..." if config.llm.api_key else " API Key: (not set)")
|
|
349
|
+
print()
|
|
350
|
+
print(f"Sirchmunk:")
|
|
351
|
+
print(f" Work Path: {config.sirchmunk.work_path}")
|
|
352
|
+
print(f" Verbose: {config.sirchmunk.verbose}")
|
|
353
|
+
print(f" Cluster Reuse: {config.sirchmunk.enable_cluster_reuse}")
|
|
354
|
+
print()
|
|
355
|
+
print(f"MCP Server:")
|
|
356
|
+
print(f" Name: {config.mcp.server_name}")
|
|
357
|
+
print(f" Version: {config.mcp.server_version}")
|
|
358
|
+
print(f" Transport: {config.mcp.transport}")
|
|
359
|
+
print(f" Log Level: {config.mcp.log_level}")
|
|
360
|
+
|
|
361
|
+
return 0
|
|
362
|
+
|
|
363
|
+
except Exception as e:
|
|
364
|
+
logger.error(f"Config command failed: {e}", exc_info=True)
|
|
365
|
+
return 1
|
|
366
|
+
|
|
367
|
+
|
|
368
|
+
def cmd_version(args: argparse.Namespace) -> int:
|
|
369
|
+
"""Show version information.
|
|
370
|
+
|
|
371
|
+
Args:
|
|
372
|
+
args: Command-line arguments
|
|
373
|
+
|
|
374
|
+
Returns:
|
|
375
|
+
Exit code
|
|
376
|
+
"""
|
|
377
|
+
print(f"Sirchmunk MCP Server v{__version__}")
|
|
378
|
+
|
|
379
|
+
mcp_version = get_mcp_version()
|
|
380
|
+
if mcp_version:
|
|
381
|
+
print(f"MCP package v{mcp_version}")
|
|
382
|
+
else:
|
|
383
|
+
print("MCP package (not installed)")
|
|
384
|
+
|
|
385
|
+
try:
|
|
386
|
+
import sirchmunk
|
|
387
|
+
print(f"Sirchmunk Core (installed)")
|
|
388
|
+
except ImportError:
|
|
389
|
+
pass
|
|
390
|
+
|
|
391
|
+
return 0
|
|
392
|
+
|
|
393
|
+
|
|
394
|
+
def main() -> int:
|
|
395
|
+
"""Main CLI entry point.
|
|
396
|
+
|
|
397
|
+
Returns:
|
|
398
|
+
Exit code
|
|
399
|
+
"""
|
|
400
|
+
parser = argparse.ArgumentParser(
|
|
401
|
+
description="Sirchmunk MCP Server - Intelligent code search as an MCP service",
|
|
402
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
parser.add_argument(
|
|
406
|
+
"--version",
|
|
407
|
+
action="store_true",
|
|
408
|
+
help="Show version information",
|
|
409
|
+
)
|
|
410
|
+
|
|
411
|
+
subparsers = parser.add_subparsers(dest="command", help="Available commands")
|
|
412
|
+
|
|
413
|
+
# serve command
|
|
414
|
+
serve_parser = subparsers.add_parser("serve", help="Run MCP server")
|
|
415
|
+
serve_parser.add_argument(
|
|
416
|
+
"--transport",
|
|
417
|
+
choices=["stdio", "http"],
|
|
418
|
+
help="Transport protocol (default: stdio)",
|
|
419
|
+
)
|
|
420
|
+
serve_parser.add_argument(
|
|
421
|
+
"--host",
|
|
422
|
+
help="Host for HTTP transport (default: localhost)",
|
|
423
|
+
)
|
|
424
|
+
serve_parser.add_argument(
|
|
425
|
+
"--port",
|
|
426
|
+
type=int,
|
|
427
|
+
help="Port for HTTP transport (default: 8080)",
|
|
428
|
+
)
|
|
429
|
+
serve_parser.add_argument(
|
|
430
|
+
"--log-level",
|
|
431
|
+
choices=["DEBUG", "INFO", "WARNING", "ERROR"],
|
|
432
|
+
help="Logging level",
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
# init command
|
|
436
|
+
init_parser = subparsers.add_parser("init", help="Initialize Sirchmunk environment")
|
|
437
|
+
init_parser.add_argument(
|
|
438
|
+
"--work-path",
|
|
439
|
+
help="Working directory path (default: ~/.sirchmunk)",
|
|
440
|
+
)
|
|
441
|
+
|
|
442
|
+
# config command
|
|
443
|
+
config_parser = subparsers.add_parser("config", help="Manage configuration")
|
|
444
|
+
config_parser.add_argument(
|
|
445
|
+
"--generate",
|
|
446
|
+
action="store_true",
|
|
447
|
+
help="Generate configuration templates",
|
|
448
|
+
)
|
|
449
|
+
config_parser.add_argument(
|
|
450
|
+
"--output",
|
|
451
|
+
help="Output path for generated config",
|
|
452
|
+
)
|
|
453
|
+
|
|
454
|
+
# version command
|
|
455
|
+
version_parser = subparsers.add_parser("version", help="Show version information")
|
|
456
|
+
|
|
457
|
+
args = parser.parse_args()
|
|
458
|
+
|
|
459
|
+
# Handle --version flag
|
|
460
|
+
if args.version:
|
|
461
|
+
return cmd_version(args)
|
|
462
|
+
|
|
463
|
+
# Handle commands
|
|
464
|
+
if args.command == "serve":
|
|
465
|
+
return cmd_serve(args)
|
|
466
|
+
elif args.command == "init":
|
|
467
|
+
return cmd_init(args)
|
|
468
|
+
elif args.command == "config":
|
|
469
|
+
return cmd_config(args)
|
|
470
|
+
elif args.command == "version":
|
|
471
|
+
return cmd_version(args)
|
|
472
|
+
else:
|
|
473
|
+
parser.print_help()
|
|
474
|
+
return 1
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
if __name__ == "__main__":
|
|
478
|
+
sys.exit(main())
|