AI generation and proposals
Convert model responses into validated document changes with review, cancellation, conflict handling and undo.
reopt designUpdated
1. From proposal to acceptance
The flow is request, document/selection snapshot, host model call, json-render patch parsing, change validation, before/after preview and user acceptance. Receiving a model response is not permission to persist it.
onAIEdit returns a candidate document or SceneTransaction. The editor previews it separately and checks the starting revision on acceptance. A candidate cannot overwrite edits made while it was being reviewed.
2. Connect the editor callback
Forward AbortSignal through fetch and the model request. The endpoint is implemented by the host, not supplied by the package. Throw on failure so the editor can show the error. Keep authentication, billing and model credentials on the server.
"use client";
import { DeckEditor, type DeckAIRequest } from "@reopt-ai/opt-deck";
import { parseDeckDocument } from "@reopt-ai/opt-deck/server";
async function requestAI(request: DeckAIRequest) {
const { signal, ...payload } = request;
// /api/presentation-ai is an endpoint implemented by your host application.
const response = await fetch("/api/presentation-ai", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
signal,
});
if (!response.ok) throw new Error("Unable to create an AI proposal");
return parseDeckDocument(await response.json());
}
export function AIEditor() {
return <DeckEditor onAIEdit={requestAI} locale="ko" />;
}3. Validate model output
createDeckPrompts returns the system prompt (the deck catalog in json-render's format) and a user prompt carrying the current deck spec. Implement callModel with your chosen host transport. parseDeckReply splits the reply into words and RFC 6902 JSONL patches; applyDeckPatches checks mode, selection, locks and revision and applies them as one undoable change.
Validate authorization, mode, selection IDs and request-size limits at the HTTP boundary. The TypeScript types below do not replace runtime validation of an untrusted request body.
import {
parseDeckDocument, createDeckPrompts, parseDeckReply, applyDeckPatches,
type DeckAIMode,
} from "@reopt-ai/opt-deck/server";
type Model = (input: {
system: string; prompt: string; signal: AbortSignal;
}) => Promise<string>;
// Call after host authentication, authorization and request validation.
export async function createProposal(input: {
document: unknown; selection: string[]; slideId: string;
mode: DeckAIMode; prompt: string;
}, signal: AbortSignal, callModel: Model) {
const document = parseDeckDocument(input.document);
const view = {
mode: input.mode,
slideId: input.slideId,
selection: input.mode === "generate" ? [] : input.selection,
};
// The deck catalog in json-render's prompt format, and the current spec.
const { system, user } = createDeckPrompts(document, {
...view, prompt: input.prompt,
});
const output = await callModel({ system, prompt: user, signal });
signal.throwIfAborted();
// Words, then RFC 6902 JSONL patches in a ```spec fence.
const { patches } = parseDeckReply(output);
return applyDeckPatches(document, patches, {
...view, baseRevision: document.revision,
});
}4. Modes and scope
- generate
- Write a whole deck as a new spec (Deck → Slide, items in props.items) with an empty selection. Written into an existing document, it keeps that document's brand and size.
- rewrite
- Words only: a Slide's title, subtitle and body, its items' title, body and value, notes and a Text's text.
- layout
- Arrangement only: a Slide's layout, tone, variant and composition, object position, size and rotation, slide order and the Deck's design, brand and aspect.
- edit
- Patches that add, replace and remove elements. With a selection, changes outside it and its descendants are rejected.
- Slide / Item
- Slides the engine lays out. They change through their props and props.items; only changed slides are laid out again.
- FreeformSlide / objects
- Hand-made slides: Text, Shape, Image, Group, Chart and Table placed by coordinates, with animations that name objects in playback order. Locked objects and the structure of slides that are not open are refused.
| Item | Behavior and usage |
|---|---|
| generate | Write a whole deck as a new spec (Deck → Slide, items in props.items) with an empty selection. Written into an existing document, it keeps that document's brand and size. |
| rewrite | Words only: a Slide's title, subtitle and body, its items' title, body and value, notes and a Text's text. |
| layout | Arrangement only: a Slide's layout, tone, variant and composition, object position, size and rotation, slide order and the Deck's design, brand and aspect. |
| edit | Patches that add, replace and remove elements. With a selection, changes outside it and its descendants are rejected. |
| Slide / Item | Slides the engine lays out. They change through their props and props.items; only changed slides are laid out again. |
| FreeformSlide / objects | Hand-made slides: Text, Shape, Image, Group, Chart and Table placed by coordinates, with animations that name objects in playback order. Locked objects and the structure of slides that are not open are refused. |
5. Cancellation, conflicts and failures
Cancel obsolete requests and discard late results when the document changes. The default editor checks cancellation and candidate revisions; custom host flows should also isolate requests by account, project and document.
A current spec above 120,000 characters is rejected with a request to select a slide. Replies above 2,000,000 characters are rejected. Hosts may impose smaller model-cost and response-size limits. Keep mocked responses separate from real-model verification.
6. Review design quality
Passing schema validation does not prove factual accuracy or design quality. Review numbers, customer names, sources, text overflow, fonts, brand consistency and unintended deletions before accepting.
When the runtime is ready, the editor fits text in the candidate document. Review real content with the intended fonts and inspect exported files separately.