abelworkflow 0.1.0 → 0.1.1

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.
@@ -1,12 +1,13 @@
1
1
  #!/usr/bin/env python3
2
- """
3
- Prompt Enhancer Script - Standalone Python script for enhancing prompts.
4
- Can be used with or without an API key.
5
- """
2
+ """Prompt Enhancer CLI."""
6
3
 
7
- import sys
8
4
  import os
9
- import subprocess
5
+ import sys
6
+
7
+ from _dotenv import load_dotenv
8
+
9
+ load_dotenv()
10
+
10
11
 
11
12
  SYSTEM_PROMPT = """
12
13
  You are an expert Prompt Engineer for Coding Agents (Claude Code, Codex, Gemini CLI).
@@ -41,21 +42,34 @@ Output Template:
41
42
  """
42
43
 
43
44
 
45
+ def debug_enabled() -> bool:
46
+ """Return True when debug logging is explicitly enabled."""
47
+ value = os.environ.get("PE_DEBUG", "")
48
+ return value.strip().lower() in {"1", "true", "yes", "on"}
49
+
50
+
51
+ def get_env_or_default(name: str, default: str) -> str:
52
+ """Return default when an env var is missing or blank."""
53
+ value = os.environ.get(name)
54
+ if value is None:
55
+ return default
56
+
57
+ value = value.strip()
58
+ return value or default
59
+
60
+
44
61
  def enhance_with_anthropic(prompt: str, api_key: str) -> str:
45
62
  """Enhance prompt using Anthropic API."""
46
63
  try:
47
64
  import anthropic
48
65
  except ImportError:
49
- print("Installing anthropic package...", file=sys.stderr)
50
- subprocess.run(
51
- [sys.executable, "-m", "pip", "install", "anthropic", "-q"],
52
- check=True
53
- )
54
- import anthropic
55
-
66
+ raise RuntimeError(
67
+ "Missing dependency: anthropic. Install dependencies for the configured provider."
68
+ ) from None
69
+
56
70
  client = anthropic.Anthropic(api_key=api_key)
57
71
  message = client.messages.create(
58
- model=os.environ.get("PE_MODEL", "claude-sonnet-4-20250514"),
72
+ model=get_env_or_default("PE_MODEL", "claude-sonnet-4-20250514"),
59
73
  max_tokens=2048,
60
74
  system=SYSTEM_PROMPT,
61
75
  messages=[{"role": "user", "content": prompt}]
@@ -68,16 +82,13 @@ def enhance_with_openai(prompt: str, api_key: str) -> str:
68
82
  try:
69
83
  import openai
70
84
  except ImportError:
71
- print("Installing openai package...", file=sys.stderr)
72
- subprocess.run(
73
- [sys.executable, "-m", "pip", "install", "openai", "-q"],
74
- check=True
75
- )
76
- import openai
77
-
85
+ raise RuntimeError(
86
+ "Missing dependency: openai. Install dependencies for the configured provider."
87
+ ) from None
88
+
78
89
  client = openai.OpenAI(api_key=api_key)
79
90
  response = client.chat.completions.create(
80
- model=os.environ.get("PE_MODEL", "gpt-4o"),
91
+ model=get_env_or_default("PE_MODEL", "gpt-4o"),
81
92
  messages=[
82
93
  {"role": "system", "content": SYSTEM_PROMPT},
83
94
  {"role": "user", "content": prompt}
@@ -89,54 +100,53 @@ def enhance_with_openai(prompt: str, api_key: str) -> str:
89
100
  def enhance_locally(prompt: str) -> str:
90
101
  """Enhance prompt using local template (no API)."""
91
102
  return f"""# Context
92
- [Analyze the context for: {prompt}]
103
+ [Add only the known repo, file, stack, or runtime context. If unknown, use placeholders like [files], [stack], or [environment].]
93
104
 
94
105
  # Objective
95
106
  {prompt}
96
107
 
97
108
  # Step-by-Step Instructions
98
- 1. First, understand the current state and requirements
99
- 2. Identify the key components involved
100
- 3. Plan the implementation approach
101
- 4. Execute the changes step by step
102
- 5. Verify the results
109
+ 1. Restate the task precisely without changing the user's intent.
110
+ 2. Carry forward every explicit constraint from the original prompt.
111
+ 3. Add only the minimum missing execution context needed to act.
112
+ 4. If important details are unknown, leave placeholders instead of inventing requirements.
113
+ 5. Return the rewritten prompt in this structure.
103
114
 
104
115
  # Constraints
105
- - Follow existing code style and conventions
106
- - Ensure backward compatibility
107
- - Add appropriate error handling
116
+ - Preserve the user's intent and explicit constraints.
117
+ - Do not invent product, compatibility, or implementation requirements.
118
+ - Keep the result concise, specific, and actionable for a coding agent.
108
119
  """
109
120
 
110
121
 
111
122
  def main():
112
123
  if len(sys.argv) < 2:
113
- print("Usage: enhance.py <prompt>", file=sys.stderr)
114
- print("Example: enhance.py 'Write a login component'", file=sys.stderr)
124
+ print("Usage: prompt_enhancer_entry.py <prompt>", file=sys.stderr)
125
+ print("Example: prompt_enhancer_entry.py 'Write a login component'", file=sys.stderr)
126
+ print("Environment: ANTHROPIC_API_KEY | OPENAI_API_KEY | PE_MODEL", file=sys.stderr)
115
127
  sys.exit(1)
116
-
128
+
117
129
  prompt = " ".join(sys.argv[1:])
118
-
130
+
119
131
  # Try Anthropic first, then OpenAI, then local
120
132
  anthropic_key = os.environ.get("ANTHROPIC_API_KEY")
121
133
  openai_key = os.environ.get("OPENAI_API_KEY")
122
-
134
+
123
135
  try:
124
136
  if anthropic_key:
125
137
  result = enhance_with_anthropic(prompt, anthropic_key)
126
138
  elif openai_key:
127
139
  result = enhance_with_openai(prompt, openai_key)
128
140
  else:
129
- # No API key - use local template
130
- print("Note: No API key found, using local template.", file=sys.stderr)
131
141
  result = enhance_locally(prompt)
132
-
142
+
133
143
  print(result)
134
144
  except Exception as e:
135
- print(f"Error: {e}", file=sys.stderr)
136
- print("\nFalling back to local template...", file=sys.stderr)
145
+ if debug_enabled():
146
+ print(f"Error: {e}", file=sys.stderr)
147
+ print("\nFalling back to local template...", file=sys.stderr)
137
148
  print(enhance_locally(prompt))
138
149
 
139
150
 
140
151
  if __name__ == "__main__":
141
152
  main()
142
-
@@ -0,0 +1,212 @@
1
+ #!/usr/bin/env python3
2
+ """Cross-platform bootstrap entrypoint for Prompt Enhancer."""
3
+
4
+ import os
5
+ import re
6
+ import shutil
7
+ import subprocess
8
+ import sys
9
+ from pathlib import Path
10
+ from typing import List, Optional
11
+
12
+ from _dotenv import load_dotenv
13
+
14
+
15
+ ROOT_DIR = Path(__file__).resolve().parent.parent
16
+ REQ_FILE = ROOT_DIR / "requirements.txt"
17
+ CLI_PY = ROOT_DIR / "scripts" / "enhance.py"
18
+
19
+
20
+ def debug_enabled() -> bool:
21
+ value = os.environ.get("PE_DEBUG", "")
22
+ return value.strip().lower() in {"1", "true", "yes", "on"}
23
+
24
+
25
+ def venv_dir() -> Path:
26
+ configured = os.environ.get("PROMPT_ENHANCER_VENV_DIR")
27
+ if not configured:
28
+ return ROOT_DIR / ".venv"
29
+ dir_path = Path(configured).expanduser()
30
+ if dir_path.is_absolute():
31
+ return dir_path
32
+ return ROOT_DIR / dir_path
33
+
34
+
35
+ def venv_python() -> Optional[Path]:
36
+ dir_path = venv_dir()
37
+ candidates = []
38
+ if sys.platform == "win32":
39
+ candidates.extend(
40
+ [
41
+ dir_path / "Scripts" / "python.exe",
42
+ dir_path / "Scripts" / "python",
43
+ ]
44
+ )
45
+ candidates.append(dir_path / "bin" / "python")
46
+ for candidate in candidates:
47
+ if candidate.is_file():
48
+ return candidate
49
+ return None
50
+
51
+
52
+ def python_spec() -> Optional[str]:
53
+ for name in ("PROMPT_ENHANCER_PYTHON", "AGENTS_SKILLS_PYTHON"):
54
+ value = os.environ.get(name)
55
+ if value:
56
+ return value
57
+ return None
58
+
59
+
60
+ def has_uv() -> bool:
61
+ return shutil.which("uv") is not None
62
+
63
+
64
+ def find_system_python() -> Optional[str]:
65
+ env_python = os.environ.get("AGENTS_SKILLS_PYTHON")
66
+ if env_python and Path(env_python).is_file():
67
+ return env_python
68
+ if sys.executable and Path(sys.executable).is_file():
69
+ return sys.executable
70
+ for command in ("python3", "python"):
71
+ found = shutil.which(command)
72
+ if found:
73
+ return found
74
+ return None
75
+
76
+
77
+ def create_venv() -> None:
78
+ dir_path = venv_dir()
79
+ if has_uv():
80
+ command = ["uv", "venv"]
81
+ spec = python_spec()
82
+ if spec:
83
+ command.extend(["--python", spec])
84
+ command.append(str(dir_path))
85
+ subprocess.run(command, check=True)
86
+ return
87
+ python_bin = find_system_python()
88
+ if not python_bin:
89
+ print("Error: No usable uv or python found. Cannot create virtual environment.", file=sys.stderr)
90
+ sys.exit(1)
91
+ subprocess.run([python_bin, "-m", "venv", str(dir_path)], check=True)
92
+
93
+
94
+ def required_modules() -> List[str]:
95
+ modules = []
96
+ if os.environ.get("ANTHROPIC_API_KEY"):
97
+ modules.append("anthropic")
98
+ if os.environ.get("OPENAI_API_KEY"):
99
+ modules.append("openai")
100
+ return modules
101
+
102
+
103
+ def install_targets(modules: List[str]) -> List[str]:
104
+ if not REQ_FILE.is_file():
105
+ return modules
106
+
107
+ requirements = {}
108
+ for raw_line in REQ_FILE.read_text(encoding="utf-8").splitlines():
109
+ line = raw_line.split("#", 1)[0].strip()
110
+ if not line:
111
+ continue
112
+ package = re.split(r"[<>=!~\\[; ]", line, maxsplit=1)[0].strip().lower()
113
+ if package:
114
+ requirements[package] = line
115
+
116
+ return [requirements.get(module.lower(), module) for module in modules]
117
+
118
+
119
+ def has_required_modules(python_bin: str, modules: List[str]) -> bool:
120
+ if not modules:
121
+ return True
122
+ check = subprocess.run(
123
+ [python_bin, "-c", "; ".join(f"import {module}" for module in modules)],
124
+ stdout=subprocess.DEVNULL,
125
+ stderr=subprocess.DEVNULL,
126
+ )
127
+ return check.returncode == 0
128
+
129
+
130
+ def install_deps(python_bin: Path, modules: Optional[List[str]] = None) -> None:
131
+ modules = required_modules() if modules is None else modules
132
+ if not modules:
133
+ return
134
+ targets = install_targets(modules)
135
+ if has_required_modules(str(python_bin), modules):
136
+ return
137
+ try:
138
+ kwargs = {
139
+ "check": True,
140
+ "stdout": subprocess.DEVNULL,
141
+ "stderr": subprocess.PIPE,
142
+ "text": True,
143
+ }
144
+ if has_uv():
145
+ subprocess.run(["uv", "pip", "install", "--python", str(python_bin), *targets], **kwargs)
146
+ return
147
+ subprocess.run([str(python_bin), "-m", "pip", "install", *targets], **kwargs)
148
+ except subprocess.CalledProcessError as exc:
149
+ if debug_enabled():
150
+ details = (exc.stderr or "").strip()
151
+ if details:
152
+ print(details, file=sys.stderr)
153
+ print(
154
+ "Warning: Failed to install prompt enhancer dependencies; continuing with existing environment.",
155
+ file=sys.stderr,
156
+ )
157
+
158
+
159
+ def validate_venv_dir() -> None:
160
+ dir_path = venv_dir()
161
+ if dir_path.exists() and not dir_path.is_dir():
162
+ print(f"Error: {dir_path} exists but is not a directory.", file=sys.stderr)
163
+ sys.exit(1)
164
+ if dir_path.is_dir() and not (dir_path / "pyvenv.cfg").exists() and venv_python() is None:
165
+ print(f"Error: {dir_path} exists but is not a valid venv.", file=sys.stderr)
166
+ sys.exit(1)
167
+
168
+
169
+ def should_passthrough_cli() -> bool:
170
+ return len(sys.argv) < 2
171
+
172
+
173
+ def passthrough_python() -> Optional[str]:
174
+ if sys.executable and Path(sys.executable).is_file():
175
+ return sys.executable
176
+ return find_system_python()
177
+
178
+
179
+ def runtime_python() -> str:
180
+ modules = required_modules()
181
+ current_python = passthrough_python()
182
+ if current_python and has_required_modules(current_python, modules):
183
+ return current_python
184
+
185
+ validate_venv_dir()
186
+ python_bin = venv_python()
187
+ if python_bin is None:
188
+ create_venv()
189
+ python_bin = venv_python()
190
+ if python_bin is None:
191
+ print("Error: Failed to locate python in venv after creation.", file=sys.stderr)
192
+ sys.exit(1)
193
+ install_deps(python_bin, modules)
194
+ return str(python_bin)
195
+
196
+
197
+ def main() -> None:
198
+ if should_passthrough_cli():
199
+ python_bin = passthrough_python()
200
+ if not python_bin:
201
+ print("Error: No usable python found for CLI usage output.", file=sys.stderr)
202
+ sys.exit(1)
203
+ result = subprocess.run([python_bin, str(CLI_PY)] + sys.argv[1:])
204
+ sys.exit(result.returncode)
205
+ load_dotenv()
206
+ python_bin = runtime_python()
207
+ result = subprocess.run([python_bin, str(CLI_PY)] + sys.argv[1:])
208
+ sys.exit(result.returncode)
209
+
210
+
211
+ if __name__ == "__main__":
212
+ main()
@@ -1,4 +0,0 @@
1
- # Context7 API Key Configuration
2
- # Get your API key from: https://context7.com/dashboard
3
-
4
- CONTEXT7_API_KEY=ctx7sk-d4d4d513-e3ae-44ae-b67d-30c046898ecf