fix(tui): restore prompt rendering on startup (#498)

* fix(tui): restore prompt rendering on startup

* test(tui): document render-time command split

* fix(tui): reduce ghostty prompt repaint scope
This commit is contained in:
sooth
2026-04-09 08:40:06 -04:00
committed by GitHub
parent c328fdf9e2
commit e30ad17ae0
17 changed files with 778 additions and 100 deletions

View File

@@ -1,6 +1,29 @@
import { describe, expect, test } from 'bun:test'
import type { Command } from '../../commands.js'
import { SkillTool } from './SkillTool.js'
import { renderToolUseMessage } from './UI.js'
function createPromptCommand(
name: string,
options: {
source?: 'builtin' | 'plugin' | 'mcp' | 'bundled'
loadedFrom?: Command['loadedFrom']
} = {},
): Command {
return {
type: 'prompt',
name,
description: `${name} description`,
progressMessage: `${name} progress`,
contentLength: 0,
source: options.source ?? 'builtin',
loadedFrom: options.loadedFrom,
async getPromptForCommand() {
return []
},
}
}
describe('SkillTool missing parameter handling', () => {
test('missing skill stays required at the schema level', async () => {
@@ -29,3 +52,47 @@ describe('SkillTool missing parameter handling', () => {
expect(parsed.success).toBe(true)
})
})
describe('SkillTool renderToolUseMessage', () => {
test('plugin skills render correctly without plugin command metadata', () => {
const pluginSkillName = 'plugin:review-pr'
expect(
renderToolUseMessage(
{ skill: pluginSkillName },
{
commands: [],
},
),
).toBe(pluginSkillName)
expect(
renderToolUseMessage(
{ skill: pluginSkillName },
{
commands: [
createPromptCommand(pluginSkillName, {
source: 'plugin',
loadedFrom: 'plugin',
}),
],
},
),
).toBe(pluginSkillName)
})
test('legacy commands still render with a slash prefix when metadata is present', () => {
expect(
renderToolUseMessage(
{ skill: 'legacy-command' },
{
commands: [
createPromptCommand('legacy-command', {
loadedFrom: 'commands_DEPRECATED',
}),
],
},
),
).toBe('/legacy-command')
})
})

View File

@@ -54,7 +54,10 @@ export function renderToolUseMessage({
if (!skill) {
return null;
}
// Look up the command to check if it came from the legacy /commands folder
// Only legacy /commands_DEPRECATED entries need the command lookup so we can
// preserve the slash-prefixed display. Plugin skills already carry the
// invoked skill name in `skill`, so transcript/history rendering does not
// need plugin command metadata.
const command = commands?.find(c => c.name === skill);
const displayName = command?.loadedFrom === 'commands_DEPRECATED' ? `/${skill}` : skill;
return displayName;