@mtayfur/opencode-prompt-enhancer 0.0.4 → 0.0.6
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 +1 -1
- package/plugins/prompt-enhancer.tsx +204 -86
package/package.json
CHANGED
|
@@ -7,50 +7,46 @@ import type {
|
|
|
7
7
|
TuiPromptInfo,
|
|
8
8
|
TuiPromptRef,
|
|
9
9
|
TuiRouteCurrent,
|
|
10
|
-
TuiSidebarFileItem,
|
|
11
|
-
TuiSidebarTodoItem,
|
|
12
10
|
TuiSlotPlugin,
|
|
13
11
|
} from "@opencode-ai/plugin/tui"
|
|
14
12
|
|
|
15
|
-
const MAX_RECENT_MESSAGES =
|
|
16
|
-
const MAX_CHANGED_FILES =
|
|
17
|
-
const MAX_PROMPT_PREVIEW_LENGTH =
|
|
18
|
-
const MAX_TODOS = 10
|
|
13
|
+
const MAX_RECENT_MESSAGES = 3
|
|
14
|
+
const MAX_CHANGED_FILES = 25
|
|
15
|
+
const MAX_PROMPT_PREVIEW_LENGTH = 250
|
|
19
16
|
const DIALOG_TITLE = "Enhance Prompt"
|
|
20
17
|
const TOAST_TITLE = "Prompt enhancer"
|
|
21
18
|
const TEMP_SESSION_TITLE = "Prompt Enhancer"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
|
|
20
|
+
function makeTempSessionTitle(): string {
|
|
21
|
+
return `${TEMP_SESSION_TITLE} ${Math.random().toString(36).slice(2, 8)}`
|
|
25
22
|
}
|
|
26
23
|
|
|
27
|
-
const ENHANCER_SYSTEM_PROMPT = `You
|
|
24
|
+
const ENHANCER_SYSTEM_PROMPT = `You are a prompt editor for OpenCode, an AI coding assistant.
|
|
28
25
|
|
|
29
26
|
Goal:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
OpenCode can inspect the workspace,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
- Preserve the
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
-
|
|
40
|
-
-
|
|
41
|
-
-
|
|
42
|
-
-
|
|
43
|
-
-
|
|
44
|
-
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
Do not:
|
|
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:
|
|
50
46
|
- Do not invent requirements, files, APIs, dependencies, bugs, or acceptance criteria.
|
|
51
47
|
- Do not broaden scope with extra features, refactors, tests, or docs unless the draft implies them.
|
|
52
|
-
- Do not ask follow-up questions
|
|
53
|
-
- Do not mention
|
|
48
|
+
- Do not ask follow-up questions.
|
|
49
|
+
- Do not mention context, tags, instructions, or the rewriting process.
|
|
54
50
|
- Do not output explanations, markdown fences, or commentary.
|
|
55
51
|
|
|
56
52
|
Output:
|
|
@@ -65,6 +61,17 @@ type Api = Parameters<TuiPlugin>[0]
|
|
|
65
61
|
type PluginState = {
|
|
66
62
|
enhancing: boolean
|
|
67
63
|
promptRef?: TuiPromptRef
|
|
64
|
+
promptTarget?: PromptTarget
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
type PromptTarget =
|
|
68
|
+
| { name: "home", workspaceID?: string }
|
|
69
|
+
| { name: "session", sessionID: string }
|
|
70
|
+
|
|
71
|
+
type PromptHandle = {
|
|
72
|
+
target: PromptTarget
|
|
73
|
+
directory: string
|
|
74
|
+
ref?: TuiPromptRef
|
|
68
75
|
}
|
|
69
76
|
|
|
70
77
|
function parseModelString(value: string | undefined): ModelRef | undefined {
|
|
@@ -107,10 +114,6 @@ function truncate(value: string, maxLength: number): string {
|
|
|
107
114
|
return value.length > maxLength ? `${value.slice(0, maxLength)}...` : value
|
|
108
115
|
}
|
|
109
116
|
|
|
110
|
-
function formatTodo(todo: TuiSidebarTodoItem): string {
|
|
111
|
-
return ` [${todo.status || "?"}] ${todo.content || "untitled"}`
|
|
112
|
-
}
|
|
113
|
-
|
|
114
117
|
function resolveEnhancerModel(api: Api, options: PluginOptions | undefined): ModelRef | undefined {
|
|
115
118
|
const override = getModelOverride(options)
|
|
116
119
|
if (override) return override
|
|
@@ -134,48 +137,124 @@ function nextPromptInfo(prompt: TuiPromptInfo, input: string): TuiPromptInfo {
|
|
|
134
137
|
}
|
|
135
138
|
}
|
|
136
139
|
|
|
137
|
-
function
|
|
138
|
-
|
|
140
|
+
function samePromptTarget(left: PromptTarget | undefined, right: PromptTarget | undefined): boolean {
|
|
141
|
+
if (!left || !right || left.name !== right.name) return false
|
|
142
|
+
if (left.name === "home" && right.name === "home") {
|
|
143
|
+
return left.workspaceID === right.workspaceID
|
|
144
|
+
}
|
|
145
|
+
if (left.name === "session" && right.name === "session") {
|
|
146
|
+
return left.sessionID === right.sessionID
|
|
147
|
+
}
|
|
148
|
+
return false
|
|
139
149
|
}
|
|
140
150
|
|
|
141
|
-
function
|
|
142
|
-
|
|
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
|
+
function isPromptHandleActive(api: Api, state: PluginState, handle: PromptHandle): boolean {
|
|
169
|
+
if (!isPromptTargetActive(api.route.current, handle.target)) return false
|
|
170
|
+
if (api.state.path.directory !== handle.directory) return false
|
|
171
|
+
|
|
172
|
+
if (handle.ref) {
|
|
173
|
+
return state.promptRef === handle.ref && samePromptTarget(state.promptTarget, handle.target)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
return true
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
function bindPromptRef(
|
|
180
|
+
state: PluginState,
|
|
181
|
+
target: PromptTarget,
|
|
182
|
+
forwarded: ((ref: TuiPromptRef | undefined) => void) | undefined,
|
|
183
|
+
ref: TuiPromptRef | undefined,
|
|
184
|
+
): void {
|
|
185
|
+
if (ref) {
|
|
186
|
+
state.promptRef = ref
|
|
187
|
+
state.promptTarget = target
|
|
188
|
+
} else if (samePromptTarget(state.promptTarget, target)) {
|
|
189
|
+
state.promptRef = undefined
|
|
190
|
+
state.promptTarget = undefined
|
|
191
|
+
}
|
|
192
|
+
|
|
143
193
|
forwarded?.(ref)
|
|
144
194
|
}
|
|
145
195
|
|
|
146
|
-
async function
|
|
147
|
-
|
|
196
|
+
async function clearPrompt(api: Api, state: PluginState, handle: PromptHandle, signal: AbortSignal, template?: TuiPromptInfo): Promise<boolean> {
|
|
197
|
+
if (!isPromptHandleActive(api, state, handle)) return false
|
|
198
|
+
|
|
199
|
+
const promptRef = handle.ref
|
|
200
|
+
if (promptRef) {
|
|
201
|
+
promptRef.set(nextPromptInfo(template ?? promptRef.current, ""))
|
|
202
|
+
return true
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
await api.client.tui.clearPrompt({ directory: handle.directory }, { signal, throwOnError: true } as const)
|
|
206
|
+
return true
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async function writePrompt(
|
|
210
|
+
api: Api,
|
|
211
|
+
state: PluginState,
|
|
212
|
+
handle: PromptHandle,
|
|
213
|
+
input: string,
|
|
214
|
+
signal: AbortSignal,
|
|
215
|
+
template?: TuiPromptInfo,
|
|
216
|
+
): Promise<boolean> {
|
|
217
|
+
if (!isPromptHandleActive(api, state, handle)) return false
|
|
218
|
+
|
|
219
|
+
const promptRef = handle.ref
|
|
148
220
|
if (promptRef) {
|
|
149
221
|
promptRef.set(nextPromptInfo(template ?? promptRef.current, input))
|
|
150
222
|
promptRef.focus()
|
|
151
|
-
return
|
|
223
|
+
return true
|
|
152
224
|
}
|
|
153
225
|
|
|
154
|
-
const directory = api.state.path.directory
|
|
155
226
|
const requestOptions = { signal, throwOnError: true } as const
|
|
156
|
-
await api.client.tui.clearPrompt({ directory }, requestOptions)
|
|
227
|
+
await api.client.tui.clearPrompt({ directory: handle.directory }, requestOptions)
|
|
157
228
|
if (input) {
|
|
158
|
-
await api.client.tui.appendPrompt({ directory, text: input }, requestOptions)
|
|
229
|
+
await api.client.tui.appendPrompt({ directory: handle.directory, text: input }, requestOptions)
|
|
159
230
|
}
|
|
231
|
+
return true
|
|
160
232
|
}
|
|
161
233
|
|
|
162
|
-
async function restorePrompt(
|
|
163
|
-
|
|
234
|
+
async function restorePrompt(
|
|
235
|
+
api: Api,
|
|
236
|
+
state: PluginState,
|
|
237
|
+
handle: PromptHandle,
|
|
238
|
+
prompt: TuiPromptInfo,
|
|
239
|
+
signal: AbortSignal,
|
|
240
|
+
): Promise<boolean> {
|
|
241
|
+
if (!isPromptHandleActive(api, state, handle)) return false
|
|
242
|
+
|
|
243
|
+
const promptRef = handle.ref
|
|
164
244
|
if (promptRef) {
|
|
165
245
|
promptRef.set(clonePromptInfo(prompt))
|
|
166
246
|
promptRef.focus()
|
|
167
|
-
return
|
|
247
|
+
return true
|
|
168
248
|
}
|
|
169
249
|
|
|
170
|
-
|
|
250
|
+
return writePrompt(api, state, handle, prompt.input, signal, prompt)
|
|
171
251
|
}
|
|
172
252
|
|
|
173
253
|
function gatherContext(api: Api): string {
|
|
174
254
|
const sections: string[] = []
|
|
175
255
|
|
|
176
256
|
const dir = api.state.path.directory
|
|
177
|
-
|
|
178
|
-
sections.push(`Working directory: ${dir}${branch ? ` (branch: ${branch})` : ""}`)
|
|
257
|
+
sections.push(`Working directory: ${dir}`)
|
|
179
258
|
|
|
180
259
|
const route = api.route.current
|
|
181
260
|
if (isSessionRoute(route)) {
|
|
@@ -183,7 +262,7 @@ function gatherContext(api: Api): string {
|
|
|
183
262
|
const messages = api.state.session.messages(sessionID)
|
|
184
263
|
|
|
185
264
|
const userMessages = messages.filter(isUserMessage)
|
|
186
|
-
const recent = userMessages.slice(-MAX_RECENT_MESSAGES)
|
|
265
|
+
const recent = userMessages.slice(-MAX_RECENT_MESSAGES).reverse()
|
|
187
266
|
if (recent.length > 0) {
|
|
188
267
|
const prompts: string[] = []
|
|
189
268
|
for (const msg of recent) {
|
|
@@ -193,26 +272,16 @@ function gatherContext(api: Api): string {
|
|
|
193
272
|
}
|
|
194
273
|
}
|
|
195
274
|
if (prompts.length > 0) {
|
|
196
|
-
sections.push(`Recent user prompts in this session (
|
|
275
|
+
sections.push(`Recent user prompts in this session (newest first):\n${prompts.map((p, i) => `${i + 1}. ${p}`).join("\n")}`)
|
|
197
276
|
}
|
|
198
277
|
}
|
|
199
278
|
|
|
200
279
|
const diff = api.state.session.diff(sessionID)
|
|
201
280
|
if (diff.length > 0) {
|
|
202
|
-
const files = diff.slice(0, MAX_CHANGED_FILES).map((f
|
|
203
|
-
|
|
204
|
-
)
|
|
205
|
-
const label = diff.length > MAX_CHANGED_FILES
|
|
206
|
-
? `Files changed in session (showing ${MAX_CHANGED_FILES} of ${diff.length}):`
|
|
207
|
-
: `Files changed in session:`
|
|
208
|
-
sections.push(`${label}\n${files.join("\n")}`)
|
|
281
|
+
const files = diff.slice(0, MAX_CHANGED_FILES).map((f) => ` ${f.file}`)
|
|
282
|
+
sections.push(`Files changed in session:\n${files.join("\n")}`)
|
|
209
283
|
}
|
|
210
284
|
|
|
211
|
-
const todos = api.state.session.todo(sessionID)
|
|
212
|
-
if (todos.length > 0) {
|
|
213
|
-
const todoLines = todos.slice(0, MAX_TODOS).map(formatTodo)
|
|
214
|
-
sections.push(`Active todos:\n${todoLines.join("\n")}`)
|
|
215
|
-
}
|
|
216
285
|
}
|
|
217
286
|
|
|
218
287
|
return sections.join("\n\n")
|
|
@@ -244,13 +313,13 @@ async function enhanceWithModel(
|
|
|
244
313
|
const created = await api.client.session.create(
|
|
245
314
|
{
|
|
246
315
|
directory,
|
|
247
|
-
title:
|
|
316
|
+
title: makeTempSessionTitle(),
|
|
248
317
|
},
|
|
249
318
|
{ signal, throwOnError: true },
|
|
250
319
|
)
|
|
251
320
|
|
|
252
321
|
const tempSessionID = created.data?.id
|
|
253
|
-
if (!tempSessionID) throw new Error("
|
|
322
|
+
if (!tempSessionID) throw new Error("Failed to start prompt enhancer.")
|
|
254
323
|
|
|
255
324
|
try {
|
|
256
325
|
const response = await api.client.session.prompt(
|
|
@@ -270,10 +339,10 @@ async function enhanceWithModel(
|
|
|
270
339
|
)
|
|
271
340
|
|
|
272
341
|
const parts = response.data?.parts
|
|
273
|
-
if (!parts) throw new Error("Enhancer
|
|
342
|
+
if (!parts) throw new Error("Enhancer returned no response.")
|
|
274
343
|
|
|
275
344
|
const enhanced = extractVisibleText(parts)
|
|
276
|
-
if (!enhanced) throw new Error("Enhancer
|
|
345
|
+
if (!enhanced) throw new Error("Enhancer returned no text.")
|
|
277
346
|
return enhanced
|
|
278
347
|
} finally {
|
|
279
348
|
try {
|
|
@@ -291,33 +360,47 @@ function openEnhanceDialog(
|
|
|
291
360
|
signal: AbortSignal,
|
|
292
361
|
): void {
|
|
293
362
|
if (state.enhancing) {
|
|
294
|
-
api.ui.toast({ variant: "warning", title: TOAST_TITLE, message: "Enhancement
|
|
363
|
+
api.ui.toast({ variant: "warning", title: TOAST_TITLE, message: "Enhancement in progress." })
|
|
295
364
|
return
|
|
296
365
|
}
|
|
297
366
|
|
|
298
367
|
if (signal.aborted) return
|
|
299
368
|
|
|
300
|
-
const
|
|
369
|
+
const target = currentPromptTarget(api, state)
|
|
370
|
+
if (!target) {
|
|
371
|
+
api.ui.toast({ variant: "warning", title: TOAST_TITLE, message: "Enhancement only works from a prompt." })
|
|
372
|
+
return
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const handle: PromptHandle = {
|
|
376
|
+
target,
|
|
377
|
+
directory: api.state.path.directory,
|
|
378
|
+
ref: state.promptRef,
|
|
379
|
+
}
|
|
380
|
+
const originalPrompt = handle.ref ? clonePromptInfo(handle.ref.current) : undefined
|
|
381
|
+
const initialValue = originalPrompt?.input ?? ""
|
|
301
382
|
|
|
302
383
|
api.ui.dialog.replace(() => (
|
|
303
384
|
<api.ui.DialogPrompt
|
|
304
385
|
title={DIALOG_TITLE}
|
|
305
|
-
placeholder="Describe
|
|
386
|
+
placeholder="Describe the task..."
|
|
306
387
|
value={initialValue}
|
|
307
388
|
onCancel={() => api.ui.dialog.clear()}
|
|
308
389
|
onConfirm={(value) => {
|
|
309
390
|
const input = value.trim()
|
|
310
391
|
if (!input) {
|
|
311
|
-
api.ui.toast({ variant: "warning", title: TOAST_TITLE, message: "
|
|
392
|
+
api.ui.toast({ variant: "warning", title: TOAST_TITLE, message: "Enter a prompt first." })
|
|
312
393
|
api.ui.dialog.clear()
|
|
313
394
|
return
|
|
314
395
|
}
|
|
315
396
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
397
|
+
if (!isPromptHandleActive(api, state, handle)) {
|
|
398
|
+
api.ui.toast({ variant: "warning", title: TOAST_TITLE, message: "Prompt changed while dialog was open." })
|
|
399
|
+
api.ui.dialog.clear()
|
|
400
|
+
return
|
|
320
401
|
}
|
|
402
|
+
|
|
403
|
+
state.enhancing = true
|
|
321
404
|
api.ui.dialog.clear()
|
|
322
405
|
api.ui.toast({
|
|
323
406
|
variant: "info",
|
|
@@ -328,24 +411,58 @@ function openEnhanceDialog(
|
|
|
328
411
|
|
|
329
412
|
void (async () => {
|
|
330
413
|
try {
|
|
414
|
+
const cleared = await clearPrompt(api, state, handle, signal, originalPrompt)
|
|
415
|
+
if (!cleared) {
|
|
416
|
+
api.ui.toast({
|
|
417
|
+
variant: "warning",
|
|
418
|
+
title: TOAST_TITLE,
|
|
419
|
+
message: "Prompt changed before enhancement started.",
|
|
420
|
+
})
|
|
421
|
+
return
|
|
422
|
+
}
|
|
423
|
+
|
|
331
424
|
const enhanced = await enhanceWithModel(api, options, input, signal)
|
|
332
425
|
if (signal.aborted) return
|
|
333
426
|
|
|
334
|
-
await writePrompt(api, state, enhanced, signal, originalPrompt)
|
|
427
|
+
const wrote = await writePrompt(api, state, handle, enhanced, signal, originalPrompt)
|
|
428
|
+
if (!wrote) {
|
|
429
|
+
api.ui.toast({
|
|
430
|
+
variant: "warning",
|
|
431
|
+
title: TOAST_TITLE,
|
|
432
|
+
message: "Enhanced prompt is ready, but that prompt is no longer active.",
|
|
433
|
+
})
|
|
434
|
+
return
|
|
435
|
+
}
|
|
436
|
+
|
|
335
437
|
api.ui.toast({
|
|
336
438
|
variant: "success",
|
|
337
439
|
title: "Prompt enhanced",
|
|
338
|
-
message: "Enhanced prompt
|
|
440
|
+
message: "Enhanced prompt added to input.",
|
|
339
441
|
duration: 3000,
|
|
340
442
|
})
|
|
341
443
|
} catch (error) {
|
|
342
444
|
if (signal.aborted) return
|
|
343
445
|
|
|
446
|
+
let restored = true
|
|
344
447
|
if (originalPrompt) {
|
|
345
|
-
|
|
448
|
+
try {
|
|
449
|
+
restored = await restorePrompt(api, state, handle, originalPrompt, signal)
|
|
450
|
+
} catch {
|
|
451
|
+
// Best-effort restore; do not suppress the error toast.
|
|
452
|
+
restored = false
|
|
453
|
+
}
|
|
454
|
+
} else {
|
|
455
|
+
try {
|
|
456
|
+
restored = await writePrompt(api, state, handle, input, signal)
|
|
457
|
+
} catch {
|
|
458
|
+
restored = false
|
|
459
|
+
}
|
|
346
460
|
}
|
|
347
461
|
|
|
348
|
-
const
|
|
462
|
+
const baseMessage = error instanceof Error ? error.message : "Prompt enhancement failed."
|
|
463
|
+
const message = restored
|
|
464
|
+
? baseMessage
|
|
465
|
+
: `${baseMessage} Original prompt could not be restored because the prompt changed.`
|
|
349
466
|
api.ui.toast({ variant: "error", title: TOAST_TITLE, message })
|
|
350
467
|
} finally {
|
|
351
468
|
state.enhancing = false
|
|
@@ -364,17 +481,16 @@ const tui: TuiPlugin = async (api, options) => {
|
|
|
364
481
|
home_prompt(_ctx, props) {
|
|
365
482
|
return (
|
|
366
483
|
<api.ui.Prompt
|
|
367
|
-
ref={(ref) => bindPromptRef(state, props.ref, ref)}
|
|
484
|
+
ref={(ref) => bindPromptRef(state, { name: "home", workspaceID: props.workspace_id }, props.ref, ref)}
|
|
368
485
|
workspaceID={props.workspace_id}
|
|
369
486
|
right={<api.ui.Slot name="home_prompt_right" workspace_id={props.workspace_id} />}
|
|
370
|
-
placeholders={HOME_PROMPT_PLACEHOLDERS}
|
|
371
487
|
/>
|
|
372
488
|
)
|
|
373
489
|
},
|
|
374
490
|
session_prompt(_ctx, props) {
|
|
375
491
|
return (
|
|
376
492
|
<api.ui.Prompt
|
|
377
|
-
ref={(ref) => bindPromptRef(state, props.ref, ref)}
|
|
493
|
+
ref={(ref) => bindPromptRef(state, { name: "session", sessionID: props.session_id }, props.ref, ref)}
|
|
378
494
|
sessionID={props.session_id}
|
|
379
495
|
visible={props.visible}
|
|
380
496
|
disabled={props.disabled}
|
|
@@ -392,7 +508,7 @@ const tui: TuiPlugin = async (api, options) => {
|
|
|
392
508
|
{
|
|
393
509
|
title: DIALOG_TITLE,
|
|
394
510
|
value: "prompt-enhancer.enhance",
|
|
395
|
-
description: "Enhance prompt
|
|
511
|
+
description: "Enhance current prompt (Ctrl+E)",
|
|
396
512
|
category: "Prompt",
|
|
397
513
|
keybind: "ctrl+e",
|
|
398
514
|
suggested: true,
|
|
@@ -409,6 +525,8 @@ const tui: TuiPlugin = async (api, options) => {
|
|
|
409
525
|
api.lifecycle.onDispose(() => {
|
|
410
526
|
unregister()
|
|
411
527
|
state.enhancing = false
|
|
528
|
+
state.promptRef = undefined
|
|
529
|
+
state.promptTarget = undefined
|
|
412
530
|
})
|
|
413
531
|
}
|
|
414
532
|
|