13-iPhone-App
๐ฑ
iPhone-first SwiftUI client. Clean, fast, modern. Drives off the same REST + SSE API that the web console uses.
1. Targets
- Platform: iOS 17+, iPhone only (no iPad split-view in v1).
- Language: Swift 5.10 / Swift 6 ready.
- UI: SwiftUI.
- Architecture: MVVM with
@Observableview models + Swift Concurrency.
- Package management: Swift Package Manager.
- CI: Xcode Cloud or GitHub Actions with
xcodebuild.
2. App structure
AgentWorkspace/
App/
AgentWorkspaceApp.swift
RootView.swift
Core/
APIClient.swift
SSEClient.swift
KeychainStore.swift
Environment.swift
Formatters.swift
Models/
Project.swift
AgentRun.swift
AgentEvent.swift
WorkspaceFile.swift
Snapshot.swift
ServerParams.swift
Features/
Auth/
LoginView.swift
LoginViewModel.swift
Projects/
ProjectsListView.swift
ProjectDetailView.swift
NewRun/
NewRunView.swift
RunDetail/
RunDetailView.swift
ConsoleListView.swift
EventRowView.swift
RunDetailViewModel.swift
FileChanges/
FileChangesView.swift
DiffView.swift
Snapshots/
SnapshotsView.swift
Docs/
DocsBrowserView.swift
ProjectMapView.swift
SchemaView.swift
DiagramsView.swift
Settings/
SettingsView.swift
Design/
Theme.swift
Badges.swift
Pills.swift3. Screens
Login
- Server URL field (prefilled from
iphone.api_base_url).
- Personal access token field (paste from clipboard supported).
- "Remember on this device" toggle โ stores token in Keychain.
- Logout from Settings.
Projects
- Vertical list: project name, status pill, last run time, Git status badge, RAG index status badge.
- Pull-to-refresh.
- Tap โ Project Detail.
- button โ connect new project (URL + name + default branch).
Project Detail
- Header: name, repo, branch, framework + language.
- Sections: Recent runs, Open runs, Snapshots, Docs shortcut.
- Actions: Pull latest, Re-index RAG, New run.
New Agent Task
- Project (locked if entered from project context).
- Title (required, slugged).
- Prompt (multiline, autosaved as draft).
- Agent picker (Architect, Backend, Frontend, iPhone, RAG, QA, DevOps, Documentation).
- Model picker (filtered by selected agent's allowed providers).
- Toggles: RAG ON/OFF, Safe Mode ON/OFF.
- Start button โ creates run + navigates to Run Detail.
Run Detail (the hero screen)
- Header (see
12 โ Console Log UIยง3).
- Tabs: Console | Files | Snapshots | Summary.
- Console: live SSE feed (see Console spec for everything).
- Pause / Resume / Cancel buttons (state-aware enabling).
- If
waiting_for_user: an input panel slides up.
File Changes
- List of changed files (path, action chip, +/โ line counts).
- Tap โ DiffView (unified diff viewer with monospaced font, syntax-tinted lines, before/after toggle).
- Per-file actions: Approve, Reject (writes to run metadata; final approval handled at run level too).
- Restore-from-snapshot CTA (jumps to Snapshots).
Snapshots
- List grouped by type (pre_run, pre_command, manual, final).
- Each: timestamp, description, Git commit short hash.
- Actions: Restore, Compare with current.
Documentation
- Tabs: Project Map | Database Schema | Architecture Diagrams | Changelog.
- Project Map: searchable table with virtualized rows.
- Database Schema: collapsible by table.
- Diagrams: Mermaid rendered via a WKWebView with
mermaid.min.jsbundled.
- Changelog: list of run entries with diff inlines.
Settings
- API base URL.
- Default model and agent.
- Notification preferences (run state changes via APNs, v1.1).
- Safe Mode default.
- RAG default.
- Logout.
- About (version, build, server health).
4. API client (Swift)
actor APIClient {
var baseURL: URL
var token: String
func get<T: Decodable>(_ path: String, query: [String: String] = [:]) async throws -> T
func post<T: Decodable, B: Encodable>(_ path: String, body: B) async throws -> T
func put<T: Decodable, B: Encodable>(_ path: String, body: B) async throws -> T
func delete(_ path: String) async throws
func stream(_ path: String, lastEventId: String?) -> AsyncThrowingStream<SSEEvent, Error>
}- All responses are camelCase JSON.
- Errors follow RFC 7807 โ decoded into
APIError { type, title, detail, status }.
- 401 โ clear Keychain token and bounce to Login.
5. SSE client
struct SSEClient {
func events(url: URL, token: String, lastEventID: String?) -> AsyncThrowingStream<SSEEvent, Error>
}- Maintains
Last-Event-IDfor reconnects.
- Heartbeats from server ignored at the app layer.
- Backoff schedule: 1s, 2s, 5s, 10s, 30s (cap).
6. State management
- Each feature owns an
@Observableview model.
- View models are constructed by a small DI container
AppContainer(built inAgentWorkspaceApp).
- No global state singletons except
Environment(config) andKeychainStore.
7. Offline / caches
- Projects list cached in SwiftData; re-validated on app foreground.
- Last 200 events per run cached for instant open.
- Diffs cached per file change id (immutable).
8. Notifications (v1.1)
- APNs token registered with backend at
POST /api/devices.
- Backend pushes when a run transitions to
waiting_for_user,failed, orcompleted.
- Tapping a notification deep-links to the run.
9. Accessibility
- Dynamic Type respected throughout.
- VoiceOver labels on every event row (severity + title + relative time).
- Color is never the only signal; icons + text accompany every status.
10. Testing
- Swift Testing for view models.
- Snapshot tests for key views.
- UI tests for: login, start run, observe console, approve diff, restore snapshot.
- A
MockAPIClientreturns canned fixtures for stable tests.