abelworkflow 0.6.5 → 0.7.0
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.
- package/.gitignore +1 -1
- package/README.md +1 -1
- package/lib/cli/logic.mjs +99 -41
- package/lib/cli.mjs +314 -274
- package/package.json +6 -2
- package/skills/confidence-check/SKILL.md +20 -110
- package/skills/confidence-check/confidence.ts +1 -60
- package/skills/grok-search/.env.example +3 -3
- package/skills/grok-search/SKILL.md +1 -1
- package/skills/grok-search/scripts/groksearch_cli.py +1 -1
- package/skills/prompt-enhancer/.env.example +6 -8
- package/skills/prompt-enhancer/ADVANCED.md +14 -12
- package/skills/prompt-enhancer/SKILL.md +5 -1
- package/skills/prompt-enhancer/scripts/enhance.py +115 -76
- package/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py +47 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "abelworkflow",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Install AbelWorkflow into ~/.agents and create Claude/Codex symlinks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -22,5 +22,9 @@
|
|
|
22
22
|
"engines": {
|
|
23
23
|
"node": ">=18"
|
|
24
24
|
},
|
|
25
|
-
"license": "MIT"
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@clack/prompts": "^1.2.0",
|
|
28
|
+
"picocolors": "^1.1.1"
|
|
29
|
+
}
|
|
26
30
|
}
|
|
@@ -1,124 +1,34 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: confidence-check
|
|
3
3
|
description: Pre-implementation confidence assessment (≥90% required). Use before starting any implementation to verify readiness with duplicate check, architecture compliance, official docs verification, OSS references, and root cause identification.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Confidence Check
|
|
6
|
+
# Confidence Check
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Prevents wrong-direction execution by assessing confidence **BEFORE** starting implementation.
|
|
11
|
-
|
|
12
|
-
**Requirement**: ≥90% confidence to proceed with implementation.
|
|
13
|
-
|
|
14
|
-
**Test Results** (2025-10-21):
|
|
15
|
-
- Precision: 1.000 (no false positives)
|
|
16
|
-
- Recall: 1.000 (no false negatives)
|
|
17
|
-
- 8/8 test cases passed
|
|
8
|
+
Run this BEFORE implementing to prevent wrong-direction work. Requires ≥90% confidence to proceed.
|
|
18
9
|
|
|
19
10
|
## When to Use
|
|
20
11
|
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
- Official documentation reviewed
|
|
25
|
-
- Working OSS implementations found
|
|
26
|
-
- Root cause properly identified
|
|
27
|
-
|
|
28
|
-
## Confidence Assessment Criteria
|
|
29
|
-
|
|
30
|
-
Calculate confidence score (0.0 - 1.0) based on 5 checks:
|
|
31
|
-
|
|
32
|
-
### 1. No Duplicate Implementations? (25%)
|
|
33
|
-
|
|
34
|
-
**Check**: Search codebase for existing functionality
|
|
35
|
-
|
|
36
|
-
```bash
|
|
37
|
-
# Use Grep to search for similar functions
|
|
38
|
-
# Use Glob to find related modules
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
✅ Pass if no duplicates found
|
|
42
|
-
❌ Fail if similar implementation exists
|
|
43
|
-
|
|
44
|
-
### 2. Architecture Compliance? (25%)
|
|
45
|
-
|
|
46
|
-
**Check**: Verify tech stack alignment
|
|
47
|
-
|
|
48
|
-
- Read `CLAUDE.md`, `AGENTS.md`, `PLANNING.md`
|
|
49
|
-
- Confirm existing patterns used
|
|
50
|
-
- Avoid reinventing existing solutions
|
|
51
|
-
|
|
52
|
-
✅ Pass if uses existing tech stack (e.g., Supabase, UV, pytest)
|
|
53
|
-
❌ Fail if introduces new dependencies unnecessarily
|
|
54
|
-
|
|
55
|
-
### 3. Official Documentation Verified? (20%)
|
|
56
|
-
|
|
57
|
-
**Check**: Review official docs before implementation
|
|
58
|
-
|
|
59
|
-
- Use Context7 MCP for official docs
|
|
60
|
-
- Use WebFetch for documentation URLs
|
|
61
|
-
- Verify API compatibility
|
|
62
|
-
|
|
63
|
-
✅ Pass if official docs reviewed
|
|
64
|
-
❌ Fail if relying on assumptions
|
|
65
|
-
|
|
66
|
-
### 4. Working OSS Implementations Referenced? (15%)
|
|
67
|
-
|
|
68
|
-
**Check**: Find proven implementations
|
|
69
|
-
|
|
70
|
-
- Use Tavily MCP or WebSearch
|
|
71
|
-
- Search GitHub for examples
|
|
72
|
-
- Verify working code samples
|
|
73
|
-
|
|
74
|
-
✅ Pass if OSS reference found
|
|
75
|
-
❌ Fail if no working examples
|
|
76
|
-
|
|
77
|
-
### 5. Root Cause Identified? (15%)
|
|
78
|
-
|
|
79
|
-
**Check**: Understand the actual problem
|
|
80
|
-
|
|
81
|
-
- Analyze error messages
|
|
82
|
-
- Check logs and stack traces
|
|
83
|
-
- Identify underlying issue
|
|
84
|
-
|
|
85
|
-
✅ Pass if root cause clear
|
|
86
|
-
❌ Fail if symptoms unclear
|
|
87
|
-
|
|
88
|
-
## Confidence Score Calculation
|
|
89
|
-
|
|
90
|
-
```
|
|
91
|
-
Total = Check1 (25%) + Check2 (25%) + Check3 (20%) + Check4 (15%) + Check5 (15%)
|
|
92
|
-
|
|
93
|
-
If Total >= 0.90: ✅ Proceed with implementation
|
|
94
|
-
If Total >= 0.70: ⚠️ Present alternatives, ask questions
|
|
95
|
-
If Total < 0.70: ❌ STOP - Request more context
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
## Output Format
|
|
99
|
-
|
|
100
|
-
```
|
|
101
|
-
📋 Confidence Checks:
|
|
102
|
-
✅ No duplicate implementations found
|
|
103
|
-
✅ Uses existing tech stack
|
|
104
|
-
✅ Official documentation verified
|
|
105
|
-
✅ Working OSS implementation found
|
|
106
|
-
✅ Root cause identified
|
|
107
|
-
|
|
108
|
-
📊 Confidence: 1.00 (100%)
|
|
109
|
-
✅ High confidence - Proceeding to implementation
|
|
110
|
-
```
|
|
12
|
+
- Before writing or modifying any implementation code
|
|
13
|
+
- Before applying a fix to verify root cause
|
|
14
|
+
- When user asks to "check confidence" or "assess readiness"
|
|
111
15
|
|
|
112
|
-
##
|
|
16
|
+
## Assessment (5 checks)
|
|
113
17
|
|
|
114
|
-
|
|
18
|
+
| Check | Weight | How |
|
|
19
|
+
|---|---|---|
|
|
20
|
+
| No duplicate implementations | 25% | Grep/Glob for similar code |
|
|
21
|
+
| Architecture compliance | 25% | Read CLAUDE.md / AGENTS.md |
|
|
22
|
+
| Official docs verified | 20% | Context7 or WebFetch |
|
|
23
|
+
| OSS reference found | 15% | WebSearch / GitHub |
|
|
24
|
+
| Root cause identified | 15% | Analyze errors and logs |
|
|
115
25
|
|
|
116
|
-
|
|
117
|
-
- Detailed check implementations
|
|
118
|
-
- Context interface definitions
|
|
26
|
+
## Thresholds
|
|
119
27
|
|
|
120
|
-
|
|
28
|
+
- **≥90%**: Proceed with implementation
|
|
29
|
+
- **70–89%**: Continue investigation, do not implement yet
|
|
30
|
+
- **<70%**: Stop and request more context
|
|
121
31
|
|
|
122
|
-
|
|
32
|
+
## Output
|
|
123
33
|
|
|
124
|
-
|
|
34
|
+
Print the checklist with pass/fail markers, the total score, and the recommended action.
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* - Low (<70%): Investigation incomplete, unclear root cause, missing official docs
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
import { existsSync
|
|
21
|
+
import { existsSync } from 'fs';
|
|
22
22
|
import { join, dirname } from 'path';
|
|
23
23
|
|
|
24
24
|
export interface Context {
|
|
@@ -238,65 +238,6 @@ export class ConfidenceChecker {
|
|
|
238
238
|
return context.root_cause_identified ?? false;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
/**
|
|
242
|
-
* Check if existing patterns can be followed
|
|
243
|
-
*
|
|
244
|
-
* Looks for:
|
|
245
|
-
* - Similar test files
|
|
246
|
-
* - Common naming conventions
|
|
247
|
-
* - Established directory structure
|
|
248
|
-
*/
|
|
249
|
-
private hasExistingPatterns(context: Context): boolean {
|
|
250
|
-
const testFile = context.test_file;
|
|
251
|
-
if (!testFile) {
|
|
252
|
-
return false;
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
const testDir = dirname(testFile);
|
|
256
|
-
|
|
257
|
-
// Check for other test files in same directory
|
|
258
|
-
if (existsSync(testDir)) {
|
|
259
|
-
try {
|
|
260
|
-
const files = readdirSync(testDir);
|
|
261
|
-
const testFiles = files.filter(f =>
|
|
262
|
-
f.startsWith('test_') && f.endsWith('.py')
|
|
263
|
-
);
|
|
264
|
-
return testFiles.length > 1;
|
|
265
|
-
} catch {
|
|
266
|
-
return false;
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
return false;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Check if implementation path is clear
|
|
275
|
-
*
|
|
276
|
-
* Considers:
|
|
277
|
-
* - Test name suggests clear purpose
|
|
278
|
-
* - Markers indicate test type
|
|
279
|
-
* - Context has sufficient information
|
|
280
|
-
*/
|
|
281
|
-
private hasClearPath(context: Context): boolean {
|
|
282
|
-
// Check test name clarity
|
|
283
|
-
const testName = context.test_name ?? '';
|
|
284
|
-
if (!testName || testName === 'test_example') {
|
|
285
|
-
return false;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// Check for markers indicating test type
|
|
289
|
-
const markers = context.markers ?? [];
|
|
290
|
-
const knownMarkers = new Set([
|
|
291
|
-
'unit', 'integration', 'hallucination',
|
|
292
|
-
'performance', 'confidence_check', 'self_check'
|
|
293
|
-
]);
|
|
294
|
-
|
|
295
|
-
const hasMarkers = markers.some(m => knownMarkers.has(m));
|
|
296
|
-
|
|
297
|
-
return hasMarkers || testName.length > 10;
|
|
298
|
-
}
|
|
299
|
-
|
|
300
241
|
/**
|
|
301
242
|
* Get recommended action based on confidence level
|
|
302
243
|
*
|
|
@@ -6,9 +6,9 @@ GROK_API_URL=
|
|
|
6
6
|
# 必填项:你的 API 密钥
|
|
7
7
|
GROK_API_KEY=
|
|
8
8
|
|
|
9
|
-
# 可选项:使用的 Grok 模型(默认:grok-4-
|
|
10
|
-
# 常用选项:grok-4-fast
|
|
11
|
-
GROK_MODEL=
|
|
9
|
+
# 可选项:使用的 Grok 模型(默认:grok-4.20-auto)
|
|
10
|
+
# 常用选项:grok-4.20-auto, grok-4-fast
|
|
11
|
+
GROK_MODEL=grok-4.20-auto
|
|
12
12
|
|
|
13
13
|
# 可选项:启用调试模式(true/false)
|
|
14
14
|
GROK_DEBUG=false
|
|
@@ -24,7 +24,7 @@ Use this skill for web search, webpage retrieval, and current-information lookup
|
|
|
24
24
|
```bash
|
|
25
25
|
cp "<SKILL_DIR>/.env.example" "<SKILL_DIR>/.env"
|
|
26
26
|
|
|
27
|
-
python "<SKILL_DIR>/scripts/groksearch_entry.py" web_search --query "search terms" [--platform "GitHub"] [--min-results 3] [--max-results 10] [--model "grok-4-
|
|
27
|
+
python "<SKILL_DIR>/scripts/groksearch_entry.py" web_search --query "search terms" [--platform "GitHub"] [--min-results 3] [--max-results 10] [--model "grok-4.20-auto"] [--extra-sources 3]
|
|
28
28
|
|
|
29
29
|
python "<SKILL_DIR>/scripts/groksearch_entry.py" web_fetch --url "https://..." [--out file.md] [--fallback-grok]
|
|
30
30
|
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
# Prompt Enhancer CLI configuration
|
|
2
2
|
# Copy this file to .env and fill in the values you want to use.
|
|
3
3
|
|
|
4
|
-
# Optional:
|
|
5
|
-
|
|
4
|
+
# Optional: third-party OpenAI-compatible base URL
|
|
5
|
+
PE_API_URL=
|
|
6
6
|
|
|
7
|
-
# Optional: OpenAI API key
|
|
8
|
-
|
|
7
|
+
# Optional: third-party OpenAI-compatible API key
|
|
8
|
+
PE_API_KEY=
|
|
9
9
|
|
|
10
|
-
# Optional: model
|
|
11
|
-
#
|
|
12
|
-
# claude-sonnet-4-20250514
|
|
13
|
-
# gpt-4o
|
|
10
|
+
# Optional: model name for the third-party endpoint
|
|
11
|
+
# Leave all three fields blank to use the current agent directly.
|
|
14
12
|
PE_MODEL=
|
|
@@ -5,22 +5,20 @@
|
|
|
5
5
|
Use the bootstrap entrypoint from the installed skill directory:
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
#
|
|
8
|
+
# Assuming third-party config is already set in <SKILL_DIR>/.env or the environment
|
|
9
9
|
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "your prompt here"
|
|
10
|
-
|
|
11
|
-
# With custom model
|
|
12
|
-
PE_MODEL=claude-sonnet-4-20250514 python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "your prompt"
|
|
13
10
|
```
|
|
14
11
|
|
|
15
12
|
`prompt_enhancer_entry.py` is the canonical entrypoint. It creates or reuses a skill-local virtual environment and then runs `scripts/enhance.py`.
|
|
13
|
+
If `PE_API_URL`, `PE_API_KEY`, and `PE_MODEL` are not all present, do not call the script; rewrite the prompt directly with the current agent instead.
|
|
16
14
|
|
|
17
15
|
## Environment Variables
|
|
18
16
|
|
|
19
17
|
| Variable | Description | Default |
|
|
20
18
|
|----------|-------------|---------|
|
|
21
|
-
| `
|
|
22
|
-
| `
|
|
23
|
-
| `PE_MODEL` | Model to use |
|
|
19
|
+
| `PE_API_URL` | Third-party OpenAI-compatible base URL | - |
|
|
20
|
+
| `PE_API_KEY` | Third-party OpenAI-compatible API key | - |
|
|
21
|
+
| `PE_MODEL` | Model to use on the third-party endpoint | - |
|
|
24
22
|
| `PE_DEBUG` | Print bootstrap and fallback diagnostics to `stderr` | `0` |
|
|
25
23
|
| `PROMPT_ENHANCER_VENV_DIR` | Override the skill-local venv path | `skills/prompt-enhancer/.venv` |
|
|
26
24
|
| `PROMPT_ENHANCER_PYTHON` | Python version/spec for `uv venv --python` | - |
|
|
@@ -41,6 +39,8 @@ The enhanced prompt is written to `stdout`. Usage or debug diagnostics stay on `
|
|
|
41
39
|
|
|
42
40
|
### Piping Output
|
|
43
41
|
|
|
42
|
+
Assuming `PE_API_URL`, `PE_API_KEY`, and `PE_MODEL` are already configured:
|
|
43
|
+
|
|
44
44
|
```bash
|
|
45
45
|
# Pipe to clipboard (macOS)
|
|
46
46
|
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "my prompt" | pbcopy
|
|
@@ -54,15 +54,17 @@ python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "my prompt" | claude -p
|
|
|
54
54
|
|
|
55
55
|
### In Shell Scripts
|
|
56
56
|
|
|
57
|
+
Assuming the environment is already configured:
|
|
58
|
+
|
|
57
59
|
```bash
|
|
58
60
|
#!/bin/bash
|
|
59
61
|
ENHANCED=$(python "$HOME/.agents/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py" "$1")
|
|
60
62
|
echo "$ENHANCED"
|
|
61
63
|
```
|
|
62
64
|
|
|
63
|
-
## Manual Enhancement (
|
|
65
|
+
## Manual Enhancement (Current Agent)
|
|
64
66
|
|
|
65
|
-
If
|
|
67
|
+
If the user does not provide `url`, `apiKey`, and `model`, use the current agent directly and apply the enhancement principles:
|
|
66
68
|
|
|
67
69
|
1. Read the user's prompt
|
|
68
70
|
2. Apply the template from [TEMPLATE.md](TEMPLATE.md)
|
|
@@ -94,8 +96,8 @@ Run the entrypoint without a prompt to print usage information:
|
|
|
94
96
|
python "$HOME/.agents/skills/prompt-enhancer/scripts/prompt_enhancer_entry.py"
|
|
95
97
|
```
|
|
96
98
|
|
|
97
|
-
###
|
|
98
|
-
The script
|
|
99
|
+
### Missing Third-Party Config
|
|
100
|
+
The script requires `PE_API_URL`, `PE_API_KEY`, and `PE_MODEL`. If any field is missing, skip the script and use the current agent directly.
|
|
99
101
|
|
|
100
102
|
### Debug Fallbacks
|
|
101
|
-
Set `PE_DEBUG=1` to show dependency-install
|
|
103
|
+
Set `PE_DEBUG=1` to show dependency-install or configuration diagnostics on `stderr`.
|
|
@@ -19,12 +19,16 @@ Do not use this for general writing edits like email, docs, or PR copy.
|
|
|
19
19
|
|
|
20
20
|
## Do
|
|
21
21
|
|
|
22
|
+
- Default path: rewrite the prompt directly with the current agent using the structure from [TEMPLATE.md](TEMPLATE.md).
|
|
23
|
+
- Third-party path: use the Python entrypoint only when the user explicitly provides `url`, `apiKey`, and `model`, or when all three are already configured in `<SKILL_DIR>/.env`.
|
|
24
|
+
|
|
22
25
|
```bash
|
|
23
26
|
python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "user's raw prompt here"
|
|
24
27
|
```
|
|
25
28
|
|
|
26
29
|
- Do not call `scripts/enhance.py` directly.
|
|
27
30
|
- Use the installed skill directory for `<SKILL_DIR>`.
|
|
31
|
+
- If any of `url`, `apiKey`, or `model` is missing, do not invoke the script. Use the current agent directly instead.
|
|
28
32
|
- Optional setup: `cp "<SKILL_DIR>/.env.example" "<SKILL_DIR>/.env"`
|
|
29
33
|
|
|
30
34
|
## Output
|
|
@@ -33,7 +37,7 @@ python "<SKILL_DIR>/scripts/prompt_enhancer_entry.py" "user's raw prompt here"
|
|
|
33
37
|
- Keep `stderr` for usage or optional debug output only.
|
|
34
38
|
- Preserve the user's intent and explicit constraints.
|
|
35
39
|
- Add structure and missing execution context only when it helps the agent act.
|
|
36
|
-
- When
|
|
40
|
+
- When running directly in the current agent, use placeholders for unknown context instead of inventing new requirements.
|
|
37
41
|
|
|
38
42
|
## Notes
|
|
39
43
|
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
-
"""Prompt Enhancer CLI."""
|
|
2
|
+
"""Prompt Enhancer CLI for OpenAI-compatible endpoints."""
|
|
3
3
|
|
|
4
|
+
import argparse
|
|
4
5
|
import os
|
|
5
6
|
import sys
|
|
7
|
+
from typing import Tuple
|
|
6
8
|
|
|
7
9
|
from _dotenv import load_dotenv
|
|
8
10
|
|
|
@@ -42,110 +44,147 @@ Output Template:
|
|
|
42
44
|
"""
|
|
43
45
|
|
|
44
46
|
|
|
47
|
+
def parse_args() -> argparse.Namespace:
|
|
48
|
+
parser = argparse.ArgumentParser(
|
|
49
|
+
prog="prompt_enhancer_entry.py",
|
|
50
|
+
description="Enhance a prompt through a third-party OpenAI-compatible API.",
|
|
51
|
+
)
|
|
52
|
+
parser.add_argument("--url", dest="api_url", help="Third-party OpenAI-compatible base URL.")
|
|
53
|
+
parser.add_argument("--api-key", dest="api_key", help="Third-party OpenAI-compatible API key.")
|
|
54
|
+
parser.add_argument("--model", help="Model name on the third-party endpoint.")
|
|
55
|
+
parser.add_argument("--prompt", help="Prompt text to enhance.")
|
|
56
|
+
parser.add_argument("prompt_parts", nargs="*", help=argparse.SUPPRESS)
|
|
57
|
+
return parser.parse_args()
|
|
58
|
+
|
|
59
|
+
|
|
45
60
|
def debug_enabled() -> bool:
|
|
46
|
-
"""Return True when debug logging is explicitly enabled."""
|
|
47
61
|
value = os.environ.get("PE_DEBUG", "")
|
|
48
62
|
return value.strip().lower() in {"1", "true", "yes", "on"}
|
|
49
63
|
|
|
50
64
|
|
|
51
|
-
def
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
def
|
|
62
|
-
|
|
65
|
+
def resolve_prompt(args: argparse.Namespace) -> str:
|
|
66
|
+
prompt = args.prompt.strip() if args.prompt else ""
|
|
67
|
+
if prompt:
|
|
68
|
+
return prompt
|
|
69
|
+
joined = " ".join(args.prompt_parts).strip()
|
|
70
|
+
if joined:
|
|
71
|
+
return joined
|
|
72
|
+
raise ValueError("Missing prompt. Pass --prompt \"...\" or a positional prompt.")
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def first_non_empty(*values: str) -> str:
|
|
76
|
+
for value in values:
|
|
77
|
+
stripped = value.strip()
|
|
78
|
+
if stripped:
|
|
79
|
+
return stripped
|
|
80
|
+
return ""
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def env_value(*names: str) -> str:
|
|
84
|
+
return first_non_empty(*(os.environ.get(name, "") for name in names))
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def resolve_config(args: argparse.Namespace) -> Tuple[str, str, str, str]:
|
|
88
|
+
api_url = (args.api_url or os.environ.get("PE_API_URL", "")).strip()
|
|
89
|
+
api_key = (args.api_key or os.environ.get("PE_API_KEY", "")).strip()
|
|
90
|
+
model = (args.model or os.environ.get("PE_MODEL", "")).strip()
|
|
91
|
+
|
|
92
|
+
missing = []
|
|
93
|
+
if not api_url:
|
|
94
|
+
missing.append("url")
|
|
95
|
+
if not api_key:
|
|
96
|
+
missing.append("apiKey")
|
|
97
|
+
if not model:
|
|
98
|
+
missing.append("model")
|
|
99
|
+
if missing:
|
|
100
|
+
has_openai_compatible_transport = bool(api_url or api_key)
|
|
101
|
+
if has_openai_compatible_transport:
|
|
102
|
+
raise ValueError(
|
|
103
|
+
"Missing third-party OpenAI-compatible config: "
|
|
104
|
+
+ ", ".join(missing)
|
|
105
|
+
+ ". If these fields are unavailable, use the current agent directly."
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
legacy_anthropic_key = env_value("ANTHROPIC_API_KEY")
|
|
109
|
+
if legacy_anthropic_key:
|
|
110
|
+
return "anthropic", "", legacy_anthropic_key, first_non_empty(model, "claude-sonnet-4-20250514")
|
|
111
|
+
|
|
112
|
+
legacy_openai_key = env_value("OPENAI_API_KEY")
|
|
113
|
+
if legacy_openai_key:
|
|
114
|
+
return "openai", "", legacy_openai_key, first_non_empty(model, "gpt-4o")
|
|
115
|
+
|
|
116
|
+
raise ValueError(
|
|
117
|
+
"Missing third-party OpenAI-compatible config: "
|
|
118
|
+
+ ", ".join(missing)
|
|
119
|
+
+ ". If these fields are unavailable, use the current agent directly."
|
|
120
|
+
)
|
|
121
|
+
return "openai-compatible", api_url, api_key, model
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def enhance_with_anthropic(prompt: str, api_key: str, model: str) -> str:
|
|
63
125
|
try:
|
|
64
126
|
import anthropic
|
|
65
127
|
except ImportError:
|
|
66
|
-
raise RuntimeError(
|
|
67
|
-
"Missing dependency: anthropic. Install dependencies for the configured provider."
|
|
68
|
-
) from None
|
|
128
|
+
raise RuntimeError("Missing dependency: anthropic. Install dependencies for the configured provider.") from None
|
|
69
129
|
|
|
70
130
|
client = anthropic.Anthropic(api_key=api_key)
|
|
71
131
|
message = client.messages.create(
|
|
72
|
-
model=
|
|
132
|
+
model=model,
|
|
73
133
|
max_tokens=2048,
|
|
74
134
|
system=SYSTEM_PROMPT,
|
|
75
|
-
messages=[{"role": "user", "content": prompt}]
|
|
135
|
+
messages=[{"role": "user", "content": prompt}],
|
|
76
136
|
)
|
|
77
137
|
return message.content[0].text
|
|
78
138
|
|
|
79
139
|
|
|
80
|
-
def
|
|
81
|
-
|
|
140
|
+
def _extract_response_text(response) -> str:
|
|
141
|
+
content = response.choices[0].message.content
|
|
142
|
+
if isinstance(content, str):
|
|
143
|
+
return content
|
|
144
|
+
if content is None:
|
|
145
|
+
raise RuntimeError("The provider returned an empty response.")
|
|
146
|
+
return str(content)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def enhance_with_openai(prompt: str, api_key: str, model: str, api_url: str = "") -> str:
|
|
82
150
|
try:
|
|
83
|
-
import
|
|
151
|
+
from openai import OpenAI
|
|
84
152
|
except ImportError:
|
|
85
|
-
raise RuntimeError(
|
|
86
|
-
"Missing dependency: openai. Install dependencies for the configured provider."
|
|
87
|
-
) from None
|
|
153
|
+
raise RuntimeError("Missing dependency: openai. Install dependencies for the configured provider.") from None
|
|
88
154
|
|
|
89
|
-
|
|
155
|
+
kwargs = {"api_key": api_key}
|
|
156
|
+
if api_url:
|
|
157
|
+
kwargs["base_url"] = api_url
|
|
158
|
+
client = OpenAI(**kwargs)
|
|
90
159
|
response = client.chat.completions.create(
|
|
91
|
-
model=
|
|
160
|
+
model=model,
|
|
92
161
|
messages=[
|
|
93
162
|
{"role": "system", "content": SYSTEM_PROMPT},
|
|
94
|
-
{"role": "user", "content": prompt}
|
|
95
|
-
]
|
|
163
|
+
{"role": "user", "content": prompt},
|
|
164
|
+
],
|
|
96
165
|
)
|
|
97
|
-
return response
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def enhance_locally(prompt: str) -> str:
|
|
101
|
-
"""Enhance prompt using local template (no API)."""
|
|
102
|
-
return f"""# Context
|
|
103
|
-
[Add only the known repo, file, stack, or runtime context. If unknown, use placeholders like [files], [stack], or [environment].]
|
|
104
|
-
|
|
105
|
-
# Objective
|
|
106
|
-
{prompt}
|
|
166
|
+
return _extract_response_text(response)
|
|
107
167
|
|
|
108
|
-
# Step-by-Step Instructions
|
|
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.
|
|
114
|
-
|
|
115
|
-
# Constraints
|
|
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.
|
|
119
|
-
"""
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def main():
|
|
123
|
-
if len(sys.argv) < 2:
|
|
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)
|
|
127
|
-
sys.exit(1)
|
|
128
|
-
|
|
129
|
-
prompt = " ".join(sys.argv[1:])
|
|
130
|
-
|
|
131
|
-
# Try Anthropic first, then OpenAI, then local
|
|
132
|
-
anthropic_key = os.environ.get("ANTHROPIC_API_KEY")
|
|
133
|
-
openai_key = os.environ.get("OPENAI_API_KEY")
|
|
134
168
|
|
|
169
|
+
def main() -> None:
|
|
135
170
|
try:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
171
|
+
args = parse_args()
|
|
172
|
+
prompt = resolve_prompt(args)
|
|
173
|
+
provider, api_url, api_key, model = resolve_config(args)
|
|
174
|
+
if provider == "anthropic":
|
|
175
|
+
print(enhance_with_anthropic(prompt, api_key, model))
|
|
140
176
|
else:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
print(result)
|
|
144
|
-
except Exception as e:
|
|
177
|
+
print(enhance_with_openai(prompt, api_key, model, api_url))
|
|
178
|
+
except Exception as exc:
|
|
145
179
|
if debug_enabled():
|
|
146
|
-
print(f"Error: {
|
|
147
|
-
|
|
148
|
-
|
|
180
|
+
print(f"Error: {exc}", file=sys.stderr)
|
|
181
|
+
else:
|
|
182
|
+
msg = str(exc)
|
|
183
|
+
if "Missing third-party OpenAI-compatible config" in msg:
|
|
184
|
+
print("Missing API configuration. Use the current agent directly instead, or set PE_API_URL, PE_API_KEY, PE_MODEL.", file=sys.stderr)
|
|
185
|
+
else:
|
|
186
|
+
print(msg, file=sys.stderr)
|
|
187
|
+
sys.exit(1)
|
|
149
188
|
|
|
150
189
|
|
|
151
190
|
if __name__ == "__main__":
|