agents
Version:
A home for your AI agents
94 lines (93 loc) • 3.2 kB
JavaScript
import { i as renderSkillResource } from "../../catalog-BpOejOsE.js";
import { tool } from "ai";
import { z } from "zod";
//#region src/skills/tools/ai-sdk.ts
/**
* Build AI SDK tools for a catalog: `activate_skill`, `read_skill_resource`,
* and, with a script runner, `run_skill_script`.
*
* Failures (an unknown skill, a missing file) are thrown, so the AI SDK
* returns them to the model as tool errors.
*
* @param catalog - The catalog to expose. Build tools again after reloading it.
* @param options - Optional script runner.
* @returns The tools, or an empty set when the catalog has no skills.
*/
function createSkillTools(catalog, options = {}) {
const [first, ...rest] = catalog.skills.map((entry) => entry.skill.name);
if (first === void 0) return {};
const nameSchema = z.enum([first, ...rest]);
const tools = {
activate_skill: tool({
description: "Activate a skill by name. Use this when the user's task matches one of the available skills.",
inputSchema: z.object({ name: nameSchema }),
execute: async ({ name }) => {
const activated = catalog.activate(name);
if (!activated.ok) throw activated.error;
return activated.value;
}
}),
read_skill_resource: tool({
description: "Read a bundled resource from an available skill by relative path. Pass name and path, or use a qualified path like skill-name/references/file.md.",
inputSchema: z.object({
name: nameSchema.optional(),
path: z.string().min(1)
}),
execute: async ({ name, path }) => {
const read = await catalog.readResource(name === void 0 ? { path } : {
name,
path
});
if (!read.ok) throw read.error;
return renderSkillResource(read.value);
}
})
};
const runner = options.scriptRunner;
if (runner) tools.run_skill_script = tool({
description: "Run a bundled script resource from an available skill. Use only when a skill instructs you to run a script.",
inputSchema: z.object({
name: nameSchema,
path: z.string().min(1),
input: z.unknown().default({})
}),
execute: async ({ name, path, input }) => {
const script = await catalog.readResource({
name,
path
});
if (!script.ok) throw script.error;
const { entry, resource } = script.value;
if (resource.kind !== "script") throw new Error(`Resource is not a script: ${name}/${path}`);
if (resource.encoding !== "text") throw new Error(`Script resource must be text: ${name}/${path}`);
const files = [];
for (const info of entry.resources) {
const read = await catalog.readResource({
name,
path: info.path
});
if (read.ok) files.push({
path: read.value.resource.path,
content: read.value.resource.content,
encoding: read.value.resource.encoding,
kind: read.value.resource.kind
});
}
try {
return await runner.run({
skill: entry.skill,
path: resource.path,
source: resource.content,
input,
resources: files
});
} catch (error) {
throw new Error(`Skill script failed: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
}
}
});
return tools;
}
//#endregion
export { createSkillTools };
//# sourceMappingURL=ai-sdk.js.map