Skip to content

Commit 89fd049

Browse files
authored
Merge pull request #2 from constructive-io/feat/add-fbp-skill
feat: add fbp skill with AGENTS.md
2 parents 6f0ef58 + 6964f4a commit 89fd049

7 files changed

Lines changed: 826 additions & 0 deletions

File tree

.agents/skills/fbp.zip

9.02 KB
Binary file not shown.

.agents/skills/fbp/SKILL.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
---
2+
name: fbp
3+
description: "Flow-Based Programming toolkit — type system (fbp-types), specification language (fbp-spec), evaluator engine (fbp-evaluator), and visual graph editor (fbp-graph-editor). Use when working with FBP graphs, defining flow types, evaluating flow specifications, or building visual flow editors."
4+
metadata:
5+
author: constructive-io
6+
version: "1.0.0"
7+
---
8+
9+
# FBP (Flow-Based Programming)
10+
11+
The complete FBP toolkit: type system, specification language, evaluator engine, and visual graph editor.
12+
13+
## When to Apply
14+
15+
Use this skill when:
16+
- Working with FBP graph definitions
17+
- Defining flow types and port contracts
18+
- Evaluating flow specifications
19+
- Building or customizing visual flow editors
20+
21+
## Components
22+
23+
### FBP Types
24+
25+
The type system for FBP — port types, graph validation, type contracts between components.
26+
27+
See [fbp-types.md](./references/fbp-types.md) for the type system reference.
28+
29+
### FBP Spec
30+
31+
The specification language for defining FBP graphs — component declarations, connections, IIPs (Initial Information Packets).
32+
33+
See [fbp-spec.md](./references/fbp-spec.md) for the specification language.
34+
35+
### FBP Evaluator
36+
37+
The evaluation engine that executes FBP graphs — scheduling, data flow, component lifecycle.
38+
39+
See [fbp-evaluator.md](./references/fbp-evaluator.md) for the evaluator reference.
40+
41+
### FBP Graph Editor
42+
43+
Visual editor for FBP graphs — drag-and-drop components, connection drawing, graph serialization.
44+
45+
See [fbp-graph-editor.md](./references/fbp-graph-editor.md) for the editor reference.
46+
47+
## Reference Guide
48+
49+
| Reference | Topic | Consult When |
50+
|-----------|-------|--------------|
51+
| [fbp-types.md](./references/fbp-types.md) | FBP type system | Defining port types, type contracts, validation |
52+
| [fbp-spec.md](./references/fbp-spec.md) | FBP specification language | Graph definitions, component declarations, connections |
53+
| [fbp-evaluator.md](./references/fbp-evaluator.md) | FBP evaluator engine | Executing graphs, scheduling, data flow |
54+
| [fbp-graph-editor.md](./references/fbp-graph-editor.md) | Visual graph editor | Editor setup, drag-and-drop, serialization |
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
---
2+
name: fbp-evaluator
3+
description: Lazy graph evaluator for Flow-Based Programming. Use when evaluating FBP graphs, running dataflow computations, or working with the @fbp/evaluator package.
4+
---
5+
6+
Lazy graph evaluator for Flow-Based Programming.
7+
8+
## Installation
9+
10+
```bash
11+
pnpm add @fbp/evaluator
12+
```
13+
14+
## Overview
15+
16+
`@fbp/evaluator` provides a lazy evaluation engine for FBP graphs. It only evaluates nodes that are needed for the requested output, making it efficient for large graphs where only a subset of nodes contribute to the result.
17+
18+
## Basic Usage
19+
20+
```typescript
21+
import { evaluate } from '@fbp/evaluator';
22+
import type { Graph } from '@fbp/types';
23+
import type { NodeDefinitionWithImpl } from '@fbp/evaluator';
24+
25+
// Define node implementations
26+
const addDef: NodeDefinitionWithImpl = {
27+
context: 'js',
28+
category: 'math',
29+
type: 'js/math/add',
30+
inputs: [
31+
{ name: 'a', type: 'number' },
32+
{ name: 'b', type: 'number' }
33+
],
34+
outputs: [{ name: 'sum', type: 'number' }],
35+
impl: (inputs) => ({
36+
sum: (inputs.a ?? 0) + (inputs.b ?? 0)
37+
})
38+
};
39+
40+
const constNumberDef: NodeDefinitionWithImpl = {
41+
context: 'js',
42+
category: 'const',
43+
type: 'js/const/number',
44+
props: [{ name: 'value', type: 'number' }],
45+
outputs: [{ name: 'value', type: 'number' }],
46+
impl: (inputs, props) => ({
47+
value: props.value ?? 0
48+
})
49+
};
50+
51+
// Create a graph
52+
const graph: Graph = {
53+
name: 'simple-add',
54+
nodes: [
55+
{ name: 'num1', type: 'js/const/number', props: [{ name: 'value', value: 5 }] },
56+
{ name: 'num2', type: 'js/const/number', props: [{ name: 'value', value: 3 }] },
57+
{ name: 'add', type: 'js/math/add' }
58+
],
59+
edges: [
60+
{ src: { node: 'num1', port: 'value' }, dst: { node: 'add', port: 'a' } },
61+
{ src: { node: 'num2', port: 'value' }, dst: { node: 'add', port: 'b' } }
62+
]
63+
};
64+
65+
// Evaluate the graph
66+
const result = evaluate(graph, {
67+
definitions: [constNumberDef, addDef],
68+
outputNode: 'add',
69+
outputPort: 'sum'
70+
});
71+
72+
console.log(result); // 8
73+
```
74+
75+
## Node Definition with Implementation
76+
77+
```typescript
78+
interface NodeDefinitionWithImpl extends NodeDefinition {
79+
impl: (
80+
inputs: Record<string, any>,
81+
props: Record<string, any>
82+
) => Record<string, any>;
83+
}
84+
```
85+
86+
The `impl` function receives:
87+
- `inputs`: Values from connected input ports
88+
- `props`: Property values set on the node instance
89+
90+
It returns an object with output port names as keys.
91+
92+
## API
93+
94+
### `evaluate(graph, options)`
95+
96+
Evaluates a graph starting from the specified output node/port.
97+
98+
```typescript
99+
const result = evaluate(graph, {
100+
definitions: NodeDefinitionWithImpl[], // Node definitions with implementations
101+
outputNode: string, // Node to get output from
102+
outputPort: string, // Port to get output from
103+
inputs?: Record<string, any>, // External inputs for graphInput nodes
104+
props?: Record<string, any> // Props for graphProp nodes
105+
});
106+
```
107+
108+
## Features
109+
110+
### Lazy Evaluation
111+
112+
Only evaluates nodes that are needed for the output. If a node's output isn't connected to the requested output path, it won't be evaluated.
113+
114+
### Multi-Input Ports
115+
116+
Supports ports that accept multiple incoming edges. Values are collected in edge array order:
117+
118+
```typescript
119+
const mergeDef: NodeDefinitionWithImpl = {
120+
type: 'js/array/merge',
121+
inputs: [{ name: 'items', type: 'any', multi: true }],
122+
outputs: [{ name: 'array', type: 'any[]' }],
123+
impl: (inputs) => ({
124+
array: inputs.items // Array of all connected values
125+
})
126+
};
127+
```
128+
129+
### Boundary Nodes
130+
131+
Supports `graphInput`, `graphOutput`, and `graphProp` boundary nodes for graph inputs/outputs/props:
132+
133+
```typescript
134+
// Provide external inputs
135+
const result = evaluate(graph, {
136+
definitions,
137+
outputNode: 'output_result',
138+
outputPort: 'value',
139+
inputs: { a: 10, b: 20 }, // Keyed by portName
140+
props: { scale: 2.0 } // Keyed by propName
141+
});
142+
```
143+
144+
## Example: Building a Node Library
145+
146+
```typescript
147+
const mathNodes: NodeDefinitionWithImpl[] = [
148+
{
149+
context: 'js',
150+
category: 'math',
151+
type: 'js/math/add',
152+
inputs: [
153+
{ name: 'a', type: 'number' },
154+
{ name: 'b', type: 'number' }
155+
],
156+
outputs: [{ name: 'sum', type: 'number' }],
157+
impl: (inputs) => ({ sum: (inputs.a ?? 0) + (inputs.b ?? 0) })
158+
},
159+
{
160+
context: 'js',
161+
category: 'math',
162+
type: 'js/math/multiply',
163+
inputs: [
164+
{ name: 'a', type: 'number' },
165+
{ name: 'b', type: 'number' }
166+
],
167+
outputs: [{ name: 'product', type: 'number' }],
168+
impl: (inputs) => ({ product: (inputs.a ?? 1) * (inputs.b ?? 1) })
169+
},
170+
{
171+
context: 'js',
172+
category: 'math',
173+
type: 'js/math/negate',
174+
inputs: [{ name: 'value', type: 'number' }],
175+
outputs: [{ name: 'negated', type: 'number' }],
176+
impl: (inputs) => ({ negated: -(inputs.value ?? 0) })
177+
}
178+
];
179+
```
180+
181+
## Best Practices
182+
183+
1. Use descriptive type paths like `context/category/name` (e.g., `js/math/add`)
184+
2. Always provide default values in `impl` functions for missing inputs
185+
3. Keep node implementations pure — no side effects
186+
4. Use `multi: true` for ports that should accept multiple connections

0 commit comments

Comments
 (0)