createLuxoChatRoute
Betafunction createLuxoChatRoute(
options: LuxoRouteOptions,
): {
GET: (request: Request) => Promise<Response>;
POST: (request: Request) => Promise<Response>;
DELETE: (request: Request) => Promise<Response>;
}| Param | Type | Required | Description |
|---|---|---|---|
| options.manifest | LuxoChatManifest | Required | Product identity, surfaces, actions, starter prompts, model routes, and (v0.2+) i18n dictionary for every user-facing string the route emits. |
| options.authenticate | (req) => Promise<LuxoRouteAuthResult | null> | Optional | Resolve the actor from the request. Return null to deny. Required when requireAuth is true (default). |
| options.requireAuth | boolean | Optional | Defaults to true. When false, anonymous calls are allowed and a synthetic tenantId is used. |
| options.complete | LuxoComplete | Optional | Buffered completion. Defaults to createEnvLuxoComplete using the manifest's model routes and process env keys. |
| options.streamComplete | LuxoStreamComplete | Optional | Added in v0.3.0. When provided AND the client sends 'Accept: text/event-stream', the route returns a ReadableStream of SSE events (start / text / done / error). Set both complete and streamComplete to let clients choose by Accept header. |
| options.persistence | LuxoPersistenceAdapter | Optional | Hook to load/save conversations and messages. Each method is independently optional. Use createSupabaseLuxoPersistence for the reference Supabase shape. |
| options.quota | LuxoQuotaAdapter | Optional | Per-actor quota check. Return { allowed: false } to surface a 429 with quota details. The client also receives this snapshot via the optional 'quota' prop to gate sends pre-flight. |
| options.onGatewayEvent | (event) => void | Promise<void> | Optional | Forwarded to the underlying gateway when using createEnvLuxoComplete / createEnvLuxoStreamComplete. |
| options.onActionsProposed | (ctx) => void | Promise<void> | Optional | Added in v0.7.0. Fires after parseLuxoResponseDirectives extracts `!>` action directives from the assistant response. Receives { actor, actions, conversationId, pathname, requestId, surfaceId }. Wire to recordLuxoAction({ status: "proposed" }) from @luxoai-dev/observability. Best-effort: errors are logged and swallowed. |
| options.siteUrl | string | () => string | undefined | Optional | Trusted origin for same-origin checks. Defaults to NEXT_PUBLIC_SITE_URL / SITE_URL / DOMAIN_URL. |
Returns
{ GET, POST, DELETE }
// app/api/luxo/chat/route.ts
import { createLuxoChatRoute } from "@luxoai-dev/luxo-assistant/server";
import { getActorFromRequest } from "@/lib/auth";
const chat = createLuxoChatRoute({
manifest: {
serviceId: "support-assistant",
productName: "Support Inbox",
audience: "support agents",
domain: "customer support",
defaultSurface: {
key: "ticket",
label: "Ticket triage",
shortLabel: "Triage",
accentLabel: "Support",
summary: "Triage a ticket and recommend the next safest step.",
tooltip: "Ask Luxo about this ticket",
paths: ["/tickets"],
},
},
authenticate: async (req) => {
const actor = await getActorFromRequest(req);
return actor ? { actor } : null;
},
});
export const GET = chat.GET;
export const POST = chat.POST;
export const DELETE = chat.DELETE;