Components
The components exported from autopilot-client/vue are renderless: each one owns the logic (reading from useAutopilotStore and the composables) and exposes its state and actions through a default scoped slot. They render no markup and ship no CSS — you provide the markup, styled however you like.
For a styled, drop-in version of all of these, use @llmor/autopilot-bar; its components are exactly these wrapped with markup + a skin.
import {
AutopilotOverlay,
ConversationMessage,
ConversationMessageAssistant,
ConfirmationPrompt,
AskUserPrompt,
} from '@llmor/autopilot-vue';TIP
These components read from useAutopilotStore. Make sure Pinia is installed and a client has been registered with setAutopilotClient(client) before mounting them.
AutopilotOverlay
The whole chat surface as one renderless component: visibility, messages, connection state, pending prompts, and the message-composer verbs. Build your entire UI from its slot.
| Slot prop | Type | Notes |
|---|---|---|
isOpen | boolean | store.isBarOpen |
messages | ConversationMessage[] | visibleMessages |
isStreaming / streamingMessage | boolean / ConversationMessage | null | streaming state |
connectionStatus / connectionError / connectionErrorTitle | — | connection state + friendly heading |
isConnected / isConnecting | boolean | |
pendingConfirmations / pendingAskUser | arrays | feed into the prompts below |
messageText / setMessageText(v) | string / (v) => void | input draft (controlled) |
isSending / canSend | boolean | |
sendMessage() | () => Promise<boolean> | sends the draft |
stopStreaming() / resetConversation() / retryConnection() | () => Promise<void> | |
open() / close() / toggle() | () => void | visibility |
<AutopilotOverlay v-slot="{ isOpen, messages, messageText, setMessageText, sendMessage }">
<div v-if="isOpen" class="my-panel">
<MyMessage v-for="m in messages" :key="m.created_at" :message="m" />
<form @submit.prevent="sendMessage">
<input :value="messageText" @input="setMessageText($event.target.value)" />
</form>
</div>
</AutopilotOverlay>ConversationMessage
A single user/system/error message. Props: message: ConversationMessage, isStreaming?: boolean.
Slot props: role, displayRole, content (raw text), html (markdown-rendered), isEmpty, isStreaming.
<ConversationMessage :message="m" v-slot="{ displayRole, html, isEmpty }">
<div class="bubble">
<strong>{{ displayRole }}</strong>
<span v-if="isEmpty">…</span>
<div v-else v-html="html" />
</div>
</ConversationMessage>ConversationMessageAssistant
An assistant message with markdown and function-call disclosure. Props: message, isStreaming?.
Slot props: html, isEmpty, isStreaming, createdAt, functionCalls, isExpanded(id), toggle(id), formatResult(result). Pair with translateFunctionName / getFunctionIcon for friendly labels.
ConfirmationPrompt
Resolves a pending sensitive function confirmation. Prop: pending: PendingConfirmation (from store.pendingConfirmations).
Slot props: pending, functionName, displayName, argumentsJson, allow(), alwaysAllow(), deny().
<ConfirmationPrompt
v-for="p in store.pendingConfirmations"
:key="p.id"
:pending="p"
v-slot="{ displayName, argumentsJson, allow, deny }"
>
<div class="confirm">
<p>Run “{{ displayName }}”?</p>
<pre>{{ argumentsJson }}</pre>
<button @click="deny">Deny</button>
<button @click="allow">Allow</button>
</div>
</ConfirmationPrompt>AskUserPrompt
Renders the pending ask-user questions. Prop: prompts: AskUserPrompt[] (from store.pendingAskUser).
Slot props: prompts, active, activeIndex, isLastTab, allAnswered, isSubmitting, the reactive drafts textDraft / boolDraft / radioDraft / checklistDraft (bind with v-model), isAnswered(p), setActiveIndex(i), advance(), send().
<AskUserPrompt :prompts="store.pendingAskUser" v-slot="{ active, textDraft, allAnswered, send }">
<div>
<p>{{ active.question }}</p>
<input v-model="textDraft[active.id]" />
<button :disabled="!allAnswered" @click="send">Send</button>
</div>
</AskUserPrompt>Prefer composables?
Every component above is a thin wrapper over a composable, so you can skip the component and call the logic directly:
useMessageComposer()— the input/send/stop/reset/reconnect verbs (behindAutopilotOverlay).useAskUserForm(promptsRef)— tabbed ask-user form state (behindAskUserPrompt).useFunctionCallDetails()— function-call disclosure + result formatting.useConfirmations,useAskUser,useAutopilotContext— the lower-level pieces the store composes.
When to use this vs. enableAutopilotBar
- Use
enableAutopilotBar(client)(bar) when you want a working, styled chat surface and do not need control over markup. - Use these renderless components / composables when you want the chat embedded in your own layout and styled with your design system. You provide 100% of the markup; nothing is styled for you.