Skip to content

Migrating to 0.4.0 ​

0.4.0 is meant to be a drop-in upgrade from 0.3.x. The new features are additive, off until a prop or the server turns them on, and a server that never pauses, cancels or limits looks exactly as before. A handful of behaviours did change; this page lists them so a test or a style does not surprise you.

bash
npm install @cognipeer/chat-ui@0.4.0

Keep importing @cognipeer/chat-ui/styles.css: it gained the status-colour variables and a few rules.

Checklist ​

  1. Upgrade the package and run your type check. See TypeScript for the two places a union grew.
  2. Search your code and tests for the behaviour changes below.
  3. If you match on error.message, switch to error.code (Errors).
  4. If you target the history rows with CSS or tests, read History.
  5. Decide which of the new opt-in features you want (What's new).
  6. Upgrade @cognipeer/agent-server to 0.3.0 or later to get approvals, reattach, server-side Stop, usage limits, raw uploads and the portal routes. Older servers keep working without them.

Behaviour changes ​

Stop ​

  • stop() now stops the run on the server on a transport that can cancel (AgentServerClient): it calls POST /conversations/:id/cancel, closes the stream, and keeps the text so far as a message marked stopped, which is then replaced by what the server kept. Before, it only detached the browser. A server without the route (404) behaves as before. Other transports are unchanged.
  • Stop while a message's files are still going up aborts the upload and gives the composer its files and text back; no cancel request is made (the message was never sent).

Files ​

Before (0.3.0)Now
Files travelled base64 in the message bodyWith fileTransport="upload" / "upload-on-select" they are stored first and the message names them (fileIds). "inline" stays the default and unchanged
Uploads were base64 JSONWhere the transport supports it (AgentServerClient) a file is sent as the request body with its own Content-Type, with progress. rawUpload: false restores the JSON form
fileTransport="upload" showed the bubble after the uploadThe bubble appears at once with progress on its chips; a failed upload takes it back
A refused upload or message cleared the composerThe typed text comes back, the optimistic message is removed and the files stay attached
image/* in allowedFileTypesMatches by media-type prefix
Refusals (too many, too large, wrong type) only reached onErrorThey also show in the error banner. A 0-byte file is refused with its own message
Image attachments with a URL were file chipsThey render as thumbnails (PNG, JPEG, GIF, WebP only; an SVG is a chip). Other files show their size
The send button needed textIt is also enabled for files without text (attachmentsOnlyMessage is sent)
File links used the address as givenOnly http:, https:, blob: and relative addresses are linked; a data: URL (such as the inline bytes of an A2A file) has no Download link
A JSON file uploaded as itselfGoes up as application/octet-stream with ?mimeType= in the query, because a JSON Content-Type is the server's JSON upload form

Approvals and questions ​

  • A question's required now defaults to true (the agent SDK's rule). A question without required is marked with an asterisk and Skip is offered only when every question says required: false. A server that wants an optional question sends required: false.
  • An answer refused with action_expired or action_cancelled turns the card into Expired / Cancelled (as action_not_pending already did) and frees the composer; any other error puts the card back to waiting.
  • A request the server refused on its own after it lapsed (resolvedBy: "system:timeout") reads Expired, not Denied.

Errors ​

  • A failed request with a known code shows a localized message. error.message is now that message; the server's own text is error.serverMessage, and error.code, error.status and error.details are on the error. Code that compared error.message against the server's English text should compare error.code. See Error codes.
  • budget_reached makes the page fetch the conversation again, like the other conflicts (conversation_busy, action_pending).
  • Errors thrown for failed requests carry status and code when the server sends them.

Messages ​

  • Text parts of a message's content array are joined with a line break instead of nothing.
  • The live turn is always drawn below the stored messages, so a continuation (Continue after a usage limit) no longer replaces the answer it carries on.
  • Opening a conversation from the history, or through conversationId, selects that conversation's agent (so the header, the paperclip, the limits and the composer mode match it) and calls onAgentChange when the agent changes.

History ​

  • ChatHistory rows are real <button>s in a list (they were clickable divs), and the delete button is named after the conversation ("Delete conversation: ..."). Update selectors, tests and CSS that targeted the old markup ([data-chat-conversation] marks a row).
  • Rows can carry a status badge; turn it off with showStatus={false}.

i18n ​

  • SupportedLocale is now "en" | "tr" | (string & {}): any locale code works once you supply customMessages; missing keys fall back to English per key.
  • Chat honours an enclosing ChatI18nProvider (its locale and customMessages), has its own customMessages prop and works without any provider. useI18n works outside a provider (English) and has has(key).

Theming ​

  • New CSS variables and tokens success, danger, warning, info (and ...Bg) back the error banner, card outcomes, the usage notice and the history badges. If you overrode --chat-* variables you may want to define these too. See Theming.

TypeScript ​

  • PendingAction and ActionResolution gained a client_tool variant, and StreamActionResolvedEvent.resolution.type can be "client_tool". An exhaustive switch over action.type or resolution.type needs a case for it (a host-page tool has no card, is not "waiting for you" and does not close the composer).
  • ChatTransport gained many optional methods; transports you wrote keep compiling.
  • AgentInfo gained capabilities, ConversationListItem gained runtime, budget, spentUsd, pinned, metadata; Message gained status, stopReason, stopDetail, actionStates, feedback; FileAttachment gained previewUrl, status, progress, uploadError, expiresAt, expired, conversionStatus. All optional.
  • ChatTheme["colors"] gained the status keys (optional).
  • pendingMode on ChatInput still works; state (ComposerState) is the new, wider form and wins when both are given. The older metadata keys on an agent (enableFileUpload, maxFileSize, ...) keep working; capabilities.attachments wins when both are present.

Things that did not change ​

  • The Chat and ChatMinimal props you used in 0.3.0, the default theme, the default file limits (10 MB, 10 files, any type) and fileTransport="inline".
  • AgentServerClient methods you called in 0.3.0.
  • The package formats (ESM and CommonJS) and the peer dependencies (React 18+).

Rolling back ​

Pin @cognipeer/chat-ui@0.3.0. The state the new features keep in the browser is limited to cp:announcement:dismissed:* and cp:notify:prefs (only when you turn those features on); ratings, pins, budgets and approvals live on the server and are unaffected by the client version.

Next steps ​

Studio · Pulse · Console · Agent SDK and more — the Cognipeer documentation hub