@bonnard/agentops
Advanced tools
+45
-13
@@ -157,3 +157,3 @@ #!/usr/bin/env node | ||
| form.append("content", metadata.content); | ||
| form.append("tags", JSON.stringify(metadata.tags)); | ||
| if (metadata.tags !== void 0) form.append("tags", JSON.stringify(metadata.tags)); | ||
| form.append("bundle", new Blob([new Uint8Array(tgz)], { type: "application/gzip" }), "bundle.tgz"); | ||
@@ -731,3 +731,3 @@ const headers = getHeaders(); | ||
| if (!description) throw new Error("Frontmatter must include \"description\""); | ||
| let tags = []; | ||
| let tags; | ||
| if (Array.isArray(fm.tags)) tags = fm.tags.filter((t) => typeof t === "string").map((t) => t.trim()).filter(Boolean); | ||
@@ -753,2 +753,28 @@ else if (typeof fm.tags === "string") tags = fm.tags.split(",").map((t) => t.trim()).filter(Boolean); | ||
| /** | ||
| * Rewrite the frontmatter of an already-extracted SKILL.md, merging the | ||
| * provided updates into the existing YAML block. Used by `install` to sync | ||
| * server-side metadata (e.g. tags edited via the web UI) back into the local | ||
| * file after unpacking the bundle. | ||
| * | ||
| * Only touches the frontmatter — the markdown body is preserved byte-for-byte. | ||
| */ | ||
| function updateSkillMdFrontmatter(skillDir, updates) { | ||
| const filePath = path.join(skillDir, "SKILL.md"); | ||
| if (!fs.existsSync(filePath)) return; | ||
| const match = fs.readFileSync(filePath, "utf-8").match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/); | ||
| if (!match) return; | ||
| const [, fmBlock, body] = match; | ||
| let fm; | ||
| try { | ||
| fm = YAML.parse(fmBlock) ?? {}; | ||
| } catch { | ||
| return; | ||
| } | ||
| if (updates.description !== void 0) fm.description = updates.description; | ||
| if (updates.tags !== void 0) if (updates.tags.length > 0) fm.tags = updates.tags; | ||
| else delete fm.tags; | ||
| const rebuilt = `---\n${YAML.stringify(fm).trimEnd()}\n---\n\n${(body ?? "").replace(/^\n+/, "")}`; | ||
| fs.writeFileSync(filePath, rebuilt); | ||
| } | ||
| /** | ||
| * Find a skill by name and read its SKILL.md. | ||
@@ -913,2 +939,9 @@ * Searches project-level first, then user-level. | ||
| await unpackSkill(tgz, dir); | ||
| try { | ||
| const metaRes = await get(`/api/skills/${encodeURIComponent(name)}`, baseUrl); | ||
| if (metaRes.ok) { | ||
| const meta = await metaRes.json(); | ||
| if (Array.isArray(meta.tags)) updateSkillMdFrontmatter(dir, { tags: meta.tags }); | ||
| } | ||
| } catch {} | ||
| if (downloadedVersion != null) try { | ||
@@ -1031,3 +1064,3 @@ fs.writeFileSync(path.join(dir, ".agentops-version"), `${downloadedVersion}\n`); | ||
| else console.log(pc.dim(`${publishedDate} · ${sizeKb} KB`)); | ||
| if (frontmatter.tags.length > 0) console.log(pc.dim(`[${frontmatter.tags.join(", ")}]`)); | ||
| if (frontmatter.tags && frontmatter.tags.length > 0) console.log(pc.dim(`[${frontmatter.tags.join(", ")}]`)); | ||
| console.log(); | ||
@@ -1115,8 +1148,7 @@ if (frontmatter.description) { | ||
| } | ||
| const title = skillName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" "); | ||
| const dir = scaffoldSkill({ | ||
| name: skillName, | ||
| description: "A brief description of what this skill does and when to use it", | ||
| tags: opts.tags ? opts.tags.split(",").map((t) => t.trim()).filter(Boolean) : void 0, | ||
| content: `# ${title} | ||
| tags: ["example"], | ||
| content: `# ${skillName.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ")} | ||
@@ -1137,6 +1169,6 @@ Describe the skill's purpose and workflow here. | ||
| const scopeLabel = scope.user ? "user" : "project"; | ||
| const tagsHint = opts.tags ? "" : " --tags engineering,testing"; | ||
| console.log(pc.green(`✓ Created ${dir}/SKILL.md (${scopeLabel})`)); | ||
| console.log(pc.dim(` Edit it, add scripts/ or references/ as needed.`)); | ||
| console.log(pc.dim(` Then share with: agentops skills submit ${skillName}${tagsHint}`)); | ||
| console.log(pc.dim(` Update the tags in the frontmatter before submitting.`)); | ||
| console.log(pc.dim(` Then share with: agentops skills submit ${skillName}`)); | ||
| } | ||
@@ -1313,3 +1345,3 @@ //#endregion | ||
| //#region src/commands/submit.ts | ||
| async function submitCommand(name, opts) { | ||
| async function submitCommand(name) { | ||
| if (!loadCredentials()) { | ||
@@ -1339,3 +1371,3 @@ console.log(pc.yellow("Not logged in. Run: agentops login")); | ||
| } | ||
| const tags = opts.tags ? opts.tags.split(",").map((t) => t.trim()).filter(Boolean) : frontmatter.tags; | ||
| const tags = frontmatter.tags; | ||
| console.log(pc.dim(`Packing "${frontmatter.name}"...`)); | ||
@@ -1387,3 +1419,3 @@ let tgz; | ||
| const result = await submitRes.json(); | ||
| const tagList = tags.length > 0 ? ` [${tags.join(", ")}]` : ""; | ||
| const tagList = tags && tags.length > 0 ? ` [${tags.join(", ")}]` : ""; | ||
| const newVersion = result.version ?? result.latestVersion; | ||
@@ -1654,5 +1686,5 @@ if (result.autoPublished) { | ||
| skills.command("installed").description("Show skills installed locally (project + user scopes)").action(installedCommand); | ||
| skills.command("create [name]").description("Scaffold a new skill locally").option("--tags <tags>", "Tags for discovery (comma-separated)").option("--user", "Create at user-level (available in all projects)").option("--project", "Create at project-level (default)").action(createCommand); | ||
| skills.command("create [name]").description("Scaffold a new skill locally").option("--user", "Create at user-level (available in all projects)").option("--project", "Create at project-level (default)").action(createCommand); | ||
| skills.command("check <name>").description("Check a local skill for issues before submitting").action(checkCommand); | ||
| skills.command("submit <name>").description("Publish a skill — creates a new version each time").option("--tags <tags>", "Tags for discovery (comma-separated)").action(submitCommand); | ||
| skills.command("submit <name>").description("Publish a skill — creates a new version each time").action(submitCommand); | ||
| skills.command("history <name>").description("Show version history for a skill").action(historyCommand); | ||
@@ -1659,0 +1691,0 @@ skills.command("rollback <spec>").description("Re-publish an older version as the new latest — use <name>@v<N> (pro+)").action(rollbackCommand); |
+1
-1
| { | ||
| "name": "@bonnard/agentops", | ||
| "version": "0.7.10", | ||
| "version": "0.8.0", | ||
| "type": "module", | ||
@@ -5,0 +5,0 @@ "bin": { |
64321
1.65%1684
1.88%