cliops 1.0.0__tar.gz → 1.0.2__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 (28) hide show
  1. {cliops-1.0.0/cliops.egg-info → cliops-1.0.2}/PKG-INFO +1 -1
  2. {cliops-1.0.0 → cliops-1.0.2/cliops.egg-info}/PKG-INFO +1 -1
  3. {cliops-1.0.0 → cliops-1.0.2}/cliops.egg-info/SOURCES.txt +2 -0
  4. cliops-1.0.2/cliops.egg-info/top_level.txt +3 -0
  5. cliops-1.0.2/main.py +177 -0
  6. cliops-1.0.2/presets.py +93 -0
  7. {cliops-1.0.0 → cliops-1.0.2}/setup.py +2 -1
  8. cliops-1.0.0/cliops.egg-info/top_level.txt +0 -1
  9. {cliops-1.0.0 → cliops-1.0.2}/LICENSE +0 -0
  10. {cliops-1.0.0 → cliops-1.0.2}/MANIFEST.in +0 -0
  11. {cliops-1.0.0 → cliops-1.0.2}/README.md +0 -0
  12. {cliops-1.0.0 → cliops-1.0.2}/cliops.egg-info/dependency_links.txt +0 -0
  13. {cliops-1.0.0 → cliops-1.0.2}/cliops.egg-info/entry_points.txt +0 -0
  14. {cliops-1.0.0 → cliops-1.0.2}/cliops.egg-info/not-zip-safe +0 -0
  15. {cliops-1.0.0 → cliops-1.0.2}/cliops.egg-info/requires.txt +0 -0
  16. {cliops-1.0.0 → cliops-1.0.2}/core/__init__.py +0 -0
  17. {cliops-1.0.0 → cliops-1.0.2}/core/analyzer.py +0 -0
  18. {cliops-1.0.0 → cliops-1.0.2}/core/config.py +0 -0
  19. {cliops-1.0.0 → cliops-1.0.2}/core/optimizer.py +0 -0
  20. {cliops-1.0.0 → cliops-1.0.2}/core/patterns.py +0 -0
  21. {cliops-1.0.0 → cliops-1.0.2}/core/state.py +0 -0
  22. {cliops-1.0.0 → cliops-1.0.2}/requirements.txt +0 -0
  23. {cliops-1.0.0 → cliops-1.0.2}/setup.cfg +0 -0
  24. {cliops-1.0.0 → cliops-1.0.2}/tests/__init__.py +0 -0
  25. {cliops-1.0.0 → cliops-1.0.2}/tests/test_integration.py +0 -0
  26. {cliops-1.0.0 → cliops-1.0.2}/tests/test_optimizer.py +0 -0
  27. {cliops-1.0.0 → cliops-1.0.2}/tests/test_patterns.py +0 -0
  28. {cliops-1.0.0 → cliops-1.0.2}/tests/test_state.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cliops
3
- Version: 1.0.0
3
+ Version: 1.0.2
4
4
  Summary: Advanced CLI tool for structured, pattern-based prompt optimization and state management
5
5
  Home-page: https://github.com/cliops/cliops
6
6
  Author: CliOps Development Team
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cliops
3
- Version: 1.0.0
3
+ Version: 1.0.2
4
4
  Summary: Advanced CLI tool for structured, pattern-based prompt optimization and state management
5
5
  Home-page: https://github.com/cliops/cliops
6
6
  Author: CliOps Development Team
@@ -1,6 +1,8 @@
1
1
  LICENSE
2
2
  MANIFEST.in
3
3
  README.md
4
+ main.py
5
+ presets.py
4
6
  requirements.txt
5
7
  setup.py
6
8
  cliops.egg-info/PKG-INFO
@@ -0,0 +1,3 @@
1
+ core
2
+ main
3
+ presets
cliops-1.0.2/main.py ADDED
@@ -0,0 +1,177 @@
1
+ import argparse
2
+ import sys
3
+ import os
4
+ from rich.console import Console
5
+ from rich.panel import Panel
6
+ from rich.syntax import Syntax
7
+ from rich.text import Text
8
+
9
+ from core.config import Config
10
+ from core.state import CLIState
11
+ from core.patterns import PatternRegistry
12
+ from core.analyzer import PromptAnalyzer
13
+ from core.optimizer import PromptOptimizer
14
+ from presets import suggest_preset_from_prompt, apply_preset_interactive
15
+
16
+ console = Console()
17
+
18
+ def _define_subparsers(subparsers):
19
+ # Optimize command
20
+ optimize_parser = subparsers.add_parser("optimize", aliases=['opt'], help="Optimize a raw prompt using a specified pattern.")
21
+ optimize_parser.add_argument("prompt", type=str, nargs='?', help="The raw prompt string to optimize. If omitted, tries to read from stdin.")
22
+ optimize_parser.add_argument("--pattern", type=str, required=False, help="The name of the optimization pattern to apply.")
23
+ optimize_parser.add_argument("--dry-run", action="store_true", help="Show parsed fields and final template before generation.")
24
+
25
+ # Common override arguments
26
+ optimize_parser.add_argument("--directive", type=str, help="Override the 'DIRECTIVE' field.")
27
+ optimize_parser.add_argument("--scope", type=str, help="Override the 'SCOPE' field.")
28
+ optimize_parser.add_argument("--constraints", type=str, help="Override the 'CONSTRAINTS' field.")
29
+ optimize_parser.add_argument("--output-format", type=str, help="Override the 'OUTPUT FORMAT' field.")
30
+ optimize_parser.add_argument("--success-criteria", type=str, help="Override the 'SUCCESS CRITERIA' field.")
31
+ optimize_parser.add_argument("--code", type=str, help="Override the 'CODE' block content.")
32
+ optimize_parser.add_argument("--context", type=str, help="Override the 'CONTEXT' for context-aware patterns.")
33
+ optimize_parser.add_argument("--current-focus", type=str, help="Override 'CURRENT FOCUS' for context-aware patterns.")
34
+ optimize_parser.add_argument("--mindset", type=str, help="Override 'MINDSET' for context-aware patterns.")
35
+
36
+ # Analyze command
37
+ analyze_parser = subparsers.add_parser("analyze", aliases=['an'], help="Analyze a raw prompt for optimization recommendations.")
38
+ analyze_parser.add_argument("prompt", type=str, nargs='?', help="The raw prompt string to analyze.")
39
+
40
+ # Patterns command
41
+ patterns_parser = subparsers.add_parser("patterns", aliases=['ls'], help="List available optimization patterns.")
42
+ patterns_parser.add_argument("pattern_name", nargs="?", type=str, help="Optional: Name of a specific pattern to get details for.")
43
+
44
+ # State command
45
+ state_parser = subparsers.add_parser("state", help="Manage persistent CLI state.")
46
+ state_subparsers = state_parser.add_subparsers(dest="state_command", help="State commands")
47
+
48
+ state_set_parser = state_subparsers.add_parser("set", help="Set a key-value pair in the CLI state.")
49
+ state_set_parser.add_argument("key", type=str, help="The key for the state variable.")
50
+ state_set_parser.add_argument("value", type=str, help="The value to set.")
51
+
52
+ state_show_parser = state_subparsers.add_parser("show", help="Show the current CLI state.")
53
+ state_clear_parser = state_subparsers.add_parser("clear", help="Clear all entries from the CLI state.")
54
+
55
+ # Init command
56
+ init_parser = subparsers.add_parser("init", help="Initialize CliOps configuration files.")
57
+
58
+ def _run_init_command(cli_state: CLIState, pattern_registry: PatternRegistry):
59
+ """Handles the 'cliops init' command to set up config files."""
60
+ console.print(Panel("[bold green]Initializing CliOps Configuration[/bold green]", expand=False, border_style="green"))
61
+
62
+ state_file = Config.get_state_file_path()
63
+ if not state_file.exists() or cli_state.state == {}:
64
+ state_file.parent.mkdir(parents=True, exist_ok=True)
65
+ cli_state.clear()
66
+ console.print(f"Created/reset CLI state file: [bold cyan]{state_file}[/bold cyan]", style="green")
67
+ else:
68
+ console.print(f"CLI state file already exists at [bold cyan]{state_file}[/bold cyan].", style="dim")
69
+
70
+ console.print(Panel("[bold green]Initialization complete![/bold green]", expand=False, border_style="green"))
71
+
72
+ def main():
73
+ # Create a dummy parser to peek at the arguments
74
+ temp_parser = argparse.ArgumentParser(add_help=False)
75
+ temp_parser.add_argument("first_arg", nargs='?', help=argparse.SUPPRESS)
76
+ temp_parser.add_argument("--verbose", action="store_true", help=argparse.SUPPRESS)
77
+
78
+ temp_args, remaining_argv = temp_parser.parse_known_args(sys.argv[1:])
79
+ verbose_mode = temp_args.verbose
80
+
81
+ known_commands = ["optimize", "opt", "analyze", "an", "patterns", "ls", "state", "init"]
82
+
83
+ # Check if the first argument looks like a prompt
84
+ is_direct_prompt = (temp_args.first_arg and
85
+ temp_args.first_arg not in known_commands and
86
+ not temp_args.first_arg.startswith('-'))
87
+
88
+ if is_direct_prompt:
89
+ new_argv = ["optimize", temp_args.first_arg] + remaining_argv
90
+ sys.argv = [sys.argv[0]] + new_argv
91
+
92
+ # Set up the real parser
93
+ parser = argparse.ArgumentParser(
94
+ description="CliOps: Command Line Interface for Prompt Optimization and State Management (v3.2)",
95
+ formatter_class=argparse.RawTextHelpFormatter
96
+ )
97
+ parser.add_argument("--verbose", action="store_true", help="Enable verbose output for debugging.")
98
+
99
+ subparsers = parser.add_subparsers(dest="command", help="Available commands")
100
+ _define_subparsers(subparsers)
101
+
102
+ args = parser.parse_args()
103
+
104
+ if hasattr(args, 'verbose') and args.verbose:
105
+ verbose_mode = True
106
+
107
+ cli_state = CLIState(Config.get_state_file_path())
108
+ pattern_registry = PatternRegistry(cli_state)
109
+
110
+ # Handle cases where prompt might be piped via stdin
111
+ if hasattr(args, 'prompt') and args.prompt is None and not sys.stdin.isatty():
112
+ args.prompt = sys.stdin.read().strip()
113
+ if not args.prompt:
114
+ console.print("[bold red]Error:[/bold red] No prompt provided via argument or stdin.", style="red")
115
+ sys.exit(1)
116
+ elif hasattr(args, 'prompt') and args.prompt is None and sys.stdin.isatty() and args.command in ["optimize", "analyze"]:
117
+ console.print(f"[bold red]Error:[/bold red] Missing prompt argument for '{args.command}' command.", style="red")
118
+ parser.print_help(sys.stderr)
119
+ sys.exit(1)
120
+
121
+ # Set default pattern if not specified
122
+ if args.command in ["optimize", "opt"] and (not hasattr(args, 'pattern') or args.pattern is None):
123
+ default_pattern = cli_state.get("DEFAULT_PATTERN")
124
+ if default_pattern and pattern_registry.get_pattern(default_pattern):
125
+ args.pattern = default_pattern
126
+ else:
127
+ args.pattern = "context_aware_generation"
128
+
129
+ if args.command in ["optimize", "opt"]:
130
+ overrides = {k: v for k, v in vars(args).items() if v is not None and k not in ['command', 'prompt', 'pattern', 'dry_run', 'verbose']}
131
+
132
+ try:
133
+ optimizer = PromptOptimizer(pattern_registry, cli_state, verbose=verbose_mode)
134
+ optimized_prompt = optimizer.optimize_prompt(args.prompt, args.pattern, overrides, args.dry_run)
135
+
136
+ if not args.dry_run:
137
+ console.print(Panel("[bold green]Optimized Prompt[/bold green]", expand=False, border_style="green"))
138
+ console.print(Syntax(optimized_prompt, "markdown", theme="monokai", line_numbers=True, word_wrap=True))
139
+ console.print(Panel.fit("[dim]Prompt Optimization Complete[/dim]", border_style="dim"))
140
+
141
+ except ValueError as e:
142
+ console.print(f"[bold red]Error:[/bold red] {e}", style="red")
143
+ sys.exit(1)
144
+
145
+ elif args.command in ["analyze", "an"]:
146
+ analyzer = PromptAnalyzer(pattern_registry)
147
+ analyzer.analyze_prompt(args.prompt)
148
+ elif args.command in ["patterns", "ls"]:
149
+ if args.pattern_name:
150
+ pattern = pattern_registry.get_pattern(args.pattern_name)
151
+ if pattern:
152
+ console.print(Panel(f"[bold blue]Pattern Details: {pattern.name}[/bold blue]", expand=False, border_style="blue"))
153
+ console.print(f"[bold]Description:[/bold] {pattern.description}")
154
+ console.print(f"[bold]Principles:[/bold] {', '.join(pattern.principles)}")
155
+ console.print(Panel(
156
+ Syntax(pattern.template, "jinja2", theme="monokai", line_numbers=True, word_wrap=True),
157
+ title="[bold]Template[/bold]", border_style="dim"
158
+ ))
159
+ else:
160
+ console.print(f"[bold red]Error:[/bold red] Pattern '{args.pattern_name}' not found.", style="red")
161
+ pattern_registry.list_patterns()
162
+ else:
163
+ pattern_registry.list_patterns()
164
+ elif args.command == "state":
165
+ if args.state_command == "set":
166
+ cli_state.set(args.key, args.value)
167
+ elif args.state_command == "show":
168
+ cli_state.show()
169
+ elif args.state_command == "clear":
170
+ cli_state.clear()
171
+ elif args.command == "init":
172
+ _run_init_command(cli_state, pattern_registry)
173
+ else:
174
+ parser.print_help()
175
+
176
+ if __name__ == "__main__":
177
+ main()
@@ -0,0 +1,93 @@
1
+ # presets.py
2
+ import json
3
+ import re
4
+ from pathlib import Path
5
+
6
+ BUILTIN_PRESETS = {
7
+ "react-tailwind": {
8
+ "ARCHITECTURE": "React + Tailwind CSS",
9
+ "FOCUS": "UI layout",
10
+ "PATTERNS": "context_aware_generation, state_anchoring",
11
+ "DEFAULT_PATTERN": "context_aware_generation"
12
+ },
13
+ "django-api": {
14
+ "ARCHITECTURE": "Django REST Framework",
15
+ "FOCUS": "API endpoints and serializers",
16
+ "PATTERNS": "bug_fix_precision",
17
+ "DEFAULT_PATTERN": "bug_fix_precision"
18
+ },
19
+ "bash-script": {
20
+ "ARCHITECTURE": "Shell scripting",
21
+ "FOCUS": "Automation and CLI behavior",
22
+ "PATTERNS": "context_aware_generation",
23
+ "DEFAULT_PATTERN": "context_aware_generation"
24
+ }
25
+ }
26
+
27
+ CUSTOM_PRESET_FILE = Path.home() / ".cliops_presets.json"
28
+
29
+ def suggest_preset_from_prompt(prompt: str) -> str | None:
30
+ prompt = prompt.lower()
31
+ if "tailwind" in prompt or "jsx" in prompt:
32
+ return "react-tailwind"
33
+ if "endpoint" in prompt or "serializer" in prompt or "django" in prompt:
34
+ return "django-api"
35
+ if re.search(r'#!/bin/bash|\\.sh|chmod|\\bcron\\b', prompt):
36
+ return "bash-script"
37
+ return None
38
+
39
+ def save_custom_preset(name, preset_dict):
40
+ if CUSTOM_PRESET_FILE.exists():
41
+ with open(CUSTOM_PRESET_FILE, 'r') as f:
42
+ all_presets = json.load(f)
43
+ else:
44
+ all_presets = {}
45
+ all_presets[name] = preset_dict
46
+ with open(CUSTOM_PRESET_FILE, 'w') as f:
47
+ json.dump(all_presets, f, indent=2)
48
+ print(f"✅ Custom preset '{name}' saved.")
49
+
50
+ def apply_preset_interactive(suggested_name, state):
51
+ print(f"\n🤖 Suggested preset based on your prompt: {suggested_name}")
52
+ use = input("Would you like to use this preset? (y/n): ").strip().lower()
53
+ if use != 'y':
54
+ print("❌ Preset declined.")
55
+ return
56
+
57
+ fields = {}
58
+ for key in BUILTIN_PRESETS.get(suggested_name, {}):
59
+ default = BUILTIN_PRESETS[suggested_name][key]
60
+ user_val = input(f"{key} [{default}]: ").strip()
61
+ fields[key] = user_val or default
62
+ state.set(key, fields[key])
63
+
64
+ save = input("Save this as a custom preset? (y/n): ").strip().lower()
65
+ if save == 'y':
66
+ name = input("Enter a name for your preset: ").strip()
67
+ if name:
68
+ save_custom_preset(name, fields)
69
+
70
+ def list_all_presets():
71
+ print("\n📦 Available Presets:")
72
+ for name in BUILTIN_PRESETS:
73
+ print(f" - {name} (built-in)")
74
+ if CUSTOM_PRESET_FILE.exists():
75
+ with open(CUSTOM_PRESET_FILE, 'r') as f:
76
+ custom = json.load(f)
77
+ for name in custom:
78
+ print(f" - {name} (custom)")
79
+
80
+
81
+ def apply_named_preset(name, state):
82
+ preset = BUILTIN_PRESETS.get(name)
83
+ if not preset and CUSTOM_PRESET_FILE.exists():
84
+ with open(CUSTOM_PRESET_FILE, 'r') as f:
85
+ preset = json.load(f).get(name)
86
+
87
+ if not preset:
88
+ print(f"❌ Preset '{name}' not found.")
89
+ return
90
+
91
+ for key, value in preset.items():
92
+ state.set(key, value)
93
+ print(f"✅ Preset '{name}' applied.")
@@ -10,7 +10,7 @@ requirements = (this_directory / "requirements.txt").read_text().strip().split('
10
10
 
11
11
  setup(
12
12
  name='cliops',
13
- version='1.0.0',
13
+ version='1.0.2',
14
14
  author='CliOps Development Team',
15
15
  author_email='contact@cliops.dev',
16
16
  description='Advanced CLI tool for structured, pattern-based prompt optimization and state management',
@@ -23,6 +23,7 @@ setup(
23
23
  'Documentation': 'https://cliops.readthedocs.io',
24
24
  },
25
25
  packages=find_packages(exclude=['tests*']),
26
+ py_modules=['main', 'presets'],
26
27
  include_package_data=True,
27
28
  install_requires=requirements,
28
29
  extras_require={
@@ -1 +0,0 @@
1
- core
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes