Allow ask headers longer than 16 chars (#20041)

This commit is contained in:
Tommaso Sciortino
2026-02-23 10:26:59 -08:00
committed by GitHub
parent 3f6cec22e6
commit 813e0c18ac
6 changed files with 40 additions and 38 deletions

View File

@@ -173,6 +173,28 @@ describe('TabHeader', () => {
unmount(); unmount();
}); });
it('truncates long headers when not selected', async () => {
const longTabs: Tab[] = [
{ key: '0', header: 'ThisIsAVeryLongHeaderThatShouldBeTruncated' },
{ key: '1', header: 'AnotherVeryLongHeader' },
];
const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
<TabHeader tabs={longTabs} currentIndex={0} />,
);
await waitUntilReady();
const frame = lastFrame();
// Current tab (index 0) should NOT be truncated
expect(frame).toContain('ThisIsAVeryLongHeaderThatShouldBeTruncated');
// Inactive tab (index 1) SHOULD be truncated to 16 chars (15 chars + …)
const expectedTruncated = 'AnotherVeryLong…';
expect(frame).toContain(expectedTruncated);
expect(frame).not.toContain('AnotherVeryLongHeader');
unmount();
});
it('falls back to default when renderStatusIcon returns undefined', async () => { it('falls back to default when renderStatusIcon returns undefined', async () => {
const renderStatusIcon = () => undefined; const renderStatusIcon = () => undefined;
const { lastFrame, waitUntilReady, unmount } = renderWithProviders( const { lastFrame, waitUntilReady, unmount } = renderWithProviders(

View File

@@ -94,16 +94,19 @@ export function TabHeader({
{showStatusIcons && ( {showStatusIcons && (
<Text color={theme.text.secondary}>{getStatusIcon(tab, i)} </Text> <Text color={theme.text.secondary}>{getStatusIcon(tab, i)} </Text>
)} )}
<Text <Box maxWidth={i !== currentIndex ? 16 : 100}>
color={ <Text
i === currentIndex ? theme.status.success : theme.text.secondary color={
} i === currentIndex ? theme.status.success : theme.text.secondary
bold={i === currentIndex} }
underline={i === currentIndex} bold={i === currentIndex}
aria-current={i === currentIndex ? 'step' : undefined} underline={i === currentIndex}
> aria-current={i === currentIndex ? 'step' : undefined}
{tab.header} wrap="truncate"
</Text> >
{tab.header}
</Text>
</Box>
</React.Fragment> </React.Fragment>
))} ))}
{showArrows && <Text color={theme.text.secondary}>{' →'}</Text>} {showArrows && <Text color={theme.text.secondary}>{' →'}</Text>}

View File

@@ -103,19 +103,6 @@ describe('AskUserTool', () => {
expect(result).toContain("must have required property 'header'"); expect(result).toContain("must have required property 'header'");
}); });
it('should return error if header exceeds max length', () => {
const result = tool.validateToolParams({
questions: [
{
question: 'Test?',
header: 'This is way too long',
type: QuestionType.CHOICE,
},
],
});
expect(result).toContain('must NOT have more than 16 characters');
});
it('should return error if options has fewer than 2 items', () => { it('should return error if options has fewer than 2 items', () => {
const result = tool.validateToolParams({ const result = tool.validateToolParams({
questions: [ questions: [
@@ -276,13 +263,7 @@ describe('AskUserTool', () => {
describe('validateBuildAndExecute', () => { describe('validateBuildAndExecute', () => {
it('should hide validation errors from returnDisplay', async () => { it('should hide validation errors from returnDisplay', async () => {
const params = { const params = {
questions: [ questions: [],
{
question: 'Test?',
header: 'This is way too long',
type: QuestionType.TEXT,
},
],
}; };
const result = await tool.validateBuildAndExecute( const result = await tool.validateBuildAndExecute(

View File

@@ -80,8 +80,7 @@ exports[`coreTools snapshots for specific models > Model: gemini-2.5-pro > snaps
"items": { "items": {
"properties": { "properties": {
"header": { "header": {
"description": "MUST be 16 characters or fewer or the call will fail. Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".", "description": "Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".",
"maxLength": 16,
"type": "string", "type": "string",
}, },
"multiSelect": { "multiSelect": {
@@ -869,8 +868,7 @@ exports[`coreTools snapshots for specific models > Model: gemini-3-pro-preview >
"items": { "items": {
"properties": { "properties": {
"header": { "header": {
"description": "MUST be 16 characters or fewer or the call will fail. Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".", "description": "Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".",
"maxLength": 16,
"type": "string", "type": "string",
}, },
"multiSelect": { "multiSelect": {

View File

@@ -609,9 +609,8 @@ The agent did not use the todo list because this task could be completed by a ti
}, },
header: { header: {
type: 'string', type: 'string',
maxLength: 16,
description: description:
'MUST be 16 characters or fewer or the call will fail. Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".', 'Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".',
}, },
type: { type: {
type: 'string', type: 'string',

View File

@@ -587,9 +587,8 @@ The agent did not use the todo list because this task could be completed by a ti
}, },
header: { header: {
type: 'string', type: 'string',
maxLength: 16,
description: description:
'MUST be 16 characters or fewer or the call will fail. Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".', 'Very short label displayed as a chip/tag. Use abbreviations: "Auth" not "Authentication", "Config" not "Configuration". Examples: "Auth method", "Library", "Approach", "Database".',
}, },
type: { type: {
type: 'string', type: 'string',