Appearance
Migration: v0.1.9 → v0.1.11
Overview
v0.1.11 includes a complete execution plan rewrite (task → node model), native SDK tool approval flow, stream rejoin infrastructure, and several bug fixes.
Breaking Changes
Execution Plan Schema Rewrite
The execution plan model was rewritten from a flat task list to a DAG-based node/run architecture.
Type Renames (@lota-sdk/shared/schemas/execution-plan)
| v0.1.9 | v0.1.11 |
|---|---|
ExecutionPlanStatus | PlanRunStatus |
ExecutionPlanTaskStatus | PlanNodeRunStatus |
ExecutionPlanTaskResultStatus | Removed (use PlanAttemptStatus) |
ExecutionPlanTaskKind | PlanNodeType |
ExecutionPlanTaskOwnerType | PlanNodeExecutorType |
SerializableExecutionPlanTask | SerializablePlanNode |
SerializableExecutionPlanEvent | Removed (use SerializablePlanApproval) |
Status Enum Changes
| v0.1.9 | v0.1.11 |
|---|---|
draft | Removed |
executing | running |
| — | awaiting-human (new) |
| — | failed (new) |
blocked | blocked |
completed | completed |
aborted | aborted |
Task Status → Node Run Status
| v0.1.9 | v0.1.11 |
|---|---|
pending | pending |
in-progress | running |
completed | completed |
blocked | blocked |
skipped | skipped |
failed | failed |
Owner Model Change
typescript
// v0.1.9
task.ownerType // 'agent' | 'plugin' | 'user'
task.ownerRef // string
// v0.1.11
node.owner.executorType // 'agent' | 'plugin' | 'user' | 'system'
node.owner.ref // stringTool Name Constants (@lota-sdk/shared/schemas/tools)
| v0.1.9 | v0.1.11 |
|---|---|
SET_EXECUTION_TASK_STATUS_TOOL_NAME (setExecutionTaskStatus) | SUBMIT_EXECUTION_NODE_RESULT_TOOL_NAME (submitExecutionNodeResult) |
RESTART_EXECUTION_TASK_TOOL_NAME (restartExecutionTask) | RESUME_EXECUTION_PLAN_RUN_TOOL_NAME (resumeExecutionPlanRun) |
Tool Arg Schemas (@lota-sdk/shared/schemas/tools)
| v0.1.9 | v0.1.11 |
|---|---|
SetExecutionTaskStatusArgsSchema | SubmitExecutionNodeResultArgsSchema |
RestartExecutionTaskArgsSchema | ResumeExecutionPlanRunArgsSchema |
SetExecutionTaskStatusArgs | SubmitExecutionNodeResultArgs |
RestartExecutionTaskArgs | ResumeExecutionPlanRunArgs |
Chat Request Routing (@lota-sdk/core/runtime/chat-request-routing)
RoutedChatRequest has a new discriminant:
typescript
// v0.1.11 — new kind
| { kind: 'native-tool-approval'; messages: ChatMessage[] }If your chat handler uses routeWorkstreamChatMessages, add a branch:
typescript
if (routed.kind === 'native-tool-approval') {
const stream = await runtime.services.createWorkstreamNativeToolApprovalStream({
workstream,
workstreamRef,
orgRef,
userRef,
userName,
approvalMessages: routed.messages,
})
return createUIMessageStreamResponse({ stream })
}Without this, native tool approval responses fall through to the regular turn handler, which creates a new turn instead of continuing the existing one.
UI Helpers (@lota-sdk/ui/tools/execution-plan)
| v0.1.9 | v0.1.11 |
|---|---|
getExecutionPlanOwnerLabel(task) | getExecutionPlanOwnerLabel(node) — reads node.owner.executorType / node.owner.ref |
getExecutionPlanStatusLabel('executing') | getExecutionPlanStatusLabel('running') — new statuses: running, awaiting-human, failed |
getExecutionPlanActionLabel('task-status-updated') | getExecutionPlanActionLabel('node-result-submitted') |
getExecutionPlanActionLabel('task-restarted') | getExecutionPlanActionLabel('run-resumed') |
New Features
Native SDK Tool Approval (needsApproval)
Tools can now declare needsApproval: true and the SDK handles the full approval lifecycle:
typescript
import { tool } from 'ai'
const myTool = tool({
description: 'Does something sensitive',
inputSchema: z.object({ input: z.string() }),
needsApproval: true,
execute: async ({ input }) => { /* runs after approval */ },
})The client renders approve/deny UI via addToolApprovalResponse from useChat. The SDK routes the approval response through createWorkstreamNativeToolApprovalStream which re-executes the agent turn with the approval attached.
Stream Rejoin Infrastructure
New server-side infrastructure for reconnecting clients to in-progress LLM streams after page refresh:
createWorkstreamResumableContext()— creates a Redis-backed resumable stream contextworkstreamService.setActiveStreamId()/getActiveStreamId()/clearActiveStreamIdIfMatches()— track the active stream per workstreamactiveStreamIdfield added to workstream schemaconsumeSseStreamcallback oncreateUIMessageStreamResponsepublishes SSE data to Redis- GET endpoint replays the buffered stream via
resumeExistingStream
Important: The useThreadChat hook's resume option now uses a ref guard to prevent React StrictMode from firing two concurrent GET requests. If you were calling resumeStream() manually, switch to passing resume: true to useThreadChat / useLotaChat.
New Exports (@lota-sdk/core)
| Export | Purpose |
|---|---|
createWorkstreamNativeToolApprovalStream | On runtime.services — handles native tool approval continuation |
createWorkstreamResumableContext | Creates Redis-backed resumable stream context |
createLogHelloWorldTool | Demo tool with needsApproval: true |
Bug Fixes
- CONFLICT error on rapid messages:
clearActiveRunIdnow runs before compaction assessment infinalizeTurnRun, preventing "A chat run is already active" when sending messages shortly after a run completes - "custom:" prefix in user questions: Free-text answers no longer include the
custom:prefix - Tool label: Active tools now show "Running" instead of "Pending"
Required Consumer Changes
Server-side chat handler
Add the native-tool-approval branch to your chat message router (see Chat Request Routing above).
Client-side execution plan rendering
Update all references to the old plan types. Search your codebase for:
SerializableExecutionPlanTask → SerializablePlanNode
task.ownerType → node.owner.executorType
task.ownerRef → node.owner.ref
setExecutionTaskStatus → submitExecutionNodeResult
restartExecutionTask → resumeExecutionPlanRun
SET_EXECUTION_TASK_STATUS_TOOL_NAME → SUBMIT_EXECUTION_NODE_RESULT_TOOL_NAME
RESTART_EXECUTION_TASK_TOOL_NAME → RESUME_EXECUTION_PLAN_RUN_TOOL_NAMEDependencies
diff
- "@lota-sdk/core": "0.1.9"
+ "@lota-sdk/core": "0.1.11"
- "@lota-sdk/shared": "0.1.9"
+ "@lota-sdk/shared": "0.1.11"
- "@lota-sdk/ui": "0.1.9"
+ "@lota-sdk/ui": "0.1.11"Optional: Stream rejoin
If you want stream rejoin support:
- Pass
streamIdtocreateWorkstreamTurnStream/createWorkstreamApprovalContinuationStream/createWorkstreamNativeToolApprovalStream - Wrap
createUIMessageStreamResponsewithconsumeSseStreamthat callsstreamContext.createNewResumableStream - Add a GET endpoint that reads
workstreamService.getActiveStreamIdand replays viastreamContext.resumeExistingStream - Pass
resume: truetouseLotaChat/useThreadChat - Configure
prepareReconnectToStreamRequeston yourDefaultChatTransportto point to your GET endpoint