@@ -4,6 +4,26 @@ This document plans the next phases of work for `agentic-kit`. It supersedes
44neither ` REDESIGN_DECISIONS.md ` nor ` README.md ` — those describe what exists.
55This describes what will exist next, why, and what is explicitly out of scope.
66
7+ ## Progress
8+
9+ - [x] ** Phase 0 — Test Infrastructure**
10+ - [x] 0.1 Test Conventions
11+ - [x] 0.2 Shared Test Helpers (` tools/test/ ` )
12+ - [ ] 0.3 Integration Test Lane (optional in Phase 1)
13+ - [x] 0.4 SSE Wire-Format Tests
14+ - [x] ** Phase 1 — Pause/Resume + React Bindings**
15+ - [x] 1.1 Pausable Tools
16+ - [x] 1.2 Run Serialization Helpers
17+ - [x] 1.3 ` @agentic-kit/react `
18+ - [ ] ** Phase 2 — Production Polish**
19+ - [ ] 2.1 Prompt Caching API
20+ - [ ] 2.2 Telemetry / Middleware Hooks
21+ - [ ] ** Phase 3 — Optional Extensions**
22+ - [ ] 3.1 Full Ollama Tool Support
23+ - [ ] 3.2 Retry / Backoff
24+ - [ ] 3.3 Stream Resume on Disconnect (introduces opt-in ` RunStore ` )
25+ - [ ] 3.4 Client-Side Tool Execution
26+
727## Current State (snapshot)
828
929| Package | Status |
@@ -319,8 +339,8 @@ const chat = useChat({
319339 api: '/api/chat',
320340 body: () => ({ /* extra request body fields */ }),
321341 initialMessages: storedMessages,
322- onMessage: (m) => {}, // streaming partial state
323- onFinish: (m) => {}, // turn complete; consumer may persist
342+ onMessage: (m) => {}, // fires once per completed message in the stream
343+ onFinish: (m) => {}, // fires once per agent_end with the final assistant message
324344 onDecisionPending: (event) => {}, // tool paused; consumer renders UI
325345})
326346
@@ -337,14 +357,21 @@ Behaviors the hook is responsible for:
337357
338358- POSTing to ` api ` with ` messages ` plus any consumer - supplied body fields .
339359- Parsing the SSE response into ` AgentEvent ` s and folding them into ` messages ` .
340- - Emitting ` onMessage ` per partial update , ` onFinish ` per turn end .
360+ ` message_start ` / ` message_update ` drive in - flight rendering by replacing the
361+ trailing assistant slot ; ` message_end ` finalizes ; ` agent_end ` is authoritative
362+ and replaces the local message log with ` event.messages ` .
363+ - Emitting ` onMessage ` per ` message_end ` (one call per completed message —
364+ user , assistant , tool result ), ` onFinish ` per ` agent_end ` with the final
365+ assistant message .
341366- Surfacing ` tool_decision_pending ` events as ` chat.pendingDecision ` and via
342- ` onDecisionPending ` .
367+ ` onDecisionPending ` . Pause = stream ended , hook idle , awaiting decision .
343368- ` respondWithDecision(toolCallId, value) ` : write the decision into the
344- matching tool - call content block in ` messages ` , then POST the augmented
345- ` messages ` back to the ** same ` api ` endpoint ** . No separate ` /resume ` route ,
346- no ` runId ` plumbing — the message log carries everything the server needs .
347- - Plumbing an ` AbortSignal ` through ` chat.abort() ` .
369+ matching tool - call content block in the trailing assistant message , then
370+ immediately POST the augmented ` messages ` back to the ** same ` api `
371+ endpoint ** . No separate ` /resume ` route , no ` runId ` plumbing — the message
372+ log carries everything the server needs .
373+ - Plumbing an ` AbortSignal ` through ` chat.abort() ` . Aborts do ** not ** populate
374+ ` chat.error ` ; only non - 200 responses and genuine network failures do .
348375
349376The hook does not own persistence , modes , system prompts , or any UI shape .
350377
@@ -366,7 +393,11 @@ return `createScriptedSSEResponse(events)` from 0.2.
366393 stream folds into ` messages ` . Assert the POSTed body contains the decision
367394 on the right tool call .
368395- Network error / non - 200 response : ` chat.error ` set ; ` messages ` not corrupted .
369- - Malformed SSE bytes : hook surfaces an error rather than crashing .
396+ - Malformed SSE bytes : silently dropped by ` parseSSEStream ` (the parser
397+ swallows JSON parse errors and yields nothing for that frame ); the hook does
398+ not crash and continues folding valid events on either side . If the
399+ underlying stream itself errors mid - read , that propagates and is surfaced
400+ via ` chat.error ` .
370401- ` initialMessages ` hydrates state on mount .
371402
372403-- -
@@ -567,20 +598,22 @@ package). Phase 2 and 3 add no new packages; everything extends in place.
567598 reuses ` validateSchema ` from ` packages/agent/src/validation.ts ` — same code
568599 path as tool inputs . Discriminated - union and ` oneOf ` / ` anyOf ` coverage is
569600 still untested ; fold into the 1.1 test matrix .
570- - ** Lifecycle events across pause boundaries .** Each entry into the loop
571- (whether via ` prompt() ` or ` continue() ` after a decision ) re - fires
572- ` agent_start ` . Consumers that distinguish " fresh prompt" from " resumed
573- loop " need a hint. Decide before 1.3 whether to add a distinct
574- ` agent_resume ` event or to redocument ` agent_start ` with explicit
575- " loop entry" semantics — the ` @agentic-kit/react ` hook codifies the
576- choice externally .
601+ - ** Lifecycle events across pause boundaries .** Resolved (1.3 ): no separate
602+ ` agent_resume ` event . ` agent_start ` carries explicit " loop entry" semantics
603+ — fired on every entry into the loop (fresh prompt or resumed continuation ).
604+ ` useChat ` does not handle ` agent_start ` as a state - reset trigger ; reset
605+ happens in ` send() ` / ` respondWithDecision() ` before the fetch , which is
606+ the only place that knows whether a run is starting .
577607- ** SSE vs . NDJSON .** SSE is the proposed default . NDJSON is simpler but lacks
578608 reconnection semantics and event - type framing . Revisit if real - world
579609 consumers report SSE problems behind specific proxies .
580- - ** ` respondWithDecision ` auto - fire vs . explicit send .** Whether the React
581- hook should auto - POST the augmented messages immediately or expose a
582- separate ` send() ` step . Default to auto for ergonomics (matches AI SDK ' s
583- ` addToolApprovalResponse ` → ` sendAutomaticallyWhen ` flow ); expose an opt - out .
610+ - ** ` respondWithDecision ` auto - fire vs . explicit send .** Resolved (1.3 ):
611+ auto - fire . ` respondWithDecision(toolCallId, value) ` mutates the trailing
612+ assistant ' s tool-call block, syncs `messages`, and immediately re-POSTs to
613+ the same ` api ` . Matches AI SDK ' s `addToolApprovalResponse` →
614+ ` sendAutomaticallyWhen ` ergonomics . An explicit opt - out is not exposed yet ;
615+ if a real consumer needs it , add a ` respondWithDecision ` overload that
616+ returns the augmented messages without sending .
584617- ** Live test policy for paid providers .** Anthropic / OpenAI live tests would
585618 burn API credits . Default position : gated ` *.live.test.ts ` files with
586619 env - var keys , manually triggered , never required by per - PR CI .
0 commit comments