chore: import upstream snapshot with attribution
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / results (push) Has been cancelled
CI / deadcode (push) Has been cancelled
CI / e2e-live (push) Has been cancelled

This commit is contained in:
wehub-resource-sync
2026-07-13 12:22:54 +08:00
commit bf9395e022
2349 changed files with 588574 additions and 0 deletions
+209
View File
@@ -0,0 +1,209 @@
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
// Package skillcontent reads embedded skill content from an injected fs.FS
// rooted at the skill list (entries like "lark-calendar/SKILL.md").
package skillcontent
import (
"io/fs"
"path"
"sort"
"strings"
"github.com/larksuite/cli/errs"
"gopkg.in/yaml.v3"
)
type Reader struct {
fsys fs.FS
}
func New(fsys fs.FS) *Reader { return &Reader{fsys: fsys} }
type SkillInfo struct {
Name string `json:"name"`
Description string `json:"description"`
Version string `json:"version,omitempty"`
Metadata map[string]any `json:"metadata,omitempty"`
}
// DirEntry.Path is skill-prefixed (e.g. "lark-doc/references/x.md") so it can be
// fed straight back into `read`.
type DirEntry struct {
Path string `json:"path"`
IsDir bool `json:"is_dir"`
}
func (r *Reader) List() ([]SkillInfo, error) {
entries, err := fs.ReadDir(r.fsys, ".")
if err != nil {
return nil, errs.NewInternalError(errs.SubtypeFileIO, "failed to read embedded skills: %v", err)
}
out := make([]SkillInfo, 0, len(entries))
for _, e := range entries {
if !e.IsDir() {
continue
}
// Skip dirs that aren't real skills (no SKILL.md).
if info, ok := r.skillInfo(e.Name()); ok {
out = append(out, info)
}
}
sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name })
return out, nil
}
func (r *Reader) skillInfo(name string) (SkillInfo, bool) {
data, err := fs.ReadFile(r.fsys, name+"/SKILL.md")
if err != nil {
return SkillInfo{}, false
}
desc, version, metadata := parseFrontmatter(data)
return SkillInfo{Name: name, Description: desc, Version: version, Metadata: metadata}, true
}
// ListPath lists one directory layer (no recursion) under "<name>" or
// "<name>/<sub>", returning the entries and the cleaned path listed.
func (r *Reader) ListPath(arg string) ([]DirEntry, string, error) {
name, sub := SplitArg(arg)
if err := r.ensureSkill(name); err != nil {
return nil, "", err
}
dir := name
if sub != "" {
cleaned, err := cleanSubPath(sub)
if err != nil {
return nil, "", err
}
dir = name + "/" + cleaned
info, err := fs.Stat(r.fsys, dir)
if err != nil {
return nil, "", errs.NewValidationError(errs.SubtypeInvalidArgument,
"path %q not found in skill %q", sub, name).
WithHint("run 'lark-cli skills list " + name + "' to see files in this skill")
}
if !info.IsDir() {
return nil, "", errs.NewValidationError(errs.SubtypeInvalidArgument,
"path %q is a file, not a directory; use 'lark-cli skills read %s/%s' to read it", sub, name, cleaned)
}
}
entries, err := fs.ReadDir(r.fsys, dir)
if err != nil {
return nil, "", errs.NewInternalError(errs.SubtypeFileIO,
"failed to read embedded skill content: %v", err)
}
out := make([]DirEntry, 0, len(entries))
for _, e := range entries {
out = append(out, DirEntry{Path: dir + "/" + e.Name(), IsDir: e.IsDir()})
}
sort.Slice(out, func(i, j int) bool { return out[i].Path < out[j].Path })
return out, dir, nil
}
// SplitArg splits "<name>/<rest>" at the first separator; an argument with no
// separator is a bare skill name (rest "").
func SplitArg(arg string) (name, rest string) {
name, rest, _ = strings.Cut(arg, "/")
return name, rest
}
// parseFrontmatter best-effort-extracts the frontmatter fields; missing or
// unparseable frontmatter yields ("", "", nil), never an error.
func parseFrontmatter(skillMD []byte) (description, version string, metadata map[string]any) {
lines := strings.Split(string(skillMD), "\n")
if strings.TrimRight(lines[0], "\r") != "---" {
return "", "", nil
}
block := make([]string, 0, len(lines))
closed := false
for _, ln := range lines[1:] {
if strings.TrimRight(ln, "\r") == "---" {
closed = true
break
}
block = append(block, ln)
}
if !closed {
return "", "", nil
}
var fm struct {
Description string `yaml:"description"`
Version string `yaml:"version"`
Metadata map[string]any `yaml:"metadata"`
}
if err := yaml.Unmarshal([]byte(strings.Join(block, "\n")), &fm); err != nil {
return "", "", nil
}
return fm.Description, fm.Version, fm.Metadata
}
func (r *Reader) ReadSkill(name string) ([]byte, error) {
if err := r.ensureSkill(name); err != nil {
return nil, err
}
data, err := fs.ReadFile(r.fsys, name+"/SKILL.md")
if err != nil {
return nil, errs.NewInternalError(errs.SubtypeFileIO,
"failed to read embedded skill content: %v", err)
}
return data, nil
}
func (r *Reader) ensureSkill(name string) error {
if name == "" || strings.ContainsAny(name, `/\`) || name == "." || name == ".." {
return unknownSkill(name)
}
info, err := fs.Stat(r.fsys, name)
if err != nil || !info.IsDir() {
return unknownSkill(name)
}
return nil
}
func unknownSkill(name string) error {
return errs.NewValidationError(errs.SubtypeInvalidArgument, "unknown skill %q", name).
WithHint("run 'lark-cli skills list' to see available skills")
}
// cleanSubPath returns the cleaned form of relpath, rejecting absolute paths and
// ".." escapes. relpath must be non-empty (callers handle the skill-root case).
func cleanSubPath(relpath string) (string, error) {
cleaned := path.Clean(relpath)
// path.Clean only treats '/' as a separator, so a Windows-style "..\" prefix
// survives; reject it explicitly alongside "../".
if relpath == "" || path.IsAbs(relpath) || cleaned == "." ||
cleaned == ".." || strings.HasPrefix(cleaned, "../") || strings.HasPrefix(cleaned, `..\`) {
return "", errs.NewValidationError(errs.SubtypeInvalidArgument,
"invalid path %q: must be a relative path without '..'", relpath)
}
return cleaned, nil
}
// ReadReference returns the bytes of <name>/<relpath> and the cleaned path.
func (r *Reader) ReadReference(name, relpath string) ([]byte, string, error) {
if err := r.ensureSkill(name); err != nil {
return nil, "", err
}
cleaned, err := cleanSubPath(relpath)
if err != nil {
return nil, "", err
}
full := name + "/" + cleaned
info, err := fs.Stat(r.fsys, full)
if err != nil {
return nil, "", errs.NewValidationError(errs.SubtypeInvalidArgument,
"reference %q not found in skill %q", relpath, name).
WithHint("run 'lark-cli skills list " + name + "' to see files in this skill")
}
if info.IsDir() {
return nil, "", errs.NewValidationError(errs.SubtypeInvalidArgument,
"reference %q is a directory, not a file", relpath)
}
data, err := fs.ReadFile(r.fsys, full)
if err != nil {
return nil, "", errs.NewInternalError(errs.SubtypeFileIO,
"failed to read embedded skill content: %v", err)
}
return data, cleaned, nil
}
+290
View File
@@ -0,0 +1,290 @@
// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package skillcontent
import (
"errors"
"strings"
"testing"
"testing/fstest"
"github.com/larksuite/cli/errs"
)
func testFS() fstest.MapFS {
return fstest.MapFS{
"lark-calendar/SKILL.md": {Data: []byte("---\nname: lark-calendar\nversion: 1.0.0\ndescription: \"Calendar skill\"\nmetadata:\n requires:\n bins: [\"lark-cli\"]\n cliHelp: \"lark-cli calendar --help\"\n---\nbody\n")},
"lark-calendar/references/agenda.md": {Data: []byte("# Agenda")},
"lark-calendar/references/create.md": {Data: []byte("# Create")},
"lark-calendar/assets/tpl.html": {Data: []byte("<html></html>")},
"lark-im/SKILL.md": {Data: []byte("no frontmatter here\n")},
"lark-im/references/send.md": {Data: []byte("# Send")},
}
}
func TestList(t *testing.T) {
r := New(testFS())
skills, err := r.List()
if err != nil {
t.Fatalf("List() error: %v", err)
}
if len(skills) != 2 {
t.Fatalf("got %d skills, want 2", len(skills))
}
if skills[0].Name != "lark-calendar" || skills[1].Name != "lark-im" {
t.Fatalf("skills not sorted by name: %v", skills)
}
if skills[0].Description != "Calendar skill" {
t.Errorf("description: got %q, want %q", skills[0].Description, "Calendar skill")
}
// version is the frontmatter `version:` field, passed through for drift checks.
if skills[0].Version != "1.0.0" {
t.Errorf("version: got %q, want %q", skills[0].Version, "1.0.0")
}
// metadata is the frontmatter `metadata:` block, passed through verbatim.
if skills[0].Metadata == nil {
t.Fatal("expected metadata for lark-calendar")
}
if skills[0].Metadata["cliHelp"] != "lark-cli calendar --help" {
t.Errorf("metadata.cliHelp: got %v", skills[0].Metadata["cliHelp"])
}
// No frontmatter → empty description and nil metadata (omitted from JSON).
if skills[1].Description != "" {
t.Errorf("lark-im description: got %q, want empty", skills[1].Description)
}
if skills[1].Metadata != nil {
t.Errorf("lark-im metadata: got %v, want nil", skills[1].Metadata)
}
if skills[1].Version != "" {
t.Errorf("lark-im version: got %q, want empty", skills[1].Version)
}
}
func TestListPath(t *testing.T) {
r := New(testFS())
// Skill root: direct children only (one layer), each path skill-prefixed.
entries, listed, err := r.ListPath("lark-calendar")
if err != nil {
t.Fatalf("ListPath root error: %v", err)
}
if listed != "lark-calendar" {
t.Errorf("listed path: got %q", listed)
}
want := map[string]bool{ // path → isDir
"lark-calendar/SKILL.md": false,
"lark-calendar/references": true,
"lark-calendar/assets": true,
}
if len(entries) != len(want) {
t.Fatalf("root entries: got %v, want %d entries", entries, len(want))
}
for _, e := range entries {
isDir, ok := want[e.Path]
if !ok {
t.Errorf("unexpected entry %q", e.Path)
continue
}
if e.IsDir != isDir {
t.Errorf("%q is_dir: got %v, want %v", e.Path, e.IsDir, isDir)
}
}
// Entries are sorted by path.
if entries[0].Path != "lark-calendar/SKILL.md" {
t.Errorf("entries not sorted: %v", entries)
}
// Subdirectory: one layer under <name>/<subpath>.
subEntries, subListed, err := r.ListPath("lark-calendar/references")
if err != nil {
t.Fatalf("ListPath subdir error: %v", err)
}
if subListed != "lark-calendar/references" {
t.Errorf("listed subpath: got %q", subListed)
}
if len(subEntries) != 2 ||
subEntries[0].Path != "lark-calendar/references/agenda.md" ||
subEntries[1].Path != "lark-calendar/references/create.md" {
t.Errorf("subdir entries: got %v", subEntries)
}
// Unknown skill → typed validation error.
if _, _, err := r.ListPath("no-such-skill"); err == nil {
t.Error("expected error for unknown skill")
} else {
var verr *errs.ValidationError
if !errors.As(err, &verr) {
t.Errorf("expected *errs.ValidationError, got %T", err)
}
}
// Path that points at a file (not a dir) → validation error.
if _, _, err := r.ListPath("lark-calendar/SKILL.md"); err == nil {
t.Error("expected error listing a file")
} else if !strings.Contains(err.Error(), "is a file") {
t.Errorf("message: got %q", err.Error())
}
// Nonexistent subpath → validation error.
if _, _, err := r.ListPath("lark-calendar/nope"); err == nil {
t.Error("expected not-found error")
} else if !strings.Contains(err.Error(), "not found") {
t.Errorf("message: got %q", err.Error())
}
// Traversal in the subpath is rejected, no listing leaked.
for _, bad := range []string{"lark-calendar/../lark-im", "lark-calendar/../../etc", `lark-calendar/..\x`} {
entries, _, err := r.ListPath(bad)
if err == nil {
t.Errorf("expected rejection for %q", bad)
}
if entries != nil {
t.Errorf("entries leaked for %q: %v", bad, entries)
}
}
}
func TestReadSkill(t *testing.T) {
r := New(testFS())
data, err := r.ReadSkill("lark-calendar")
if err != nil {
t.Fatalf("ReadSkill error: %v", err)
}
if !strings.HasPrefix(string(data), "---\nname: lark-calendar") {
t.Errorf("unexpected content: %q", string(data))
}
_, err = r.ReadSkill("no-such-skill")
if err == nil {
t.Fatal("expected error for unknown skill")
}
var verr *errs.ValidationError
if !errors.As(err, &verr) {
t.Fatalf("expected *errs.ValidationError, got %T", err)
}
if !strings.Contains(verr.Message, `unknown skill "no-such-skill"`) {
t.Errorf("message: got %q", verr.Message)
}
if _, err := r.ReadSkill("../etc"); err == nil {
t.Error("expected error for name with separator")
}
}
func TestReadReference(t *testing.T) {
r := New(testFS())
data, cleaned, err := r.ReadReference("lark-calendar", "references/agenda.md")
if err != nil {
t.Fatalf("ReadReference error: %v", err)
}
if string(data) != "# Agenda" {
t.Errorf("content: got %q", string(data))
}
if cleaned != "references/agenda.md" {
t.Errorf("cleaned path: got %q", cleaned)
}
if _, _, err := r.ReadReference("lark-calendar", "references/nope.md"); err == nil {
t.Error("expected not-found error")
} else if !strings.Contains(err.Error(), "not found") {
t.Errorf("message: got %q", err.Error())
}
if _, _, err := r.ReadReference("lark-calendar", "references"); err == nil {
t.Error("expected directory error")
} else if !strings.Contains(err.Error(), "is a directory") {
t.Errorf("message: got %q", err.Error())
}
for _, bad := range []string{"../../etc/passwd", "/etc/passwd", "..", "", "references/../../im/SKILL.md", `..\..\x`} {
data, _, err := r.ReadReference("lark-calendar", bad)
if err == nil {
t.Errorf("expected rejection for %q", bad)
}
if data != nil {
t.Errorf("content leaked for %q: %q", bad, string(data))
}
var verr *errs.ValidationError
if !errors.As(err, &verr) {
t.Errorf("expected validation error for %q, got %T", bad, err)
}
}
}
func TestParseFrontmatter(t *testing.T) {
cases := []struct {
name string
input string
wantDesc string
wantVer string
wantHasMeta bool
}{
{
name: "description, version and metadata",
input: "---\ndescription: My skill\nversion: 2.1.0\nmetadata:\n cliHelp: \"x\"\n---\nbody\n",
wantDesc: "My skill",
wantVer: "2.1.0",
wantHasMeta: true,
},
{
name: "description only, no metadata",
input: "---\ndescription: Plain\n---\nbody\n",
wantDesc: "Plain",
},
{
name: "no frontmatter",
input: "no frontmatter here\n",
},
{
name: "unclosed frontmatter",
input: "---\ndescription: Never closed\n",
},
{
name: "malformed YAML inside frontmatter",
input: "---\n: bad: yaml: [\n---\nbody\n",
},
{
name: "CRLF line endings",
input: "---\r\ndescription: CRLF skill\r\nmetadata:\r\n cliHelp: \"y\"\r\n---\r\nbody\r\n",
wantDesc: "CRLF skill",
wantHasMeta: true,
},
{
name: "empty input",
input: "",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
desc, ver, meta := parseFrontmatter([]byte(tc.input))
if desc != tc.wantDesc {
t.Errorf("description = %q, want %q", desc, tc.wantDesc)
}
if ver != tc.wantVer {
t.Errorf("version = %q, want %q", ver, tc.wantVer)
}
if (meta != nil) != tc.wantHasMeta {
t.Errorf("metadata = %v, wantHasMeta %v", meta, tc.wantHasMeta)
}
})
}
}
func TestReadSkillMissingFile(t *testing.T) {
// Use a separate MapFS so testFS() (and TestList) are unaffected.
emptyFS := fstest.MapFS{
"lark-empty/references/x.md": {Data: []byte("# X")},
}
r := New(emptyFS)
_, err := r.ReadSkill("lark-empty")
if err == nil {
t.Fatal("expected error when SKILL.md is absent")
}
var ierr *errs.InternalError
if !errors.As(err, &ierr) {
t.Fatalf("expected *errs.InternalError, got %T: %v", err, err)
}
}