@zibby/skills 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/package.json +56 -0
- package/dist/workflow-builder.js +175 -0
- package/package.json +2 -3
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{registerSkill as l}from"@zibby/core/framework/skill-registry.js";import{browserSkill as o}from"./browser.js";import{jiraSkill as t}from"./jira.js";import{githubSkill as m}from"./github.js";import{slackSkill as r}from"./slack.js";import{memorySkill as
|
|
1
|
+
import{registerSkill as l}from"@zibby/core/framework/skill-registry.js";import{browserSkill as o}from"./browser.js";import{jiraSkill as t}from"./jira.js";import{githubSkill as m}from"./github.js";import{slackSkill as r}from"./slack.js";import{memorySkill as e}from"./memory.js";import{skillInstallerSkill as k}from"./skill-installer.js";import{coreToolsSkill as S}from"./core-tools.js";import{sentrySkill as s}from"./sentry.js";import{testRunnerSkill as i}from"./test-runner.js";import{gitSkill as f}from"./git.js";import{chatMemorySkill as p}from"./chat-memory.js";import{workflowBuilderSkill as n}from"./workflow-builder.js";l(o),l(t),l(m),l(r),l(s),l(e),l(i),l(f),l(k),l(S),l(p),l(n),l({...r,id:"slack_notify"});const h={BROWSER:"browser",JIRA:"jira",GITHUB:"github",GIT:"git",SLACK:"slack",SENTRY:"sentry",MEMORY:"memory",RUNNER:"runner",SKILL_INSTALLER:"skill-installer",CORE_TOOLS:"core-tools",CHAT_MEMORY:"chat-memory",WORKFLOW_BUILDER:"workflow-builder"};import{skill as _,functionSkill as d}from"./function-skill.js";import{registerSkill as B,getSkill as K,hasSkill as N,getAllSkills as C,listSkillIds as U}from"@zibby/core/framework/skill-registry.js";export{h as SKILLS,o as browserSkill,p as chatMemorySkill,S as coreToolsSkill,d as functionSkill,C as getAllSkills,K as getSkill,f as gitSkill,m as githubSkill,N as hasSkill,t as jiraSkill,U as listSkillIds,e as memorySkill,B as registerSkill,i as runnerSkill,s as sentrySkill,_ as skill,k as skillInstallerSkill,r as slackSkill,i as testRunnerSkill,n as workflowBuilderSkill};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zibby/skills",
|
|
3
|
+
"version": "0.1.6",
|
|
4
|
+
"description": "Built-in skill definitions for Zibby test automation framework",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js",
|
|
9
|
+
"./browser": "./src/browser.js",
|
|
10
|
+
"./jira": "./src/jira.js",
|
|
11
|
+
"./github": "./src/github.js",
|
|
12
|
+
"./slack": "./src/slack.js",
|
|
13
|
+
"./memory": "./src/memory.js",
|
|
14
|
+
"./function": "./src/function-skill.js"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "node ../scripts/build.mjs",
|
|
18
|
+
"lint": "eslint .",
|
|
19
|
+
"lint:fix": "eslint --fix ."
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"zibby",
|
|
23
|
+
"skills",
|
|
24
|
+
"mcp",
|
|
25
|
+
"automation",
|
|
26
|
+
"testing"
|
|
27
|
+
],
|
|
28
|
+
"author": "Zibby",
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"homepage": "https://zibby.app",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/ZibbyHQ/zibby-agent"
|
|
34
|
+
},
|
|
35
|
+
"bugs": {
|
|
36
|
+
"url": "https://github.com/ZibbyHQ/zibby-agent/issues"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"src/",
|
|
40
|
+
"README.md",
|
|
41
|
+
"LICENSE"
|
|
42
|
+
],
|
|
43
|
+
"engines": {
|
|
44
|
+
"node": ">=18.0.0"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"@zibby/core": ">=0.1.0"
|
|
48
|
+
},
|
|
49
|
+
"optionalDependencies": {
|
|
50
|
+
"@zibby/mcp-browser": "^0.1.8",
|
|
51
|
+
"@zibby/mcp-memory": "*"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"esbuild": "^0.28.0"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import{existsSync as f,readFileSync as j,readdirSync as S,mkdirSync as W,writeFileSync as m,statSync as J}from"fs";import{join as p,resolve as F,relative as _}from"path";const v=`## Workflow Builder
|
|
2
|
+
|
|
3
|
+
You can help users build custom AI workflows using the Zibby workflow framework.
|
|
4
|
+
|
|
5
|
+
### What is a workflow?
|
|
6
|
+
A directed graph of nodes (AI steps) connected by edges. Each node has:
|
|
7
|
+
- \`name\` \u2014 unique identifier (snake_case)
|
|
8
|
+
- \`prompt\` \u2014 function that receives state and returns the LLM prompt string
|
|
9
|
+
- \`outputSchema\` \u2014 Zod schema defining the structured output
|
|
10
|
+
- \`skills\` (optional) \u2014 array of MCP skill IDs the node needs (e.g., 'browser', 'github')
|
|
11
|
+
|
|
12
|
+
### File structure
|
|
13
|
+
\`\`\`
|
|
14
|
+
.zibby/workflows/<name>/
|
|
15
|
+
\u251C\u2500\u2500 graph.mjs \u2014 WorkflowAgent subclass with buildGraph()
|
|
16
|
+
\u251C\u2500\u2500 nodes/
|
|
17
|
+
\u2502 \u251C\u2500\u2500 index.mjs \u2014 barrel export for all nodes
|
|
18
|
+
\u2502 \u2514\u2500\u2500 <node>.mjs \u2014 one file per node
|
|
19
|
+
\u2514\u2500\u2500 workflow.json \u2014 manifest (name, description, triggers)
|
|
20
|
+
\`\`\`
|
|
21
|
+
|
|
22
|
+
### Node pattern
|
|
23
|
+
\`\`\`javascript
|
|
24
|
+
import { z } from '@zibby/core';
|
|
25
|
+
|
|
26
|
+
const OutputSchema = z.object({
|
|
27
|
+
summary: z.string().describe('Brief summary'),
|
|
28
|
+
items: z.array(z.string()).describe('List of items'),
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
export const myNode = {
|
|
32
|
+
name: 'my_node',
|
|
33
|
+
prompt: (state) => \\\`Analyze the input and return structured results.
|
|
34
|
+
Input: \\\${JSON.stringify(state.input || {}, null, 2)}\\\`,
|
|
35
|
+
outputSchema: OutputSchema,
|
|
36
|
+
};
|
|
37
|
+
\`\`\`
|
|
38
|
+
|
|
39
|
+
### Graph pattern
|
|
40
|
+
\`\`\`javascript
|
|
41
|
+
import { WorkflowAgent, WorkflowGraph } from '@zibby/core';
|
|
42
|
+
import { classifyNode, routeNode } from './nodes/index.mjs';
|
|
43
|
+
|
|
44
|
+
export class MyWorkflow extends WorkflowAgent {
|
|
45
|
+
buildGraph() {
|
|
46
|
+
const graph = new WorkflowGraph();
|
|
47
|
+
graph.addNode('classify', classifyNode);
|
|
48
|
+
graph.addNode('route', routeNode);
|
|
49
|
+
graph.setEntryPoint('classify');
|
|
50
|
+
graph.addEdge('classify', 'route');
|
|
51
|
+
graph.addEdge('route', 'END');
|
|
52
|
+
return graph;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
\`\`\`
|
|
56
|
+
|
|
57
|
+
Conditional edges: \`graph.addConditionalEdges('node', (state) => state.node.priority === 'high' ? 'escalate' : 'notify')\`
|
|
58
|
+
|
|
59
|
+
### How to use the builder tools
|
|
60
|
+
1. Ask the user what their workflow should do, what input it receives, and what steps are needed.
|
|
61
|
+
2. Call \`design_workflow\` with the structured spec for the user to review.
|
|
62
|
+
3. Once approved, call \`build_workflow\` to generate real code on disk.
|
|
63
|
+
4. Remind the user: \`zibby start <name>\` to test, \`zibby deploy <name> --project <id>\` to deploy, \`zibby logs --workflow <name>\` to tail logs.
|
|
64
|
+
|
|
65
|
+
### Important
|
|
66
|
+
- Each node prompt should be detailed and specific \u2014 tell the AI exactly what to do and what format to return.
|
|
67
|
+
- Zod schemas should use .describe() on every field so the AI knows what each field means.
|
|
68
|
+
- Node names must be snake_case (e.g., classify_ticket, generate_report).
|
|
69
|
+
- Workflow names must be kebab-case (e.g., ticket-triage, pr-review).
|
|
70
|
+
- State flows through: each node's output is stored under its name in state (e.g., state.classify_ticket).
|
|
71
|
+
- Downstream nodes can reference upstream outputs in their prompt function.`,O=/^[a-z][a-z0-9-]{0,62}[a-z0-9]$/;function z(n){return`${n.split("-").map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join("")}Workflow`}function y(n){return`${n.replace(/_([a-z])/g,(e,s)=>s.toUpperCase())}Node`}function A(n){const e=n?.agent;return e?e.provider?e.provider:e.gemini?"gemini":e.codex?"codex":e.claude?"claude":e.cursor?"cursor":process.env.AGENT_TYPE||"cursor":process.env.AGENT_TYPE||"cursor"}async function E(n){const e=F(n,".zibby.config.mjs");if(!f(e))return{};try{return(await import(e)).default||{}}catch{return{}}}function D(n){const e=n.nodes.map(o=>{const t=o.inputFields?.length?`Input fields: ${o.inputFields.join(", ")}`:"Input: receives full state",i=o.outputFields?.length?`Output fields: ${o.outputFields.join(", ")}`:"Output: determined by task";return`- ${o.name}: ${o.description}. ${t}. ${i}.`}).join(`
|
|
72
|
+
`),s=n.edges.map(o=>o.condition?`- ${o.from} \u2192 ${o.to} (conditional: ${o.condition})`:`- ${o.from} \u2192 ${o.to}`).join(`
|
|
73
|
+
`);return`Generate the code for a Zibby workflow called "${n.name}".
|
|
74
|
+
|
|
75
|
+
## Workflow description
|
|
76
|
+
${n.description}
|
|
77
|
+
|
|
78
|
+
## Nodes
|
|
79
|
+
${e}
|
|
80
|
+
|
|
81
|
+
## Edges (flow)
|
|
82
|
+
${s}
|
|
83
|
+
|
|
84
|
+
## Requirements
|
|
85
|
+
For EACH node, generate a complete ESM module with:
|
|
86
|
+
1. A Zod output schema with .describe() on every field
|
|
87
|
+
2. A prompt function that takes state and returns a detailed, specific prompt string
|
|
88
|
+
3. The prompt should reference upstream node outputs from state when applicable
|
|
89
|
+
|
|
90
|
+
Return a JSON object with this exact structure:
|
|
91
|
+
{
|
|
92
|
+
"nodes": {
|
|
93
|
+
"<node_name>": {
|
|
94
|
+
"code": "// complete ESM module code as a string"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
Each node's code must:
|
|
100
|
+
- Start with: import { z } from '@zibby/core';
|
|
101
|
+
- Define a const schema (e.g., ClassifyOutputSchema)
|
|
102
|
+
- Export a const node object with name, prompt (function), and outputSchema
|
|
103
|
+
- The export name should be camelCase + "Node" (e.g., classifyTicketNode)
|
|
104
|
+
|
|
105
|
+
Example node code:
|
|
106
|
+
\`\`\`
|
|
107
|
+
import { z } from '@zibby/core';
|
|
108
|
+
|
|
109
|
+
const ClassifyOutputSchema = z.object({
|
|
110
|
+
priority: z.enum(['critical', 'high', 'medium', 'low']).describe('Ticket priority level'),
|
|
111
|
+
category: z.string().describe('Issue category'),
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
export const classifyTicketNode = {
|
|
115
|
+
name: 'classify_ticket',
|
|
116
|
+
prompt: (state) => \`You are a ticket classifier.
|
|
117
|
+
|
|
118
|
+
Input ticket:
|
|
119
|
+
\${JSON.stringify(state.input || {}, null, 2)}
|
|
120
|
+
|
|
121
|
+
Classify this ticket by priority and category.\`,
|
|
122
|
+
outputSchema: ClassifyOutputSchema,
|
|
123
|
+
};
|
|
124
|
+
\`\`\`
|
|
125
|
+
|
|
126
|
+
IMPORTANT: Return ONLY valid JSON. No markdown fences, no explanation outside the JSON.`}async function x(n,e){const s=await E(e),o=A(s);try{const{invokeAgent:t}=await import("@zibby/core"),i=D(n),r=await t(i,{state:{agentType:o,config:s,cwd:e,workspace:e}},{model:s?.agent?.[o]?.model||"auto",workspace:e,config:s,timeout:12e4}),a=(typeof r=="string"?r:r?.raw||JSON.stringify(r?.structured||r)).match(/\{[\s\S]*\}/);if(!a)throw new Error("Agent did not return valid JSON");return JSON.parse(a[0])}catch(t){return console.warn(`Agent code generation failed (${t.message}), using templates`),I(n)}}function I(n){const e={};for(const s of n.nodes){const o=y(s.name),t=`${s.name.split("_").map(a=>a.charAt(0).toUpperCase()+a.slice(1)).join("")}OutputSchema`,i=s.outputFields?.length?s.outputFields.map(a=>` ${a}: z.string().describe('${a}'),`).join(`
|
|
127
|
+
`):` summary: z.string().describe('Summary of the result'),
|
|
128
|
+
status: z.enum(['ok', 'warn', 'error']).describe('Overall status'),`,r=n.edges.filter(a=>a.to===s.name&&a.from!=="START").map(a=>`Previous step (${a.from}): \${JSON.stringify(state.${a.from} || {}, null, 2)}`).join(`
|
|
129
|
+
`),c=r?`${s.description}
|
|
130
|
+
|
|
131
|
+
Input:
|
|
132
|
+
\${JSON.stringify(state.input || {}, null, 2)}
|
|
133
|
+
|
|
134
|
+
${r}`:`${s.description}
|
|
135
|
+
|
|
136
|
+
Input:
|
|
137
|
+
\${JSON.stringify(state.input || {}, null, 2)}`;e[s.name]={code:`import { z } from '@zibby/core';
|
|
138
|
+
|
|
139
|
+
const ${t} = z.object({
|
|
140
|
+
${i}
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
export const ${o} = {
|
|
144
|
+
name: '${s.name}',
|
|
145
|
+
prompt: (state) => \`${c}\`,
|
|
146
|
+
outputSchema: ${t},
|
|
147
|
+
};
|
|
148
|
+
`}}return{nodes:e}}function T(n,e,s,o){const t=e.toLowerCase(),i=z(t),r=p(n,".zibby","workflows",t),c=p(r,"nodes");W(c,{recursive:!0});const a=s.nodes.map(d=>d.name);for(const d of s.nodes){const u=o.nodes?.[d.name]?.code;u&&m(p(c,`${d.name.replace(/_/g,"-")}.mjs`),u,"utf-8")}const l=a.map(d=>{const u=y(d),C=d.replace(/_/g,"-");return`export { ${u} } from './${C}.mjs';`});m(p(c,"index.mjs"),`${l.join(`
|
|
149
|
+
`)}
|
|
150
|
+
`,"utf-8");const $=a[0],N=a.map(d=>y(d)).join(", "),h=a.map(d=>` graph.addNode('${d}', ${y(d)});`).join(`
|
|
151
|
+
`),k=s.edges.map(d=>d.condition?` graph.addConditionalEdges('${d.from}', (state) => {
|
|
152
|
+
${d.condition}
|
|
153
|
+
});`:` graph.addEdge('${d.from}', '${d.to}');`).join(`
|
|
154
|
+
`),b=`import { WorkflowAgent, WorkflowGraph } from '@zibby/core';
|
|
155
|
+
import { ${N} } from './nodes/index.mjs';
|
|
156
|
+
|
|
157
|
+
export class ${i} extends WorkflowAgent {
|
|
158
|
+
buildGraph() {
|
|
159
|
+
const graph = new WorkflowGraph();
|
|
160
|
+
|
|
161
|
+
${h}
|
|
162
|
+
|
|
163
|
+
graph.setEntryPoint('${$}');
|
|
164
|
+
${k}
|
|
165
|
+
|
|
166
|
+
return graph;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async onComplete(result) {
|
|
170
|
+
console.log(\`[${t}] workflow complete \u2014 success: \${result.success !== false}\`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
`;m(p(r,"graph.mjs"),b,"utf-8");const g={name:t,description:s.description||`${i} workflow`,entryClass:i,triggers:{api:!0}};m(p(r,"workflow.json"),`${JSON.stringify(g,null,2)}
|
|
174
|
+
`,"utf-8");const w=["graph.mjs","workflow.json","nodes/index.mjs",...a.map(d=>`nodes/${d.replace(/_/g,"-")}.mjs`)];return{workflowDir:_(n,r),files:w,className:i,slug:t}}async function L(n){const{name:e,description:s,nodes:o,edges:t}=n;if(!e||!O.test(e.toLowerCase()))return JSON.stringify({error:`Invalid workflow name "${e}". Must be kebab-case, 2-64 chars, lowercase letters/numbers/hyphens.`});if(!o||o.length===0)return JSON.stringify({error:"At least one node is required."});const i={name:e.toLowerCase(),description:s||`${z(e.toLowerCase())} workflow`,nodes:o.map(r=>({name:r.name.replace(/-/g,"_"),description:r.description||`Process ${r.name}`,inputFields:r.inputFields||[],outputFields:r.outputFields||[]})),edges:t||[]};if(i.edges.length===0&&i.nodes.length>0){for(let r=0;r<i.nodes.length-1;r++)i.edges.push({from:i.nodes[r].name,to:i.nodes[r+1].name});i.edges.push({from:i.nodes[i.nodes.length-1].name,to:"END"})}return JSON.stringify({ok:!0,spec:i,message:`Workflow "${i.name}" designed with ${i.nodes.length} node(s). Call build_workflow to generate the code.`,preview:{nodes:i.nodes.map(r=>r.name),flow:i.edges.map(r=>r.condition?`${r.from} \u2192(if ${r.condition})\u2192 ${r.to}`:`${r.from} \u2192 ${r.to}`)}})}async function G(n,e){const{name:s,spec:o}=n,t=(s||o?.name||"").toLowerCase();if(!t||!O.test(t))return JSON.stringify({error:`Invalid workflow name "${t}".`});if(!o||!o.nodes||o.nodes.length===0)return JSON.stringify({error:"spec with nodes is required. Call design_workflow first."});const i=p(e,".zibby","workflows",t);if(f(i))return JSON.stringify({error:`Workflow "${t}" already exists at .zibby/workflows/${t}/. Delete it first or choose a different name.`});const r=await x(o,e),c=T(e,t,o,r);return JSON.stringify({ok:!0,...c,message:`Workflow "${t}" created at ${c.workflowDir}/`,nextSteps:[`Test locally: zibby start ${t}`,`Deploy to cloud: zibby deploy ${t} --project <project-id>`,`Tail logs: zibby logs --workflow ${t} --project <project-id>`]})}async function P(n,e){const{workflowName:s,nodeName:o,description:t,inputFields:i,outputFields:r}=n,c=(s||"").toLowerCase(),a=(o||"").replace(/-/g,"_"),l=p(e,".zibby","workflows",c);if(!f(l))return JSON.stringify({error:`Workflow "${c}" not found. Create it first with build_workflow.`});const $={name:c,description:"",nodes:[{name:a,description:t||`Process ${a}`,inputFields:i||[],outputFields:r||[]}],edges:[]},h=(await x($,e)).nodes?.[a]?.code;if(!h)return JSON.stringify({error:"Failed to generate node code."});const k=p(l,"nodes"),b=`${a.replace(/_/g,"-")}.mjs`;m(p(k,b),h,"utf-8");const g=p(k,"index.mjs"),w=y(a),d=`export { ${w} } from './${a.replace(/_/g,"-")}.mjs';
|
|
175
|
+
`,u=f(g)?j(g,"utf-8"):"";return u.includes(w)||m(g,u+d,"utf-8"),JSON.stringify({ok:!0,file:`nodes/${b}`,exportName:w,message:`Node "${a}" added. Update graph.mjs to wire it into the graph.`})}async function q(n,e){const{name:s,projectId:o}=n,t=(s||"").toLowerCase();if(!t)return JSON.stringify({error:"Workflow name is required."});if(!o)return JSON.stringify({error:"projectId is required."});const i=p(e,".zibby","workflows",t);if(!f(i))return JSON.stringify({error:`Workflow "${t}" not found at .zibby/workflows/${t}/`});try{const{execSync:r}=await import("child_process"),c=r(`node "${p(e,"packages/cli/bin/zibby.js")}" deploy ${t} --project ${o}`,{cwd:e,encoding:"utf-8",timeout:3e4,stdio:["pipe","pipe","pipe"]});return JSON.stringify({ok:!0,output:c.trim()})}catch{try{const{execSync:c}=await import("child_process"),a=c(`npx zibby deploy ${t} --project ${o}`,{cwd:e,encoding:"utf-8",timeout:3e4,stdio:["pipe","pipe","pipe"]});return JSON.stringify({ok:!0,output:a.trim()})}catch(c){return JSON.stringify({error:`Deploy failed: ${c.message}`})}}}function R(n){const e=p(n,".zibby","workflows");if(!f(e))return JSON.stringify({workflows:[],message:"No workflows found. Use build_workflow to create one."});const o=S(e).filter(t=>{try{return J(p(e,t)).isDirectory()}catch{return!1}}).map(t=>{const i=p(e,t,"workflow.json");let r={};try{r=JSON.parse(j(i,"utf-8"))}catch{}const c=p(e,t,"nodes");let a=0;try{a=S(c).filter(l=>l.endsWith(".mjs")&&l!=="index.mjs").length}catch{}return{name:t,description:r.description||"",nodeCount:a,path:_(n,p(e,t))}});return JSON.stringify({workflows:o})}const B={id:"workflow-builder",description:"Build, scaffold, and deploy custom AI workflows via conversation",envKeys:[],promptFragment:v,tools:[{name:"design_workflow",description:"Design a workflow spec (nodes, edges, descriptions) for the user to review before building. Call this after understanding requirements.",input_schema:{type:"object",properties:{name:{type:"string",description:"Workflow name in kebab-case (e.g., ticket-triage)"},description:{type:"string",description:"What the workflow does"},nodes:{type:"array",items:{type:"object",properties:{name:{type:"string",description:"Node name in snake_case (e.g., classify_ticket)"},description:{type:"string",description:"What this node does \u2014 be specific about input/output"},inputFields:{type:"array",items:{type:"string"},description:"Key fields this node reads from state"},outputFields:{type:"array",items:{type:"string"},description:"Key fields this node produces"}},required:["name","description"]},description:"Workflow nodes (processing steps)"},edges:{type:"array",items:{type:"object",properties:{from:{type:"string",description:"Source node name"},to:{type:"string",description:'Target node name (or "END")'},condition:{type:"string",description:"JS expression for conditional routing (optional)"}},required:["from","to"]},description:"Edges connecting nodes. If omitted, nodes are wired linearly."}},required:["name","description","nodes"]}},{name:"build_workflow",description:"Generate real workflow code on disk from a design spec. Uses the configured AI agent for high-quality code generation.",input_schema:{type:"object",properties:{name:{type:"string",description:"Workflow name (from design_workflow)"},spec:{type:"object",description:"The full spec object returned by design_workflow",properties:{name:{type:"string"},description:{type:"string"},nodes:{type:"array",items:{type:"object"}},edges:{type:"array",items:{type:"object"}}}}},required:["name","spec"]}},{name:"add_node",description:"Add a new node to an existing workflow. Generates the node file and updates the barrel export.",input_schema:{type:"object",properties:{workflowName:{type:"string",description:"Existing workflow name (kebab-case)"},nodeName:{type:"string",description:"New node name (snake_case)"},description:{type:"string",description:"What this node does"},inputFields:{type:"array",items:{type:"string"},description:"Fields read from state"},outputFields:{type:"array",items:{type:"string"},description:"Fields produced"}},required:["workflowName","nodeName","description"]}},{name:"deploy_workflow",description:"Deploy a workflow to Zibby Cloud. Returns the trigger URL.",input_schema:{type:"object",properties:{name:{type:"string",description:"Workflow name to deploy"},projectId:{type:"string",description:"Target project ID"}},required:["name","projectId"]}},{name:"list_workflows",description:"List all local workflows in .zibby/workflows/.",input_schema:{type:"object",properties:{}}}],async handleToolCall(n,e,s){const o=s?.options?.workspace||process.cwd();try{switch(n){case"design_workflow":return await L(e);case"build_workflow":return await G(e,o);case"add_node":return await P(e,o);case"deploy_workflow":return await q(e,o);case"list_workflows":return R(o);default:return JSON.stringify({error:`Unknown tool: ${n}`})}}catch(t){return JSON.stringify({error:t.message})}},resolve(){return null}};export{B as workflowBuilderSkill};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/skills",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Built-in skill definitions for Zibby test automation framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -47,8 +47,7 @@
|
|
|
47
47
|
"@zibby/core": ">=0.1.0"
|
|
48
48
|
},
|
|
49
49
|
"optionalDependencies": {
|
|
50
|
-
"@zibby/mcp-browser": "^0.1.
|
|
51
|
-
"@zibby/mcp-jira": "*",
|
|
50
|
+
"@zibby/mcp-browser": "^0.1.8",
|
|
52
51
|
"@zibby/mcp-memory": "*"
|
|
53
52
|
},
|
|
54
53
|
"devDependencies": {
|