From 9cd60a253451aa7c9e5825c6bd3a97d67fbfaa5c Mon Sep 17 00:00:00 2001 From: GRayHook Date: Wed, 17 Jun 2026 10:23:51 +0700 Subject: [PATCH] =?UTF-8?q?Phase=203:=20add=20matchReadPathToSkill=20?= =?UTF-8?q?=E2=80=94=20read=20tool=20path=20to=20skill=20mapping.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Match read paths against registered SKILL.md filePath for the read tracking source. Co-authored-by: Cursor --- src/detect.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/detect.ts b/src/detect.ts index cbaa480..54e1882 100644 --- a/src/detect.ts +++ b/src/detect.ts @@ -1,3 +1,6 @@ +import { isAbsolute, normalize, resolve } from "node:path"; +import type { Skill } from "@earendil-works/pi-coding-agent"; + /** Raw `/skill:name` at start of user input (SPEC §6.2 #1). */ const SLASH_SKILL_RE = /^\/skill:([a-z0-9-]+)/; @@ -11,6 +14,13 @@ export interface ParsedSkillBlock { content: string; } +/** Minimal skill fields for read-path matching (SPEC §6.2 #3). */ +export type SkillPathMeta = Pick; + +function normalizePathForCompare(filePath: string): string { + return normalize(filePath); +} + /** Returns skill name when text is a slash skill command, else null. */ export function detectSlashSkill(text: string): string | null { const match = SLASH_SKILL_RE.exec(text); @@ -29,3 +39,24 @@ export function parseSkillBlocksFromText(text: string): ParsedSkillBlock[] { } return blocks; } + +/** Match read tool path to a registered skill SKILL.md (SPEC §6.2 #3). */ +export function matchReadPathToSkill( + path: string, + skills: readonly SkillPathMeta[], +): SkillPathMeta | null { + const normalizedPath = normalizePathForCompare(path); + for (const skill of skills) { + const skillPath = normalizePathForCompare(skill.filePath); + if (normalizedPath === skillPath) { + return skill; + } + if (!isAbsolute(path)) { + const resolvedFromBase = normalizePathForCompare(resolve(skill.baseDir, path)); + if (resolvedFromBase === skillPath) { + return skill; + } + } + } + return null; +}