mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 18:44:45 +00:00
feat(hermes-v12): version-aware capability detection (Phase A)
Introduces `HermesCapabilities` (parsed from `hermes --version`) and a
per-server `HermesCapabilitiesStore` injected into Mac `ContextBoundRoot`
and iOS `ScarfGoTabRoot` via `.environment(_:)` and `.hermesCapabilities`.
Subsequent v0.12-targeted UI (Curator, Kanban, ACP image input,
auxiliary.curator, prompt cache TTL, etc.) can branch on these flags so
older Hermes installs degrade silently instead of throwing on unknown CLI
subcommands.
Adds `curatorReportJSON` / `curatorReportMD` paths to `HermesPathSet`.
Bumps the Hermes version target in CLAUDE.md from v2026.4.23 (v0.11.0) to
v2026.4.30 (v0.12.0) and lists the v0.12 surfaces Scarf will consume.
Side fixes:
- `M5FeatureVMTests.ScriptedTransport` was missing
`cachedSnapshotPath` after that property was added in 7b864d7;
added `URL? { nil }` stub.
- `M0dViewModelsTests` referenced `.degraded(reason:)` after the case
gained `hint` + `cause`; updated.
- `RemoteBackupService.zipDirectory` and `RemoteRestoreService.unzipArchive`
used `Foundation.Process` unconditionally, breaking the iOS build
(Process is unavailable on iOS). Wrapped in `#if !os(iOS)` with iOS
stubs that throw — the backup/restore flow is Mac-only by design.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,29 @@ struct ScarfGoTabRoot: View {
|
||||
/// through here.
|
||||
@State private var coordinator = ScarfGoCoordinator()
|
||||
|
||||
/// Hermes version + capability flags for this remote. Drives the
|
||||
/// iOS version banner (v0.11 hosts get a yellow "update for new
|
||||
/// features" banner) and capability-gated affordances like ACP
|
||||
/// image attachments. Constructed once per server connection so
|
||||
/// the detection runs over the active SSH transport.
|
||||
@State private var capabilities: HermesCapabilitiesStore
|
||||
|
||||
init(
|
||||
serverID: ServerID,
|
||||
config: IOSServerConfig,
|
||||
key: SSHKeyBundle,
|
||||
onSoftDisconnect: @escaping @MainActor () async -> Void,
|
||||
onForget: @escaping @MainActor () async -> Void
|
||||
) {
|
||||
self.serverID = serverID
|
||||
self.config = config
|
||||
self.key = key
|
||||
self.onSoftDisconnect = onSoftDisconnect
|
||||
self.onForget = onForget
|
||||
let ctx = config.toServerContext(id: serverID)
|
||||
_capabilities = State(initialValue: HermesCapabilitiesStore(context: ctx))
|
||||
}
|
||||
|
||||
/// SwiftUI's `.onChange(of: ScenePhase)` modifier on a non-active
|
||||
/// tab doesn't fire while the tab is unmounted — the coordinator
|
||||
/// is the single source of truth for scene-phase transitions
|
||||
@@ -118,6 +141,8 @@ struct ScarfGoTabRoot: View {
|
||||
.tabViewStyle(.sidebarAdaptable)
|
||||
.environment(\.serverContext, ctx)
|
||||
.environment(\.scarfGoCoordinator, coordinator)
|
||||
.environment(capabilities)
|
||||
.hermesCapabilities(capabilities)
|
||||
.onAppear {
|
||||
// Give the notification router a handle to this session's
|
||||
// coordinator so notification-taps can route across tabs.
|
||||
|
||||
Reference in New Issue
Block a user