spb/zyquo-cloud Public MIT
Native macOS AI chat client for 12 cloud providers — your keys, every cloud model, one beautiful chat.
Swift 97.4%
Shell 1.7%
Makefile 1%
1# Zyquo Cloud — Build Plan23## Phase 0 — Provider Research ✅ (completed 2026-07-30)45- [x] Live-probe `/models` endpoints of all 12 providers with real keys (authoritative current model IDs)6- [x] Live SSE streaming smoke test on all 12 providers (all HTTP 200)7- [x] Web research: official docs for each provider (auth, endpoints, schema, streaming, special params, rate limits, pricing)8- [x] Write `docs/PROVIDERS.md` covering all 12 providers × 8 research points9- [x] Phase checkpoint: PROVIDERS.md complete + summary1011**Phase 0 checkpoint summary:** All 12 providers documented in `docs/PROVIDERS.md` (assembled from12per-provider files in `docs/research/`), each covering the 8 mandatory points, verified against live13probes with real keys — every key authenticated, every provider streamed successfully. Major catalog14churn found vs. training data: DeepSeek → v4-flash/v4-pro only; Mistral deprecates Magistral/Devstral/15Nemo 2026-07-31 (reasoning via `reasoning_effort`); xAI catalog now grok-4.5/4.3/4.20/build; Cerebras16down to 3 models; Perplexity has no `/models` (built-in catalog: sonar, sonar-pro, sonar-reasoning-pro,17sonar-deep-research). Items unverifiable from docs are flagged inline and queued for Phase 7.1819## Phase 1 — Project Setup ✅ (completed 2026-07-30)2021- [x] `Package.swift` — executable targets `ZyquoCloud` + `zyquo-verify`, test target, macOS 13+, swift-markdown dep22- [x] Minimal `@main` SwiftUI app that builds and launches (activation policy handled)23- [x] `Makefile`: `make dev` (release build + assemble `Zyquo Cloud.app` + ad-hoc sign), `make release`24 (universal + Developer ID + notarize skeleton, completed in Phase 8), `scripts/write-info-plist.sh`25- [x] Phase checkpoint: `swift build` clean (0 warnings), `make dev` assembles bundle, app launched via26 `open`, process verified, quit cleanly2728**Phase 1 checkpoint summary:** SPM-only toolchain working on Swift 6.4. `make dev` produces an29ad-hoc-signed `dist/Zyquo Cloud.app` with correct Info.plist (`com.zyquo.cloud`, macOS 13+,30productivity category). Release/notarization targets stubbed to `scripts/notarize.sh` using the31verified zyquo-term identity + `MacLustr-Notarize` profile (implemented fully in Phase 8).3233## Phase 2 — Architecture ✅ (completed 2026-07-30)3435- [x] Models: `ProviderID`, `AIModel`, `ModelCapabilities`, `ModelPricing`, `ParameterSupport`, `Message`, `Conversation`, `Persona`, `PromptTemplate`, `ChatParameters`, `TokenUsage`36- [x] Providers: `ProviderProtocol` (`ChatRequest` → `AsyncThrowingStream<ChatEvent>`), `OpenAICompatibleClient` (11 providers incl. Gemini-compat + custom), `AnthropicClient` (native Messages API), `ProviderRegistry`37- [x] Services: `StreamingService` (SSE parser + URLSession streaming), `ModelCatalog` (+ seed `ModelCatalogData`, full data generated next), `PersistenceService` (JSON in Application Support)38- [x] ViewModels/Views skeleton folders39- [x] Phase checkpoint: builds clean (0 warnings), 10/10 unit tests pass (SSE parser incl. Anthropic40 named events / keep-alive comments / multi-line data; model JSON round-trip; error mapping)4142**Phase 2 checkpoint summary:** Full provider abstraction in place — all quirks (auth headers,43stream_options, max_completion_tokens, enable_thinking, reasoning_content, citations, bare-array44/models) isolated in the two clients. Toolchain note: no Xcode on this machine (CLT only), so tests45use Swift Testing with `scripts/test.sh` wiring the CLT TestingMacros plugin + framework symlinks46(`make test`).4748## Phase 3 — SecureKeyStore ✅ (completed 2026-07-30)4950- [x] AES-256-GCM vault via CryptoKit at `~/Library/Application Support/ZyquoCloud/vault.zq`51- [x] HKDF master key: random salt + IOPlatformUUID (IOKit) + home path + obfuscated compiled-in pepper (XOR-assembled at runtime)52- [x] Vault format `[salt 32B][nonce+ciphertext+tag]`, plaintext JSON dict of provider→key, atomic writes, stable salt across saves53- [x] Round-trip encrypt/decrypt test (phase gate) + tamper test + machine-binding test + plaintext-leak test + no-Keychain sweep (clean)5455**Phase 3 checkpoint summary:** Vault gate passed — 17/17 tests green including encrypt/decrypt56round-trip, GCM tamper detection, cross-machine rejection (injected entropy), salt stability, and57a scan proving no key material or field names appear in the vault file. Zero Keychain/SecItem usage58in the codebase. Keys redact to `••••` + last 4 via `SecureKeyStore.redacted`.5960## Phase 4 — Design System & UI Spec ✅ (completed 2026-07-30)6162- [x] `ZyquoTheme` tokens: full color spec (light flagship + night-sky dark derivation as dynamic63 NSColors), typography scale (title/body 13.5 lh 1.45/caption/code SF Mono), spacing 4–32,64 radii 6/10/14, soft shadow token, layout metrics (sidebar 260, header 52, column 760…), motion tokens65- [x] Reusable components: `ZyquoHairline` (0.5pt), `ZyquoBadge`, `StatusDot`, hover highlight (80ms),66 pressable style (0.97), provider glyphs67- [x] `AppearanceStore`: light/dark/system, 5 accent choices (sky-indigo default), chat font size 12–18 clamped, persisted68- [x] Phase checkpoint: builds clean; tokens are the only color/size source (raw-hex sweep of Views/ViewModels clean)6970**Phase 4 checkpoint summary:** Design system complete per spec; the Phase 4.2 layout spec is the71contract for all Phase 6 UI and the 4.4 quality gate is re-checked before "done". Toolchain: builds72pinned to macOS 26 SDK (`SDKROOT` in Makefile/test.sh) because CLT lacks Xcode's SwiftUIMacros73plugin required by SDK 27's macro-based @State.7475## Phase 5 — App Icon ✅ (completed 2026-07-30)7677- [x] `assets/icon/zyquo-cloud.svg` — white geometric cloud + luminous-beam Z on a true superellipse78 squircle (n=4.6, computed path), sky gradient #82B4FF→#4E6AF0→#3A3F9E, soft top light, two79 distant parallax cloud layers; no SVG filters (CoreSVG-safe)80- [x] Rendered 16→1024 and visually inspected; iterated (lightened sky; small sizes were muddy →81 dedicated `zyquo-cloud-small.svg`: bigger cloud, 86px Z stroke, flat fills — used for 16/32 slots)82- [x] `scripts/generate-icon.sh` → iconset (small variant for ≤64px slots) → `Resources/AppIcon.icns`,83 embedded in the bundle by `make dev`/`release`; rasterizer: `scripts/rasterize-svg.swift` (AppKit)84- [x] Menu bar template glyph `zyquo-cloud-template.svg` (cloud silhouette, Z knocked out via mask) →85 `Resources/MenuBarIcon(@2x).png`; in-app wordmark/empty-state glyph will draw the same geometry86 as a SwiftUI Shape in Phase 68788**Phase 5 checkpoint summary:** Icon is crisp and on-identity at every size (verified visually at891024/512/256/128/64/32/16). SVG sources are the single source of truth in `assets/icon/`.9091## Phase 6 — Features ✅ (completed 2026-07-30; design gate re-checked before Done)9293- [x] Core chat: sidebar (search ⌘F, pin, rename, delete, tags), streaming with stop (⌘.), model picker94 per conversation + per message, message actions (copy/edit&resend/regenerate/delete/quote),95 reasoning display (collapsible), Perplexity citations chips, per-message + per-conversation96 tokens & est. cost, system prompt per conversation + global default, gated parameters editor97- [x] Vision & attachments: image + text-file drag/drop + picker, 56pt thumbnails, dashed drop highlight98- [x] Productivity: 56-template prompt library + user templates ({{input}}), 8 personas + user personas,99 Quick Chat (⌥Space floating panel + "Continue in app"), compare mode (2–4 columns), export100 Markdown/PDF, full-text search, auto-titles via cheapest same-provider model101- [x] macOS polish: ⌘N/⌘K palette/⌘F/⌘↩/⌘⇧E/⌥Space/⌘., menu bar extra (template icon, toggleable),102 empty state per spec103- [x] Model management: 195-model built-in catalog, dynamic /models refresh + catalog diff in Settings,104 custom OpenAI-compatible models (ID + base URL), favorites105- [x] Markdown: full rendering (tables, quotes, lists, links, headings) + code blocks with copy button,106 language label, 11-language syntax highlighter; streaming-safe, memoized107- [x] Checkpoint: builds clean 0 warnings, 26 tests green, app launched + UI visually verified (dark)108109**Phase 6 checkpoint summary:** All Phase 6 features implemented and wired. UI verified running;110light/dark render from the same tokens. End-to-end chat with live keys is exercised in Phase 7.111112## Phase 7 — API Verification ✅ (completed 2026-07-30 — table fully green)113114- [x] Verify harness: app binary gains `--verify` mode reusing the exact production provider clients;115 `zyquo-verify` target execs it (keys via env from .env.keys, never committed); `--load-vault` seeds the GUI vault116- [x] /models diff vs catalog per provider; "OK" completion on every catalog chat model;117 streaming test per provider; vision test per vision-capable provider118- [x] **Final result: 202/202 tests passed** (12 providers, 170 catalog models) — docs/VERIFICATION.md119- [x] Every failure across 3 sweeps fixed, PROVIDERS.md + catalog updated together120121**Phase 7 checkpoint summary:** Live verification caught and fixed real bugs: SSE event separators122dropped by AsyncBytes.lines (all streams hung); async @main breaking GUI task scheduling; a --verify123MainActor deadlock; Together's completions-style `choices[].text` deltas; Mistral's high/none-only124reasoning_effort + ThinkChunk content arrays; Gemini's `models/` ID prefixes; deprecated models125(OpenAI chat-latest generations, Gemini 2.0/3-pro-preview, 18 Together dedicated-only, broken126DeepInfra gemma-4-31B) removed; streaming-only models flagged (`requiresStreaming`); 429/5xx127backoff added. End-to-end GUI chat verified live; auto-title now uses cheapest non-reasoning model.128129## Phase 8 — Signing & Notarization ✅ (completed 2026-07-30)130131- [x] `make release`: universal binary (arm64 + x86_64 via lipo; x86_64 needs `-U` for CLT's132 arm64-only swiftCompatibility56), Developer ID sign (hardened runtime, minimal entitlements),133 notarize app zip + DMG (`MacLustr-Notarize`, both **Accepted**), staple both134- [x] `spctl -a -vv` → **accepted, source=Notarized Developer ID** · `stapler validate` OK ·135 `lipo -archs` → x86_64 arm64 · notarized app launches and quits cleanly136- [x] Gotcha fixed: AMFI rejects XML comments inside the entitlements dict — plist is now comment-free137138**Phase 8 checkpoint summary:** `dist/Zyquo Cloud.app` (signed, notarized, stapled, universal) and139`dist/ZyquoCloud.dmg` (notarized, stapled) ship-ready. Identity140"Developer ID Application: Simon-Pierre Boucher (3YM54G49SN)", profile MacLustr-Notarize.141142---143144## Definition of Done — final sweep (2026-07-30)145146- [x] `make release` → Developer ID-signed, notarized, stapled `Zyquo Cloud.app` (spctl-verified), zero Xcode147- [x] Cloud SVG icon (+ small-size & template variants) striking at all sizes, embedded icns + menu bar template + in-app glyph/wordmark148- [x] Light theme per Phase 4 spec (visually verified), dark derived (visually verified)149- [x] Naming coherent: "Zyquo Cloud" UI, com.zyquo.cloud, ZyquoCloud target/data folder (sweeps clean)150- [x] 12 providers configured; custom AES-GCM vault, zero Keychain usage (sweep clean)151- [x] Verification harness: **202/202 green** across all providers/models with real keys (docs/VERIFICATION.md)152- [x] All Phase 6 features implemented and functional153- [x] Header audit: every code file carries the Author/Mail header (scripts/audit-headers.sh)154- [x] PROVIDERS.md ↔ ModelCatalog in sync (Phase 7 amendments recorded); 27/27 unit tests; zero compiler warnings155## Phase 2 — Architecture (pending)156## Phase 3 — SecureKeyStore (pending)157## Phase 4 — Design System (pending)158## Phase 5 — App Icon (pending)159## Phase 6 — Features (pending)160## Phase 7 — API Verification (pending)161## Phase 8 — Signing & Notarization (pending)162