fix(skill): allow missing descriptions (#26391)
This commit is contained in:
@@ -27,7 +27,7 @@ const SKILL_PATTERN = "**/SKILL.md"
|
|||||||
|
|
||||||
export const Info = Schema.Struct({
|
export const Info = Schema.Struct({
|
||||||
name: Schema.String,
|
name: Schema.String,
|
||||||
description: Schema.String,
|
description: Schema.optional(Schema.String),
|
||||||
location: Schema.String,
|
location: Schema.String,
|
||||||
content: Schema.String,
|
content: Schema.String,
|
||||||
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
}).pipe(withStatics((s) => ({ zod: zod(s) })))
|
||||||
@@ -93,7 +93,7 @@ const add = Effect.fnUntraced(function* (state: State, match: string, bus: Bus.I
|
|||||||
|
|
||||||
if (!md) return
|
if (!md) return
|
||||||
|
|
||||||
const parsed = z.object({ name: z.string(), description: z.string() }).safeParse(md.data)
|
const parsed = z.object({ name: z.string(), description: z.string().optional() }).safeParse(md.data)
|
||||||
if (!parsed.success) return
|
if (!parsed.success) return
|
||||||
|
|
||||||
if (state.skills[parsed.data.name]) {
|
if (state.skills[parsed.data.name]) {
|
||||||
@@ -269,12 +269,13 @@ export const defaultLayer = layer.pipe(
|
|||||||
)
|
)
|
||||||
|
|
||||||
export function fmt(list: Info[], opts: { verbose: boolean }) {
|
export function fmt(list: Info[], opts: { verbose: boolean }) {
|
||||||
if (list.length === 0) return "No skills are currently available."
|
const described = list.filter((skill) => skill.description !== undefined)
|
||||||
|
if (described.length === 0) return "No skills are currently available."
|
||||||
if (opts.verbose) {
|
if (opts.verbose) {
|
||||||
return [
|
return [
|
||||||
"<available_skills>",
|
"<available_skills>",
|
||||||
...list
|
...described
|
||||||
.sort((a, b) => a.name.localeCompare(b.name))
|
.toSorted((a, b) => a.name.localeCompare(b.name))
|
||||||
.flatMap((skill) => [
|
.flatMap((skill) => [
|
||||||
" <skill>",
|
" <skill>",
|
||||||
` <name>${skill.name}</name>`,
|
` <name>${skill.name}</name>`,
|
||||||
@@ -288,7 +289,7 @@ export function fmt(list: Info[], opts: { verbose: boolean }) {
|
|||||||
|
|
||||||
return [
|
return [
|
||||||
"## Available Skills",
|
"## Available Skills",
|
||||||
...list
|
...described
|
||||||
.toSorted((a, b) => a.name.localeCompare(b.name))
|
.toSorted((a, b) => a.name.localeCompare(b.name))
|
||||||
.map((skill) => `- **${skill.name}**: ${skill.description}`),
|
.map((skill) => `- **${skill.name}**: ${skill.description}`),
|
||||||
].join("\n")
|
].join("\n")
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ const skills: Skill.Info[] = [
|
|||||||
location: "/tmp/middle-skill/SKILL.md",
|
location: "/tmp/middle-skill/SKILL.md",
|
||||||
content: "# middle-skill",
|
content: "# middle-skill",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "manual-skill",
|
||||||
|
location: "/tmp/manual-skill/SKILL.md",
|
||||||
|
content: "# manual-skill",
|
||||||
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
const build: Agent.Info = {
|
const build: Agent.Info = {
|
||||||
@@ -68,6 +73,7 @@ describe("session.system", () => {
|
|||||||
expect(alpha).toBeGreaterThan(-1)
|
expect(alpha).toBeGreaterThan(-1)
|
||||||
expect(middle).toBeGreaterThan(alpha)
|
expect(middle).toBeGreaterThan(alpha)
|
||||||
expect(zeta).toBeGreaterThan(middle)
|
expect(zeta).toBeGreaterThan(middle)
|
||||||
|
expect(output).not.toContain("manual-skill")
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -163,6 +163,37 @@ Just some content without YAML frontmatter.
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
it.live("discovers skills without descriptions", () =>
|
||||||
|
provideTmpdirInstance(
|
||||||
|
(dir) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
yield* Effect.promise(() =>
|
||||||
|
Bun.write(
|
||||||
|
path.join(dir, ".opencode", "skill", "manual-skill", "SKILL.md"),
|
||||||
|
`---
|
||||||
|
name: manual-skill
|
||||||
|
---
|
||||||
|
|
||||||
|
# Manual Skill
|
||||||
|
|
||||||
|
Instructions here.
|
||||||
|
`,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
const skill = yield* Skill.Service
|
||||||
|
const list = yield* skill.all()
|
||||||
|
expect(list.length).toBe(1)
|
||||||
|
const item = list.find((x) => x.name === "manual-skill")
|
||||||
|
expect(item).toBeDefined()
|
||||||
|
expect(item!.description).toBeUndefined()
|
||||||
|
expect(Skill.fmt(list, { verbose: false })).toBe("No skills are currently available.")
|
||||||
|
expect(Skill.fmt(list, { verbose: true })).toBe("No skills are currently available.")
|
||||||
|
}),
|
||||||
|
{ git: true },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
it.live("discovers skills from .claude/skills/ directory", () =>
|
it.live("discovers skills from .claude/skills/ directory", () =>
|
||||||
provideTmpdirInstance(
|
provideTmpdirInstance(
|
||||||
(dir) =>
|
(dir) =>
|
||||||
|
|||||||
@@ -4195,7 +4195,7 @@ export type AppSkillsResponses = {
|
|||||||
*/
|
*/
|
||||||
200: Array<{
|
200: Array<{
|
||||||
name: string
|
name: string
|
||||||
description: string
|
description?: string
|
||||||
location: string
|
location: string
|
||||||
content: string
|
content: string
|
||||||
}>
|
}>
|
||||||
|
|||||||
Reference in New Issue
Block a user