mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-29 18:46:59 +00:00
Merge pull request #73074 from NousResearch/bb/slash-after-command
fix(desktop): keep slash completion alive after a leading command
This commit is contained in:
commit
202140db53
2 changed files with 37 additions and 7 deletions
|
|
@ -120,6 +120,29 @@ describe('useComposerTrigger — slash anywhere in the prompt', () => {
|
|||
|
||||
expect(hook.result.current.trigger).toBeNull()
|
||||
})
|
||||
|
||||
it('opens the list for a second slash after a leading command', () => {
|
||||
// `/work /cle`: the command regex's argument tail would otherwise swallow
|
||||
// `/cle` as an argument to `/work`, and a no-arg command suppresses the
|
||||
// popover — so every slash after the first went dead.
|
||||
const editor = mountEditor('/work /cle')
|
||||
const { hook } = mountTrigger(editor, [item('/clean')])
|
||||
|
||||
act(() => hook.result.current.refreshTrigger())
|
||||
|
||||
expect(hook.result.current.trigger).toMatchObject({ kind: '/', inline: true, query: 'cle' })
|
||||
expect(hook.result.current.triggerItems).toHaveLength(1)
|
||||
})
|
||||
|
||||
it('inserts the second command without disturbing the first', () => {
|
||||
const editor = mountEditor('/work rewrite the composer /cle')
|
||||
const { hook } = mountTrigger(editor, [item('/clean')])
|
||||
|
||||
act(() => hook.result.current.refreshTrigger())
|
||||
act(() => hook.result.current.replaceTriggerWithChip(item('/clean')))
|
||||
|
||||
expect(composerPlainText(editor)).toBe('/work rewrite the composer /clean ')
|
||||
})
|
||||
})
|
||||
|
||||
describe('useComposerTrigger — free-text slash arguments', () => {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,11 @@ export interface TriggerState {
|
|||
// there are no args to complete — the trigger is a single token that ends at
|
||||
// the next space, exactly like `@`.
|
||||
//
|
||||
// Only the FIRST slash can be an invocation, so the inline shape is tested
|
||||
// first: the command regex's argument tail (`(?:\s+\S*)*`) happily swallows a
|
||||
// later `/skill` as if it were an argument, which killed completion for every
|
||||
// slash after a leading command (`/work /cle` → nothing).
|
||||
//
|
||||
// The inline shape is what makes skills reachable anywhere in a prompt. Both
|
||||
// shapes need the trailing `$`: detection runs against the text BEFORE the
|
||||
// caret, so the match must end where the user is typing.
|
||||
|
|
@ -124,14 +129,10 @@ export function textBeforeCaret(editor: HTMLDivElement): string | null {
|
|||
}
|
||||
|
||||
export function detectTrigger(textBefore: string): TriggerState | null {
|
||||
const command = SLASH_COMMAND_TRIGGER_RE.exec(textBefore)
|
||||
|
||||
if (command) {
|
||||
return { kind: '/', query: command[2], tokenLength: 1 + command[2].length }
|
||||
}
|
||||
|
||||
// An inline `/skill` is a reference dropped into prose, so it carries no args
|
||||
// and the whole match is the token the chip replaces.
|
||||
// and the whole match is the token the chip replaces. Checked before the
|
||||
// anchored command shape so a second slash isn't mistaken for the first
|
||||
// command's argument.
|
||||
const inline = SLASH_INLINE_TRIGGER_RE.exec(textBefore)
|
||||
|
||||
if (inline) {
|
||||
|
|
@ -140,6 +141,12 @@ export function detectTrigger(textBefore: string): TriggerState | null {
|
|||
return { inline: true, kind: '/', query, tokenLength: 1 + query.length }
|
||||
}
|
||||
|
||||
const command = SLASH_COMMAND_TRIGGER_RE.exec(textBefore)
|
||||
|
||||
if (command) {
|
||||
return { kind: '/', query: command[2], tokenLength: 1 + command[2].length }
|
||||
}
|
||||
|
||||
const at = AT_TRIGGER_RE.exec(textBefore)
|
||||
|
||||
if (at) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue