9p: serve sk/idx as read-only synthetic file

sk/idx is written by rebuildSkillsIdx() at session start but was
invisible via 9P since sk/ reads go through skills.Read() which only
knows skill directories. Add explicit handling in pathType, read, stat,
and directory listing — same pattern as s/idx.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-04-14 14:34:08 +02:00
parent e176e7ef7f
commit 547e0d79dc
1 changed files with 14 additions and 0 deletions

View File

@ -303,6 +303,9 @@ func (s *Server) pathType(path string) string {
return "file"
}
case len(parts) == 2 && parts[0] == "sk":
if parts[1] == "idx" {
return "file"
}
name := strings.TrimSuffix(parts[1], ".md")
if _, err := skills.Read(name); err == nil {
return "file"
@ -599,6 +602,14 @@ func (s *Server) read(cs *connState, fc *plan9.Fcall) *plan9.Fcall {
// Skill files are served via pkg/skills (reads from disk each time).
if strings.HasPrefix(path, "/sk/") {
if pathBase(path) == "idx" {
skillsPath := skills.Dirs()[0]
content, err := os.ReadFile(skillsPath + "/idx")
if err != nil {
return errFcall(fc, err.Error())
}
return s.readSlice(fc, content)
}
name := strings.TrimSuffix(pathBase(path), ".md")
content, err := skills.Read(name)
if err != nil {
@ -1427,6 +1438,7 @@ func (s *Server) readDir(path string, offset uint64, count uint32) []byte {
}
}
} else if path == "/sk" {
dirs = append(dirs, makeDir("idx", "/sk/idx", false, 0444))
for _, m := range skills.List() {
name := m.Name + ".md"
dirs = append(dirs, makeDir(name, "/sk/"+name, false, 0666))
@ -1550,6 +1562,8 @@ func (s *Server) makeStat(path string) plan9.Dir {
mode = 0666
} else if strings.HasPrefix(path, "/pl/") {
mode = 0666
} else if path == "/sk/idx" {
mode = 0444
} else if strings.HasPrefix(path, "/sk/") {
mode = 0666
} else if strings.HasPrefix(path, "/t/") {