Skip to content
Open
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
137 changes: 86 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ If you are using [Director](https://github.com/video-db/Director), make sure it'

![Structure](https://github.com/user-attachments/assets/3dd8feaa-483a-4f28-bfd2-e8bc23dfffea)



The `ChatInterface` component is composed of two primary sub-components:

- `<ChatMessageContainer/>`
Expand Down Expand Up @@ -100,7 +98,6 @@ _This package includes other UI components that enhance the chat experience_

![image (1)](https://github.com/user-attachments/assets/f4524358-882b-4563-9d0b-b5c864d46dd4)


### `<Sidebar/>`

This component facilitates navigation between different sessions and collections. It can be used to switch between various conversations or collections.
Expand All @@ -117,7 +114,7 @@ This component displays the default screen when there are no conversations in th

These components are used to display collection and video views, helping users better understand the context of the conversation.

# 🧑‍💻 Concepts
# 🧑‍💻 Concepts

### 🔧 Message Handlers

Expand All @@ -127,44 +124,41 @@ Message handlers are UI components that are used to render the content of a mess

These are the default message handlers that are currently supported by this package:

**Text**:
---
`contentType`: `text`
_Renders the text/markdown of the message_
## **Text**:

`contentType`: `text`
_Renders the text/markdown of the message_

![TextResponse](https://github.com/user-attachments/assets/6e7cb7a8-0f5a-473d-8b46-a104da92922d)

[View implementation](https://github.com/video-db/videodb-chat/blob/main/src/components/message-handlers/TextResponse.vue)
[View implementation](https://github.com/video-db/videodb-chat/blob/main/src/components/message-handlers/TextResponse.vue)

**Video**:
---
`contentType`: `video`
_Renders the video(streaming urls) of the message_

![chatvideo](https://github.com/user-attachments/assets/e3b07ad3-5258-42c0-9276-49321d840e95)
## **Video**:

`contentType`: `video`
_Renders the video(streaming urls) of the message_

[View implementation](https://github.com/video-db/videodb-chat/blob/main/src/components/message-handlers/ChatVideo.vue)
![chatvideo](https://github.com/user-attachments/assets/e3b07ad3-5258-42c0-9276-49321d840e95)

[View implementation](https://github.com/video-db/videodb-chat/blob/main/src/components/message-handlers/ChatVideo.vue)

## **Image**:

`contentType`: `image`
_Renders the image of the message_

**Image**:
---
`contentType`: `image`
_Renders the image of the message_

![ImageHandler](https://github.com/user-attachments/assets/afc02ffb-2704-43ab-8f62-c66e2a0c2178)

[View implementation](https://github.com/video-db/videodb-chat/blob/main/src/components/message-handlers/ImageHandler.vue)

[View implementation](https://github.com/video-db/videodb-chat/blob/main/src/components/message-handlers/ImageHandler.vue)
## **Search Results**:

**Search Results**:
---
`contentType`: `search_results`
_Renders the search results of the video_

![ChatSearchResults](https://github.com/user-attachments/assets/2192a1c0-def2-4472-9c08-14e08d66f6da)
`contentType`: `search_results`
_Renders the search results of the video_

[View implementation](https://github.com/video-db/videodb-chat/blob/main/src/components/message-handlers/ChatSearchResults.vue)
![ChatSearchResults](https://github.com/user-attachments/assets/2192a1c0-def2-4472-9c08-14e08d66f6da)

[View implementation](https://github.com/video-db/videodb-chat/blob/main/src/components/message-handlers/ChatSearchResults.vue)

### 🔧 Custom Message Handler

Expand All @@ -182,15 +176,51 @@ The `ChatInterface` component exposes a method `registerMessageHandler` accessib

**The handler component will receive the following props:**

- `content`: _Object_
The content object of matched content type.
- `content` (Object): The matched content object for this type
- `isLastConv` (Boolean): Whether this message is in the last conversation block
- `isUser` (Boolean): Whether the message is authored by the user
- `searchTerm` (String): Current chat search term (if any)
- `convId` (String): Conversation ID for this message
- `msgId` (String): Message ID for this message
- `callApi` (Function): Helper for calling backend endpoints bound to `httpUrl`

#### Register via prop: customMessageHandlers

You can also declare handlers declaratively using the `customMessageHandlers` prop on `ChatInterface`.

- `isLastConv`: _Boolean_
Indicates if the message is the last conversation.
Schema for each handler item:

- `type`: String → matched against `content.type`
- `component`: Vue component → rendered when the type matches; receives the same props as built-in handlers

Example:

```html
<script setup>
import { ChatInterface } from "@videodb/chat-vue";
import MyCustomHandler from "./MyCustomHandler.vue";

const socketUrl = "http://127.0.0.1:8000/chat";
const httpUrl = "http://127.0.0.1:8000";

const customMessageHandlers = [
{ type: "chart", component: MyCustomHandler },
// add more handlers here
];
</script>

<template>
<ChatInterface
:chat-hook-config="{ socketUrl, httpUrl }"
:custom-message-handlers="customMessageHandlers"
/>
</template>
```

**Checkout these resources to understand better:**

- [View default message handlers Implementation](https://github.com/video-db/videodb-chat/blob/main/src/components/message-handlers/)

### 🔧 Custom ChatHook

---
Expand All @@ -202,8 +232,10 @@ The Custom ChatHook is an advanced feature of this package that allows you to:
- Control conversation state and manage side effects.

To use a custom hook, pass a function to the `customChatHook` prop. This function should return an object with the following properties:

- `session`: _Object_ (reactive)
Session object.

```js
{
isConnected: false,
Expand Down Expand Up @@ -255,21 +287,25 @@ To use a custom hook, pass a function to the `customChatHook` prop. This functio

The ChatInterface component accepts the following props:

- `chatInputPlaceholder`:
- `chatInputPlaceholder`:

- default: "Ask Speilberg"
- Customizes the placeholder text for the chat input field.

- `size(string)`:
- default: full
- `size(string)`:

- default: full
- Determines the size of the chat interface. Options are `full` or `embedded`.
Full takes up the entire width of the screen.
Embedded takes up space of the parent container.
Full takes up the entire width of the screen.
Embedded takes up space of the parent container.

- `customChatHook(Function)`:

- `customChatHook(Function)`:
- default: [videoDBChatHook](https://github.com/video-db/videodb-chat/blob/main/src/components/hooks/useVideoDBAgent.js)
- Allows for a custom hook to handle chat functionality.

- `chatHookConfig(object)`:
- `chatHookConfig(object)`:

- Configures the chat hook. For the default chat hook, it includes:
- default
```js
Expand All @@ -278,8 +314,9 @@ The ChatInterface component accepts the following props:
debug: false,
```

- `sidebarConfig(string)`:
- Customizes the sidebar.
- `sidebarConfig(string)`:

- Customizes the sidebar.
- default:
```js
{
Expand All @@ -293,25 +330,23 @@ The ChatInterface component accepts the following props:
}
```

- `defaultScreenConfig(Object)`:
- default: a list of action cards with default queries
- `defaultScreenConfig(Object)`:
- default: a list of action cards with default queries
- Customizes the default screen.

### Exposed Variables

#### State Variables

- `conversations`: Object
- `conversations`: Object

#### Methods

- `addMessage(message)`:
Adds a message to the conversation.
- `registerMessageHandler(contentType, handler)`:
- `addMessage(message)`:
Adds a message to the conversation.
- `registerMessageHandler(contentType, handler)`:
Registers a custom message handler for a specific content type.



[npm-shield]: https://img.shields.io/npm/v/@videodb/chat-vue?style=for-the-badge
[npm-url]: https://www.npmjs.com/package/@videodb/chat-vue
[discord-shield]: https://img.shields.io/badge/dynamic/json?style=for-the-badge&url=https://discord.com/api/invites/py9P639jGz?with_counts=true&query=$.approximate_member_count&logo=discord&logoColor=blue&color=green&label=discord
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"lint": "eslint 'src/**/*.{ts,vue}'",
"test": "vitest",
"test-ci": "vitest --run",
"prepublishOnly": "npm run build"
"prepublishOnly": "npm run build",
"prepare": "npm run build"
},
"peerDependencies": {
"vue": "^3.0.4"
Expand Down
15 changes: 15 additions & 0 deletions src/components/chat/ChatInterface.vue
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@
:key="key"
:conversation="conversations[key]"
:search-term="chatInput"
:call-api="callApi"
:add-message="addMessage"
:is-static-page="isStaticPage"
:is-last-conv="i === Object.keys(conversations).length - 1"
class="vdb-c-px-30 vdb-c-transition-all vdb-c-duration-300 vdb-c-ease-in-out md:vdb-c-px-60"
Expand Down Expand Up @@ -424,6 +426,10 @@ const props = defineProps({
],
}),
},
customMessageHandlers: {
type: Array,
default: () => [],
},
});
const emit = defineEmits([]);

Expand Down Expand Up @@ -466,6 +472,7 @@ const {
deleteVideo,
deleteAudio,
deleteImage,
callApi,
} = useChatHook(props.chatHookConfig);

const {
Expand Down Expand Up @@ -518,6 +525,14 @@ registerMessageHandler("text", TextResponse);
registerMessageHandler("search_results", ChatSearchResults);
registerMessageHandler("image", ImageHandler);

if (Array.isArray(props.customMessageHandlers)) {
for (const handler of props.customMessageHandlers) {
if (handler && typeof handler.type === "string" && handler.component) {
registerMessageHandler(handler.type, handler.component);
}
}
}

const isStaticPage = ref(false);
const chatWindowRef = ref(null);
const headerRef = ref(null);
Expand Down
10 changes: 10 additions & 0 deletions src/components/chat/ChatMessage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
:search-term="searchTerm"
:conv-id="message.conv_id"
:msg-id="message.msg_id"
:call-api="callApi"
:add-message="addMessage"
/>
</div>
</div>
Expand All @@ -69,6 +71,14 @@ const props = defineProps({
type: Object,
default: () => ({}),
},
callApi: {
type: Function,
default: null,
},
addMessage: {
type: Function,
default: null,
},
isStaticPage: {
type: Boolean,
default: false,
Expand Down
14 changes: 11 additions & 3 deletions src/components/chat/ChatMessageContainer.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<template>
<div
class="vdb-c-relative vdb-c-h-auto vdb-c-w-full"
>
<div class="vdb-c-relative vdb-c-h-auto vdb-c-w-full">
<div
v-for="(message, i) in messages"
:key="message.msg_id"
Expand All @@ -15,6 +13,8 @@
:current-index="i"
:message-loading="messageLoading"
:search-term="searchTerm"
:call-api="callApi"
:add-message="addMessage"
/>
</div>
</div>
Expand All @@ -29,6 +29,14 @@ const props = defineProps({
type: Object,
default: () => ({}),
},
callApi: {
type: Function,
default: null,
},
addMessage: {
type: Function,
default: null,
},
isStaticPage: {
type: Boolean,
default: false,
Expand Down
Loading