Add Nostr Feed Manager: Rust backend with Electron + React GUI

- Rust library (nostr-manager-backend) with CLI and JSON-lines IPC serve mode:
  profiles, publishing with per-relay reports, relays, settings, vault storage
  and legacy-vault migration
- Electron + React + TypeScript desktop GUI using the same backend over stdio IPC
- Vitest suite with a fake backend speaking the real protocol
- electron-builder linux packaging; README with build and usage instructions
This commit is contained in:
Avi 2026-08-03 16:05:59 -05:00
commit 7e3bac345c
68 changed files with 18262 additions and 0 deletions

60
nostr_feed_manager.py Normal file
View file

@ -0,0 +1,60 @@
import subprocess
import json
import os
import sys
from typing import Dict, Any, Optional
# Path to your Rust binary (adjust if you move it)
RUST_BINARY = "/home/avi/Projects/skills/nost-feed-manager/target/release/nostr-manager-backend"
class NostrFeedManager:
"""
A skill for Hermes to manage multiple Nostr profiles.
"""
def __init__(self):
self.vault_file = "/home/avi/Projects/skills/nost-feed-manager/profiles_vault.json"
def _run_rust_command(self, command: str, args: list) -> str:
"""Executes the Rust binary."""
# Ensure the Rust binary exists
if not os.path.exists(RUST_BINARY):
return f"Error: Rust binary not found at {RUST_BINARY}. Please compile it first."
cmd = [RUST_BINARY, command] + args
try:
# Set the environment variable for the Rust binary if needed
env = os.environ.copy()
result = subprocess.run(cmd, capture_output=True, text=True, timeout=10, env=env)
if result.returncode == 0:
return result.stdout.strip()
else:
return f"Error: {result.stderr.strip()}"
except Exception as e:
return f"Execution Error: {str(e)}"
def create_profile(self, label: str) -> str:
"""Create a new Nostr profile."""
return self._run_rust_command("create", [label])
def list_profiles(self) -> str:
"""List all managed profiles."""
return self._run_rust_command("list", [])
def switch_profile(self, npub: str) -> str:
"""Switch the active profile context."""
return self._run_rust_command("switch", [npub])
def publish_action(self, profile_npub: str, content: str, is_private: bool = False, recipient: Optional[str] = None) -> str:
"""Publish a post or DM."""
args = [profile_npub, content, str(is_private).lower()]
if is_private and recipient:
args.append(recipient)
return self._run_rust_command("publish", args)
# Export the class so Hermes can import it if running as a module
if __name__ == "__main__":
# Simple CLI test
manager = NostrFeedManager()
print("Nostr Feed Manager Skill Loaded.")
print("Usage: manager.create_profile('Name')")