# LLM Integration Using `generateText` and `generateObject` in patterns. **Important:** These functions can only be called from pattern bodies, not handlers or `computed()`. --- ## generateText Free-form text generation. ```typescript const response = generateText({ prompt: userInput, system: "You are a helpful assistant.", // optional }); // Response: { result: string, error: string, pending: boolean } {ifElse(response.pending, Generating..., ifElse(response.error, Error: {response.error},
{response.result}
) )} ``` --- ## generateObject\ Structured data matching a TypeScript type. Schema is inferred automatically. ```typescript interface ProductIdea { name: string; description: string; price: number; } const idea = generateObject({ prompt: userInput, system: "Generate a product idea.", model: "anthropic:claude-sonnet-4-5", }); // Response: { result: ProductIdea, error: string, pending: boolean } {ifElse(idea.pending, Generating..., ifElse(idea.error, Error: {idea.error},

{idea.result?.name}

{idea.result?.description}

${idea.result?.price}

) )} ``` ### Schema Root Must Be Object Arrays at root fail (OpenAI API requirement). Wrap in object: ```typescript // ❌ Fails generateObject({...}) // ✅ Works interface TodoResponse { todos: TodoItem[]; } generateObject({...}) // Access via result.todos ``` ### Requires `/// ` If you get "schema is required" error, add to file top: ```typescript /// ``` --- ## Handling Pending State ### With ct-loader ```typescript {ifElse( data.pending, Generating...,
{data.result}
)} ``` ### With Elapsed Time and Cancel ```typescript const { result, pending, error, cancel } = generateText({ prompt }); {ifElse( pending, Generating...,
{result}
)} ``` ### Disable Button While Pending ```typescript {ifElse(analysis.pending, "Analyzing...", "Regenerate")} ``` --- ## Processing Arrays Map over items - caching is automatic per-item: ```typescript const summaries = articles.map((article) => ({ article, summary: generateText({ prompt: computed(() => `Summarize: ${article.title}\n${article.content}`), }), })); {summaries.map(({ article, summary }) => (

{article.title}

{ifElse(summary.pending, Summarizing...,

{summary.result}

)}
))} ``` ### Template Strings Require computed() When referencing multiple properties from reactive references: ```typescript // ❌ Fails: reactive references can't be used in template strings directly prompt: `Title: ${article.title}\nContent: ${article.content}` // ✅ Works: defer evaluation with computed() prompt: computed(() => `Title: ${article.title}\nContent: ${article.content}`) ``` --- ## Constraints ### Call From Pattern Body Only ```typescript // ❌ Won't work - handler const myHandler = handler((_, { prompt }) => { const result = generateText({ prompt }); }); // ❌ Won't work - computed() const summary = computed(() => generateText({ prompt })); // ✅ Works - pattern body export default pattern(({ prompt }) => { const result = generateText({ prompt }); return { [UI]:
{result.result}
}; }); ``` ### No Async/Await Results are reactive nodes, not promises: ```typescript // ❌ Don't await const result = await generateText({ prompt }); // ✅ Check pending/error/result const result = generateText({ prompt }); if (!result.pending && !result.error) { // use result.result } ``` --- ## Automatic Caching The framework caches LLM responses by content hash. Don't build custom caching: ```typescript // ❌ Unnecessary - framework handles this const cache = new Map(); if (!cache.has(key)) cache.set(key, generateText({...})); // ✅ Just call directly - caching is automatic const result = generateText({ prompt }); ``` When adding items to an array, only new items trigger LLM requests. --- ## Summary | Function | Returns | Use For | |----------|---------|---------| | `generateText` | `{ result: string, error, pending }` | Free-form text | | `generateObject` | `{ result: T, error, pending }` | Structured data | **Key rules:** - Call from pattern body only - Handle pending/error/result states - Use `computed()` for template strings with reactive references - Schema root must be object (not array)