npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@8wave/ai-elements

v0.83.0

Published

AI chat components and utilities for the Eight Wave Agent Studio platform. The package offers multiple entry points depending on your use case — from a drop-in web component to a framework-agnostic API client.

Readme

@8wave/ai-elements

AI chat components and utilities for the Eight Wave Agent Studio platform. The package offers multiple entry points depending on your use case — from a drop-in web component to a framework-agnostic API client.

Entry points

| Import path | Framework | Description | | ---------------------------------- | --------- | ---------------------------------------------------- | | @8wave/ai-elements | None | Self-registering <floating-chat-widget> and <embedded-chat-widget> custom elements. | | @8wave/ai-elements/api | None | createChatbotApiClient — zero-dependency HTTP client. | | @8wave/ai-elements/vue | Vue 3 | All Pk* chat components (barrel import). | | @8wave/ai-elements/vue/composables | Vue 3 | useChatbotAuth, useChatbotAgent, useChatbotStore, and utilities. | | @8wave/ai-elements/vue/locales | Vue 3 | Cherry-picked i18n messages for Pk* components. | | @8wave/ai-elements/vue/style.css | — | Stylesheet for Vue components. |

Overview

The package exposes two custom elements. <floating-chat-widget> renders a fixed-position button in the bottom-right corner of the page — clicking it opens a full chat panel. <embedded-chat-widget> renders a full-width chat interface inline, with no toggle button, suitable for dedicated chat pages. Anonymous authentication is handled automatically by both components.

Installation

npm install @8wave/ai-elements
# or
pnpm add @8wave/ai-elements

Usage

Via npm package

Import the package once (e.g. in your app entry point). The custom element registers itself automatically.

import '@8wave/ai-elements'

Then use either element anywhere in your HTML:

<!-- Floating toggle button -->
<floating-chat-widget
  organization-slug="your-org-slug"
  agent-id="your-agent-id"
></floating-chat-widget>

<!-- Inline full-page chat -->
<embedded-chat-widget
  organization-slug="your-org-slug"
  agent-id="your-agent-id"
></embedded-chat-widget>

Via CDN (no bundler)

<!-- jsDelivr -->
<script type="module" async src="https://cdn.jsdelivr.net/npm/@8wave/ai-elements/dist/ai-elements.es.js"></script>
<!-- or unpkg (redirects automatically) -->
<!-- <script type="module" async src="https://unpkg.com/@8wave/ai-elements"></script> -->

<!-- Floating toggle button -->
<floating-chat-widget
  organization-slug="your-org-slug"
  agent-id="your-agent-id"
></floating-chat-widget>

<!-- Inline full-page chat -->
<embedded-chat-widget
  organization-slug="your-org-slug"
  agent-id="your-agent-id"
></embedded-chat-widget>

External authentication (JWT)

By default both custom elements sign in anonymously. If your application already has an authenticated user, pass their JWT via the external-token attribute to link the chat session to that user. When the token is invalid or expired the component falls back to anonymous sign-in automatically.

The external-token attribute is reactive — you can set or change it at any time after mount and the widget will automatically authenticate with the new token. If the token is not available at mount time, add the await-external-token attribute to prevent the widget from creating an anonymous session:

<floating-chat-widget
  organization-slug="your-org-slug"
  agent-id="your-agent-id"
  external-token="eyJhbGciOiJSUzI1NiIs..."
></floating-chat-widget>

If the token is generated dynamically (e.g. after login), set the attribute from JavaScript:

const widget = document.querySelector('floating-chat-widget')
widget.setAttribute('external-token', currentUser.jwt)

If the token is fetched asynchronously, use await-external-token to prevent anonymous sign-in while waiting:

<floating-chat-widget
  organization-slug="your-org-slug"
  agent-id="your-agent-id"
  await-external-token
></floating-chat-widget>
const widget = document.querySelector('floating-chat-widget')

// Widget waits — no anonymous session is created
const jwt = await fetchTokenFromMyApi()
widget.setAttribute('external-token', jwt) // Single session created

Note: The external-token value is validated server-side. On a 401 response the component silently re-authenticates — either with the external token again or falling back to anonymous.

Attributes

<floating-chat-widget>

| Attribute | Type | Required | Default | Description | | -------------------------- | -------------------- | -------- | ------------------------------- | ---------------------------------------------------------------------------------------------------- | | agent-id | string | ✅ | — | The unique identifier of the AI agent to connect to. | | organization-slug | string | ✅ | — | The slug of the organization that owns the agent. | | base-url | string | ❌ | https://ai-api.8wave.it (build-time) | Base URL of the Eight Wave backend API. Override when self-hosting or pointing to a different environment. | | external-token | string | ❌ | — | Pre-existing auth token. Reactive — can be set or changed at any time. When set, the widget authenticates with this token instead of anonymous sign-in. | | await-external-token | boolean | ❌ | false | When present, the widget waits for external-token instead of signing in anonymously. Use when the token is fetched asynchronously after mount. | | floating-button-position | 'left' \| 'right' | ❌ | 'right' | Position of the floating toggle button on the screen. | | custom-css | string | ❌ | — | Raw CSS string injected into the shadow root to override default styles. |

<embedded-chat-widget>

| Attribute | Type | Required | Default | Description | | ------------------- | -------- | -------- | ------------------------------- | ---------------------------------------------------------------------------------------------------- | | agent-id | string | ✅ | — | The unique identifier of the AI agent to connect to. | | organization-slug | string | ✅ | — | The slug of the organization that owns the agent. | | base-url | string | ❌ | https://ai-api.8wave.it (build-time) | Base URL of the Eight Wave backend API. Override when self-hosting or pointing to a different environment. | | external-token | string | ❌ | — | Pre-existing auth token. Reactive — can be set or changed at any time. When set, the widget authenticates with this token instead of anonymous sign-in. | | await-external-token | boolean | ❌ | false | When present, the widget waits for external-token instead of signing in anonymously. Use when the token is fetched asynchronously after mount. | | forwarded-slots | string | ❌ | — | Comma-separated slot names to forward to PkChatbot (e.g. "tool-showArtifact,subagent"). | | custom-css | string | ❌ | — | Raw CSS string injected into the shadow root to override default styles. |

How it works

  1. On mount the component automatically signs in as an anonymous user via the Eight Wave Auth service.
  2. Once authenticated it fetches the agent configuration (name, interface colors, etc.) from the public API.
  3. A circular floating button appears in the bottom-right corner, styled with the agent's mainColor.
  4. Clicking the button toggles the chat panel open/closed.
  5. All styles are encapsulated inside a Shadow DOM — no CSS leaks in or out.

Vue Components

In addition to the web component, the package exposes all Pk* Vue 3 components for direct use inside Vue applications.

Installation

pnpm add @8wave/ai-elements vue vue-i18n @volverjs/ui-vue

# Optional — only required if you use PkEditorCode
pnpm add monaco-editor-vue3

Setup

The components require vue-i18n to be installed and configured in the host application. They call useI18n({ useScope: 'global' }) internally, so the i18n instance must be registered via app.use(i18n) before mounting any component.

// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { createI18n } from 'vue-i18n'
import { messagesEn, messagesIt } from '@8wave/ai-elements/vue/locales'
import '@8wave/ai-elements/vue/style.css'
import App from './App.vue'

const i18n = createI18n({
    legacy: false,
    locale: 'it',
    messages: {
        it: { ...messagesIt, /* your own keys */ },
        en: { ...messagesEn, /* your own keys */ },
    },
})

createApp(App).use(createPinia()).use(i18n).mount('#app')

Note: @volverjs/ui-vue must also be registered via app.use(VolverPlugin, { ... }) with the icon collections and any component defaults you need.

Usage

// Barrel import (all components)
import { PkChatbot } from '@8wave/ai-elements/vue'

// Individual import (tree-shakeable)
import PkChatbot from '@8wave/ai-elements/vue/PkChatbot'
<PkChatbot
  base-url="https://api.example.com"
  agent-id="your-agent-id"
  v-model:chat-id="chatId"
  :headers="{ Authorization: `Bearer ${token}` }"
  :actions="['upvote', 'downvote', 'copy']"
  system-theme="light"
  @error="handleError"
/>

PkChatbot props

| Prop | Type | Required | Description | | ----------------- | ------------------------------------- | -------- | -------------------------------------------------------------- | | baseUrl | string | ✅ | Base URL of the Eight Wave backend API. | | basePath | string | ❌ | Path prefix appended to baseUrl for all API requests. | | agentId | string | ✅ | Unique identifier of the AI agent. | | agentType | 'chat' \| 'reasoning' | ❌ | Enables reasoning mode (hides feedback actions). | | userId | string | ❌ | Optional user identifier forwarded to the backend. | | name | string | ❌ | Display name shown in the chat header. | | model | string | ❌ | Override the default language model. | | agentModel | AgentModel | ❌ | Full model configuration object. | | agentTools | AgentTools | ❌ | Tool configuration exposed to the agent. | | agentInterface | AgentInterface | ❌ | Interface customization (colors, placeholder text, etc.). | | actions | ChatMessageActions[] | ❌ | Actions available on each message ('upvote', 'downvote', 'copy', 'feedback', …). | | revisedAnswers | RevisedAnswer[] | ❌ | List of revised answers to display inline. | | headers | Record<string, string> | ❌ | Extra HTTP headers forwarded to every API request. | | systemTheme | 'light' \| 'dark' | ❌ | Override the OS color scheme preference. | | agentFileUpload | AgentFileUpload | ❌ | File upload configuration (accepted types, size limits). | | fallbackModels | string[] | ❌ | Ordered list of fallback model identifiers. | | gatewayOptions | Partial<AgentGatewayOptions> | ❌ | Gateway-level options (routing, caching, etc.). |

PkChatbot v-model

| Model | Type | Description | | --------- | --------------------- | ------------------------------------------------- | | chatId | string \| undefined | Two-way binding for the active conversation ID. |

PkChatbot events

| Event | Payload | Description | | ---------------- | ---------------------------------------------------- | ---------------------------------------- | | message-update | UIChatMessage | Emitted whenever a message is updated. | | show-info | UIChatMessage | User requested info panel for a message. | | revise | UIChatMessage | User requested answer revision. | | error | { type: string; title: string; status: number } | A transport or API error occurred. |

Available components

| Component | Description | | ------------------------------- | -------------------------------------------------------- | | PkChatbot | Main chatbot component — use this as your entry point. | | PkChatbotMessages | Scrollable message list. | | PkChatbotInput | Chat input bar with file/audio support. | | PkChatbotError | Error state display. | | PkChatbotFeedbackForm | Feedback collection form. | | PkChatbotViewChat | Full chat view (messages + input). | | PkChatbotViewConversations | Conversation history list. | | PkChatbotViewProfile | User profile view. |

Locales

The package exports cherry-picked i18n messages (messagesEn, messagesIt) containing only the translation keys used by Pk* components. Merge them into your vue-i18n instance as shown in the Setup section above, or add them at runtime to an existing instance:

import { messagesEn, messagesIt } from '@8wave/ai-elements/vue/locales'

i18n.global.mergeLocaleMessage('it', messagesIt)
i18n.global.mergeLocaleMessage('en', messagesEn)

Auth

Auth utilities are exported from @8wave/ai-elements/vue/composables.

import { useChatbotAuth, setSessionCookie, getSessionCookie } from '@8wave/ai-elements/vue/composables'

useChatbotAuth(options)

Orchestrates the authentication lifecycle for the chatbot widgets. Handles anonymous sign-in, external token sign-in, and automatic re-authentication on 401 errors.

import { useChatbotAuth } from '@8wave/ai-elements/vue/composables'

const { client, session, isAuthenticating, token, headers, onError, userId } = useChatbotAuth()

| Option | Type | Required | Description | | --------------- | -------------------------------- | -------- | ------------------------------------------------------------------------ | | baseUrl | string | ❌ | Base URL of the Eight Wave backend. Defaults to https://ai-api.8wave.it (build-time env variable). | | basePath | string | ❌ | Auth base path appended to baseUrl. Defaults to auth. | | externalToken | MaybeRefOrGetter<string \| undefined> | ❌ | Pre-existing auth token. Accepts a static string, a ref, or a getter. When the value is truthy, the composable authenticates with it instead of signing in anonymously. Reactive — authentication triggers automatically when the value changes. | | awaitExternalToken | boolean | ❌ | When true, the composable does not fall back to anonymous sign-in while externalToken is falsy. Authentication triggers automatically when the token value becomes available. | | isActive | MaybeRefOrGetter<boolean> | ❌ | Reactive signal that triggers authentication when it becomes true. Defaults to always active. | | cookieName | string | ❌ | Cookie name for session persistence. Defaults to eight-wave-ai. Use different names to isolate multiple sessions on the same page. |

Returns:

| Property | Type | Description | | ----------------- | ----------------------- | ----------------------------------------------------------------- | | client | AuthClient | The underlying Better Auth client instance. Exposes signIn.anonymous(), signIn.externalToken({ token }), and useSession(). | | session | Ref<Session> | Reactive session state from the auth client. | | isAuthenticating| Ref<boolean> | true while a sign-in request is in flight. | | token | WritableComputedRef<string> | Reactive Bearer token, synced to the first-party cookie. | | headers | ComputedRef<Record<string, string> \| undefined> | Reactive Authorization header derived from token. Pass directly to useChatbotAgent or PkChatbot. | | onError | (error) => void | Pass to PkChatbot's @error event to trigger automatic re-auth on 401. | | userId | ComputedRef<string \| undefined> | Reactive user ID extracted from the session. Pass to PkChatbot's :user-id. |

End-to-end example (Vue + external JWT)

The following example shows how to wire useChatbotAuth, useChatbotAgent, and PkChatbot together with an external JWT token inside a Vue 3 application.

<script setup lang="ts">
import { ref } from 'vue'
import { useChatbotAuth, useChatbotAgent } from '@8wave/ai-elements/vue/composables'
import { PkChatbot } from '@8wave/ai-elements/vue'

const isActive = ref(true)

// 1. Authenticate — pass externalToken to skip anonymous sign-in
const { session, token, headers, onError, userId } = useChatbotAuth({
    baseUrl: 'https://api.example.com', // optional, defaults to https://ai-api.8wave.it
    externalToken: 'eyJhbGciOiJSUzI1NiIs...', // optional JWT from your auth system
    isActive, // optional ref that triggers authentication when true (defaults to always active)
})

// 2. Fetch agent metadata and theme — headers flow directly from auth
const { agent, themeClass, themeStyle } = useChatbotAgent({
    baseUrl: 'https://api.example.com', // optional, defaults to https://ai-api.8wave.it
    organizationSlug: 'your-org-slug',
    agentId: 'your-agent-id',
    headers,
})
</script>

<template>
    <PkChatbot
        v-if="agent && session.data"
        :class="themeClass"
        :style="themeStyle"
        base-url="https://api.example.com"
        :agent-id="agent.id"
        :user-id="userId"
        :name="agent.name"
        :agent-interface="agent.interface"
        :headers="headers"
        :actions="['upvote', 'downvote', 'feedback', 'regenerate']"
        @error="onError"
    />
</template>

How the auth flow works:

  1. useChatbotAuth validates the external token server-side. If valid, the session is linked to the authenticated user.
  2. If the token is invalid or expired, the composable silently falls back to anonymous sign-in.
  3. When awaitExternalToken is true and externalToken is not yet available, the composable waits — no anonymous session is created. Authentication triggers automatically when the token arrives.
  4. If externalToken is provided as a reactive getter or ref, authentication triggers automatically whenever the value changes.
  5. On any subsequent 401 error, pass onError to PkChatbot's @error event — it triggers automatic re-authentication.
  6. token is a reactive ref synced to a first-party cookie, so the session persists across page reloads.

useChatbotAgent(options)

Fetches the agent configuration and derives theme properties from it.

import { useChatbotAgent } from '@8wave/ai-elements/vue/composables'

const { agent, contrastColor, mainColor, themeClass, themeStyle } = useChatbotAgent({
    organizationSlug: 'your-org-slug',
    agentId: 'your-agent-id',
    headers,
})

| Option | Type | Required | Description | | ------------------ | -------------------------------------------------- | -------- | ------------------------------------------------------------------------ | | baseUrl | string | ❌ | Base URL of the Eight Wave backend. Defaults to https://ai-api.8wave.it. | | basePath | string | ❌ | API base path appended to baseUrl. | | organizationSlug | MaybeRefOrGetter<string> | ❌ | The slug of the organization that owns the agent. | | agentId | MaybeRefOrGetter<string> | ❌ | The unique identifier of the AI agent. | | headers | MaybeRefOrGetter<Record<string, string> \| undefined> | ❌ | Reactive headers (typically from useChatbotAuth). |

Returns:

| Property | Type | Description | | --------------- | --------------------------------- | -------------------------------------------------------- | | agent | Ref<AgentPublic \| undefined> | Reactive agent configuration fetched from the API. | | contrastColor | ComputedRef<string> | Contrast color computed from the agent's mainColor. | | mainColor | ComputedRef<string \| undefined> | The agent's primary color. | | themeClass | ComputedRef<string[]> | CSS class array for the agent's theme (light / dark). | | themeStyle | ComputedRef<CSSProperties \| undefined> | CSS custom properties (--chatbot-main-color, --chatbot-contrast-color). |

setSessionCookie(token, cookieName?)

Writes the session token to a first-party Secure; SameSite=Lax cookie with a 1-year expiry. Defaults to the eight-wave-ai cookie name.

getSessionCookie(cookieName?)

Reads and returns the current value of the session cookie, or an empty string if it is not set. Defaults to the eight-wave-ai cookie name.


API Client (framework-agnostic)

A zero-dependency HTTP client factory that can be used in any JavaScript or TypeScript project — no Vue, no Pinia required. Exported from a dedicated @8wave/ai-elements/api entry point.

Installation

No extra peer dependencies are needed beyond the base package.

pnpm add @8wave/ai-elements

Usage

import { createChatbotApiClient } from '@8wave/ai-elements/api'

const client = createChatbotApiClient({
    baseUrl: 'https://ai-api.8wave.it',
    headers: () => ({ Authorization: `Bearer ${token}` }),
    credentials: 'include', // optional, defaults to 'include'
})

// Fetch the agent configuration
const agent = await client.getAgent('my-org', 'my-agent-id')

// Fetch an existing conversation
const chat = await client.getChat('my-agent-id', 'my-chat-id')

// Rename a conversation
await client.updateChatTitle('my-agent-id', 'my-chat-id', 'New Title')

// Delete a conversation
await client.deleteChat('my-agent-id', 'my-chat-id')

// Submit a message feedback
await client.submitMessageFeedback({
    messageId: 'msg-123',
    chatId: 'chat-456',
    agentId: 'my-agent-id',
    vote: 'upvote',
    userQuestion: 'What is Vue?',
    assistantMessage: 'Vue is a progressive JavaScript framework.',
})

// Get the streaming chat endpoint URL (use with Vercel AI SDK or plain fetch)
const endpoint = client.getChatEndpoint('my-agent-id')
// => 'https://api.example.com/agents/my-agent-id/chat'

createChatbotApiClient(options)

| Option | Type | Required | Description | | ------------- | -------------------------------------------- | -------- | ------------------------------------------------------------ | | baseUrl | string | ✅ | Base URL of the Eight Wave backend API. | | basePath | string | ❌ | Path prefix appended to baseUrl for all requests. | | headers | () => Record<string, string> \| undefined | ❌ | Factory function called before each request to inject custom headers (e.g. auth tokens). | | credentials | RequestCredentials | ❌ | Fetch credentials mode. Defaults to 'include'. |

ChatbotApiClient methods

| Method | Signature | Description | | ----------------------- | -------------------------------------------------------------------------- | ------------------------------------------------------------------ | | getAgent | (orgSlug, agentId) => Promise<AgentPublic> | Fetches the public agent configuration. | | getConversations | (agentId, userId?) => Promise<Chat[]> | Returns the last 100 conversations for the given agent / user. | | getChat | (agentId, chatId) => Promise<Chat \| null> | Fetches a single conversation. Returns null when not found (204). | | updateChatTitle | (agentId, chatId, title) => Promise<Chat> | Updates the title of a conversation. | | deleteChat | (agentId, chatId) => Promise<void> | Deletes (soft-deletes) a conversation. | | getMessageFeedbacks | (chatId) => Promise<MessageFeedback[]> | Returns all feedback entries for a conversation. | | submitMessageFeedback | (payload: SubmitFeedbackPayload) => Promise<MessageFeedback> | Creates or updates a feedback entry for a message. | | submitLead | (payload: SubmitLeadPayload) => Promise<void> | Submits a lead form associated with the current conversation. | | getChatEndpoint | (agentId, type?) => string | Returns the streaming chat endpoint URL. type defaults to 'chat', pass 'reasoning' for reasoning agents. | | uploadMedia | (agentId, chatId, file: File) => Promise<MediaSource> | Uploads a file to a conversation and returns its media source metadata. | | getMediaUrl | (agentId, chatId, storedFileName) => string | Returns the authenticated URL for viewing an uploaded media file. | | appendAuthToken | (url) => string | Appends the current Bearer token as a token query parameter to a URL. | | expandSourceContext | (agentId, documentId, chunkIndex, windowSize?) => Promise<{ content: string }> | Fetches expanded context around a source chunk. | | downloadSourceDocument| (agentId, documentId) => Promise<{ downloadUrl, filename, mimeType }> | Returns a download URL for a source document. | | reverseGeocode | (lat, lon, lang?) => Promise<string \| undefined> | Resolves coordinates to a display name. | | forwardGeocode | (query, lang?) => Promise<{ latitude, longitude, displayName } \| undefined> | Resolves a text query to coordinates. |


Chatbot Store (Vue / Pinia)

The useChatbotStore composable is the Pinia store that backs all PkChatbot* components. It can be used directly when you need programmatic access to the chat state outside of the pre-built components.

Exported from @8wave/ai-elements/vue/composables.

Installation

Requires the same peer dependencies as the Vue components plus Pinia.

pnpm add @8wave/ai-elements vue vue-i18n pinia @vueuse/core ai @ai-sdk/vue @ai-sdk/ui-utils

Setup

pinia must be installed in the Vue app before using the store.

// main.ts
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { createI18n } from 'vue-i18n'
import App from './App.vue'

const i18n = createI18n({ legacy: false, locale: 'it', messages: {} })

createApp(App).use(createPinia()).use(i18n).mount('#app')

Usage

import { useChatbotStore } from '@8wave/ai-elements/vue/composables'

const store = useChatbotStore('my-agent-id')

// Configure the store (equivalent to setting PkChatbot props)
store.baseUrl = 'https://api.example.com'
store.name = 'My Agent'
store.headers = { Authorization: `Bearer ${token}` }

// Load existing conversation
await store.initialize('my-agent-id', store.localChatId)

// Send a message
store.input = 'Hello!'
await store.handleSubmit()

// Rename a conversation
await store.renameChatTitle('chat-id', 'New Title')

// Delete a conversation
await store.deleteChat('chat-id')

// Navigate between views
store.navigate('conversations')

Key store state

| Property | Type | Description | | ---------------------- | ------------------------------- | ----------------------------------------------------------------- | | baseUrl | string | Backend base URL. | | agentId | Ref<string> | The agent ID this store instance is bound to (read-only after init). | | messages | ComputedRef<UIChatMessage[]> | Full message list including the welcome message. | | conversations | Ref<Chat[]> | List of past conversations. | | localChatId | WritableComputedRef<string> | Active conversation ID, persisted to localStorage. | | input | Ref<string> | Current value of the text input. | | activeView | Ref<'chat' \| 'conversations' \| 'profile'> | Currently visible view. | | pendingAttachments | Ref<PendingAttachment[]> | Files queued for upload or already uploaded. | | isConversationBlocked| Ref<boolean> | Whether the current conversation is blocked. | | chatError | Ref<Error \| undefined> | Latest chat error, if any. | | isLeadSubmitted | Ref<boolean> | Whether the lead form was submitted successfully. | | messageFeedbacks | Ref<MessageFeedback[]> | Feedback entries for the current conversation. |

Store actions

| Action | Signature | Description | | ---------------------- | ------------------------------------------------ | ----------------------------------------------------------------- | | initialize | (agentId, chatId) => Promise<void> | Loads conversation, feedbacks, and agent config. | | loadConversations | (agentId) => Promise<void> | Fetches the conversation list for the agent. | | handleSubmit | (options?) => Promise<void> | Sends the current input as a message. | | stopGeneration | () => Promise<void> | Aborts the current streaming response. | | startNewChat | () => Promise<string> | Clears state and generates a new chat ID. | | regenerate | (options?) => Promise<void> | Regenerates the last assistant response. | | addToolOutput | (params) => void | Provides output for a pending tool call. | | handleFileSelect | (file: File) => Promise<void> | Uploads a file and adds it to pending attachments. | | clearPendingAttachments | (revoke?) => void | Removes all pending attachments. | | onUpvote | (message) => Promise<void> | Submits an upvote for a message. | | onDownvote | (message) => Promise<void> | Submits a downvote for a message. | | onFeedback | (message) => void | Opens the feedback dialog for a message. | | onFeedbackSubmit | (comment) => Promise<void> | Submits feedback with a comment. | | onLeadSubmit | (data) => Promise<void> | Submits a lead form. | | navigate | (view) => void | Switches the active view. | | renameChatTitle | (chatId, title) => Promise<void> | Updates the title of a conversation. | | deleteChat | (chatId) => Promise<void> | Deletes a conversation and navigates to a new chat if needed. |

Note: agentId is immutable per component lifecycle. If you need to switch agents, use :key="agentId" on the parent component to force a remount and a fresh store instance.