Siti AI — visionOS app
A native SwiftUI chat app for visionOS, built directly on the onde-swift SDK — the same on-device inference engine that powers the Tauri app at the repo root. This is a separate native client, not a Tauri build target; Tauri does not support visionOS.
Project layout and build-target conventions (window sizing, xros/xrsimulator platform settings, App Group entitlements, solid-image-stack app icon) follow the SplitFireAIVision target in the sibling splitfire repo (../splitfire/frontend/xcode/splitfire/SplitFireAI.xcodeproj). The chat engine wiring (streaming bridge, model lifecycle, conversation persistence) follows onde-swift's own Examples/OndeExample app.
Setup
Install XcodeGen if you don't have it:
brew install xcodegen
Generate the Xcode project and open it:
cd xcode
xcodegen generate
open SitiVision.xcodeproj
Set your development team under Signing & Capabilities (defaults to 2TQF86ZACD, the same team as the Tauri app's iOS build — see ../src-tauri/tauri.conf.json), pick a Vision Pro simulator or device, hit Run.
Developing against a local onde-swift checkout
By default project.yml pulls Onde from the published onde-swift releases (from: 1.1.0), the same way src-tauri/Cargo.toml pins onde = "1.1" from crates.io. To iterate against a sibling onde-swift checkout instead — e.g. while adding a new SDK method — point the package at a local path the same way the Rust side's [patch.crates-io] block does:
packages:
Onde:
path: ../../onde-swift
Then, from that onde-swift checkout, build the visionOS slice before regenerating:
make visionos
make visionos needs the sibling onde Rust crate checked out next to onde-swift (ONDE_REPO defaults to ../onde) and a nightly Rust toolchain with -Z build-std, since visionOS is a tier-3 target.
What it does
On first launch, it downloads and loads the platform-default model (Qwen 2.5 3B on visionOS, same tier as macOS) and streams replies token-by-token. Conversations persist locally between launches. The model cache lives in the shared group.com.ondeinference.apps App Group, so a model already downloaded by the Tauri macOS/iOS build of Siti is reused here instead of being fetched twice.
Current MVP feature set (mirrors onde-swift's example app, reskinned for Siti):
- token-by-token streaming with a stop button
- local conversation persistence between launches
- model settings sheet for system prompt + sampling preset
- toolbar actions to reload the model or clear the conversation
- prompt suggestions when the conversation is empty
Not yet done: a real visionOS-native layout (ornaments, volumes, spatial windows) — this MVP is a single glass WindowGroup, functionally equivalent to the iOS/macOS chat view. Immersive-space exploration is a good next step once the 2D chat flow is verified end-to-end.
Files
| File | What's in it |
|---|---|
SitiVisionApp.swift |
Entry point. Calls setupInferenceEnvironment() at launch, sizes the default window. |
ContentView.swift |
The chat UI: header, empty state, message list, input bar, reload/clear actions, settings sheet. |
ChatViewModel.swift |
Bridges UniFFI streaming into Swift concurrency, manages model lifecycle, restores history, persists conversation. |
SitiDefaults.swift |
Siti's system prompt (mirrors ../src-tauri/src/chat/mod.rs's CHAT_SYSTEM_PROMPT), sampling presets, prompt suggestions. |
InferenceEnvironment.swift |
Points HF_HOME/TMPDIR at the shared App Group container so downloads land somewhere visionOS allows and are shared with the Tauri build. |
SitiVision.entitlements |
Generated by xcodegen generate from project.yml's entitlements.properties — do not hand-edit, it's overwritten on every generate. |
project.yml |
XcodeGen spec. SitiVision.xcodeproj is generated from this, not checked in. |