Skip to content

Commit b6f7fe0

Browse files
committed
fix: address skill tool UI/typing and built-in skill location issues
- Remove <location> from built-in skills in prompt (only show for file-based skills) - Add 'skill' case to ChatRow.tsx for tool approval UI rendering - Add 'skill' to ClineSayTool union type and interface - Update i18n keys from 'instructions' to 'skill'
1 parent 99b424c commit b6f7fe0

File tree

4 files changed

+73
-17
lines changed

4 files changed

+73
-17
lines changed

packages/types/src/vscode-extension-host.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,7 @@ export interface ClineSayTool {
794794
| "imageGenerated"
795795
| "runSlashCommand"
796796
| "updateTodoList"
797+
| "skill"
797798
path?: string
798799
diff?: string
799800
content?: string
@@ -834,6 +835,8 @@ export interface ClineSayTool {
834835
args?: string
835836
source?: string
836837
description?: string
838+
// Properties for skill tool
839+
skill?: string
837840
}
838841

839842
// Must keep in sync with system prompt.

src/core/prompts/sections/skills.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ export async function getSkillsSection(
3333
.map((skill) => {
3434
const name = escapeXml(skill.name)
3535
const description = escapeXml(skill.description)
36-
// Per the Agent Skills integration guidance for filesystem-based agents,
37-
// location should be an absolute path to the SKILL.md file.
38-
const location = escapeXml(skill.path)
39-
return ` <skill>\n <name>${name}</name>\n <description>${description}</description>\n <location>${location}</location>\n </skill>`
36+
// Only include location for file-based skills (not built-in)
37+
// Built-in skills are loaded via the skill tool by name, not by path
38+
const isFileBasedSkill = skill.source !== "built-in" && skill.path !== "built-in"
39+
const locationLine = isFileBasedSkill ? `\n <location>${escapeXml(skill.path)}</location>` : ""
40+
return ` <skill>\n <name>${name}</name>\n <description>${description}</description>${locationLine}\n </skill>`
4041
})
4142
.join("\n")
4243

webview-ui/src/components/chat/ChatRow.tsx

Lines changed: 62 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -661,24 +661,75 @@ export const ChatRowContent = ({
661661
</div>
662662
</>
663663
)
664-
case "fetchInstructions":
664+
case "skill": {
665+
const skillInfo = tool
665666
return (
666667
<>
667668
<div style={headerStyle}>
668-
{toolIcon("file-code")}
669-
<span style={{ fontWeight: "bold" }}>{t("chat:instructions.wantsToFetch")}</span>
669+
{toolIcon("book")}
670+
<span style={{ fontWeight: "bold" }}>
671+
{message.type === "ask" ? t("chat:skill.wantsToLoad") : t("chat:skill.didLoad")}
672+
</span>
670673
</div>
671-
<div className="pl-6">
672-
<CodeAccordian
673-
code={tool.content}
674-
language="markdown"
675-
isLoading={message.partial}
676-
isExpanded={isExpanded}
677-
onToggleExpand={handleToggleExpand}
678-
/>
674+
<div
675+
style={{
676+
marginTop: "4px",
677+
backgroundColor: "var(--vscode-editor-background)",
678+
border: "1px solid var(--vscode-editorGroup-border)",
679+
borderRadius: "4px",
680+
overflow: "hidden",
681+
cursor: "pointer",
682+
}}
683+
onClick={handleToggleExpand}>
684+
<ToolUseBlockHeader
685+
className="group"
686+
style={{
687+
display: "flex",
688+
alignItems: "center",
689+
justifyContent: "space-between",
690+
padding: "10px 12px",
691+
}}>
692+
<div style={{ display: "flex", alignItems: "center", gap: "8px" }}>
693+
<span style={{ fontWeight: "500", fontSize: "var(--vscode-font-size)" }}>
694+
{skillInfo.skill}
695+
</span>
696+
{skillInfo.source && (
697+
<VSCodeBadge style={{ fontSize: "calc(var(--vscode-font-size) - 2px)" }}>
698+
{skillInfo.source}
699+
</VSCodeBadge>
700+
)}
701+
</div>
702+
<span
703+
className={`codicon codicon-chevron-${isExpanded ? "up" : "down"} opacity-0 group-hover:opacity-100 transition-opacity duration-200`}></span>
704+
</ToolUseBlockHeader>
705+
{isExpanded && (skillInfo.args || skillInfo.description) && (
706+
<div
707+
style={{
708+
padding: "12px 16px",
709+
borderTop: "1px solid var(--vscode-editorGroup-border)",
710+
display: "flex",
711+
flexDirection: "column",
712+
gap: "8px",
713+
}}>
714+
{skillInfo.description && (
715+
<div style={{ color: "var(--vscode-descriptionForeground)" }}>
716+
{skillInfo.description}
717+
</div>
718+
)}
719+
{skillInfo.args && (
720+
<div>
721+
<span style={{ fontWeight: "500" }}>Arguments: </span>
722+
<span style={{ color: "var(--vscode-descriptionForeground)" }}>
723+
{skillInfo.args}
724+
</span>
725+
</div>
726+
)}
727+
</div>
728+
)}
679729
</div>
680730
</>
681731
)
732+
}
682733
case "listFilesTopLevel":
683734
return (
684735
<>

webview-ui/src/i18n/locales/en/chat.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,9 @@
199199
"description": "Older messages were removed from the conversation to stay within the context window limit. This is a fast but less context-preserving approach compared to condensation."
200200
}
201201
},
202-
"instructions": {
203-
"wantsToFetch": "Roo wants to fetch detailed instructions to assist with the current task"
202+
"skill": {
203+
"wantsToLoad": "Roo wants to load a skill",
204+
"didLoad": "Roo loaded a skill"
204205
},
205206
"fileOperations": {
206207
"wantsToRead": "Roo wants to read this file",

0 commit comments

Comments
 (0)