flowli 0.1.0__tar.gz

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.
Files changed (64) hide show
  1. flowli-0.1.0/LICENSE +21 -0
  2. flowli-0.1.0/PKG-INFO +207 -0
  3. flowli-0.1.0/README.md +157 -0
  4. flowli-0.1.0/pyproject.toml +101 -0
  5. flowli-0.1.0/setup.cfg +4 -0
  6. flowli-0.1.0/src/flowli/__init__.py +3 -0
  7. flowli-0.1.0/src/flowli/adapters/__init__.py +1 -0
  8. flowli-0.1.0/src/flowli/adapters/cairndb.py +832 -0
  9. flowli-0.1.0/src/flowli/adapters/cairndb_projection.py +766 -0
  10. flowli-0.1.0/src/flowli/adapters/evidence.py +76 -0
  11. flowli-0.1.0/src/flowli/adapters/memory.py +554 -0
  12. flowli-0.1.0/src/flowli/api/__init__.py +27 -0
  13. flowli-0.1.0/src/flowli/api/app.py +72 -0
  14. flowli-0.1.0/src/flowli/api/auth.py +223 -0
  15. flowli-0.1.0/src/flowli/api/catalog.py +124 -0
  16. flowli-0.1.0/src/flowli/api/deps.py +101 -0
  17. flowli-0.1.0/src/flowli/api/dto.py +236 -0
  18. flowli-0.1.0/src/flowli/api/frames.py +137 -0
  19. flowli-0.1.0/src/flowli/api/problems.py +87 -0
  20. flowli-0.1.0/src/flowli/api/reads.py +78 -0
  21. flowli-0.1.0/src/flowli/api/routes/__init__.py +17 -0
  22. flowli-0.1.0/src/flowli/api/routes/catalog.py +31 -0
  23. flowli-0.1.0/src/flowli/api/routes/evidence.py +125 -0
  24. flowli-0.1.0/src/flowli/api/routes/executions.py +280 -0
  25. flowli-0.1.0/src/flowli/api/routes/queues.py +60 -0
  26. flowli-0.1.0/src/flowli/api/routes/reviews.py +80 -0
  27. flowli-0.1.0/src/flowli/api/routes/worker.py +198 -0
  28. flowli-0.1.0/src/flowli/cli.py +595 -0
  29. flowli-0.1.0/src/flowli/cli_render.py +178 -0
  30. flowli-0.1.0/src/flowli/codec.py +89 -0
  31. flowli-0.1.0/src/flowli/domain/__init__.py +142 -0
  32. flowli-0.1.0/src/flowli/domain/channels.py +23 -0
  33. flowli-0.1.0/src/flowli/domain/errors.py +69 -0
  34. flowli-0.1.0/src/flowli/domain/execution.py +61 -0
  35. flowli-0.1.0/src/flowli/domain/frames.py +150 -0
  36. flowli-0.1.0/src/flowli/domain/journal.py +292 -0
  37. flowli-0.1.0/src/flowli/domain/names.py +55 -0
  38. flowli-0.1.0/src/flowli/domain/ports.py +310 -0
  39. flowli-0.1.0/src/flowli/domain/provenance.py +84 -0
  40. flowli-0.1.0/src/flowli/domain/tasks.py +83 -0
  41. flowli-0.1.0/src/flowli/domain/timers.py +30 -0
  42. flowli-0.1.0/src/flowli/evidence.py +181 -0
  43. flowli-0.1.0/src/flowli/log.py +89 -0
  44. flowli-0.1.0/src/flowli/patterns/__init__.py +18 -0
  45. flowli-0.1.0/src/flowli/patterns/delegate.py +72 -0
  46. flowli-0.1.0/src/flowli/patterns/fanout.py +25 -0
  47. flowli-0.1.0/src/flowli/patterns/review.py +112 -0
  48. flowli-0.1.0/src/flowli/patterns/saga.py +39 -0
  49. flowli-0.1.0/src/flowli/patterns/schedule.py +32 -0
  50. flowli-0.1.0/src/flowli/py.typed +0 -0
  51. flowli-0.1.0/src/flowli/runtime/__init__.py +56 -0
  52. flowli-0.1.0/src/flowli/runtime/consumer.py +351 -0
  53. flowli-0.1.0/src/flowli/runtime/context.py +714 -0
  54. flowli-0.1.0/src/flowli/runtime/engine.py +412 -0
  55. flowli-0.1.0/src/flowli/runtime/registry.py +48 -0
  56. flowli-0.1.0/src/flowli/runtime/retention.py +119 -0
  57. flowli-0.1.0/src/flowli/runtime/sweeper.py +250 -0
  58. flowli-0.1.0/src/flowli/runtime/worker.py +430 -0
  59. flowli-0.1.0/src/flowli.egg-info/PKG-INFO +207 -0
  60. flowli-0.1.0/src/flowli.egg-info/SOURCES.txt +62 -0
  61. flowli-0.1.0/src/flowli.egg-info/dependency_links.txt +1 -0
  62. flowli-0.1.0/src/flowli.egg-info/entry_points.txt +2 -0
  63. flowli-0.1.0/src/flowli.egg-info/requires.txt +35 -0
  64. flowli-0.1.0/src/flowli.egg-info/top_level.txt +1 -0
flowli-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Thomas Zamojski
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
flowli-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,207 @@
1
+ Metadata-Version: 2.4
2
+ Name: flowli
3
+ Version: 0.1.0
4
+ Summary: Workflow engine: a journaled coroutine execution stack on CairnDB
5
+ Author: Thomas Zamojski
6
+ License-Expression: MIT
7
+ Project-URL: Documentation, https://quadratic-labs.github.io/flowli/
8
+ Project-URL: Repository, https://github.com/Quadratic-Labs/flowli
9
+ Project-URL: Changelog, https://github.com/Quadratic-Labs/flowli/blob/main/CHANGELOG.md
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.14
14
+ Classifier: Typing :: Typed
15
+ Requires-Python: >=3.14
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: cairndb<0.5,>=0.4.1
19
+ Requires-Dist: cattrs>=24.1.0
20
+ Requires-Dist: structlog>=24.1.0
21
+ Provides-Extra: cli
22
+ Requires-Dist: typer>=0.9.0; extra == "cli"
23
+ Requires-Dist: rich>=13.8.0; extra == "cli"
24
+ Requires-Dist: uvicorn>=0.52.4; extra == "cli"
25
+ Provides-Extra: api
26
+ Requires-Dist: fastapi>=0.115.0; extra == "api"
27
+ Requires-Dist: pydantic>=2.7.0; extra == "api"
28
+ Requires-Dist: pyjwt[crypto]>=2.9.0; extra == "api"
29
+ Requires-Dist: uvicorn>=0.52.4; extra == "api"
30
+ Provides-Extra: docs
31
+ Requires-Dist: sphinx>=8.1.0; extra == "docs"
32
+ Requires-Dist: myst-parser>=4.0.0; extra == "docs"
33
+ Requires-Dist: furo>=2024.8.6; extra == "docs"
34
+ Requires-Dist: sphinx-design>=0.6.0; extra == "docs"
35
+ Requires-Dist: sphinx-copybutton>=0.5.2; extra == "docs"
36
+ Requires-Dist: sphinxcontrib-mermaid>=1.0.0; extra == "docs"
37
+ Requires-Dist: sphinx-autobuild>=2024.10.3; extra == "docs"
38
+ Provides-Extra: dev
39
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
40
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
41
+ Requires-Dist: hypothesis>=6.98.0; extra == "dev"
42
+ Requires-Dist: ruff>=0.2.0; extra == "dev"
43
+ Requires-Dist: mypy>=1.8.0; extra == "dev"
44
+ Requires-Dist: fastapi>=0.115.0; extra == "dev"
45
+ Requires-Dist: httpx>=0.27.0; extra == "dev"
46
+ Requires-Dist: pyjwt[crypto]>=2.9.0; extra == "dev"
47
+ Requires-Dist: asgi-lifespan>=2.1.0; extra == "dev"
48
+ Requires-Dist: uvicorn>=0.52.4; extra == "dev"
49
+ Dynamic: license-file
50
+
51
+ # flowli
52
+
53
+ A workflow engine that runs a workflow as a coroutine execution stack and
54
+ journals every frame to CairnDB.
55
+
56
+ **Documentation: <https://quadratic-labs.github.io/flowli/>** — the quickstart,
57
+ the concepts, the architecture, every setting, the hosting guide, and the API
58
+ reference from the docstrings. The specifications stay in `specs/`.
59
+
60
+ ```bash
61
+ uv sync --extra docs
62
+ uv run sphinx-build -b html -W docs docs/_build/html # or: make -C docs livehtml
63
+ ```
64
+
65
+ Layout:
66
+
67
+ - `src/flowli/domain/` — pure domain objects and ports. No I/O, no CairnDB import.
68
+ - `src/flowli/adapters/` — port implementations (CairnDB, in-memory).
69
+ - `src/flowli/api/` — the HTTP service (the `api` extra).
70
+ - `web/` — the operator interface over that service.
71
+ - `runner/` — `flowli-runner`: coding agents as delegate consumers.
72
+ - `codeflow/` — `flowli-codeflow`: the controller over the runner.
73
+
74
+ ## Running the jobs
75
+
76
+ Install with the CLI extra, then point the CLI at your workflow registry:
77
+
78
+ ```bash
79
+ pip install "flowli[cli]"
80
+ export CAIRNDB_STORAGE_TYPE=s3 CAIRNDB_S3_BUCKET=my-bucket # or --storage-path ./bucket
81
+
82
+ flowli worker --app myapp.flows:registry --queue default --queue finance
83
+ flowli sweeper --app myapp.flows:registry --interval 60
84
+ flowli retention --app myapp.flows:registry --delay-days 30 --once
85
+ ```
86
+
87
+ `--app module:attr` names a `Registry`, an `Engine`, or a zero-argument callable
88
+ returning one. With a `Registry` the CLI builds the CairnDB backend from the
89
+ `CAIRNDB_*` variables. `--once` runs one pass and exits, which suits a cron job.
90
+ `--projection PATH` makes the sweeper and retention read statuses from the SQLite
91
+ projection instead of folding the control log. Every job stops cleanly on
92
+ SIGINT or SIGTERM.
93
+
94
+ Operator commands share the same `--app` and storage options:
95
+
96
+ ```bash
97
+ flowli status EID --journal
98
+ flowli signal EID payments '{"amount": 100}' --by bank@example.com
99
+ flowli cancel EID --by ops@example.com
100
+ flowli migrate EID 2 --by ops@example.com
101
+ ```
102
+
103
+ `--by` names the actor recorded in provenance: an email, or `kind:id` with kind
104
+ `human`, `system`, `schedule` or `worker`. It defaults to the local user, or to
105
+ `FLOWLI_BY`. Commands exit with code 1 on an unknown execution or a refused
106
+ action, such as cancelling a finished execution.
107
+
108
+ ## What the commands print
109
+
110
+ `status` answers the two questions an operator arrives with — where is it, and
111
+ what happened last:
112
+
113
+ ```
114
+ eid 01a093cc-265e-730a-b05c-e7e36d377452
115
+ status completed
116
+ workflow greet v1
117
+ queue default
118
+ created 2026-09-12T04:07:05.054046Z by human:thomas@example.com
119
+ last execution.completed at 2026-09-12T04:07:05.128988Z by worker:w-1 on host-3 epoch 1
120
+ payload
121
+ {
122
+ "value": "hi zoe"
123
+ }
124
+ ```
125
+
126
+ A suspended execution names what it waits for instead of a payload:
127
+
128
+ ```
129
+ status suspended
130
+ last execution.suspended at 2026-09-12T04:07:05.193632Z by worker:w-1 on host-3 epoch 1
131
+ waiting channel:01a093cc-26cd-7373-8944-38c18b531442.go
132
+ ```
133
+
134
+ `--journal` appends the whole log, one event per line:
135
+
136
+ ```
137
+ seq type fid at actor
138
+ 1000000 execution.started root 2026-09-12T04:07:05.128988Z worker:w-1
139
+ 2000000 frame.started root/greet#0 2026-09-12T04:07:05.139587Z worker:w-1
140
+ 3000000 frame.completed root/greet#0 2026-09-12T04:07:05.139587Z worker:w-1
141
+ 4000000 execution.completed root 2026-09-12T04:07:05.128988Z worker:w-1
142
+ ```
143
+
144
+ Every `--once` job answers with one line of counters, which suits a cron job
145
+ that mails its output:
146
+
147
+ ```bash
148
+ flowli sweeper --once # timers_fired=1 recovered=0 restarted=0 repaired=0 waits_cleared=0
149
+ flowli retention --once # archived=1 cleaned=0, then one line per archived execution
150
+ flowli-runner --once # recovered=0 processed=1, then one line per reattached task
151
+ flowli-codeflow merge --once # merged=1
152
+ flowli-codeflow board --once # reconciled=3
153
+ ```
154
+
155
+ ### Colour
156
+
157
+ On a terminal the output is coloured: the status by what it means (green
158
+ completed, red failed, yellow suspended), workflow names in cyan, timestamps
159
+ and actor kinds dimmed so the identity stands out, and JSON payloads syntax
160
+ highlighted. The theme paints with the terminal's own sixteen colours, so it
161
+ suits a light background as well as a dark one.
162
+
163
+ **Piped output is plain text, byte for byte.** Redirect the output, capture it
164
+ in a test, or run it under `cron`, and you get exactly the columns above with
165
+ no escape sequences — so `grep`, `awk` and `cut` keep working. Set `NO_COLOR`
166
+ to drop the colour on a terminal too.
167
+
168
+ ## The HTTP service and the interface
169
+
170
+ ```bash
171
+ pip install "flowli[api]"
172
+ uv run python web/dev_server.py # an engine, a worker and the service
173
+ cd web && npm install && npm run dev # the operator interface
174
+ ```
175
+
176
+ `flowli.api.create_app(engine, projection=..., authenticator=...)` is the
177
+ service: the catalog and the control plane (`specs/09-http-api.md`,
178
+ sections 7 and 8), the worker plane for consumers that cannot reach the bucket
179
+ (section 9), and evidence (section 10). It holds no state of its own: reads
180
+ come from the projection, writes go through the engine, and the actor of every
181
+ write comes from the access token.
182
+
183
+ `web/` is the interface over it. `web/dev_server.py` runs a demo backend for
184
+ it. See `web/README.md`.
185
+
186
+ ## Logging
187
+
188
+ Every component emits structured events through structlog, the library CairnDB
189
+ uses, so one configuration produces one stream:
190
+
191
+ ```python
192
+ from flowli.log import configure_logging
193
+ configure_logging("INFO", "json") # or "console"
194
+ ```
195
+
196
+ All three CLIs — `flowli`, `flowli-runner` and `flowli-codeflow` — take
197
+ `--log-level` and `--log-format console|json`; `flowli` also reads
198
+ `FLOWLI_LOG_LEVEL` and `FLOWLI_LOG_FORMAT`. Logs go to stderr, so a job's
199
+ report on stdout stays pipeable on its own. Events are named with snake_case
200
+ nouns such as `execution_started`, `execution_suspended`, `frame_failed`,
201
+ `execution_recovered` and `execution_archived`. While a worker holds a task,
202
+ `worker_id`, `task_id`, `eid` and `epoch` are bound to every event it emits, and
203
+ live frames add `fid` and `attempt`. Frame events are at DEBUG level.
204
+
205
+ ## License
206
+
207
+ MIT. See [LICENSE](https://github.com/Quadratic-Labs/flowli/blob/main/LICENSE).
flowli-0.1.0/README.md ADDED
@@ -0,0 +1,157 @@
1
+ # flowli
2
+
3
+ A workflow engine that runs a workflow as a coroutine execution stack and
4
+ journals every frame to CairnDB.
5
+
6
+ **Documentation: <https://quadratic-labs.github.io/flowli/>** — the quickstart,
7
+ the concepts, the architecture, every setting, the hosting guide, and the API
8
+ reference from the docstrings. The specifications stay in `specs/`.
9
+
10
+ ```bash
11
+ uv sync --extra docs
12
+ uv run sphinx-build -b html -W docs docs/_build/html # or: make -C docs livehtml
13
+ ```
14
+
15
+ Layout:
16
+
17
+ - `src/flowli/domain/` — pure domain objects and ports. No I/O, no CairnDB import.
18
+ - `src/flowli/adapters/` — port implementations (CairnDB, in-memory).
19
+ - `src/flowli/api/` — the HTTP service (the `api` extra).
20
+ - `web/` — the operator interface over that service.
21
+ - `runner/` — `flowli-runner`: coding agents as delegate consumers.
22
+ - `codeflow/` — `flowli-codeflow`: the controller over the runner.
23
+
24
+ ## Running the jobs
25
+
26
+ Install with the CLI extra, then point the CLI at your workflow registry:
27
+
28
+ ```bash
29
+ pip install "flowli[cli]"
30
+ export CAIRNDB_STORAGE_TYPE=s3 CAIRNDB_S3_BUCKET=my-bucket # or --storage-path ./bucket
31
+
32
+ flowli worker --app myapp.flows:registry --queue default --queue finance
33
+ flowli sweeper --app myapp.flows:registry --interval 60
34
+ flowli retention --app myapp.flows:registry --delay-days 30 --once
35
+ ```
36
+
37
+ `--app module:attr` names a `Registry`, an `Engine`, or a zero-argument callable
38
+ returning one. With a `Registry` the CLI builds the CairnDB backend from the
39
+ `CAIRNDB_*` variables. `--once` runs one pass and exits, which suits a cron job.
40
+ `--projection PATH` makes the sweeper and retention read statuses from the SQLite
41
+ projection instead of folding the control log. Every job stops cleanly on
42
+ SIGINT or SIGTERM.
43
+
44
+ Operator commands share the same `--app` and storage options:
45
+
46
+ ```bash
47
+ flowli status EID --journal
48
+ flowli signal EID payments '{"amount": 100}' --by bank@example.com
49
+ flowli cancel EID --by ops@example.com
50
+ flowli migrate EID 2 --by ops@example.com
51
+ ```
52
+
53
+ `--by` names the actor recorded in provenance: an email, or `kind:id` with kind
54
+ `human`, `system`, `schedule` or `worker`. It defaults to the local user, or to
55
+ `FLOWLI_BY`. Commands exit with code 1 on an unknown execution or a refused
56
+ action, such as cancelling a finished execution.
57
+
58
+ ## What the commands print
59
+
60
+ `status` answers the two questions an operator arrives with — where is it, and
61
+ what happened last:
62
+
63
+ ```
64
+ eid 01a093cc-265e-730a-b05c-e7e36d377452
65
+ status completed
66
+ workflow greet v1
67
+ queue default
68
+ created 2026-09-12T04:07:05.054046Z by human:thomas@example.com
69
+ last execution.completed at 2026-09-12T04:07:05.128988Z by worker:w-1 on host-3 epoch 1
70
+ payload
71
+ {
72
+ "value": "hi zoe"
73
+ }
74
+ ```
75
+
76
+ A suspended execution names what it waits for instead of a payload:
77
+
78
+ ```
79
+ status suspended
80
+ last execution.suspended at 2026-09-12T04:07:05.193632Z by worker:w-1 on host-3 epoch 1
81
+ waiting channel:01a093cc-26cd-7373-8944-38c18b531442.go
82
+ ```
83
+
84
+ `--journal` appends the whole log, one event per line:
85
+
86
+ ```
87
+ seq type fid at actor
88
+ 1000000 execution.started root 2026-09-12T04:07:05.128988Z worker:w-1
89
+ 2000000 frame.started root/greet#0 2026-09-12T04:07:05.139587Z worker:w-1
90
+ 3000000 frame.completed root/greet#0 2026-09-12T04:07:05.139587Z worker:w-1
91
+ 4000000 execution.completed root 2026-09-12T04:07:05.128988Z worker:w-1
92
+ ```
93
+
94
+ Every `--once` job answers with one line of counters, which suits a cron job
95
+ that mails its output:
96
+
97
+ ```bash
98
+ flowli sweeper --once # timers_fired=1 recovered=0 restarted=0 repaired=0 waits_cleared=0
99
+ flowli retention --once # archived=1 cleaned=0, then one line per archived execution
100
+ flowli-runner --once # recovered=0 processed=1, then one line per reattached task
101
+ flowli-codeflow merge --once # merged=1
102
+ flowli-codeflow board --once # reconciled=3
103
+ ```
104
+
105
+ ### Colour
106
+
107
+ On a terminal the output is coloured: the status by what it means (green
108
+ completed, red failed, yellow suspended), workflow names in cyan, timestamps
109
+ and actor kinds dimmed so the identity stands out, and JSON payloads syntax
110
+ highlighted. The theme paints with the terminal's own sixteen colours, so it
111
+ suits a light background as well as a dark one.
112
+
113
+ **Piped output is plain text, byte for byte.** Redirect the output, capture it
114
+ in a test, or run it under `cron`, and you get exactly the columns above with
115
+ no escape sequences — so `grep`, `awk` and `cut` keep working. Set `NO_COLOR`
116
+ to drop the colour on a terminal too.
117
+
118
+ ## The HTTP service and the interface
119
+
120
+ ```bash
121
+ pip install "flowli[api]"
122
+ uv run python web/dev_server.py # an engine, a worker and the service
123
+ cd web && npm install && npm run dev # the operator interface
124
+ ```
125
+
126
+ `flowli.api.create_app(engine, projection=..., authenticator=...)` is the
127
+ service: the catalog and the control plane (`specs/09-http-api.md`,
128
+ sections 7 and 8), the worker plane for consumers that cannot reach the bucket
129
+ (section 9), and evidence (section 10). It holds no state of its own: reads
130
+ come from the projection, writes go through the engine, and the actor of every
131
+ write comes from the access token.
132
+
133
+ `web/` is the interface over it. `web/dev_server.py` runs a demo backend for
134
+ it. See `web/README.md`.
135
+
136
+ ## Logging
137
+
138
+ Every component emits structured events through structlog, the library CairnDB
139
+ uses, so one configuration produces one stream:
140
+
141
+ ```python
142
+ from flowli.log import configure_logging
143
+ configure_logging("INFO", "json") # or "console"
144
+ ```
145
+
146
+ All three CLIs — `flowli`, `flowli-runner` and `flowli-codeflow` — take
147
+ `--log-level` and `--log-format console|json`; `flowli` also reads
148
+ `FLOWLI_LOG_LEVEL` and `FLOWLI_LOG_FORMAT`. Logs go to stderr, so a job's
149
+ report on stdout stays pipeable on its own. Events are named with snake_case
150
+ nouns such as `execution_started`, `execution_suspended`, `frame_failed`,
151
+ `execution_recovered` and `execution_archived`. While a worker holds a task,
152
+ `worker_id`, `task_id`, `eid` and `epoch` are bound to every event it emits, and
153
+ live frames add `fid` and `attempt`. Frame events are at DEBUG level.
154
+
155
+ ## License
156
+
157
+ MIT. See [LICENSE](https://github.com/Quadratic-Labs/flowli/blob/main/LICENSE).
@@ -0,0 +1,101 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0"] # >=77: SPDX license expressions (PEP 639)
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "flowli"
7
+ version = "0.1.0"
8
+ description = "Workflow engine: a journaled coroutine execution stack on CairnDB"
9
+ readme = "README.md"
10
+ requires-python = ">=3.14"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [{name = "Thomas Zamojski"}]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: Developers",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.14",
19
+ "Typing :: Typed",
20
+ ]
21
+ dependencies = [
22
+ "cairndb>=0.4.1,<0.5",
23
+ "cattrs>=24.1.0",
24
+ "structlog>=24.1.0",
25
+ ]
26
+
27
+ [project.urls]
28
+ Documentation = "https://quadratic-labs.github.io/flowli/"
29
+ Repository = "https://github.com/Quadratic-Labs/flowli"
30
+ Changelog = "https://github.com/Quadratic-Labs/flowli/blob/main/CHANGELOG.md"
31
+
32
+ [project.optional-dependencies]
33
+ cli = ["typer>=0.9.0", "rich>=13.8.0", "uvicorn>=0.52.4"]
34
+ api = [
35
+ "fastapi>=0.115.0",
36
+ "pydantic>=2.7.0",
37
+ "pyjwt[crypto]>=2.9.0",
38
+ "uvicorn>=0.52.4",
39
+ ]
40
+ docs = [
41
+ "sphinx>=8.1.0",
42
+ "myst-parser>=4.0.0",
43
+ "furo>=2024.8.6",
44
+ "sphinx-design>=0.6.0",
45
+ "sphinx-copybutton>=0.5.2",
46
+ "sphinxcontrib-mermaid>=1.0.0",
47
+ "sphinx-autobuild>=2024.10.3",
48
+ ]
49
+ dev = [
50
+ "pytest>=8.0.0",
51
+ "pytest-asyncio>=0.23.0",
52
+ "hypothesis>=6.98.0",
53
+ "ruff>=0.2.0",
54
+ "mypy>=1.8.0",
55
+ "fastapi>=0.115.0",
56
+ "httpx>=0.27.0",
57
+ "pyjwt[crypto]>=2.9.0",
58
+ "asgi-lifespan>=2.1.0",
59
+ "uvicorn>=0.52.4",
60
+ ]
61
+
62
+ [project.scripts]
63
+ flowli = "flowli.cli:app"
64
+
65
+ [tool.setuptools.packages.find]
66
+ where = ["src"]
67
+
68
+ [tool.setuptools.package-data]
69
+ "flowli" = ["py.typed"]
70
+
71
+ [tool.pytest.ini_options]
72
+ asyncio_mode = "auto"
73
+ testpaths = ["tests"]
74
+
75
+ [tool.ruff]
76
+ line-length = 100
77
+ target-version = "py314"
78
+
79
+ [tool.ruff.format]
80
+ # Code blocks in the docs and specs are aligned by hand.
81
+ exclude = ["*.md"]
82
+
83
+ [tool.ruff.lint]
84
+ select = ["E", "F", "I", "UP", "B"]
85
+
86
+ [tool.ruff.lint.per-file-ignores]
87
+ "docs/conf.py" = ["E501"] # the inline GitHub icon
88
+
89
+ [tool.mypy]
90
+ strict = true
91
+ python_version = "3.14"
92
+
93
+ [[tool.mypy.overrides]]
94
+ module = ["msgpack"]
95
+ ignore_missing_imports = true
96
+ follow_untyped_imports = true
97
+
98
+ [dependency-groups]
99
+ dev = [
100
+ "mutmut>=3.8.0",
101
+ ]
flowli-0.1.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """flowli: a journaled coroutine execution stack on CairnDB."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1 @@
1
+ """Port implementations. `memory` for tests, `cairndb` for production."""