diff --git a/packages/cli/src/ui/commands/skillsCommand.ts b/packages/cli/src/ui/commands/skillsCommand.ts index 25433426a..8e41a1ce9 100644 --- a/packages/cli/src/ui/commands/skillsCommand.ts +++ b/packages/cli/src/ui/commands/skillsCommand.ts @@ -10,7 +10,7 @@ import { type CommandContext, type SlashCommand, } from './types.js'; -import { MessageType } from '../types.js'; +import { MessageType, type HistoryItemSkillsList } from '../types.js'; import { t } from '../../i18n/index.js'; import { AsyncFzf } from 'fzf'; import type { SkillConfig } from '@qwen-code/qwen-code-core'; @@ -41,7 +41,7 @@ export const skillsCommand: SlashCommand = { if (skills.length === 0) { context.ui.addItem( { - type: MessageType.WARNING, + type: MessageType.INFO, text: t('No skills are currently available.'), }, Date.now(), @@ -50,13 +50,14 @@ export const skillsCommand: SlashCommand = { } if (!skillName) { - context.ui.addItem( - { - type: MessageType.INFO, - text: t('Use /skills to select a skill'), - }, - Date.now(), + const sortedSkills = [...skills].sort((left, right) => + left.name.localeCompare(right.name), ); + const skillsListItem: HistoryItemSkillsList = { + type: MessageType.SKILLS_LIST, + skills: sortedSkills.map((skill) => ({ name: skill.name })), + }; + context.ui.addItem(skillsListItem, Date.now()); return; } const normalizedName = skillName.toLowerCase(); diff --git a/packages/cli/src/ui/components/HistoryItemDisplay.tsx b/packages/cli/src/ui/components/HistoryItemDisplay.tsx index 97e1fb47d..d1b247a64 100644 --- a/packages/cli/src/ui/components/HistoryItemDisplay.tsx +++ b/packages/cli/src/ui/components/HistoryItemDisplay.tsx @@ -30,6 +30,7 @@ import { Help } from './Help.js'; import type { SlashCommand } from '../commands/types.js'; import { ExtensionsList } from './views/ExtensionsList.js'; import { getMCPServerStatus } from '@qwen-code/qwen-code-core'; +import { SkillsList } from './views/SkillsList.js'; import { ToolsList } from './views/ToolsList.js'; import { McpStatus } from './views/McpStatus.js'; @@ -153,6 +154,9 @@ const HistoryItemDisplayComponent: React.FC = ({ showDescriptions={itemForDisplay.showDescriptions} /> )} + {itemForDisplay.type === 'skills_list' && ( + + )} {itemForDisplay.type === 'mcp_status' && ( )} diff --git a/packages/cli/src/ui/components/messages/InfoMessage.tsx b/packages/cli/src/ui/components/messages/InfoMessage.tsx index e4ca2d83b..1d132a898 100644 --- a/packages/cli/src/ui/components/messages/InfoMessage.tsx +++ b/packages/cli/src/ui/components/messages/InfoMessage.tsx @@ -23,7 +23,7 @@ export const InfoMessage: React.FC = ({ text }) => { const prefixWidth = prefix.length; return ( - + {prefix} diff --git a/packages/cli/src/ui/components/messages/WarningMessage.tsx b/packages/cli/src/ui/components/messages/WarningMessage.tsx index adc86b6f1..8e1e9f1d1 100644 --- a/packages/cli/src/ui/components/messages/WarningMessage.tsx +++ b/packages/cli/src/ui/components/messages/WarningMessage.tsx @@ -18,7 +18,7 @@ export const WarningMessage: React.FC = ({ text }) => { const prefixWidth = 3; return ( - + {prefix} diff --git a/packages/cli/src/ui/components/views/SkillsList.tsx b/packages/cli/src/ui/components/views/SkillsList.tsx new file mode 100644 index 000000000..c3d73c8e5 --- /dev/null +++ b/packages/cli/src/ui/components/views/SkillsList.tsx @@ -0,0 +1,36 @@ +/** + * @license + * Copyright 2025 Qwen + * SPDX-License-Identifier: Apache-2.0 + */ + +import type React from 'react'; +import { Box, Text } from 'ink'; +import { theme } from '../../semantic-colors.js'; +import { type SkillDefinition } from '../../types.js'; +import { t } from '../../../i18n/index.js'; + +interface SkillsListProps { + skills: readonly SkillDefinition[]; +} + +export const SkillsList: React.FC = ({ skills }) => ( + + + {t('Available skills:')} + + + {skills.length > 0 ? ( + skills.map((skill) => ( + + {' '}- + + {skill.name} + + + )) + ) : ( + {t('No skills available')} + )} + +); diff --git a/packages/cli/src/ui/types.ts b/packages/cli/src/ui/types.ts index 96ed4c50c..ff7e68aaf 100644 --- a/packages/cli/src/ui/types.ts +++ b/packages/cli/src/ui/types.ts @@ -201,12 +201,21 @@ export interface ToolDefinition { description?: string; } +export interface SkillDefinition { + name: string; +} + export type HistoryItemToolsList = HistoryItemBase & { type: 'tools_list'; tools: ToolDefinition[]; showDescriptions: boolean; }; +export type HistoryItemSkillsList = HistoryItemBase & { + type: 'skills_list'; + skills: SkillDefinition[]; +}; + // JSON-friendly types for using as a simple data model showing info about an // MCP Server. export interface JsonMcpTool { @@ -268,6 +277,7 @@ export type HistoryItemWithoutId = | HistoryItemCompression | HistoryItemExtensionsList | HistoryItemToolsList + | HistoryItemSkillsList | HistoryItemMcpStatus; export type HistoryItem = HistoryItemWithoutId & { id: number }; @@ -289,6 +299,7 @@ export enum MessageType { SUMMARY = 'summary', EXTENSIONS_LIST = 'extensions_list', TOOLS_LIST = 'tools_list', + SKILLS_LIST = 'skills_list', MCP_STATUS = 'mcp_status', }