prompt-enhancer-cli 1.5.0__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.
@@ -0,0 +1,2 @@
1
+ """Prompt Enhancer — reverse-engineered from Auggie's Ctrl+P."""
2
+ __version__ = "1.5.0"
@@ -0,0 +1,205 @@
1
+ """
2
+ Agent backends for prompt-enhancer — delegate enhancement to existing coding agents.
3
+
4
+ Each backend takes a seed prompt and returns an enhanced version by shelling out
5
+ to the agent's CLI. No API key needed — uses the agent's existing configuration.
6
+
7
+ Supported agents:
8
+ claude — Claude Code (claude -p)
9
+ codex — Codex CLI (codex)
10
+ auggie — Auggie (auggie --print)
11
+ opencode — OpenCode (opencode --print)
12
+ """
13
+
14
+ import subprocess
15
+ import sys
16
+ import os
17
+ from pathlib import Path
18
+
19
+
20
+ ENHANCEMENT_PROMPT_TEMPLATE = """Transform this rough idea into a 7-section system prompt for AI coding agents.
21
+
22
+ SECTIONS: ROLE → CONTEXT → BEHAVIORAL RULES → TECHNICAL GUIDELINES → OUTPUT FORMAT → PITFALLS/GUARDRAILS → EXAMPLES
23
+
24
+ RULES:
25
+ - Be concrete — reference actual tools, patterns, conventions
26
+ - Be actionable — rules translate directly into agent behavior
27
+ - Be concise — 2-4 bullets per section
28
+ - Include a "pro tip" at the end
29
+ - Output ONLY the system prompt markdown, start with "# System Prompt: <Role>"
30
+
31
+ ## Rough idea
32
+ {seed}
33
+
34
+ ## Output
35
+ # System Prompt:"""
36
+
37
+
38
+ def _find_binary(names):
39
+ """Find the first available binary from a list of names."""
40
+ for name in names:
41
+ # Check common locations
42
+ for prefix in ["", str(Path.home() / ".local/bin/"), str(Path.home() / ".nvm/versions/node/v26.1.0/bin/")]:
43
+ path = os.path.join(prefix, name)
44
+ if os.path.exists(path) and os.access(path, os.X_OK):
45
+ return path
46
+ # Try which
47
+ try:
48
+ result = subprocess.run(["which", name], capture_output=True, text=True, timeout=5)
49
+ if result.returncode == 0:
50
+ return result.stdout.strip()
51
+ except Exception:
52
+ pass
53
+ return None
54
+
55
+
56
+ def enhance_via_claude(seed, config=None):
57
+ """Enhance via Claude Code."""
58
+ binary = _find_binary(["claude"])
59
+ if not binary:
60
+ raise RuntimeError("Claude Code not found. Install: npm install -g @anthropic-ai/claude-code")
61
+
62
+ prompt = ENHANCEMENT_PROMPT_TEMPLATE.format(seed=seed)
63
+ result = subprocess.run(
64
+ [binary, "-p", prompt],
65
+ capture_output=True, text=True, timeout=120,
66
+ env={**os.environ, "CLAUDE_CODE_HEADLESS": "1"}
67
+ )
68
+ if result.returncode != 0:
69
+ raise RuntimeError(f"Claude Code failed: {result.stderr[:200]}")
70
+ return result.stdout.strip()
71
+
72
+
73
+ def enhance_via_codex(seed, config=None):
74
+ """Enhance via Codex CLI."""
75
+ binary = _find_binary(["codex"])
76
+ if not binary:
77
+ raise RuntimeError("Codex not found. Install: npm install -g @openai/codex")
78
+
79
+ prompt = ENHANCEMENT_PROMPT_TEMPLATE.format(seed=seed)
80
+ result = subprocess.run(
81
+ [binary, prompt],
82
+ capture_output=True, text=True, timeout=120,
83
+ env={**os.environ}
84
+ )
85
+ if result.returncode != 0:
86
+ raise RuntimeError(f"Codex failed: {result.stderr[:200]}")
87
+ return result.stdout.strip()
88
+
89
+
90
+ def enhance_via_auggie(seed, config=None):
91
+ """Enhance via Auggie (Augment)."""
92
+ binary = _find_binary(["auggie"])
93
+ if not binary:
94
+ raise RuntimeError("Auggie not found. Install: npm install -g @augmentcode/auggie")
95
+
96
+ prompt = ENHANCEMENT_PROMPT_TEMPLATE.format(seed=seed)
97
+ result = subprocess.run(
98
+ [binary, "--print", prompt],
99
+ capture_output=True, text=True, timeout=120,
100
+ env={**os.environ}
101
+ )
102
+ if result.returncode != 0:
103
+ raise RuntimeError(f"Auggie failed: {result.stderr[:200]}")
104
+
105
+ output = result.stdout.strip()
106
+ # Strip Auggie's thinking/exploration prefix
107
+ if "🤖" in output:
108
+ output = output.split("🤖")[-1].strip()
109
+ # Strip ANSI escape codes
110
+ import re
111
+ output = re.sub(r'\x1b\[[0-9;]*[a-zA-Z]', '', output)
112
+ return output
113
+
114
+
115
+ def enhance_via_opencode(seed, config=None):
116
+ """Enhance via OpenCode."""
117
+ binary = _find_binary(["opencode"])
118
+ if not binary:
119
+ raise RuntimeError("OpenCode not found.")
120
+
121
+ prompt = ENHANCEMENT_PROMPT_TEMPLATE.format(seed=seed)
122
+ result = subprocess.run(
123
+ [binary, "--print", prompt],
124
+ capture_output=True, text=True, timeout=120,
125
+ env={**os.environ}
126
+ )
127
+ if result.returncode != 0:
128
+ raise RuntimeError(f"OpenCode failed: {result.stderr[:200]}")
129
+ return result.stdout.strip()
130
+
131
+
132
+ # Map agent names to enhancers
133
+ AGENT_ENHANCERS = {
134
+ "claude": enhance_via_claude,
135
+ "codex": enhance_via_codex,
136
+ "auggie": enhance_via_auggie,
137
+ "opencode": enhance_via_opencode,
138
+ }
139
+
140
+
141
+ # Invocation recipes for running an arbitrary prompt through an agent CLI.
142
+ # Used by the blind-judge path so the benchmark judge can differ from the generator.
143
+ AGENT_INVOKERS = {
144
+ "claude": {"binary": "claude", "args": ["-p"], "env": {"CLAUDE_CODE_HEADLESS": "1"}},
145
+ "codex": {"binary": "codex", "args": [], "env": {}},
146
+ "auggie": {"binary": "auggie", "args": ["--print"], "env": {}},
147
+ "opencode": {"binary": "opencode", "args": ["--print"], "env": {}},
148
+ }
149
+
150
+
151
+ def run_via_agent(prompt, via_agent, timeout=180):
152
+ """Run a raw prompt through an agent CLI and return its stdout.
153
+
154
+ Unlike enhance_via_*, this passes the prompt verbatim — no enhancement
155
+ template wrapping. Used for blind judging in `pe benchmark --judge-via`.
156
+ """
157
+ recipe = AGENT_INVOKERS.get(via_agent)
158
+ if not recipe:
159
+ raise RuntimeError(f"Unknown agent: {via_agent}. Supported: {', '.join(AGENT_INVOKERS.keys())}")
160
+ binary = _find_binary([recipe["binary"]])
161
+ if not binary:
162
+ raise RuntimeError(f"{via_agent} not found on PATH")
163
+ result = subprocess.run(
164
+ [binary, *recipe["args"], prompt],
165
+ capture_output=True, text=True, timeout=timeout,
166
+ env={**os.environ, **recipe["env"]},
167
+ )
168
+ if result.returncode != 0:
169
+ raise RuntimeError(f"{via_agent} failed: {result.stderr[:200]}")
170
+ output = result.stdout.strip()
171
+ if via_agent == "auggie":
172
+ if "🤖" in output:
173
+ output = output.split("🤖")[-1].strip()
174
+ import re
175
+ output = re.sub(r'\x1b\[[0-9;]*[a-zA-Z]', '', output)
176
+ return output
177
+
178
+
179
+ def enhance(seed, via_agent=None, config=None):
180
+ """Enhance a seed prompt. If via_agent is set, delegate to that agent.
181
+ Otherwise, use the API key (legacy path).
182
+ """
183
+ if via_agent:
184
+ enhancer = AGENT_ENHANCERS.get(via_agent)
185
+ if not enhancer:
186
+ raise RuntimeError(f"Unknown agent: {via_agent}. Supported: {', '.join(AGENT_ENHANCERS.keys())}")
187
+ return enhancer(seed, config)
188
+
189
+ # Fall through to API-key mode — caller must handle
190
+ raise RuntimeError("No enhancement method available. Use --via <agent> or set LLM_API_KEY.")
191
+
192
+
193
+ def get_available_agents():
194
+ """Return list of agents with available binaries."""
195
+ available = []
196
+ for agent, enhancer in AGENT_ENHANCERS.items():
197
+ try:
198
+ binary = _find_binary([agent])
199
+ if binary:
200
+ available.append((agent, binary, "ready"))
201
+ else:
202
+ available.append((agent, None, "not found"))
203
+ except Exception:
204
+ available.append((agent, None, "error"))
205
+ return available