diff --git a/crates/buckaroo-tauri/build.rs b/crates/buckaroo-tauri/build.rs
index a3eadc0..f9d7693 100644
--- a/crates/buckaroo-tauri/build.rs
+++ b/crates/buckaroo-tauri/build.rs
@@ -5,7 +5,10 @@
/// Hosts opt in via `"buckaroo:default"` in their capability file.
const COMMANDS: &[&str] = &[
"buckaroo_health",
+ "buckaroo_diagnostics",
"buckaroo_load_path",
+ "buckaroo_load_expr",
+ "buckaroo_load_compare",
"buckaroo_send",
"buckaroo_pick_file",
];
diff --git a/crates/buckaroo-tauri/permissions/autogenerated/commands/buckaroo_diagnostics.toml b/crates/buckaroo-tauri/permissions/autogenerated/commands/buckaroo_diagnostics.toml
new file mode 100644
index 0000000..478672d
--- /dev/null
+++ b/crates/buckaroo-tauri/permissions/autogenerated/commands/buckaroo_diagnostics.toml
@@ -0,0 +1,13 @@
+# Automatically generated - DO NOT EDIT!
+
+"$schema" = "../../schemas/schema.json"
+
+[[permission]]
+identifier = "allow-buckaroo-diagnostics"
+description = "Enables the buckaroo_diagnostics command without any pre-configured scope."
+commands.allow = ["buckaroo_diagnostics"]
+
+[[permission]]
+identifier = "deny-buckaroo-diagnostics"
+description = "Denies the buckaroo_diagnostics command without any pre-configured scope."
+commands.deny = ["buckaroo_diagnostics"]
diff --git a/crates/buckaroo-tauri/permissions/autogenerated/commands/buckaroo_load_compare.toml b/crates/buckaroo-tauri/permissions/autogenerated/commands/buckaroo_load_compare.toml
new file mode 100644
index 0000000..a64e900
--- /dev/null
+++ b/crates/buckaroo-tauri/permissions/autogenerated/commands/buckaroo_load_compare.toml
@@ -0,0 +1,13 @@
+# Automatically generated - DO NOT EDIT!
+
+"$schema" = "../../schemas/schema.json"
+
+[[permission]]
+identifier = "allow-buckaroo-load-compare"
+description = "Enables the buckaroo_load_compare command without any pre-configured scope."
+commands.allow = ["buckaroo_load_compare"]
+
+[[permission]]
+identifier = "deny-buckaroo-load-compare"
+description = "Denies the buckaroo_load_compare command without any pre-configured scope."
+commands.deny = ["buckaroo_load_compare"]
diff --git a/crates/buckaroo-tauri/permissions/autogenerated/commands/buckaroo_load_expr.toml b/crates/buckaroo-tauri/permissions/autogenerated/commands/buckaroo_load_expr.toml
new file mode 100644
index 0000000..4f09e66
--- /dev/null
+++ b/crates/buckaroo-tauri/permissions/autogenerated/commands/buckaroo_load_expr.toml
@@ -0,0 +1,13 @@
+# Automatically generated - DO NOT EDIT!
+
+"$schema" = "../../schemas/schema.json"
+
+[[permission]]
+identifier = "allow-buckaroo-load-expr"
+description = "Enables the buckaroo_load_expr command without any pre-configured scope."
+commands.allow = ["buckaroo_load_expr"]
+
+[[permission]]
+identifier = "deny-buckaroo-load-expr"
+description = "Denies the buckaroo_load_expr command without any pre-configured scope."
+commands.deny = ["buckaroo_load_expr"]
diff --git a/crates/buckaroo-tauri/permissions/autogenerated/reference.md b/crates/buckaroo-tauri/permissions/autogenerated/reference.md
index 438ccce..a82cfab 100644
--- a/crates/buckaroo-tauri/permissions/autogenerated/reference.md
+++ b/crates/buckaroo-tauri/permissions/autogenerated/reference.md
@@ -1,11 +1,14 @@
## Default Permission
-Default permissions for the buckaroo Tauri plugin. Allows the webview to call all four IPC commands the plugin exposes.
+Default permissions for the buckaroo Tauri plugin. Allows the webview to call every IPC command the plugin exposes.
#### This default permission set includes the following:
- `allow-buckaroo-health`
+- `allow-buckaroo-diagnostics`
- `allow-buckaroo-load-path`
+- `allow-buckaroo-load-expr`
+- `allow-buckaroo-load-compare`
- `allow-buckaroo-send`
- `allow-buckaroo-pick-file`
@@ -18,6 +21,32 @@ Default permissions for the buckaroo Tauri plugin. Allows the webview to call al
+
+|
+
+`buckaroo-tauri:allow-buckaroo-diagnostics`
+
+ |
+
+
+Enables the buckaroo_diagnostics command without any pre-configured scope.
+
+ |
+
+
+
+|
+
+`buckaroo-tauri:deny-buckaroo-diagnostics`
+
+ |
+
+
+Denies the buckaroo_diagnostics command without any pre-configured scope.
+
+ |
+
+
|
@@ -47,6 +76,58 @@ Denies the buckaroo_health command without any pre-configured scope.
|
|
+`buckaroo-tauri:allow-buckaroo-load-compare`
+
+ |
+
+
+Enables the buckaroo_load_compare command without any pre-configured scope.
+
+ |
+
+
+
+|
+
+`buckaroo-tauri:deny-buckaroo-load-compare`
+
+ |
+
+
+Denies the buckaroo_load_compare command without any pre-configured scope.
+
+ |
+
+
+
+|
+
+`buckaroo-tauri:allow-buckaroo-load-expr`
+
+ |
+
+
+Enables the buckaroo_load_expr command without any pre-configured scope.
+
+ |
+
+
+
+|
+
+`buckaroo-tauri:deny-buckaroo-load-expr`
+
+ |
+
+
+Denies the buckaroo_load_expr command without any pre-configured scope.
+
+ |
+
+
+
+|
+
`buckaroo-tauri:allow-buckaroo-load-path`
|
diff --git a/crates/buckaroo-tauri/permissions/default.toml b/crates/buckaroo-tauri/permissions/default.toml
index bde23f5..23db589 100644
--- a/crates/buckaroo-tauri/permissions/default.toml
+++ b/crates/buckaroo-tauri/permissions/default.toml
@@ -1,10 +1,13 @@
"$schema" = "schemas/schema.json"
[default]
-description = "Default permissions for the buckaroo Tauri plugin. Allows the webview to call all four IPC commands the plugin exposes."
+description = "Default permissions for the buckaroo Tauri plugin. Allows the webview to call every IPC command the plugin exposes."
permissions = [
"allow-buckaroo-health",
+ "allow-buckaroo-diagnostics",
"allow-buckaroo-load-path",
+ "allow-buckaroo-load-expr",
+ "allow-buckaroo-load-compare",
"allow-buckaroo-send",
"allow-buckaroo-pick-file",
]
diff --git a/crates/buckaroo-tauri/permissions/schemas/schema.json b/crates/buckaroo-tauri/permissions/schemas/schema.json
index 20e9408..0603c5f 100644
--- a/crates/buckaroo-tauri/permissions/schemas/schema.json
+++ b/crates/buckaroo-tauri/permissions/schemas/schema.json
@@ -294,6 +294,18 @@
"PermissionKind": {
"type": "string",
"oneOf": [
+ {
+ "description": "Enables the buckaroo_diagnostics command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-buckaroo-diagnostics",
+ "markdownDescription": "Enables the buckaroo_diagnostics command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the buckaroo_diagnostics command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-buckaroo-diagnostics",
+ "markdownDescription": "Denies the buckaroo_diagnostics command without any pre-configured scope."
+ },
{
"description": "Enables the buckaroo_health command without any pre-configured scope.",
"type": "string",
@@ -306,6 +318,30 @@
"const": "deny-buckaroo-health",
"markdownDescription": "Denies the buckaroo_health command without any pre-configured scope."
},
+ {
+ "description": "Enables the buckaroo_load_compare command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-buckaroo-load-compare",
+ "markdownDescription": "Enables the buckaroo_load_compare command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the buckaroo_load_compare command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-buckaroo-load-compare",
+ "markdownDescription": "Denies the buckaroo_load_compare command without any pre-configured scope."
+ },
+ {
+ "description": "Enables the buckaroo_load_expr command without any pre-configured scope.",
+ "type": "string",
+ "const": "allow-buckaroo-load-expr",
+ "markdownDescription": "Enables the buckaroo_load_expr command without any pre-configured scope."
+ },
+ {
+ "description": "Denies the buckaroo_load_expr command without any pre-configured scope.",
+ "type": "string",
+ "const": "deny-buckaroo-load-expr",
+ "markdownDescription": "Denies the buckaroo_load_expr command without any pre-configured scope."
+ },
{
"description": "Enables the buckaroo_load_path command without any pre-configured scope.",
"type": "string",
@@ -343,10 +379,10 @@
"markdownDescription": "Denies the buckaroo_send command without any pre-configured scope."
},
{
- "description": "Default permissions for the buckaroo Tauri plugin. Allows the webview to call all four IPC commands the plugin exposes.\n#### This default permission set includes:\n\n- `allow-buckaroo-health`\n- `allow-buckaroo-load-path`\n- `allow-buckaroo-send`\n- `allow-buckaroo-pick-file`",
+ "description": "Default permissions for the buckaroo Tauri plugin. Allows the webview to call every IPC command the plugin exposes.\n#### This default permission set includes:\n\n- `allow-buckaroo-health`\n- `allow-buckaroo-diagnostics`\n- `allow-buckaroo-load-path`\n- `allow-buckaroo-load-expr`\n- `allow-buckaroo-load-compare`\n- `allow-buckaroo-send`\n- `allow-buckaroo-pick-file`",
"type": "string",
"const": "default",
- "markdownDescription": "Default permissions for the buckaroo Tauri plugin. Allows the webview to call all four IPC commands the plugin exposes.\n#### This default permission set includes:\n\n- `allow-buckaroo-health`\n- `allow-buckaroo-load-path`\n- `allow-buckaroo-send`\n- `allow-buckaroo-pick-file`"
+ "markdownDescription": "Default permissions for the buckaroo Tauri plugin. Allows the webview to call every IPC command the plugin exposes.\n#### This default permission set includes:\n\n- `allow-buckaroo-health`\n- `allow-buckaroo-diagnostics`\n- `allow-buckaroo-load-path`\n- `allow-buckaroo-load-expr`\n- `allow-buckaroo-load-compare`\n- `allow-buckaroo-send`\n- `allow-buckaroo-pick-file`"
}
]
}
diff --git a/crates/buckaroo-tauri/src/commands.rs b/crates/buckaroo-tauri/src/commands.rs
index d83cdf1..fb64f24 100644
--- a/crates/buckaroo-tauri/src/commands.rs
+++ b/crates/buckaroo-tauri/src/commands.rs
@@ -48,6 +48,35 @@ pub(crate) struct LoadPathArgs {
/// Requires a `buckaroo[xorq]` install on the sidecar.
#[serde(default)]
pub backend: Option,
+ /// Optional: prompt string echoed back in the initial_state payload,
+ /// used by some hosts for breadcrumb / title chrome. Matches the field
+ /// on `LoadExprArgs`.
+ #[serde(default)]
+ pub prompt: Option,
+ /// Optional: server-side component_config override forwarded verbatim
+ /// into the session's `df_viewer_config.component_config`. Matches the
+ /// field on `LoadExprArgs`.
+ #[serde(default)]
+ pub component_config: Option,
+}
+
+#[derive(Deserialize)]
+pub(crate) struct LoadCompareArgs {
+ /// Path to the "left" dataset (any extension load_file handles).
+ pub path1: String,
+ /// Path to the "right" dataset.
+ pub path2: String,
+ /// Columns to join on. Forwarded verbatim into the server's
+ /// `col_join_dfs(...)` call.
+ pub join_columns: Vec,
+ /// Optional: join kind, forwarded as-is. Server defaults to `"outer"`
+ /// when omitted. Accepts the values pandas merge `how=` accepts.
+ #[serde(default)]
+ pub how: Option,
+ /// `/load_compare` requires a session id (unlike `/load` and
+ /// `/load_expr`, which mint one when omitted). Surface that contract
+ /// at the IPC layer rather than papering over it.
+ pub session: String,
}
#[derive(Deserialize)]
@@ -122,6 +151,12 @@ pub(crate) async fn buckaroo_load_path(
if let Some(b) = &args.backend {
body.as_object_mut().unwrap().insert("backend".into(), serde_json::Value::String(b.clone()));
}
+ if let Some(p) = &args.prompt {
+ body.as_object_mut().unwrap().insert("prompt".into(), serde_json::Value::String(p.clone()));
+ }
+ if let Some(c) = &args.component_config {
+ body.as_object_mut().unwrap().insert("component_config".into(), c.clone());
+ }
let resp = reqwest::Client::new()
.post(format!("http://127.0.0.1:{}/load", port))
@@ -219,6 +254,77 @@ pub(crate) async fn buckaroo_load_expr(
})
}
+/// Diff two files via the sidecar's HTTP `/load_compare` endpoint, then open
+/// the internal WS to that session if not already open. The server runs
+/// `col_join_dfs(df1, df2, join_columns, how)`, stores the merged frame on
+/// the session with diff styling baked into the column config, and pushes
+/// the new state to any connected WS clients.
+///
+/// Unlike `/load` and `/load_expr`, the server requires the caller to
+/// supply a session id — the IPC type makes that non-optional rather than
+/// papering over it. The response carries the per-column equality stats
+/// (`eqs`) the server returns so host UIs can surface "n of N rows equal".
+#[tauri::command]
+pub(crate) async fn buckaroo_load_compare(
+ args: LoadCompareArgs,
+ app: AppHandle,
+ state: tauri::State<'_, SidecarState>,
+) -> Result {
+ let port = state
+ .port
+ .lock()
+ .unwrap()
+ .ok_or_else(|| "sidecar not yet ready".to_string())?;
+
+ let mut body = serde_json::Map::new();
+ body.insert("session".into(), serde_json::Value::String(args.session.clone()));
+ body.insert("path1".into(), serde_json::Value::String(args.path1));
+ body.insert("path2".into(), serde_json::Value::String(args.path2));
+ body.insert(
+ "join_columns".into(),
+ serde_json::Value::Array(
+ args.join_columns
+ .into_iter()
+ .map(serde_json::Value::String)
+ .collect(),
+ ),
+ );
+ if let Some(h) = args.how {
+ body.insert("how".into(), serde_json::Value::String(h));
+ }
+ body.insert("no_browser".into(), serde_json::Value::Bool(true));
+
+ let resp = reqwest::Client::new()
+ .post(format!("http://127.0.0.1:{}/load_compare", port))
+ .json(&serde_json::Value::Object(body))
+ .send()
+ .await
+ .map_err(|e| format!("POST /load_compare failed: {}", e))?;
+
+ let status = resp.status();
+ let text = resp.text().await.map_err(|e| e.to_string())?;
+ if !status.is_success() {
+ return Err(format!("POST /load_compare returned {}: {}", status, text));
+ }
+ let metadata: serde_json::Value = serde_json::from_str(&text)
+ .map_err(|e| format!("invalid JSON from /load_compare: {}", e))?;
+
+ let session_id = metadata
+ .get("session")
+ .and_then(|v| v.as_str())
+ .map(|s| s.to_string())
+ .ok_or_else(|| "load_compare response missing 'session' field".to_string())?;
+ let rows = metadata.get("rows").and_then(|v| v.as_u64());
+
+ supervisor::connect_internal_ws(&app, port, &session_id).await?;
+
+ Ok(LoadResult {
+ session_id,
+ rows,
+ metadata,
+ })
+}
+
/// Fetch the sidecar's server-side diagnostics blob (`GET /diagnostics`).
/// Useful for host UIs that want to surface server version, uptime,
/// installed extras, etc.
diff --git a/crates/buckaroo-tauri/src/lib.rs b/crates/buckaroo-tauri/src/lib.rs
index f23c8e6..2a23293 100644
--- a/crates/buckaroo-tauri/src/lib.rs
+++ b/crates/buckaroo-tauri/src/lib.rs
@@ -51,6 +51,7 @@ pub fn init(config: BuckarooConfig) -> TauriPlugin {
commands::buckaroo_diagnostics,
commands::buckaroo_load_path,
commands::buckaroo_load_expr,
+ commands::buckaroo_load_compare,
commands::buckaroo_send,
commands::buckaroo_pick_file,
])
diff --git a/packages/buckaroo-tauri-adapter/src/TauriIPCModel.ts b/packages/buckaroo-tauri-adapter/src/TauriIPCModel.ts
index 931d840..41696ab 100644
--- a/packages/buckaroo-tauri-adapter/src/TauriIPCModel.ts
+++ b/packages/buckaroo-tauri-adapter/src/TauriIPCModel.ts
@@ -217,7 +217,13 @@ export async function listenForInitialState(): Promise;
+ },
): Promise<{ sessionId: string; rows?: number; metadata: any }> {
return invoke("plugin:buckaroo-tauri|buckaroo_load_path", {
args: { path, ...(opts ?? {}) },
@@ -238,3 +244,25 @@ export async function loadExpr(
args: { build_dir, ...(opts ?? {}) },
});
}
+
+/**
+ * Convenience: trigger the Rust plugin's load_compare command, diffing
+ * two files via the server's `col_join_dfs(...)` and serving the merged
+ * frame with diff styling. The session id is required (unlike loadPath /
+ * loadExpr, where the server mints one when omitted) — the server's
+ * `/load_compare` contract requires it on the caller's side.
+ *
+ * `eqs` on the returned metadata is the per-column equality dictionary
+ * the server computes; host UIs can use it to surface "n of N rows equal"
+ * style summaries.
+ */
+export async function loadCompare(
+ path1: string,
+ path2: string,
+ join_columns: string[],
+ opts: { session: string; how?: string },
+): Promise<{ sessionId: string; rows?: number; metadata: any }> {
+ return invoke("plugin:buckaroo-tauri|buckaroo_load_compare", {
+ args: { path1, path2, join_columns, ...opts },
+ });
+}
diff --git a/packages/buckaroo-tauri-adapter/src/index.ts b/packages/buckaroo-tauri-adapter/src/index.ts
index 902d0a6..22406f5 100644
--- a/packages/buckaroo-tauri-adapter/src/index.ts
+++ b/packages/buckaroo-tauri-adapter/src/index.ts
@@ -4,4 +4,5 @@ export {
listenForInitialState,
loadPath,
loadExpr,
+ loadCompare,
} from "./TauriIPCModel";