diff options
| author | t <t@tjp.lol> | 2026-06-09 00:00:56 -0600 |
|---|---|---|
| committer | t <t@tjp.lol> | 2026-06-09 08:52:47 -0600 |
| commit | 97b10466d83d488ad2cb9e084159a445af74c845 (patch) | |
| tree | 6bea7c23d00ff1178a43e631fc700f210cb7d85b /docs/tui-refactor-plan.md | |
| parent | 104001d25c9c8cb5ec45ced1678f7c7b70888808 (diff) | |
event lifecycle
Diffstat (limited to 'docs/tui-refactor-plan.md')
| -rw-r--r-- | docs/tui-refactor-plan.md | 60 |
1 files changed, 46 insertions, 14 deletions
diff --git a/docs/tui-refactor-plan.md b/docs/tui-refactor-plan.md index 15c7e8e..9f18ff0 100644 --- a/docs/tui-refactor-plan.md +++ b/docs/tui-refactor-plan.md @@ -357,16 +357,31 @@ is at fault, not the framework. No magic merge. ### 7.4 Timing & lifecycle -- An event fires **once, at its component-creation boundary**, *before* the - component first paints — so `setComponent` swaps it before anything renders. -- For `tool`, that boundary is tool-use **start** (name known). The single - `tool` event covers the whole call: the chosen component is then **driven by - panto** with the streaming args/result/status as structured deltas. The - handler does **not** re-fire per delta; it chooses the component once. -- All streamable components share this shape: fire once at start, hand over a - component, drive with deltas (§8). -- **No "active component" (§6 invariant).** Each `tool`/subagent event yields its - own component instance keyed by call-id. Parallel calls each get their own. +- **Streaming LIFECYCLE events (as built).** Rather than a single fire-once + boundary, each streaming block emits events across its whole lifecycle, so a + handler can act (and re-choose the component) at any meaningful point: + - thinking: `thinking` (start) → `thinking_delta` (per chunk) → + `thinking_complete`. + - assistant text: `assistant_text` → `assistant_text_delta` → + `assistant_text_complete`. + - tool: `tool` (block-start; name **unknown**, component shows `tool (?)`) → + `tool_details` (name resolved) → `tool_delta` (args chunk) → + `tool_call_complete` (full args) → `tool_result` (atomic result block). + - `user_message` / `session_start` / `compaction` fire once. +- **Mid-stream swap.** `setComponent` may be called at **any** lifecycle event, + not only creation. Swapping replaces the slot's component at the **same key**; + the incoming component fully takes over the region (renders from line 0, the + predecessor's orphaned lines cleared). The superseded component is released by + its owner. This is what makes `tool` honest: it fires at block-start as + `tool (?)`, and a handler **claims the call by name at `tool_details`** by + swapping in its own component over the default that was already rendering. +- **panto keeps driving.** Across any swap, panto continues feeding the + structured deltas/details/result into the slot's typed default box; the engine + renders whatever component currently owns the slot (default, wrapper, or + swapped-in). Drive-by-default-box, render-by-current-component. +- **No "active component" (§6 invariant).** Each `tool`/subagent block yields its + own component instance keyed by call-id/block-index. Parallel calls each get + their own; a swap replaces the component *at* a key, never a global current. ### 7.5 The skills example (worked) @@ -450,11 +465,28 @@ the vtable stays C-ABI-friendly so it can be added elsewhere later. cache_write`, latest from `message_complete`). **No git branch** (panto uses jj, not git). -**P3 — Extension components + cursor/IME polish.** -- Event system (`on`/`emit`, `event.get/setComponent`); built-in events wired at - component-creation boundaries; public default components. -- Zig event + component API → Lua bridge. +**P3 — Extension components + cursor/IME polish. ✅ COMPLETE.** +- Event system (`on`/`emit`, `event.get/setComponent`); a full **streaming + lifecycle** taxonomy wired at the real libpanto boundaries (start / `_delta` / + `_complete` for thinking & assistant; `tool` / `tool_details` / `tool_delta` / + `tool_call_complete` / `tool_result` for tools; `user_message` / + `session_start` / `compaction` once — see §7.4); public default components. + **Mid-stream component swaps** are supported: a handler may `setComponent` at + any lifecycle event, replacing the slot's component (full-region takeover, + superseded component released) while panto keeps driving deltas into the + default box. `tool` fires at block-start as `tool (?)`; handlers claim by name + at `tool_details` (§7.5). +- Zig event + component API → Lua bridge. Extension-authoring APIs moved under + `panto.ext` (`register_tool`/`register_command`/`on`/`emit`); the bare + `panto` namespace is reserved for the future full libpanto API. Lua-defined + components bridge the `Component` vtable via **synchronous** `lua_pcallk` + render (not the libuv scheduler) with a native cache-derived + `firstLineChanged`. - Virtual cursor compositing + hardware-cursor sync (IME marker positioning). + Relative-move positioning inside the sync block; `differential` reconciles + from the actual left-on row so repaints stay correct. **IME anchoring is + implemented but unverified against a real IME** (the plan's [verify] flag + stands). **Deferred (post-refactor):** - Markdown + syntax highlighting renderer (hosting components designed for it |
