Skip to content
This repository was archived by the owner on Jun 14, 2026. It is now read-only.

Commit d02ba4f

Browse files
committed
docs: roadmap progress for phase 1.3
1 parent c6605dc commit d02ba4f

1 file changed

Lines changed: 53 additions & 20 deletions

File tree

ROADMAP.md

Lines changed: 53 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,26 @@ This document plans the next phases of work for `agentic-kit`. It supersedes
44
neither `REDESIGN_DECISIONS.md` nor `README.md` — those describe what exists.
55
This 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` plumbingthe 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` plumbingthe 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

349376
The 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" semanticsthe `@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

Comments
 (0)