Releases: zvictor/BrainyFlow
TypeScript Package v2.1.0
BrainyFlow TypeScript Package v2.1.0
Automatic Triggers Propagation
Since v2.0, Brainyflow propagates triggers from terminal nodes (i.e. nodes missing successors) to subsequent flows. This let you permeate an action from a node directly to outside of the parent flow, skipping the need to explicitly re-trigger the actions at the end of every flow execution.
This allows for more fluid and permeable flows, and effectively stops the parent flow from being a rigid barrier in the graph execution.
Think about it as "handing over unfinished tasks in a flow to the first node in the next flow".
It also means that you can preserve the concurrency of that execution path as you navigate into the next flow: the execution doesn’t end at the leaf node, it continues into the next flow.
Ignoring Implicit Triggers Propagation
In v2.1 we are stopping the propagation of Implicit Triggers - the default action that is automatically triggered when no .trigger()
was explicitly called - to give users more control over trigger's propagation and avoid unexpected behavior.
Thus, this is the behaviour you can expect:
- If a terminal node does NOT explicitly call
.trigger()
, no action is propagated from that terminal node. - If a terminal node calls
.trigger()
, then the parent flow propagates that action to its own sucessors - and any forking data passed is preserved.
Check https://brainy.gitbook.io/flow/core-abstraction/flow for more info!
Installation
npm install [email protected]
pnpm add [email protected]
yarn add [email protected]
NPM Package
Python Package v2.1.0
BrainyFlow Python Package v2.1.0
Automatic Triggers Propagation
Since v2.0, Brainyflow propagates triggers from terminal nodes (i.e. nodes missing successors) to subsequent flows. This let you permeate an action from a node directly to outside of the parent flow, skipping the need to explicitly re-trigger the actions at the end of every flow execution.
This allows for more fluid and permeable flows, and effectively stops the parent flow from being a rigid barrier in the graph execution.
Think about it as "handing over unfinished tasks in a flow to the first node in the next flow".
It also means that you can preserve the concurrency of that execution path as you navigate into the next flow: the execution doesn’t end at the leaf node, it continues into the next flow.
Ignoring Implicit Triggers Propagation
In v2.1 we are stopping the propagation of Implicit Triggers - the default action that is automatically triggered when no .trigger()
was explicitly called - to give users more control over trigger's propagation and avoid unexpected behavior.
Thus, this is the behaviour you can expect:
- If a terminal node does NOT explicitly call
.trigger()
, no action is propagated from that terminal node. - If a terminal node calls
.trigger()
, then the parent flow propagates that action to its own sucessors - and any forking data passed is preserved.
Check https://brainy.gitbook.io/flow/core-abstraction/flow for more info!
Installation
pip install brainyflow==2.1.0
PyPI Package
TypeScript Package v2.0.0
BrainyFlow TypeScript Package v2.0.0
NPM Package
Major Changes
-
7dc9291: # Major Refactor and Enhancement for TypeScript
This release introduces significant improvements to
Memory
management,Flow
execution, and overall type safety.Breaking Changes
- Flow as Node - Trigger Propagation: When a sub-flow (acting as a node) has an internal node triggering an action for which the sub-flow has no defined successor, this action now correctly propagates as a trigger from the sub-flow node itself in the parent flow's
ExecutionTree
. - Simplified Generic Types: The generic type hints for
Flow
andNode
have been simplified, removing theL
(i.e.LocalMemory
) type parameter and moving theActionT
to the end of the list as it is rarely used. The local memory type can be defined inside the Global by using the property.local
. Before:Node[G, L, ActionT, PrepResultT, ExecResultT]
; Now:Node[G, PrepResultT, ExecResultT, ActionT]
. - New License: Brainyflow is now licensed under the Mozilla Public License 2.0.
Rarely used other than internally, but still breaking changes:
- Memory Creation:
Memory.create(global, local)
static method is removed. To create a memory object, just pass a plain object toflow.run({ ... })
as you always did or call thecreateMemory(global, local)
factory function instead. This aligns with a more functional approach for creating the proxiedMemory
objects. - Memory Type:
Memory
is now an exported type alias representing the complex proxied structure, not a class to be instantiated directly withnew
. - Flow Execution Result:
Flow.run()
now returns anExecutionTree
object, providing a structured representation of the flow's execution path, triggered actions, and sub-node results. This replaces the previous less-structured result. TheExecutionTree
structure is:type ExecutionTree = { order: number type: string triggered: Record<Action, ExecutionTree[]> | null }
- Node
__nodeOrder
: The__nodeOrder
property onBaseNode
is now consistently a number.
Core Library Changes & New Features
Memory Management (
createMemory
)- Proxy-Based Implementation:
createMemory
function now constructsMemory
objects using nested proxies to manage global and local scopes, closely mirroring the advanced PythonMemory
behavior. - Deletion and Existence: The
Memory
proxy handler now supportsdeleteProperty
(fordelete memory.key
) andhas
(for'key' in memory
), operating on both local and global stores appropriately.memory.local
proxy also supports these for the local scope. - Type Safety:
Memory
type uses genericsGlobalStore
andLocalStore
for better type inference._isMemoryObject
flag added for runtime type assertions if needed.
Flow Execution &
ExecutionTree
Flow.run()
: Returns a detailedExecutionTree
.- Cycle Detection: Default
maxVisits
forFlow
instances increased from 5 to 15. Error messages for cycle detection now include node class name and ID (e.g.,Maximum cycle count (15) reached for TestNode#0
). - Node
__nodeOrder
: Now consistently a number. Theorder
field inExecutionTree
is also a number.
Node Lifecycle and Error Handling
BaseNode.triggers
: Changed from private to protected to allow manipulation in subclasses if necessary (e.g., for complex trigger logic inParallelFlow
tests).NodeError
: Remains anError
subtype with an optionalretryCount
.- Warnings:
- The warning "Node won't run successors. Use Flow!" when
run()
is called on aBaseNode
with successors has been removed to reduce noise. #20 - Warning for an "orphan action" (action triggered with no successor) in
get_next_nodes
has been refined for better clarity:Flow ends for node {ClassName}#{node_order}: Action '{action}' not found in its defined successors [...]
.
- The warning "Node won't run successors. Use Flow!" when
Developer Experience & Testing
- Test Suite: Comprehensive updates to
memory.test.ts
andflow.test.ts
to cover newMemory
functionalities (including cloning, local proxy operations, deletion, existence checks) and the newExecutionTree
structure. - Mock Resetting: Improved mock handling in tests for better isolation, particularly for
TestNode
instances. - Type Generics: Enhanced use of generics in
TestNode
andBranchingNode
for better type safety in tests.
Bug Fixes
- V8 Debugger Craskeeping
structuredClone
and Proxies: Resolved by ensuringstructuredClone
inmemory.clone()
operates on plain object representations of proxied data. ExecutionTree
Structure: Standardized and made more robust.- Type Inconsistencies: Addressed various type issues for a more stable and predictable API.
This major update significantly enhances the capabilities and reliability of the TypeScript port, especially around state management and flow execution tracking.
- Flow as Node - Trigger Propagation: When a sub-flow (acting as a node) has an internal node triggering an action for which the sub-flow has no defined successor, this action now correctly propagates as a trigger from the sub-flow node itself in the parent flow's
1.0.0
Major Changes
-
Refactor: Introduce Memory, trigger mechanism; remove Batch classes and params
This release introduces a major architectural refactor:
- Replaced the dictionary-based
shared
store with aMemory
class managing global and local state via proxy access. - Nodes now use
this.trigger("action", forkingData)
inpost
to control flow instead of returning action strings. - Removed the
params
mechanism (setParams
). Context should be passed viaMemory
(global or local viaforkingData
). - Removed
BatchNode
,ParallelBatchNode
,SequentialBatchFlow
,ParallelBatchFlow
. Batch processing is now achieved using standardNode
s withinFlow
orParallelFlow
(e.g., fan-out pattern). - Updated documentation and tests extensively to reflect these changes.
- Replaced the dictionary-based
Python Package v2.0.0
BrainyFlow Python Package v2.0.0
Installation
pip install brainyflow
PyPI Package
Major Changes
-
10289fa: # Major Refactor and Enhancement Release (Python)
This release introduces a significant overhaul of the
Memory
class, refinesFlow
execution and cycle detection, and improves overall type safety and developer experience.Breaking Changes
- Flow as Node - Trigger Propagation: When a sub-flow (acting as a node) has an internal node triggering an action for which the sub-flow has no defined successor, this action now correctly propagates as a trigger from the sub-flow node itself in the parent flow's
ExecutionTree
. - Simplified Generic Type Hints: The generic type hints for
Flow
andNode
have been simplified, removing theL
(i.e.LocalMemory
) type parameter and moving theActionT
to the end of the list as it is rarely used. Before:Node[G, L, ActionT, PrepResultT, ExecResultT]
; Now:Node[G, PrepResultT, ExecResultT, ActionT]
. - NodeError: Changed from an
Exception
subclass to aProtocol
(runtime_checkable
). This affects howNodeError
might be caught or checked, promoting structural typing and fixing the double-raising of the exception. - New License: Brainyflow is now licensed under the Mozilla Public License 2.0.
Rarely used other than internally, but still breaking changes:
- Memory Creation: The static method
Memory.create(global_store, local_store=None)
has been removed. To createMemory
instances, just pass a dict toflow.run({ ... })
as you always did, or use the standard constructor:Memory(global_store, local_store=None)
. - Flow Execution Result (
Flow.run()
): Therun()
method of aFlow
now returns anExecutionTree
(aTypedDict
withorder: int
,type: str
,triggered: Optional[Dict[Action, List[ExecutionTree]]]
). This provides a structured log of the execution, replacing the previous, less defined dictionary structure. Code that previously traversed therun()
result will need to be updated to work with the newExecutionTree
format. - Internal Node Order (
_node_order
): This is now consistently an integer.
Core Library Changes & New Features
Memory Management (
Memory
Class)- Enhanced Proxy Behavior:
memory.local
now returns a dedicatedLocalProxy
instance, providing isolated attribute and item access (getattr
,getitem
,setattr
,setitem
,delattr
,delitem
,contains
) that operates only on the local store.- The main
Memory
object's attribute/item access (memory.foo
,memory['foo']
) continues to prioritize local then global for reads. - Writes (
memory.foo = 'bar'
,memory['foo'] = 'bar'
) now consistently write to the global store, removing the key from the local store first if it exists there.
- Comprehensive Deletion Support:
del memory.attr
anddel memory[key]
now delete the key from both global and local stores if present in either (delegating to_delete_from_stores
).del memory.local.attr
anddel memory.local[key]
delete only from the local store.
- Helper Functions: Internal
_get_from_stores
and_delete_from_stores
utility functions have been added to centralize store access logic. - Cloning:
memory.clone(forking_data=None)
remains, ensuring deep copy of the local store and merging offorking_data
. Global store is shared by reference.
Flow Execution & Cycle Detection
Flow.run()
andExecutionTree
: As mentioned in Breaking Changes, returns a structuredExecutionTree
.- Default
maxVisits
: Increased from 5 to 15 in theFlow
constructor for cycle detection. - Cycle Detection Error Message: Improved format to:
Maximum cycle count ({max_visits}) reached for {ClassName}#{node_order}
.
Node Lifecycle and Error Handling
NodeError
Protocol: Now atyping.Protocol
for more flexible error handling.error.retry_count
is added to exceptions during the retry mechanism inNode.exec_runner
.- Warnings:
- The warning "Node won't run successors. Use Flow!" when
run()
is called on aBaseNode
with successors has been removed to reduce noise. #20 - Warning for an "orphan action" (action triggered with no successor) in
get_next_nodes
has been refined for better clarity:Flow ends for node {ClassName}#{node_order}: Action '{action}' not found in its defined successors [...]
.
- The warning "Node won't run successors. Use Flow!" when
Type Annotations & Developer Experience
- Improved Type Hints: Extensive improvements to type annotations throughout the library using
TypeVar
,Generic
,Protocol
,TypeAlias
, andTypedDict
for better static analysis and developer understanding. All MyPy errors and inconsistencies addressed. - Test Suite Enhancements:
- Tests for new
Memory
deletion features andLocalProxy
behavior. - Updated assertions for the new
ExecutionTree
structure. BaseNode._next_id
is reset in test fixtures/setups for predictable node ordering in tests.- More robust mocking and assertions for flow execution paths.
- Tests for new
- Documentation:
- Migration guide (
migrating_from_pocketflow.md
) updated with clearer steps forasync
, trigger usage, memory access, and the new batch processing pattern. - Core abstraction documentation (
flow.md
,design.md
) updated to reflect changes (e.g.,maxVisits
,Memory
creation). - "Contributors Wanted!" section added to
README.md
.
- Migration guide (
Infrastructure Improvements
- CI/CD: GitHub Actions workflow
changeset-check.yml
updated to usechangesets/[email protected]
and properly prepare the Python directory for changeset tooling. .envrc
: Addeddotenv_if_exists
..gitignore
: Addedpython/README.md
(if it's auto-generated and shouldn't be committed).
This release significantly modernizes the Python BrainyFlow library, especially its state management capabilities and execution tracking, while enhancing type safety and the overall development experience.
- Flow as Node - Trigger Propagation: When a sub-flow (acting as a node) has an internal node triggering an action for which the sub-flow has no defined successor, this action now correctly propagates as a trigger from the sub-flow node itself in the parent flow's