Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,14 @@ lhci/
*.key
*.crt
*.cert
*.p12
*.pfx
*.mobileprovision
# Signing identities are sometimes kept base64'd so they can be pasted into a
# CI secret. That strips the extension the rules above catch, which left a
# Developer ID p12 sitting untracked and unignored in the repo root.
*-signing.b64
*signing*.b64

# =============================================================================
# Project Specific
Expand Down
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ bun run dev

# Build
bun run build # Frontend build (tsc + vite)
bun tauri build # Full production app
bun run tauri:build # Full production app (loads ~/.tauri/juno.key for updater signing)
bun run build:universal # Universal macOS binary

# Testing
Expand Down
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,10 @@ lto = "thin"
codegen-units = 1
panic = "abort"
strip = true

# `block` 0.1.6 (unmaintained, pulled in by cocoa/objc) trips the
# `uninhabited_static` future-incompat lint that will become a hard error
# (rust-lang/rust#74840). vendor/block is the same crate with a one-line fix.
# Remove once cocoa/objc are migrated to objc2 + block2.
[patch.crates-io]
block = { path = "vendor/block" }
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ bun test # Frontend (Vitest)
cargo test --manifest-path src-tauri/Cargo.toml # Backend

# Build
bun tauri build # Production app
bun run tauri:build # Production app (signed updater artifacts)
```

See [CLAUDE.md](CLAUDE.md) for detailed development rules and architecture docs.
Expand Down
979 changes: 516 additions & 463 deletions bun.lock

Large diffs are not rendered by default.

190 changes: 98 additions & 92 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@
"dev": "vite",
"build": "tsc && vite build",
"precommit:docs-guard": "bash scripts/check-no-root-md.sh",
"build:universal": "bun run tauri build --target universal-apple-darwin",
"build:universal": "bash scripts/tauri-build.sh --target universal-apple-darwin",
"preview": "vite preview",
"generate-constants": "node scripts/generate-ts-constants.js",
"prebuild": "npm run generate-constants",
"tauri": "tauri",
"tauri:dev": "tauri dev",
"tauri:build": "bash scripts/tauri-build.sh",
"tauri:dev:multi": "node scripts/dev-multi-instance.js",
"tauri:dev:instance2": "node scripts/dev-multi-instance.js --port=1422",
"tauri:dev:instance3": "node scripts/dev-multi-instance.js --port=1424",
Expand All @@ -40,121 +41,122 @@
"test:watch": "vitest"
},
"dependencies": {
"@hookform/resolvers": "^5.1.1",
"@icons-pack/react-simple-icons": "^13.1.0",
"@radix-ui/react-accordion": "^1.2.11",
"@radix-ui/react-alert-dialog": "^1.1.14",
"@radix-ui/react-aspect-ratio": "^1.1.7",
"@radix-ui/react-avatar": "^1.1.10",
"@radix-ui/react-checkbox": "^1.3.2",
"@radix-ui/react-collapsible": "^1.1.11",
"@radix-ui/react-context-menu": "^2.2.15",
"@radix-ui/react-dialog": "^1.1.14",
"@radix-ui/react-dropdown-menu": "^2.1.15",
"@radix-ui/react-hover-card": "^1.1.14",
"@radix-ui/react-label": "^2.1.7",
"@radix-ui/react-menubar": "^1.1.15",
"@radix-ui/react-navigation-menu": "^1.2.13",
"@radix-ui/react-popover": "^1.1.14",
"@radix-ui/react-progress": "^1.1.7",
"@radix-ui/react-radio-group": "^1.3.7",
"@radix-ui/react-scroll-area": "^1.2.9",
"@radix-ui/react-select": "^2.2.5",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slider": "^1.3.5",
"@radix-ui/react-slot": "^1.2.3",
"@radix-ui/react-switch": "^1.2.5",
"@radix-ui/react-tabs": "^1.1.12",
"@radix-ui/react-toggle": "^1.1.9",
"@radix-ui/react-toggle-group": "^1.1.10",
"@radix-ui/react-tooltip": "^1.2.7",
"@radix-ui/react-use-controllable-state": "^1.2.2",
"@railway/cli": "^4.5.3",
"@react-three/drei": "^9",
"@react-three/fiber": "^8",
"@rive-app/react-webgl2": "^4.27.0",
"@shikijs/transformers": "^3.6.0",
"@shikijs/types": "^3.22.0",
"@streamdown/cjk": "^1.0.2",
"@streamdown/code": "^1.0.2",
"@hookform/resolvers": "^5.9.1",
"@icons-pack/react-simple-icons": "^13.15.1",
"@radix-ui/react-accordion": "^1.2.20",
"@radix-ui/react-alert-dialog": "^1.1.23",
"@radix-ui/react-aspect-ratio": "^1.1.15",
"@radix-ui/react-avatar": "^1.2.6",
"@radix-ui/react-checkbox": "^1.3.11",
"@radix-ui/react-collapsible": "^1.1.20",
"@radix-ui/react-context-menu": "^2.3.7",
"@radix-ui/react-dialog": "^1.1.23",
"@radix-ui/react-dropdown-menu": "^2.1.24",
"@radix-ui/react-hover-card": "^1.1.23",
"@radix-ui/react-label": "^2.1.15",
"@radix-ui/react-menubar": "^1.1.24",
"@radix-ui/react-navigation-menu": "^1.2.22",
"@radix-ui/react-popover": "^1.1.23",
"@radix-ui/react-progress": "^1.1.16",
"@radix-ui/react-radio-group": "^1.4.7",
"@radix-ui/react-scroll-area": "^1.2.18",
"@radix-ui/react-select": "^2.3.7",
"@radix-ui/react-separator": "^1.1.15",
"@radix-ui/react-slider": "^1.4.7",
"@radix-ui/react-slot": "^1.3.3",
"@radix-ui/react-switch": "^1.3.7",
"@radix-ui/react-tabs": "^1.1.21",
"@radix-ui/react-toggle": "^1.1.18",
"@radix-ui/react-toggle-group": "^1.1.19",
"@radix-ui/react-tooltip": "^1.2.16",
"@radix-ui/react-use-controllable-state": "^1.2.6",
"@railway/cli": "^5.52.1",
"@react-three/drei": "^10.7.8",
"@react-three/fiber": "^9.7.0",
"@rive-app/react-webgl2": "^4.34.1",
"@shikijs/transformers": "^4.4.3",
"@shikijs/types": "^4.4.3",
"@streamdown/cjk": "^1.0.3",
"@streamdown/code": "^1.1.1",
"@streamdown/math": "^1.0.2",
"@streamdown/mermaid": "^1.0.2",
"@tailwindcss/vite": "^4.1.3",
"@tauri-apps/api": "^2.11.0",
"@tailwindcss/vite": "^4.3.3",
"@tauri-apps/api": "^2.11.1",
"@tauri-apps/plugin-autostart": "^2.5.1",
"@tauri-apps/plugin-global-shortcut": "^2.3.1",
"@tauri-apps/plugin-notification": "^2.3.3",
"@tauri-apps/plugin-opener": "^2.5.4",
"@tauri-apps/plugin-global-shortcut": "^2.3.2",
"@tauri-apps/plugin-notification": "^2.4.0",
"@tauri-apps/plugin-opener": "^2.5.5",
"@tauri-apps/plugin-process": "^2.3.1",
"@tauri-apps/plugin-store": "^2.4.3",
"@tauri-apps/plugin-updater": "^2.10.1",
"@xyflow/react": "^12.10.0",
"ai": "^6.0.86",
"@tauri-apps/plugin-store": "^2.4.4",
"@tauri-apps/plugin-updater": "^2.11.0",
"@xyflow/react": "^12.11.6",
"ai": "^7.0.97",
"ansi-to-react": "^6.2.6",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"cmdk": "^1.1.1",
"date-fns": "^4.1.0",
"cn": "^0.2.6",
"date-fns": "^4.4.0",
"embla-carousel-react": "^8.6.0",
"framer-motion": "^12.23.0",
"input-otp": "^1.4.2",
"lucide-react": "^0.564.0",
"media-chrome": "^4.17.2",
"motion": "^12.34.0",
"nanoid": "^5.1.6",
"framer-motion": "^13.2.0",
"input-otp": "^1.5.0",
"lucide-react": "^1.45.0",
"media-chrome": "^4.19.2",
"motion": "^13.2.0",
"nanoid": "^6.0.1",
"next-themes": "^0.4.6",
"radix-ui": "^1.4.3",
"react": "^18.3.1",
"react-day-picker": "^9.7.0",
"react-dom": "^18.3.1",
"radix-ui": "^1.6.7",
"react": "^19.3.0",
"react-day-picker": "^10.0.1",
"react-dom": "^19.3.0",
"react-fast-marquee": "^1.6.5",
"react-hook-form": "^7.57.0",
"react-hook-form": "^7.87.0",
"react-jsx-parser": "^2.4.1",
"react-markdown": "^10.1.0",
"react-resizable-panels": "^3.0.2",
"react-router-dom": "^7.15.0",
"recharts": "^2.15.3",
"react-resizable-panels": "^4",
"react-router-dom": "^7.18.3",
"recharts": "^3.10.1",
"remark-gfm": "^4.0.1",
"shiki": "^3.22.0",
"sonner": "^2.0.5",
"streamdown": "^2.2.0",
"tailwind-merge": "^3.2.0",
"shiki": "^4.4.3",
"sonner": "^2.0.8",
"streamdown": "^2.6.0",
"tailwind-merge": "^3.6.0",
"tauri-plugin-voice-transcription-api": "file:tauri-plugin-voice-transcription/api",
"three": "^0.183.2",
"three": "^0.186.0",
"tokenlens": "^1.3.1",
"tw-animate-css": "^1.2.5",
"use-stick-to-bottom": "^1.1.3",
"tw-animate-css": "^1.4.0",
"use-stick-to-bottom": "^1.1.6",
"vaul": "^1.1.2",
"zod": "^3.25.57"
"zod": "^4.6.2"
},
"devDependencies": {
"@lacymorrow/shipx": "^0.1.2",
"@tauri-apps/cli": "^2.11.1",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@types/node": "^22.14.1",
"@types/react": "^18.3.1",
"@types/react-dom": "^18.3.1",
"@types/three": "^0.183.1",
"@vitejs/plugin-react": "^4.7.0",
"autoprefixer": "^10.4.21",
"jsdom": "^26.1.0",
"postcss": "^8.5.3",
"tailwindcss": "^4.1.3",
"terser": "^5.43.1",
"typescript": "~5.6.2",
"vite": "^6.4.3",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.2.7"
"@lacymorrow/shipx": "^0.1.19",
"@tauri-apps/cli": "^2.11.4",
"@testing-library/jest-dom": "^7.0.1",
"@testing-library/react": "^16.3.3",
"@types/node": "^22.20.2",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"@types/three": "^0.185.4",
"@vitejs/plugin-react": "^6.1.1",
"autoprefixer": "^10.5.6",
"jsdom": "^30.0.1",
"postcss": "^8.5.28",
"tailwindcss": "^4.3.3",
"terser": "^5.51.2",
"typescript": "^7.0.2",
"vite": "^8.3.0",
"vite-tsconfig-paths": "^6.1.1",
"vitest": "^5.0.0"
},
"trustedDependencies": [
"@tailwindcss/oxide",
"esbuild"
],
"optionalDependencies": {
"@rollup/rollup-darwin-arm64": "^4.42.0",
"@tauri-apps/cli-darwin-arm64": "^2.11.1",
"lightningcss-darwin-arm64": "^1.30.1"
"@rollup/rollup-darwin-arm64": "^4.63.1",
"@tauri-apps/cli-darwin-arm64": "^2.11.4",
"lightningcss-darwin-arm64": "^1.33.0"
},
"funding": [
{
Expand All @@ -165,5 +167,9 @@
"type": "individual",
"url": "https://www.buymeacoffee.com/lm"
}
]
],
"overrides": {
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0"
}
}
2 changes: 1 addition & 1 deletion src-tauri/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ cargo check --manifest-path src-tauri/Cargo.toml # CRITICAL: Run after every Ru
cargo build --manifest-path src-tauri/Cargo.toml # Build backend
cargo test --manifest-path src-tauri/Cargo.toml # Run tests
bun run tauri dev # Full app development
bun run tauri build # Build production app
bun run tauri:build # Build production app (see scripts/tauri-build.sh)
```

## Architecture
Expand Down
24 changes: 24 additions & 0 deletions src-tauri/mcp-server-os-level/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
fn main() {
// The test binary links Swift-backed system frameworks that reference
// @rpath/libswift_Concurrency.dylib. Library link args do not reach the
// final binary (see src-tauri/build.rs, which does the same for the app),
// so without this `cargo test --workspace` aborts in dyld before any test
// runs. The plain form covers this crate's test binaries and does not propagate to dependents.
#[cfg(target_os = "macos")]
{
println!("cargo::rustc-link-arg=-Wl,-rpath,/usr/lib/swift");

if let Ok(output) = std::process::Command::new("xcode-select")
.arg("-p")
.output()
{
if output.status.success() {
let dev_path = String::from_utf8_lossy(&output.stdout).trim().to_string();
println!(
"cargo::rustc-link-arg=-Wl,-rpath,{}/usr/lib/swift/macosx",
dev_path
);
}
}
}
}
2 changes: 2 additions & 0 deletions src-tauri/src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub mod safari_tools;
pub mod agent_continuation;
pub mod agent_sessions; // Parallel agent-session registry commands (LAC-1432)
pub mod always_listening;
pub mod auto_grant; // Post-Accessibility auto-grant of remaining permission toggles
pub mod bar_position; // Floating-bar last-well persistence
pub mod cloud;
pub mod cloud_test;
Expand Down Expand Up @@ -107,6 +108,7 @@ pub use self::enhanced_visual_reasoning_commands::{
pub use self::error_recovery::*;
pub use self::filesystem::{get_file_content, list_files, save_agent_response, set_file_content};
// Floating bar functionality fully migrated to ui_commands.rs - no longer needed
pub use self::auto_grant::*;
pub use self::mcp::*;
pub use self::memory::*;
pub use self::mouse::*;
Expand Down
6 changes: 3 additions & 3 deletions src-tauri/src/commands/onboarding_guidance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,9 +121,9 @@ fn find_system_settings_window_bounds() -> Option<(f64, f64, f64, f64)> {
}

/// Wait up to `timeout_ms` for the System Settings window to be findable via AX.
/// Polls every 150ms.
/// Polls every 150ms. Shared with the auto-grant flow (`commands::auto_grant`).
#[cfg(target_os = "macos")]
async fn wait_for_settings_window(timeout_ms: u64) -> Option<(f64, f64, f64, f64)> {
pub(crate) async fn wait_for_settings_window(timeout_ms: u64) -> Option<(f64, f64, f64, f64)> {
let deadline = std::time::Instant::now() + Duration::from_millis(timeout_ms);
loop {
// Run the AX call on a blocking thread to avoid stalling the async runtime
Expand All @@ -142,7 +142,7 @@ async fn wait_for_settings_window(timeout_ms: u64) -> Option<(f64, f64, f64, f64
}

#[cfg(not(target_os = "macos"))]
async fn wait_for_settings_window(_timeout_ms: u64) -> Option<(f64, f64, f64, f64)> {
pub(crate) async fn wait_for_settings_window(_timeout_ms: u64) -> Option<(f64, f64, f64, f64)> {
None
}

Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/constants/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,8 @@ pub mod permissions {
pub const REQUEST_INPUT_MONITORING_PERMISSION: &str =
"request_input_monitoring_permission_native";
pub const TEST_MICROPHONE_FUNCTIONALITY: &str = "test_microphone_functionality";
pub const AUTO_GRANT_PERMISSIONS: &str = "auto_grant_permissions";
pub const CANCEL_AUTO_GRANT: &str = "cancel_auto_grant";
}

/// Utility command names
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/constants/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ pub mod permissions {
pub const GUIDANCE_NEEDED: &str = "permission-guidance-needed";
/// Emitted when a specific permission flips from denied → granted during polling
pub const GRANTED: &str = "permission-granted";
/// Streamed progress of the post-Accessibility auto-grant run (auto_grant_permissions)
pub const AUTO_GRANT_PROGRESS: &str = "permissions-auto-grant-progress";
}

/// Development tool events
Expand Down
2 changes: 2 additions & 0 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,8 @@ pub fn run() {
// Phase C: guided cursor flight to System Settings + permission demos
commands::guide_to_system_settings,
commands::run_permission_demo,
commands::auto_grant_permissions,
commands::cancel_auto_grant,
// Phase D: onboarding analytics (local buffer; no external network)
commands::record_onboarding_event,
commands::get_last_onboarding_phase,
Expand Down
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ function App() {

{/* Main Content */}
<div className="flex-1 min-h-0">
<ResizablePanelGroup direction="horizontal">
<ResizablePanelGroup orientation="horizontal">
{/* Primary Content Panel */}
<ResizablePanel defaultSize={appState.isDevPanelOpen ? 70 : 100}>
<div className="flex flex-col h-full">
Expand Down
2 changes: 1 addition & 1 deletion src/components/ChatMessageV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ type RiskLevel = "low" | "medium" | "high" | "critical";

const RISK_CONFIG: Record<
RiskLevel,
{ label: string; className: string; Icon: React.ElementType }
{ label: string; className: string; Icon: React.ComponentType<{ className?: string }> }
> = {
low: {
label: "Low risk",
Expand Down
Loading