AIChat
AIChat is a @MainActor and @Observable chat state object. It manages input, messages, loading state, errors, cancellation, and streaming assistant updates.
| Public state or config | Meaning |
|---|---|
messages | Visible chat history owned by the helper |
input | Editable user input bound to a text field |
isLoading | True while the assistant stream is active |
error | Last stream or model error |
Constructor maxMessages | Private limit for history sent to the model |
State Model
@State private var chat = AIChat(
model: "openai/gpt-4o-mini",
systemPrompt: "You are a helpful support assistant.",
maxMessages: 30,
options: GenerationOptions(temperature: 0.3)
)Sending
chat.input = "How do I reset my API key?"
chat.send()send() ignores empty input and ignores duplicate sends while a stream is already running. It clears input, appends the user message, appends an empty assistant message, then fills that assistant message as chunks arrive.
View Example
struct SupportChatView: View {
@State private var chat = AIChat(model: "openai/gpt-4o-mini")
var body: some View {
VStack {
ScrollView {
LazyVStack(alignment: .leading) {
ForEach(chat.messages) { message in
Text(message.content)
.frame(maxWidth: .infinity, alignment: message.role == .user ? .trailing : .leading)
}
}
}
HStack {
TextField("Ask support", text: $chat.input)
Button(chat.isLoading ? "Stop" : "Send") {
chat.isLoading ? chat.stop() : chat.send()
}
}
if let error = chat.error {
Text(error.localizedDescription)
.foregroundStyle(.red)
}
}
}
}Reset And Limits
reset() cancels any active stream, clears messages, clears input, and clears the error. maxMessages prunes the history sent to the model, while keeping the visible messages array as app state.
chat.stop()
chat.reset()Use maxMessages for simple chat apps. For advanced token budgeting, combine manual history management with ContextWindow.