๐Ÿ“ฑ

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 @Observable view 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.swift

3. 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.js bundled.
  • 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-ID for reconnects.
  • Heartbeats from server ignored at the app layer.
  • Backoff schedule: 1s, 2s, 5s, 10s, 30s (cap).

6. State management

  • Each feature owns an @Observable view model.
  • View models are constructed by a small DI container AppContainer (built in AgentWorkspaceApp).
  • No global state singletons except Environment (config) and KeychainStore.

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, or completed.
  • 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 MockAPIClient returns canned fixtures for stable tests.