fix(frontend): show empty skill export requirements (#5659)

This commit is contained in:
dong 2026-09-22 11:44:43 +08:00 committed by GitHub
parent ef3c1c2aee
commit b200e5b91b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 67 additions and 8 deletions

View File

@ -217,8 +217,11 @@ export default function SkillExportDialog({
{text.exportTools}
</dt>
<dd className="break-words">
{manifest.requirements.allowed_tools?.join(", ") ??
text.exportUndeclared}
{manifest.requirements.allowed_tools === null
? text.exportUndeclared
: manifest.requirements.allowed_tools.length === 0
? text.exportNone
: manifest.requirements.allowed_tools.join(", ")}
</dd>
</div>
<div>
@ -226,12 +229,16 @@ export default function SkillExportDialog({
{text.exportSecrets}
</dt>
<dd className="break-words">
{manifest.requirements.required_secrets
?.map(
(secret) =>
`${secret.name} (${secret.optional ? text.exportOptional : text.exportRequired})`,
)
.join(", ") ?? text.exportUndeclared}
{manifest.requirements.required_secrets === null
? text.exportUndeclared
: manifest.requirements.required_secrets.length === 0
? text.exportNone
: manifest.requirements.required_secrets
.map(
(secret) =>
`${secret.name} (${secret.optional ? text.exportOptional : text.exportRequired})`,
)
.join(", ")}
</dd>
</div>
</dl>

View File

@ -1792,6 +1792,7 @@ export const enUS: Translations = {
exportOptional: "optional",
exportRequired: "required",
exportUndeclared: "Not declared",
exportNone: "None",
exportScope:
"Includes all files inside this skill. Account settings, conversations and history outside the skill folder are excluded. Configure tools and credentials again on the destination.",
exportWarnings: "Check package contents",

View File

@ -1434,6 +1434,7 @@ export interface Translations {
exportOptional: string;
exportRequired: string;
exportUndeclared: string;
exportNone: string;
exportScope: string;
exportWarnings: string;
exportWarningDescription: string;

View File

@ -1683,6 +1683,7 @@ export const zhCN: Translations = {
exportOptional: "可选",
exportRequired: "必需",
exportUndeclared: "未声明",
exportNone: "无",
exportScope:
"包含此技能目录内的全部文件。账号配置、对话和目录外的历史不会导出;目标环境需重新配置工具与凭据。",
exportWarnings: "请检查包内文件",

View File

@ -66,6 +66,55 @@ beforeEach(() => {
afterEach(cleanup);
describe("export dialog lifecycle", () => {
it.each([
{
name: "undeclared",
allowedTools: null,
requiredSecrets: null,
expectedTools: "Not declared",
expectedSecrets: "Not declared",
},
{
name: "explicitly empty",
allowedTools: [],
requiredSecrets: [],
expectedTools: "None",
expectedSecrets: "None",
},
{
name: "declared values",
allowedTools: ["read_file"],
requiredSecrets: [{ name: "API_KEY", optional: false }],
expectedTools: "read_file",
expectedSecrets: "API_KEY (required)",
},
])(
"renders $name requirements",
async ({
allowedTools,
requiredSecrets,
expectedTools,
expectedSecrets,
}) => {
mocks.load.mockResolvedValue({
...manifest,
requirements: {
...manifest.requirements,
allowed_tools: allowedTools,
required_secrets: requiredSecrets,
},
});
render(<SkillExportDialog name="demo" onClose={rs.fn()} />);
await screen.findByText("Declared requirements");
expect(
screen.getByText("Allowed tools").nextElementSibling?.textContent,
).toBe(expectedTools);
expect(
screen.getByText("Credential names").nextElementSibling?.textContent,
).toBe(expectedSecrets);
},
);
it("pages the file list and distinguishes undeclared dependencies", async () => {
render(<SkillExportDialog name="demo" onClose={rs.fn()} />);
await screen.findByText("DEMO_KEY (optional)");