Skip to content

Store API

The chat store manages all chat state and provides methods for interaction. It's built with Pinia and provides reactive state management.

Import

typescript
import { useChatStore } from '@sprout_ai_labs/sidekick'

Usage

The useChatStore() function accepts optional configuration options. When used within components, it automatically receives the plugin options via Vue's inject system. For standalone usage, you can pass options directly:

typescript
// Within a component (automatically gets plugin options)
import { inject } from 'vue'
import { useChatStore } from '@sprout_ai_labs/sidekick'
import type { SidekickChatOptions } from '@sprout_ai_labs/sidekick'

const pluginOptions = inject<SidekickChatOptions>('sidekickChatOptions')
const chatStore = useChatStore(pluginOptions)

// Standalone usage (must provide required options)
const chatStore = useChatStore({
  mode: 'PROD', // Required
  appName: 'My Application', // Required
  baseUrl: 'https://custom-backend.com', // Optional
})

REQUIRED OPTIONS

When using the store standalone (outside of plugin installation), you must provide the required options:

  • mode: Backend environment ('QA' or 'PROD')
  • appName: Application name (for analytics tracking)

These are automatically provided when the store is used within components that have the plugin installed.

Note: The store uses the provided options to determine which backend endpoint to use (based on mode or baseUrl configuration) and tracks analytics with the specified appName.

State

messages

  • Type: Ref<ChatMessage[]>
  • Description: Array of all chat messages
  • Reactive: Yes
typescript
const messages = chatStore.messages
// or
const messages = computed(() => chatStore.messages)

isTyping

  • Type: Ref<boolean>
  • Description: Indicates if the bot is currently typing
  • Reactive: Yes

isConnected

  • Type: Ref<boolean>
  • Description: Indicates if the chat is connected
  • Reactive: Yes

token

  • Type: Ref<string | null>
  • Description: Authentication token
  • Reactive: Yes

isOpen

  • Type: Ref<boolean>
  • Description: Indicates if the chat widget is open (for SidekickChatPlugin)
  • Reactive: Yes

Getters

messageCount

  • Type: ComputedRef<number>
  • Description: Total number of messages
  • Returns: Number of messages in the chat
typescript
const count = chatStore.messageCount

lastMessage

  • Type: ComputedRef<ChatMessage | undefined>
  • Description: The most recent message
  • Returns: Last message object or undefined if no messages
typescript
const lastMsg = chatStore.lastMessage

isAuthenticated

  • Type: ComputedRef<boolean>
  • Description: Whether user is authenticated (has a valid token)
  • Returns: True if token exists
typescript
const isAuth = chatStore.isAuthenticated

Actions

Authentication

setToken(newToken: string)

Sets the authentication token and marks the connection as active.

typescript
chatStore.setToken('your-auth-token-here')

Parameters:

  • newToken (string): The authentication token

Side Effects:

  • Sets isConnected to true

clearToken()

Clears the authentication token and disconnects.

typescript
chatStore.clearToken()

Side Effects:

  • Sets isConnected to false
  • Sets token to null

Message Management

addMessage(text: string, sender?: 'user' | 'bot')

Adds a new message to the chat.

typescript
// Add user message
chatStore.addMessage('Hello!', 'user')

// Add bot message
chatStore.addMessage('Hi there!', 'bot')

// Default is 'user'
chatStore.addMessage('Default user message')

Parameters:

  • text (string): The message text
  • sender ('user' | 'bot', optional): Message sender, defaults to 'user'

Returns: void

clearMessages()

Removes all messages from the chat locally.

typescript
chatStore.clearMessages()

clearSession()

Clears the chat session both locally and on the server. This will call the clear_chat API endpoint and then clear local messages.

typescript
try {
  await chatStore.clearSession()
} catch (error) {
  console.error('Failed to clear session:', error)
  // Local messages are still cleared even if API call fails
}

Returns: Promise<void>

Throws: Error if not authenticated or API call fails

Behavior:

  1. Calls the clear_chat API endpoint with user credentials
  2. Clears local messages after successful API call
  3. If API call fails, still clears local messages as fallback

sendMessage(text: string)

Sends a user message and triggers a bot response.

typescript
try {
  await chatStore.sendMessage('How can you help me?')
} catch (error) {
  console.error('Failed to send message:', error)
}

Parameters:

  • text (string): The message text to send

Returns: Promise<void>

Throws: Error if not authenticated

Behavior:

  1. Adds user message
  2. Sets isTyping to true
  3. Simulates API delay (1-2 seconds)
  4. Sets isTyping to false
  5. Adds bot response message

Chat State Management

setTyping(typing: boolean)

Sets the typing indicator state.

typescript
chatStore.setTyping(true) // Show typing indicator
chatStore.setTyping(false) // Hide typing indicator

toggleChat()

Toggles the chat widget open/closed state.

typescript
chatStore.toggleChat()

openChat()

Opens the chat widget.

typescript
chatStore.openChat()

closeChat()

Closes the chat widget.

typescript
chatStore.closeChat()

Types

SidekickChatOptions

typescript
interface SidekickChatOptions {
  mode: 'QA' | 'PROD' | 'qa' | 'prod' // Required
  appName: string // Required
  skipDesignSystem?: boolean // Optional
  baseUrl?: string // Optional
  deviceSource?: 'mobile' | 'web' // Optional
}

ChatMessage

typescript
interface ChatMessage {
  id: string
  text: string
  sender: 'user' | 'bot' | 'ticket'
  timestamp: Date
  isStreaming?: boolean
  thoughtSteps?: ThoughtStep[]
  thinkingDuration?: number
  isError?: boolean
  errorDetails?: ErrorDetails
  feedback?: Feedback
  analyticsId?: string
  redactedText?: string
  kbSources?: KBSource[]
}

ChatState

typescript
interface ChatState {
  messages: ChatMessage[]
  isTyping: boolean
  isConnected: boolean
  token: string | null
  isOpen: boolean
  user: AuthUser | null
  currentStreamingMessage: ChatMessage | null
}

Usage Examples

Basic Chat Implementation

vue
<script setup lang="ts">
import { computed, ref } from 'vue'
import { useChatStore } from '@sprout_ai_labs/sidekick'

const chatStore = useChatStore()
const newMessage = ref('')

// Computed properties
const messages = computed(() => chatStore.messages)
const isTyping = computed(() => chatStore.isTyping)
const isAuthenticated = computed(() => chatStore.isAuthenticated)

// Methods
async function sendMessage() {
  if (!newMessage.value.trim()) return

  try {
    await chatStore.sendMessage(newMessage.value)
    newMessage.value = ''
  } catch (error) {
    console.error('Send error:', error)
  }
}

function authenticate() {
  const token = 'mock-token-' + Date.now()
  chatStore.setToken(token)
}
</script>

Watching State Changes

typescript
import { watch } from 'vue'
import { useChatStore } from '@sprout_ai_labs/sidekick'

const chatStore = useChatStore()

// Watch for new messages
watch(
  () => chatStore.messages,
  (newMessages, oldMessages) => {
    if (newMessages.length > oldMessages.length) {
      console.log('New message received')
    }
  },
  { deep: true },
)

// Watch authentication state
watch(
  () => chatStore.isAuthenticated,
  (isAuth) => {
    if (isAuth) {
      console.log('User authenticated')
    } else {
      console.log('User logged out')
    }
  },
)

Error Handling

typescript
async function handleSendMessage(text: string) {
  try {
    await chatStore.sendMessage(text)
  } catch (error) {
    if (error.message === 'Not authenticated') {
      // Redirect to authentication
      showAuthModal()
    } else {
      // Handle other errors
      showErrorMessage('Failed to send message')
    }
  }
}

Released under the MIT License.