hashcli 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. hashcli-0.1.0/LICENSE +21 -0
  2. hashcli-0.1.0/PKG-INFO +52 -0
  3. hashcli-0.1.0/README.md +9 -0
  4. hashcli-0.1.0/hashcli/__init__.py +29 -0
  5. hashcli-0.1.0/hashcli/command_proxy.py +240 -0
  6. hashcli-0.1.0/hashcli/commands/__init__.py +17 -0
  7. hashcli-0.1.0/hashcli/commands/clear.py +70 -0
  8. hashcli-0.1.0/hashcli/commands/config.py +124 -0
  9. hashcli-0.1.0/hashcli/commands/fix.py +54 -0
  10. hashcli-0.1.0/hashcli/commands/help.py +89 -0
  11. hashcli-0.1.0/hashcli/commands/ls.py +88 -0
  12. hashcli-0.1.0/hashcli/commands/model.py +143 -0
  13. hashcli-0.1.0/hashcli/config.py +348 -0
  14. hashcli-0.1.0/hashcli/history.py +451 -0
  15. hashcli-0.1.0/hashcli/llm_handler.py +340 -0
  16. hashcli-0.1.0/hashcli/main.py +321 -0
  17. hashcli-0.1.0/hashcli/providers/__init__.py +13 -0
  18. hashcli-0.1.0/hashcli/providers/anthropic_provider.py +157 -0
  19. hashcli-0.1.0/hashcli/providers/base.py +53 -0
  20. hashcli-0.1.0/hashcli/providers/google_provider.py +179 -0
  21. hashcli-0.1.0/hashcli/providers/openai_provider.py +111 -0
  22. hashcli-0.1.0/hashcli/tools/__init__.py +16 -0
  23. hashcli-0.1.0/hashcli/tools/base.py +60 -0
  24. hashcli-0.1.0/hashcli/tools/code_analysis.py +339 -0
  25. hashcli-0.1.0/hashcli/tools/filesystem.py +205 -0
  26. hashcli-0.1.0/hashcli/tools/shell.py +128 -0
  27. hashcli-0.1.0/hashcli/tools/web_search.py +85 -0
  28. hashcli-0.1.0/hashcli.egg-info/PKG-INFO +52 -0
  29. hashcli-0.1.0/hashcli.egg-info/SOURCES.txt +38 -0
  30. hashcli-0.1.0/hashcli.egg-info/dependency_links.txt +1 -0
  31. hashcli-0.1.0/hashcli.egg-info/entry_points.txt +2 -0
  32. hashcli-0.1.0/hashcli.egg-info/requires.txt +18 -0
  33. hashcli-0.1.0/hashcli.egg-info/top_level.txt +1 -0
  34. hashcli-0.1.0/pyproject.toml +151 -0
  35. hashcli-0.1.0/setup.cfg +4 -0
  36. hashcli-0.1.0/tests/test_command_proxy.py +219 -0
  37. hashcli-0.1.0/tests/test_config.py +180 -0
  38. hashcli-0.1.0/tests/test_history.py +335 -0
  39. hashcli-0.1.0/tests/test_integration.py +310 -0
  40. hashcli-0.1.0/tests/test_main.py +87 -0
hashcli-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Wensheng
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
hashcli-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,52 @@
1
+ Metadata-Version: 2.4
2
+ Name: hashcli
3
+ Version: 0.1.0
4
+ Summary: Hash - Intelligent CLI system with dual-mode functionality (LLM chat and command proxy)
5
+ Author: Wensheng Wang
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/wensheng/hash
8
+ Project-URL: Repository, https://github.com/wensheng/hash.git
9
+ Project-URL: Documentation, https://github.com/wensheng/hash/docs
10
+ Project-URL: Bug Tracker, https://github.com/wensheng/hash/issues
11
+ Keywords: cli,llm,assistant,terminal,ai,hash
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
20
+ Classifier: Topic :: System :: System Shells
21
+ Classifier: Topic :: Utilities
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: openai>=1.0.0
26
+ Requires-Dist: google-generativeai>=0.3.0
27
+ Requires-Dist: anthropic>=0.28.0
28
+ Requires-Dist: typer[all]>=0.9.0
29
+ Requires-Dist: rich>=13.0.0
30
+ Requires-Dist: pydantic>=2.0.0
31
+ Requires-Dist: aiohttp>=3.8.0
32
+ Requires-Dist: toml>=0.10.2
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
35
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
36
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
37
+ Requires-Dist: black>=23.0.0; extra == "dev"
38
+ Requires-Dist: isort>=5.0.0; extra == "dev"
39
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
40
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
41
+ Requires-Dist: pre-commit>=3.0.0; extra == "dev"
42
+ Dynamic: license-file
43
+
44
+ # hash \#
45
+
46
+ Hash # (HAcker SHell).
47
+
48
+ ## Installation
49
+
50
+ With pip:
51
+
52
+ pip install hashcli
@@ -0,0 +1,9 @@
1
+ # hash \#
2
+
3
+ Hash # (HAcker SHell).
4
+
5
+ ## Installation
6
+
7
+ With pip:
8
+
9
+ pip install hashcli
@@ -0,0 +1,29 @@
1
+ """Hash (HAcker SHell) - Intelligent CLI system with dual-mode functionality.
2
+
3
+ This package provides a modern CLI that combines LLM conversational assistance
4
+ with command proxy functionality, operating in two distinct modes:
5
+
6
+ - LLM Chat Mode: Natural language queries for intelligent assistance
7
+ - Command Proxy Mode: Slash-prefixed commands for direct functionality
8
+
9
+ The system is designed for cross-platform compatibility and extensibility,
10
+ supporting multiple LLM providers and built-in command extensions.
11
+ """
12
+
13
+ from .command_proxy import CommandProxy
14
+ from .config import HashConfig
15
+ from .history import ConversationHistory
16
+ from .llm_handler import LLMHandler
17
+ from .main import app
18
+
19
+ __version__ = "0.1.0"
20
+ __author__ = "Hash CLI Team"
21
+ __email__ = "team@hashcli.dev"
22
+
23
+ __all__ = [
24
+ "app",
25
+ "HashConfig",
26
+ "LLMHandler",
27
+ "CommandProxy",
28
+ "ConversationHistory",
29
+ ]
@@ -0,0 +1,240 @@
1
+ """Command proxy system for handling slash-prefixed commands."""
2
+
3
+ import os
4
+ import platform
5
+ import shlex
6
+ import subprocess
7
+ from abc import ABC, abstractmethod
8
+ from typing import Any, Dict, List, Optional
9
+
10
+ from rich.console import Console
11
+
12
+ from .config import HashConfig
13
+
14
+ console = Console()
15
+
16
+
17
+ class Command(ABC):
18
+ """Abstract base class for all commands."""
19
+
20
+ @abstractmethod
21
+ def execute(self, args: List[str], config: HashConfig) -> str:
22
+ """Execute the command with given arguments."""
23
+ pass
24
+
25
+ @abstractmethod
26
+ def get_help(self) -> str:
27
+ """Get help text for this command."""
28
+ pass
29
+
30
+ def validate_args(self, args: List[str]) -> bool:
31
+ """Validate command arguments. Override if needed."""
32
+ return True
33
+
34
+
35
+ class CommandProxy:
36
+ """Main command proxy that routes slash commands to their handlers."""
37
+
38
+ def __init__(self, config: HashConfig):
39
+ self.config = config
40
+ self.commands = self._register_commands()
41
+
42
+ def execute(self, command_line: str) -> str:
43
+ """Execute a slash command."""
44
+ # Remove leading slash and parse command
45
+ command_line = command_line.lstrip().lstrip("/")
46
+
47
+ if not command_line:
48
+ return "No command specified. Use /help for available commands."
49
+
50
+ # Parse command and arguments safely
51
+ try:
52
+ parts = shlex.split(command_line)
53
+ except ValueError as e:
54
+ return f"Error parsing command: {e}"
55
+
56
+ if not parts:
57
+ return "No command specified. Use /help for available commands."
58
+
59
+ cmd = parts[0]
60
+ args = parts[1:] if len(parts) > 1 else []
61
+
62
+ # Check if command exists
63
+ if cmd not in self.commands:
64
+ return f"Unknown command: /{cmd}\nUse /help for available commands."
65
+
66
+ # Get command handler
67
+ handler = self.commands[cmd]
68
+
69
+ # Validate arguments
70
+ if not handler.validate_args(args):
71
+ return f"Invalid arguments for /{cmd}\n{handler.get_help()}"
72
+
73
+ # Execute command
74
+ try:
75
+ return handler.execute(args, self.config)
76
+ except Exception as e:
77
+ if self.config.show_debug:
78
+ import traceback
79
+
80
+ return f"Command execution error: {e}\n{traceback.format_exc()}"
81
+ else:
82
+ return f"Command execution error: {e}"
83
+
84
+ def _register_commands(self) -> Dict[str, Command]:
85
+ """Register all available commands."""
86
+ from .commands import (
87
+ ClearCommand,
88
+ ConfigCommand,
89
+ FixCommand,
90
+ HelpCommand,
91
+ LSCommand,
92
+ ModelCommand,
93
+ )
94
+
95
+ return {
96
+ "ls": LSCommand(),
97
+ "dir": LSCommand(), # Windows alias
98
+ "clear": ClearCommand(),
99
+ "model": ModelCommand(),
100
+ "fix": FixCommand(),
101
+ "help": HelpCommand(),
102
+ "config": ConfigCommand(),
103
+ "history": HistoryCommand(),
104
+ "exit": ExitCommand(),
105
+ "quit": ExitCommand(),
106
+ }
107
+
108
+ def get_available_commands(self) -> List[str]:
109
+ """Get list of available command names."""
110
+ return sorted(self.commands.keys())
111
+
112
+ def get_command_help(self, command: str) -> Optional[str]:
113
+ """Get help for a specific command."""
114
+ if command in self.commands:
115
+ return self.commands[command].get_help()
116
+ return None
117
+
118
+
119
+ class SystemCommand(Command):
120
+ """Base class for system commands that execute shell operations."""
121
+
122
+ def execute_system_command(self, cmd_args: List[str], config: HashConfig) -> str:
123
+ """Execute a system command with security checks."""
124
+
125
+ # Security check: validate command against blocked list
126
+ cmd_str = " ".join(cmd_args)
127
+ for blocked in config.blocked_commands:
128
+ if blocked.lower() in cmd_str.lower():
129
+ return f"Blocked command detected: {blocked}"
130
+
131
+ # Security check: validate against allowed list if configured
132
+ if config.allowed_commands:
133
+ base_cmd = cmd_args[0] if cmd_args else ""
134
+ if base_cmd not in config.allowed_commands:
135
+ return f"Command not in allowed list: {base_cmd}"
136
+
137
+ try:
138
+ # Execute command with timeout
139
+ result = subprocess.run(
140
+ cmd_args,
141
+ capture_output=True,
142
+ text=True,
143
+ timeout=config.command_timeout,
144
+ shell=False, # Never use shell=True for security
145
+ )
146
+
147
+ # Format output
148
+ output = ""
149
+ if result.stdout:
150
+ output += result.stdout
151
+ if result.stderr:
152
+ if output:
153
+ output += "\n"
154
+ output += f"stderr: {result.stderr}"
155
+
156
+ if result.returncode != 0 and not output:
157
+ output = f"Command failed with exit code {result.returncode}"
158
+
159
+ return output.strip()
160
+
161
+ except subprocess.TimeoutExpired:
162
+ return f"Command timed out after {config.command_timeout} seconds"
163
+ except subprocess.CalledProcessError as e:
164
+ return f"Command failed: {e}"
165
+ except FileNotFoundError:
166
+ return f"Command not found: {cmd_args[0] if cmd_args else 'unknown'}"
167
+ except Exception as e:
168
+ return f"Execution error: {e}"
169
+
170
+
171
+ # History command for conversation history management
172
+ class HistoryCommand(Command):
173
+ """Command to manage conversation history."""
174
+
175
+ def execute(self, args: List[str], config: HashConfig) -> str:
176
+ from .history import ConversationHistory
177
+
178
+ if not config.history_enabled:
179
+ return "History is disabled in configuration."
180
+
181
+ history = ConversationHistory(config.history_dir)
182
+
183
+ if not args or args[0] == "list":
184
+ # List recent conversations
185
+ sessions = history.list_sessions()
186
+ if not sessions:
187
+ return "No conversation history found."
188
+
189
+ output = "Recent conversations:\n"
190
+ for session in sessions[-10:]: # Show last 10
191
+ output += f" {session['id']}: {session['created']} ({session['message_count']} messages)\n"
192
+ return output.strip()
193
+
194
+ elif args[0] == "show" and len(args) > 1:
195
+ # Show specific conversation
196
+ session_id = args[1]
197
+ messages = history.get_session_messages(session_id)
198
+ if not messages:
199
+ return f"No messages found for session {session_id}"
200
+
201
+ output = f"Conversation {session_id}:\n\n"
202
+ for msg in messages:
203
+ role = msg["role"].upper()
204
+ content = (
205
+ msg["content"][:200] + "..."
206
+ if len(msg["content"]) > 200
207
+ else msg["content"]
208
+ )
209
+ output += f"[{role}] {content}\n\n"
210
+ return output.strip()
211
+
212
+ elif args[0] == "clear":
213
+ # Clear all history
214
+ if history.clear_all_history():
215
+ return "All conversation history cleared."
216
+ else:
217
+ return "Failed to clear history."
218
+
219
+ else:
220
+ return self.get_help()
221
+
222
+ def get_help(self) -> str:
223
+ return """Manage conversation history:
224
+ /history list - List recent conversations
225
+ /history show <id> - Show specific conversation
226
+ /history clear - Clear all history"""
227
+
228
+
229
+ # Exit command
230
+ class ExitCommand(Command):
231
+ """Command to exit the application."""
232
+
233
+ def execute(self, args: List[str], config: HashConfig) -> str:
234
+ import sys
235
+
236
+ console.print("[yellow]Goodbye![/yellow]")
237
+ sys.exit(0)
238
+
239
+ def get_help(self) -> str:
240
+ return "Exit the Hash CLI application."
@@ -0,0 +1,17 @@
1
+ """Built-in command implementations for command proxy mode."""
2
+
3
+ from .clear import ClearCommand
4
+ from .config import ConfigCommand
5
+ from .fix import FixCommand
6
+ from .help import HelpCommand
7
+ from .ls import LSCommand
8
+ from .model import ModelCommand
9
+
10
+ __all__ = [
11
+ "LSCommand",
12
+ "ClearCommand",
13
+ "ModelCommand",
14
+ "FixCommand",
15
+ "HelpCommand",
16
+ "ConfigCommand",
17
+ ]
@@ -0,0 +1,70 @@
1
+ """Clear command implementation for clearing conversation history."""
2
+
3
+ from typing import List
4
+
5
+ from ..command_proxy import Command
6
+ from ..config import HashConfig
7
+
8
+
9
+ class ClearCommand(Command):
10
+ """Command to clear conversation history."""
11
+
12
+ def execute(self, args: List[str], config: HashConfig) -> str:
13
+ """Clear conversation history."""
14
+ from ..history import ConversationHistory
15
+
16
+ if not config.history_enabled:
17
+ return "History is disabled in configuration."
18
+
19
+ # Parse arguments
20
+ clear_all = "--all" in args or "-a" in args
21
+
22
+ try:
23
+ history = ConversationHistory(config.history_dir)
24
+
25
+ if clear_all:
26
+ # Clear all history
27
+ success = history.clear_all_history()
28
+ if success:
29
+ return "All conversation history cleared successfully."
30
+ else:
31
+ return "Failed to clear conversation history."
32
+ else:
33
+ # Clear old history (default: 30 days)
34
+ days = 30
35
+
36
+ # Check for custom days argument
37
+ for i, arg in enumerate(args):
38
+ if arg == "--days" or arg == "-d":
39
+ if i + 1 < len(args):
40
+ try:
41
+ days = int(args[i + 1])
42
+ except ValueError:
43
+ return f"Invalid days value: {args[i + 1]}"
44
+ break
45
+
46
+ cleared_count = history.clear_old_history(days)
47
+ if cleared_count > 0:
48
+ return f"Cleared {cleared_count} old conversations (older than {days} days)."
49
+ else:
50
+ return f"No conversations older than {days} days found."
51
+
52
+ except Exception as e:
53
+ if config.show_debug:
54
+ import traceback
55
+
56
+ return f"Error clearing history: {e}\n{traceback.format_exc()}"
57
+ else:
58
+ return f"Error clearing history: {e}"
59
+
60
+ def get_help(self) -> str:
61
+ """Get help text for the clear command."""
62
+ return """Clear conversation history:
63
+ /clear - Clear conversations older than 30 days
64
+ /clear --days N - Clear conversations older than N days
65
+ /clear --all - Clear ALL conversation history
66
+
67
+ Examples:
68
+ /clear - Clear old conversations
69
+ /clear --days 7 - Clear conversations older than 7 days
70
+ /clear --all - Clear everything (cannot be undone)"""
@@ -0,0 +1,124 @@
1
+ """Config command implementation for configuration management."""
2
+
3
+ from typing import List
4
+
5
+ from ..command_proxy import Command
6
+ from ..config import HashConfig, save_config
7
+
8
+
9
+ class ConfigCommand(Command):
10
+ """Command to show and manage configuration."""
11
+
12
+ def execute(self, args: List[str], config: HashConfig) -> str:
13
+ """Show or manage configuration."""
14
+
15
+ if not args:
16
+ return self._show_config(config)
17
+
18
+ command = args[0].lower()
19
+
20
+ if command == "show":
21
+ return self._show_config(config)
22
+ elif command == "save":
23
+ return self._save_config(config)
24
+ elif command == "stats":
25
+ return self._show_stats(config)
26
+ else:
27
+ return f"Unknown config command: {command}\n{self.get_help()}"
28
+
29
+ def _show_config(self, config: HashConfig) -> str:
30
+ """Show current configuration."""
31
+ output = "Hash CLI Configuration:\n\n"
32
+
33
+ # LLM Configuration
34
+ output += "[bold blue]LLM Configuration:[/bold blue]\n"
35
+ output += f" Provider: {config.llm_provider.value}\n"
36
+ output += f" Model: {config.get_current_model()}\n"
37
+ output += f" API Key: {'✓ Set' if config.get_current_api_key() else '✗ Not set'}\n\n"
38
+
39
+ # Tool Configuration
40
+ output += "[bold blue]Tool Configuration:[/bold blue]\n"
41
+ output += f" Command execution: {'Enabled' if config.allow_command_execution else 'Disabled'}\n"
42
+ output += f" Confirmation required: {'Yes' if config.require_confirmation else 'No'}\n"
43
+ output += f" Command timeout: {config.command_timeout}s\n"
44
+ output += (
45
+ f" Sandbox commands: {'Yes' if config.sandbox_commands else 'No'}\n\n"
46
+ )
47
+
48
+ # History Configuration
49
+ output += "[bold blue]History Configuration:[/bold blue]\n"
50
+ output += f" History enabled: {'Yes' if config.history_enabled else 'No'}\n"
51
+ if config.history_enabled:
52
+ output += f" History directory: {config.history_dir}\n"
53
+ output += f" Max history size: {config.max_history_size}\n"
54
+ output += f" Retention days: {config.history_retention_days}\n"
55
+ output += "\n"
56
+
57
+ # Output Configuration
58
+ output += "[bold blue]Output Configuration:[/bold blue]\n"
59
+ output += f" Rich output: {'Yes' if config.rich_output else 'No'}\n"
60
+ output += f" Debug mode: {'Yes' if config.show_debug else 'No'}\n"
61
+ output += f" Log level: {config.log_level.value}\n\n"
62
+
63
+ # Security Configuration
64
+ output += "[bold blue]Security Configuration:[/bold blue]\n"
65
+ if config.allowed_commands:
66
+ output += f" Allowed commands: {', '.join(config.allowed_commands)}\n"
67
+ else:
68
+ output += f" Allowed commands: All (no whitelist)\n"
69
+ output += f" Blocked commands: {', '.join(config.blocked_commands)}\n"
70
+
71
+ return output.strip()
72
+
73
+ def _save_config(self, config: HashConfig) -> str:
74
+ """Save current configuration to file."""
75
+ try:
76
+ success = save_config(config)
77
+ if success:
78
+ config_path = config.history_dir.parent / "config.toml"
79
+ return f"Configuration saved to {config_path}"
80
+ else:
81
+ return "Failed to save configuration"
82
+ except Exception as e:
83
+ return f"Error saving configuration: {e}"
84
+
85
+ def _show_stats(self, config: HashConfig) -> str:
86
+ """Show usage statistics."""
87
+ if not config.history_enabled:
88
+ return "History is disabled - no statistics available."
89
+
90
+ try:
91
+ from ..history import ConversationHistory
92
+
93
+ history = ConversationHistory(config.history_dir)
94
+ stats = history.get_statistics()
95
+
96
+ output = "Hash CLI Usage Statistics:\n\n"
97
+ output += f"Total conversations: {stats['total_sessions']}\n"
98
+ output += f"Total messages: {stats['total_messages']}\n"
99
+ output += f"Recent conversations (7d): {stats['recent_sessions_7d']}\n"
100
+ output += f"Recent messages (7d): {stats['recent_messages_7d']}\n"
101
+ output += f"Database size: {stats['database_size_bytes'] / 1024:.1f} KB\\n"
102
+ output += f"Database location: {stats['database_path']}\\n"
103
+
104
+ if stats["total_sessions"] > 0:
105
+ avg_messages = stats["total_messages"] / stats["total_sessions"]
106
+ output += f"Average messages per conversation: {avg_messages:.1f}\\n"
107
+
108
+ return output
109
+
110
+ except Exception as e:
111
+ return f"Error getting statistics: {e}"
112
+
113
+ def get_help(self) -> str:
114
+ """Get help text for the config command."""
115
+ return """Show and manage configuration:
116
+ /config - Show current configuration
117
+ /config show - Show current configuration (same as above)
118
+ /config save - Save current config to file
119
+ /config stats - Show usage statistics
120
+
121
+ Examples:
122
+ /config - View all settings
123
+ /config save - Save to ~/.hashcli/config.toml
124
+ /config stats - See usage statistics"""
@@ -0,0 +1,54 @@
1
+ """Fix command implementation for coding assistance."""
2
+
3
+ from typing import List
4
+
5
+ from ..command_proxy import Command
6
+ from ..config import HashConfig
7
+
8
+
9
+ class FixCommand(Command):
10
+ """Command for coding-specialized assistance."""
11
+
12
+ def execute(self, args: List[str], config: HashConfig) -> str:
13
+ """Execute fix command for coding assistance."""
14
+
15
+ if not args:
16
+ return self.get_help()
17
+
18
+ # Join all arguments into a description
19
+ description = " ".join(args)
20
+
21
+ # Create a specialized prompt for coding assistance
22
+ coding_prompt = f"""I need help with a coding issue. Please provide a practical solution:
23
+
24
+ Issue: {description}
25
+
26
+ Please provide:
27
+ 1. A clear explanation of the problem
28
+ 2. A concrete solution with code examples if applicable
29
+ 3. Any relevant best practices or alternatives
30
+ 4. Commands to run if needed (I can execute them with your guidance)
31
+
32
+ Focus on being practical and actionable."""
33
+
34
+ # This would normally trigger LLM mode with the specialized prompt
35
+ # For now, return a message indicating the prompt would be processed
36
+ return f"Coding assistance request: '{description}'\n\nThis would normally trigger an LLM conversation with specialized coding context. In a full implementation, this would seamlessly switch to LLM mode with the enhanced prompt above."
37
+
38
+ def get_help(self) -> str:
39
+ """Get help text for the fix command."""
40
+ return """Get coding assistance for development issues:
41
+ /fix <description> - Get help with a coding problem
42
+
43
+ Examples:
44
+ /fix my python script has a syntax error
45
+ /fix how do I implement authentication in Express.js
46
+ /fix git merge conflict resolution
47
+ /fix optimize this slow database query
48
+ /fix unit test is failing with TypeError
49
+
50
+ This command provides specialized coding assistance with:
51
+ - Problem analysis and solutions
52
+ - Code examples and best practices
53
+ - Command suggestions for fixes
54
+ - Step-by-step guidance"""