|
|
@@ -57,17 +57,26 @@ function isSkillFrontmatter(data: unknown): data is { name: string; description?
|
|
|
)
|
|
|
}
|
|
|
|
|
|
-export const InvalidError = NamedError.create("SkillInvalidError", {
|
|
|
+export class InvalidError extends Schema.TaggedErrorClass<InvalidError>()("SkillInvalidError", {
|
|
|
path: Schema.String,
|
|
|
message: Schema.optional(Schema.String),
|
|
|
issues: Schema.optional(Schema.Array(Issue)),
|
|
|
-})
|
|
|
+}) {}
|
|
|
|
|
|
-export const NameMismatchError = NamedError.create("SkillNameMismatchError", {
|
|
|
+export class NameMismatchError extends Schema.TaggedErrorClass<NameMismatchError>()("SkillNameMismatchError", {
|
|
|
path: Schema.String,
|
|
|
expected: Schema.String,
|
|
|
actual: Schema.String,
|
|
|
-})
|
|
|
+}) {}
|
|
|
+
|
|
|
+export class NotFoundError extends Schema.TaggedErrorClass<NotFoundError>()("Skill.NotFoundError", {
|
|
|
+ name: Schema.String,
|
|
|
+ available: Schema.Array(Schema.String),
|
|
|
+}) {
|
|
|
+ override get message() {
|
|
|
+ return `Skill "${this.name}" not found. Available skills: ${this.available.join(", ") || "none"}`
|
|
|
+ }
|
|
|
+}
|
|
|
|
|
|
type State = {
|
|
|
skills: Record<string, Info>
|
|
|
@@ -86,6 +95,7 @@ type ScanState = {
|
|
|
|
|
|
export interface Interface {
|
|
|
readonly get: (name: string) => Effect.Effect<Info | undefined>
|
|
|
+ readonly require: (name: string) => Effect.Effect<Info, NotFoundError>
|
|
|
readonly all: () => Effect.Effect<Info[]>
|
|
|
readonly dirs: () => Effect.Effect<string[]>
|
|
|
readonly available: (agent?: Agent.Info) => Effect.Effect<Info[]>
|
|
|
@@ -277,6 +287,13 @@ export const layer = Layer.effect(
|
|
|
return s.skills[name]
|
|
|
})
|
|
|
|
|
|
+ const require = Effect.fn("Skill.require")(function* (name: string) {
|
|
|
+ const s = yield* InstanceState.get(state)
|
|
|
+ const info = s.skills[name]
|
|
|
+ if (info) return info
|
|
|
+ return yield* new NotFoundError({ name, available: Object.keys(s.skills).toSorted() })
|
|
|
+ })
|
|
|
+
|
|
|
const all = Effect.fn("Skill.all")(function* () {
|
|
|
const s = yield* InstanceState.get(state)
|
|
|
return Object.values(s.skills)
|
|
|
@@ -293,7 +310,7 @@ export const layer = Layer.effect(
|
|
|
return list.filter((skill) => Permission.evaluate("skill", skill.name, agent.permission).action !== "deny")
|
|
|
})
|
|
|
|
|
|
- return Service.of({ get, all, dirs, available })
|
|
|
+ return Service.of({ get, require, all, dirs, available })
|
|
|
}),
|
|
|
)
|
|
|
|