From 5366063cd2406ecb3f99b396af385d5ce711f8f2 Mon Sep 17 00:00:00 2001 From: krypticmouse Date: Thu, 26 Mar 2026 21:29:55 +0000 Subject: [PATCH] feat: add openjarvis:// deep link handler for Tauri MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Registers the openjarvis:// URL scheme via the Tauri 2 deep-link plugin in tauri.conf.json. Adds frontend/src/lib/deep-link.ts with parseDeepLink() that parses openjarvis://{type}/{id} URLs into structured DeepLinkTarget objects (e.g. openjarvis://research/abc123 → {type:"research", id:"abc123"}). Co-Authored-By: Claude Sonnet 4.6 --- desktop/src-tauri/tauri.conf.json | 5 +++ frontend/src/lib/deep-link.ts | 61 +++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 frontend/src/lib/deep-link.ts diff --git a/desktop/src-tauri/tauri.conf.json b/desktop/src-tauri/tauri.conf.json index 0fac08e3..d1b31e23 100644 --- a/desktop/src-tauri/tauri.conf.json +++ b/desktop/src-tauri/tauri.conf.json @@ -62,6 +62,11 @@ "endpoints": [ "https://github.com/open-jarvis/OpenJarvis/releases/download/desktop-latest/latest.json" ] + }, + "deep-link": { + "desktop": { + "schemes": ["openjarvis"] + } } } } diff --git a/frontend/src/lib/deep-link.ts b/frontend/src/lib/deep-link.ts new file mode 100644 index 00000000..c30cf035 --- /dev/null +++ b/frontend/src/lib/deep-link.ts @@ -0,0 +1,61 @@ +/** + * deep-link.ts — Handler for openjarvis:// deep links in the Tauri desktop app. + * + * The Tauri deep-link plugin routes custom-scheme URLs to the frontend. + * This module parses those URLs and extracts structured navigation targets + * so the UI can respond (e.g. open a research session, navigate to a connector). + * + * Supported URL formats: + * openjarvis://research/{session_id} → open a research session + * openjarvis://connector/{connector_id} → open a connector settings panel + */ + +export interface DeepLinkTarget { + /** The resource type extracted from the URL path (e.g. "research", "connector"). */ + type: string; + /** The resource identifier (e.g. a session ID or connector name). */ + id: string; +} + +/** + * Parse an `openjarvis://` deep link URL into a structured target. + * + * @param url - The raw deep link URL string (e.g. `openjarvis://research/abc123`). + * @returns A {@link DeepLinkTarget} if the URL is valid, or `null` if it + * cannot be parsed or does not use the `openjarvis:` scheme. + * + * @example + * parseDeepLink("openjarvis://research/abc123"); + * // → { type: "research", id: "abc123" } + * + * parseDeepLink("openjarvis://connector/gmail"); + * // → { type: "connector", id: "gmail" } + * + * parseDeepLink("https://example.com"); + * // → null + */ +export function parseDeepLink(url: string): DeepLinkTarget | null { + try { + const parsed = new URL(url); + if (parsed.protocol !== "openjarvis:") return null; + + // The URL constructor treats "openjarvis://research/abc123" such that + // parsed.hostname === "research" and parsed.pathname === "/abc123". + // We also handle the double-slash form where both end up in pathname. + const parts = parsed.pathname.replace(/^\/\//, "").split("/").filter(Boolean); + + // If the path part is empty but hostname is set, use hostname as type + // and the first path segment as id. + if (parsed.hostname && parts.length >= 1) { + return { type: parsed.hostname, id: parts[0] }; + } + + if (parts.length >= 2) { + return { type: parts[0], id: parts[1] }; + } + + return null; + } catch { + return null; + } +}