feat: consolidate iOS with API and web preserving history
Rebuild & Deploy / rebuild (push) Failing after 23s
Rebuild & Deploy / rebuild (push) Failing after 23s
This commit is contained in:
commit
d735ee72fa
102 files changed
+13077
-258
No files matched your search
@@ -0,0 +1,78 @@
|
||||
# Voice — iOS client for Hope Voice
|
||||
|
||||
Native SwiftUI iOS app (iOS 17+) maintained in the [Hope monorepo](https://git.srmr.xyz/snowspeeder/hope-voice-api) under `ios/`: authenticated durable Chats, separate Talk/Activity, account-scoped library and server-managed preferences. Run native commands below from this directory. See [migration/history](../docs/IOS_MONOREPO_MIGRATION.md) and [current status](docs/PROJECT_STATUS.md). The old standalone iOS repository is retained as a read-only archive after verified migration.
|
||||
|
||||
> **Status:** Core functionality is implemented and verified in simulator to the extent the
|
||||
> environment allows. Full device qualification (mic capture, interruption behavior)
|
||||
> remains pending. The native Talk/Activity redesign is implemented —
|
||||
> see [PLAN.md](PLAN.md) and [docs/DEVICE_TESTING.md](docs/DEVICE_TESTING.md).
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Xcode 16+ (Swift 6), iOS 17 simulator or a real iPhone on the LAN.
|
||||
- [xcodegen](https://github.com/yonaskolb/XcodeGen) (`brew install xcodegen`).
|
||||
- The `voice` container running on Unraid (LiveKit + token server).
|
||||
- Mic: the simulator mic is unreliable in this environment (CoreAudio `-4010`, 0 input
|
||||
channels) — voice mode needs a real device. If the simulator was wiped, grant permission
|
||||
first: `xcrun simctl privacy booted grant microphone dev.shane.voice`.
|
||||
|
||||
## Build & run
|
||||
|
||||
```sh
|
||||
xcodegen generate # regenerate Voice.xcodeproj after file changes
|
||||
xcodebuild -project Voice.xcodeproj -scheme Voice_iOS \
|
||||
-destination 'generic/platform=iOS Simulator' build
|
||||
```
|
||||
|
||||
The scheme is **`Voice_iOS`** (not `Voice`). Bundle id: `dev.shane.voice`.
|
||||
To run in the simulator, use Xcode or `xcrun simctl` with the built app.
|
||||
|
||||
## Server configuration
|
||||
|
||||
Default base URL is `https://192.168.86.2:9178` (see `Sources/App/SettingsStore.swift`).
|
||||
Change it at runtime in **Settings → Server URL** (the app disconnects and recreates the
|
||||
session when idle). The app derives the LiveKit signaling endpoint from this base URL.
|
||||
|
||||
### TLS cert pinning
|
||||
|
||||
The deployment uses a persistent self-signed cert. The entrypoint regenerates it if
|
||||
missing or issued for a different IP. The pinned SHA-256 in
|
||||
`Sources/Networking/TLSPinning.swift` must match after any actual cert rotation:
|
||||
|
||||
```sh
|
||||
openssl s_client -connect 192.168.86.2:9178 </dev/null 2>/dev/null \
|
||||
| openssl x509 -outform der | openssl dgst -sha256
|
||||
```
|
||||
|
||||
Paste the new hash into `TLSPinning.pinnedCertSHA256Hex`. Until you do, token calls
|
||||
fail with a pin mismatch (not a network error).
|
||||
|
||||
## Features
|
||||
|
||||
- **Conversation** — LiveKit room with the Hope agent; voice mode (mic + TTS) and text mode
|
||||
(composer), toggleable and persisted. State machine (idle/connecting/listening/thinking/
|
||||
speaking) driven by audio levels, with a compact status indicator and mic meter.
|
||||
- **Transcripts** — partials updated in place, finals with timestamps, delivery-marker
|
||||
stripping, last-50 history persisted to UserDefaults, clear button.
|
||||
- **Voice & model pickers** — 13 Azure TTS voices; LLM models from the agent's `models`
|
||||
message. Both persist and sync on join (`set_voice`/`set_model`).
|
||||
- **Activity tab** — live `task_event` updates (steps, result, error) with an active
|
||||
count badge on the tab.
|
||||
|
||||
## Known limitations
|
||||
|
||||
- **Simulator mic**: CoreAudio returns `-4010` (no usable input source) in this environment;
|
||||
voice capture must be verified on a real device. Text mode works in the simulator.
|
||||
- **Cert pin rotation**: see above — re-export the pin after each server cert regeneration.
|
||||
- **LiveKit signaling** uses plain `ws://192.168.86.2:7880` (not wss) because the Swift SDK
|
||||
cannot trust the self-signed cert on its WebSocket; token calls still go over pinned TLS.
|
||||
|
||||
## Docs
|
||||
|
||||
- [docs/PROJECT_STATUS.md](docs/PROJECT_STATUS.md) — current handoff, decisions, and remaining work; read first.
|
||||
- [docs/ENGINEERING_LEARNINGS.md](docs/ENGINEERING_LEARNINGS.md) — regression invariants, diagnostic lessons, and deployment safeguards.
|
||||
- [docs/VERIFICATION.md](docs/VERIFICATION.md) — test evidence and remaining qualification.
|
||||
- [docs/DEPLOYMENT.md](docs/DEPLOYMENT.md) — live NAS configuration and rollback.
|
||||
- [PLAN.md](PLAN.md) — phase-by-phase progress, verified facts, open items.
|
||||
- [docs/DEVICE_TESTING.md](docs/DEVICE_TESTING.md) — real-device qualification checklist.
|
||||
- [UPDATE_PATH.md](UPDATE_PATH.md) — original plan & protocol reference (read-only).
|
||||
Reference in new issue
Block a user