hermes-agent / ui-tui /src /__tests__ /inlineSlashSkill.test.ts
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
48ea638 verified
Raw History Blame Contribute Delete
3.39 kB
import { describe, expect, it } from 'vitest'
import { inlineSlashTrigger } from '../domain/slash.js'
import { completionRequestForInput } from '../hooks/useCompletion.js'
describe('inlineSlashTrigger', () => {
it('detects a slash typed mid-message', () => {
// The reported bug: only a position-0 slash offered anything, so
// "please run /cle" completed nothing.
expect(inlineSlashTrigger('please run /cle')).toEqual({ query: 'cle', start: 11 })
})
it('detects a bare slash after whitespace, before any name is typed', () => {
expect(inlineSlashTrigger('please run /')).toEqual({ query: '', start: 11 })
})
it('fires after a newline, not just a space', () => {
expect(inlineSlashTrigger('text\n/skill')).toEqual({ query: 'skill', start: 5 })
})
it('does not fire at position 0 — that is a command invocation', () => {
expect(inlineSlashTrigger('/clean')).toBeNull()
expect(inlineSlashTrigger('/')).toBeNull()
})
it('leaves file paths alone', () => {
expect(inlineSlashTrigger('look at /usr/local/bin')).toBeNull()
expect(inlineSlashTrigger('check src/foo/bar')).toBeNull()
expect(inlineSlashTrigger('and/or')).toBeNull()
})
it('stops at the command token — an inline reference takes no args', () => {
// Only a position-0 slash is a real invocation, so `/personality alic`
// mid-message is prose with a reference in it, already ended.
expect(inlineSlashTrigger('hello there /personality alic')).toBeNull()
})
it('reports a start index that replaces only the typed token', () => {
const text = 'please run /cle'
const trigger = inlineSlashTrigger(text)!
expect(text.slice(0, trigger.start)).toBe('please run ')
expect(text.slice(trigger.start)).toBe('/cle')
})
})
describe('completionRequestForInput — inline skill references', () => {
it('asks for skills only when the slash is mid-message', () => {
const request = completionRequestForInput('please run /cle')
expect(request).toMatchObject({
method: 'complete.slash',
params: { text: '/cle' },
replaceFrom: 12,
skillsOnly: true
})
})
it('keeps the full command set at position 0', () => {
expect(completionRequestForInput('/cle')).toEqual({
method: 'complete.slash',
params: { text: '/cle' },
replaceFrom: 1
})
})
it('completes a second slash in a line that starts with a command', () => {
// Only the first slash is an invocation. Routing the whole line to the
// completer offered nothing, so `/work /cle` went dead while
// `do /work then /cle` completed fine.
expect(completionRequestForInput('/work /cle')).toMatchObject({
method: 'complete.slash',
params: { text: '/cle' },
replaceFrom: 7,
skillsOnly: true
})
})
it('leaves a command own arguments to the command', () => {
for (const input of ['/personality alic', '/cron ad', '/details ']) {
expect(completionRequestForInput(input)).toEqual({
method: 'complete.slash',
params: { text: input },
replaceFrom: 1
})
}
})
it('routes a real mid-message path to path completion, not skills', () => {
expect(completionRequestForInput('open src/foo/ba')).toMatchObject({ method: 'complete.path' })
expect(completionRequestForInput('open /usr/lo')).toMatchObject({ method: 'complete.path' })
})
})