crackerjack 0.34.2__py3-none-any.whl → 0.35.1__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 crackerjack might be problematic. Click here for more details.
- crackerjack/__main__.py +3 -4
- crackerjack/agents/documentation_agent.py +2 -2
- crackerjack/api.py +4 -4
- crackerjack/cli/options.py +41 -9
- crackerjack/dynamic_config.py +12 -6
- crackerjack/managers/publish_manager.py +3 -3
- crackerjack/mcp/progress_components.py +3 -5
- crackerjack/mcp/server_core.py +34 -7
- crackerjack/services/dependency_monitor.py +2 -2
- crackerjack/services/health_metrics.py +2 -2
- crackerjack/services/server_manager.py +29 -8
- crackerjack/ui/__init__.py +1 -0
- crackerjack/ui/server_panels.py +126 -0
- {crackerjack-0.34.2.dist-info → crackerjack-0.35.1.dist-info}/METADATA +1 -1
- {crackerjack-0.34.2.dist-info → crackerjack-0.35.1.dist-info}/RECORD +18 -16
- {crackerjack-0.34.2.dist-info → crackerjack-0.35.1.dist-info}/WHEEL +0 -0
- {crackerjack-0.34.2.dist-info → crackerjack-0.35.1.dist-info}/entry_points.txt +0 -0
- {crackerjack-0.34.2.dist-info → crackerjack-0.35.1.dist-info}/licenses/LICENSE +0 -0
crackerjack/__main__.py
CHANGED
|
@@ -11,7 +11,6 @@ from crackerjack.services.git import GitService
|
|
|
11
11
|
|
|
12
12
|
from .cli import (
|
|
13
13
|
CLI_OPTIONS,
|
|
14
|
-
BumpOption,
|
|
15
14
|
create_options,
|
|
16
15
|
handle_interactive_mode,
|
|
17
16
|
handle_standard_mode,
|
|
@@ -1220,9 +1219,9 @@ def main(
|
|
|
1220
1219
|
update_precommit: bool = CLI_OPTIONS["update_precommit"],
|
|
1221
1220
|
verbose: bool = CLI_OPTIONS["verbose"],
|
|
1222
1221
|
debug: bool = CLI_OPTIONS["debug"],
|
|
1223
|
-
publish:
|
|
1224
|
-
all:
|
|
1225
|
-
bump:
|
|
1222
|
+
publish: str | None = CLI_OPTIONS["publish"],
|
|
1223
|
+
all: str | None = CLI_OPTIONS["all"],
|
|
1224
|
+
bump: str | None = CLI_OPTIONS["bump"],
|
|
1226
1225
|
strip_code: bool = CLI_OPTIONS["strip_code"],
|
|
1227
1226
|
run_tests: bool = CLI_OPTIONS["run_tests"],
|
|
1228
1227
|
benchmark: bool = CLI_OPTIONS["benchmark"],
|
|
@@ -325,8 +325,8 @@ class DocumentationAgent(SubAgent):
|
|
|
325
325
|
|
|
326
326
|
All notable changes to this project will be documented in this file.
|
|
327
327
|
|
|
328
|
-
The format is based on [Keep a Changelog](https
|
|
329
|
-
and this project adheres to [Semantic Versioning](https
|
|
328
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
329
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
330
330
|
|
|
331
331
|
{entry}
|
|
332
332
|
"""
|
crackerjack/api.py
CHANGED
|
@@ -601,10 +601,10 @@ class CrackerjackAPI:
|
|
|
601
601
|
return None
|
|
602
602
|
|
|
603
603
|
def _find_fallback_package_directory(self) -> Path | None:
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
604
|
+
# Only check project directory name, not src
|
|
605
|
+
package_dir = self.project_path / self.project_path.name
|
|
606
|
+
if self._is_valid_python_package_directory(package_dir):
|
|
607
|
+
return package_dir
|
|
608
608
|
return None
|
|
609
609
|
|
|
610
610
|
def _is_valid_python_package_directory(self, directory: Path) -> bool:
|
crackerjack/cli/options.py
CHANGED
|
@@ -2,15 +2,36 @@ import typing as t
|
|
|
2
2
|
import warnings
|
|
3
3
|
from enum import Enum
|
|
4
4
|
|
|
5
|
+
import click
|
|
5
6
|
import typer
|
|
6
7
|
from pydantic import BaseModel, field_validator, model_validator
|
|
7
8
|
|
|
8
9
|
|
|
10
|
+
def parse_bump_option_with_flag_support(
|
|
11
|
+
ctx: click.Context, param: click.Parameter, value: str | None
|
|
12
|
+
) -> str | None:
|
|
13
|
+
"""Parse bump option that supports both flag usage (-p) and value usage (-p patch)."""
|
|
14
|
+
if value is None:
|
|
15
|
+
return None
|
|
16
|
+
|
|
17
|
+
# If the value starts with a dash, it's likely another flag that typer mistakenly captured
|
|
18
|
+
if value.startswith("-"):
|
|
19
|
+
# Put the value back into the arguments for typer to process
|
|
20
|
+
if hasattr(ctx, "protected_args"):
|
|
21
|
+
ctx.protected_args.insert(0, value)
|
|
22
|
+
elif hasattr(ctx, "args"):
|
|
23
|
+
ctx.args.insert(0, value)
|
|
24
|
+
return "interactive"
|
|
25
|
+
|
|
26
|
+
return value
|
|
27
|
+
|
|
28
|
+
|
|
9
29
|
class BumpOption(str, Enum):
|
|
10
30
|
patch = "patch"
|
|
11
31
|
minor = "minor"
|
|
12
32
|
major = "major"
|
|
13
33
|
interactive = "interactive"
|
|
34
|
+
auto = "auto"
|
|
14
35
|
|
|
15
36
|
def __str__(self) -> str:
|
|
16
37
|
return str(self.value)
|
|
@@ -91,7 +112,7 @@ class Options(BaseModel):
|
|
|
91
112
|
strip_code: bool | None = None # Replaces clean
|
|
92
113
|
run_tests: bool = False # Replaces test
|
|
93
114
|
ai_fix: bool | None = None # Replaces ai_agent
|
|
94
|
-
full_release:
|
|
115
|
+
full_release: str | None = None # Replaces all
|
|
95
116
|
show_progress: bool | None = None # Replaces track_progress
|
|
96
117
|
advanced_monitor: bool | None = None # Replaces enhanced_monitor
|
|
97
118
|
coverage_report: bool | None = None # Replaces coverage_status
|
|
@@ -223,6 +244,11 @@ class Options(BaseModel):
|
|
|
223
244
|
return None
|
|
224
245
|
if value == "":
|
|
225
246
|
return BumpOption.interactive
|
|
247
|
+
|
|
248
|
+
# Handle case where typer parsed a flag as the value (e.g., -p -c becomes value="-c")
|
|
249
|
+
if isinstance(value, str) and value.startswith("-"):
|
|
250
|
+
return BumpOption.interactive
|
|
251
|
+
|
|
226
252
|
try:
|
|
227
253
|
return BumpOption(value.lower())
|
|
228
254
|
except ValueError:
|
|
@@ -275,9 +301,12 @@ CLI_OPTIONS = {
|
|
|
275
301
|
None,
|
|
276
302
|
"-p",
|
|
277
303
|
"--publish",
|
|
304
|
+
callback=parse_bump_option_with_flag_support,
|
|
278
305
|
help=(
|
|
279
|
-
"Bump version and publish to PyPI (patch, minor, major). "
|
|
280
|
-
"Use 'interactive' to be prompted for version selection."
|
|
306
|
+
"Bump version and publish to PyPI (patch, minor, major, auto). "
|
|
307
|
+
"Use 'interactive' to be prompted for version selection. "
|
|
308
|
+
"Use 'auto' to automatically use AI recommendations. "
|
|
309
|
+
"When used as a flag (-p), defaults to 'interactive'."
|
|
281
310
|
),
|
|
282
311
|
case_sensitive=False,
|
|
283
312
|
),
|
|
@@ -285,14 +314,16 @@ CLI_OPTIONS = {
|
|
|
285
314
|
None,
|
|
286
315
|
"-a",
|
|
287
316
|
"--all",
|
|
288
|
-
|
|
317
|
+
callback=parse_bump_option_with_flag_support,
|
|
318
|
+
help="Full release workflow: bump version, run quality checks, and publish (patch, minor, major, auto). When used as a flag (-a), defaults to 'interactive'.",
|
|
289
319
|
case_sensitive=False,
|
|
290
320
|
),
|
|
291
321
|
"bump": typer.Option(
|
|
292
322
|
None,
|
|
293
323
|
"-b",
|
|
294
324
|
"--bump",
|
|
295
|
-
|
|
325
|
+
callback=parse_bump_option_with_flag_support,
|
|
326
|
+
help="Bump version (patch, minor, major, auto). When used as a flag (-b), defaults to 'interactive'.",
|
|
296
327
|
case_sensitive=False,
|
|
297
328
|
),
|
|
298
329
|
"benchmark": typer.Option(
|
|
@@ -644,7 +675,8 @@ CLI_OPTIONS = {
|
|
|
644
675
|
None,
|
|
645
676
|
"-a",
|
|
646
677
|
"--full-release",
|
|
647
|
-
|
|
678
|
+
callback=parse_bump_option_with_flag_support,
|
|
679
|
+
help="Complete release workflow: strip code, run tests, bump version, and publish (patch, minor, major, auto). Equivalent to `-x -t -p <version> -c`. When used as a flag (-a), defaults to 'interactive'.",
|
|
648
680
|
case_sensitive=False,
|
|
649
681
|
),
|
|
650
682
|
"show_progress": typer.Option(
|
|
@@ -869,8 +901,8 @@ def create_options(
|
|
|
869
901
|
update_precommit: bool,
|
|
870
902
|
verbose: bool,
|
|
871
903
|
debug: bool,
|
|
872
|
-
publish:
|
|
873
|
-
bump:
|
|
904
|
+
publish: str | None,
|
|
905
|
+
bump: str | None,
|
|
874
906
|
benchmark: bool,
|
|
875
907
|
test_workers: int,
|
|
876
908
|
test_timeout: int,
|
|
@@ -953,7 +985,7 @@ def create_options(
|
|
|
953
985
|
strip_code: bool | None = None,
|
|
954
986
|
run_tests: bool = False,
|
|
955
987
|
ai_fix: bool | None = None,
|
|
956
|
-
full_release:
|
|
988
|
+
full_release: str | None = None,
|
|
957
989
|
show_progress: bool | None = None,
|
|
958
990
|
advanced_monitor: bool | None = None,
|
|
959
991
|
coverage_report: bool | None = None,
|
crackerjack/dynamic_config.py
CHANGED
|
@@ -499,13 +499,12 @@ class DynamicConfigGenerator:
|
|
|
499
499
|
except Exception:
|
|
500
500
|
pass
|
|
501
501
|
|
|
502
|
-
# Fallback to
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
return possible_name
|
|
502
|
+
# Fallback to project directory name
|
|
503
|
+
if (current_dir / current_dir.name).exists():
|
|
504
|
+
return current_dir.name
|
|
506
505
|
|
|
507
|
-
# Default fallback
|
|
508
|
-
return
|
|
506
|
+
# Default fallback to current directory name
|
|
507
|
+
return current_dir.name
|
|
509
508
|
|
|
510
509
|
def _should_include_hook(
|
|
511
510
|
self,
|
|
@@ -565,6 +564,13 @@ class DynamicConfigGenerator:
|
|
|
565
564
|
"crackerjack", self.package_directory
|
|
566
565
|
)
|
|
567
566
|
|
|
567
|
+
# Ensure hooks exclude src directories to avoid JavaScript conflicts
|
|
568
|
+
if hook["exclude"]:
|
|
569
|
+
if "src/" not in hook["exclude"]:
|
|
570
|
+
hook["exclude"] = f"{hook['exclude']}|^src/"
|
|
571
|
+
else:
|
|
572
|
+
hook["exclude"] = "^src/"
|
|
573
|
+
|
|
568
574
|
return hook
|
|
569
575
|
|
|
570
576
|
def group_hooks_by_repo(
|
|
@@ -284,7 +284,7 @@ class PublishManagerImpl:
|
|
|
284
284
|
[
|
|
285
285
|
"keyring",
|
|
286
286
|
"get",
|
|
287
|
-
"https
|
|
287
|
+
"https://upload.pypi.org/legacy/",
|
|
288
288
|
"__token__",
|
|
289
289
|
],
|
|
290
290
|
)
|
|
@@ -315,7 +315,7 @@ class PublishManagerImpl:
|
|
|
315
315
|
" 1. Set environment variable: export UV_PUBLISH_TOKEN=<your-pypi-token>",
|
|
316
316
|
)
|
|
317
317
|
self.console.print(
|
|
318
|
-
" 2. Use keyring: keyring set[t.Any] https
|
|
318
|
+
" 2. Use keyring: keyring set[t.Any] https://upload.pypi.org/legacy/ __token__",
|
|
319
319
|
)
|
|
320
320
|
self.console.print(
|
|
321
321
|
" 3. Ensure token starts with 'pypi-' and is properly formatted",
|
|
@@ -434,7 +434,7 @@ class PublishManagerImpl:
|
|
|
434
434
|
package_name = self._get_package_name()
|
|
435
435
|
|
|
436
436
|
if package_name and current_version:
|
|
437
|
-
url = f"https
|
|
437
|
+
url = f"https://pypi.org/project/{package_name}/{current_version}/"
|
|
438
438
|
self.console.print(f"[cyan]🔗[/ cyan] Package URL: {url}")
|
|
439
439
|
|
|
440
440
|
def _get_package_name(self) -> str | None:
|
|
@@ -157,11 +157,9 @@ class JobDataCollector:
|
|
|
157
157
|
"network_operations",
|
|
158
158
|
timeout=5.0,
|
|
159
159
|
):
|
|
160
|
-
websocket_base = self.websocket_url.replace(
|
|
161
|
-
"
|
|
162
|
-
|
|
163
|
-
"wss: //",
|
|
164
|
-
"https: //",
|
|
160
|
+
websocket_base = self.websocket_url.replace("ws://", "http://").replace(
|
|
161
|
+
"wss://",
|
|
162
|
+
"https://",
|
|
165
163
|
)
|
|
166
164
|
|
|
167
165
|
async with (
|
crackerjack/mcp/server_core.py
CHANGED
|
@@ -6,6 +6,8 @@ from typing import Final
|
|
|
6
6
|
|
|
7
7
|
from rich.console import Console
|
|
8
8
|
|
|
9
|
+
from ..ui.server_panels import create_server_panels
|
|
10
|
+
|
|
9
11
|
try:
|
|
10
12
|
import tomli
|
|
11
13
|
except ImportError:
|
|
@@ -259,18 +261,23 @@ def _print_server_info(
|
|
|
259
261
|
websocket_port: int | None,
|
|
260
262
|
http_mode: bool,
|
|
261
263
|
) -> None:
|
|
262
|
-
|
|
263
|
-
console.print(f"Project path: {project_path}")
|
|
264
|
+
panels = create_server_panels(console)
|
|
264
265
|
|
|
265
266
|
if mcp_config.get("http_enabled", False) or http_mode:
|
|
266
|
-
|
|
267
|
-
|
|
267
|
+
mode = "HTTP"
|
|
268
|
+
http_endpoint = (
|
|
269
|
+
f"http://{mcp_config['http_host']}:{mcp_config['http_port']}/mcp"
|
|
268
270
|
)
|
|
269
271
|
else:
|
|
270
|
-
|
|
272
|
+
mode = "STDIO"
|
|
273
|
+
http_endpoint = None
|
|
271
274
|
|
|
272
|
-
|
|
273
|
-
|
|
275
|
+
panels.start_panel(
|
|
276
|
+
project_path=project_path,
|
|
277
|
+
mode=mode,
|
|
278
|
+
http_endpoint=http_endpoint,
|
|
279
|
+
websocket_port=websocket_port,
|
|
280
|
+
)
|
|
274
281
|
|
|
275
282
|
|
|
276
283
|
def _run_mcp_server(
|
|
@@ -331,6 +338,26 @@ def main(
|
|
|
331
338
|
f"[yellow]⚠️ WebSocket server auto-start failed: {e}[/yellow]"
|
|
332
339
|
)
|
|
333
340
|
|
|
341
|
+
# Show final success panel before starting the server
|
|
342
|
+
panels = create_server_panels(console)
|
|
343
|
+
|
|
344
|
+
if mcp_config.get("http_enabled", False) or http_mode:
|
|
345
|
+
http_endpoint = (
|
|
346
|
+
f"http://{mcp_config['http_host']}:{mcp_config['http_port']}/mcp"
|
|
347
|
+
)
|
|
348
|
+
else:
|
|
349
|
+
http_endpoint = None
|
|
350
|
+
|
|
351
|
+
websocket_monitor = (
|
|
352
|
+
f"ws://127.0.0.1:{websocket_port}" if websocket_port else None
|
|
353
|
+
)
|
|
354
|
+
|
|
355
|
+
panels.success_panel(
|
|
356
|
+
http_endpoint=http_endpoint,
|
|
357
|
+
websocket_monitor=websocket_monitor,
|
|
358
|
+
process_id=None, # Will be set by the process manager
|
|
359
|
+
)
|
|
360
|
+
|
|
334
361
|
_run_mcp_server(mcp_app, mcp_config, http_mode)
|
|
335
362
|
|
|
336
363
|
except KeyboardInterrupt:
|
|
@@ -452,13 +452,13 @@ class DependencyMonitorService:
|
|
|
452
452
|
|
|
453
453
|
import requests
|
|
454
454
|
|
|
455
|
-
url = f"https
|
|
455
|
+
url = f"https://pypi.org/pypi/{package}/json"
|
|
456
456
|
self._validate_pypi_url(url)
|
|
457
457
|
|
|
458
458
|
parsed = urlparse(url)
|
|
459
459
|
|
|
460
460
|
if parsed.scheme != "https" or parsed.netloc != "pypi.org":
|
|
461
|
-
msg = f"Invalid URL: only https
|
|
461
|
+
msg = f"Invalid URL: only https://pypi.org URLs are allowed, got {url}"
|
|
462
462
|
raise ValueError(msg)
|
|
463
463
|
|
|
464
464
|
response = requests.get(url, timeout=10, verify=True)
|
|
@@ -347,11 +347,11 @@ class HealthMetricsService:
|
|
|
347
347
|
try:
|
|
348
348
|
from urllib.parse import urlparse
|
|
349
349
|
|
|
350
|
-
url = f"https
|
|
350
|
+
url = f"https://pypi.org/pypi/{package_name}/json"
|
|
351
351
|
|
|
352
352
|
parsed = urlparse(url)
|
|
353
353
|
if parsed.scheme != "https" or parsed.netloc != "pypi.org":
|
|
354
|
-
msg = f"Invalid URL: only https
|
|
354
|
+
msg = f"Invalid URL: only https://pypi.org URLs are allowed, got {url}"
|
|
355
355
|
raise ValueError(msg)
|
|
356
356
|
|
|
357
357
|
if not parsed.path.startswith("/pypi/") or not parsed.path.endswith(
|
|
@@ -7,6 +7,7 @@ from pathlib import Path
|
|
|
7
7
|
|
|
8
8
|
from rich.console import Console
|
|
9
9
|
|
|
10
|
+
from ..ui.server_panels import create_server_panels
|
|
10
11
|
from .secure_subprocess import execute_secure_subprocess
|
|
11
12
|
from .security_logger import get_security_logger
|
|
12
13
|
|
|
@@ -201,21 +202,27 @@ def stop_mcp_server(console: Console | None = None) -> bool:
|
|
|
201
202
|
if console is None:
|
|
202
203
|
console = Console()
|
|
203
204
|
|
|
205
|
+
panels = create_server_panels(console)
|
|
204
206
|
processes = find_mcp_server_processes()
|
|
205
207
|
|
|
206
208
|
if not processes:
|
|
207
209
|
console.print("[yellow]⚠️ No MCP server processes found[/ yellow]")
|
|
208
210
|
return True
|
|
209
211
|
|
|
212
|
+
panels.stop_servers(len(processes))
|
|
213
|
+
|
|
210
214
|
success = True
|
|
211
215
|
for proc in processes:
|
|
212
|
-
console.print(f"
|
|
216
|
+
console.print(f"Stopping process {proc['pid']}...")
|
|
213
217
|
if stop_process(proc["pid"]):
|
|
214
|
-
console.print(f"✅
|
|
218
|
+
console.print(f"✅ Process {proc['pid']} terminated gracefully")
|
|
215
219
|
else:
|
|
216
220
|
console.print(f"❌ Failed to stop process {proc['pid']}")
|
|
217
221
|
success = False
|
|
218
222
|
|
|
223
|
+
if success:
|
|
224
|
+
panels.stop_complete(len(processes))
|
|
225
|
+
|
|
219
226
|
return success
|
|
220
227
|
|
|
221
228
|
|
|
@@ -282,14 +289,15 @@ def restart_mcp_server(
|
|
|
282
289
|
if console is None:
|
|
283
290
|
console = Console()
|
|
284
291
|
|
|
285
|
-
|
|
292
|
+
panels = create_server_panels(console)
|
|
293
|
+
panels.restart_header()
|
|
286
294
|
|
|
287
295
|
stop_mcp_server(console)
|
|
288
296
|
|
|
289
|
-
|
|
297
|
+
panels.cleanup_wait()
|
|
290
298
|
time.sleep(2)
|
|
291
299
|
|
|
292
|
-
|
|
300
|
+
panels.starting_server()
|
|
293
301
|
try:
|
|
294
302
|
cmd = [sys.executable, "-m", "crackerjack", "--start-mcp-server"]
|
|
295
303
|
if websocket_port:
|
|
@@ -297,7 +305,7 @@ def restart_mcp_server(
|
|
|
297
305
|
|
|
298
306
|
import subprocess
|
|
299
307
|
|
|
300
|
-
subprocess.Popen(
|
|
308
|
+
process = subprocess.Popen(
|
|
301
309
|
cmd,
|
|
302
310
|
stdout=subprocess.DEVNULL,
|
|
303
311
|
stderr=subprocess.DEVNULL,
|
|
@@ -310,11 +318,24 @@ def restart_mcp_server(
|
|
|
310
318
|
purpose="mcp_server_restart",
|
|
311
319
|
)
|
|
312
320
|
|
|
313
|
-
|
|
321
|
+
# Give the server a moment to start
|
|
322
|
+
time.sleep(1)
|
|
323
|
+
|
|
324
|
+
# Display success panel with server details
|
|
325
|
+
http_endpoint = "http://127.0.0.1:8676/mcp"
|
|
326
|
+
websocket_monitor = (
|
|
327
|
+
f"ws://127.0.0.1:{websocket_port or 8675}" if websocket_port else None
|
|
328
|
+
)
|
|
329
|
+
|
|
330
|
+
panels.success_panel(
|
|
331
|
+
http_endpoint=http_endpoint,
|
|
332
|
+
websocket_monitor=websocket_monitor,
|
|
333
|
+
process_id=process.pid,
|
|
334
|
+
)
|
|
314
335
|
return True
|
|
315
336
|
|
|
316
337
|
except Exception as e:
|
|
317
|
-
|
|
338
|
+
panels.failure_panel(str(e))
|
|
318
339
|
return False
|
|
319
340
|
|
|
320
341
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""UI components for Crackerjack."""
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""Rich panel utilities for MCP server operations with consistent styling."""
|
|
2
|
+
|
|
3
|
+
import typing as t
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
from rich.panel import Panel
|
|
8
|
+
from rich.text import Text
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ServerPanels:
|
|
12
|
+
"""Rich panel utilities for server operations with 74-char width limit."""
|
|
13
|
+
|
|
14
|
+
WIDTH = 74 # Match session-mgmt-mcp width constraint
|
|
15
|
+
|
|
16
|
+
def __init__(self, console: Console | None = None) -> None:
|
|
17
|
+
self.console = console or Console()
|
|
18
|
+
|
|
19
|
+
def restart_header(self) -> None:
|
|
20
|
+
"""Display server restart header panel."""
|
|
21
|
+
panel = Panel(
|
|
22
|
+
"🔄 Restarting Crackerjack MCP Server...",
|
|
23
|
+
width=self.WIDTH,
|
|
24
|
+
title="Server Restart",
|
|
25
|
+
style="cyan",
|
|
26
|
+
)
|
|
27
|
+
self.console.print(panel)
|
|
28
|
+
|
|
29
|
+
def stop_servers(self, count: int) -> None:
|
|
30
|
+
"""Display stopping servers status."""
|
|
31
|
+
self.console.print("📴 Stopping existing servers...")
|
|
32
|
+
self.console.print(f"🛑 Stopping {count} server process(es)...")
|
|
33
|
+
|
|
34
|
+
def process_stopped(self, pid: int) -> None:
|
|
35
|
+
"""Display process stopped message."""
|
|
36
|
+
self.console.print(f"Stopping process {pid}...")
|
|
37
|
+
self.console.print(f"✅ Process {pid} terminated gracefully")
|
|
38
|
+
|
|
39
|
+
def stop_complete(self, count: int) -> None:
|
|
40
|
+
"""Display stop completion panel."""
|
|
41
|
+
panel = Panel(
|
|
42
|
+
f"✅ Successfully stopped {count} process(es)",
|
|
43
|
+
width=self.WIDTH,
|
|
44
|
+
title="Server Stopped",
|
|
45
|
+
style="green",
|
|
46
|
+
)
|
|
47
|
+
self.console.print(panel)
|
|
48
|
+
|
|
49
|
+
def cleanup_wait(self) -> None:
|
|
50
|
+
"""Display cleanup waiting message."""
|
|
51
|
+
self.console.print("⏳ Waiting for cleanup...")
|
|
52
|
+
|
|
53
|
+
def starting_server(self) -> None:
|
|
54
|
+
"""Display starting server message."""
|
|
55
|
+
self.console.print("🚀 Starting fresh server instance...")
|
|
56
|
+
self.console.print("🚀 Starting Crackerjack MCP Server...")
|
|
57
|
+
self.console.print("⏳ Waiting for server to start...")
|
|
58
|
+
|
|
59
|
+
def success_panel(
|
|
60
|
+
self,
|
|
61
|
+
http_endpoint: str | None = None,
|
|
62
|
+
websocket_monitor: str | None = None,
|
|
63
|
+
process_id: int | None = None
|
|
64
|
+
) -> None:
|
|
65
|
+
"""Display success panel with server details."""
|
|
66
|
+
content = Text()
|
|
67
|
+
content.append("✅ Server started successfully!\n", style="green bold")
|
|
68
|
+
|
|
69
|
+
if http_endpoint:
|
|
70
|
+
content.append(f"🌐 HTTP Endpoint: {http_endpoint}\n", style="cyan")
|
|
71
|
+
|
|
72
|
+
if websocket_monitor:
|
|
73
|
+
content.append(f"🔌 WebSocket Monitor: {websocket_monitor}\n", style="cyan")
|
|
74
|
+
|
|
75
|
+
if process_id:
|
|
76
|
+
content.append(f"📊 Process ID: {process_id}", style="cyan")
|
|
77
|
+
|
|
78
|
+
panel = Panel(
|
|
79
|
+
content,
|
|
80
|
+
width=self.WIDTH,
|
|
81
|
+
title="Crackerjack MCP Server",
|
|
82
|
+
style="green",
|
|
83
|
+
)
|
|
84
|
+
self.console.print(panel)
|
|
85
|
+
|
|
86
|
+
def failure_panel(self, error: str) -> None:
|
|
87
|
+
"""Display failure panel with error details."""
|
|
88
|
+
panel = Panel(
|
|
89
|
+
f"❌ Server failed to start: {error}",
|
|
90
|
+
width=self.WIDTH,
|
|
91
|
+
title="Server Error",
|
|
92
|
+
style="red",
|
|
93
|
+
)
|
|
94
|
+
self.console.print(panel)
|
|
95
|
+
|
|
96
|
+
def start_panel(
|
|
97
|
+
self,
|
|
98
|
+
project_path: Path,
|
|
99
|
+
mode: str = "STDIO",
|
|
100
|
+
http_endpoint: str | None = None,
|
|
101
|
+
websocket_port: int | None = None,
|
|
102
|
+
) -> None:
|
|
103
|
+
"""Display server start panel with configuration details."""
|
|
104
|
+
content = Text()
|
|
105
|
+
content.append("🚀 Starting Crackerjack MCP Server...\n", style="green bold")
|
|
106
|
+
content.append(f"📁 Project: {project_path.name}\n", style="cyan")
|
|
107
|
+
content.append(f"🔗 Mode: {mode}\n", style="cyan")
|
|
108
|
+
|
|
109
|
+
if http_endpoint:
|
|
110
|
+
content.append(f"🌐 HTTP: {http_endpoint}\n", style="cyan")
|
|
111
|
+
|
|
112
|
+
if websocket_port:
|
|
113
|
+
content.append(f"🔌 WebSocket: {websocket_port}", style="cyan")
|
|
114
|
+
|
|
115
|
+
panel = Panel(
|
|
116
|
+
content,
|
|
117
|
+
width=self.WIDTH,
|
|
118
|
+
title="Server Configuration",
|
|
119
|
+
style="green",
|
|
120
|
+
)
|
|
121
|
+
self.console.print(panel)
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def create_server_panels(console: Console | None = None) -> ServerPanels:
|
|
125
|
+
"""Factory function to create ServerPanels instance."""
|
|
126
|
+
return ServerPanels(console)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: crackerjack
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.35.1
|
|
4
4
|
Summary: Crackerjack Python project management tool
|
|
5
5
|
Project-URL: documentation, https://github.com/lesleslie/crackerjack
|
|
6
6
|
Project-URL: homepage, https://github.com/lesleslie/crackerjack
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
crackerjack/__init__.py,sha256=k8_Ev_3fWdjFtGNSJdSOvyaSLW54y3j484d3a8k_Ob4,1396
|
|
2
|
-
crackerjack/__main__.py,sha256=
|
|
3
|
-
crackerjack/api.py,sha256=
|
|
2
|
+
crackerjack/__main__.py,sha256=lE5ZDbAzI9TLCzMTxFGw23Dk1hP-MEhd1i_nNbi_Mag,52515
|
|
3
|
+
crackerjack/api.py,sha256=sfKzCphsTMFCvdNizviPdYemwg0H8Oei_5C08LAuDvA,21538
|
|
4
4
|
crackerjack/code_cleaner.py,sha256=M1zVaq31uW0nOkPneKR8kfR3892gyyVx0VhFgRaxsj4,44338
|
|
5
|
-
crackerjack/dynamic_config.py,sha256=
|
|
5
|
+
crackerjack/dynamic_config.py,sha256=YGlUyTEp_K9rGWtLsboXMtVeKyI7bUoNoftO3ZnCiwc,21815
|
|
6
6
|
crackerjack/errors.py,sha256=yYbZ92kn_y6acEWgQvEPvozAYs2HT65uLwAXrtXxGsE,10049
|
|
7
7
|
crackerjack/interactive.py,sha256=QXFZrnbY0nc8rFJcivFAVFNgUTHXqLCu3FFv5bmq_eI,21634
|
|
8
8
|
crackerjack/adapters/__init__.py,sha256=k-8ajMDL9DS9hV2FYOu694nmNQg3HkudJRuNcXmx8N4,451
|
|
@@ -15,7 +15,7 @@ crackerjack/agents/__init__.py,sha256=OkL6WdzTk1_EnhJpIPsHV2qCrw6tqKegu_zTpZXnJi
|
|
|
15
15
|
crackerjack/agents/architect_agent.py,sha256=Gq9eAy1_pl-1iEYC28xn4rdIPi9AVynZ7Sd5FnBrNn8,8130
|
|
16
16
|
crackerjack/agents/base.py,sha256=XRF0VKrkIB-QJ_izuM33EPKL26gBABrDKKgMNJy9lJQ,4888
|
|
17
17
|
crackerjack/agents/coordinator.py,sha256=uLh-9aTJedqmTSDmwV2dx42_aeIIOCEFbcdj9wcIR4w,22470
|
|
18
|
-
crackerjack/agents/documentation_agent.py,sha256=
|
|
18
|
+
crackerjack/agents/documentation_agent.py,sha256=bI9qPJ5rTZrjimythO_N27zpJFrFcP6i1N2hYZMr_u4,17178
|
|
19
19
|
crackerjack/agents/dry_agent.py,sha256=OP386uTOEQEQZCetCIHV6j7_cl7BKrhK3BmAmRqdgYI,13302
|
|
20
20
|
crackerjack/agents/formatting_agent.py,sha256=eDkLABvpkc3vkYLBjsjib9_AtqsdjxyPIddIvD293L8,6821
|
|
21
21
|
crackerjack/agents/import_optimization_agent.py,sha256=DoDaN7Pb0Z6Nt6YkkKeWMu3Paffy5eOb6ao4khtL3ko,40578
|
|
@@ -34,7 +34,7 @@ crackerjack/cli/cache_handlers_enhanced.py,sha256=6X5rYSo1l-rj9eb7eB8mpA-6BlUagy
|
|
|
34
34
|
crackerjack/cli/facade.py,sha256=e4_oB04awqEijI3yqiYAZGc6x09uMBa4ih0SsXpgMuY,3751
|
|
35
35
|
crackerjack/cli/handlers.py,sha256=mYhwMLUKid6mQLff0ScpcnhP0yUS9IzOIMdM7VLkUCc,17178
|
|
36
36
|
crackerjack/cli/interactive.py,sha256=bGOMXHYyuselHh2b4khbDGJ4tX9yI2rVN3SZ1oSDOaM,16988
|
|
37
|
-
crackerjack/cli/options.py,sha256=
|
|
37
|
+
crackerjack/cli/options.py,sha256=tpvOMQHrL7-j9wuo2_NwvzJTAWF3XcyeOEonQPbepa4,35433
|
|
38
38
|
crackerjack/cli/utils.py,sha256=XC7dT8GNidhORjUe2p2hQOpZgCi2KvVCNu6g3azzgqY,584
|
|
39
39
|
crackerjack/config/__init__.py,sha256=b0481N2f_JvGufMPcbo5IXu2VjYd111r1BHw0oD3x7o,330
|
|
40
40
|
crackerjack/config/global_lock_config.py,sha256=PyonoA2__HKEEvn6SD-gEYh9iD7xIAdts2C3lNoTWhw,1996
|
|
@@ -84,7 +84,7 @@ crackerjack/intelligence/integration.py,sha256=vVaC2Fp5RbbABpaohCePzGw1XANuRztGl
|
|
|
84
84
|
crackerjack/managers/__init__.py,sha256=PFWccXx4hDQA76T02idAViOLVD-aPeVpgjdfSkh_Dmk,298
|
|
85
85
|
crackerjack/managers/async_hook_manager.py,sha256=c0HFR98sFwfk0uZ3NmAe_6OVZpBrq9I570V8A2DoIxw,5129
|
|
86
86
|
crackerjack/managers/hook_manager.py,sha256=_FT0ngwPwujqg0KZGpLz-pP07mwDmptJ5pVkiy5yS8k,7820
|
|
87
|
-
crackerjack/managers/publish_manager.py,sha256
|
|
87
|
+
crackerjack/managers/publish_manager.py,sha256=-sHzSVMF6fSUXuPdWA47gBFkFCT8sIb4cPj3GJB-uX4,21370
|
|
88
88
|
crackerjack/managers/test_command_builder.py,sha256=1TlPzddNcDDxRORH6UvAudcbRc6hKwFyknSEVLkiWAo,3459
|
|
89
89
|
crackerjack/managers/test_executor.py,sha256=2837Ti4OaNsmLxnmELjbQ18hmfL0-Z2EW-W2UeFSDcE,13871
|
|
90
90
|
crackerjack/managers/test_manager.py,sha256=BRPBWXx4flPDK0w96xyHhg-9dmUca1vpKQRM2VofSlI,13158
|
|
@@ -97,11 +97,11 @@ crackerjack/mcp/context.py,sha256=T1rhScFxbqi0Kaf6o8NusVUIwc8o7YGxcsLdmlWVsPI,28
|
|
|
97
97
|
crackerjack/mcp/dashboard.py,sha256=eApQekZe1DfKBrlDW5yobyqaN_gdh17ZQlqGmut5TCs,19602
|
|
98
98
|
crackerjack/mcp/enhanced_progress_monitor.py,sha256=xhACaEjreDw1cLObJmhr5ttowl5mRqeohmMzQfRQj3w,16448
|
|
99
99
|
crackerjack/mcp/file_monitor.py,sha256=4OR-nxqH0ettiGInIY6MckFoflwX5VP9bgxXcAZZzfE,12824
|
|
100
|
-
crackerjack/mcp/progress_components.py,sha256=
|
|
100
|
+
crackerjack/mcp/progress_components.py,sha256=URtnrNv1QQzUKY3msO_cBrYHjPlzVDqFbZa_trfZHXY,20535
|
|
101
101
|
crackerjack/mcp/progress_monitor.py,sha256=3TxQ_Og1md8zuNrH9cltOa8RQf_5lHNiVh9DiBkvbBM,37546
|
|
102
102
|
crackerjack/mcp/rate_limiter.py,sha256=oM29wHyvoR9Q9cMBAEqWquHoiBBS1ylrZkUhhFnDkVo,12309
|
|
103
103
|
crackerjack/mcp/server.py,sha256=-AdHHoFNAtoPM1A3_M2giZbIbggUhhvv16uIXk2xqNo,403
|
|
104
|
-
crackerjack/mcp/server_core.py,sha256=
|
|
104
|
+
crackerjack/mcp/server_core.py,sha256=o93_j8nmGRIl-FL-Y5cKCDDJh3J7vTi1SmxIOdoqj0w,11301
|
|
105
105
|
crackerjack/mcp/service_watchdog.py,sha256=_z99JrYrmVaXI2tVERts0_xHsl4pjltD5iF47mQVADk,16826
|
|
106
106
|
crackerjack/mcp/state.py,sha256=pNclwUxGTH5YiRMq8hB15B9_rpX9aJ-IVnhMw7q9dtI,14427
|
|
107
107
|
crackerjack/mcp/task_manager.py,sha256=hxuZGbRHwEBO-W3UTbg7Lx7gMhTcPRaAiQ8I8VIFs6g,8713
|
|
@@ -166,7 +166,7 @@ crackerjack/services/coverage_badge_service.py,sha256=gzC3LEyVLt4rpf378APsFVRGgN
|
|
|
166
166
|
crackerjack/services/coverage_ratchet.py,sha256=eKxmFyg-7Rnctnk--6P-yNNOFhoKwzTxd4iCJ52dtZE,13439
|
|
167
167
|
crackerjack/services/debug.py,sha256=kTy2vy6JjjNReNn4z7xmhXDVIj8xImaE67kYi-Pfb3o,23227
|
|
168
168
|
crackerjack/services/dependency_analyzer.py,sha256=4MxexuyQ3wyPHVsHr77N22EsAqZTDGOVcSBSm1mOXFQ,16322
|
|
169
|
-
crackerjack/services/dependency_monitor.py,sha256=
|
|
169
|
+
crackerjack/services/dependency_monitor.py,sha256=x_PpRUt-LbzHlTyoSt2kiXTQn2fqAiqouiwFSAU9SGg,20560
|
|
170
170
|
crackerjack/services/documentation_generator.py,sha256=xDJ2dv3Q_HTGCPJADKPVtYzcIpSOhuH5qUxPU2ttICE,16482
|
|
171
171
|
crackerjack/services/documentation_service.py,sha256=V2fY01u_tP_ep87KMGxIocgP6hfpwbf-YyVqssLQSns,24792
|
|
172
172
|
crackerjack/services/enhanced_filesystem.py,sha256=IT-obfj2U2Sfy0iJOq0ZAiczEN6LdHf6VAhnugQe1mQ,15487
|
|
@@ -175,7 +175,7 @@ crackerjack/services/error_pattern_analyzer.py,sha256=bTMwhAMAjVPSUXrNkrtm1KDqfx
|
|
|
175
175
|
crackerjack/services/file_hasher.py,sha256=eReytwwK-_-B8JBnpwytDC52cKKgg4qpaxaZKcQjD-0,5211
|
|
176
176
|
crackerjack/services/filesystem.py,sha256=nmL3mYqylS_BSQpwFbC7EMHoA44K5qUxa9CPg1QFZvc,17480
|
|
177
177
|
crackerjack/services/git.py,sha256=g0D9K7PFGWiv_-CbPXEhGtxJVJccEsshYNEmGstjXss,12716
|
|
178
|
-
crackerjack/services/health_metrics.py,sha256=
|
|
178
|
+
crackerjack/services/health_metrics.py,sha256=nDuKEC2a5csOhMpy6zXJkls1Y4Vfrr62-4cFcWCr8ow,21536
|
|
179
179
|
crackerjack/services/heatmap_generator.py,sha256=zz5V-zXPfoCGNXoj7iuyOeFuDRRUhFpxuENUnd0X75g,26200
|
|
180
180
|
crackerjack/services/initialization.py,sha256=_ZjGpIG5eGHzrVXCxlhlouhY-E-4OITEln1GDTswZ6s,26049
|
|
181
181
|
crackerjack/services/input_validator.py,sha256=Botr3ottp9InSw163QaFrNfy0kM_STsJdWBbjsCX96M,22262
|
|
@@ -202,7 +202,7 @@ crackerjack/services/secure_status_formatter.py,sha256=yhwNtzvvQVcuHsNOTNZMzlqIM
|
|
|
202
202
|
crackerjack/services/secure_subprocess.py,sha256=upuiBL0sYIElC8DWQ622-A6572zBaSBoMPVnNM8AeaQ,19838
|
|
203
203
|
crackerjack/services/security.py,sha256=plgIz-B8oYN_mpF4NYrqHnT7TRcsp4jr0-YlV9WgD5o,7298
|
|
204
204
|
crackerjack/services/security_logger.py,sha256=AAjd9VKVmCo158UifyEKd79VgtWKeuaIVyXYL8qvqT8,17001
|
|
205
|
-
crackerjack/services/server_manager.py,sha256=
|
|
205
|
+
crackerjack/services/server_manager.py,sha256=MwvMMxhaCiZD4pcKM2ODXB-gu2s22n_v_uIqrwoJsHs,11934
|
|
206
206
|
crackerjack/services/smart_scheduling.py,sha256=VSaL7DpKR6aa0sC_TUrYP9ZgC9CB7tE3TTNzEqB-GpE,4352
|
|
207
207
|
crackerjack/services/status_authentication.py,sha256=2OJ1MoWlBuvUUXOX02N_zdWKzQfXz4jhEZpsmIJfQ00,16453
|
|
208
208
|
crackerjack/services/status_security_manager.py,sha256=et0h6w7Wt1cPFjzg7frsykAQ-IMfiAXr44WU9Fs6-1U,10967
|
|
@@ -222,8 +222,10 @@ crackerjack/slash_commands/status.md,sha256=U3qqppVLtIIm2lEiMYaKagaHYLI9UplL7OH1
|
|
|
222
222
|
crackerjack/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
223
223
|
crackerjack/tools/validate_input_validator_patterns.py,sha256=NN7smYlXWrHLQXTb-81gRam2vjW-cJav92f1klPA0qA,8234
|
|
224
224
|
crackerjack/tools/validate_regex_patterns.py,sha256=9ejFb7Tw1js_oydzuEeeeXvrU5ipHUEX9ATBfkLCCE8,5811
|
|
225
|
-
crackerjack
|
|
226
|
-
crackerjack
|
|
227
|
-
crackerjack-0.
|
|
228
|
-
crackerjack-0.
|
|
229
|
-
crackerjack-0.
|
|
225
|
+
crackerjack/ui/__init__.py,sha256=seLTuIcCzZDvUNfCvm1xNkiw0814JqUxoaQKmocJPpU,36
|
|
226
|
+
crackerjack/ui/server_panels.py,sha256=1MsCbKVPUD6EOONw7miovL_r5CDvllTxjnVU14dKtIE,4249
|
|
227
|
+
crackerjack-0.35.1.dist-info/METADATA,sha256=s6RH3Wqup4CHvmsEcd3fTtqBnshDsrGM9-0cZJkDMgE,37942
|
|
228
|
+
crackerjack-0.35.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
229
|
+
crackerjack-0.35.1.dist-info/entry_points.txt,sha256=AJKNft0WXm9xoGUJ3Trl-iXHOWxRAYbagQiza3AILr4,57
|
|
230
|
+
crackerjack-0.35.1.dist-info/licenses/LICENSE,sha256=fDt371P6_6sCu7RyqiZH_AhT1LdN3sN1zjBtqEhDYCk,1531
|
|
231
|
+
crackerjack-0.35.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|