@zibby/skills 0.1.8 → 0.1.9
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/browser.js +2 -2
- package/dist/chat-memory.js +15 -15
- package/dist/core-tools.js +2 -2
- package/dist/function-skill.js +1 -1
- package/dist/git.js +2 -2
- package/dist/github.js +3 -3
- package/dist/index.js +646 -1
- package/dist/jira.js +6 -6
- package/dist/memory.js +4 -4
- package/dist/package.json +15 -10
- package/dist/sentry.js +2 -2
- package/dist/skill-installer.js +3 -3
- package/dist/slack.js +2 -2
- package/dist/test-runner.js +13 -13
- package/dist/workflow-builder.js +146 -82
- package/docs/analysis.md +109 -0
- package/docs/cli-reference.md +338 -0
- package/docs/cloning-repositories.md +285 -0
- package/docs/custom-workflows.md +358 -0
- package/docs/getting-started.md +108 -0
- package/docs/installation.md +127 -0
- package/docs/integrations/github.md +73 -0
- package/docs/integrations/jira.md +71 -0
- package/docs/intro.md +87 -0
- package/docs/packages/cli.md +238 -0
- package/docs/packages/core.md +256 -0
- package/docs/packages/mcp-browser.md +110 -0
- package/docs/packages/memory.md +223 -0
- package/docs/packages/skills.md +216 -0
- package/docs/reviewing-results.md +114 -0
- package/docs/running-tests.md +134 -0
- package/docs/triggering-workflows.md +552 -0
- package/docs/workflow-artifact-layout-evaluation.md +119 -0
- package/docs/workflow.md +558 -0
- package/package.json +6 -1
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Workflow Artifact Layout Evaluation
|
|
2
|
+
|
|
3
|
+
## Context
|
|
4
|
+
|
|
5
|
+
Current workflow authoring is centered on hidden project files under `.zibby/`:
|
|
6
|
+
|
|
7
|
+
- `.zibby/graph.mjs`
|
|
8
|
+
- `.zibby/nodes/*`
|
|
9
|
+
- `.zibby/chat.mjs`
|
|
10
|
+
- `.zibby/result-handler.mjs`
|
|
11
|
+
- runtime output in `.zibby/output/sessions/*`
|
|
12
|
+
|
|
13
|
+
The product direction is to support live workflow creation via `zibby chat` and local/remote arbitrary workflow execution, while keeping user-authored workflow code commit-friendly.
|
|
14
|
+
|
|
15
|
+
## Options
|
|
16
|
+
|
|
17
|
+
### Option A: Keep everything in hidden `.zibby/`
|
|
18
|
+
|
|
19
|
+
Pros:
|
|
20
|
+
- No migration needed.
|
|
21
|
+
- Fully compatible with current Studio/CLI assumptions.
|
|
22
|
+
|
|
23
|
+
Cons:
|
|
24
|
+
- User-authored workflow source remains hidden and less discoverable.
|
|
25
|
+
- Weaker commit ergonomics for user-owned workflow code.
|
|
26
|
+
|
|
27
|
+
### Option B: Move everything to visible `zibby/`
|
|
28
|
+
|
|
29
|
+
Pros:
|
|
30
|
+
- Clear, commit-friendly source-of-truth for workflow code.
|
|
31
|
+
- Better UX for editing workflow artifacts directly.
|
|
32
|
+
|
|
33
|
+
Cons:
|
|
34
|
+
- High migration cost.
|
|
35
|
+
- Breaks many path assumptions in Studio bridge, Electron, docs, and integrations.
|
|
36
|
+
- Requires dual-path compatibility window to avoid immediate breakage.
|
|
37
|
+
|
|
38
|
+
### Option C: Hybrid (recommended)
|
|
39
|
+
|
|
40
|
+
Store user-authored workflow source in visible `zibby/`, keep runtime/output in hidden `.zibby/output`.
|
|
41
|
+
|
|
42
|
+
Pros:
|
|
43
|
+
- Commit-friendly source artifacts.
|
|
44
|
+
- Preserves hidden runtime/cache/output behavior.
|
|
45
|
+
- Smaller migration blast radius than full move.
|
|
46
|
+
|
|
47
|
+
Cons:
|
|
48
|
+
- Requires resolver precedence logic and migration tooling.
|
|
49
|
+
- Transitional complexity (legacy `.zibby` source + new `zibby` source).
|
|
50
|
+
|
|
51
|
+
### Option D: Hybrid + configurable path in `.zibby.config.mjs`
|
|
52
|
+
|
|
53
|
+
Same as Option C, but adds explicit config override for source workflow path.
|
|
54
|
+
|
|
55
|
+
Pros:
|
|
56
|
+
- Flexible for monorepos and custom project conventions.
|
|
57
|
+
- Future-proofs enterprise setups.
|
|
58
|
+
|
|
59
|
+
Cons:
|
|
60
|
+
- Slightly larger surface area and testing burden.
|
|
61
|
+
|
|
62
|
+
## Impact Map (Current Coupling)
|
|
63
|
+
|
|
64
|
+
Key areas that currently assume hidden-source and/or hidden-output conventions:
|
|
65
|
+
|
|
66
|
+
- `studio/electron/main.js`
|
|
67
|
+
- project-root detection uses `.zibby/graph.mjs`
|
|
68
|
+
- default sessions root uses `.zibby/output/sessions`
|
|
69
|
+
- `studio/vite.config.js`
|
|
70
|
+
- bridge fallbacks for session/output discovery
|
|
71
|
+
- `studio/src/adapters/platform.js`
|
|
72
|
+
- APIs and comments assume `.zibby/output/sessions`
|
|
73
|
+
- `docsite/docs/*`
|
|
74
|
+
- user docs describe hidden `.zibby` workflow/source model
|
|
75
|
+
|
|
76
|
+
Secondary impacts:
|
|
77
|
+
|
|
78
|
+
- integrations under `integrations/*` referencing current command/path patterns
|
|
79
|
+
- helper comments and UI command snippets across Studio/frontend
|
|
80
|
+
|
|
81
|
+
## Recommended Migration Strategy
|
|
82
|
+
|
|
83
|
+
### Phase 1 (compatibility, no breakage)
|
|
84
|
+
|
|
85
|
+
- Keep `.zibby/` source loading as primary behavior.
|
|
86
|
+
- Add support for visible `zibby/` source layout in resolvers.
|
|
87
|
+
- Resolver precedence:
|
|
88
|
+
1. explicit config path (if set)
|
|
89
|
+
2. `zibby/` source
|
|
90
|
+
3. legacy `.zibby/` source
|
|
91
|
+
- Keep runtime output in `.zibby/output`.
|
|
92
|
+
|
|
93
|
+
### Phase 2 (opt-in default shift)
|
|
94
|
+
|
|
95
|
+
- New projects scaffold workflow source under `zibby/`.
|
|
96
|
+
- Existing projects continue to work with `.zibby/`.
|
|
97
|
+
- Add migration helper command to copy/move source artifacts safely.
|
|
98
|
+
|
|
99
|
+
### Phase 3 (deprecation)
|
|
100
|
+
|
|
101
|
+
- Emit warnings for legacy hidden-source layouts.
|
|
102
|
+
- After a compatibility window, finalize the preferred source layout.
|
|
103
|
+
- Continue hidden runtime/output unless there is strong product need to change it.
|
|
104
|
+
|
|
105
|
+
## Suggested Source/Runtime Split
|
|
106
|
+
|
|
107
|
+
- User-authored source (commit-friendly):
|
|
108
|
+
- `zibby/graph.mjs`
|
|
109
|
+
- `zibby/nodes/*`
|
|
110
|
+
- `zibby/chat.mjs`
|
|
111
|
+
- `zibby/result-handler.mjs`
|
|
112
|
+
- Runtime/cache/output (hidden):
|
|
113
|
+
- `.zibby/output/*`
|
|
114
|
+
- `.zibby/scratch/*`
|
|
115
|
+
- `.zibby/memory/*`
|
|
116
|
+
|
|
117
|
+
## Why this recommendation
|
|
118
|
+
|
|
119
|
+
Hybrid with configuration gives the best balance: user-visible source for authoring and version control, while preserving stable hidden runtime/output semantics already used by Studio, CLI, and integrations.
|
package/docs/workflow.md
ADDED
|
@@ -0,0 +1,558 @@
|
|
|
1
|
+
---
|
|
2
|
+
sidebar_position: 4
|
|
3
|
+
title: Workflow Engine
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Workflow Engine
|
|
7
|
+
|
|
8
|
+
Zibby's workflow engine is a **graph-based orchestration system for AI agents**, inspired by [LangGraph](https://github.com/langchain-ai/langgraph) but designed to be **agent-agnostic**. The same workflow definition runs identically on Cursor, Claude, or Codex — you switch agents with a single flag, not by rewriting your pipeline.
|
|
9
|
+
|
|
10
|
+
## Core Concepts
|
|
11
|
+
|
|
12
|
+
### Graph = Nodes + Edges + State
|
|
13
|
+
|
|
14
|
+
A workflow is a directed graph where:
|
|
15
|
+
|
|
16
|
+
- **Nodes** — individual steps (AI calls, data transformations, tool usage)
|
|
17
|
+
- **Edges** — connections between nodes (linear or conditional)
|
|
18
|
+
- **State** — a shared key-value store that flows through the graph; every node reads from and writes to it
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
┌──────────┐ ┌──────────────┐ ┌─────────────────┐
|
|
22
|
+
│ preflight│────▶│ execute_live │────▶│ generate_script │───▶ END
|
|
23
|
+
└──────────┘ └──────────────┘ └─────────────────┘
|
|
24
|
+
│
|
|
25
|
+
▼ (conditional)
|
|
26
|
+
END
|
|
27
|
+
(no actions recorded)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Agent-Agnostic Design
|
|
31
|
+
|
|
32
|
+
The workflow framework never calls a specific AI provider directly. Instead, it uses a **Strategy Pattern**:
|
|
33
|
+
|
|
34
|
+
1. Each agent (Cursor, Claude, Codex) implements the `AgentStrategy` base class
|
|
35
|
+
2. The `invokeAgent()` function selects the right strategy at runtime based on your config
|
|
36
|
+
3. Nodes call `invokeAgent()` — they never know which provider executes the prompt
|
|
37
|
+
|
|
38
|
+
This means:
|
|
39
|
+
- Workflows are **portable** across agents
|
|
40
|
+
- Skills (MCP tools) are resolved per-agent automatically
|
|
41
|
+
- You can override the model per-node in config without touching workflow code
|
|
42
|
+
|
|
43
|
+
```javascript
|
|
44
|
+
// .zibby.config.js — switch agent with one line
|
|
45
|
+
export default {
|
|
46
|
+
agent: {
|
|
47
|
+
cursor: { model: 'auto' },
|
|
48
|
+
// claude: { model: 'sonnet-4.6' },
|
|
49
|
+
// codex: { model: 'gpt-5.2-codex' },
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Three Supported Agents
|
|
55
|
+
|
|
56
|
+
| Agent | SDK | MCP Integration | Structured Output |
|
|
57
|
+
|---|---|---|---|
|
|
58
|
+
| **Cursor** | cursor-agent CLI / API | MCP servers via `~/.cursor/mcp.json` | JSON extraction from response |
|
|
59
|
+
| **Claude** | `@anthropic-ai/claude-agent-sdk` | Native MCP tool_use with `allowedTools` | Zod schema → SDK structured output |
|
|
60
|
+
| **Codex** | `@openai/codex-sdk` | `mcp_servers` config in SDK | Zod → JSON Schema via `outputSchema` |
|
|
61
|
+
|
|
62
|
+
All three implement the same interface:
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
class AgentStrategy {
|
|
66
|
+
canHandle(context) // Is this agent available?
|
|
67
|
+
invoke(prompt, options) // Execute prompt with tools + schema
|
|
68
|
+
getName() // 'cursor' | 'claude' | 'codex'
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Building a Workflow
|
|
73
|
+
|
|
74
|
+
### The Built-in Default: Browser Test Automation
|
|
75
|
+
|
|
76
|
+
When you run `zibby test test.txt`, the CLI uses the built-in `BrowserTestAutomationAgent` workflow — no init or config needed:
|
|
77
|
+
|
|
78
|
+
```javascript
|
|
79
|
+
import { WorkflowAgent, WorkflowGraph } from '@zibby/core';
|
|
80
|
+
import { preflightNode, executeLiveNode, generateScriptNode } from './nodes/index.mjs';
|
|
81
|
+
|
|
82
|
+
export class BrowserTestAutomationAgent extends WorkflowAgent {
|
|
83
|
+
buildGraph() {
|
|
84
|
+
const graph = new WorkflowGraph();
|
|
85
|
+
|
|
86
|
+
graph.addNode('preflight', preflightNode);
|
|
87
|
+
graph.addNode('execute_live', executeLiveNode);
|
|
88
|
+
graph.addNode('generate_script', generateScriptNode);
|
|
89
|
+
|
|
90
|
+
graph.setEntryPoint('preflight');
|
|
91
|
+
graph.addEdge('preflight', 'execute_live');
|
|
92
|
+
|
|
93
|
+
graph.addConditionalEdges('execute_live', (state) => {
|
|
94
|
+
const result = state.execute_live;
|
|
95
|
+
const hasExecution = (result?.steps?.length > 0) || (result?.actions?.length > 0);
|
|
96
|
+
return hasExecution ? 'generate_script' : 'END';
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
graph.addEdge('generate_script', 'END');
|
|
100
|
+
return graph;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async onComplete(result) {
|
|
104
|
+
// Save artifacts, push to memory, etc.
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**What each node does:**
|
|
110
|
+
|
|
111
|
+
| Node | Type | Skills | Purpose |
|
|
112
|
+
|---|---|---|---|
|
|
113
|
+
| `preflight` | Prompt-only (no tools) | — | Reads test spec, extracts title + assertion checklist via LLM |
|
|
114
|
+
| `execute_live` | Tool-using | Browser, Memory | AI drives a real browser, fills forms, clicks, captures selectors |
|
|
115
|
+
| `generate_script` | Prompt-only | — | Converts recorded actions into a reusable Playwright `.spec.js` |
|
|
116
|
+
|
|
117
|
+
### Custom Workflows via `zibby init`
|
|
118
|
+
|
|
119
|
+
Scaffold a customizable workflow into your project:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
zibby init --agent cursor
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
This creates:
|
|
126
|
+
|
|
127
|
+
```
|
|
128
|
+
.zibby.config.js # Project configuration
|
|
129
|
+
.zibby/
|
|
130
|
+
├── graph.js # Workflow graph (nodes + edges)
|
|
131
|
+
├── nodes/
|
|
132
|
+
│ ├── preflight.js # Extract title + assertions
|
|
133
|
+
│ ├── execute-live.js # AI drives browser
|
|
134
|
+
│ └── generate-script.js # Generate Playwright script
|
|
135
|
+
└── result-handler.js # Post-execution artifact saving
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
You can then modify any node, add new nodes, or change the graph structure.
|
|
139
|
+
|
|
140
|
+
## WorkflowGraph API
|
|
141
|
+
|
|
142
|
+
### Creating a Graph
|
|
143
|
+
|
|
144
|
+
```javascript
|
|
145
|
+
import { WorkflowGraph, Node } from '@zibby/core';
|
|
146
|
+
|
|
147
|
+
const graph = new WorkflowGraph({
|
|
148
|
+
stateSchema: MyZodSchema, // Optional: Zod schema for state validation
|
|
149
|
+
middleware: [myMiddleware], // Optional: middleware functions
|
|
150
|
+
});
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Adding Nodes
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
// Simple node with prompt function + output schema
|
|
157
|
+
graph.addNode('my_node', {
|
|
158
|
+
name: 'my_node',
|
|
159
|
+
prompt: (state) => `Analyze: ${state.testSpec}`,
|
|
160
|
+
outputSchema: z.object({
|
|
161
|
+
title: z.string(),
|
|
162
|
+
items: z.array(z.string()),
|
|
163
|
+
}),
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Node with skills (MCP tools)
|
|
167
|
+
graph.addNode('browser_step', {
|
|
168
|
+
name: 'browser_step',
|
|
169
|
+
skills: [SKILLS.BROWSER, SKILLS.MEMORY],
|
|
170
|
+
prompt: (state) => `Execute: ${state.testSpec}`,
|
|
171
|
+
outputSchema: ExecutionSchema,
|
|
172
|
+
timeout: 600000,
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
// Node with custom execute (no LLM call)
|
|
176
|
+
graph.addNode('transform', {
|
|
177
|
+
name: 'transform',
|
|
178
|
+
_isCustomCode: true,
|
|
179
|
+
execute: async (context) => {
|
|
180
|
+
const data = context.state.get('raw_data');
|
|
181
|
+
return { cleaned: data.trim(), wordCount: data.split(' ').length };
|
|
182
|
+
},
|
|
183
|
+
outputSchema: TransformSchema,
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Wiring Edges
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
// Linear flow
|
|
191
|
+
graph.setEntryPoint('step_a');
|
|
192
|
+
graph.addEdge('step_a', 'step_b');
|
|
193
|
+
graph.addEdge('step_b', 'step_c');
|
|
194
|
+
graph.addEdge('step_c', 'END');
|
|
195
|
+
|
|
196
|
+
// Conditional branching
|
|
197
|
+
graph.addConditionalEdges('step_b', (state) => {
|
|
198
|
+
return state.step_b.success ? 'step_c' : 'error_handler';
|
|
199
|
+
});
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Running the Graph
|
|
203
|
+
|
|
204
|
+
```javascript
|
|
205
|
+
const result = await graph.run(agent, {
|
|
206
|
+
testSpec: 'Go to example.com and verify the title',
|
|
207
|
+
cwd: process.cwd(),
|
|
208
|
+
config: { agent: { cursor: { model: 'auto' } } },
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
console.log(result.success); // true
|
|
212
|
+
console.log(result.state.preflight); // { title: '...', assertions: [...] }
|
|
213
|
+
console.log(result.executionLog); // [{ node, success, duration }, ...]
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
## Node Anatomy
|
|
217
|
+
|
|
218
|
+
Every node has three key parts:
|
|
219
|
+
|
|
220
|
+
### 1. Prompt
|
|
221
|
+
|
|
222
|
+
A function or string template that receives the current state and produces the LLM prompt:
|
|
223
|
+
|
|
224
|
+
```javascript
|
|
225
|
+
prompt: (state) => `
|
|
226
|
+
Test spec: ${state.testSpec}
|
|
227
|
+
Previous results: ${JSON.stringify(state.preflight)}
|
|
228
|
+
|
|
229
|
+
Execute the test and return structured results.
|
|
230
|
+
`
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Nodes can also use Handlebars templates when configured with a `prompt` option:
|
|
234
|
+
|
|
235
|
+
```javascript
|
|
236
|
+
graph.addNode('my_node', nodeImpl, {
|
|
237
|
+
prompt: `Analyze {{testSpec}} and produce {{outputFormat}} results`
|
|
238
|
+
});
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### 2. Output Schema (Zod)
|
|
242
|
+
|
|
243
|
+
Every node declares a Zod schema for its output. The framework validates the AI response against it:
|
|
244
|
+
|
|
245
|
+
```javascript
|
|
246
|
+
import { z } from '@zibby/core';
|
|
247
|
+
|
|
248
|
+
const MyOutputSchema = z.object({
|
|
249
|
+
title: z.string().describe('Concise test title'),
|
|
250
|
+
assertions: z.array(z.object({
|
|
251
|
+
description: z.string(),
|
|
252
|
+
expected: z.string(),
|
|
253
|
+
})),
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
export const myNode = {
|
|
257
|
+
name: 'my_node',
|
|
258
|
+
outputSchema: MyOutputSchema,
|
|
259
|
+
prompt: (state) => '...',
|
|
260
|
+
};
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
The schema serves three purposes:
|
|
264
|
+
- **Runtime validation** — the LLM response is parsed and validated against the schema
|
|
265
|
+
- **Structured output** — Claude and Codex agents use the schema for native structured output (no JSON extraction needed)
|
|
266
|
+
- **State contract** — downstream nodes know exactly what shape to expect from upstream output
|
|
267
|
+
|
|
268
|
+
### 3. Skills
|
|
269
|
+
|
|
270
|
+
Skills declare what MCP tools a node needs. The framework resolves the right MCP server per-agent:
|
|
271
|
+
|
|
272
|
+
```javascript
|
|
273
|
+
import { SKILLS } from '@zibby/core';
|
|
274
|
+
|
|
275
|
+
export const executeLiveNode = {
|
|
276
|
+
name: 'execute_live',
|
|
277
|
+
skills: [SKILLS.BROWSER, SKILLS.MEMORY],
|
|
278
|
+
// ...
|
|
279
|
+
};
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Available built-in skills: `BROWSER`, `JIRA`, `GITHUB`, `SLACK`, `MEMORY`.
|
|
283
|
+
|
|
284
|
+
## State Management
|
|
285
|
+
|
|
286
|
+
State is a shared key-value store managed by `WorkflowState`. Each node's output is automatically stored under its name:
|
|
287
|
+
|
|
288
|
+
```javascript
|
|
289
|
+
// After preflight runs:
|
|
290
|
+
state.get('preflight') // → { title: '...', assertions: [...] }
|
|
291
|
+
|
|
292
|
+
// After execute_live runs:
|
|
293
|
+
state.get('execute_live') // → { success: true, steps: [...], actions: [...] }
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Built-in state keys:
|
|
297
|
+
|
|
298
|
+
| Key | Type | Description |
|
|
299
|
+
|---|---|---|
|
|
300
|
+
| `messages` | `Array` | Accumulated messages |
|
|
301
|
+
| `errors` | `Array` | Error records `{ node, error }` |
|
|
302
|
+
| `artifacts` | `Object` | Generated artifacts |
|
|
303
|
+
| `config` | `Object` | Resolved `.zibby.config.js` |
|
|
304
|
+
| `agentType` | `string` | Active agent (`cursor`, `claude`, `codex`) |
|
|
305
|
+
| `sessionPath` | `string` | Path to session output directory |
|
|
306
|
+
| `context` | `Object` | Loaded context files (CONTEXT.md, AGENTS.md, env) |
|
|
307
|
+
| `testSpec` | `string` | The test specification text |
|
|
308
|
+
| `<node_name>` | `Object` | Each node's validated output |
|
|
309
|
+
|
|
310
|
+
State supports history and rollback:
|
|
311
|
+
|
|
312
|
+
```javascript
|
|
313
|
+
state.set('key', 'value');
|
|
314
|
+
state.update({ a: 1, b: 2 });
|
|
315
|
+
state.append('errors', { node: 'x', error: 'failed' });
|
|
316
|
+
state.rollback(); // Undo last mutation
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Graph Compiler
|
|
320
|
+
|
|
321
|
+
Zibby includes a **graph compiler** that takes a serialized JSON graph (from the dashboard's visual editor) and compiles it into an executable `WorkflowGraph`:
|
|
322
|
+
|
|
323
|
+
```javascript
|
|
324
|
+
import { compileGraph, validateGraphConfig } from '@zibby/core';
|
|
325
|
+
|
|
326
|
+
// Validate before compiling
|
|
327
|
+
const { valid, errors } = validateGraphConfig(graphJson);
|
|
328
|
+
|
|
329
|
+
// Compile JSON → executable graph
|
|
330
|
+
const graph = compileGraph(graphJson, {
|
|
331
|
+
stateSchema: MySchema,
|
|
332
|
+
middleware: [memoryMiddleware],
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
await graph.run(agent, initialState);
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
The compiler handles:
|
|
339
|
+
- **Node resolution** — maps node types to registered implementations
|
|
340
|
+
- **Decision nodes** — collapses visual decision diamonds into `addConditionalEdges`
|
|
341
|
+
- **Custom code** — safely compiles inline JavaScript from the visual editor
|
|
342
|
+
- **Tool resolution** — wires MCP tool permissions per node
|
|
343
|
+
- **Entry point detection** — finds the node with no incoming edges
|
|
344
|
+
|
|
345
|
+
## Middleware
|
|
346
|
+
|
|
347
|
+
Middleware wraps every node execution, enabling cross-cutting concerns:
|
|
348
|
+
|
|
349
|
+
```javascript
|
|
350
|
+
const graph = new WorkflowGraph({
|
|
351
|
+
middleware: [
|
|
352
|
+
async (nodeName, next, stateValues, state) => {
|
|
353
|
+
console.log(`Starting: ${nodeName}`);
|
|
354
|
+
const result = await next();
|
|
355
|
+
console.log(`Completed: ${nodeName} in ${result.duration}ms`);
|
|
356
|
+
return result;
|
|
357
|
+
}
|
|
358
|
+
]
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Skills can also provide middleware. For example, the Memory skill injects a middleware that loads test history before each node and persists insights after:
|
|
363
|
+
|
|
364
|
+
```javascript
|
|
365
|
+
// Automatically injected when a node declares skills: [SKILLS.MEMORY]
|
|
366
|
+
const memoryMiddleware = await memorySkill.middleware();
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## Skill Adaptation per Agent
|
|
370
|
+
|
|
371
|
+
Skills are resolved differently depending on which agent is active:
|
|
372
|
+
|
|
373
|
+
| Agent | How Skills (MCP servers) Are Wired |
|
|
374
|
+
|---|---|
|
|
375
|
+
| **Cursor** | Written to `~/.cursor/mcp.json` — Cursor IDE manages the MCP lifecycle |
|
|
376
|
+
| **Claude** | Passed as `mcpServers` config to the Claude Agent SDK — native MCP support |
|
|
377
|
+
| **Codex** | Passed as `mcp_servers` config to the Codex SDK — SDK manages MCP processes |
|
|
378
|
+
|
|
379
|
+
The skill's `resolve()` function returns a platform-neutral server config:
|
|
380
|
+
|
|
381
|
+
```javascript
|
|
382
|
+
{
|
|
383
|
+
command: 'node',
|
|
384
|
+
args: ['/path/to/mcp-browser.js', '--save-video=1280x720', '--viewport-size=1280x720', '--output-dir=./output'],
|
|
385
|
+
env: { SOME_KEY: '...' }
|
|
386
|
+
}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Each agent strategy translates this into its native MCP format. Node code never changes.
|
|
390
|
+
|
|
391
|
+
## Context Loading
|
|
392
|
+
|
|
393
|
+
The workflow engine auto-discovers context files that are prepended to prompts:
|
|
394
|
+
|
|
395
|
+
```javascript
|
|
396
|
+
// .zibby.config.js
|
|
397
|
+
export default {
|
|
398
|
+
context: {
|
|
399
|
+
filenames: ['CONTEXT.md', 'AGENTS.md'],
|
|
400
|
+
discovery: {
|
|
401
|
+
env: `env-${process.env.ENV || 'local'}.js`,
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Context files cascade from the project root down to the spec's directory. This lets you provide domain knowledge (login credentials, app structure, known quirks) that the AI uses during execution.
|
|
408
|
+
|
|
409
|
+
## Per-Node Model Override
|
|
410
|
+
|
|
411
|
+
Override the AI model for specific nodes without changing the workflow:
|
|
412
|
+
|
|
413
|
+
```javascript
|
|
414
|
+
// .zibby.config.js
|
|
415
|
+
export default {
|
|
416
|
+
agent: {
|
|
417
|
+
cursor: { model: 'auto' },
|
|
418
|
+
},
|
|
419
|
+
models: {
|
|
420
|
+
default: 'auto',
|
|
421
|
+
execute_live: 'claude-opus-4', // Use a more capable model for browser execution
|
|
422
|
+
preflight: 'claude-sonnet-4.6', // Faster model for analysis
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Model resolution priority: node override → `models.default` → agent block model → `'auto'`.
|
|
428
|
+
|
|
429
|
+
## Workflow Templates
|
|
430
|
+
|
|
431
|
+
`@zibby/core` ships two built-in workflow templates:
|
|
432
|
+
|
|
433
|
+
### Browser Test Automation (`browser-test-automation`)
|
|
434
|
+
|
|
435
|
+
The default workflow for `zibby test`:
|
|
436
|
+
|
|
437
|
+
```
|
|
438
|
+
preflight → execute_live → generate_script → END
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Three nodes: extract spec, drive browser, generate Playwright script.
|
|
442
|
+
|
|
443
|
+
### Code Analysis (`code-analysis`)
|
|
444
|
+
|
|
445
|
+
Used by the cloud analysis pipeline:
|
|
446
|
+
|
|
447
|
+
```
|
|
448
|
+
setup → analyze_ticket → generate_code → generate_test_cases → finalize → END
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
Six nodes: clone repo, analyze Jira ticket, generate code changes, write test cases, compile report.
|
|
452
|
+
|
|
453
|
+
## Creating Custom Skills
|
|
454
|
+
|
|
455
|
+
### MCP Skill (wraps an external MCP server)
|
|
456
|
+
|
|
457
|
+
```javascript
|
|
458
|
+
import { skill } from '@zibby/skills';
|
|
459
|
+
|
|
460
|
+
export const linear = skill('linear', {
|
|
461
|
+
description: 'Linear project management',
|
|
462
|
+
serverName: 'linear',
|
|
463
|
+
allowedTools: ['mcp__linear__*'],
|
|
464
|
+
envKeys: ['LINEAR_API_KEY'],
|
|
465
|
+
resolve() {
|
|
466
|
+
if (!process.env.LINEAR_API_KEY) return null;
|
|
467
|
+
return {
|
|
468
|
+
command: 'npx',
|
|
469
|
+
args: ['-y', '@anthropic/linear-mcp-server'],
|
|
470
|
+
env: { LINEAR_API_KEY: process.env.LINEAR_API_KEY }
|
|
471
|
+
};
|
|
472
|
+
}
|
|
473
|
+
});
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
### Function Skill (single tool, no MCP server)
|
|
477
|
+
|
|
478
|
+
```javascript
|
|
479
|
+
import { skill } from '@zibby/skills';
|
|
480
|
+
|
|
481
|
+
export const add = skill('add', {
|
|
482
|
+
description: 'Add two numbers',
|
|
483
|
+
input: { a: 'number', b: 'number' },
|
|
484
|
+
handler: async ({ a, b }) => ({ result: a + b })
|
|
485
|
+
});
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
Function skills are automatically bridged to MCP at runtime — the framework spawns a lightweight MCP server that delegates to your handler.
|
|
489
|
+
|
|
490
|
+
## End-to-End Example: Custom Workflow
|
|
491
|
+
|
|
492
|
+
```javascript
|
|
493
|
+
import { WorkflowGraph, SKILLS } from '@zibby/core';
|
|
494
|
+
import { z } from '@zibby/core';
|
|
495
|
+
|
|
496
|
+
// 1. Define output schemas
|
|
497
|
+
const AnalysisSchema = z.object({
|
|
498
|
+
summary: z.string(),
|
|
499
|
+
testCases: z.array(z.object({
|
|
500
|
+
name: z.string(),
|
|
501
|
+
steps: z.array(z.string()),
|
|
502
|
+
})),
|
|
503
|
+
});
|
|
504
|
+
|
|
505
|
+
const ExecutionSchema = z.object({
|
|
506
|
+
success: z.boolean(),
|
|
507
|
+
steps: z.array(z.string()),
|
|
508
|
+
actions: z.array(z.object({
|
|
509
|
+
type: z.string(),
|
|
510
|
+
description: z.string(),
|
|
511
|
+
})),
|
|
512
|
+
browserClosed: z.boolean(),
|
|
513
|
+
});
|
|
514
|
+
|
|
515
|
+
// 2. Define nodes
|
|
516
|
+
const analyzeNode = {
|
|
517
|
+
name: 'analyze',
|
|
518
|
+
prompt: (state) => `Analyze this requirement and produce test cases:\n${state.testSpec}`,
|
|
519
|
+
outputSchema: AnalysisSchema,
|
|
520
|
+
};
|
|
521
|
+
|
|
522
|
+
const executeNode = {
|
|
523
|
+
name: 'execute',
|
|
524
|
+
skills: [SKILLS.BROWSER, SKILLS.MEMORY],
|
|
525
|
+
prompt: (state) => `Execute test "${state.analyze.testCases[0].name}":\n${state.analyze.testCases[0].steps.join('\n')}`,
|
|
526
|
+
outputSchema: ExecutionSchema,
|
|
527
|
+
timeout: 600000,
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
// 3. Build graph
|
|
531
|
+
const graph = new WorkflowGraph();
|
|
532
|
+
graph.addNode('analyze', analyzeNode);
|
|
533
|
+
graph.addNode('execute', executeNode);
|
|
534
|
+
graph.setEntryPoint('analyze');
|
|
535
|
+
graph.addEdge('analyze', 'execute');
|
|
536
|
+
graph.addEdge('execute', 'END');
|
|
537
|
+
|
|
538
|
+
// 4. Run
|
|
539
|
+
const result = await graph.run(agent, {
|
|
540
|
+
testSpec: 'Verify the user can log in and see the dashboard',
|
|
541
|
+
cwd: process.cwd(),
|
|
542
|
+
});
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
## Workflow CLI Commands
|
|
546
|
+
|
|
547
|
+
```bash
|
|
548
|
+
# Run a specific workflow (if you have multiple defined)
|
|
549
|
+
zibby test test.txt --workflow QuickSmokeWorkflow
|
|
550
|
+
|
|
551
|
+
# Run a single node (for debugging)
|
|
552
|
+
zibby test test.txt --node execute_live --session last
|
|
553
|
+
|
|
554
|
+
# Upload/download workflow graphs to/from Zibby Cloud
|
|
555
|
+
zibby workflow list
|
|
556
|
+
zibby workflow download --type run_test
|
|
557
|
+
zibby workflow upload --type analysis --file .zibby/workflow-analysis.json
|
|
558
|
+
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zibby/skills",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.9",
|
|
4
4
|
"description": "Built-in skill definitions for Zibby test automation framework",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "node ../scripts/build.mjs",
|
|
18
|
+
"prepack": "node scripts/copy-docs.mjs",
|
|
18
19
|
"lint": "eslint .",
|
|
19
20
|
"lint:fix": "eslint --fix ."
|
|
20
21
|
},
|
|
@@ -37,12 +38,16 @@
|
|
|
37
38
|
},
|
|
38
39
|
"files": [
|
|
39
40
|
"dist/",
|
|
41
|
+
"docs/",
|
|
40
42
|
"README.md",
|
|
41
43
|
"LICENSE"
|
|
42
44
|
],
|
|
43
45
|
"engines": {
|
|
44
46
|
"node": ">=18.0.0"
|
|
45
47
|
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@zibby/workflow": "^0.1.0"
|
|
50
|
+
},
|
|
46
51
|
"peerDependencies": {
|
|
47
52
|
"@zibby/core": ">=0.1.0"
|
|
48
53
|
},
|