@mtayfur/opencode-prompt-enhancer 0.0.6 → 0.0.8
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/README.md +21 -12
- package/package.json +2 -1
- package/plugins/enhancer-system-prompt.ts +29 -0
- package/plugins/prompt-enhancer.tsx +124 -96
package/README.md
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
# opencode-prompt-enhancer
|
|
2
2
|
|
|
3
|
-
OpenCode TUI plugin that rewrites rough prompt drafts into stronger prompts
|
|
3
|
+
OpenCode TUI plugin that rewrites rough prompt drafts into clearer, stronger prompts.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## What it does
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
7
|
+
- Rewrites rough prompt drafts into clearer, stronger prompts.
|
|
8
|
+
- Uses lightweight workspace context.
|
|
9
|
+
- Keeps the original intent and language, and does not read file contents.
|
|
10
|
+
|
|
11
|
+
## Context used
|
|
12
|
+
|
|
13
|
+
The enhancer uses:
|
|
14
|
+
|
|
15
|
+
- the current working directory
|
|
16
|
+
- recent user prompts in the current session
|
|
17
|
+
- files changed in the current session
|
|
9
18
|
|
|
10
19
|
## Install
|
|
11
20
|
|
|
@@ -14,20 +23,20 @@ Add the package to OpenCode's `tui.json` plugin list:
|
|
|
14
23
|
```jsonc
|
|
15
24
|
{
|
|
16
25
|
"plugin": [
|
|
17
|
-
"opencode-prompt-enhancer@latest"
|
|
26
|
+
"@mtayfur/opencode-prompt-enhancer@latest"
|
|
18
27
|
]
|
|
19
28
|
}
|
|
20
29
|
```
|
|
21
30
|
|
|
22
|
-
|
|
31
|
+
OpenCode `>=1.3.14` is required.
|
|
23
32
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
The plugin opens a dialog, rewrites your draft with workspace context, and writes the enhanced prompt back into the current input.
|
|
27
|
-
|
|
28
|
-
## Context
|
|
33
|
+
## Use
|
|
29
34
|
|
|
30
|
-
|
|
35
|
+
1. Open OpenCode in a workspace.
|
|
36
|
+
2. Enter a rough prompt in the TUI prompt.
|
|
37
|
+
3. Press `Ctrl+E` or run `/enhance`.
|
|
38
|
+
4. Review the prefilled dialog, edit it if needed, and confirm.
|
|
39
|
+
5. The enhanced prompt replaces the current input.
|
|
31
40
|
|
|
32
41
|
## Development
|
|
33
42
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mtayfur/opencode-prompt-enhancer",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "OpenCode plugin that rewrites rough drafts into stronger prompts.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@opencode-ai/plugin": "*",
|
|
29
29
|
"@opencode-ai/sdk": "*",
|
|
30
|
+
"@opentui/core": "*",
|
|
30
31
|
"@opentui/solid": "*",
|
|
31
32
|
"solid-js": "*"
|
|
32
33
|
},
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const ENHANCER_SYSTEM_PROMPT = `You are a prompt editor for OpenCode, an AI coding assistant.
|
|
2
|
+
|
|
3
|
+
Goal:
|
|
4
|
+
Clean up the user's draft only when it improves clarity. Preserve intent, scope, priorities, language, and tone. Always fix typos and awkward phrasing; otherwise return the draft unchanged when it is already clear.
|
|
5
|
+
|
|
6
|
+
Capabilities:
|
|
7
|
+
OpenCode can inspect the workspace, edit files, run commands, and verify changes. Respect the user's requested mode: if the draft asks for discussion, planning, or review, keep it that way.
|
|
8
|
+
|
|
9
|
+
Rewrite rules:
|
|
10
|
+
- Preserve the request form. Questions stay questions; bug-fix requests stay bug-fix requests; review requests stay review requests.
|
|
11
|
+
- Preserve the language of the draft. Do not translate.
|
|
12
|
+
- Preserve inline code, file paths, command strings, error messages, identifiers, and quoted phrases verbatim.
|
|
13
|
+
- Preserve explicit constraints, file names, commands, acceptance criteria, and user wording.
|
|
14
|
+
- Use workspace context only when it directly clarifies an ambiguous reference.
|
|
15
|
+
- Resolve vague references like "this" or "that bug" only when context makes them unambiguous.
|
|
16
|
+
- Do not invent details when context is ambiguous.
|
|
17
|
+
- Do not add background, motivation, implementation steps, acceptance criteria, or structure the draft did not imply.
|
|
18
|
+
- Match the draft's structure and tone. Keep prose as prose and lists as lists.
|
|
19
|
+
|
|
20
|
+
Hard constraints:
|
|
21
|
+
- Do not invent requirements, files, APIs, dependencies, bugs, or acceptance criteria.
|
|
22
|
+
- Do not broaden scope with extra features, refactors, tests, or docs.
|
|
23
|
+
- Do not inject assistant-style directives (e.g., "identify root cause", "verify the changed path", "follow local conventions").
|
|
24
|
+
- Do not ask follow-up questions.
|
|
25
|
+
- Do not mention context, tags, instructions, or the rewriting process.
|
|
26
|
+
- Do not output explanations, markdown fences, or commentary.
|
|
27
|
+
|
|
28
|
+
Output:
|
|
29
|
+
Return exactly one enhanced user prompt as plain text.`
|
|
@@ -9,48 +9,13 @@ import type {
|
|
|
9
9
|
TuiRouteCurrent,
|
|
10
10
|
TuiSlotPlugin,
|
|
11
11
|
} from "@opencode-ai/plugin/tui"
|
|
12
|
+
import { ENHANCER_SYSTEM_PROMPT } from "./enhancer-system-prompt"
|
|
12
13
|
|
|
13
14
|
const MAX_RECENT_MESSAGES = 3
|
|
14
15
|
const MAX_CHANGED_FILES = 25
|
|
15
16
|
const MAX_PROMPT_PREVIEW_LENGTH = 250
|
|
16
17
|
const DIALOG_TITLE = "Enhance Prompt"
|
|
17
18
|
const TOAST_TITLE = "Prompt enhancer"
|
|
18
|
-
const TEMP_SESSION_TITLE = "Prompt Enhancer"
|
|
19
|
-
|
|
20
|
-
function makeTempSessionTitle(): string {
|
|
21
|
-
return `${TEMP_SESSION_TITLE} ${Math.random().toString(36).slice(2, 8)}`
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const ENHANCER_SYSTEM_PROMPT = `You are a prompt editor for OpenCode, an AI coding assistant.
|
|
25
|
-
|
|
26
|
-
Goal:
|
|
27
|
-
Rewrite the user's draft into the strongest possible next prompt for OpenCode. Preserve the user's intent, scope, priorities, and language. Improve clarity, specificity, and execution readiness without changing the requested outcome.
|
|
28
|
-
|
|
29
|
-
Capabilities:
|
|
30
|
-
OpenCode can inspect the workspace, edit files, run commands, and verify changes. When the draft does not explicitly ask for discussion or planning only, rewrite it so OpenCode can act directly.
|
|
31
|
-
|
|
32
|
-
Rewrite rules:
|
|
33
|
-
- Preserve the request form. Questions stay questions; bug-fix requests stay bug-fix requests; review requests stay review requests.
|
|
34
|
-
- Preserve the language of the draft. Do not translate.
|
|
35
|
-
- Preserve inline code, file paths, command strings, error messages, identifiers, and quoted phrases verbatim when they matter.
|
|
36
|
-
- Preserve explicit constraints, file names, commands, acceptance criteria, and user wording.
|
|
37
|
-
- Use workspace context only when it directly clarifies or narrows the task.
|
|
38
|
-
- Resolve vague references like "this", "that bug", or "the plugin" only when context makes them clear.
|
|
39
|
-
- Do not invent details when context is ambiguous.
|
|
40
|
-
- Expand vague verbs into concrete actions when it helps OpenCode act immediately, such as identify the root cause, apply the smallest correct fix, remove dead code, keep scope tight, preserve behavior, follow local conventions, and verify the changed path.
|
|
41
|
-
- Keep the rewrite proportional to the draft. Do not add background, motivation, or steps the draft did not imply.
|
|
42
|
-
- Match the draft's structure and tone. Keep prose as prose and lists as lists.
|
|
43
|
-
- If the draft is already precise, make only minimal cleanup.
|
|
44
|
-
|
|
45
|
-
Hard constraints:
|
|
46
|
-
- Do not invent requirements, files, APIs, dependencies, bugs, or acceptance criteria.
|
|
47
|
-
- Do not broaden scope with extra features, refactors, tests, or docs unless the draft implies them.
|
|
48
|
-
- Do not ask follow-up questions.
|
|
49
|
-
- Do not mention context, tags, instructions, or the rewriting process.
|
|
50
|
-
- Do not output explanations, markdown fences, or commentary.
|
|
51
|
-
|
|
52
|
-
Output:
|
|
53
|
-
Return exactly one enhanced user prompt as plain text.`
|
|
54
19
|
|
|
55
20
|
type ModelRef = {
|
|
56
21
|
providerID: string
|
|
@@ -62,6 +27,8 @@ type PluginState = {
|
|
|
62
27
|
enhancing: boolean
|
|
63
28
|
promptRef?: TuiPromptRef
|
|
64
29
|
promptTarget?: PromptTarget
|
|
30
|
+
lastOriginal?: TuiPromptInfo
|
|
31
|
+
lastEnhancedInput?: string
|
|
65
32
|
}
|
|
66
33
|
|
|
67
34
|
type PromptTarget =
|
|
@@ -85,37 +52,20 @@ function parseModelString(value: string | undefined): ModelRef | undefined {
|
|
|
85
52
|
}
|
|
86
53
|
}
|
|
87
54
|
|
|
88
|
-
function getModelOverride(options: PluginOptions | undefined): ModelRef | undefined {
|
|
89
|
-
const value = typeof options?.model === "string" ? options.model : undefined
|
|
90
|
-
return parseModelString(value)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
55
|
function isSessionRoute(route: TuiRouteCurrent): route is Extract<TuiRouteCurrent, { name: "session" }> {
|
|
94
56
|
return route.name === "session"
|
|
95
57
|
}
|
|
96
58
|
|
|
97
|
-
function isUserMessage(message: Message): message is Extract<Message, { role: "user" }> {
|
|
98
|
-
return message.role === "user"
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function isVisibleTextPart(part: Part): part is TextPart {
|
|
102
|
-
return part.type === "text" && !part.ignored
|
|
103
|
-
}
|
|
104
|
-
|
|
105
59
|
function extractVisibleText(parts: ReadonlyArray<Part>): string {
|
|
106
60
|
return parts
|
|
107
|
-
.filter(
|
|
61
|
+
.filter((part): part is TextPart => part.type === "text" && !part.ignored)
|
|
108
62
|
.map((part) => part.text)
|
|
109
63
|
.join("")
|
|
110
64
|
.trim()
|
|
111
65
|
}
|
|
112
66
|
|
|
113
|
-
function truncate(value: string, maxLength: number): string {
|
|
114
|
-
return value.length > maxLength ? `${value.slice(0, maxLength)}...` : value
|
|
115
|
-
}
|
|
116
|
-
|
|
117
67
|
function resolveEnhancerModel(api: Api, options: PluginOptions | undefined): ModelRef | undefined {
|
|
118
|
-
const override =
|
|
68
|
+
const override = typeof options?.model === "string" ? parseModelString(options.model) : undefined
|
|
119
69
|
if (override) return override
|
|
120
70
|
|
|
121
71
|
return parseModelString(api.state.config.small_model || api.state.config.model)
|
|
@@ -148,25 +98,14 @@ function samePromptTarget(left: PromptTarget | undefined, right: PromptTarget |
|
|
|
148
98
|
return false
|
|
149
99
|
}
|
|
150
100
|
|
|
151
|
-
function resolvePromptTarget(route: TuiRouteCurrent, workspaceID?: string): PromptTarget | undefined {
|
|
152
|
-
if (route.name === "home") return { name: "home", workspaceID }
|
|
153
|
-
if (isSessionRoute(route)) {
|
|
154
|
-
return { name: "session", sessionID: route.params.sessionID }
|
|
155
|
-
}
|
|
156
|
-
return undefined
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
function isPromptTargetActive(route: TuiRouteCurrent, target: PromptTarget): boolean {
|
|
160
|
-
if (target.name === "home") return route.name === "home"
|
|
161
|
-
return isSessionRoute(route) && route.params.sessionID === target.sessionID
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
function currentPromptTarget(api: Api, state: PluginState): PromptTarget | undefined {
|
|
165
|
-
return state.promptTarget ?? resolvePromptTarget(api.route.current)
|
|
166
|
-
}
|
|
167
|
-
|
|
168
101
|
function isPromptHandleActive(api: Api, state: PluginState, handle: PromptHandle): boolean {
|
|
169
|
-
|
|
102
|
+
const route = api.route.current
|
|
103
|
+
const target = handle.target
|
|
104
|
+
if (target.name === "home") {
|
|
105
|
+
if (route.name !== "home") return false
|
|
106
|
+
} else if (!isSessionRoute(route) || route.params.sessionID !== target.sessionID) {
|
|
107
|
+
return false
|
|
108
|
+
}
|
|
170
109
|
if (api.state.path.directory !== handle.directory) return false
|
|
171
110
|
|
|
172
111
|
if (handle.ref) {
|
|
@@ -247,7 +186,7 @@ async function restorePrompt(
|
|
|
247
186
|
return true
|
|
248
187
|
}
|
|
249
188
|
|
|
250
|
-
return
|
|
189
|
+
return false
|
|
251
190
|
}
|
|
252
191
|
|
|
253
192
|
function gatherContext(api: Api): string {
|
|
@@ -256,19 +195,24 @@ function gatherContext(api: Api): string {
|
|
|
256
195
|
const dir = api.state.path.directory
|
|
257
196
|
sections.push(`Working directory: ${dir}`)
|
|
258
197
|
|
|
198
|
+
const branch = api.state.vcs?.branch
|
|
199
|
+
if (branch) {
|
|
200
|
+
sections.push(`Current branch: ${branch}`)
|
|
201
|
+
}
|
|
202
|
+
|
|
259
203
|
const route = api.route.current
|
|
260
204
|
if (isSessionRoute(route)) {
|
|
261
205
|
const sessionID = route.params.sessionID
|
|
262
206
|
const messages = api.state.session.messages(sessionID)
|
|
263
207
|
|
|
264
|
-
const userMessages = messages.filter(
|
|
208
|
+
const userMessages = messages.filter((message): message is Extract<Message, { role: "user" }> => message.role === "user")
|
|
265
209
|
const recent = userMessages.slice(-MAX_RECENT_MESSAGES).reverse()
|
|
266
210
|
if (recent.length > 0) {
|
|
267
211
|
const prompts: string[] = []
|
|
268
212
|
for (const msg of recent) {
|
|
269
213
|
const text = extractVisibleText(api.state.part(msg.id))
|
|
270
214
|
if (text) {
|
|
271
|
-
prompts.push(
|
|
215
|
+
prompts.push(text.length > MAX_PROMPT_PREVIEW_LENGTH ? `${text.slice(0, MAX_PROMPT_PREVIEW_LENGTH)}...` : text)
|
|
272
216
|
}
|
|
273
217
|
}
|
|
274
218
|
if (prompts.length > 0) {
|
|
@@ -287,19 +231,6 @@ function gatherContext(api: Api): string {
|
|
|
287
231
|
return sections.join("\n\n")
|
|
288
232
|
}
|
|
289
233
|
|
|
290
|
-
function buildUserMessage(input: string, context: string): string {
|
|
291
|
-
const sections = [
|
|
292
|
-
"Rewrite the following user draft into a stronger prompt.",
|
|
293
|
-
`User draft:\n${input}`,
|
|
294
|
-
]
|
|
295
|
-
|
|
296
|
-
if (context) {
|
|
297
|
-
sections.splice(1, 0, `Workspace context (use only if directly relevant):\n${context}`)
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
return sections.join("\n\n")
|
|
301
|
-
}
|
|
302
|
-
|
|
303
234
|
async function enhanceWithModel(
|
|
304
235
|
api: Api,
|
|
305
236
|
options: PluginOptions | undefined,
|
|
@@ -309,11 +240,18 @@ async function enhanceWithModel(
|
|
|
309
240
|
const directory = api.state.path.directory
|
|
310
241
|
const model = resolveEnhancerModel(api, options)
|
|
311
242
|
const context = gatherContext(api)
|
|
243
|
+
const userMessage = context
|
|
244
|
+
? [
|
|
245
|
+
"Rewrite the following user draft into a stronger prompt.",
|
|
246
|
+
`Workspace context (use only if directly relevant):\n${context}`,
|
|
247
|
+
`User draft:\n${input}`,
|
|
248
|
+
].join("\n\n")
|
|
249
|
+
: ["Rewrite the following user draft into a stronger prompt.", `User draft:\n${input}`].join("\n\n")
|
|
312
250
|
|
|
313
251
|
const created = await api.client.session.create(
|
|
314
252
|
{
|
|
315
253
|
directory,
|
|
316
|
-
title:
|
|
254
|
+
title: `Prompt Enhancer ${Math.random().toString(36).slice(2, 8)}`,
|
|
317
255
|
},
|
|
318
256
|
{ signal, throwOnError: true },
|
|
319
257
|
)
|
|
@@ -331,7 +269,7 @@ async function enhanceWithModel(
|
|
|
331
269
|
parts: [
|
|
332
270
|
{
|
|
333
271
|
type: "text",
|
|
334
|
-
text:
|
|
272
|
+
text: userMessage,
|
|
335
273
|
},
|
|
336
274
|
],
|
|
337
275
|
},
|
|
@@ -366,7 +304,11 @@ function openEnhanceDialog(
|
|
|
366
304
|
|
|
367
305
|
if (signal.aborted) return
|
|
368
306
|
|
|
369
|
-
const target =
|
|
307
|
+
const target = state.promptTarget ?? (api.route.current.name === "home"
|
|
308
|
+
? { name: "home" as const }
|
|
309
|
+
: isSessionRoute(api.route.current)
|
|
310
|
+
? { name: "session" as const, sessionID: api.route.current.params.sessionID }
|
|
311
|
+
: undefined)
|
|
370
312
|
if (!target) {
|
|
371
313
|
api.ui.toast({ variant: "warning", title: TOAST_TITLE, message: "Enhancement only works from a prompt." })
|
|
372
314
|
return
|
|
@@ -406,7 +348,7 @@ function openEnhanceDialog(
|
|
|
406
348
|
variant: "info",
|
|
407
349
|
title: TOAST_TITLE,
|
|
408
350
|
message: "Enhancing prompt...",
|
|
409
|
-
duration:
|
|
351
|
+
duration: 8_000,
|
|
410
352
|
})
|
|
411
353
|
|
|
412
354
|
void (async () => {
|
|
@@ -434,6 +376,9 @@ function openEnhanceDialog(
|
|
|
434
376
|
return
|
|
435
377
|
}
|
|
436
378
|
|
|
379
|
+
state.lastOriginal = originalPrompt
|
|
380
|
+
state.lastEnhancedInput = enhanced
|
|
381
|
+
|
|
437
382
|
api.ui.toast({
|
|
438
383
|
variant: "success",
|
|
439
384
|
title: "Prompt enhanced",
|
|
@@ -462,7 +407,7 @@ function openEnhanceDialog(
|
|
|
462
407
|
const baseMessage = error instanceof Error ? error.message : "Prompt enhancement failed."
|
|
463
408
|
const message = restored
|
|
464
409
|
? baseMessage
|
|
465
|
-
: `${baseMessage} Original prompt could not be restored because the prompt changed.`
|
|
410
|
+
: `${baseMessage} Original prompt could not be restored because the prompt changed. Please re-enter your prompt manually.`
|
|
466
411
|
api.ui.toast({ variant: "error", title: TOAST_TITLE, message })
|
|
467
412
|
} finally {
|
|
468
413
|
state.enhancing = false
|
|
@@ -473,6 +418,72 @@ function openEnhanceDialog(
|
|
|
473
418
|
))
|
|
474
419
|
}
|
|
475
420
|
|
|
421
|
+
function revertEnhancement(
|
|
422
|
+
api: Api,
|
|
423
|
+
state: PluginState,
|
|
424
|
+
signal: AbortSignal,
|
|
425
|
+
): void {
|
|
426
|
+
if (!state.lastOriginal) {
|
|
427
|
+
api.ui.toast({ variant: "warning", title: TOAST_TITLE, message: "No enhancement to revert." })
|
|
428
|
+
return
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const target = state.promptTarget
|
|
432
|
+
if (!target) {
|
|
433
|
+
api.ui.toast({ variant: "warning", title: TOAST_TITLE, message: "Revert only works from a prompt." })
|
|
434
|
+
return
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
const handle: PromptHandle = {
|
|
438
|
+
target,
|
|
439
|
+
directory: api.state.path.directory,
|
|
440
|
+
ref: state.promptRef,
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
if (!isPromptHandleActive(api, state, handle)) {
|
|
444
|
+
api.ui.toast({ variant: "warning", title: TOAST_TITLE, message: "Prompt changed since enhancement." })
|
|
445
|
+
return
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
const currentInput = handle.ref?.current.input ?? ""
|
|
449
|
+
if (currentInput !== state.lastEnhancedInput) {
|
|
450
|
+
api.ui.toast({
|
|
451
|
+
variant: "warning",
|
|
452
|
+
title: TOAST_TITLE,
|
|
453
|
+
message: "Prompt was manually changed after enhancement. Revert skipped.",
|
|
454
|
+
})
|
|
455
|
+
return
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
void (async () => {
|
|
459
|
+
try {
|
|
460
|
+
const wrote = await restorePrompt(api, state, handle, state.lastOriginal!, signal)
|
|
461
|
+
if (!wrote) {
|
|
462
|
+
api.ui.toast({
|
|
463
|
+
variant: "warning",
|
|
464
|
+
title: TOAST_TITLE,
|
|
465
|
+
message: "Prompt changed while reverting.",
|
|
466
|
+
})
|
|
467
|
+
return
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
state.lastOriginal = undefined
|
|
471
|
+
state.lastEnhancedInput = undefined
|
|
472
|
+
|
|
473
|
+
api.ui.toast({
|
|
474
|
+
variant: "success",
|
|
475
|
+
title: TOAST_TITLE,
|
|
476
|
+
message: "Reverted to original prompt.",
|
|
477
|
+
duration: 3000,
|
|
478
|
+
})
|
|
479
|
+
} catch (error) {
|
|
480
|
+
if (signal.aborted) return
|
|
481
|
+
const message = error instanceof Error ? error.message : "Revert failed."
|
|
482
|
+
api.ui.toast({ variant: "error", title: TOAST_TITLE, message })
|
|
483
|
+
}
|
|
484
|
+
})()
|
|
485
|
+
}
|
|
486
|
+
|
|
476
487
|
const tui: TuiPlugin = async (api, options) => {
|
|
477
488
|
const state: PluginState = { enhancing: false }
|
|
478
489
|
|
|
@@ -520,19 +531,36 @@ const tui: TuiPlugin = async (api, options) => {
|
|
|
520
531
|
openEnhanceDialog(api, options, state, api.lifecycle.signal)
|
|
521
532
|
},
|
|
522
533
|
},
|
|
534
|
+
{
|
|
535
|
+
title: "Revert Enhanced Prompt",
|
|
536
|
+
value: "prompt-enhancer.revert",
|
|
537
|
+
description: "Revert last prompt enhancement (Ctrl+Shift+E)",
|
|
538
|
+
category: "Prompt",
|
|
539
|
+
keybind: "ctrl+shift+e",
|
|
540
|
+
slash: {
|
|
541
|
+
name: "revert-enhance",
|
|
542
|
+
aliases: ["revert-enhancement"],
|
|
543
|
+
},
|
|
544
|
+
onSelect: () => {
|
|
545
|
+
revertEnhancement(api, state, api.lifecycle.signal)
|
|
546
|
+
},
|
|
547
|
+
},
|
|
523
548
|
])
|
|
524
549
|
|
|
525
550
|
api.lifecycle.onDispose(() => {
|
|
526
551
|
unregister()
|
|
552
|
+
api.ui.dialog.clear()
|
|
527
553
|
state.enhancing = false
|
|
528
554
|
state.promptRef = undefined
|
|
529
555
|
state.promptTarget = undefined
|
|
556
|
+
state.lastOriginal = undefined
|
|
557
|
+
state.lastEnhancedInput = undefined
|
|
530
558
|
})
|
|
531
559
|
}
|
|
532
560
|
|
|
533
|
-
const plugin
|
|
561
|
+
const plugin = {
|
|
534
562
|
id: "prompt-enhancer",
|
|
535
563
|
tui,
|
|
536
|
-
}
|
|
564
|
+
} satisfies TuiPluginModule & { id: string }
|
|
537
565
|
|
|
538
566
|
export default plugin
|