Skip to content

v2.5.0

Latest

Choose a tag to compare

@github-actions github-actions released this 03 Apr 04:48
· 105 commits to main since this release

[2.5.0] - 2026-03-20

Breaking Changes

  • Chat API is now async (mutation + polling): queryKnowledgeBase moved from Query to Mutation. Returns immediately with PENDING status. Clients must poll getConversation for results. The old synchronous query no longer exists. All consumers must redeploy their backend stack.
  • conversationId and requestId must be UUID v4: The backend validates both IDs. Non-UUID conversation IDs stored in localStorage from previous versions are automatically regenerated by the web component. Custom conversationId props that aren't valid UUIDs are silently replaced (with a console warning).
  • ChatResponse type removed from schema: Replaced by ChatRequest (mutation response) and ConversationTurn (within Conversation type).

Added

  • Async chat pattern: queryKnowledgeBase mutation writes a PENDING record to DynamoDB, async-invokes QueryKBFunction, and returns immediately. Bypasses AppSync's 30-second resolver timeout for Bedrock Converse API calls that take 30-50s.
  • getConversation query: Returns all turns for a conversation from DynamoDB. Used by the client for polling and will support future conversation listing/search.
  • New schema types: ChatRequest, ChatStatus, ConversationTurn, Conversation.
  • Polling with step backoff: Client polls at 1s initial interval, 1.5x growth, 5s cap. Progressive timeout UX: 30s "taking longer than usual" indicator, 90s hard timeout.
  • AbortController support: Polling cancels on component unmount or new message send. In-flight fetch requests are aborted via AbortSignal.
  • User-scoped conversations: userId persisted on conversation turns. getConversation denies access when the turn's userId doesn't match the requester (or requester is unauthenticated).
  • Conversation ID validation: Web component validates localStorage and prop values, auto-regenerates invalid (non-UUID) IDs with console warning.

Fixed

  • Race condition in turn number assignment: Concurrent requests could assign the same turnNumber. Now uses conditional put_item with attribute_not_exists(turnNumber) and retry on conflict.
  • PENDING turns contaminate LLM context: get_conversation_history now filters out PENDING turns so in-progress requests don't inject empty assistant responses into the Bedrock Converse context.
  • Orphaned PENDING records: If async Lambda invoke fails after writing the PENDING record, the record is cleaned up via delete_item.
  • Polling swallowed HTTP errors: Non-OK poll responses now track consecutive failures; 4xx errors surface immediately; 5 consecutive failures trigger an error.
  • CONVERSATION_TABLE_NAME not guarded: Both resolvers now raise a clear error if the env var is missing.
  • DynamoDB type safety: turnNumber, status, sources values normalized from DynamoDB attribute unions to concrete Python types. Passes mypy strict mode.
  • Chat prompts logged to CloudWatch: queryKnowledgeBase arguments now redact the query field in resolver logs.
  • Stale callback refs: onSendMessage and onResponseReceived callbacks use useRef pattern to avoid stale closures.
  • except (ClientError, Exception) simplified: Redundant catch clause replaced with except ClientError.

Changed

  • getConversation added to access_requirements: Public access gate now enforced before reading conversations.
  • store_conversation_turn includes status and userId: Sync code path now writes status: "COMPLETED" and userId for consistency with async path.
  • getConversation paginates DynamoDB results: Iterates LastEvaluatedKey to handle conversations exceeding the 1 MB page limit.
  • CSS design token: Slow response indicator uses var(--chat-spacing-xs) instead of hardcoded 4px.
  • Removed unused isSlowResponse from ChatMessage type: Only used as component state and MessageListProps prop.

Docs

  • API reference updated: Documents async mutation + polling pattern with GraphQL and curl examples.
  • ragstack-chat docs updated: conversationId prop documented as UUID (auto-generated if omitted or invalid). Non-UUID examples removed.