mirror of
http://10.0.2.1:3031/sauer/claude-code.git
synced 2026-06-30 18:26:58 +10:00
237 lines
27 KiB
TypeScript
237 lines
27 KiB
TypeScript
|
|
import { c as _c } from "react/compiler-runtime";
|
||
|
|
import capitalize from 'lodash-es/capitalize.js';
|
||
|
|
import * as React from 'react';
|
||
|
|
import { useMemo } from 'react';
|
||
|
|
import { type Command, type CommandBase, type CommandResultDisplay, getCommandName, type PromptCommand } from '../../commands.js';
|
||
|
|
import { Box, Text } from '../../ink.js';
|
||
|
|
import { estimateSkillFrontmatterTokens, getSkillsPath } from '../../skills/loadSkillsDir.js';
|
||
|
|
import { getDisplayPath } from '../../utils/file.js';
|
||
|
|
import { formatTokens } from '../../utils/format.js';
|
||
|
|
import { getSettingSourceName, type SettingSource } from '../../utils/settings/constants.js';
|
||
|
|
import { plural } from '../../utils/stringUtils.js';
|
||
|
|
import { ConfigurableShortcutHint } from '../ConfigurableShortcutHint.js';
|
||
|
|
import { Dialog } from '../design-system/Dialog.js';
|
||
|
|
|
||
|
|
// Skills are always PromptCommands with CommandBase properties
|
||
|
|
type SkillCommand = CommandBase & PromptCommand;
|
||
|
|
type SkillSource = SettingSource | 'plugin' | 'mcp';
|
||
|
|
type Props = {
|
||
|
|
onExit: (result?: string, options?: {
|
||
|
|
display?: CommandResultDisplay;
|
||
|
|
}) => void;
|
||
|
|
commands: Command[];
|
||
|
|
};
|
||
|
|
function getSourceTitle(source: SkillSource): string {
|
||
|
|
if (source === 'plugin') {
|
||
|
|
return 'Plugin skills';
|
||
|
|
}
|
||
|
|
if (source === 'mcp') {
|
||
|
|
return 'MCP skills';
|
||
|
|
}
|
||
|
|
return `${capitalize(getSettingSourceName(source))} skills`;
|
||
|
|
}
|
||
|
|
function getSourceSubtitle(source: SkillSource, skills: SkillCommand[]): string | undefined {
|
||
|
|
// MCP skills show server names; file-based skills show filesystem paths.
|
||
|
|
// Skill names are `<server>:<skill>`, not `mcp__<server>__…`.
|
||
|
|
if (source === 'mcp') {
|
||
|
|
const servers = [...new Set(skills.map(s => {
|
||
|
|
const idx = s.name.indexOf(':');
|
||
|
|
return idx > 0 ? s.name.slice(0, idx) : null;
|
||
|
|
}).filter((n): n is string => n != null))];
|
||
|
|
return servers.length > 0 ? servers.join(', ') : undefined;
|
||
|
|
}
|
||
|
|
const skillsPath = getDisplayPath(getSkillsPath(source, 'skills'));
|
||
|
|
const hasCommandsSkills = skills.some(s => s.loadedFrom === 'commands_DEPRECATED');
|
||
|
|
return hasCommandsSkills ? `${skillsPath}, ${getDisplayPath(getSkillsPath(source, 'commands'))}` : skillsPath;
|
||
|
|
}
|
||
|
|
export function SkillsMenu(t0) {
|
||
|
|
const $ = _c(35);
|
||
|
|
const {
|
||
|
|
onExit,
|
||
|
|
commands
|
||
|
|
} = t0;
|
||
|
|
let t1;
|
||
|
|
if ($[0] !== commands) {
|
||
|
|
t1 = commands.filter(_temp);
|
||
|
|
$[0] = commands;
|
||
|
|
$[1] = t1;
|
||
|
|
} else {
|
||
|
|
t1 = $[1];
|
||
|
|
}
|
||
|
|
const skills = t1;
|
||
|
|
let groups;
|
||
|
|
if ($[2] !== skills) {
|
||
|
|
groups = {
|
||
|
|
policySettings: [],
|
||
|
|
userSettings: [],
|
||
|
|
projectSettings: [],
|
||
|
|
localSettings: [],
|
||
|
|
flagSettings: [],
|
||
|
|
plugin: [],
|
||
|
|
mcp: []
|
||
|
|
};
|
||
|
|
for (const skill of skills) {
|
||
|
|
const source = skill.source as SkillSource;
|
||
|
|
if (source in groups) {
|
||
|
|
groups[source].push(skill);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
for (const group of Object.values(groups)) {
|
||
|
|
group.sort(_temp2);
|
||
|
|
}
|
||
|
|
$[2] = skills;
|
||
|
|
$[3] = groups;
|
||
|
|
} else {
|
||
|
|
groups = $[3];
|
||
|
|
}
|
||
|
|
const skillsBySource = groups;
|
||
|
|
let t2;
|
||
|
|
if ($[4] !== onExit) {
|
||
|
|
t2 = () => {
|
||
|
|
onExit("Skills dialog dismissed", {
|
||
|
|
display: "system"
|
||
|
|
});
|
||
|
|
};
|
||
|
|
$[4] = onExit;
|
||
|
|
$[5] = t2;
|
||
|
|
} else {
|
||
|
|
t2 = $[5];
|
||
|
|
}
|
||
|
|
const handleCancel = t2;
|
||
|
|
if (skills.length === 0) {
|
||
|
|
let t3;
|
||
|
|
if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
|
||
|
|
t3 = <Text dimColor={true}>Create skills in .claude/skills/ or ~/.claude/skills/</Text>;
|
||
|
|
$[6] = t3;
|
||
|
|
} else {
|
||
|
|
t3 = $[6];
|
||
|
|
}
|
||
|
|
let t4;
|
||
|
|
if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
|
||
|
|
t4 = <Text dimColor={true} italic={true}><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="close" /></Text>;
|
||
|
|
$[7] = t4;
|
||
|
|
} else {
|
||
|
|
t4 = $[7];
|
||
|
|
}
|
||
|
|
let t5;
|
||
|
|
if ($[8] !== handleCancel) {
|
||
|
|
t5 = <Dialog title="Skills" subtitle="No skills found" onCancel={handleCancel} hideInputGuide={true}>{t3}{t4}</Dialog>;
|
||
|
|
$[8] = handleCancel;
|
||
|
|
$[9] = t5;
|
||
|
|
} else {
|
||
|
|
t5 = $[9];
|
||
|
|
}
|
||
|
|
return t5;
|
||
|
|
}
|
||
|
|
const renderSkill = _temp3;
|
||
|
|
let t3;
|
||
|
|
if ($[10] !== skillsBySource) {
|
||
|
|
t3 = source_0 => {
|
||
|
|
const groupSkills = skillsBySource[source_0];
|
||
|
|
if (groupSkills.length === 0) {
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
const title = getSourceTitle(source_0);
|
||
|
|
const subtitle = getSourceSubtitle(source_0, groupSkills);
|
||
|
|
return <Box flexDirection="column" key={source_0}><Box><Text bold={true} dimColor={true}>{title}</Text>{subtitle && <Text dimColor={true}> ({subtitle})</Text>}</Box>{groupSkills.map(skill_1 => renderSkill(skill_1))}</Box>;
|
||
|
|
};
|
||
|
|
$[10] = skillsBySource;
|
||
|
|
$[11] = t3;
|
||
|
|
} else {
|
||
|
|
t3 = $[11];
|
||
|
|
}
|
||
|
|
const renderSkillGroup = t3;
|
||
|
|
const t4 = skills.length;
|
||
|
|
let t5;
|
||
|
|
if ($[12] !== skills.length) {
|
||
|
|
t5 = plural(skills.length, "skill");
|
||
|
|
$[12] = skills.length;
|
||
|
|
$[13] = t5;
|
||
|
|
} else {
|
||
|
|
t5 = $[13];
|
||
|
|
}
|
||
|
|
const t6 = `${t4} ${t5}`;
|
||
|
|
let t7;
|
||
|
|
if ($[14] !== renderSkillGroup) {
|
||
|
|
t7 = renderSkillGroup("projectSettings");
|
||
|
|
$[14] = renderSkillGroup;
|
||
|
|
$[15] = t7;
|
||
|
|
} else {
|
||
|
|
t7 = $[15];
|
||
|
|
}
|
||
|
|
let t8;
|
||
|
|
if ($[16] !== renderSkillGroup) {
|
||
|
|
t8 = renderSkillGroup("userSettings");
|
||
|
|
$[16] = renderSkillGroup;
|
||
|
|
$[17] = t8;
|
||
|
|
} else {
|
||
|
|
t8 = $[17];
|
||
|
|
}
|
||
|
|
let t9;
|
||
|
|
if ($[18] !== renderSkillGroup) {
|
||
|
|
t9 = renderSkillGroup("policySettings");
|
||
|
|
$[18] = renderSkillGroup;
|
||
|
|
$[19] = t9;
|
||
|
|
} else {
|
||
|
|
t9 = $[19];
|
||
|
|
}
|
||
|
|
let t10;
|
||
|
|
if ($[20] !== renderSkillGroup) {
|
||
|
|
t10 = renderSkillGroup("plugin");
|
||
|
|
$[20] = renderSkillGroup;
|
||
|
|
$[21] = t10;
|
||
|
|
} else {
|
||
|
|
t10 = $[21];
|
||
|
|
}
|
||
|
|
let t11;
|
||
|
|
if ($[22] !== renderSkillGroup) {
|
||
|
|
t11 = renderSkillGroup("mcp");
|
||
|
|
$[22] = renderSkillGroup;
|
||
|
|
$[23] = t11;
|
||
|
|
} else {
|
||
|
|
t11 = $[23];
|
||
|
|
}
|
||
|
|
let t12;
|
||
|
|
if ($[24] !== t10 || $[25] !== t11 || $[26] !== t7 || $[27] !== t8 || $[28] !== t9) {
|
||
|
|
t12 = <Box flexDirection="column" gap={1}>{t7}{t8}{t9}{t10}{t11}</Box>;
|
||
|
|
$[24] = t10;
|
||
|
|
$[25] = t11;
|
||
|
|
$[26] = t7;
|
||
|
|
$[27] = t8;
|
||
|
|
$[28] = t9;
|
||
|
|
$[29] = t12;
|
||
|
|
} else {
|
||
|
|
t12 = $[29];
|
||
|
|
}
|
||
|
|
let t13;
|
||
|
|
if ($[30] === Symbol.for("react.memo_cache_sentinel")) {
|
||
|
|
t13 = <Text dimColor={true} italic={true}><ConfigurableShortcutHint action="confirm:no" context="Confirmation" fallback="Esc" description="close" /></Text>;
|
||
|
|
$[30] = t13;
|
||
|
|
} else {
|
||
|
|
t13 = $[30];
|
||
|
|
}
|
||
|
|
let t14;
|
||
|
|
if ($[31] !== handleCancel || $[32] !== t12 || $[33] !== t6) {
|
||
|
|
t14 = <Dialog title="Skills" subtitle={t6} onCancel={handleCancel} hideInputGuide={true}>{t12}{t13}</Dialog>;
|
||
|
|
$[31] = handleCancel;
|
||
|
|
$[32] = t12;
|
||
|
|
$[33] = t6;
|
||
|
|
$[34] = t14;
|
||
|
|
} else {
|
||
|
|
t14 = $[34];
|
||
|
|
}
|
||
|
|
return t14;
|
||
|
|
}
|
||
|
|
function _temp3(skill_0) {
|
||
|
|
const estimatedTokens = estimateSkillFrontmatterTokens(skill_0);
|
||
|
|
const tokenDisplay = `~${formatTokens(estimatedTokens)}`;
|
||
|
|
const pluginName = skill_0.source === "plugin" ? skill_0.pluginInfo?.pluginManifest.name : undefined;
|
||
|
|
return <Box key={`${skill_0.name}-${skill_0.source}`}><Text>{getCommandName(skill_0)}</Text><Text dimColor={true}>{pluginName ? ` · ${pluginName}` : ""} · {tokenDisplay} description tokens</Text></Box>;
|
||
|
|
}
|
||
|
|
function _temp2(a, b) {
|
||
|
|
return getCommandName(a).localeCompare(getCommandName(b));
|
||
|
|
}
|
||
|
|
function _temp(cmd) {
|
||
|
|
return cmd.type === "prompt" && (cmd.loadedFrom === "skills" || cmd.loadedFrom === "commands_DEPRECATED" || cmd.loadedFrom === "plugin" || cmd.loadedFrom === "mcp");
|
||
|
|
}
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjYXBpdGFsaXplIiwiUmVhY3QiLCJ1c2VNZW1vIiwiQ29tbWFuZCIsIkNvbW1hbmRCYXNlIiwiQ29tbWFuZFJlc3VsdERpc3BsYXkiLCJnZXRDb21tYW5kTmFtZSIsIlByb21wdENvbW1hbmQiLCJCb3giLCJUZXh0IiwiZXN0aW1hdGVTa2lsbEZyb250bWF0dGVyVG9rZW5zIiwiZ2V0U2tpbGxzUGF0aCIsImdldERpc3BsYXlQYXRoIiwiZm9ybWF0VG9rZW5zIiwiZ2V0U2V0dGluZ1NvdXJjZU5hbWUiLCJTZXR0aW5nU291cmNlIiwicGx1cmFsIiwiQ29uZmlndXJhYmxlU2hvcnRjdXRIaW50IiwiRGlhbG9nIiwiU2tpbGxDb21tYW5kIiwiU2tpbGxTb3VyY2UiLCJQcm9wcyIsIm9uRXhpdCIsInJlc3VsdCIsIm9wdGlvbnMiLCJkaXNwbGF5IiwiY29tbWFuZHMiLCJnZXRTb3VyY2VUaXRsZSIsInNvdXJjZSIsImdldFNvdXJjZVN1YnRpdGxlIiwic2tpbGxzIiwic2VydmVycyIsIlNldCIsIm1hcCIsInMiLCJpZHgiLCJuYW1lIiwiaW5kZXhPZiIsInNsaWNlIiwiZmlsdGVyIiwibiIsImxlbmd0aCIsImpvaW4iLCJ1bmRlZmluZWQiLCJza2lsbHNQYXRoIiwiaGFzQ29tbWFuZHNTa2lsbHMiLCJzb21lIiwibG9hZGVkRnJvbSIsIlNraWxsc01lbnUiLCJ0MCIsIiQiLCJfYyIsInQxIiwiX3RlbXAiLCJncm91cHMiLCJwb2xpY3lTZXR0aW5ncyIsInVzZXJTZXR0aW5ncyIsInByb2plY3RTZXR0aW5ncyIsImxvY2FsU2V0dGluZ3MiLCJmbGFnU2V0dGluZ3MiLCJwbHVnaW4iLCJtY3AiLCJza2lsbCIsInB1c2giLCJncm91cCIsIk9iamVjdCIsInZhbHVlcyIsInNvcnQiLCJfdGVtcDIiLCJza2lsbHNCeVNvdXJjZSIsInQyIiwiaGFuZGxlQ2FuY2VsIiwidDMiLCJTeW1ib2wiLCJmb3IiLCJ0NCIsInQ1IiwicmVuZGVyU2tpbGwiLCJfdGVtcDMiLCJzb3VyY2VfMCIsImdyb3VwU2tpbGxzIiwidGl0bGUiLCJzdWJ0aXRsZSIsInNraWxsXzEiLCJyZW5kZXJTa2lsbEdyb3VwIiwidDYiLCJ0NyIsInQ4IiwidDkiLCJ0MTAiLCJ0MTEiLCJ0MTIiLCJ0MTMiLCJ0MTQiLCJza2lsbF8wIiwiZXN0aW1hdGVkVG9rZW5zIiwidG9rZW5EaXNwbGF5IiwicGx1Z2luTmFtZSIsInBsdWdpbkluZm8iLCJwbHVnaW5NYW5pZmVzdCIsImEiLCJiIiwibG9jYWxlQ29tcGFyZSIsImNtZCIsInR5cGUiXSwic291cmNlcyI6WyJTa2lsbHNNZW51LnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgY2FwaXRhbGl6ZSBmcm9tICdsb2Rhc2gtZXMvY2FwaXRhbGl6ZS5qcydcbmltcG9ydCAqIGFzIFJlYWN0IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHsgdXNlTWVtbyB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHtcbiAgdHlwZSBDb21tYW5kLFxuICB0eXBlIENvbW1hbmRCYXNlLFxuICB0eXBlIENvbW1hbmRSZXN1bHREaXNwbGF5LFxuICBnZXRDb21tYW5kTmFtZSxcbiAgdHlwZSBQcm9tcHRDb21tYW5kLFxufSBmcm9tICcuLi8uLi9jb21tYW5kcy5qcydcbmltcG9ydCB7IEJveCwgVGV4dCB9IGZyb20gJy4uLy4uL2luay5qcydcbmltcG9ydCB7XG4gIGVzdGltYXRlU2tpbGxGcm9udG1hdHRlclRva2VucyxcbiAgZ2V0U2tpbGxzUGF0aCxcbn0gZnJvbSAnLi4vLi4vc2tpbGxzL2xvYWRTa2lsbHNEaXIuanMnXG5pbXBvcnQgeyBnZXREaXNwbGF5UGF0aCB9IGZyb20gJy4uLy4uL3V0aWxzL2ZpbGUuanMnXG5pbXBvcnQgeyBmb3JtYXRUb2tlbnMgfSBmcm9tICcuLi8uLi91dGlscy9mb3JtYXQuanMnXG5pbXBvcnQge1xuICBnZXRTZXR0aW5nU291cmNlTmFtZSxcbiAgdHlwZSBTZXR0aW5nU291cmNlLFxufSBmcm9tICcuLi8uLi91dGlscy9zZXR0aW5ncy9jb25zdGFudHMuanMnXG5pbXBvcnQgeyBwbHVyYWwgfSBmcm9tICcuLi8uLi91dGlscy9zdHJpbmdVdGlscy5qcydcbmltcG9ydCB7IENvbmZpZ3VyYWJsZVNob3J0Y3V0SGludCB9IGZyb20gJy4uL0NvbmZpZ3VyYWJsZVNob3J0Y3V0SGludC5qcydcbmltcG9ydCB7IERpYWxvZyB9IGZyb20gJy4uL2Rlc2lnbi1zeXN0ZW0vRGlhbG9nLmpzJ1xuXG4vLyBTa2lsbHMgYXJlIGFsd2F5cyBQcm9tcHRDb21tYW5kcyB3aXRoIENvbW1hbmRCYXNlIHByb3BlcnRpZXNcbnR5cGUgU2tpbGxDb21tYW5kID0gQ29tbWFuZEJhc2UgJiBQcm9tcHRDb21tYW5kXG5cbnR5cGUgU2tpbGxTb3VyY2UgPSBTZXR0aW5nU291cmNlIHwgJ3BsdWdpbicgfCAnbWNwJ1xuXG50eXBlIFByb3BzID0ge1xuICBvbkV4aXQ6IChcbiAgICByZXN1bHQ/OiBzdHJpbmcsXG4gICAgb3B0aW9ucz86IHsgZGlzcGxheT86IENvbW1hbmRSZXN1bHREaXNwbGF5IH0sXG4gICkgPT4gdm9pZFxuICBjb21tYW5kczogQ29tbWFuZFtdXG59XG5cbmZ1bmN0aW9uIGdldFNvdXJjZVRpdGxlKHNvdXJjZTogU2tpbGxTb3VyY2UpOiBzdHJpbmcge1xuICBpZiAoc291cmNlID09PSAncGx1Z2luJykge1xuICAgIHJldHVybiAnUGx1Z2luIHNraWxscydcbiAgfVxuICBpZiAoc291cmNlID09PSAnbWNwJykge1xuICAgIHJldHVybiAnTUNQIHNraWxscydcbiAgfVxuICByZXR1cm4gYCR7Y2FwaXRhbGl6ZShnZXRTZXR0aW5nU291cmNlTmFtZShzb3VyY2UpKX0gc2tpbGxzYFxufVxuXG5mdW5jdGlvbiBnZXRTb3VyY2VTdWJ0aXRsZShcbiAgc291cmNlOiBTa2lsbFNvdXJjZSxcbiAgc2tpbGxzOiBTa2lsbENvbW1hbmRbXSxcbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIC8vIE1DUCBza2lsbHMgc2hvdyBzZXJ2ZXIgbmFtZXM7IGZpbGUtYmFzZWQgc2tpbGxzIHNob3cgZmlsZXN5c3RlbSBwYXRocy5cbiAgLy8gU2tpbGwgbmFtZXMgYXJlIGA8c2VydmVyPjo8c2tpbGw+YCwgbm90IGBtY3BfXzxzZXJ2ZXI+X1/igKZgLlxuICBpZiAoc291cmNlID09PSAnbWNwJykge1xuICAgIGNvbnN0IHNlcnZlcnMgPSBbXG4gICAgICAuLi5uZXcgU2V0KFxuICAgICAgICBza2lsbHNcbiAgICAgICAgICAubWFwKHMgPT4ge1xuICAgICAgICAgICAgY29uc3QgaWR4ID0gcy5uYW1lLmluZGV4T2YoJzonKVxuICAgICAgICAgICAgcmV0dXJuIGlkeCA+IDAgPyBzLm5hbWUuc2xpY2UoMCwgaWR4KSA6IG51bGxcbiAgICAgICAgICB9KVx
|