You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(market): workflow publishing UI across webview, CLI, and MCP tool (#88)
Wires a kind toggle + required-skills picker through the shared
publishSkill message, the host routing in env.ts, and every UI surface.
The chain layer (publishWorkflow, publishItemIx) already existed; the
gap was purely contract + UI. Also fixes publishWorkflow() to
synthesize frontmatter from separate fields (mirroring publishSkill),
so a clean form needs no hand-typed YAML, and extends the agent-facing
publish_skill MCP tool to route to publishWorkflow when requiredSkills
is non-empty.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
"Publish a new skill to the marketplace: mint it as a soulbound Token-2022 NFT and store the SKILL.md body on-chain (you, the creator, auto-receive 1 copy). This is the raw publish action — it does NOT decide WHETHER something is worth becoming a skill; call it once you've authored the SKILL.md content and chosen a name/price.",
229
+
"Publish a new skill OR workflow to the marketplace: mint it as a soulbound Token-2022 NFT and store the SKILL.md body on-chain (you, the creator, auto-receive 1 copy). Pass requiredSkills (non-empty) to publish a WORKFLOW instead of a plain skill — a workflow gates its mint on the buyer holding every listed prerequisite skill. This is the raw publish action — it does NOT decide WHETHER something is worth becoming a skill/workflow; call it once you've authored the SKILL.md content and chosen a name/price.",
229
230
schema: {
230
-
name: z.string().describe("Short skill name / slug, e.g. 'clean-code-refactor'."),
231
-
description: z.string().describe("One or two lines on what the skill does."),
232
-
text: z.string().describe("The full SKILL.md body the agent reads when this skill fires."),
231
+
name: z.string().describe("Short skill/workflow name / slug, e.g. 'clean-code-refactor'."),
232
+
description: z.string().describe("One or two lines on what it does."),
233
+
text: z.string().describe("The full SKILL.md body the agent reads when this fires."),
233
234
category: z.string().optional().describe("Optional single category, e.g. 'clean-code'."),
234
235
hashtags: z.array(z.string()).optional().describe("Optional tags, e.g. ['refactoring','testing']."),
235
236
priceSol: z.string().optional().describe("Price in SOL a buyer pays (e.g. '0.1'). Use '0' for a free skill. Defaults to 0.1 if omitted."),
236
237
image: z.string().optional().describe("Cover image, ONLY if the user explicitly gave you an image URL or on-chain (base58) address. Pass it through verbatim. Do NOT generate, invent, or ask for one, and NEVER pass raw/base64 image data — omit this field entirely when the user didn't provide a link."),
238
+
requiredSkills: z.array(z.string()).optional().describe("Base58 skill mint addresses this item requires the buyer to already hold. Non-empty = publish a WORKFLOW (gated); omitted/empty = publish a plain skill (no gate)."),
237
239
},
238
240
},
239
241
];
@@ -425,21 +427,35 @@ export async function handleToolCall(
425
427
if(lamports===null){
426
428
return{isError: true,content: [{type: "text",text: `Invalid priceSol "${priceSol}" — use a SOL amount like "0.1" or "0".`}]};
427
429
}
430
+
// Non-empty requiredSkills IS the workflow signal — no separate kind param needed for
431
+
// this structured-args tool (unlike the freeform-text UI forms, which sniff/toggle it).
0 commit comments