feat(ui): Control UI polish — skills revamp, markdown preview, agent workspace, macOS config tree (#53411) thanks @BunsDev

Co-authored-by: BunsDev <68980965+BunsDev@users.noreply.github.com>
Co-authored-by: Nova <nova@openknot.ai>
This commit is contained in:
Val Alexander
2026-03-24 01:21:13 -05:00
parent ecb3aa7fe0
commit a710366e9e
40 changed files with 1534 additions and 662 deletions

View File

@@ -36,7 +36,7 @@ function formatSkillStatus(skill: SkillStatusEntry): string {
if (skill.blockedByAllowlist) {
return theme.warn("🚫 blocked");
}
return theme.error("✗ missing");
return theme.warn("△ needs setup");
}
function normalizeSkillEmoji(emoji?: string): string {
@@ -192,7 +192,7 @@ export function formatSkillInfo(
? theme.warn("⏸ Disabled")
: skill.blockedByAllowlist
? theme.warn("🚫 Blocked by allowlist")
: theme.error("✗ Missing requirements");
: theme.warn("△ Needs setup");
lines.push(`${emoji} ${theme.heading(skill.name)} ${status}`);
lines.push("");
@@ -265,6 +265,23 @@ export function formatSkillInfo(
}
}
if (skill.primaryEnv && skill.missing.env.includes(skill.primaryEnv)) {
lines.push("");
lines.push(theme.heading("API key setup:"));
if (skill.homepage) {
lines.push(` Get your key: ${skill.homepage}`);
}
lines.push(
` Save via UI: ${theme.muted("Control UI → Skills → ")}${skill.name}${theme.muted(" → Save key")}`,
);
lines.push(
` Save via CLI: ${formatCliCommand(`openclaw config set skills.entries.${skill.skillKey}.apiKey YOUR_KEY`)}`,
);
lines.push(
` Stored in: ${theme.muted("~/.openclaw/openclaw.json")} ${theme.muted(`(skills.entries.${skill.skillKey}.apiKey)`)}`,
);
}
return appendClawHubHint(lines.join("\n"), opts.json);
}

View File

@@ -90,7 +90,7 @@ describe("skills-cli", () => {
]);
const output = formatSkillsList(report, { verbose: true });
expect(output).toContain("needs-stuff");
expect(output).toContain("missing");
expect(output).toContain("needs setup");
expect(output).toContain("anyBins");
expect(output).toContain("os:");
});