rho-cli 0.1.25

Rho CLI tools for encrypted agent collaboration, dataset publishing, controlled runs, and result release workflows
Documentation
import React from "react";
import ReactDOM from "react-dom/client";
import { invoke } from "@tauri-apps/api/core";
import App from "./App";
import "./styles.css";

const ISSUES_URL = "https://github.com/madhavajay/rho/issues/new";

async function reportFromCrash() {
  // The crash itself is already auto-captured by Sentry (the boundary re-throws to
  // the global handler). This adds a screenshot to the clipboard + opens an issue.
  try {
    const { default: html2canvas } = await import("html2canvas-pro");
    const canvas = await html2canvas(document.body, {
      backgroundColor: null,
      logging: false,
      scale: Math.min(window.devicePixelRatio || 1, 2)
    });
    const blob = await new Promise<Blob | null>((resolve) =>
      canvas.toBlob((value) => resolve(value), "image/png")
    );
    if (blob && typeof ClipboardItem !== "undefined" && navigator.clipboard?.write) {
      await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]);
    }
  } catch {
    // capture is best-effort
  }
  // window.open is a no-op in the Tauri webview; use the native opener command.
  void invoke("open_external_url", { url: ISSUES_URL }).catch(() => {});
}

type BoundaryState = { error: Error | null };

class ErrorBoundary extends React.Component<{ children: React.ReactNode }, BoundaryState> {
  state: BoundaryState = { error: null };

  static getDerivedStateFromError(error: Error): BoundaryState {
    return { error };
  }

  componentDidCatch(error: Error) {
    // React boundaries swallow the throw, so it never reaches window.onerror
    // where the auto-injected Sentry browser handler lives. Re-throw on a
    // macrotask so Sentry still captures the crash while we show a fallback.
    window.setTimeout(() => {
      throw error;
    }, 0);
  }

  render() {
    if (this.state.error) {
      return (
        <main className="app-shell desktop-wallpaper">
          <section className="crash-screen">
            <h1>Something went wrong</h1>
            <p>
              The app hit an unexpected error and it was reported to Sentry automatically. You can
              also open a GitHub issue (a screenshot is copied to your clipboard to paste in).
            </p>
            <pre>{this.state.error.message}</pre>
            <div className="crash-actions">
              <button
                type="button"
                className="primary-action"
                onClick={() => window.location.reload()}
              >
                Reload app
              </button>
              <button type="button" onClick={() => void reportFromCrash()}>
                Report this
              </button>
            </div>
          </section>
        </main>
      );
    }
    return this.props.children;
  }
}

ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
  <React.StrictMode>
    <ErrorBoundary>
      <App />
    </ErrorBoundary>
  </React.StrictMode>
);