mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-08 02:14:37 +00:00
feat(memory): hermes memory reset toolbar action + v0.11 CLI doc (Phase 5)
Adopt the lowest-risk new CLI subcommand from Hermes v2026.4.23 — `hermes memory reset --yes` — and document the deferred ones for v2.6. Wholesale plugin/profile/webhook/logs adoption is forward- compatible work the existing services don't block on; deferring keeps v2.5 scope tight. MemoryView: - Toolbar button "Reset memory…" with .arrow.counterclockwise icon. - Confirmation dialog explaining the destructive semantics (no undo, wipes both MEMORY.md and USER.md). Routes through context.runHermes(["memory", "reset", "--yes"]); on non-zero exit shows the stderr in an alert. Refreshes the on-screen content on success. CLAUDE.md: - "Hermes Version" section now leads with v2026.4.23 (v0.11.0) and enumerates the v2.5-adopted features (slash steer, state.db deltas, new skills, frontmatter chips, memory reset) with file pointers. v2.6-deferred CLIs (plugins / profile / webhook / insights / logs) are flagged so future bandwidth knows where to pick up. Verified: Mac build clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -84,7 +84,16 @@ Public documentation lives in the GitHub wiki at https://github.com/awizemann/sc
|
||||
|
||||
## Hermes Version
|
||||
|
||||
Targets Hermes v0.10.0 (v2026.4.16). Log lines may carry an optional `[session_id]` tag between the level and logger name — `HermesLogService.parseLine` treats the session tag as an optional capture group, so older untagged lines still parse.
|
||||
Targets Hermes v2026.4.23 (v0.11.0). Log lines may carry an optional `[session_id]` tag between the level and logger name — `HermesLogService.parseLine` treats the session tag as an optional capture group, so older untagged lines still parse.
|
||||
|
||||
**v2026.4.23 (v0.11.0)** added (Scarf-relevant subset):
|
||||
|
||||
- `/steer <prompt>` — non-interruptive mid-run guidance slash command. Surfaced in Scarf chat menus via `RichChatViewModel.nonInterruptiveCommands`; `ChatViewModel.sendViaACP` (Mac) and `ChatController.send` (iOS) skip the "Agent working…" status flip and show a transient toast instead.
|
||||
- New CLI subcommands: `hermes plugins` / `profile` / `webhook` / `insights` / `logs` / `memory reset` / `completion` / `dashboard`. Scarf v2.5 adopts **`hermes memory reset`** (toolbar button on MemoryView with destructive confirmation). The other CLIs are documented here for v2.6 — Scarf still reads `~/.hermes/plugins/`, `~/.hermes/profiles/` etc directly today; switching those paths to the canonical CLI is a forward-compatible change to make when bandwidth permits.
|
||||
- New state.db columns: `messages.reasoning_content` + `sessions.api_call_count`. `HermesDataService.detectSchema` flips `hasV011Schema` only when both are present (partial migrations stay on v0.7 path). Surfaced as the "API" chip on session rows + a network-icon counter in DashboardView. `HermesMessage.preferredReasoning` picks the newer column when both reasoning channels are populated.
|
||||
- New skills: `design-md` (Google's DESIGN.md authoring; needs `npx`/Node 18+ on host — checked via `SkillPrereqService` and surfaced as a yellow banner) and `spotify` (OAuth via `hermes auth spotify` — driven by `SpotifyAuthFlow` + `SpotifySignInSheet`, mirroring v2.3 Nous Portal pattern).
|
||||
- Updated skills: `research-paper-writing` 1.1.0 (+SciencePlots dep), `segment-anything-model` (expanded docs), `google-workspace` (gws CLI prefer + granular OAuth scopes), `hermes-agent` (in-tree).
|
||||
- SKILL.md frontmatter gains `allowed_tools` / `related_skills` / `dependencies` lists. `HermesSkill` carries them as optional fields; `SkillsView` (Mac) + `SkillDetailView` (iOS) render them as chip rows when populated.
|
||||
|
||||
v0.10.0 introduced the **Tool Gateway** — paid Nous Portal subscribers route web search, image generation, TTS, and browser automation through their subscription without separate API keys. In Scarf:
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ import ScarfCore
|
||||
|
||||
struct MemoryView: View {
|
||||
@State private var viewModel: MemoryViewModel
|
||||
@State private var showResetConfirm: Bool = false
|
||||
@State private var resetError: String?
|
||||
@Environment(HermesFileWatcher.self) private var fileWatcher
|
||||
|
||||
init(context: ServerContext) {
|
||||
@@ -61,6 +63,56 @@ struct MemoryView: View {
|
||||
.sheet(isPresented: $viewModel.isEditing) {
|
||||
editorSheet
|
||||
}
|
||||
.toolbar {
|
||||
// v2.5: `hermes memory reset` (Hermes v2026.4.23+) wipes
|
||||
// both MEMORY.md and USER.md atomically — useful when a
|
||||
// session went off the rails. Destructive, confirmation-
|
||||
// gated, surfaced as a small toolbar button rather than
|
||||
// a prominent button to avoid accidental clicks.
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
Button {
|
||||
showResetConfirm = true
|
||||
} label: {
|
||||
Label("Reset memory…", systemImage: "arrow.counterclockwise")
|
||||
}
|
||||
.help("Reset MEMORY.md and USER.md to empty (Hermes v2026.4.23+)")
|
||||
}
|
||||
}
|
||||
.confirmationDialog(
|
||||
"Reset memory?",
|
||||
isPresented: $showResetConfirm,
|
||||
titleVisibility: .visible
|
||||
) {
|
||||
Button("Reset", role: .destructive) {
|
||||
resetMemoryRemotely()
|
||||
}
|
||||
Button("Cancel", role: .cancel) {}
|
||||
} message: {
|
||||
Text("Wipes MEMORY.md and USER.md to empty via `hermes memory reset --yes`. The agent's accumulated knowledge for this server is gone immediately. Use this when a session went off the rails — there's no undo.")
|
||||
}
|
||||
.alert("Couldn't reset memory", isPresented: Binding(
|
||||
get: { resetError != nil },
|
||||
set: { if !$0 { resetError = nil } }
|
||||
)) {
|
||||
Button("OK") { resetError = nil }
|
||||
} message: {
|
||||
Text(resetError ?? "")
|
||||
}
|
||||
}
|
||||
|
||||
/// Run `hermes memory reset --yes` over the active context's
|
||||
/// transport. Refreshes the on-screen content on success; surfaces
|
||||
/// stderr in an alert on failure.
|
||||
private func resetMemoryRemotely() {
|
||||
let result = viewModel.context.runHermes(["memory", "reset", "--yes"])
|
||||
if result.exitCode == 0 {
|
||||
viewModel.load()
|
||||
} else {
|
||||
let trimmed = result.output.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
resetError = trimmed.isEmpty
|
||||
? "hermes memory reset exited with status \(result.exitCode)."
|
||||
: trimmed
|
||||
}
|
||||
}
|
||||
|
||||
private func memorySection(_ title: String, content: String, charCount: Int, target: MemoryViewModel.EditTarget) -> some View {
|
||||
|
||||
Reference in New Issue
Block a user