AbsoluteJS

Vue AI

The useAIStream composable connects Vue components to the AI streaming WebSocket with reactive refs. Import from @absolutejs/ai/vue.

#useAIStream

The composable takes a WebSocket path and optional conversation ID. All returned state values are Vue refs that update reactively as messages stream in. The connection cleans up automatically on onUnmounted.

HTML
<script setup lang="ts">
import { useAIStream } from '@absolutejs/ai/vue';

const { messages, send, cancel, branch, isStreaming, error } =
  useAIStream('/chat');

const handleSend = (text: string) => {
  send(text);
};
</script>

<template>
  <div>
    <div v-for="msg in messages" :key="msg.id">
      <strong>{{ msg.role }}:</strong> {{ msg.content }}
      <details v-if="msg.thinking">
        <summary>Thinking</summary>
        <p>{{ msg.thinking }}</p>
      </details>
    </div>

    <button v-if="isStreaming" @click="cancel()">Stop</button>
    <p v-if="error" style="color: red">{{ error }}</p>
  </div>
</template>

#Return Type

TS
// useAIStream return type (all values are Vue refs)
{
  send: (content: string, attachments?: AIAttachment[]) => void;
  cancel: () => void;
  branch: (messageId: string, content: string) => void;
  destroy: () => void; // Clean up connection manually

  messages: ShallowRef<AIMessage[]>;
  isStreaming: Ref<boolean>;
  error: Ref<string | null>;
}

#Provide / Inject

Share a single AI connection across your component tree using Vue's provide/inject pattern. The exported AIStreamKey symbol ensures type safety.

HTML
<script setup lang="ts">
import { provide } from 'vue';
import { useAIStream, AIStreamKey } from '@absolutejs/ai/vue';

// Create the stream and provide it to descendants
const ai = useAIStream('/chat');
provide(AIStreamKey, ai);
</script>

<!-- Child component -->
<script setup lang="ts">
import { inject } from 'vue';
import { AIStreamKey } from '@absolutejs/ai/vue';

const ai = inject(AIStreamKey)!;
// ai.messages, ai.send, ai.cancel, etc.
</script>