fix(coding-agent): identify user-invoked skills and expose skill directory
User-invoked skills (typed /skill:, steered, follow-up, interrupted/ resumed via compaction, ACP, RPC) only appended a bare "Skill: <path>" line, so the model neither learned the user had invoked that specific skill nor where the skill directory was. Relative paths in skill bodies (scripts/, templates/) could not be resolved. Route all user-invoked paths through a self-identifying, baseDir-aware prompt template; keep hidden autoload skills on the minimal non-user format. Interactive skillCommands now carries the loaded Skill object instead of a bare path so baseDir flows through without reconstruction. The invocation kind defaults to "user" to keep buildSkillPromptMessage source-compatible. Op: correct Restores: spec:user-invoked-skill-prompt-self-identifies-and-exposes-skill-directory
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import type { ImageContent, TextContent } from "@oh-my-pi/pi-ai";
|
||||
import { buildSkillPromptMessage } from "../extensibility/skills";
|
||||
import { type CustomMessage, SKILL_PROMPT_MESSAGE_TYPE, type SkillPromptDetails } from "../session/messages";
|
||||
import type { InteractiveModeContext } from "./types";
|
||||
|
||||
@@ -61,32 +62,19 @@ export async function buildSkillCommandPrompt(
|
||||
): Promise<BuiltSkillCommandPrompt | undefined> {
|
||||
const parsed = parseSkillCommand(text);
|
||||
if (!parsed) return undefined;
|
||||
const skillPath = ctx.skillCommands.get(parsed.commandName);
|
||||
if (!skillPath) return undefined;
|
||||
const skill = ctx.skillCommands.get(parsed.commandName);
|
||||
if (!skill) return undefined;
|
||||
|
||||
const content = await Bun.file(skillPath).text();
|
||||
const body = content.replace(/^---\n[\s\S]*?\n---\n/, "").trim();
|
||||
const metaLines = [`Skill: ${skillPath}`];
|
||||
if (parsed.args) {
|
||||
metaLines.push(`User: ${parsed.args}`);
|
||||
}
|
||||
const message = `${body}\n\n---\n\n${metaLines.join("\n")}`;
|
||||
const textBlock: TextContent = { type: "text", text: message };
|
||||
const promptContent = images && images.length > 0 ? [textBlock, ...images] : message;
|
||||
const skillName = parsed.commandName.slice("skill:".length);
|
||||
const details: SkillPromptDetails = {
|
||||
name: skillName || parsed.commandName,
|
||||
path: skillPath,
|
||||
args: parsed.args || undefined,
|
||||
lineCount: body ? body.split("\n").length : 0,
|
||||
};
|
||||
const built = await buildSkillPromptMessage(skill, parsed.args, "user");
|
||||
const textBlock: TextContent = { type: "text", text: built.message };
|
||||
const promptContent = images && images.length > 0 ? [textBlock, ...images] : built.message;
|
||||
|
||||
return {
|
||||
message: {
|
||||
customType: SKILL_PROMPT_MESSAGE_TYPE,
|
||||
content: promptContent,
|
||||
display: true,
|
||||
details,
|
||||
details: built.details,
|
||||
attribution: "user",
|
||||
},
|
||||
options: { streamingBehavior, queueChipText: text },
|
||||
|
||||
Reference in New Issue
Block a user