|
2 | 2 |
|
3 | 3 | ## Unreleased |
4 | 4 |
|
5 | | -## v0.102.0 — Agents finish MVP: async dispatch + blocking await |
| 5 | +## v0.102.0 — Agents finish MVP: async dispatch + pool split + C-API |
6 | 6 |
|
7 | 7 | Agent execution model removes the synchronous-on-the-calling-thread |
8 | | -fallback. Per-state agent worker thread + run queue land in this |
9 | | -cycle. |
| 8 | +fallback. Per-state agent workers + run queues land in this cycle, |
| 9 | +with a separate POOLED / SOLO split for `send` / `send-off`, and a |
| 10 | +public C-API perimeter for embedders. |
10 | 11 |
|
11 | 12 | - Internal: `agent_action_node_t` data structure for the run-queue |
12 | 13 | of `(agent fn extra)` tuples; per-agent `in_flight` counter; |
13 | | - state-level `agent_run_head`/`agent_run_tail`, mutex, condvar, |
14 | | - worker thread fields. Lifecycle hooks in `state_init` / |
15 | | - `mino_state_free`. GC root-marking walks the runq so queued |
16 | | - actions keep their fn / args / dyn snapshot live until the |
17 | | - worker pops them. |
| 14 | + per-state `agent_pool[2]` array (POOLED for `send`, SOLO for |
| 15 | + `send-off`) with each pool carrying its own run head/tail and |
| 16 | + worker thread; shared `agent_mu` and `agent_cv` so an `await` |
| 17 | + waiter sleeps once and wakes for either pool's progress. |
| 18 | + Lifecycle hooks in `state_init` / `mino_state_free`. GC |
| 19 | + root-marking walks both pools' runqs so queued actions keep |
| 20 | + their fn / args / dyn snapshot live until the worker pops them. |
18 | 21 | - `send` and `send-off` now enqueue the action onto the per-state |
19 | 22 | run-queue and return the agent immediately. A worker thread is |
20 | 23 | lazy-spawned on the first send (gated on `thread_limit`; throws |
@@ -49,13 +52,30 @@ cycle. |
49 | 52 | rebroadcasts `agent_cv` so any await waiter wakes. The dropped |
50 | 53 | actions are released without running. |
51 | 54 | - `dosync`'s post-commit drain enqueues pending sends onto the |
52 | | - worker's runq instead of running them synchronously on the |
53 | | - embedder thread. Same path as a top-level send, so the action |
54 | | - body sees post-commit ref state via `*agent*` bindings and |
55 | | - doesn't tie up the embedder. STM dosync sends now require the |
56 | | - same thread budget as direct sends; spawn refusals (host hasn't |
57 | | - granted threads) silently drop the queued sends rather than |
58 | | - surfacing the post-commit drain as a failed dosync. |
| 55 | + POOLED worker's runq instead of running them synchronously on |
| 56 | + the embedder thread. Same path as a top-level send, so the |
| 57 | + action body sees post-commit ref state via `*agent*` bindings |
| 58 | + and doesn't tie up the embedder. STM dosync sends now require |
| 59 | + the same thread budget as direct sends; spawn refusals (host |
| 60 | + hasn't granted threads) silently drop the queued sends rather |
| 61 | + than surfacing the post-commit drain as a failed dosync. |
| 62 | +- `send` and `send-off` now route onto separate POOLED and SOLO |
| 63 | + pools. mino's per-state eval lock means actions across the two |
| 64 | + pools still serialize, so the user-visible effect is the same |
| 65 | + as before, but the queues are independent: a long-running |
| 66 | + send-off action does not stall pending sends, and vice versa. |
| 67 | + Each pool's worker counts against `thread_limit`, so embedders |
| 68 | + that want both shapes alive concurrently must raise the limit |
| 69 | + to at least 3 (embedder + POOLED + SOLO worker). The split is |
| 70 | + also a clean seam for a future SOLO-yields-eval-lock-during- |
| 71 | + blocking-IO design without further user-facing churn. |
| 72 | +- Public C-API entries: `mino_send`, `mino_send_off`, `mino_await`, |
| 73 | + `mino_await_for`, `mino_agent_error`, `mino_restart_agent`. Each |
| 74 | + takes the same `mino_lock` perimeter `mino_call` already uses |
| 75 | + and routes through the shared `agent_send_core` helper, so the |
| 76 | + guarantees are identical to the Clojure-level prims. Cross- |
| 77 | + state misuse fires at the C boundary: passing an agent from |
| 78 | + another `mino_state_t` throws MST007 and returns NULL. |
59 | 79 |
|
60 | 80 | ## v0.101.1 — STM and agent hardening pass |
61 | 81 |
|
|
0 commit comments