Melony
HomeGitHub

Text Delta Handling

Learn how melony automatically handles streaming text updates for smooth user experience.

Overview

melony automatically handles text deltas for smooth streaming. When your server sends incremental text updates, melony joins them together to create a seamless typing effect.

How It Works

Your server streams individual text deltas, and melony automatically combines them:

Server streams deltas

data: {"type": "text-delta", "id": "block1", "delta": "Hello"}
data: {"type": "text-delta", "id": "block1", "delta": " world"}
data: {"type": "text-delta", "id": "block1", "delta": "!"}

Client receives joined text

{type: "text", text: "Hello world!"}

Configuration

Configure delta handling with useMelonyMessages:

const messages = useMelonyMessages({
  joinTextDeltas: {
    deltaType: "text-delta",
    idField: "id", 
    deltaField: "delta",
    outputType: "text",
    outputField: "text",
  },
});

Configuration Options

deltaType - The type field that identifies delta messages
idField - Field containing the unique identifier for grouping deltas
deltaField - Field containing the text delta content
outputType - The type of the final joined part
outputField - Field name for the joined text in the output

Default Behavior

If you don't specify configuration, melony uses these defaults:

// These are the default values
const messages = useMelonyMessages({
  joinTextDeltas: {
    deltaType: "text-delta",
    idField: "id",
    deltaField: "delta", 
    outputType: "text",
    outputField: "text",
  },
});

Note: The default configuration works with AI SDK's toUIMessageStream() output format.

Custom Delta Types

You can configure melony to work with different delta formats from your server:

Example: Custom server format

If your server sends deltas in this format:

data: {"type": "chunk", "blockId": "msg-123", "content": "Hello"}
data: {"type": "chunk", "blockId": "msg-123", "content": " world"}
data: {"type": "chunk", "blockId": "msg-123", "content": "!"}

Configure melony accordingly

const messages = useMelonyMessages({
  joinTextDeltas: {
    deltaType: "chunk",
    idField: "blockId",
    deltaField: "content",
    outputType: "text",
    outputField: "text",
  },
});

Disabling Delta Handling

If you don't want automatic delta joining, you can disable it:

const messages = useMelonyMessages({
  joinTextDeltas: false, // Disable delta handling
});

Note: When disabled, you'll receive individual delta parts as they arrive, and you'll need to handle joining them manually in your UI.

Real-World Example

Here's a complete example showing how text deltas work in practice:

"use client";
import { MelonyProvider, useMelonyMessages } from "melony";

function StreamingChat() {
  const messages = useMelonyMessages({
    joinTextDeltas: true, // Enable automatic delta joining
  });

  return (
    <div className="chat-container">
      {messages.map((message) => (
        <div key={message.id} className="message">
          <div className="message-role">{message.role}</div>
          <div className="message-content">
            {message.parts.map((part, i) => (
              <div key={i}>
                {part.type === "text" && (
                  <p className="streaming-text">{part.text}</p>
                )}
              </div>
            ))}
          </div>
        </div>
      ))}
    </div>
  );
}

export default function Chat() {
  return (
    <MelonyProvider endpoint="/api/chat">
      <StreamingChat />
    </MelonyProvider>
  );
}

Troubleshooting

Deltas not joining

Check that your server is sending the correct format and that the configuration matches your server's delta structure.

Multiple text parts

If you see multiple text parts instead of joined text, verify that theidField values match for deltas that should be joined.