abelworkflow 0.6.5 → 0.8.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/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "abelworkflow",
3
- "version": "0.6.5",
3
+ "version": "0.8.0",
4
4
  "description": "Install AbelWorkflow into ~/.agents and create Claude/Codex symlinks.",
5
5
  "type": "module",
6
6
  "scripts": {
7
+ "test": "node --test test/runtime-doc-contracts.test.mjs test/cli-contracts.test.mjs test/codex-config.test.mjs",
7
8
  "test:contracts": "node --test test/runtime-doc-contracts.test.mjs test/cli-contracts.test.mjs"
8
9
  },
9
10
  "bin": {
@@ -22,5 +23,9 @@
22
23
  "engines": {
23
24
  "node": ">=18"
24
25
  },
25
- "license": "MIT"
26
+ "license": "MIT",
27
+ "dependencies": {
28
+ "@clack/prompts": "^1.2.0",
29
+ "picocolors": "^1.1.1"
30
+ }
26
31
  }
@@ -1,124 +1,34 @@
1
1
  ---
2
- name: Confidence Check
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 Skill
6
+ # Confidence Check
7
7
 
8
- ## Purpose
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
- Use this skill BEFORE implementing any task to ensure:
22
- - No duplicate implementations exist
23
- - Architecture compliance verified
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
- ## Implementation Details
16
+ ## Assessment (5 checks)
113
17
 
114
- The TypeScript implementation is available in `confidence.ts` for reference, containing:
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
- - `confidenceCheck(context)` - Main assessment function
117
- - Detailed check implementations
118
- - Context interface definitions
26
+ ## Thresholds
119
27
 
120
- ## ROI
28
+ - **≥90%**: Proceed with implementation
29
+ - **70–89%**: Continue investigation, do not implement yet
30
+ - **<70%**: Stop and request more context
121
31
 
122
- **Token Savings**: Spend 100-200 tokens on confidence check to save 5,000-50,000 tokens on wrong-direction work.
32
+ ## Output
123
33
 
124
- **Success Rate**: 100% precision and recall in production testing.
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, readdirSync } from 'fs';
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-fast
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-fast"] [--extra-sources 3]
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
 
@@ -65,7 +65,7 @@ load_dotenv()
65
65
 
66
66
  class Config:
67
67
  _instance = None
68
- _DEFAULT_MODEL = "grok-4-fast"
68
+ _DEFAULT_MODEL = "grok-4.20-auto"
69
69
 
70
70
  def __new__(cls):
71
71
  if cls._instance is None:
@@ -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: Anthropic API key (preferred when set)
5
- ANTHROPIC_API_KEY=
4
+ # Optional: third-party OpenAI-compatible base URL
5
+ PE_API_URL=
6
6
 
7
- # Optional: OpenAI API key (fallback when Anthropic key is absent)
8
- OPENAI_API_KEY=
7
+ # Optional: third-party OpenAI-compatible API key
8
+ PE_API_KEY=
9
9
 
10
- # Optional: model override
11
- # Examples:
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
- # Basic usage
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
- | `ANTHROPIC_API_KEY` | Anthropic API key for Claude | - |
22
- | `OPENAI_API_KEY` | OpenAI API key (fallback) | - |
23
- | `PE_MODEL` | Model to use | `claude-sonnet-4-20250514` |
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 (No API)
65
+ ## Manual Enhancement (Current Agent)
64
66
 
65
- If no API key is available, you can manually apply the enhancement principles:
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
- ### No API Key
98
- The script will fall back to a local template-based enhancement if no API key is found.
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, provider, or fallback diagnostics on `stderr`.
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 falling back to the local template, use placeholders for unknown context instead of inventing new requirements.
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 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
-
61
- def enhance_with_anthropic(prompt: str, api_key: str) -> str:
62
- """Enhance prompt using Anthropic API."""
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=get_env_or_default("PE_MODEL", "claude-sonnet-4-20250514"),
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 enhance_with_openai(prompt: str, api_key: str) -> str:
81
- """Enhance prompt using OpenAI API."""
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 openai
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
- client = openai.OpenAI(api_key=api_key)
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=get_env_or_default("PE_MODEL", "gpt-4o"),
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.choices[0].message.content
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
- if anthropic_key:
137
- result = enhance_with_anthropic(prompt, anthropic_key)
138
- elif openai_key:
139
- result = enhance_with_openai(prompt, openai_key)
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
- result = enhance_locally(prompt)
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: {e}", file=sys.stderr)
147
- print("\nFalling back to local template...", file=sys.stderr)
148
- print(enhance_locally(prompt))
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__":