fix(native-chat): suggest verified OMP terminal commands

Co-authored-by: Nafisul Haque <100821672+nafisul-haque@users.noreply.github.com>
This commit is contained in:
Neil
2026-09-14 11:51:30 -07:00
co-authored by Nafisul Haque
parent 875b86d168
commit b3847f936e
3 changed files with 98 additions and 1 deletions
@@ -2,6 +2,13 @@ import { describe, expect, it } from 'vitest'
import { classifyMobileNativeChatSend } from './mobile-native-chat-send-classification'
describe('classifyMobileNativeChatSend', () => {
it('recognizes OMP selectors and context commands without claiming generic help', () => {
expect(classifyMobileNativeChatSend('omp', '/switch')).toBe('command')
expect(classifyMobileNativeChatSend('omp', '/compact focus on tests')).toBe('command')
expect(classifyMobileNativeChatSend('omp', '/help')).toBe('unknown-token')
expect(classifyMobileNativeChatSend('omp', '/smol')).toBe('unknown-token')
})
it('classifies catalog commands per agent', () => {
expect(classifyMobileNativeChatSend('claude', '/clear')).toBe('command')
expect(classifyMobileNativeChatSend('claude', '/compact')).toBe('command')
@@ -0,0 +1,60 @@
import { describe, expect, it } from 'vitest'
import {
getNativeChatAgentProfile,
getVerifiedNativeChatCommands
} from './native-chat-agent-profiles'
import {
applySlashSuggestion,
classifyNativeChatSend,
filterSlashCommands,
getAgentSlashCommands,
sessionSlashCommandSuggestions,
slashCommandDispatchText
} from './native-chat-slash-commands'
describe('OMP terminal command catalog', () => {
it('offers the verified model, planning and context commands without generic help', () => {
const commands = getAgentSlashCommands('omp')
const names = commands.map((command) => command.name)
expect(names).toEqual(
expect.arrayContaining(['model', 'switch', 'plan', 'compact', 'context', 'usage'])
)
expect(names).not.toContain('help')
expect(getVerifiedNativeChatCommands('omp')).toEqual(commands)
expect(getNativeChatAgentProfile('omp')).toBeNull()
expect(new Set(names).size).toBe(names.length)
expect(getAgentSlashCommands('pi').map((command) => command.name)).toEqual(['clear', 'help'])
})
it('completes arguments separately from picker command dispatch', () => {
const matches = filterSlashCommands(getAgentSlashCommands('omp'), 'MOD')
expect(matches).toHaveLength(1)
const command = matches[0]
if (!command) {
throw new Error('Expected an OMP model suggestion')
}
expect(command.name).toBe('model')
expect(applySlashSuggestion(command)).toBe('/model ')
expect(slashCommandDispatchText(command)).toBe('/model')
})
it('classifies known OMP commands as terminal actions, preserving unknown and prose paths', () => {
const commands = getAgentSlashCommands('omp')
expect(classifyNativeChatSend('/compact focus on tests', commands, null, null)).toBe('command')
expect(classifyNativeChatSend('/model', commands, null, null)).toBe('command')
expect(classifyNativeChatSend('/help', commands, null, null)).toBe('unknown-token')
expect(classifyNativeChatSend(' /model', commands, null, null)).toBe('chat')
expect(classifyNativeChatSend('/plan', commands, '/plan', '/')).toBe('chat')
})
it('lets a session command report replace the curated set and descriptions', () => {
expect(
sessionSlashCommandSuggestions('omp', [
{ name: 'model', kind: 'command', description: 'Host model selector' },
{ name: 'custom', kind: 'command' },
{ name: 'plan', kind: 'skill' }
])
).toEqual([{ name: 'model', description: 'Host model selector' }, { name: 'custom' }])
expect(sessionSlashCommandSuggestions('omp', [])).toEqual([])
})
})
+31 -1
View File
@@ -82,10 +82,40 @@ const CODEX_COMMANDS: readonly SlashCommandSuggestion[] = [
{ name: 'subagents', description: 'Switch the active agent thread' }
]
// OMP built-in registry; interactive commands still execute in its terminal.
const OMP_COMMANDS: readonly SlashCommandSuggestion[] = [
{ name: 'model', description: 'Open the model selector in Terminal' },
{
name: 'switch',
description: 'Open the temporary model selector in Terminal'
},
{ name: 'plan', description: 'Toggle plan mode' },
{ name: 'compact', description: 'Compact conversation context' },
{ name: 'clear', description: 'Clear context while keeping the session' },
{ name: 'new', description: 'Start a new session' },
{ name: 'resume', description: 'Resume a session; without arguments, choose in Terminal' },
{ name: 'fork', description: 'Fork from a previous message in Terminal' },
{ name: 'branch', description: 'Rewind to a previous message in Terminal' },
{ name: 'tree', description: 'Browse the session tree in Terminal' },
{ name: 'session', description: 'Show session information and controls' },
{ name: 'rename', description: 'Rename the session' },
{ name: 'context', description: 'Show estimated context usage' },
{ name: 'usage', description: 'Show provider usage and limits' },
{ name: 'fast', description: 'Toggle priority service tier' },
{ name: 'tools', description: 'Show tools visible to the agent' },
{ name: 'jobs', description: 'Show background jobs' },
{ name: 'git', description: 'Open the Git viewer in Terminal' },
{ name: 'export', description: 'Export the session to HTML' },
{ name: 'settings', description: 'Open settings in Terminal' },
{ name: 'extensions', description: 'Open the extension dashboard in Terminal' },
{ name: 'hotkeys', description: 'Show keyboard shortcuts in Terminal' }
]
const COMMANDS_BY_AGENT: Partial<Record<AgentType, readonly SlashCommandSuggestion[]>> = {
claude: CLAUDE_COMMANDS,
openclaude: CLAUDE_COMMANDS,
codex: CODEX_COMMANDS
codex: CODEX_COMMANDS,
omp: OMP_COMMANDS
}
/** Known slash commands for an agent, falling back to a small common set so the