Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions calls/flutter/migration-guide-v5.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,9 +13,7 @@ Calls SDK v5 is a **drop-in replacement** for v4. All v4 APIs are preserved as d

```yaml
dependencies:
cometchat_calls_sdk:
hosted: https://dart.cloudsmith.io/cometchat/cometchat/
version: ^5.0.0
cometchat_calls_sdk: ^5.0.3
```

<Info>
Expand Down
151 changes: 144 additions & 7 deletions sdk/flutter/ai-agents.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ AI Agents enable intelligent, automated interactions within your application. Th

## Agent Run Lifecycle and Message Flow

This section explains how a users text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
This section explains how a user's text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
- A user sends a text message to an Agent.
- The platform starts a run and streams real-time events via the **`AIAssistantListener`**.
- After the run completes, persisted Agentic Messages arrive via the **`MessageListener`**.
Expand All@@ -26,16 +26,21 @@ Events are received via the **`onAIAssistantEventReceived`** method of the **`AI
- Tool Call Arguments
- Tool Call End
- Tool Call Result
3. One or more assistant reply streams:
3. Zero or more card generation cycles (repeats for each card produced):
- Card Start
- Card (full payload)
- Card End
4. One or more assistant reply streams:
- Text Message Start
- Text Message Content (multiple times; token/char streaming)
- Text Message End
4. Run Finished
5. Run Finished

Notes:
- `Run Start` and `Run Finished` are always emitted.
- `Tool Call` events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run.
- `Text Message` events are always emitted and carry the assistant’s reply incrementally.
- `Card` events appear only when the agent produces a card. The UI can show a loading state on `Card Start`, render the card on `Card` (payload), and finalize on `Card End`.
- `Text Message` events are always emitted and carry the assistant's reply incrementally.

<Tabs>
<Tab title="Dart">
Expand DownExpand Up@@ -63,23 +68,46 @@ class AIAssistantEventHandler with AIAssistantListener {
debugPrint(
"Received AI Event: ${aiAssistantBaseEvent.type} for Run ID: ${aiAssistantBaseEvent.id}",
);

// Handle card streaming events
if (aiAssistantBaseEvent is AIAssistantCardStartedEvent) {
debugPrint("Card generation started: ${aiAssistantBaseEvent.cardId}");
debugPrint("Execution text: ${aiAssistantBaseEvent.executionText}");
} else if (aiAssistantBaseEvent is AIAssistantCardReceivedEvent) {
debugPrint("Card received: ${aiAssistantBaseEvent.cardId}");
final cardPayload = aiAssistantBaseEvent.getCard();
// Pass cardPayload to CometChatCardView renderer
} else if (aiAssistantBaseEvent is AIAssistantCardEndedEvent) {
debugPrint("Card generation ended: ${aiAssistantBaseEvent.cardId}");
}
}
}
```
</Tab>
</Tabs>

#### Event descriptions
- Run Start: A new run has begun for the users message.
- Run Start: A new run has begun for the user's message.
- Tool Call Start: The agent decided to invoke a tool.
- Tool Call Arguments: Arguments being passed to the tool.
- Tool Call End: Tool execution completed.
- Tool Call Result: Tool’s output is available.
- Tool Call Result: Tool's output is available.
- Card Start: The agent started generating a card. Contains `cardId` and `executionText` (a human-readable status like "Building your product card...").
- Card: The full card payload is available. Use `getCard()` to retrieve the raw card JSON and pass it to the renderer.
- Card End: The card generation flow is finalized.
- Text Message Start: The agent started composing a reply.
- Text Message Content: Streaming content chunks for progressive rendering.
- Text Message End: The agent reply is complete.
- Run Finished: The run is finalized; persisted messages will follow.

#### Card Streaming Event Classes

| Class | Properties |
| -- | -- |
| `AIAssistantCardStartedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `executionText` |
| `AIAssistantCardReceivedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `getCard()` → `Map<String, dynamic>?` |
| `AIAssistantCardEndedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId` |

### Agentic Messages

These events are received via the **`MessageListener`** after the run completes.
Expand DownExpand Up@@ -112,4 +140,113 @@ These events are received via the **`MessageListener`** after the run completes.
}
```
</Tab>
</Tabs>
</Tabs>

<Note>

Starting from SDK version **5.0.5**, AI assistant message content is delivered via `getElements()`. If the agent response contains only a card (no accompanying text), `getText()` will return an empty string — always prefer `getElements()` as the primary data source for rendering.

</Note>

### AIAssistantMessage Elements

A persisted `AIAssistantMessage` carries its content in two ways:

1. **`getText()`** — The flat content string (unchanged, legacy/fallback path).
2. **`getElements()`** — An ordered array of `AIAssistantElement` objects representing discrete content blocks (text and cards) in the order the agent produced them. **This is the default render source** — when present, walk the list left-to-right and render each block in order.

When `getElements()` returns `null` or is empty (older messages), fall back to `getText()`.

#### AIAssistantElement

Each element exposes two accessors:

| Method | Return Type | Description |
| -- | -- | -- |
| `getType()` | `String?` | The element's type: `"text"`, `"card"`, `"graph"`, etc. |
| `getData()` | `dynamic` | The element's raw body data. Shape depends on type — `String` for text, `Map<String, dynamic>` (with keys `card` and `cardId`) for card, raw JSON value for others. |

<Tabs>
<Tab title="Dart">
```dart
void handleAIAssistantMessage(AIAssistantMessage message) {
final elements = message.getElements();

if (elements != null && elements.isNotEmpty) {
// Preferred path: walk elements in order
for (final element in elements) {
switch (element.getType()) {
case 'text':
final textContent = element.getData() as String;
debugPrint("Text block: $textContent");
break;
case 'card':
final cardData = element.getData() as Map<String, dynamic>;
final cardPayload = cardData['card'] as Map<String, dynamic>;
final cardId = cardData['cardId'] as String;
debugPrint("Card block: $cardId");
// Pass cardPayload to CometChatCardView renderer
break;
default:
debugPrint("Unknown element type: ${element.getType()}");
break;
}
}
} else {
// Fallback: use getText() for older messages without elements
debugPrint("Message text: ${message.text}");
}
}
```
</Tab>
</Tabs>

## Card Messages (Developer Cards)

Developer card messages are rich, interactive messages (buttons, images, styled layouts) described as JSON and sent via the Platform API or Bubble Builder. The SDK only **receives** card messages — it does not send them.

A `CardMessage` arrives with `category: "card"` and is delivered on the `onCardMessageReceived` callback of the `MessageListener`.

### CardMessage Class

| Method | Return Type | Description |
| -- | -- | -- |
| `getCard()` | `Map<String, dynamic>?` | The raw card schema payload. Pass directly to the card renderer. |
| `getText()` | `String?` | Preview text for push notifications and conversation list. |
| `getFallbackText()` | `String?` | Fallback text from inside the card (`card.fallbackText`). Used for accessibility or when the renderer fails. |
| `getTags()` | `List<String>?` | Tags associated with this message. |

<Tabs>
<Tab title="Dart">
```dart
const listenerId = "unique_listener_id";

class CardMessageHandler with MessageListener {
// CometChat.addMessageListener(listenerId, this);

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received: ${cardMessage.id}");

// Get the raw card payload for the renderer
final cardPayload = cardMessage.getCard();
debugPrint("Card payload: $cardPayload");

// Get fallback text for previews
final fallback = cardMessage.getFallbackText();
debugPrint("Fallback: $fallback");

// Get preview text for conversation list
final previewText = cardMessage.getText();
debugPrint("Preview text: $previewText");
}
}
```
</Tab>
</Tabs>

<Note>

Card messages are **receive-only**. They are created and sent exclusively via the Platform (REST) API and Dashboard Bubble Builder. The SDK exposes the card payload raw via `getCard()` — an external renderer library (e.g., CometChatCardView) is responsible for drawing the card UI.

</Note>
18 changes: 12 additions & 6 deletions sdk/flutter/real-time-listeners.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,6 +152,7 @@ The `MessageListener` class provides you with live events related to messages. B
| `onMessageEdited(BaseMessage message)` | This method is triggered when a particular message has been edited in a user/group conversation. |
| `onMessageDeleted(BaseMessage message)` | This event is triggered when a particular message is deleted in a user/group conversation. |
| `onInteractiveMessageReceived(InteractiveMessage message)` | This event is triggered when an Interactive Message is received. |
| `onCardMessageReceived(CardMessage message)` | This event is triggered when a Card Message is received. |
| `onInteractionGoalCompleted(InteractionReceipt receipt)` | This event is triggered when an interaction Goal is achieved. |
| `onTransientMessageReceived(TransientMessage transientMessage)` | This event is triggered when a Transient Message is received. |
| `onMessageReactionAdded(ReactionEvent reactionEvent)` | This event is triggered when a reaction is added to a message in a user/group conversation. |
Expand DownExpand Up@@ -222,19 +223,24 @@ class Class_Name with MessageListener {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {

}

@Override
public void onTransientMessageReceived(TransientMessage transientMessage) {

@override
void onTransientMessageReceived(TransientMessage transientMessage) {

}

@Override
public void onMessageReactionAdded(ReactionEvent reactionEvent) {
@override
void onMessageReactionAdded(ReactionEvent reactionEvent) {

}

@Override
public void onMessageReactionRemoved(ReactionEvent reactionEvent) {
@override
void onMessageReactionRemoved(ReactionEvent reactionEvent) {

}

Expand Down
7 changes: 6 additions & 1 deletion sdk/flutter/receive-messages.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,6 +44,11 @@ onInteractiveMessageReceived(InteractiveMessage message) {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received successfully: $cardMessage");
}


}
```
Expand DownExpand Up@@ -227,7 +232,7 @@ messageRequest.fetchPrevious(onSuccess: (List<BaseMessage> list) {
<Note>
Base Message

The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.
The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `CardMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.

</Note>

Expand Down
9 changes: 1 addition & 8 deletions sdk/flutter/setup.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,16 +22,9 @@ Minimum Requirement

### Add the CometChat Dependency

### Cloudsmith

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
9 changes: 3 additions & 6 deletions sdk/flutter/upgrading-from-v4-guide.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,16 +7,13 @@ This guide helps you migrate your Flutter application from CometChat SDK v4 to v

## Installation

### Cloudsmith
### Add the CometChat Dependency

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:
Update your `pubspec.yaml` to the latest v5 SDK:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions calls/flutter/migration-guide-v5.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,9 +13,7 @@ Calls SDK v5 is a **drop-in replacement** for v4. All v4 APIs are preserved as d

```yaml
dependencies:
cometchat_calls_sdk:
hosted: https://dart.cloudsmith.io/cometchat/cometchat/
version: ^5.0.0
cometchat_calls_sdk: ^5.0.3
```

<Info>
Expand Down
151 changes: 144 additions & 7 deletions sdk/flutter/ai-agents.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ AI Agents enable intelligent, automated interactions within your application. Th

## Agent Run Lifecycle and Message Flow

This section explains how a users text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
This section explains how a user's text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
- A user sends a text message to an Agent.
- The platform starts a run and streams real-time events via the **`AIAssistantListener`**.
- After the run completes, persisted Agentic Messages arrive via the **`MessageListener`**.
Expand All@@ -26,16 +26,21 @@ Events are received via the **`onAIAssistantEventReceived`** method of the **`AI
- Tool Call Arguments
- Tool Call End
- Tool Call Result
3. One or more assistant reply streams:
3. Zero or more card generation cycles (repeats for each card produced):
- Card Start
- Card (full payload)
- Card End
4. One or more assistant reply streams:
- Text Message Start
- Text Message Content (multiple times; token/char streaming)
- Text Message End
4. Run Finished
5. Run Finished

Notes:
- `Run Start` and `Run Finished` are always emitted.
- `Tool Call` events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run.
- `Text Message` events are always emitted and carry the assistant’s reply incrementally.
- `Card` events appear only when the agent produces a card. The UI can show a loading state on `Card Start`, render the card on `Card` (payload), and finalize on `Card End`.
- `Text Message` events are always emitted and carry the assistant's reply incrementally.

<Tabs>
<Tab title="Dart">
Expand DownExpand Up@@ -63,23 +68,46 @@ class AIAssistantEventHandler with AIAssistantListener {
debugPrint(
"Received AI Event: ${aiAssistantBaseEvent.type} for Run ID: ${aiAssistantBaseEvent.id}",
);

// Handle card streaming events
if (aiAssistantBaseEvent is AIAssistantCardStartedEvent) {
debugPrint("Card generation started: ${aiAssistantBaseEvent.cardId}");
debugPrint("Execution text: ${aiAssistantBaseEvent.executionText}");
} else if (aiAssistantBaseEvent is AIAssistantCardReceivedEvent) {
debugPrint("Card received: ${aiAssistantBaseEvent.cardId}");
final cardPayload = aiAssistantBaseEvent.getCard();
// Pass cardPayload to CometChatCardView renderer
} else if (aiAssistantBaseEvent is AIAssistantCardEndedEvent) {
debugPrint("Card generation ended: ${aiAssistantBaseEvent.cardId}");
}
}
}
```
</Tab>
</Tabs>

#### Event descriptions
- Run Start: A new run has begun for the users message.
- Run Start: A new run has begun for the user's message.
- Tool Call Start: The agent decided to invoke a tool.
- Tool Call Arguments: Arguments being passed to the tool.
- Tool Call End: Tool execution completed.
- Tool Call Result: Tool’s output is available.
- Tool Call Result: Tool's output is available.
- Card Start: The agent started generating a card. Contains `cardId` and `executionText` (a human-readable status like "Building your product card...").
- Card: The full card payload is available. Use `getCard()` to retrieve the raw card JSON and pass it to the renderer.
- Card End: The card generation flow is finalized.
- Text Message Start: The agent started composing a reply.
- Text Message Content: Streaming content chunks for progressive rendering.
- Text Message End: The agent reply is complete.
- Run Finished: The run is finalized; persisted messages will follow.

#### Card Streaming Event Classes

| Class | Properties |
| -- | -- |
| `AIAssistantCardStartedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `executionText` |
| `AIAssistantCardReceivedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `getCard()` → `Map<String, dynamic>?` |
| `AIAssistantCardEndedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId` |

### Agentic Messages

These events are received via the **`MessageListener`** after the run completes.
Expand DownExpand Up@@ -112,4 +140,113 @@ These events are received via the **`MessageListener`** after the run completes.
}
```
</Tab>
</Tabs>
</Tabs>

<Note>

Starting from SDK version **5.0.5**, AI assistant message content is delivered via `getElements()`. If the agent response contains only a card (no accompanying text), `getText()` will return an empty string — always prefer `getElements()` as the primary data source for rendering.

</Note>

### AIAssistantMessage Elements

A persisted `AIAssistantMessage` carries its content in two ways:

1. **`getText()`** — The flat content string (unchanged, legacy/fallback path).
2. **`getElements()`** — An ordered array of `AIAssistantElement` objects representing discrete content blocks (text and cards) in the order the agent produced them. **This is the default render source** — when present, walk the list left-to-right and render each block in order.

When `getElements()` returns `null` or is empty (older messages), fall back to `getText()`.

#### AIAssistantElement

Each element exposes two accessors:

| Method | Return Type | Description |
| -- | -- | -- |
| `getType()` | `String?` | The element's type: `"text"`, `"card"`, `"graph"`, etc. |
| `getData()` | `dynamic` | The element's raw body data. Shape depends on type — `String` for text, `Map<String, dynamic>` (with keys `card` and `cardId`) for card, raw JSON value for others. |

<Tabs>
<Tab title="Dart">
```dart
void handleAIAssistantMessage(AIAssistantMessage message) {
final elements = message.getElements();

if (elements != null && elements.isNotEmpty) {
// Preferred path: walk elements in order
for (final element in elements) {
switch (element.getType()) {
case 'text':
final textContent = element.getData() as String;
debugPrint("Text block: $textContent");
break;
case 'card':
final cardData = element.getData() as Map<String, dynamic>;
final cardPayload = cardData['card'] as Map<String, dynamic>;
final cardId = cardData['cardId'] as String;
debugPrint("Card block: $cardId");
// Pass cardPayload to CometChatCardView renderer
break;
default:
debugPrint("Unknown element type: ${element.getType()}");
break;
}
}
} else {
// Fallback: use getText() for older messages without elements
debugPrint("Message text: ${message.text}");
}
}
```
</Tab>
</Tabs>

## Card Messages (Developer Cards)

Developer card messages are rich, interactive messages (buttons, images, styled layouts) described as JSON and sent via the Platform API or Bubble Builder. The SDK only **receives** card messages — it does not send them.

A `CardMessage` arrives with `category: "card"` and is delivered on the `onCardMessageReceived` callback of the `MessageListener`.

### CardMessage Class

| Method | Return Type | Description |
| -- | -- | -- |
| `getCard()` | `Map<String, dynamic>?` | The raw card schema payload. Pass directly to the card renderer. |
| `getText()` | `String?` | Preview text for push notifications and conversation list. |
| `getFallbackText()` | `String?` | Fallback text from inside the card (`card.fallbackText`). Used for accessibility or when the renderer fails. |
| `getTags()` | `List<String>?` | Tags associated with this message. |

<Tabs>
<Tab title="Dart">
```dart
const listenerId = "unique_listener_id";

class CardMessageHandler with MessageListener {
// CometChat.addMessageListener(listenerId, this);

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received: ${cardMessage.id}");

// Get the raw card payload for the renderer
final cardPayload = cardMessage.getCard();
debugPrint("Card payload: $cardPayload");

// Get fallback text for previews
final fallback = cardMessage.getFallbackText();
debugPrint("Fallback: $fallback");

// Get preview text for conversation list
final previewText = cardMessage.getText();
debugPrint("Preview text: $previewText");
}
}
```
</Tab>
</Tabs>

<Note>

Card messages are **receive-only**. They are created and sent exclusively via the Platform (REST) API and Dashboard Bubble Builder. The SDK exposes the card payload raw via `getCard()` — an external renderer library (e.g., CometChatCardView) is responsible for drawing the card UI.

</Note>
18 changes: 12 additions & 6 deletions sdk/flutter/real-time-listeners.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,6 +152,7 @@ The `MessageListener` class provides you with live events related to messages. B
| `onMessageEdited(BaseMessage message)` | This method is triggered when a particular message has been edited in a user/group conversation. |
| `onMessageDeleted(BaseMessage message)` | This event is triggered when a particular message is deleted in a user/group conversation. |
| `onInteractiveMessageReceived(InteractiveMessage message)` | This event is triggered when an Interactive Message is received. |
| `onCardMessageReceived(CardMessage message)` | This event is triggered when a Card Message is received. |
| `onInteractionGoalCompleted(InteractionReceipt receipt)` | This event is triggered when an interaction Goal is achieved. |
| `onTransientMessageReceived(TransientMessage transientMessage)` | This event is triggered when a Transient Message is received. |
| `onMessageReactionAdded(ReactionEvent reactionEvent)` | This event is triggered when a reaction is added to a message in a user/group conversation. |
Expand DownExpand Up@@ -222,19 +223,24 @@ class Class_Name with MessageListener {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {

}

@Override
public void onTransientMessageReceived(TransientMessage transientMessage) {

@override
void onTransientMessageReceived(TransientMessage transientMessage) {

}

@Override
public void onMessageReactionAdded(ReactionEvent reactionEvent) {
@override
void onMessageReactionAdded(ReactionEvent reactionEvent) {

}

@Override
public void onMessageReactionRemoved(ReactionEvent reactionEvent) {
@override
void onMessageReactionRemoved(ReactionEvent reactionEvent) {

}

Expand Down
7 changes: 6 additions & 1 deletion sdk/flutter/receive-messages.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,6 +44,11 @@ onInteractiveMessageReceived(InteractiveMessage message) {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received successfully: $cardMessage");
}


}
```
Expand DownExpand Up@@ -227,7 +232,7 @@ messageRequest.fetchPrevious(onSuccess: (List<BaseMessage> list) {
<Note>
Base Message

The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.
The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `CardMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.

</Note>

Expand Down
9 changes: 1 addition & 8 deletions sdk/flutter/setup.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,16 +22,9 @@ Minimum Requirement

### Add the CometChat Dependency

### Cloudsmith

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
9 changes: 3 additions & 6 deletions sdk/flutter/upgrading-from-v4-guide.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,16 +7,13 @@ This guide helps you migrate your Flutter application from CometChat SDK v4 to v

## Installation

### Cloudsmith
### Add the CometChat Dependency

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:
Update your `pubspec.yaml` to the latest v5 SDK:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions calls/flutter/migration-guide-v5.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,9 +13,7 @@ Calls SDK v5 is a **drop-in replacement** for v4. All v4 APIs are preserved as d

```yaml
dependencies:
cometchat_calls_sdk:
hosted: https://dart.cloudsmith.io/cometchat/cometchat/
version: ^5.0.0
cometchat_calls_sdk: ^5.0.3
```

<Info>
Expand Down
151 changes: 144 additions & 7 deletions sdk/flutter/ai-agents.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ AI Agents enable intelligent, automated interactions within your application. Th

## Agent Run Lifecycle and Message Flow

This section explains how a users text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
This section explains how a user's text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
- A user sends a text message to an Agent.
- The platform starts a run and streams real-time events via the **`AIAssistantListener`**.
- After the run completes, persisted Agentic Messages arrive via the **`MessageListener`**.
Expand All@@ -26,16 +26,21 @@ Events are received via the **`onAIAssistantEventReceived`** method of the **`AI
- Tool Call Arguments
- Tool Call End
- Tool Call Result
3. One or more assistant reply streams:
3. Zero or more card generation cycles (repeats for each card produced):
- Card Start
- Card (full payload)
- Card End
4. One or more assistant reply streams:
- Text Message Start
- Text Message Content (multiple times; token/char streaming)
- Text Message End
4. Run Finished
5. Run Finished

Notes:
- `Run Start` and `Run Finished` are always emitted.
- `Tool Call` events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run.
- `Text Message` events are always emitted and carry the assistant’s reply incrementally.
- `Card` events appear only when the agent produces a card. The UI can show a loading state on `Card Start`, render the card on `Card` (payload), and finalize on `Card End`.
- `Text Message` events are always emitted and carry the assistant's reply incrementally.

<Tabs>
<Tab title="Dart">
Expand DownExpand Up@@ -63,23 +68,46 @@ class AIAssistantEventHandler with AIAssistantListener {
debugPrint(
"Received AI Event: ${aiAssistantBaseEvent.type} for Run ID: ${aiAssistantBaseEvent.id}",
);

// Handle card streaming events
if (aiAssistantBaseEvent is AIAssistantCardStartedEvent) {
debugPrint("Card generation started: ${aiAssistantBaseEvent.cardId}");
debugPrint("Execution text: ${aiAssistantBaseEvent.executionText}");
} else if (aiAssistantBaseEvent is AIAssistantCardReceivedEvent) {
debugPrint("Card received: ${aiAssistantBaseEvent.cardId}");
final cardPayload = aiAssistantBaseEvent.getCard();
// Pass cardPayload to CometChatCardView renderer
} else if (aiAssistantBaseEvent is AIAssistantCardEndedEvent) {
debugPrint("Card generation ended: ${aiAssistantBaseEvent.cardId}");
}
}
}
```
</Tab>
</Tabs>

#### Event descriptions
- Run Start: A new run has begun for the users message.
- Run Start: A new run has begun for the user's message.
- Tool Call Start: The agent decided to invoke a tool.
- Tool Call Arguments: Arguments being passed to the tool.
- Tool Call End: Tool execution completed.
- Tool Call Result: Tool’s output is available.
- Tool Call Result: Tool's output is available.
- Card Start: The agent started generating a card. Contains `cardId` and `executionText` (a human-readable status like "Building your product card...").
- Card: The full card payload is available. Use `getCard()` to retrieve the raw card JSON and pass it to the renderer.
- Card End: The card generation flow is finalized.
- Text Message Start: The agent started composing a reply.
- Text Message Content: Streaming content chunks for progressive rendering.
- Text Message End: The agent reply is complete.
- Run Finished: The run is finalized; persisted messages will follow.

#### Card Streaming Event Classes

| Class | Properties |
| -- | -- |
| `AIAssistantCardStartedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `executionText` |
| `AIAssistantCardReceivedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `getCard()` → `Map<String, dynamic>?` |
| `AIAssistantCardEndedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId` |

### Agentic Messages

These events are received via the **`MessageListener`** after the run completes.
Expand DownExpand Up@@ -112,4 +140,113 @@ These events are received via the **`MessageListener`** after the run completes.
}
```
</Tab>
</Tabs>
</Tabs>

<Note>

Starting from SDK version **5.0.5**, AI assistant message content is delivered via `getElements()`. If the agent response contains only a card (no accompanying text), `getText()` will return an empty string — always prefer `getElements()` as the primary data source for rendering.

</Note>

### AIAssistantMessage Elements

A persisted `AIAssistantMessage` carries its content in two ways:

1. **`getText()`** — The flat content string (unchanged, legacy/fallback path).
2. **`getElements()`** — An ordered array of `AIAssistantElement` objects representing discrete content blocks (text and cards) in the order the agent produced them. **This is the default render source** — when present, walk the list left-to-right and render each block in order.

When `getElements()` returns `null` or is empty (older messages), fall back to `getText()`.

#### AIAssistantElement

Each element exposes two accessors:

| Method | Return Type | Description |
| -- | -- | -- |
| `getType()` | `String?` | The element's type: `"text"`, `"card"`, `"graph"`, etc. |
| `getData()` | `dynamic` | The element's raw body data. Shape depends on type — `String` for text, `Map<String, dynamic>` (with keys `card` and `cardId`) for card, raw JSON value for others. |

<Tabs>
<Tab title="Dart">
```dart
void handleAIAssistantMessage(AIAssistantMessage message) {
final elements = message.getElements();

if (elements != null && elements.isNotEmpty) {
// Preferred path: walk elements in order
for (final element in elements) {
switch (element.getType()) {
case 'text':
final textContent = element.getData() as String;
debugPrint("Text block: $textContent");
break;
case 'card':
final cardData = element.getData() as Map<String, dynamic>;
final cardPayload = cardData['card'] as Map<String, dynamic>;
final cardId = cardData['cardId'] as String;
debugPrint("Card block: $cardId");
// Pass cardPayload to CometChatCardView renderer
break;
default:
debugPrint("Unknown element type: ${element.getType()}");
break;
}
}
} else {
// Fallback: use getText() for older messages without elements
debugPrint("Message text: ${message.text}");
}
}
```
</Tab>
</Tabs>

## Card Messages (Developer Cards)

Developer card messages are rich, interactive messages (buttons, images, styled layouts) described as JSON and sent via the Platform API or Bubble Builder. The SDK only **receives** card messages — it does not send them.

A `CardMessage` arrives with `category: "card"` and is delivered on the `onCardMessageReceived` callback of the `MessageListener`.

### CardMessage Class

| Method | Return Type | Description |
| -- | -- | -- |
| `getCard()` | `Map<String, dynamic>?` | The raw card schema payload. Pass directly to the card renderer. |
| `getText()` | `String?` | Preview text for push notifications and conversation list. |
| `getFallbackText()` | `String?` | Fallback text from inside the card (`card.fallbackText`). Used for accessibility or when the renderer fails. |
| `getTags()` | `List<String>?` | Tags associated with this message. |

<Tabs>
<Tab title="Dart">
```dart
const listenerId = "unique_listener_id";

class CardMessageHandler with MessageListener {
// CometChat.addMessageListener(listenerId, this);

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received: ${cardMessage.id}");

// Get the raw card payload for the renderer
final cardPayload = cardMessage.getCard();
debugPrint("Card payload: $cardPayload");

// Get fallback text for previews
final fallback = cardMessage.getFallbackText();
debugPrint("Fallback: $fallback");

// Get preview text for conversation list
final previewText = cardMessage.getText();
debugPrint("Preview text: $previewText");
}
}
```
</Tab>
</Tabs>

<Note>

Card messages are **receive-only**. They are created and sent exclusively via the Platform (REST) API and Dashboard Bubble Builder. The SDK exposes the card payload raw via `getCard()` — an external renderer library (e.g., CometChatCardView) is responsible for drawing the card UI.

</Note>
18 changes: 12 additions & 6 deletions sdk/flutter/real-time-listeners.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,6 +152,7 @@ The `MessageListener` class provides you with live events related to messages. B
| `onMessageEdited(BaseMessage message)` | This method is triggered when a particular message has been edited in a user/group conversation. |
| `onMessageDeleted(BaseMessage message)` | This event is triggered when a particular message is deleted in a user/group conversation. |
| `onInteractiveMessageReceived(InteractiveMessage message)` | This event is triggered when an Interactive Message is received. |
| `onCardMessageReceived(CardMessage message)` | This event is triggered when a Card Message is received. |
| `onInteractionGoalCompleted(InteractionReceipt receipt)` | This event is triggered when an interaction Goal is achieved. |
| `onTransientMessageReceived(TransientMessage transientMessage)` | This event is triggered when a Transient Message is received. |
| `onMessageReactionAdded(ReactionEvent reactionEvent)` | This event is triggered when a reaction is added to a message in a user/group conversation. |
Expand DownExpand Up@@ -222,19 +223,24 @@ class Class_Name with MessageListener {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {

}

@Override
public void onTransientMessageReceived(TransientMessage transientMessage) {

@override
void onTransientMessageReceived(TransientMessage transientMessage) {

}

@Override
public void onMessageReactionAdded(ReactionEvent reactionEvent) {
@override
void onMessageReactionAdded(ReactionEvent reactionEvent) {

}

@Override
public void onMessageReactionRemoved(ReactionEvent reactionEvent) {
@override
void onMessageReactionRemoved(ReactionEvent reactionEvent) {

}

Expand Down
7 changes: 6 additions & 1 deletion sdk/flutter/receive-messages.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,6 +44,11 @@ onInteractiveMessageReceived(InteractiveMessage message) {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received successfully: $cardMessage");
}


}
```
Expand DownExpand Up@@ -227,7 +232,7 @@ messageRequest.fetchPrevious(onSuccess: (List<BaseMessage> list) {
<Note>
Base Message

The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.
The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `CardMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.

</Note>

Expand Down
9 changes: 1 addition & 8 deletions sdk/flutter/setup.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,16 +22,9 @@ Minimum Requirement

### Add the CometChat Dependency

### Cloudsmith

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
9 changes: 3 additions & 6 deletions sdk/flutter/upgrading-from-v4-guide.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,16 +7,13 @@ This guide helps you migrate your Flutter application from CometChat SDK v4 to v

## Installation

### Cloudsmith
### Add the CometChat Dependency

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:
Update your `pubspec.yaml` to the latest v5 SDK:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions calls/flutter/migration-guide-v5.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,9 +13,7 @@ Calls SDK v5 is a **drop-in replacement** for v4. All v4 APIs are preserved as d

```yaml
dependencies:
cometchat_calls_sdk:
hosted: https://dart.cloudsmith.io/cometchat/cometchat/
version: ^5.0.0
cometchat_calls_sdk: ^5.0.3
```

<Info>
Expand Down
151 changes: 144 additions & 7 deletions sdk/flutter/ai-agents.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ AI Agents enable intelligent, automated interactions within your application. Th

## Agent Run Lifecycle and Message Flow

This section explains how a users text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
This section explains how a user's text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
- A user sends a text message to an Agent.
- The platform starts a run and streams real-time events via the **`AIAssistantListener`**.
- After the run completes, persisted Agentic Messages arrive via the **`MessageListener`**.
Expand All@@ -26,16 +26,21 @@ Events are received via the **`onAIAssistantEventReceived`** method of the **`AI
- Tool Call Arguments
- Tool Call End
- Tool Call Result
3. One or more assistant reply streams:
3. Zero or more card generation cycles (repeats for each card produced):
- Card Start
- Card (full payload)
- Card End
4. One or more assistant reply streams:
- Text Message Start
- Text Message Content (multiple times; token/char streaming)
- Text Message End
4. Run Finished
5. Run Finished

Notes:
- `Run Start` and `Run Finished` are always emitted.
- `Tool Call` events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run.
- `Text Message` events are always emitted and carry the assistant’s reply incrementally.
- `Card` events appear only when the agent produces a card. The UI can show a loading state on `Card Start`, render the card on `Card` (payload), and finalize on `Card End`.
- `Text Message` events are always emitted and carry the assistant's reply incrementally.

<Tabs>
<Tab title="Dart">
Expand DownExpand Up@@ -63,23 +68,46 @@ class AIAssistantEventHandler with AIAssistantListener {
debugPrint(
"Received AI Event: ${aiAssistantBaseEvent.type} for Run ID: ${aiAssistantBaseEvent.id}",
);

// Handle card streaming events
if (aiAssistantBaseEvent is AIAssistantCardStartedEvent) {
debugPrint("Card generation started: ${aiAssistantBaseEvent.cardId}");
debugPrint("Execution text: ${aiAssistantBaseEvent.executionText}");
} else if (aiAssistantBaseEvent is AIAssistantCardReceivedEvent) {
debugPrint("Card received: ${aiAssistantBaseEvent.cardId}");
final cardPayload = aiAssistantBaseEvent.getCard();
// Pass cardPayload to CometChatCardView renderer
} else if (aiAssistantBaseEvent is AIAssistantCardEndedEvent) {
debugPrint("Card generation ended: ${aiAssistantBaseEvent.cardId}");
}
}
}
```
</Tab>
</Tabs>

#### Event descriptions
- Run Start: A new run has begun for the users message.
- Run Start: A new run has begun for the user's message.
- Tool Call Start: The agent decided to invoke a tool.
- Tool Call Arguments: Arguments being passed to the tool.
- Tool Call End: Tool execution completed.
- Tool Call Result: Tool’s output is available.
- Tool Call Result: Tool's output is available.
- Card Start: The agent started generating a card. Contains `cardId` and `executionText` (a human-readable status like "Building your product card...").
- Card: The full card payload is available. Use `getCard()` to retrieve the raw card JSON and pass it to the renderer.
- Card End: The card generation flow is finalized.
- Text Message Start: The agent started composing a reply.
- Text Message Content: Streaming content chunks for progressive rendering.
- Text Message End: The agent reply is complete.
- Run Finished: The run is finalized; persisted messages will follow.

#### Card Streaming Event Classes

| Class | Properties |
| -- | -- |
| `AIAssistantCardStartedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `executionText` |
| `AIAssistantCardReceivedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `getCard()` → `Map<String, dynamic>?` |
| `AIAssistantCardEndedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId` |

### Agentic Messages

These events are received via the **`MessageListener`** after the run completes.
Expand DownExpand Up@@ -112,4 +140,113 @@ These events are received via the **`MessageListener`** after the run completes.
}
```
</Tab>
</Tabs>
</Tabs>

<Note>

Starting from SDK version **5.0.5**, AI assistant message content is delivered via `getElements()`. If the agent response contains only a card (no accompanying text), `getText()` will return an empty string — always prefer `getElements()` as the primary data source for rendering.

</Note>

### AIAssistantMessage Elements

A persisted `AIAssistantMessage` carries its content in two ways:

1. **`getText()`** — The flat content string (unchanged, legacy/fallback path).
2. **`getElements()`** — An ordered array of `AIAssistantElement` objects representing discrete content blocks (text and cards) in the order the agent produced them. **This is the default render source** — when present, walk the list left-to-right and render each block in order.

When `getElements()` returns `null` or is empty (older messages), fall back to `getText()`.

#### AIAssistantElement

Each element exposes two accessors:

| Method | Return Type | Description |
| -- | -- | -- |
| `getType()` | `String?` | The element's type: `"text"`, `"card"`, `"graph"`, etc. |
| `getData()` | `dynamic` | The element's raw body data. Shape depends on type — `String` for text, `Map<String, dynamic>` (with keys `card` and `cardId`) for card, raw JSON value for others. |

<Tabs>
<Tab title="Dart">
```dart
void handleAIAssistantMessage(AIAssistantMessage message) {
final elements = message.getElements();

if (elements != null && elements.isNotEmpty) {
// Preferred path: walk elements in order
for (final element in elements) {
switch (element.getType()) {
case 'text':
final textContent = element.getData() as String;
debugPrint("Text block: $textContent");
break;
case 'card':
final cardData = element.getData() as Map<String, dynamic>;
final cardPayload = cardData['card'] as Map<String, dynamic>;
final cardId = cardData['cardId'] as String;
debugPrint("Card block: $cardId");
// Pass cardPayload to CometChatCardView renderer
break;
default:
debugPrint("Unknown element type: ${element.getType()}");
break;
}
}
} else {
// Fallback: use getText() for older messages without elements
debugPrint("Message text: ${message.text}");
}
}
```
</Tab>
</Tabs>

## Card Messages (Developer Cards)

Developer card messages are rich, interactive messages (buttons, images, styled layouts) described as JSON and sent via the Platform API or Bubble Builder. The SDK only **receives** card messages — it does not send them.

A `CardMessage` arrives with `category: "card"` and is delivered on the `onCardMessageReceived` callback of the `MessageListener`.

### CardMessage Class

| Method | Return Type | Description |
| -- | -- | -- |
| `getCard()` | `Map<String, dynamic>?` | The raw card schema payload. Pass directly to the card renderer. |
| `getText()` | `String?` | Preview text for push notifications and conversation list. |
| `getFallbackText()` | `String?` | Fallback text from inside the card (`card.fallbackText`). Used for accessibility or when the renderer fails. |
| `getTags()` | `List<String>?` | Tags associated with this message. |

<Tabs>
<Tab title="Dart">
```dart
const listenerId = "unique_listener_id";

class CardMessageHandler with MessageListener {
// CometChat.addMessageListener(listenerId, this);

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received: ${cardMessage.id}");

// Get the raw card payload for the renderer
final cardPayload = cardMessage.getCard();
debugPrint("Card payload: $cardPayload");

// Get fallback text for previews
final fallback = cardMessage.getFallbackText();
debugPrint("Fallback: $fallback");

// Get preview text for conversation list
final previewText = cardMessage.getText();
debugPrint("Preview text: $previewText");
}
}
```
</Tab>
</Tabs>

<Note>

Card messages are **receive-only**. They are created and sent exclusively via the Platform (REST) API and Dashboard Bubble Builder. The SDK exposes the card payload raw via `getCard()` — an external renderer library (e.g., CometChatCardView) is responsible for drawing the card UI.

</Note>
18 changes: 12 additions & 6 deletions sdk/flutter/real-time-listeners.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,6 +152,7 @@ The `MessageListener` class provides you with live events related to messages. B
| `onMessageEdited(BaseMessage message)` | This method is triggered when a particular message has been edited in a user/group conversation. |
| `onMessageDeleted(BaseMessage message)` | This event is triggered when a particular message is deleted in a user/group conversation. |
| `onInteractiveMessageReceived(InteractiveMessage message)` | This event is triggered when an Interactive Message is received. |
| `onCardMessageReceived(CardMessage message)` | This event is triggered when a Card Message is received. |
| `onInteractionGoalCompleted(InteractionReceipt receipt)` | This event is triggered when an interaction Goal is achieved. |
| `onTransientMessageReceived(TransientMessage transientMessage)` | This event is triggered when a Transient Message is received. |
| `onMessageReactionAdded(ReactionEvent reactionEvent)` | This event is triggered when a reaction is added to a message in a user/group conversation. |
Expand DownExpand Up@@ -222,19 +223,24 @@ class Class_Name with MessageListener {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {

}

@Override
public void onTransientMessageReceived(TransientMessage transientMessage) {

@override
void onTransientMessageReceived(TransientMessage transientMessage) {

}

@Override
public void onMessageReactionAdded(ReactionEvent reactionEvent) {
@override
void onMessageReactionAdded(ReactionEvent reactionEvent) {

}

@Override
public void onMessageReactionRemoved(ReactionEvent reactionEvent) {
@override
void onMessageReactionRemoved(ReactionEvent reactionEvent) {

}

Expand Down
7 changes: 6 additions & 1 deletion sdk/flutter/receive-messages.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,6 +44,11 @@ onInteractiveMessageReceived(InteractiveMessage message) {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received successfully: $cardMessage");
}


}
```
Expand DownExpand Up@@ -227,7 +232,7 @@ messageRequest.fetchPrevious(onSuccess: (List<BaseMessage> list) {
<Note>
Base Message

The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.
The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `CardMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.

</Note>

Expand Down
9 changes: 1 addition & 8 deletions sdk/flutter/setup.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,16 +22,9 @@ Minimum Requirement

### Add the CometChat Dependency

### Cloudsmith

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
9 changes: 3 additions & 6 deletions sdk/flutter/upgrading-from-v4-guide.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,16 +7,13 @@ This guide helps you migrate your Flutter application from CometChat SDK v4 to v

## Installation

### Cloudsmith
### Add the CometChat Dependency

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:
Update your `pubspec.yaml` to the latest v5 SDK:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions calls/flutter/migration-guide-v5.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,9 +13,7 @@ Calls SDK v5 is a **drop-in replacement** for v4. All v4 APIs are preserved as d

```yaml
dependencies:
cometchat_calls_sdk:
hosted: https://dart.cloudsmith.io/cometchat/cometchat/
version: ^5.0.0
cometchat_calls_sdk: ^5.0.3
```

<Info>
Expand Down
151 changes: 144 additions & 7 deletions sdk/flutter/ai-agents.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ AI Agents enable intelligent, automated interactions within your application. Th

## Agent Run Lifecycle and Message Flow

This section explains how a users text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
This section explains how a user's text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
- A user sends a text message to an Agent.
- The platform starts a run and streams real-time events via the **`AIAssistantListener`**.
- After the run completes, persisted Agentic Messages arrive via the **`MessageListener`**.
Expand All@@ -26,16 +26,21 @@ Events are received via the **`onAIAssistantEventReceived`** method of the **`AI
- Tool Call Arguments
- Tool Call End
- Tool Call Result
3. One or more assistant reply streams:
3. Zero or more card generation cycles (repeats for each card produced):
- Card Start
- Card (full payload)
- Card End
4. One or more assistant reply streams:
- Text Message Start
- Text Message Content (multiple times; token/char streaming)
- Text Message End
4. Run Finished
5. Run Finished

Notes:
- `Run Start` and `Run Finished` are always emitted.
- `Tool Call` events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run.
- `Text Message` events are always emitted and carry the assistant’s reply incrementally.
- `Card` events appear only when the agent produces a card. The UI can show a loading state on `Card Start`, render the card on `Card` (payload), and finalize on `Card End`.
- `Text Message` events are always emitted and carry the assistant's reply incrementally.

<Tabs>
<Tab title="Dart">
Expand DownExpand Up@@ -63,23 +68,46 @@ class AIAssistantEventHandler with AIAssistantListener {
debugPrint(
"Received AI Event: ${aiAssistantBaseEvent.type} for Run ID: ${aiAssistantBaseEvent.id}",
);

// Handle card streaming events
if (aiAssistantBaseEvent is AIAssistantCardStartedEvent) {
debugPrint("Card generation started: ${aiAssistantBaseEvent.cardId}");
debugPrint("Execution text: ${aiAssistantBaseEvent.executionText}");
} else if (aiAssistantBaseEvent is AIAssistantCardReceivedEvent) {
debugPrint("Card received: ${aiAssistantBaseEvent.cardId}");
final cardPayload = aiAssistantBaseEvent.getCard();
// Pass cardPayload to CometChatCardView renderer
} else if (aiAssistantBaseEvent is AIAssistantCardEndedEvent) {
debugPrint("Card generation ended: ${aiAssistantBaseEvent.cardId}");
}
}
}
```
</Tab>
</Tabs>

#### Event descriptions
- Run Start: A new run has begun for the users message.
- Run Start: A new run has begun for the user's message.
- Tool Call Start: The agent decided to invoke a tool.
- Tool Call Arguments: Arguments being passed to the tool.
- Tool Call End: Tool execution completed.
- Tool Call Result: Tool’s output is available.
- Tool Call Result: Tool's output is available.
- Card Start: The agent started generating a card. Contains `cardId` and `executionText` (a human-readable status like "Building your product card...").
- Card: The full card payload is available. Use `getCard()` to retrieve the raw card JSON and pass it to the renderer.
- Card End: The card generation flow is finalized.
- Text Message Start: The agent started composing a reply.
- Text Message Content: Streaming content chunks for progressive rendering.
- Text Message End: The agent reply is complete.
- Run Finished: The run is finalized; persisted messages will follow.

#### Card Streaming Event Classes

| Class | Properties |
| -- | -- |
| `AIAssistantCardStartedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `executionText` |
| `AIAssistantCardReceivedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `getCard()` → `Map<String, dynamic>?` |
| `AIAssistantCardEndedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId` |

### Agentic Messages

These events are received via the **`MessageListener`** after the run completes.
Expand DownExpand Up@@ -112,4 +140,113 @@ These events are received via the **`MessageListener`** after the run completes.
}
```
</Tab>
</Tabs>
</Tabs>

<Note>

Starting from SDK version **5.0.5**, AI assistant message content is delivered via `getElements()`. If the agent response contains only a card (no accompanying text), `getText()` will return an empty string — always prefer `getElements()` as the primary data source for rendering.

</Note>

### AIAssistantMessage Elements

A persisted `AIAssistantMessage` carries its content in two ways:

1. **`getText()`** — The flat content string (unchanged, legacy/fallback path).
2. **`getElements()`** — An ordered array of `AIAssistantElement` objects representing discrete content blocks (text and cards) in the order the agent produced them. **This is the default render source** — when present, walk the list left-to-right and render each block in order.

When `getElements()` returns `null` or is empty (older messages), fall back to `getText()`.

#### AIAssistantElement

Each element exposes two accessors:

| Method | Return Type | Description |
| -- | -- | -- |
| `getType()` | `String?` | The element's type: `"text"`, `"card"`, `"graph"`, etc. |
| `getData()` | `dynamic` | The element's raw body data. Shape depends on type — `String` for text, `Map<String, dynamic>` (with keys `card` and `cardId`) for card, raw JSON value for others. |

<Tabs>
<Tab title="Dart">
```dart
void handleAIAssistantMessage(AIAssistantMessage message) {
final elements = message.getElements();

if (elements != null && elements.isNotEmpty) {
// Preferred path: walk elements in order
for (final element in elements) {
switch (element.getType()) {
case 'text':
final textContent = element.getData() as String;
debugPrint("Text block: $textContent");
break;
case 'card':
final cardData = element.getData() as Map<String, dynamic>;
final cardPayload = cardData['card'] as Map<String, dynamic>;
final cardId = cardData['cardId'] as String;
debugPrint("Card block: $cardId");
// Pass cardPayload to CometChatCardView renderer
break;
default:
debugPrint("Unknown element type: ${element.getType()}");
break;
}
}
} else {
// Fallback: use getText() for older messages without elements
debugPrint("Message text: ${message.text}");
}
}
```
</Tab>
</Tabs>

## Card Messages (Developer Cards)

Developer card messages are rich, interactive messages (buttons, images, styled layouts) described as JSON and sent via the Platform API or Bubble Builder. The SDK only **receives** card messages — it does not send them.

A `CardMessage` arrives with `category: "card"` and is delivered on the `onCardMessageReceived` callback of the `MessageListener`.

### CardMessage Class

| Method | Return Type | Description |
| -- | -- | -- |
| `getCard()` | `Map<String, dynamic>?` | The raw card schema payload. Pass directly to the card renderer. |
| `getText()` | `String?` | Preview text for push notifications and conversation list. |
| `getFallbackText()` | `String?` | Fallback text from inside the card (`card.fallbackText`). Used for accessibility or when the renderer fails. |
| `getTags()` | `List<String>?` | Tags associated with this message. |

<Tabs>
<Tab title="Dart">
```dart
const listenerId = "unique_listener_id";

class CardMessageHandler with MessageListener {
// CometChat.addMessageListener(listenerId, this);

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received: ${cardMessage.id}");

// Get the raw card payload for the renderer
final cardPayload = cardMessage.getCard();
debugPrint("Card payload: $cardPayload");

// Get fallback text for previews
final fallback = cardMessage.getFallbackText();
debugPrint("Fallback: $fallback");

// Get preview text for conversation list
final previewText = cardMessage.getText();
debugPrint("Preview text: $previewText");
}
}
```
</Tab>
</Tabs>

<Note>

Card messages are **receive-only**. They are created and sent exclusively via the Platform (REST) API and Dashboard Bubble Builder. The SDK exposes the card payload raw via `getCard()` — an external renderer library (e.g., CometChatCardView) is responsible for drawing the card UI.

</Note>
18 changes: 12 additions & 6 deletions sdk/flutter/real-time-listeners.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,6 +152,7 @@ The `MessageListener` class provides you with live events related to messages. B
| `onMessageEdited(BaseMessage message)` | This method is triggered when a particular message has been edited in a user/group conversation. |
| `onMessageDeleted(BaseMessage message)` | This event is triggered when a particular message is deleted in a user/group conversation. |
| `onInteractiveMessageReceived(InteractiveMessage message)` | This event is triggered when an Interactive Message is received. |
| `onCardMessageReceived(CardMessage message)` | This event is triggered when a Card Message is received. |
| `onInteractionGoalCompleted(InteractionReceipt receipt)` | This event is triggered when an interaction Goal is achieved. |
| `onTransientMessageReceived(TransientMessage transientMessage)` | This event is triggered when a Transient Message is received. |
| `onMessageReactionAdded(ReactionEvent reactionEvent)` | This event is triggered when a reaction is added to a message in a user/group conversation. |
Expand DownExpand Up@@ -222,19 +223,24 @@ class Class_Name with MessageListener {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {

}

@Override
public void onTransientMessageReceived(TransientMessage transientMessage) {

@override
void onTransientMessageReceived(TransientMessage transientMessage) {

}

@Override
public void onMessageReactionAdded(ReactionEvent reactionEvent) {
@override
void onMessageReactionAdded(ReactionEvent reactionEvent) {

}

@Override
public void onMessageReactionRemoved(ReactionEvent reactionEvent) {
@override
void onMessageReactionRemoved(ReactionEvent reactionEvent) {

}

Expand Down
7 changes: 6 additions & 1 deletion sdk/flutter/receive-messages.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,6 +44,11 @@ onInteractiveMessageReceived(InteractiveMessage message) {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received successfully: $cardMessage");
}


}
```
Expand DownExpand Up@@ -227,7 +232,7 @@ messageRequest.fetchPrevious(onSuccess: (List<BaseMessage> list) {
<Note>
Base Message

The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.
The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `CardMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.

</Note>

Expand Down
9 changes: 1 addition & 8 deletions sdk/flutter/setup.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,16 +22,9 @@ Minimum Requirement

### Add the CometChat Dependency

### Cloudsmith

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
9 changes: 3 additions & 6 deletions sdk/flutter/upgrading-from-v4-guide.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,16 +7,13 @@ This guide helps you migrate your Flutter application from CometChat SDK v4 to v

## Installation

### Cloudsmith
### Add the CometChat Dependency

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:
Update your `pubspec.yaml` to the latest v5 SDK:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions calls/flutter/migration-guide-v5.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,9 +13,7 @@ Calls SDK v5 is a **drop-in replacement** for v4. All v4 APIs are preserved as d

```yaml
dependencies:
cometchat_calls_sdk:
hosted: https://dart.cloudsmith.io/cometchat/cometchat/
version: ^5.0.0
cometchat_calls_sdk: ^5.0.3
```

<Info>
Expand Down
151 changes: 144 additions & 7 deletions sdk/flutter/ai-agents.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ AI Agents enable intelligent, automated interactions within your application. Th

## Agent Run Lifecycle and Message Flow

This section explains how a users text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
This section explains how a user's text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
- A user sends a text message to an Agent.
- The platform starts a run and streams real-time events via the **`AIAssistantListener`**.
- After the run completes, persisted Agentic Messages arrive via the **`MessageListener`**.
Expand All@@ -26,16 +26,21 @@ Events are received via the **`onAIAssistantEventReceived`** method of the **`AI
- Tool Call Arguments
- Tool Call End
- Tool Call Result
3. One or more assistant reply streams:
3. Zero or more card generation cycles (repeats for each card produced):
- Card Start
- Card (full payload)
- Card End
4. One or more assistant reply streams:
- Text Message Start
- Text Message Content (multiple times; token/char streaming)
- Text Message End
4. Run Finished
5. Run Finished

Notes:
- `Run Start` and `Run Finished` are always emitted.
- `Tool Call` events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run.
- `Text Message` events are always emitted and carry the assistant’s reply incrementally.
- `Card` events appear only when the agent produces a card. The UI can show a loading state on `Card Start`, render the card on `Card` (payload), and finalize on `Card End`.
- `Text Message` events are always emitted and carry the assistant's reply incrementally.

<Tabs>
<Tab title="Dart">
Expand DownExpand Up@@ -63,23 +68,46 @@ class AIAssistantEventHandler with AIAssistantListener {
debugPrint(
"Received AI Event: ${aiAssistantBaseEvent.type} for Run ID: ${aiAssistantBaseEvent.id}",
);

// Handle card streaming events
if (aiAssistantBaseEvent is AIAssistantCardStartedEvent) {
debugPrint("Card generation started: ${aiAssistantBaseEvent.cardId}");
debugPrint("Execution text: ${aiAssistantBaseEvent.executionText}");
} else if (aiAssistantBaseEvent is AIAssistantCardReceivedEvent) {
debugPrint("Card received: ${aiAssistantBaseEvent.cardId}");
final cardPayload = aiAssistantBaseEvent.getCard();
// Pass cardPayload to CometChatCardView renderer
} else if (aiAssistantBaseEvent is AIAssistantCardEndedEvent) {
debugPrint("Card generation ended: ${aiAssistantBaseEvent.cardId}");
}
}
}
```
</Tab>
</Tabs>

#### Event descriptions
- Run Start: A new run has begun for the users message.
- Run Start: A new run has begun for the user's message.
- Tool Call Start: The agent decided to invoke a tool.
- Tool Call Arguments: Arguments being passed to the tool.
- Tool Call End: Tool execution completed.
- Tool Call Result: Tool’s output is available.
- Tool Call Result: Tool's output is available.
- Card Start: The agent started generating a card. Contains `cardId` and `executionText` (a human-readable status like "Building your product card...").
- Card: The full card payload is available. Use `getCard()` to retrieve the raw card JSON and pass it to the renderer.
- Card End: The card generation flow is finalized.
- Text Message Start: The agent started composing a reply.
- Text Message Content: Streaming content chunks for progressive rendering.
- Text Message End: The agent reply is complete.
- Run Finished: The run is finalized; persisted messages will follow.

#### Card Streaming Event Classes

| Class | Properties |
| -- | -- |
| `AIAssistantCardStartedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `executionText` |
| `AIAssistantCardReceivedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `getCard()` → `Map<String, dynamic>?` |
| `AIAssistantCardEndedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId` |

### Agentic Messages

These events are received via the **`MessageListener`** after the run completes.
Expand DownExpand Up@@ -112,4 +140,113 @@ These events are received via the **`MessageListener`** after the run completes.
}
```
</Tab>
</Tabs>
</Tabs>

<Note>

Starting from SDK version **5.0.5**, AI assistant message content is delivered via `getElements()`. If the agent response contains only a card (no accompanying text), `getText()` will return an empty string — always prefer `getElements()` as the primary data source for rendering.

</Note>

### AIAssistantMessage Elements

A persisted `AIAssistantMessage` carries its content in two ways:

1. **`getText()`** — The flat content string (unchanged, legacy/fallback path).
2. **`getElements()`** — An ordered array of `AIAssistantElement` objects representing discrete content blocks (text and cards) in the order the agent produced them. **This is the default render source** — when present, walk the list left-to-right and render each block in order.

When `getElements()` returns `null` or is empty (older messages), fall back to `getText()`.

#### AIAssistantElement

Each element exposes two accessors:

| Method | Return Type | Description |
| -- | -- | -- |
| `getType()` | `String?` | The element's type: `"text"`, `"card"`, `"graph"`, etc. |
| `getData()` | `dynamic` | The element's raw body data. Shape depends on type — `String` for text, `Map<String, dynamic>` (with keys `card` and `cardId`) for card, raw JSON value for others. |

<Tabs>
<Tab title="Dart">
```dart
void handleAIAssistantMessage(AIAssistantMessage message) {
final elements = message.getElements();

if (elements != null && elements.isNotEmpty) {
// Preferred path: walk elements in order
for (final element in elements) {
switch (element.getType()) {
case 'text':
final textContent = element.getData() as String;
debugPrint("Text block: $textContent");
break;
case 'card':
final cardData = element.getData() as Map<String, dynamic>;
final cardPayload = cardData['card'] as Map<String, dynamic>;
final cardId = cardData['cardId'] as String;
debugPrint("Card block: $cardId");
// Pass cardPayload to CometChatCardView renderer
break;
default:
debugPrint("Unknown element type: ${element.getType()}");
break;
}
}
} else {
// Fallback: use getText() for older messages without elements
debugPrint("Message text: ${message.text}");
}
}
```
</Tab>
</Tabs>

## Card Messages (Developer Cards)

Developer card messages are rich, interactive messages (buttons, images, styled layouts) described as JSON and sent via the Platform API or Bubble Builder. The SDK only **receives** card messages — it does not send them.

A `CardMessage` arrives with `category: "card"` and is delivered on the `onCardMessageReceived` callback of the `MessageListener`.

### CardMessage Class

| Method | Return Type | Description |
| -- | -- | -- |
| `getCard()` | `Map<String, dynamic>?` | The raw card schema payload. Pass directly to the card renderer. |
| `getText()` | `String?` | Preview text for push notifications and conversation list. |
| `getFallbackText()` | `String?` | Fallback text from inside the card (`card.fallbackText`). Used for accessibility or when the renderer fails. |
| `getTags()` | `List<String>?` | Tags associated with this message. |

<Tabs>
<Tab title="Dart">
```dart
const listenerId = "unique_listener_id";

class CardMessageHandler with MessageListener {
// CometChat.addMessageListener(listenerId, this);

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received: ${cardMessage.id}");

// Get the raw card payload for the renderer
final cardPayload = cardMessage.getCard();
debugPrint("Card payload: $cardPayload");

// Get fallback text for previews
final fallback = cardMessage.getFallbackText();
debugPrint("Fallback: $fallback");

// Get preview text for conversation list
final previewText = cardMessage.getText();
debugPrint("Preview text: $previewText");
}
}
```
</Tab>
</Tabs>

<Note>

Card messages are **receive-only**. They are created and sent exclusively via the Platform (REST) API and Dashboard Bubble Builder. The SDK exposes the card payload raw via `getCard()` — an external renderer library (e.g., CometChatCardView) is responsible for drawing the card UI.

</Note>
18 changes: 12 additions & 6 deletions sdk/flutter/real-time-listeners.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,6 +152,7 @@ The `MessageListener` class provides you with live events related to messages. B
| `onMessageEdited(BaseMessage message)` | This method is triggered when a particular message has been edited in a user/group conversation. |
| `onMessageDeleted(BaseMessage message)` | This event is triggered when a particular message is deleted in a user/group conversation. |
| `onInteractiveMessageReceived(InteractiveMessage message)` | This event is triggered when an Interactive Message is received. |
| `onCardMessageReceived(CardMessage message)` | This event is triggered when a Card Message is received. |
| `onInteractionGoalCompleted(InteractionReceipt receipt)` | This event is triggered when an interaction Goal is achieved. |
| `onTransientMessageReceived(TransientMessage transientMessage)` | This event is triggered when a Transient Message is received. |
| `onMessageReactionAdded(ReactionEvent reactionEvent)` | This event is triggered when a reaction is added to a message in a user/group conversation. |
Expand DownExpand Up@@ -222,19 +223,24 @@ class Class_Name with MessageListener {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {

}

@Override
public void onTransientMessageReceived(TransientMessage transientMessage) {

@override
void onTransientMessageReceived(TransientMessage transientMessage) {

}

@Override
public void onMessageReactionAdded(ReactionEvent reactionEvent) {
@override
void onMessageReactionAdded(ReactionEvent reactionEvent) {

}

@Override
public void onMessageReactionRemoved(ReactionEvent reactionEvent) {
@override
void onMessageReactionRemoved(ReactionEvent reactionEvent) {

}

Expand Down
7 changes: 6 additions & 1 deletion sdk/flutter/receive-messages.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,6 +44,11 @@ onInteractiveMessageReceived(InteractiveMessage message) {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received successfully: $cardMessage");
}


}
```
Expand DownExpand Up@@ -227,7 +232,7 @@ messageRequest.fetchPrevious(onSuccess: (List<BaseMessage> list) {
<Note>
Base Message

The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.
The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `CardMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.

</Note>

Expand Down
9 changes: 1 addition & 8 deletions sdk/flutter/setup.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,16 +22,9 @@ Minimum Requirement

### Add the CometChat Dependency

### Cloudsmith

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
9 changes: 3 additions & 6 deletions sdk/flutter/upgrading-from-v4-guide.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,16 +7,13 @@ This guide helps you migrate your Flutter application from CometChat SDK v4 to v

## Installation

### Cloudsmith
### Add the CometChat Dependency

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:
Update your `pubspec.yaml` to the latest v5 SDK:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions calls/flutter/migration-guide-v5.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,9 +13,7 @@ Calls SDK v5 is a **drop-in replacement** for v4. All v4 APIs are preserved as d

```yaml
dependencies:
cometchat_calls_sdk:
hosted: https://dart.cloudsmith.io/cometchat/cometchat/
version: ^5.0.0
cometchat_calls_sdk: ^5.0.3
```

<Info>
Expand Down
151 changes: 144 additions & 7 deletions sdk/flutter/ai-agents.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ AI Agents enable intelligent, automated interactions within your application. Th

## Agent Run Lifecycle and Message Flow

This section explains how a users text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
This section explains how a user's text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
- A user sends a text message to an Agent.
- The platform starts a run and streams real-time events via the **`AIAssistantListener`**.
- After the run completes, persisted Agentic Messages arrive via the **`MessageListener`**.
Expand All@@ -26,16 +26,21 @@ Events are received via the **`onAIAssistantEventReceived`** method of the **`AI
- Tool Call Arguments
- Tool Call End
- Tool Call Result
3. One or more assistant reply streams:
3. Zero or more card generation cycles (repeats for each card produced):
- Card Start
- Card (full payload)
- Card End
4. One or more assistant reply streams:
- Text Message Start
- Text Message Content (multiple times; token/char streaming)
- Text Message End
4. Run Finished
5. Run Finished

Notes:
- `Run Start` and `Run Finished` are always emitted.
- `Tool Call` events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run.
- `Text Message` events are always emitted and carry the assistant’s reply incrementally.
- `Card` events appear only when the agent produces a card. The UI can show a loading state on `Card Start`, render the card on `Card` (payload), and finalize on `Card End`.
- `Text Message` events are always emitted and carry the assistant's reply incrementally.

<Tabs>
<Tab title="Dart">
Expand DownExpand Up@@ -63,23 +68,46 @@ class AIAssistantEventHandler with AIAssistantListener {
debugPrint(
"Received AI Event: ${aiAssistantBaseEvent.type} for Run ID: ${aiAssistantBaseEvent.id}",
);

// Handle card streaming events
if (aiAssistantBaseEvent is AIAssistantCardStartedEvent) {
debugPrint("Card generation started: ${aiAssistantBaseEvent.cardId}");
debugPrint("Execution text: ${aiAssistantBaseEvent.executionText}");
} else if (aiAssistantBaseEvent is AIAssistantCardReceivedEvent) {
debugPrint("Card received: ${aiAssistantBaseEvent.cardId}");
final cardPayload = aiAssistantBaseEvent.getCard();
// Pass cardPayload to CometChatCardView renderer
} else if (aiAssistantBaseEvent is AIAssistantCardEndedEvent) {
debugPrint("Card generation ended: ${aiAssistantBaseEvent.cardId}");
}
}
}
```
</Tab>
</Tabs>

#### Event descriptions
- Run Start: A new run has begun for the users message.
- Run Start: A new run has begun for the user's message.
- Tool Call Start: The agent decided to invoke a tool.
- Tool Call Arguments: Arguments being passed to the tool.
- Tool Call End: Tool execution completed.
- Tool Call Result: Tool’s output is available.
- Tool Call Result: Tool's output is available.
- Card Start: The agent started generating a card. Contains `cardId` and `executionText` (a human-readable status like "Building your product card...").
- Card: The full card payload is available. Use `getCard()` to retrieve the raw card JSON and pass it to the renderer.
- Card End: The card generation flow is finalized.
- Text Message Start: The agent started composing a reply.
- Text Message Content: Streaming content chunks for progressive rendering.
- Text Message End: The agent reply is complete.
- Run Finished: The run is finalized; persisted messages will follow.

#### Card Streaming Event Classes

| Class | Properties |
| -- | -- |
| `AIAssistantCardStartedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `executionText` |
| `AIAssistantCardReceivedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `getCard()` → `Map<String, dynamic>?` |
| `AIAssistantCardEndedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId` |

### Agentic Messages

These events are received via the **`MessageListener`** after the run completes.
Expand DownExpand Up@@ -112,4 +140,113 @@ These events are received via the **`MessageListener`** after the run completes.
}
```
</Tab>
</Tabs>
</Tabs>

<Note>

Starting from SDK version **5.0.5**, AI assistant message content is delivered via `getElements()`. If the agent response contains only a card (no accompanying text), `getText()` will return an empty string — always prefer `getElements()` as the primary data source for rendering.

</Note>

### AIAssistantMessage Elements

A persisted `AIAssistantMessage` carries its content in two ways:

1. **`getText()`** — The flat content string (unchanged, legacy/fallback path).
2. **`getElements()`** — An ordered array of `AIAssistantElement` objects representing discrete content blocks (text and cards) in the order the agent produced them. **This is the default render source** — when present, walk the list left-to-right and render each block in order.

When `getElements()` returns `null` or is empty (older messages), fall back to `getText()`.

#### AIAssistantElement

Each element exposes two accessors:

| Method | Return Type | Description |
| -- | -- | -- |
| `getType()` | `String?` | The element's type: `"text"`, `"card"`, `"graph"`, etc. |
| `getData()` | `dynamic` | The element's raw body data. Shape depends on type — `String` for text, `Map<String, dynamic>` (with keys `card` and `cardId`) for card, raw JSON value for others. |

<Tabs>
<Tab title="Dart">
```dart
void handleAIAssistantMessage(AIAssistantMessage message) {
final elements = message.getElements();

if (elements != null && elements.isNotEmpty) {
// Preferred path: walk elements in order
for (final element in elements) {
switch (element.getType()) {
case 'text':
final textContent = element.getData() as String;
debugPrint("Text block: $textContent");
break;
case 'card':
final cardData = element.getData() as Map<String, dynamic>;
final cardPayload = cardData['card'] as Map<String, dynamic>;
final cardId = cardData['cardId'] as String;
debugPrint("Card block: $cardId");
// Pass cardPayload to CometChatCardView renderer
break;
default:
debugPrint("Unknown element type: ${element.getType()}");
break;
}
}
} else {
// Fallback: use getText() for older messages without elements
debugPrint("Message text: ${message.text}");
}
}
```
</Tab>
</Tabs>

## Card Messages (Developer Cards)

Developer card messages are rich, interactive messages (buttons, images, styled layouts) described as JSON and sent via the Platform API or Bubble Builder. The SDK only **receives** card messages — it does not send them.

A `CardMessage` arrives with `category: "card"` and is delivered on the `onCardMessageReceived` callback of the `MessageListener`.

### CardMessage Class

| Method | Return Type | Description |
| -- | -- | -- |
| `getCard()` | `Map<String, dynamic>?` | The raw card schema payload. Pass directly to the card renderer. |
| `getText()` | `String?` | Preview text for push notifications and conversation list. |
| `getFallbackText()` | `String?` | Fallback text from inside the card (`card.fallbackText`). Used for accessibility or when the renderer fails. |
| `getTags()` | `List<String>?` | Tags associated with this message. |

<Tabs>
<Tab title="Dart">
```dart
const listenerId = "unique_listener_id";

class CardMessageHandler with MessageListener {
// CometChat.addMessageListener(listenerId, this);

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received: ${cardMessage.id}");

// Get the raw card payload for the renderer
final cardPayload = cardMessage.getCard();
debugPrint("Card payload: $cardPayload");

// Get fallback text for previews
final fallback = cardMessage.getFallbackText();
debugPrint("Fallback: $fallback");

// Get preview text for conversation list
final previewText = cardMessage.getText();
debugPrint("Preview text: $previewText");
}
}
```
</Tab>
</Tabs>

<Note>

Card messages are **receive-only**. They are created and sent exclusively via the Platform (REST) API and Dashboard Bubble Builder. The SDK exposes the card payload raw via `getCard()` — an external renderer library (e.g., CometChatCardView) is responsible for drawing the card UI.

</Note>
18 changes: 12 additions & 6 deletions sdk/flutter/real-time-listeners.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,6 +152,7 @@ The `MessageListener` class provides you with live events related to messages. B
| `onMessageEdited(BaseMessage message)` | This method is triggered when a particular message has been edited in a user/group conversation. |
| `onMessageDeleted(BaseMessage message)` | This event is triggered when a particular message is deleted in a user/group conversation. |
| `onInteractiveMessageReceived(InteractiveMessage message)` | This event is triggered when an Interactive Message is received. |
| `onCardMessageReceived(CardMessage message)` | This event is triggered when a Card Message is received. |
| `onInteractionGoalCompleted(InteractionReceipt receipt)` | This event is triggered when an interaction Goal is achieved. |
| `onTransientMessageReceived(TransientMessage transientMessage)` | This event is triggered when a Transient Message is received. |
| `onMessageReactionAdded(ReactionEvent reactionEvent)` | This event is triggered when a reaction is added to a message in a user/group conversation. |
Expand DownExpand Up@@ -222,19 +223,24 @@ class Class_Name with MessageListener {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {

}

@Override
public void onTransientMessageReceived(TransientMessage transientMessage) {

@override
void onTransientMessageReceived(TransientMessage transientMessage) {

}

@Override
public void onMessageReactionAdded(ReactionEvent reactionEvent) {
@override
void onMessageReactionAdded(ReactionEvent reactionEvent) {

}

@Override
public void onMessageReactionRemoved(ReactionEvent reactionEvent) {
@override
void onMessageReactionRemoved(ReactionEvent reactionEvent) {

}

Expand Down
7 changes: 6 additions & 1 deletion sdk/flutter/receive-messages.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,6 +44,11 @@ onInteractiveMessageReceived(InteractiveMessage message) {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received successfully: $cardMessage");
}


}
```
Expand DownExpand Up@@ -227,7 +232,7 @@ messageRequest.fetchPrevious(onSuccess: (List<BaseMessage> list) {
<Note>
Base Message

The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.
The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `CardMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.

</Note>

Expand Down
9 changes: 1 addition & 8 deletions sdk/flutter/setup.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,16 +22,9 @@ Minimum Requirement

### Add the CometChat Dependency

### Cloudsmith

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
9 changes: 3 additions & 6 deletions sdk/flutter/upgrading-from-v4-guide.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,16 +7,13 @@ This guide helps you migrate your Flutter application from CometChat SDK v4 to v

## Installation

### Cloudsmith
### Add the CometChat Dependency

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:
Update your `pubspec.yaml` to the latest v5 SDK:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions calls/flutter/migration-guide-v5.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -13,9 +13,7 @@ Calls SDK v5 is a **drop-in replacement** for v4. All v4 APIs are preserved as d

```yaml
dependencies:
cometchat_calls_sdk:
hosted: https://dart.cloudsmith.io/cometchat/cometchat/
version: ^5.0.0
cometchat_calls_sdk: ^5.0.3
```

<Info>
Expand Down
151 changes: 144 additions & 7 deletions sdk/flutter/ai-agents.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ AI Agents enable intelligent, automated interactions within your application. Th

## Agent Run Lifecycle and Message Flow

This section explains how a users text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
This section explains how a user's text message to an Agent becomes a structured "run" which emits real-time events and then produces agentic messages for historical retrieval.
- A user sends a text message to an Agent.
- The platform starts a run and streams real-time events via the **`AIAssistantListener`**.
- After the run completes, persisted Agentic Messages arrive via the **`MessageListener`**.
Expand All@@ -26,16 +26,21 @@ Events are received via the **`onAIAssistantEventReceived`** method of the **`AI
- Tool Call Arguments
- Tool Call End
- Tool Call Result
3. One or more assistant reply streams:
3. Zero or more card generation cycles (repeats for each card produced):
- Card Start
- Card (full payload)
- Card End
4. One or more assistant reply streams:
- Text Message Start
- Text Message Content (multiple times; token/char streaming)
- Text Message End
4. Run Finished
5. Run Finished

Notes:
- `Run Start` and `Run Finished` are always emitted.
- `Tool Call` events appear only when a backend or frontend tool is invoked. There can be multiple tool calls in a single run.
- `Text Message` events are always emitted and carry the assistant’s reply incrementally.
- `Card` events appear only when the agent produces a card. The UI can show a loading state on `Card Start`, render the card on `Card` (payload), and finalize on `Card End`.
- `Text Message` events are always emitted and carry the assistant's reply incrementally.

<Tabs>
<Tab title="Dart">
Expand DownExpand Up@@ -63,23 +68,46 @@ class AIAssistantEventHandler with AIAssistantListener {
debugPrint(
"Received AI Event: ${aiAssistantBaseEvent.type} for Run ID: ${aiAssistantBaseEvent.id}",
);

// Handle card streaming events
if (aiAssistantBaseEvent is AIAssistantCardStartedEvent) {
debugPrint("Card generation started: ${aiAssistantBaseEvent.cardId}");
debugPrint("Execution text: ${aiAssistantBaseEvent.executionText}");
} else if (aiAssistantBaseEvent is AIAssistantCardReceivedEvent) {
debugPrint("Card received: ${aiAssistantBaseEvent.cardId}");
final cardPayload = aiAssistantBaseEvent.getCard();
// Pass cardPayload to CometChatCardView renderer
} else if (aiAssistantBaseEvent is AIAssistantCardEndedEvent) {
debugPrint("Card generation ended: ${aiAssistantBaseEvent.cardId}");
}
}
}
```
</Tab>
</Tabs>

#### Event descriptions
- Run Start: A new run has begun for the users message.
- Run Start: A new run has begun for the user's message.
- Tool Call Start: The agent decided to invoke a tool.
- Tool Call Arguments: Arguments being passed to the tool.
- Tool Call End: Tool execution completed.
- Tool Call Result: Tool’s output is available.
- Tool Call Result: Tool's output is available.
- Card Start: The agent started generating a card. Contains `cardId` and `executionText` (a human-readable status like "Building your product card...").
- Card: The full card payload is available. Use `getCard()` to retrieve the raw card JSON and pass it to the renderer.
- Card End: The card generation flow is finalized.
- Text Message Start: The agent started composing a reply.
- Text Message Content: Streaming content chunks for progressive rendering.
- Text Message End: The agent reply is complete.
- Run Finished: The run is finalized; persisted messages will follow.

#### Card Streaming Event Classes

| Class | Properties |
| -- | -- |
| `AIAssistantCardStartedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `executionText` |
| `AIAssistantCardReceivedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId`, `getCard()` → `Map<String, dynamic>?` |
| `AIAssistantCardEndedEvent` | `runId`, `threadId`, `streamMessageId`, `cardId` |

### Agentic Messages

These events are received via the **`MessageListener`** after the run completes.
Expand DownExpand Up@@ -112,4 +140,113 @@ These events are received via the **`MessageListener`** after the run completes.
}
```
</Tab>
</Tabs>
</Tabs>

<Note>

Starting from SDK version **5.0.5**, AI assistant message content is delivered via `getElements()`. If the agent response contains only a card (no accompanying text), `getText()` will return an empty string — always prefer `getElements()` as the primary data source for rendering.

</Note>

### AIAssistantMessage Elements

A persisted `AIAssistantMessage` carries its content in two ways:

1. **`getText()`** — The flat content string (unchanged, legacy/fallback path).
2. **`getElements()`** — An ordered array of `AIAssistantElement` objects representing discrete content blocks (text and cards) in the order the agent produced them. **This is the default render source** — when present, walk the list left-to-right and render each block in order.

When `getElements()` returns `null` or is empty (older messages), fall back to `getText()`.

#### AIAssistantElement

Each element exposes two accessors:

| Method | Return Type | Description |
| -- | -- | -- |
| `getType()` | `String?` | The element's type: `"text"`, `"card"`, `"graph"`, etc. |
| `getData()` | `dynamic` | The element's raw body data. Shape depends on type — `String` for text, `Map<String, dynamic>` (with keys `card` and `cardId`) for card, raw JSON value for others. |

<Tabs>
<Tab title="Dart">
```dart
void handleAIAssistantMessage(AIAssistantMessage message) {
final elements = message.getElements();

if (elements != null && elements.isNotEmpty) {
// Preferred path: walk elements in order
for (final element in elements) {
switch (element.getType()) {
case 'text':
final textContent = element.getData() as String;
debugPrint("Text block: $textContent");
break;
case 'card':
final cardData = element.getData() as Map<String, dynamic>;
final cardPayload = cardData['card'] as Map<String, dynamic>;
final cardId = cardData['cardId'] as String;
debugPrint("Card block: $cardId");
// Pass cardPayload to CometChatCardView renderer
break;
default:
debugPrint("Unknown element type: ${element.getType()}");
break;
}
}
} else {
// Fallback: use getText() for older messages without elements
debugPrint("Message text: ${message.text}");
}
}
```
</Tab>
</Tabs>

## Card Messages (Developer Cards)

Developer card messages are rich, interactive messages (buttons, images, styled layouts) described as JSON and sent via the Platform API or Bubble Builder. The SDK only **receives** card messages — it does not send them.

A `CardMessage` arrives with `category: "card"` and is delivered on the `onCardMessageReceived` callback of the `MessageListener`.

### CardMessage Class

| Method | Return Type | Description |
| -- | -- | -- |
| `getCard()` | `Map<String, dynamic>?` | The raw card schema payload. Pass directly to the card renderer. |
| `getText()` | `String?` | Preview text for push notifications and conversation list. |
| `getFallbackText()` | `String?` | Fallback text from inside the card (`card.fallbackText`). Used for accessibility or when the renderer fails. |
| `getTags()` | `List<String>?` | Tags associated with this message. |

<Tabs>
<Tab title="Dart">
```dart
const listenerId = "unique_listener_id";

class CardMessageHandler with MessageListener {
// CometChat.addMessageListener(listenerId, this);

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received: ${cardMessage.id}");

// Get the raw card payload for the renderer
final cardPayload = cardMessage.getCard();
debugPrint("Card payload: $cardPayload");

// Get fallback text for previews
final fallback = cardMessage.getFallbackText();
debugPrint("Fallback: $fallback");

// Get preview text for conversation list
final previewText = cardMessage.getText();
debugPrint("Preview text: $previewText");
}
}
```
</Tab>
</Tabs>

<Note>

Card messages are **receive-only**. They are created and sent exclusively via the Platform (REST) API and Dashboard Bubble Builder. The SDK exposes the card payload raw via `getCard()` — an external renderer library (e.g., CometChatCardView) is responsible for drawing the card UI.

</Note>
18 changes: 12 additions & 6 deletions sdk/flutter/real-time-listeners.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,6 +152,7 @@ The `MessageListener` class provides you with live events related to messages. B
| `onMessageEdited(BaseMessage message)` | This method is triggered when a particular message has been edited in a user/group conversation. |
| `onMessageDeleted(BaseMessage message)` | This event is triggered when a particular message is deleted in a user/group conversation. |
| `onInteractiveMessageReceived(InteractiveMessage message)` | This event is triggered when an Interactive Message is received. |
| `onCardMessageReceived(CardMessage message)` | This event is triggered when a Card Message is received. |
| `onInteractionGoalCompleted(InteractionReceipt receipt)` | This event is triggered when an interaction Goal is achieved. |
| `onTransientMessageReceived(TransientMessage transientMessage)` | This event is triggered when a Transient Message is received. |
| `onMessageReactionAdded(ReactionEvent reactionEvent)` | This event is triggered when a reaction is added to a message in a user/group conversation. |
Expand DownExpand Up@@ -222,19 +223,24 @@ class Class_Name with MessageListener {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {

}

@Override
public void onTransientMessageReceived(TransientMessage transientMessage) {

@override
void onTransientMessageReceived(TransientMessage transientMessage) {

}

@Override
public void onMessageReactionAdded(ReactionEvent reactionEvent) {
@override
void onMessageReactionAdded(ReactionEvent reactionEvent) {

}

@Override
public void onMessageReactionRemoved(ReactionEvent reactionEvent) {
@override
void onMessageReactionRemoved(ReactionEvent reactionEvent) {

}

Expand Down
7 changes: 6 additions & 1 deletion sdk/flutter/receive-messages.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -44,6 +44,11 @@ onInteractiveMessageReceived(InteractiveMessage message) {

}

@override
void onCardMessageReceived(CardMessage cardMessage) {
debugPrint("Card message received successfully: $cardMessage");
}


}
```
Expand DownExpand Up@@ -227,7 +232,7 @@ messageRequest.fetchPrevious(onSuccess: (List<BaseMessage> list) {
<Note>
Base Message

The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.
The list of messages received is in the form of objects of `BaseMessage` class. A `BaseMessage` can either be an object of the `TextMessage`, `MediaMessage`, `CustomMessage`, `CardMessage`, `Action` or `Call` class. You can use the `is` operator to check the type of object.

</Note>

Expand Down
9 changes: 1 addition & 8 deletions sdk/flutter/setup.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,16 +22,9 @@ Minimum Requirement

### Add the CometChat Dependency

### Cloudsmith

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down
9 changes: 3 additions & 6 deletions sdk/flutter/upgrading-from-v4-guide.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,16 +7,13 @@ This guide helps you migrate your Flutter application from CometChat SDK v4 to v

## Installation

### Cloudsmith
### Add the CometChat Dependency

Add the Cloudsmith hosted repository and dependency to your `pubspec.yaml`:
Update your `pubspec.yaml` to the latest v5 SDK:

```yaml
dependencies:
cometchat_sdk:
hosted:
url: https://dart.cloudsmith.io/cometchat/cometchat/
version: 5.0.0
cometchat_sdk: ^5.0.5
```

Then run:
Expand Down