UNPKG

assistant-cloud

Version:

Cloud integration for assistant-ui

125 lines (94 loc) • 5.66 kB
# `assistant-cloud` [![npm version](https://img.shields.io/npm/v/assistant-cloud)](https://www.npmjs.com/package/assistant-cloud) [![npm downloads](https://img.shields.io/npm/dm/assistant-cloud)](https://www.npmjs.com/package/assistant-cloud) [![GitHub stars](https://img.shields.io/github/stars/assistant-ui/assistant-ui)](https://github.com/assistant-ui/assistant-ui) Server- and client-side SDK for [Assistant Cloud](https://cloud.assistant-ui.com), the managed thread-history, telemetry, and file-storage backend for `@assistant-ui/react`. ## Installation ```bash npm install @assistant-ui/react @assistant-ui/ai-sdk ai assistant-cloud ``` ## Usage Pass an `AssistantCloud` instance to your runtime hook (typically `useChatRuntime` from `@assistant-ui/ai-sdk`): ```tsx import { AssistantCloud, AssistantRuntimeProvider } from "@assistant-ui/react"; import { useChatRuntime } from "@assistant-ui/ai-sdk"; const cloud = new AssistantCloud({ baseUrl: process.env.NEXT_PUBLIC_ASSISTANT_BASE_URL!, anonymous: true, }); export function Provider({ children }: { children: React.ReactNode }) { const runtime = useChatRuntime({ cloud }); return <AssistantRuntimeProvider runtime={runtime}>{children}</AssistantRuntimeProvider>; } ``` ## Building an integration The pieces every client integration needs live in the package, so a runtime binding only maps its own events onto them. Every API request carries `Aui-Sdk` with the client's own version and the identities integrations pass to `registerSdk` (the anonymous token bootstrap requests do not), so the cloud can tell which packages talk to a project. - `CloudRunReporter` sends run reports: nothing while telemetry is off, the cloud's environment, release and tags on every report, the `beforeReport` hook applied last, and a failed send that never surfaces. Keyed reports are deduplicated while in flight and after an attempt, while rate limiting releases the key for a later attempt; without a key every call reports. - `CloudEngagementReporter` derives engagement events (`message_sent`, `run_stopped`, `error_shown`, `suggestions_shown` and the rest) from what a chat integration observes and keeps the per thread state they need, such as a run's start for the stop duration. An id resolver turns the integration's own thread and message ids into the ids the cloud stores. - `assistant-cloud/ai-sdk` holds the AI SDK specifics: `aiSDKV6FormatAdapter`, the stored form of a `UIMessage`, and `extractAISDKRunTelemetry`, which reads the run report fields out of one run's assistant messages. The entry types its messages with `ai` and needs no runtime from it. ```ts import { AssistantCloud, CloudRunReporter } from "assistant-cloud"; import { extractAISDKRunTelemetry } from "assistant-cloud/ai-sdk"; const cloud = new AssistantCloud({ baseUrl, anonymous: true }); const reporter = new CloudRunReporter(cloud); const run = extractAISDKRunTelemetry(messages); if (run) { await reporter.report( { threadId, ...run }, run.assistantMessageId && `${threadId}:${run.assistantMessageId}`, ); } ``` ## Server telemetry Send AI SDK 7 GenAI spans to Assistant Cloud from a Next.js app. The AI SDK emits spans through `@ai-sdk/otel`, and the `assistant-cloud/telemetry` entry needs the OpenTelemetry packages installed next to it: ```sh npm i @vercel/otel @ai-sdk/otel @opentelemetry/api @opentelemetry/sdk-trace-base @opentelemetry/exporter-trace-otlp-http ``` Register the span processor in `instrumentation.ts` so it starts once per server process: ```ts import { registerOTel } from "@vercel/otel"; import { createAssistantCloudSpanProcessor, createAssistantCloudTraceExporter, } from "assistant-cloud/telemetry"; export function register() { registerOTel({ serviceName: "my-app", spanProcessors: [ "auto", createAssistantCloudSpanProcessor( createAssistantCloudTraceExporter({ apiKey: process.env.ASSISTANT_API_KEY!, }), ), ], }); } ``` In the route that calls `streamText`, enable the OpenTelemetry integration and pass the active trace ID to the browser with `messageMetadata`: ```ts import { OpenTelemetry } from "@ai-sdk/otel"; import { openai } from "@ai-sdk/openai"; import { convertToModelMessages, streamText } from "ai"; import { withAssistantCloudTraceMetadata } from "assistant-cloud/telemetry"; export async function POST(request: Request) { const { messages } = await request.json(); const result = streamText({ model: openai("gpt-6-luna"), messages: await convertToModelMessages(messages), telemetry: { integrations: [new OpenTelemetry()] }, }); return result.toUIMessageStreamResponse({ messageMetadata: withAssistantCloudTraceMetadata(), }); } ``` [Traces](https://www.assistant-ui.com/docs/cloud/traces) covers the exporter options, the span filter, and how Assistant Cloud merges a trace with the browser's run report. ## Authentication | Mode | Required fields | Use case | | ---------------- | ------------------------------------------------------- | ------------------------------------- | | Anonymous | `baseUrl`, `anonymous: true` | Demos and unauthenticated playgrounds.| | JWT | `baseUrl`, `authToken: () => Promise<string \| null>` | Browser apps with their own auth. | | API key (server) | `apiKey`, `userId`, `workspaceId` | Server-side admin and data-plane jobs.| For advanced persistence adapters and MCP sampling instrumentation, see the [docs](https://www.assistant-ui.com/docs/cloud).