@involvex/prompt-enhancer 0.0.2 → 0.0.3
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/dist/components/enhance-prompt.d.ts +1 -1
- package/dist/components/enhance-prompt.js +101 -10
- package/dist/lib/enhancement/engine.d.ts +1 -0
- package/dist/lib/enhancement/engine.js +2 -0
- package/dist/lib/utils/clipboard.d.ts +5 -0
- package/dist/lib/utils/clipboard.js +69 -0
- package/dist/prompt-enhancer.exe +0 -0
- package/package.json +1 -1
- package/readme.md +8 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
interface EnhancePromptProps {
|
|
2
2
|
onBack: () => void;
|
|
3
3
|
}
|
|
4
|
-
export default function EnhancePrompt({ onBack
|
|
4
|
+
export default function EnhancePrompt({ onBack }: EnhancePromptProps): import("react/jsx-runtime").JSX.Element | null;
|
|
5
5
|
export {};
|
|
@@ -2,13 +2,44 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { useState, useEffect } from 'react';
|
|
3
3
|
import { Box, Text } from 'ink';
|
|
4
4
|
import TextInput from 'ink-text-input';
|
|
5
|
+
import SelectInput from './select-input.js';
|
|
5
6
|
import { ConfigManager } from '../lib/config/manager.js';
|
|
6
7
|
import { HistoryManager } from '../lib/history/manager.js';
|
|
7
8
|
import { EnhancementEngine } from '../lib/enhancement/engine.js';
|
|
8
|
-
|
|
9
|
+
import { writeToClipboard } from '../lib/utils/clipboard.js';
|
|
10
|
+
const PROVIDERS = ['gemini', 'copilot', 'kilo', 'opencode'];
|
|
11
|
+
const DEFAULT_SYSTEM_PROMPT = 'You are an expert at enhancing and improving user prompts for LLMs. Analyze the given prompt and return an improved version that is clearer, more specific, and more likely to produce better results. Return ONLY the enhanced prompt, no explanations.';
|
|
12
|
+
const PRESETS = {
|
|
13
|
+
concise: {
|
|
14
|
+
label: 'Make concise',
|
|
15
|
+
instruction: 'Prioritize brevity and remove unnecessary detail while preserving all critical intent.',
|
|
16
|
+
},
|
|
17
|
+
detailed: {
|
|
18
|
+
label: 'Make more detailed',
|
|
19
|
+
instruction: 'Expand the prompt with richer context, constraints, and expected outcomes.',
|
|
20
|
+
},
|
|
21
|
+
structured: {
|
|
22
|
+
label: 'Add structure + output format',
|
|
23
|
+
instruction: 'Restructure the prompt with clear sections and explicit output format instructions.',
|
|
24
|
+
},
|
|
25
|
+
coding: {
|
|
26
|
+
label: 'Improve for coding tasks',
|
|
27
|
+
instruction: 'Optimize for software engineering tasks with explicit technical constraints, edge cases, and validation expectations.',
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
function isProviderType(value) {
|
|
31
|
+
return PROVIDERS.includes(value);
|
|
32
|
+
}
|
|
33
|
+
function createPresetSystemPrompt(presetId) {
|
|
34
|
+
const preset = PRESETS[presetId];
|
|
35
|
+
return `${DEFAULT_SYSTEM_PROMPT}\n\nAdditional enhancement direction:\n${preset.instruction}\n\nKeep your response as ONLY the improved prompt text.`;
|
|
36
|
+
}
|
|
37
|
+
export default function EnhancePrompt({ onBack }) {
|
|
9
38
|
const [state, setState] = useState('input');
|
|
10
39
|
const [prompt, setPrompt] = useState('');
|
|
40
|
+
const [sourcePrompt, setSourcePrompt] = useState('');
|
|
11
41
|
const [enhancedText, setEnhancedText] = useState('');
|
|
42
|
+
const [statusMessage, setStatusMessage] = useState('');
|
|
12
43
|
const [error, setError] = useState('');
|
|
13
44
|
const [defaultProvider, setDefaultProvider] = useState('kilo');
|
|
14
45
|
const [loading, setLoading] = useState(true);
|
|
@@ -18,11 +49,14 @@ export default function EnhancePrompt({ onBack: _onBack }) {
|
|
|
18
49
|
const configManager = new ConfigManager();
|
|
19
50
|
await configManager.load();
|
|
20
51
|
const cfg = configManager.getConfig();
|
|
21
|
-
setDefaultProvider(cfg.defaultProvider
|
|
52
|
+
setDefaultProvider(cfg.defaultProvider && isProviderType(cfg.defaultProvider)
|
|
53
|
+
? cfg.defaultProvider
|
|
54
|
+
: 'kilo');
|
|
22
55
|
setLoading(false);
|
|
23
56
|
}
|
|
24
57
|
catch (_err) {
|
|
25
58
|
setError('Failed to load configuration');
|
|
59
|
+
setState('error');
|
|
26
60
|
setLoading(false);
|
|
27
61
|
}
|
|
28
62
|
})();
|
|
@@ -32,11 +66,14 @@ export default function EnhancePrompt({ onBack: _onBack }) {
|
|
|
32
66
|
setError('Prompt cannot be empty');
|
|
33
67
|
return;
|
|
34
68
|
}
|
|
35
|
-
|
|
36
|
-
void enhancePrompt(defaultProvider);
|
|
69
|
+
void runEnhancement(prompt);
|
|
37
70
|
};
|
|
38
|
-
const
|
|
71
|
+
const runEnhancement = async (inputPrompt, systemPrompt) => {
|
|
39
72
|
setState('enhancing');
|
|
73
|
+
setSourcePrompt(inputPrompt);
|
|
74
|
+
setError('');
|
|
75
|
+
setStatusMessage('');
|
|
76
|
+
setEnhancedText('');
|
|
40
77
|
try {
|
|
41
78
|
const configManager = new ConfigManager();
|
|
42
79
|
await configManager.load();
|
|
@@ -45,8 +82,9 @@ export default function EnhancePrompt({ onBack: _onBack }) {
|
|
|
45
82
|
const engine = new EnhancementEngine(configManager, historyManager);
|
|
46
83
|
let result = '';
|
|
47
84
|
const generator = engine.enhanceStream({
|
|
48
|
-
prompt,
|
|
49
|
-
provider:
|
|
85
|
+
prompt: inputPrompt,
|
|
86
|
+
provider: defaultProvider,
|
|
87
|
+
systemPrompt,
|
|
50
88
|
saveToHistory: true,
|
|
51
89
|
});
|
|
52
90
|
for await (const chunk of generator) {
|
|
@@ -56,6 +94,7 @@ export default function EnhancePrompt({ onBack: _onBack }) {
|
|
|
56
94
|
if (!result.trim()) {
|
|
57
95
|
throw new Error('Enhancement returned an empty result — the model may be rate-limited or temporarily unavailable. Try a different model.');
|
|
58
96
|
}
|
|
97
|
+
setPrompt(result);
|
|
59
98
|
setState('complete');
|
|
60
99
|
}
|
|
61
100
|
catch (err) {
|
|
@@ -63,6 +102,42 @@ export default function EnhancePrompt({ onBack: _onBack }) {
|
|
|
63
102
|
setState('error');
|
|
64
103
|
}
|
|
65
104
|
};
|
|
105
|
+
const handleCompleteActionSelect = (action) => {
|
|
106
|
+
if (action === 'copy') {
|
|
107
|
+
void (async () => {
|
|
108
|
+
const result = await writeToClipboard(enhancedText);
|
|
109
|
+
setStatusMessage(result.success
|
|
110
|
+
? '✓ Enhanced prompt copied to clipboard.'
|
|
111
|
+
: `Copy failed: ${result.message}`);
|
|
112
|
+
})();
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
if (action === 'enhance-further') {
|
|
116
|
+
setStatusMessage('');
|
|
117
|
+
setState('preset-select');
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
onBack();
|
|
121
|
+
};
|
|
122
|
+
const handlePresetSelect = (presetId) => {
|
|
123
|
+
if (presetId === 'back') {
|
|
124
|
+
setState('complete');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
void runEnhancement(enhancedText, createPresetSystemPrompt(presetId));
|
|
128
|
+
};
|
|
129
|
+
const handleErrorActionSelect = (action) => {
|
|
130
|
+
if (action === 'retry') {
|
|
131
|
+
const retryPrompt = sourcePrompt || prompt;
|
|
132
|
+
if (!retryPrompt.trim()) {
|
|
133
|
+
setError('No prompt is available to retry. Return to the main menu and start a new enhancement.');
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
void runEnhancement(retryPrompt);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
onBack();
|
|
140
|
+
};
|
|
66
141
|
if (loading) {
|
|
67
142
|
return (_jsx(Box, { paddingX: 2, children: _jsx(Text, { color: "yellow", children: "Loading configuration..." }) }));
|
|
68
143
|
}
|
|
@@ -70,13 +145,29 @@ export default function EnhancePrompt({ onBack: _onBack }) {
|
|
|
70
145
|
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsx(Text, { bold: true, color: "cyan", children: "Enter prompt to enhance:" }), _jsxs(Box, { marginY: 1, children: [_jsx(Text, { children: "Prompt: " }), _jsx(TextInput, { value: prompt, onChange: setPrompt, onSubmit: handleInputComplete, placeholder: "Type your prompt here..." })] }), error && _jsxs(Text, { color: "red", children: ["Error: ", error] })] }));
|
|
71
146
|
}
|
|
72
147
|
if (state === 'enhancing') {
|
|
73
|
-
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsxs(Text, { bold: true, color: "cyan", children: ["Enhancing with ", defaultProvider, "..."] }), _jsx(Box, { marginY: 1, children: _jsx(Text, { children: enhancedText }) })] }));
|
|
148
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsxs(Text, { bold: true, color: "cyan", children: ["Enhancing with ", defaultProvider, "..."] }), _jsx(Box, { marginY: 1, children: _jsx(Text, { children: enhancedText }) }), _jsx(Text, { color: "gray", children: "Streaming response..." })] }));
|
|
74
149
|
}
|
|
75
150
|
if (state === 'complete') {
|
|
76
|
-
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsx(Text, { bold: true, color: "green", children: "\u2713 Enhancement complete!" }), _jsx(Text, {}), _jsx(Text, { bold: true, children: "
|
|
151
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsx(Text, { bold: true, color: "green", children: "\u2713 Enhancement complete!" }), _jsx(Text, {}), _jsx(Text, { bold: true, children: "Source prompt:" }), _jsx(Text, { children: sourcePrompt }), _jsx(Text, {}), _jsx(Text, { bold: true, children: "Enhanced:" }), _jsx(Text, { children: enhancedText }), _jsx(Text, {}), statusMessage && (_jsx(Text, { color: statusMessage.startsWith('✓') ? 'green' : 'red', children: statusMessage })), _jsx(Box, { marginY: 1, children: _jsx(SelectInput, { items: [
|
|
152
|
+
{ label: 'Copy enhanced prompt to clipboard', value: 'copy' },
|
|
153
|
+
{ label: 'Enhance further', value: 'enhance-further' },
|
|
154
|
+
{ label: 'Return to main menu', value: 'main-menu' },
|
|
155
|
+
], onSelect: item => handleCompleteActionSelect(item.value), initialIndex: 0 }) })] }));
|
|
156
|
+
}
|
|
157
|
+
if (state === 'preset-select') {
|
|
158
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsx(Text, { bold: true, color: "cyan", children: "Enhance further" }), _jsx(Text, { color: "gray", children: "Select how to refine the enhanced prompt:" }), _jsx(Box, { marginY: 1, children: _jsx(SelectInput, { items: [
|
|
159
|
+
{ label: PRESETS.concise.label, value: 'concise' },
|
|
160
|
+
{ label: PRESETS.detailed.label, value: 'detailed' },
|
|
161
|
+
{ label: PRESETS.structured.label, value: 'structured' },
|
|
162
|
+
{ label: PRESETS.coding.label, value: 'coding' },
|
|
163
|
+
{ label: 'Back to actions', value: 'back' },
|
|
164
|
+
], onSelect: item => handlePresetSelect(item.value), initialIndex: 0 }) })] }));
|
|
77
165
|
}
|
|
78
166
|
if (state === 'error') {
|
|
79
|
-
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsx(Text, { bold: true, color: "red", children: "\u2717 Error:" }), _jsx(Text, { color: "red", children: error }), _jsx(Text, {}), _jsx(
|
|
167
|
+
return (_jsxs(Box, { flexDirection: "column", paddingX: 2, children: [_jsx(Text, { bold: true, color: "red", children: "\u2717 Error:" }), _jsx(Text, { color: "red", children: error }), _jsx(Text, {}), _jsx(Box, { marginY: 1, children: _jsx(SelectInput, { items: [
|
|
168
|
+
{ label: 'Retry enhancement', value: 'retry' },
|
|
169
|
+
{ label: 'Return to main menu', value: 'main-menu' },
|
|
170
|
+
], onSelect: item => handleErrorActionSelect(item.value), initialIndex: 0 }) })] }));
|
|
80
171
|
}
|
|
81
172
|
return null;
|
|
82
173
|
}
|
|
@@ -35,6 +35,7 @@ export class EnhancementEngine {
|
|
|
35
35
|
model: request.model || config.defaultModel,
|
|
36
36
|
temperature: request.temperature ?? config.temperature,
|
|
37
37
|
maxTokens: request.maxTokens ?? config.maxTokens,
|
|
38
|
+
systemPrompt: request.systemPrompt,
|
|
38
39
|
};
|
|
39
40
|
// Enhance the prompt
|
|
40
41
|
let enhanced;
|
|
@@ -90,6 +91,7 @@ export class EnhancementEngine {
|
|
|
90
91
|
model: request.model || config.defaultModel,
|
|
91
92
|
temperature: request.temperature ?? config.temperature,
|
|
92
93
|
maxTokens: request.maxTokens ?? config.maxTokens,
|
|
94
|
+
systemPrompt: request.systemPrompt,
|
|
93
95
|
};
|
|
94
96
|
// Stream enhancement
|
|
95
97
|
let enhancedText = '';
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import process from 'node:process';
|
|
3
|
+
function runClipboardCommand(command, args, text) {
|
|
4
|
+
return new Promise((resolve, reject) => {
|
|
5
|
+
const child = spawn(command, args);
|
|
6
|
+
let stderr = '';
|
|
7
|
+
child.on('error', error => {
|
|
8
|
+
reject(error);
|
|
9
|
+
});
|
|
10
|
+
child.stderr.on('data', chunk => {
|
|
11
|
+
stderr += chunk.toString();
|
|
12
|
+
});
|
|
13
|
+
child.on('close', code => {
|
|
14
|
+
if (code === 0) {
|
|
15
|
+
resolve();
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
reject(new Error(stderr.trim() ||
|
|
19
|
+
`Command "${command}" failed with exit code ${code}.`));
|
|
20
|
+
});
|
|
21
|
+
child.stdin.write(text);
|
|
22
|
+
child.stdin.end();
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function getClipboardCommands() {
|
|
26
|
+
switch (process.platform) {
|
|
27
|
+
case 'win32': {
|
|
28
|
+
return [{ command: 'clip', args: [] }];
|
|
29
|
+
}
|
|
30
|
+
case 'darwin': {
|
|
31
|
+
return [{ command: 'pbcopy', args: [] }];
|
|
32
|
+
}
|
|
33
|
+
default: {
|
|
34
|
+
return [
|
|
35
|
+
{ command: 'xclip', args: ['-selection', 'clipboard'] },
|
|
36
|
+
{ command: 'xsel', args: ['--clipboard', '--input'] },
|
|
37
|
+
{ command: 'wl-copy', args: [] },
|
|
38
|
+
];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export async function writeToClipboard(text) {
|
|
43
|
+
if (!text.trim()) {
|
|
44
|
+
return {
|
|
45
|
+
success: false,
|
|
46
|
+
message: 'Cannot copy an empty enhanced prompt.',
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const errors = [];
|
|
50
|
+
const commands = getClipboardCommands();
|
|
51
|
+
for (const clipboardCommand of commands) {
|
|
52
|
+
try {
|
|
53
|
+
await runClipboardCommand(clipboardCommand.command, clipboardCommand.args, text);
|
|
54
|
+
return {
|
|
55
|
+
success: true,
|
|
56
|
+
message: `Copied using ${clipboardCommand.command}.`,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
errors.push(`${clipboardCommand.command}: ${error instanceof Error ? error.message : String(error)}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
success: false,
|
|
65
|
+
message: errors.length > 0
|
|
66
|
+
? errors.join(' | ')
|
|
67
|
+
: 'No clipboard command is available on this system.',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
Binary file
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
- 💾 **Config Management** - Persistent settings at `~/.prompt-enhancer/`
|
|
13
13
|
- 📜 **History Tracking** - Browse past enhancements
|
|
14
14
|
- 🔄 **Streaming Output** - Real-time enhanced prompt display
|
|
15
|
+
- 📋 **Post-Enhancement Actions** - Copy to clipboard, enhance further, or return to main menu
|
|
16
|
+
- 🧠 **Enhance Further Presets** - Make concise, make more detailed, add structure/output format, improve for coding tasks
|
|
15
17
|
- 🎨 **Interactive Settings** - Configure providers via TUI
|
|
16
18
|
|
|
17
19
|
## Install
|
|
@@ -41,6 +43,12 @@ This launches the interactive menu where you can:
|
|
|
41
43
|
- View enhancement history
|
|
42
44
|
- Get help
|
|
43
45
|
|
|
46
|
+
After an enhancement completes in TUI mode, you can:
|
|
47
|
+
|
|
48
|
+
- Copy the enhanced prompt to clipboard
|
|
49
|
+
- Run "Enhance further" with presets
|
|
50
|
+
- Return to the main menu without exiting
|
|
51
|
+
|
|
44
52
|
### CLI Mode - Direct Enhancement
|
|
45
53
|
|
|
46
54
|
```bash
|