Skip to content

Quick Reference

Installation

bash
npm install @sprout_ai_labs/sidekick

Import Statements

Unified Components (with store)

typescript
import { createApp } from 'vue'
import SproutSidekick from '@sprout_ai_labs/sidekick'
import '@sprout_ai_labs/sidekick/dist/sprout-sidekick.css'

// Install plugin
app.use(SproutSidekick, {
  mode: 'PROD',
  appName: 'My App',
})

// Use store
import { useChatStore } from '@sprout_ai_labs/sidekick'
const chatStore = useChatStore()

Standalone Components (no store)

typescript
import {
  SidekickMessages,
  SidekickChatInput,
  SidekickCollapsibleThought,
  SidekickCollapsibleThoughtStreaming,
  SidekickLoader,
  SidekickLogo,
  SidekickChatSources,
} from '@sprout_ai_labs/sidekick'

// CSS
import '@sprout_ai_labs/sidekick/dist/sprout-sidekick.css'

Types

typescript
import type {
  ChatMessage,
  ChatState,
  KBSource,
  SidekickChatOptions,
} from '@sprout_ai_labs/sidekick'

Component Quick Reference

SidekickMessages

vue
<SidekickMessages
  :messages="messages"
  :is-typing="false"
  :current-thoughts="[]"
  :current-chunked-message="''"
  :streaming-animating="false"
/>

Props:

  • messages: ChatMessage[] - Array of messages
  • isTyping: boolean - Show typing indicator
  • currentThoughts: ThoughtStep[] - Live thoughts
  • currentChunkedMessage: string - Streaming message
  • streamingAnimating: boolean - Enable shimmer

SidekickChatInput

vue
<SidekickChatInput
  placeholder="Ask me anything..."
  :placeholders="['Question 1', 'Question 2']"
  :disabled="false"
  :show-clear-button="true"
  :auto-focus="false"
  @submit="handleSubmit"
  @input="handleInput"
  @clear="handleClear"
/>

Props:

  • placeholder: string - Default placeholder
  • placeholders: string[] - Cycling placeholders
  • disabled: boolean - Disable input
  • showClearButton: boolean - Show clear button
  • maxHeight: string - Max height (default: '120px')
  • minHeight: string - Min height (default: '42px')
  • autoFocus: boolean - Auto-focus on mount

Events:

  • @submit: (message: string) => void
  • @input: (value: string) => void
  • @clear: () => void

SidekickCollapsibleThought

vue
<SidekickCollapsibleThought :steps="thoughtSteps" :duration="5" />

Props:

  • steps: ThinkingStep[] - Array of thought steps
  • duration: number - Duration in seconds (optional)

Step Interface:

typescript
interface ThinkingStep {
  text: string // Step message
  completed: boolean // Should be true for completed
  event?: string // 'tool_call', 'observation', 'process', etc.
  agent_name?: string
  tool_details?: Record<string, unknown>
}

SidekickCollapsibleThoughtStreaming

vue
<SidekickCollapsibleThoughtStreaming :steps="liveThoughts" :duration="0" />

Props:

  • steps: ThinkingStep[] - Array of thought steps
  • duration: number - Duration when completed

Step Interface:

typescript
interface ThinkingStep {
  message: string // Note: 'message' not 'text'
  completed: boolean // Last step should be false
  event?: string
  agent_name?: string
  tool_details?: Record<string, unknown>
}

Common Types

ChatMessage

typescript
interface ChatMessage {
  id: string
  sender: 'user' | 'bot' | 'ticket'
  text: string
  isError?: boolean
  thoughtSteps?: ThoughtStep[]
  thinkingDuration?: number
  kbSources?: KBSource[]
  analyticsId?: string
}

ThoughtStep (Completed)

typescript
interface ThoughtStep {
  text: string // For SidekickCollapsibleThought
  completed: boolean
  event?: string
  agent_name?: string
  tool_details?: Record<string, unknown>
}

ThoughtStep (Streaming)

typescript
interface ThoughtStep {
  message: string // For SidekickCollapsibleThoughtStreaming
  completed: boolean
  event?: string
  agent_name?: string
  tool_details?: Record<string, unknown>
}

KBSource

typescript
interface KBSource {
  id: string
  title: string
  url?: string
  snippet?: string
}

Event Types

Common event types for thought steps:

  • tool_call - Function/tool invocations
  • observation - Search results, observations
  • process - Processing, thinking
  • route_to - Routing to agents
  • start - Starting actions

Complete Example

vue
<template>
  <div class="chat-container">
    <!-- Messages -->
    <div class="messages-area">
      <SidekickMessages
        :messages="messages"
        :is-typing="isTyping"
        :current-thoughts="currentThoughts"
        :current-chunked-message="currentChunkedMessage"
        :streaming-animating="streamingAnimating"
      />
    </div>

    <!-- Input -->
    <div class="input-area">
      <SidekickChatInput
        placeholder="Ask me anything..."
        :disabled="isLoading"
        @submit="handleSubmit"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { SidekickMessages, SidekickChatInput, type ChatMessage } from '@sprout_ai_labs/sidekick'

const messages = ref<ChatMessage[]>([])
const isTyping = ref(false)
const currentThoughts = ref([])
const currentChunkedMessage = ref('')
const streamingAnimating = ref(false)
const isLoading = ref(false)

async function handleSubmit(message: string) {
  // Add user message
  messages.value.push({
    id: Date.now().toString(),
    sender: 'user',
    text: message,
  })

  // Start streaming
  isTyping.value = true
  streamingAnimating.value = true
  isLoading.value = true

  try {
    await sendToAPI(message)
  } finally {
    isTyping.value = false
    streamingAnimating.value = false
    isLoading.value = false
  }
}

async function sendToAPI(message: string) {
  // Your API implementation here
}
</script>

<style scoped>
.chat-container {
  display: flex;
  flex-direction: column;
  height: 100vh;
}

.messages-area {
  flex: 1;
  overflow-y: auto;
  padding: 1rem;
}

.input-area {
  border-top: 1px solid #e5e7eb;
  padding: 1rem;
}
</style>

Store API (Unified Components)

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

const chatStore = useChatStore()

// Authentication
chatStore.setToken('your-token')
chatStore.clearToken()

// Send message
chatStore.sendMessage('Hello')

// Access state
chatStore.messages // ChatMessage[]
chatStore.isTyping // boolean
chatStore.isConnected // boolean
chatStore.user // AuthUser | null

// Clear conversation
chatStore.clearConversation()

Styling

CSS Import

typescript
import '@sprout_ai_labs/sidekick/dist/sprout-sidekick.css'

Key CSS Classes

css
/* Messages */
.scp-messages
.scp-message-bubble
.scp-user-message-text
.scp-ai-message-text

/* Input */
.sidekick-chat-input-container
.sidekick-chat-input-editable

/* Thoughts */
.collapsible-thought
.thought-header
.thought-steps

Custom Styling Example

css
/* Override message colors */
.scp-user-message-text {
  background: #your-brand-color !important;
}

/* Override input styling */
.sidekick-chat-input-editable {
  font-size: 16px;
  padding: 12px;
}

Plugin Configuration

typescript
app.use(SproutSidekick, {
  mode: 'PROD', // Required: 'QA' | 'PROD'
  appName: 'My App', // Required: Your app name
  skipDesignSystem: false, // Optional: Skip design system
  baseUrl: 'https://...', // Optional: Custom backend URL
  deviceSource: 'web', // Optional: 'mobile' | 'web'
})

Released under the MIT License.