Add the flow API: typed messages, git-backed store, REST and live events
Makes the flow engine reachable from the API, which is what M3 needs before
any of it can reach the browser.
- app/flow is a package now; the prototype's watch-dir scripts and the
matplotlib/networkx visualiser are gone with their dependencies.
- Messages carry a serializable dtype instead of a live Python type, and a
port name, so the graph can speak qualified names while node functions keep
local arguments. Redis state is JSON, not pickle.
- Message names are namespaced per flow ("heating.temp"); a bare name resolves
to its own flow, a dotted one crosses flows.
- Several nodes may provide the same message: producers are a list, so fan-in
is a real edge instead of a silently dropped one.
- Flows are stored as flow.json plus node sources in a git repository, one
commit per save, with identical saves skipped so autosave stays quiet.
- Node failures are isolated and reported per node; validate() returns cycles
and unconnected inputs instead of raising deep in a run.
- Credentials live in an encrypted store and are referenced as {"$secret": …}.
- Engine events reach websocket clients through a bus, so values, node status
and execution show up live.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016WzrvW7rjQbynnhF6pxh6i
This commit is contained in:
co-authored by
Claude Fable 5
parent
61be29827d
commit
06a4506767
+16
-11
@@ -19,12 +19,9 @@ dependencies = [
|
||||
"sentry-sdk[fastapi]<2.0.0,>=1.40.6",
|
||||
"pyjwt<3.0.0,>=2.8.0",
|
||||
"pwdlib[argon2,bcrypt]>=0.3.0",
|
||||
"networkx>=3.4.2",
|
||||
"numpy>=2.2.6",
|
||||
"matplotlib>=3.10.8",
|
||||
"redis>=7.1.0",
|
||||
"scipy>=1.15.3",
|
||||
"watchfiles>=1.0.0",
|
||||
"cryptography>=44.0.0",
|
||||
"aiomqtt>=2.0.0",
|
||||
"influxdb-client[async]>=1.40.0",
|
||||
"croniter>=1.3.0",
|
||||
@@ -45,16 +42,18 @@ build-backend = "hatchling.build"
|
||||
|
||||
[tool.mypy]
|
||||
strict = true
|
||||
# app/flow is the standalone flow-engine prototype: it is not importable as a
|
||||
# package yet (no __init__.py, top-level sibling imports) and nothing in the API
|
||||
# reaches it. Type-checking it would only report on code that is scheduled to be
|
||||
# restructured — see NOTEPAD.md. Drop the exclusion when it is wired up.
|
||||
exclude = ["venv", ".venv", "alembic", "app/flow"]
|
||||
exclude = ["venv", ".venv", "alembic"]
|
||||
|
||||
# app/flow/nodes.py still carries the prototype's node classes, and state.py's
|
||||
# redis calls type as sync/async unions under the current stubs. Both are being
|
||||
# revisited; every module around them is checked strictly.
|
||||
[[tool.mypy.overrides]]
|
||||
module = ["app.flow.nodes", "app.flow.pipeline", "app.flow.state"]
|
||||
ignore_errors = true
|
||||
|
||||
[tool.ruff]
|
||||
target-version = "py310"
|
||||
# See the note on the same exclusion under [tool.mypy].
|
||||
exclude = ["alembic", "app/flow"]
|
||||
exclude = ["alembic"]
|
||||
|
||||
[tool.ruff.lint]
|
||||
select = [
|
||||
@@ -75,6 +74,12 @@ ignore = [
|
||||
"B904", # Allow raising exceptions without from e, for HTTPException
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
# Node functions take `params` whether or not they use it — that is the
|
||||
# contract the engine calls them with.
|
||||
"app/flow/nodes.py" = ["ARG001", "ARG002"]
|
||||
"tests/flow/*" = ["ARG001"]
|
||||
|
||||
[tool.ruff.lint.pyupgrade]
|
||||
# Preserve types, even if a file imports `from __future__ import annotations`.
|
||||
keep-runtime-typing = true
|
||||
|
||||
Reference in New Issue
Block a user