'use strict'; var chunkAR7VSXHH_cjs = require('./chunk-AR7VSXHH.cjs'); var chunkKGUHJRHZ_cjs = require('./chunk-KGUHJRHZ.cjs'); var chunkHXICAUTW_cjs = require('./chunk-HXICAUTW.cjs'); var chunkGZ4HWZWE_cjs = require('./chunk-GZ4HWZWE.cjs'); var chunkZ7LCIYK7_cjs = require('./chunk-Z7LCIYK7.cjs'); var chunkG54X6VE6_cjs = require('./chunk-G54X6VE6.cjs'); var chunk64ITUOXI_cjs = require('./chunk-64ITUOXI.cjs'); var v4 = require('zod/v4'); var builderRegistryEntrySchema = v4.z.object({ id: v4.z.literal("skills-sh").describe("Stable registry identifier"), enabled: v4.z.boolean().describe("Whether this registry is enabled in the running deployment"), label: v4.z.string().describe("Human-readable registry name") }); var builderRegistriesResponseSchema = v4.z.object({ registries: v4.z.array(builderRegistryEntrySchema) }); var builderRegistryPathParams = v4.z.object({ registryId: v4.z.string().describe('Registry identifier (e.g. "skills-sh")') }); var builderRegistrySearchQuerySchema = v4.z.object({ q: v4.z.string().describe("Search query"), limit: v4.z.coerce.number().int().min(1).max(100).optional().default(10).describe("Maximum number of results (1-100)") }); var builderRegistryPopularQuerySchema = v4.z.object({ limit: v4.z.coerce.number().int().min(1).max(100).optional().default(10).describe("Maximum number of results (1-100)"), offset: v4.z.coerce.number().int().min(0).optional().default(0).describe("Offset for pagination (must be a multiple of `limit`)") }).refine((args) => args.offset % args.limit === 0, { message: "offset must be a multiple of limit (the upstream registry pages by `limit`)", path: ["offset"] }); var builderRegistryPreviewQuerySchema = v4.z.object({ owner: v4.z.string().describe("GitHub repository owner"), repo: v4.z.string().describe("GitHub repository name"), path: v4.z.string().describe("Skill name within repo") }); var builderRegistryInstallBodySchema = v4.z.object({ owner: v4.z.string().describe("GitHub repository owner"), repo: v4.z.string().describe("GitHub repository name"), skillName: v4.z.string().describe("Skill name from the registry"), visibility: v4.z.enum(["private", "public"]).optional().describe("Visibility for the new stored skill") }); var builderRegistryInstallResponseSchema = v4.z.object({ storedSkillId: v4.z.string().describe("Id of the newly created stored skill"), name: v4.z.string().describe("Resolved skill name"), filesWritten: v4.z.number().describe("Number of files materialized into the skill version snapshot") }); // src/server/handlers/builder-registry.ts var REGISTRY_LABELS = { "skills-sh": "skills.sh" }; async function resolveRegistries(mastra) { const editor = mastra.getEditor(); if (!editor || typeof editor.resolveBuilder !== "function") { return [{ id: "skills-sh", enabled: false, label: REGISTRY_LABELS["skills-sh"] }]; } const builder = await editor.resolveBuilder(); const registries = builder?.getRegistries?.(); return [ { id: "skills-sh", enabled: registries?.skillsSh?.enabled === true, label: REGISTRY_LABELS["skills-sh"] } ]; } async function requireEnabledRegistry(mastra, registryId) { const list = await resolveRegistries(mastra); const match = list.find((r) => r.id === registryId); if (!match || !match.enabled) { throw new chunk64ITUOXI_cjs.HTTPException(404, { message: "Registry not found" }); } } function buildFileTree(files) { const root = []; for (const file of files) { const safePath = chunkAR7VSXHH_cjs.assertSafeFilePath(file.path); const segments = safePath.split("/").filter(Boolean); if (segments.length === 0) continue; let cursor = root; for (let i = 0; i < segments.length - 1; i++) { const segment = segments[i]; let folder = cursor.find((node) => node.type === "folder" && node.name === segment); if (!folder) { folder = { name: segment, type: "folder", children: [] }; cursor.push(folder); } if (!folder.children) folder.children = []; cursor = folder.children; } const fileName = segments[segments.length - 1]; const content = file.encoding === "base64" ? Buffer.from(file.content, "base64").toString("utf-8") : file.content; cursor.push({ name: fileName, type: "file", content }); } return root; } function parseSkillSnapshot(files) { const skillMd = files.find((f) => f.path === "SKILL.md"); if (!skillMd) return null; const raw = skillMd.encoding === "base64" ? Buffer.from(skillMd.content, "base64").toString("utf-8") : skillMd.content; const fmMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/); if (!fmMatch) { return { instructions: raw.trim() }; } const fmBlock = fmMatch[1] ?? ""; const body = fmMatch[2] ?? ""; const frontmatter = {}; for (const line of fmBlock.split(/\r?\n/)) { const m = line.match(/^([A-Za-z0-9_-]+)\s*:\s*(.*)$/); if (!m) continue; const key = m[1]; const value = m[2] ?? ""; if (!key) continue; frontmatter[key] = value.trim().replace(/^["'](.*)["']$/, "$1"); } return { name: frontmatter.name, description: frontmatter.description, instructions: body.trim() }; } var LIST_BUILDER_REGISTRIES_ROUTE = chunkG54X6VE6_cjs.createRoute({ method: "GET", path: "/editor/builder/registries", responseType: "json", responseSchema: builderRegistriesResponseSchema, summary: "List available skill registries", description: "Returns the configured external skill registries and their enabled state.", tags: ["Editor"], requiresAuth: true, requiresPermission: "stored-skills:read", handler: async ({ mastra }) => { try { const registries = await resolveRegistries(mastra); return { registries }; } catch (error) { return chunkZ7LCIYK7_cjs.handleError(error, "Error listing builder registries"); } } }); var BUILDER_REGISTRY_SEARCH_ROUTE = chunkG54X6VE6_cjs.createRoute({ method: "GET", path: "/editor/builder/registries/:registryId/search", responseType: "json", pathParamSchema: builderRegistryPathParams, queryParamSchema: builderRegistrySearchQuerySchema, responseSchema: chunkHXICAUTW_cjs.skillsShSearchResponseSchema, summary: "Search skills in a registry", description: "Proxies a search request to the configured registry to avoid CORS issues.", tags: ["Editor", "Skills"], requiresAuth: true, requiresPermission: "stored-skills:read", handler: async ({ mastra, registryId, q, limit }) => { try { await requireEnabledRegistry(mastra, registryId); return await chunkAR7VSXHH_cjs.searchSkillsSh({ q, limit }); } catch (error) { if (error instanceof chunk64ITUOXI_cjs.HTTPException) throw error; return chunkZ7LCIYK7_cjs.handleError(error, "Error searching registry"); } } }); var BUILDER_REGISTRY_POPULAR_ROUTE = chunkG54X6VE6_cjs.createRoute({ method: "GET", path: "/editor/builder/registries/:registryId/popular", responseType: "json", pathParamSchema: builderRegistryPathParams, queryParamSchema: builderRegistryPopularQuerySchema, responseSchema: chunkHXICAUTW_cjs.skillsShListResponseSchema, summary: "Get popular skills from a registry", description: "Proxies a popular-skills request to the configured registry to avoid CORS issues.", tags: ["Editor", "Skills"], requiresAuth: true, requiresPermission: "stored-skills:read", handler: async ({ mastra, registryId, limit, offset }) => { try { await requireEnabledRegistry(mastra, registryId); return await chunkAR7VSXHH_cjs.getPopularSkillsSh({ limit, offset }); } catch (error) { if (error instanceof chunk64ITUOXI_cjs.HTTPException) throw error; return chunkZ7LCIYK7_cjs.handleError(error, "Error fetching popular skills"); } } }); var BUILDER_REGISTRY_PREVIEW_ROUTE = chunkG54X6VE6_cjs.createRoute({ method: "GET", path: "/editor/builder/registries/:registryId/preview", responseType: "json", pathParamSchema: builderRegistryPathParams, queryParamSchema: builderRegistryPreviewQuerySchema, responseSchema: chunkHXICAUTW_cjs.skillsShPreviewResponseSchema, summary: "Preview a skill from a registry", description: "Fetches the SKILL.md content for a single skill in the configured registry.", tags: ["Editor", "Skills"], requiresAuth: true, requiresPermission: "stored-skills:read", handler: async ({ mastra, registryId, owner, repo, path: skillName }) => { try { await requireEnabledRegistry(mastra, registryId); return await chunkAR7VSXHH_cjs.previewSkillsSh({ owner, repo, skillName }); } catch (error) { if (error instanceof chunk64ITUOXI_cjs.HTTPException) throw error; return chunkZ7LCIYK7_cjs.handleError(error, "Error fetching skill preview"); } } }); var BUILDER_REGISTRY_INSTALL_ROUTE = chunkG54X6VE6_cjs.createRoute({ method: "POST", path: "/editor/builder/registries/:registryId/install", responseType: "json", pathParamSchema: builderRegistryPathParams, bodySchema: builderRegistryInstallBodySchema, responseSchema: builderRegistryInstallResponseSchema, summary: "Install a registry skill into stored skills", description: "Fetches a skill from the configured registry and persists it as a new stored skill.", tags: ["Editor", "Skills"], requiresAuth: true, requiresPermission: "stored-skills:write", handler: async ({ mastra, requestContext, registryId, owner, repo, skillName, visibility: bodyVisibility }) => { try { await requireEnabledRegistry(mastra, registryId); const storage = mastra.getStorage(); if (!storage) { throw new chunk64ITUOXI_cjs.HTTPException(500, { message: "Storage is not configured" }); } const skillStore = await storage.getStore("skills"); if (!skillStore) { throw new chunk64ITUOXI_cjs.HTTPException(500, { message: "Skills storage domain is not available" }); } const result = await chunkAR7VSXHH_cjs.fetchSkillFiles(owner, repo, skillName); if (!result || result.files.length === 0) { throw new chunk64ITUOXI_cjs.HTTPException(404, { message: `Could not find skill "${skillName}" in ${owner}/${repo}.` }); } const safeSkillId = chunkAR7VSXHH_cjs.assertSafeSkillName(result.skillId); const files = buildFileTree(result.files); const snapshot = parseSkillSnapshot(result.files); const resolvedName = snapshot?.name ?? safeSkillId; const description = snapshot?.description ?? `Imported from ${owner}/${repo}`; const id = chunkGZ4HWZWE_cjs.toSlug(resolvedName) || safeSkillId; if (!id) { throw new chunk64ITUOXI_cjs.HTTPException(400, { message: "Could not derive skill ID from registry skill metadata." }); } const existing = await skillStore.getById(id); if (existing) { throw new chunk64ITUOXI_cjs.HTTPException(409, { message: `Skill with id "${id}" already exists.`, // Surface the existing id so the client can deep-link. cause: { storedSkillId: id } }); } const authorId = chunkKGUHJRHZ_cjs.getCallerAuthorId(requestContext) ?? void 0; const visibility = authorId ? bodyVisibility ?? "private" : "public"; const instructions = snapshot?.instructions?.trim() ? snapshot.instructions : description; await skillStore.create({ skill: { id, authorId, visibility, name: resolvedName, description, instructions, files, metadata: { origin: { type: "skills-sh", owner, repo, skillName } } } }); return { storedSkillId: id, name: resolvedName, filesWritten: result.files.length }; } catch (error) { if (error instanceof chunk64ITUOXI_cjs.HTTPException) throw error; return chunkZ7LCIYK7_cjs.handleError(error, "Error installing registry skill"); } } }); exports.BUILDER_REGISTRY_INSTALL_ROUTE = BUILDER_REGISTRY_INSTALL_ROUTE; exports.BUILDER_REGISTRY_POPULAR_ROUTE = BUILDER_REGISTRY_POPULAR_ROUTE; exports.BUILDER_REGISTRY_PREVIEW_ROUTE = BUILDER_REGISTRY_PREVIEW_ROUTE; exports.BUILDER_REGISTRY_SEARCH_ROUTE = BUILDER_REGISTRY_SEARCH_ROUTE; exports.LIST_BUILDER_REGISTRIES_ROUTE = LIST_BUILDER_REGISTRIES_ROUTE; //# sourceMappingURL=chunk-7FIDKZUG.cjs.map //# sourceMappingURL=chunk-7FIDKZUG.cjs.map