Message Management
SwiftyAI uses ChatMessage for chat history. A message has a role, text content, optional multimodal parts, an id, and a creation date.
| Type | Role |
|---|---|
ChatMessage | One visible or model-sent message |
ChatRole | .system, .user, or .assistant |
AIMessageContent | Text, image, PDF, file, audio, or video prompt parts |
ContextWindow | Approximate token budgeting for messages |
maxMessages | Simple history pruning for chat helpers |
Text Messages
let messages = [
ChatMessage(role: .system, content: "Answer like a support engineer."),
ChatMessage(role: .user, content: "Why did my export fail?")
]
for try await chunk in model.stream(messages: messages) {
print(chunk.text, terminator: "")
}Roles are .system, .user, and .assistant.
Multimodal Messages
let message = ChatMessage(
role: .user,
parts: [
.text("Explain this screenshot."),
.imageData(imageData, mediaType: .png, detail: .high)
]
)content and parts stay synchronized. Text-only parts are joined into content; setting content replaces parts with a single .text value.
Built-In Chat Limits
AIChat and SwiftyChat accept maxMessages.
let chat = AIChat(
model: "openai/gpt-4o-mini",
systemPrompt: "Be concise.",
maxMessages: 20
)The visible message array stays in state, but the history sent to the model is pruned.
Context Estimates
let context = ContextWindow(maxTokens: 16_000)
if context.isNearLimit(for: chat.messages) {
print("Consider summarizing older messages.")
}The estimator uses a simple character-based approximation and assigns a fixed estimate to non-text parts. It is good for warnings, not exact billing.
| Strategy | Use |
|---|---|
maxMessages | Keep the most recent turns for simple chats |
ContextWindow warning | Show UI warnings before the context gets too large |
| Manual summarization | Replace older turns with a summary when long sessions matter |
| Provider tokenizers | Use when billing-exact token counts are required |