@hasna/workflows 0.1.0 → 0.1.2
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/README.md +75 -18
- package/dist/agent-tools.js +1937 -1
- package/dist/cli/index.js +2762 -7
- package/dist/handlers.js +96 -1
- package/dist/index.js +2062 -9
- package/dist/mcp/index.js +1994 -16
- package/dist/serve/index.js +1992 -9
- package/dist/service.js +1911 -7
- package/hasna.contract.json +2 -2
- package/package.json +7 -5
- package/types/agent-tools.d.ts +2 -6
- package/types/daemon.d.ts +119 -0
- package/types/expr.d.ts +58 -0
- package/types/graph.d.ts +80 -0
- package/types/handlers.d.ts +1 -5
- package/types/lanes/claude.d.ts +16 -0
- package/types/lanes/codex.d.ts +12 -0
- package/types/lanes/cursor.d.ts +13 -0
- package/types/lanes/grok.d.ts +16 -0
- package/types/lanes/index.d.ts +14 -0
- package/types/lanes/types.d.ts +64 -0
- package/types/render.d.ts +12 -0
- package/types/secrets.d.ts +30 -0
- package/types/service.d.ts +18 -0
- package/types/session.d.ts +51 -0
- package/types/store.d.ts +86 -0
- package/types/wal.d.ts +85 -0
package/README.md
CHANGED
|
@@ -1,36 +1,90 @@
|
|
|
1
1
|
# @hasna/workflows
|
|
2
2
|
|
|
3
|
-
Universal graph workflow app
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
The graph language (with `while` nodes), three-table store, session WAL with
|
|
8
|
-
torn-run repair, memoization, secrets write-gate, claims/leases daemon, and
|
|
9
|
-
four lane adapters (claude, codex, cursor, grok) are **roadmap slices — not
|
|
10
|
-
shipped in 0.1.0**. Nothing in this package reads or writes a workflow
|
|
11
|
-
database yet.
|
|
3
|
+
Universal graph workflow app: a graph language (with `while` nodes), a
|
|
4
|
+
three-table store, session WAL with torn-run repair, memoization, a secrets
|
|
5
|
+
write-gate, a claims/leases daemon, and four lane adapters (claude, codex,
|
|
6
|
+
cursor, grok) — one domain implementation, four interface surfaces.
|
|
12
7
|
|
|
13
8
|
## Surfaces
|
|
14
9
|
|
|
15
10
|
| surface | bin / export | what it is |
|
|
16
11
|
|---|---|---|
|
|
17
|
-
| CLI | `workflows` |
|
|
18
|
-
| MCP | `workflows-mcp` | stdio MCP server for coding agents (
|
|
19
|
-
| Serve | `workflows-serve` | HTTP server (`/health`, `/ready`, `/version`, `/openapi.json`); binds `127.0.0.1` by default
|
|
12
|
+
| CLI | `workflows` | init, validate, graph (render), run (--context/--input/--idempotency-key), runs list/show/cancel/resume/events, nodes list/show, sessions list/pull, machines list/status, lanes list/probe, daemon start/status/stop, memos list/clear, resume (interrupted-run restore), serve, repair (+ version, health, info) |
|
|
13
|
+
| MCP | `workflows-mcp` | stdio MCP server for coding agents (7 tools incl. workflows_validate, workflows_run, workflows_runs_list, workflows_lanes_list) |
|
|
14
|
+
| Serve | `workflows-serve` (or `workflows serve`) | HTTP server (`/health`, `/ready`, `/version`, authenticated `/trigger`, `/openapi.json`); binds `127.0.0.1` by default; `/trigger` requires `WORKFLOWS_API_KEY` + Bearer token |
|
|
20
15
|
| SDK | `./sdk` (`@hasna/workflows/sdk`) | importable module surface (exports `WorkflowsService`, `createWorkflowsService`, `createRequestHandler`, `workflowsTools`, `callWorkflowTool`) |
|
|
21
16
|
|
|
22
17
|
All three bins answer `--version` / `--help` before binding or serving.
|
|
23
18
|
|
|
24
|
-
The
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
19
|
+
## The graph language (v1)
|
|
20
|
+
|
|
21
|
+
A workflow is a JSON graph with five node types — `start`, `step`, `decision`,
|
|
22
|
+
`while`, `end` — one `start`, at least one `end`, explicit edges only
|
|
23
|
+
(`next`/`then`/`else`), and no explicit cycles: repetition lives in the `while`
|
|
24
|
+
node's condition, which is REQUIRED to carry a finite `maxIterations` bound.
|
|
25
|
+
`validate` reports every rule violation with a dotted path. Conditions are a
|
|
26
|
+
bounded expression language (comparisons, `and`/`or`/`not`, parens, dotted
|
|
27
|
+
paths like `steps.build.exitCode`, and the loop counter `i`).
|
|
28
|
+
|
|
29
|
+
```json
|
|
30
|
+
{
|
|
31
|
+
"name": "retry-until-green",
|
|
32
|
+
"version": "1.0.0",
|
|
33
|
+
"nodes": [
|
|
34
|
+
{ "id": "start", "type": "start", "next": "w" },
|
|
35
|
+
{ "id": "w", "type": "while", "condition": "steps.check.ok != true",
|
|
36
|
+
"body": ["work", "check"], "maxIterations": 5, "next": "done" },
|
|
37
|
+
{ "id": "work", "type": "step", "lane": "claude", "prompt": "fix it" },
|
|
38
|
+
{ "id": "check", "type": "step", "command": "bun test" },
|
|
39
|
+
{ "id": "done", "type": "end" }
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Execution model
|
|
45
|
+
|
|
46
|
+
- **Store**: exactly three SQLite tables — `runs`, `run_nodes`, `memos`
|
|
47
|
+
(input-hash memoization across runs).
|
|
48
|
+
- **Session WAL**: append-only JSONL journal with per-entry sha256 checksums;
|
|
49
|
+
torn tails are truncated and reported on replay.
|
|
50
|
+
- **Torn-run repair**: a run left `running` with no live claim is marked
|
|
51
|
+
`interrupted` (attempts + 1, up to a bound) or failed; `repair` exposes it.
|
|
52
|
+
An interrupted run continues from its durable cursor either via the daemon
|
|
53
|
+
(which dispatches interrupted runs) or via top-level `resume <run-id>`,
|
|
54
|
+
which restores it and reuses memoized node outputs.
|
|
55
|
+
- **Daemon**: fencing-tokened, expiring, WAL-recorded claims; heartbeat and
|
|
56
|
+
release are fencing-checked; the reaper expires stale leases, repairs torn
|
|
57
|
+
runs, dispatches pending + interrupted runs, and advances each run ONE step
|
|
58
|
+
per bounded cycle (maxDispatchPerCycle / maxStepsPerCycle / maxCycles /
|
|
59
|
+
maxIterations — every invocation carries a finite budget).
|
|
60
|
+
- **Secrets write-gate**: no node output, run result, or context containing a
|
|
61
|
+
credential-shaped value is ever persisted; the write is refused with the
|
|
62
|
+
path and detector named.
|
|
63
|
+
- **Lanes**: exactly four adapters — claude (@anthropic-ai/claude-agent-sdk),
|
|
64
|
+
codex (@openai/codex-sdk), cursor (@cursor/sdk, local mode), grok (no xAI
|
|
65
|
+
Grok SDK exists on npm — measured; local grok CLI). Each falls back to its
|
|
66
|
+
local CLI and reports LANE_DEPENDENCY_MISSING (exit 127) when neither
|
|
67
|
+
substrate exists.
|
|
28
68
|
|
|
29
69
|
## Usage
|
|
30
70
|
|
|
31
71
|
```bash
|
|
32
72
|
workflows --version
|
|
33
|
-
workflows
|
|
73
|
+
workflows init # creates workflows/ + sessions/ + workflows.db and scaffolds a sample graph
|
|
74
|
+
workflows validate graph.json
|
|
75
|
+
workflows graph graph.json # render (text | --format dot | --format json)
|
|
76
|
+
workflows run graph.json --context '{"repo":"x"}' --input go=yes --idempotency-key k1
|
|
77
|
+
workflows runs list
|
|
78
|
+
workflows runs show <run-id>
|
|
79
|
+
workflows runs events <run-id> # the run's WAL event stream
|
|
80
|
+
workflows nodes show <run-id> <node-id>
|
|
81
|
+
workflows sessions pull # session WAL state (entries, torn, live claims)
|
|
82
|
+
workflows machines status # this machine's store/WAL/daemon status
|
|
83
|
+
workflows lanes probe claude # wired-vs-not-ready-with-reason maturity check
|
|
84
|
+
workflows resume <run-id> # restore an INTERRUPTED run from its durable cursor
|
|
85
|
+
workflows daemon start --once # or a continuous reap loop
|
|
86
|
+
workflows memos clear --yes
|
|
87
|
+
workflows serve # HTTP server (same as workflows-serve)
|
|
34
88
|
workflows-mcp # stdio MCP server
|
|
35
89
|
workflows-serve # HTTP server, port from HASNA_WORKFLOWS_PORT (default 8790)
|
|
36
90
|
```
|
|
@@ -48,7 +102,10 @@ console.log(svc.health());
|
|
|
48
102
|
|---|---|---|
|
|
49
103
|
| `HASNA_WORKFLOWS_PORT` / `WORKFLOWS_PORT` | serve port | 8790 |
|
|
50
104
|
| `HASNA_WORKFLOWS_HOST` / `WORKFLOWS_HOST` | serve bind host | 127.0.0.1 |
|
|
51
|
-
| `HASNA_WORKFLOWS_DATA_DIR` / `WORKFLOWS_DATA_DIR` | data directory
|
|
105
|
+
| `HASNA_WORKFLOWS_DATA_DIR` / `WORKFLOWS_DATA_DIR` | data directory | `~/.hasna/workflows` |
|
|
106
|
+
|
|
107
|
+
The server data backend is sqlite (default) or postgresql when
|
|
108
|
+
`HASNA_WORKFLOWS_DATABASE_URL` is set.
|
|
52
109
|
|
|
53
110
|
## License
|
|
54
111
|
|