feat(coding-agent): make skill invocation messages collapsible
- Add ParsedSkillBlock interface and parseSkillBlock() function - Change skill expansion to use XML-style <skill> tags - Add SkillInvocationMessageComponent for collapsible display - Collapsed: single line with skill name and expand hint - User message rendered separately after skill block Fixes #894
This commit is contained in:
@@ -70,6 +70,33 @@ import { buildSystemPrompt } from "./system-prompt.js";
|
||||
import type { BashOperations } from "./tools/bash.js";
|
||||
import { createAllTools } from "./tools/index.js";
|
||||
|
||||
// ============================================================================
|
||||
// Skill Block Parsing
|
||||
// ============================================================================
|
||||
|
||||
/** Parsed skill block from a user message */
|
||||
export interface ParsedSkillBlock {
|
||||
name: string;
|
||||
location: string;
|
||||
content: string;
|
||||
userMessage: string | undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a skill block from message text.
|
||||
* Returns null if the text doesn't contain a skill block.
|
||||
*/
|
||||
export function parseSkillBlock(text: string): ParsedSkillBlock | null {
|
||||
const match = text.match(/^<skill name="([^"]+)" location="([^"]+)">\n([\s\S]*?)\n<\/skill>(?:\n\n([\s\S]+))?$/);
|
||||
if (!match) return null;
|
||||
return {
|
||||
name: match[1],
|
||||
location: match[2],
|
||||
content: match[3],
|
||||
userMessage: match[4]?.trim() || undefined,
|
||||
};
|
||||
}
|
||||
|
||||
/** Session-specific events that extend the core AgentEvent */
|
||||
export type AgentSessionEvent =
|
||||
| AgentEvent
|
||||
@@ -796,9 +823,8 @@ export class AgentSession {
|
||||
try {
|
||||
const content = readFileSync(skill.filePath, "utf-8");
|
||||
const body = stripFrontmatter(content).trim();
|
||||
const header = `Skill location: ${skill.filePath}\nReferences are relative to ${skill.baseDir}.`;
|
||||
const skillMessage = `${header}\n\n${body}`;
|
||||
return args ? `${skillMessage}\n\n---\n\nUser: ${args}` : skillMessage;
|
||||
const skillBlock = `<skill name="${skill.name}" location="${skill.filePath}">\nReferences are relative to ${skill.baseDir}.\n\n${body}\n</skill>`;
|
||||
return args ? `${skillBlock}\n\n${args}` : skillBlock;
|
||||
} catch (err) {
|
||||
// Emit error like extension commands do
|
||||
this._extensionRunner?.emitError({
|
||||
|
||||
Reference in New Issue
Block a user