Skip to content

Commit d3f8fc1

Browse files
committed
Refactor symbol handling logic and introduce PromptTemplate component to support symbol insertion in preset prefix and suffix fields
- Create a special component for prefix/suffix textareas in the `apps/editor/src/views/panel/frontend/components/edit-preset-form/EditPresetForm/EditPresetForm.tsx`. It should have "insert symbol" button just like `packages/ui/src/components/editor/panel/PromptField/PromptField.tsx`. When the button is clicked, log to the console 'insert button clicked'. - TemplateTextarea should be a separate UI component - in UiTemplateTextarea add prop for [Fragment] - handle "insert symbol click" with the `apps/editor/src/views/panel/backend/message-handlers/handle-hash-sign-quick-pick/handle-hash-sign-quick-pick.ts` - move `packages/ui/src/components/editor/common/TemplateTextarea/TemplateTextarea.tsx` to `packages/ui/src/components/editor/panel` - from prompt field, extract handling of symbols to `packages/ui/src/components/editor/panel/prompt-symbols` and use it in 'template textarea' - rename `packages/ui/src/components/editor/panel/prompt` to `packages/ui/src/components/editor/panel/prompts` - [Pasted text] - place PromptField and TemplateTextarea in `packages/ui/src/components/editor/panel/prompts` - `TemplateTextarea` rename to `PromptTemplate` - in the prompt template, trigger[Fragment] on '#' typed in the field
1 parent eec2074 commit d3f8fc1

29 files changed

Lines changed: 1352 additions & 1024 deletions

‎apps/editor/src/views/panel/backend/message-handlers/handle-hash-sign-quick-pick/handle-hash-sign-quick-pick.ts‎

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,8 @@ const hash_sign_quick_pick = async (params: {
158158
export const handle_hash_sign_quick_pick = async (
159159
panel_provider: PanelProvider,
160160
context: vscode.ExtensionContext,
161-
is_for_code_completions: boolean
161+
is_for_code_completions: boolean,
162+
target?: 'prompt-field' | 'preset-prefix' | 'preset-suffix'
162163
): Promise<void> => {
163164
const is_prune_context =
164165
(panel_provider.mode == MODE.WEB &&
@@ -173,24 +174,34 @@ export const handle_hash_sign_quick_pick = async (
173174
})
174175

175176
if (!replacement) {
176-
panel_provider.send_message({
177-
command: 'FOCUS_PROMPT_FIELD'
178-
})
177+
if (!target || target == 'prompt-field') {
178+
panel_provider.send_message({
179+
command: 'FOCUS_PROMPT_FIELD'
180+
})
181+
}
179182
return
180183
}
181184

182-
const current_text = panel_provider.current_instruction
183-
184-
const is_after_hash_sign = current_text
185-
.slice(0, panel_provider.caret_position)
186-
.endsWith('#')
187-
if (is_after_hash_sign) {
188-
panel_provider.add_text_at_cursor_position(replacement, 1)
185+
if (target == 'preset-prefix' || target == 'preset-suffix') {
186+
panel_provider.send_message({
187+
command: 'INSERT_SYMBOL_AT_CURSOR',
188+
text: replacement,
189+
target
190+
})
189191
} else {
190-
panel_provider.add_text_at_cursor_position(replacement)
191-
}
192+
const current_text = panel_provider.current_instruction
193+
194+
const is_after_hash_sign = current_text
195+
.slice(0, panel_provider.caret_position)
196+
.endsWith('#')
197+
if (is_after_hash_sign) {
198+
panel_provider.add_text_at_cursor_position(replacement, 1)
199+
} else {
200+
panel_provider.add_text_at_cursor_position(replacement)
201+
}
192202

193-
panel_provider.send_message({
194-
command: 'FOCUS_PROMPT_FIELD'
195-
})
203+
panel_provider.send_message({
204+
command: 'FOCUS_PROMPT_FIELD'
205+
})
206+
}
196207
}

‎apps/editor/src/views/panel/backend/panel-provider.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -858,7 +858,8 @@ export class PanelProvider implements vscode.WebviewViewProvider {
858858
await handle_hash_sign_quick_pick(
859859
this,
860860
this.context,
861-
message.is_for_code_completions
861+
message.is_for_code_completions,
862+
message.target
862863
)
863864
} else if (message.command == 'GO_TO_FILE') {
864865
handle_go_to_file(message)

‎apps/editor/src/views/panel/frontend/Main/MainView/MainView.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import styles from './MainView.module.scss'
22
import { Configurations as UiConfigurations } from '@ui/components/editor/panel/Configurations'
33
import { Presets as UiPresets } from '@ui/components/editor/panel/Presets'
4-
import { PromptField as UiPromptField } from '@ui/components/editor/panel/PromptField'
4+
import { PromptField as UiPromptField } from '@ui/components/editor/panel/prompts/PromptField'
55
import { Separator as UiSeparator } from '@ui/components/editor/panel/Separator'
66
import { Preset } from '@shared/types/preset'
77
import { Responses as UiResponses } from '@ui/components/editor/panel/Responses'

‎apps/editor/src/views/panel/frontend/Panel.tsx‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,13 @@ export const Panel = () => {
529529
<EditPresetForm
530530
preset={updating_preset}
531531
on_update={set_updated_preset}
532+
on_insert_symbol_click={(target) => {
533+
post_message(vscode, {
534+
command: 'SHOW_HASH_SIGN_QUICK_PICK',
535+
is_for_code_completions: false,
536+
target
537+
})
538+
}}
532539
pick_model={(chatbot_name, current_model_id) => {
533540
post_message(vscode, {
534541
command: 'PICK_MODEL',
@@ -546,7 +553,6 @@ export const Panel = () => {
546553
current_effort
547554
})
548555
}}
549-
on_at_sign_in_affix={() => {}}
550556
/>
551557
</UiPage>
552558
</div>

‎apps/editor/src/views/panel/frontend/components/edit-preset-form/EditPresetForm/EditPresetForm.tsx‎

Lines changed: 50 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ import { Field as UiField } from '@ui/components/editor/panel/Field'
88
import { Slider as UiSlider } from '@ui/components/editor/panel/Slider'
99
import { Input as UiInput } from '@ui/components/editor/common/Input'
1010
import { Textarea as UiTextarea } from '@ui/components/editor/common/Textarea'
11+
import {
12+
PromptTemplate as UiPromptTemplate,
13+
PromptTemplateHandle
14+
} from '@ui/components/editor/panel/prompts/PromptTemplate'
1115
import { BackendMessage } from '@/views/panel/types/messages'
1216
import { PresetOption as UiPresetOption } from '@ui/components/editor/panel/PresetOption'
1317
import { Scrollable as UiScrollable } from '@ui/components/editor/panel/Scrollable'
@@ -22,7 +26,7 @@ type Props = {
2226
supported_efforts: string[],
2327
current_effort?: string
2428
) => void
25-
on_at_sign_in_affix: () => void
29+
on_insert_symbol_click: (target: 'preset-prefix' | 'preset-suffix') => void
2630
}
2731

2832
/**
@@ -31,8 +35,8 @@ type Props = {
3135
* - add additional prefix and suffix to each preset below it.
3236
*/
3337
export const EditPresetForm: React.FC<Props> = (props) => {
34-
const prefix_ref = useRef<HTMLTextAreaElement>(null)
35-
const suffix_ref = useRef<HTMLTextAreaElement>(null)
38+
const prefix_ref = useRef<PromptTemplateHandle>(null)
39+
const suffix_ref = useRef<PromptTemplateHandle>(null)
3640

3741
const [chatbot, set_chatbot] = useState(props.preset.chatbot)
3842
const [name, set_name] = useState(props.preset.name)
@@ -192,23 +196,43 @@ export const EditPresetForm: React.FC<Props> = (props) => {
192196
handle_chatbot_change(message.chatbot_id as keyof typeof CHATBOTS)
193197
} else if (message.command == 'NEWLY_PICKED_REASONING_EFFORT') {
194198
set_reasoning_effort(message.effort)
199+
} else if (message.command == 'INSERT_SYMBOL_AT_CURSOR') {
200+
const ref = message.target == 'preset-prefix' ? prefix_ref : suffix_ref
201+
const set_text =
202+
message.target == 'preset-prefix'
203+
? set_prompt_prefix
204+
: set_prompt_suffix
205+
const text =
206+
message.target == 'preset-prefix' ? prompt_prefix : prompt_suffix
207+
208+
if (ref.current) {
209+
const start = ref.current.get_caret_position()
210+
const end = start
211+
const before = (text || '').substring(0, start)
212+
const after = (text || '').substring(end)
213+
214+
const is_after_hash_sign = before.endsWith('#')
215+
const prefix_before = is_after_hash_sign
216+
? before.slice(0, -1)
217+
: before
218+
219+
const new_text = prefix_before + message.text + after
220+
set_text(new_text)
221+
222+
setTimeout(() => {
223+
if (ref.current) {
224+
ref.current.focus()
225+
const new_caret = prefix_before.length + message.text.length
226+
ref.current.set_caret_position(new_caret)
227+
}
228+
}, 0)
229+
}
195230
}
196231
}
197232
window.addEventListener('message', handle_message)
198233
return () => window.removeEventListener('message', handle_message)
199234
}, [active_field, prompt_prefix, prompt_suffix])
200235

201-
const check_for_at_sign = (
202-
value: string,
203-
ref: React.RefObject<HTMLTextAreaElement>
204-
) => {
205-
if (ref.current && value.charAt(ref.current.selectionStart - 1) == '@') {
206-
setTimeout(() => {
207-
props.on_at_sign_in_affix()
208-
}, 150)
209-
}
210-
}
211-
212236
const supported_reasoning_efforts = useMemo(() => {
213237
return (
214238
chatbot_config?.supported_reasoning_efforts ||
@@ -527,17 +551,15 @@ export const EditPresetForm: React.FC<Props> = (props) => {
527551
: "Text prepended to all prompts used with this group's presets."
528552
}
529553
>
530-
<UiTextarea
554+
<UiPromptTemplate
531555
id="prefix"
532556
ref={prefix_ref}
533557
value={prompt_prefix}
534-
on_change={(value) => {
535-
set_prompt_prefix(value)
536-
check_for_at_sign(value, prefix_ref)
537-
}}
538-
onFocus={() => set_active_field('prompt_prefix')}
539-
min_rows={2}
540-
blur_on_enter={false}
558+
on_change={(value) => set_prompt_prefix(value)}
559+
on_focus={() => set_active_field('prompt_prefix')}
560+
on_insert_symbol_click={() =>
561+
props.on_insert_symbol_click('preset-prefix')
562+
}
541563
/>
542564
</UiField>
543565

@@ -550,17 +572,15 @@ export const EditPresetForm: React.FC<Props> = (props) => {
550572
: "Text appended to all prompts used with this group's presets."
551573
}
552574
>
553-
<UiTextarea
575+
<UiPromptTemplate
554576
id="suffix"
555577
ref={suffix_ref}
556578
value={prompt_suffix}
557-
on_change={(value) => {
558-
set_prompt_suffix(value)
559-
check_for_at_sign(value, suffix_ref)
560-
}}
561-
onFocus={() => set_active_field('prompt_suffix')}
562-
min_rows={2}
563-
blur_on_enter={false}
579+
on_change={(value) => set_prompt_suffix(value)}
580+
on_focus={() => set_active_field('prompt_suffix')}
581+
on_insert_symbol_click={() =>
582+
props.on_insert_symbol_click('preset-suffix')
583+
}
564584
/>
565585
</UiField>
566586
</UiFieldset>

‎apps/editor/src/views/panel/types/messages.ts‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ export interface ShowAtSignQuickPickMessage extends BaseMessage {
260260
export interface ShowHashSignQuickPickMessage extends BaseMessage {
261261
command: 'SHOW_HASH_SIGN_QUICK_PICK'
262262
is_for_code_completions: boolean
263+
target?: 'prompt-field' | 'preset-prefix' | 'preset-suffix'
263264
}
264265

265266
export interface CancelApiRequestMessage extends BaseMessage {
@@ -561,6 +562,12 @@ export interface SetupProgressMessage {
561562
setup_progress: SetupProgress
562563
}
563564

565+
export interface InsertSymbolAtCursorMessage extends BaseMessage {
566+
command: 'INSERT_SYMBOL_AT_CURSOR'
567+
text: string
568+
target: 'preset-prefix' | 'preset-suffix'
569+
}
570+
564571
export type FrontendMessage =
565572
| GetInstructionsMessage
566573
| SaveInstructionsMessage
@@ -957,3 +964,4 @@ export type BackendMessage =
957964
| PruneContextInstructionsPrefixMessage
958965
| RecordingStateMessage
959966
| SetupProgressMessage
967+
| InsertSymbolAtCursorMessage

0 commit comments

Comments
 (0)