Skip to content

Make the Tauri frontend handle workspace file links and views properly #107

@ElioNeto

Description

@ElioNeto

Issue imported from tinyhumansai/openhuman#1402
Created at: unknown


Summary

Make the Tauri frontend render, hyperlink, and open workspace-backed files and views properly, so local workspace content behaves like a first-class desktop surface instead of a mix of plain text, Obsidian-only links, and browser-only anchors.

Problem

As a follow-on to the sandbox/workspace isolation work, the desktop UI also needs a clean contract for interacting with the workspace.

Today the frontend has a few useful pieces, but they do not add up to a general workspace-file UX:

  • openUrl() can hand URLs to the OS through tauri-plugin-opener, which is good for external links and custom schemes (app/src/utils/openUrl.ts).
  • the conversations markdown renderer explicitly only allows http:, https:, and mailto: links (app/src/pages/conversations/utils/format.ts:53-61).
  • AgentMessageBubble routes markdown anchors through that allowlist, so file:, workspace-relative, and other local-link patterns are not first-class clickable targets (app/src/pages/conversations/components/AgentMessageBubble.tsx:57-75).
  • the Memory tab has bespoke Obsidian launch helpers (obsidian://open?...) for the vault and summary nodes, but those are one-off flows rather than a general workspace-link system (app/src/components/intelligence/MemoryWorkspace.tsx:58-79, app/src/components/intelligence/MemoryGraph.tsx:132-156).
  • there is a Tauri command to reveal the logs folder, which shows the shell can already open a local directory in Finder / Explorer / xdg-open, but there is no equivalent generic workspace-file or workspace-folder open/reveal surface (app/src-tauri/src/file_logging.rs:121-133).

This leaves several UX gaps:

  • if the agent references a workspace file in markdown, the user cannot reliably click it and open it in the right local handler
  • if a surface is “hosting” workspace content in the webview, it is unclear when links should stay in-app vs. open in the OS vs. reveal in the file manager
  • the desktop app has no single contract for opening a workspace file, revealing its parent folder, or previewing safe text/markdown content inside the app
  • link behavior is fragmented across chat, Memory, and Tauri-native helper flows

Examples of current fragmentation:

  • chat markdown treats local/workspace links as invalid because the external-href allowlist rejects them
  • Memory graph can open summaries in Obsidian, but not through a more general “open this workspace file” route
  • logs folder can be revealed via a dedicated Tauri command, but this pattern is not generalized for arbitrary workspace paths

This becomes more important once workspace security/isolation is strengthened: if the app tells the user “this file exists in the workspace” or “the agent changed this file,” the desktop UX needs a safe, intentional way to open and inspect it.

Solution

Add a unified workspace-link and workspace-file interaction layer for the Tauri desktop app.

UX goals

  • Workspace file references in rendered markdown should become intentional hyperlinks instead of inert text.
  • The app should support three distinct actions for local workspace paths:
    • open — launch the file with the system/default handler or approved app flow
    • reveal — open Finder / Explorer / file manager at the parent folder and select or focus the file when possible
    • preview — render safe text/markdown content inside the app/webview when appropriate
  • Link behavior should be consistent across chat bubbles, Memory surfaces, settings/dev tooling, and any future workspace-aware UI.

Implementation direction

  1. Define a workspace-link contract
  • Introduce a typed frontend notion of a “workspace link” instead of treating everything as an external URL string.
  • Support at least:
    • workspace-relative file paths
    • workspace directories
    • memory-tree content files
    • explicit external URLs
    • custom app deep links (Obsidian, etc.)
  • Decide, per link type, whether it should preview in-app, reveal in file manager, or open via the OS handler.
  1. Add Tauri commands for workspace path interaction
  • Generalize the reveal_logs_folder pattern into reusable commands like:
    • reveal a workspace path in Finder / Explorer / file manager
    • open a workspace file with the default handler
    • return a safe preview payload for text/markdown files inside the workspace
  • All of these should validate the resolved path stays inside the workspace before opening anything.
  1. Upgrade markdown/link rendering in chat
  • Extend the conversations renderer so it can recognize workspace-local link patterns instead of only http/https/mailto.
  • Keep external URL handling via openUrl(), but route workspace links through the new workspace-link handlers.
  • Preserve explicit separation between trusted local links and arbitrary untrusted file:// or path-like text.
  1. Improve workspace-hosted views
  • When the app is viewing workspace content in a browser/webview context, ensure embedded links are rewritten or intercepted correctly:
    • workspace markdown links should navigate through the desktop workspace-link layer
    • external web links should still open externally
    • custom deep-link schemes should continue to route via the OS handler
  • Avoid broken anchors that look clickable but do nothing.
  1. Reuse the Memory tab patterns, but generalize them
  • The existing Obsidian helpers in MemoryWorkspace / MemoryGraph should sit on top of the shared workspace-link layer rather than being their own standalone path logic.
  • If a summary/file can be opened in Obsidian, revealed in the file manager, or previewed in-app, the shared layer should decide which affordance to show.

Suggested rollout

Phase 1

  • Add generic Tauri commands for open_workspace_path, reveal_workspace_path, and safe text/markdown preview.
  • Add path validation and logging.

Phase 2

  • Upgrade chat markdown/link rendering to support workspace links.
  • Add a reusable WorkspaceLink / WorkspaceFileLink component in the frontend.

Phase 3

  • Migrate Memory tab / developer panels / any existing local-path affordances onto the shared layer.
  • Add richer in-app preview where it improves flow.

Acceptance criteria

  • Workspace links are first-class — the desktop app has a shared link/path handling layer for workspace-local content instead of scattered one-off openers.

  • Chat can open local workspace references — rendered conversation content can hyperlink intentional workspace file references and route them through Tauri-safe handlers.

  • Open / reveal / preview are distinct — the UI can open a workspace file, reveal it in the file manager, or preview supported content in-app, depending on the action and file type.

  • Memory surfaces use the shared layer — Memory tab links (including current Obsidian flows) build on the same workspace-link contract instead of bespoke handlers.

  • Path safety is enforced — workspace path actions validate that resolved paths remain inside the active workspace before opening or previewing anything.

  • Broken-looking links are removed — clickable UI for workspace files either works reliably or is not rendered as an active hyperlink.

  • Cross-platform desktop behavior is documented — macOS, Windows, and Linux behavior for open/reveal flows is explicit where platform differences matter.

  • Regression safety — add/update tests for frontend link parsing/rendering plus Tauri command coverage for open/reveal/preview flows.

  • Diff coverage ≥ 80% — the implementing PR meets the changed-lines coverage gate (Vitest + cargo-llvm-cov, enforced by .github/workflows/coverage.yml).

  • Example verify-before-close scenario: the agent references a workspace markdown file in chat, the user clicks it in the Tauri app, and the app can correctly preview it in-app, reveal it in Finder/Explorer, or open it in the configured handler without breaking navigation or leaving the link inert.

Related

  • Follow-on to workspace security/isolation: Make sandboxed agents use real OS-enforced workspace isolation tinyhumansai/openhuman#1401
  • URL opener helper: app/src/utils/openUrl.ts
  • External-link allowlist in chat formatting: app/src/pages/conversations/utils/format.ts
  • Chat markdown anchor handling: app/src/pages/conversations/components/AgentMessageBubble.tsx
  • Memory workspace Obsidian opener: app/src/components/intelligence/MemoryWorkspace.tsx
  • Memory graph summary opener: app/src/components/intelligence/MemoryGraph.tsx
  • Existing Tauri folder reveal example: app/src-tauri/src/file_logging.rs

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNet-new user-facing capability or product behavior.react-uiReact app work in app/src: pages, components, providers, store, and UX.tauri-shellDesktop host work in app/src-tauri: windowing, relay, sidecar lifecycle.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions