diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index fd4d01cd6..d78c36820 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -16,7 +16,7 @@ ## Testing - [ ] `yarn -s compile` -- [ ] `cargo check --manifest-path src-tauri/Cargo.toml` +- [ ] `cargo check --manifest-path app/src-tauri/Cargo.toml` - [ ] Other checks run (list commands) - [ ] Manual validation completed (list scenarios) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 99ed92be7..555471715 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -30,7 +30,7 @@ jobs: cache: 'yarn' - name: Install Rust stable - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@1.93.0 with: targets: x86_64-unknown-linux-gnu @@ -44,7 +44,7 @@ jobs: id: cargo-lock-fingerprint shell: bash run: | - echo "hash=$(tail -n +8 src-tauri/Cargo.lock | openssl dgst -sha256 | awk '{print $2}')" >> "$GITHUB_OUTPUT" + echo "hash=$(tail -n +8 Cargo.lock | openssl dgst -sha256 | awk '{print $2}')" >> "$GITHUB_OUTPUT" - name: Cache Cargo registry and git sources uses: actions/cache@v4 @@ -73,16 +73,17 @@ jobs: run: cd skills && yarn install --frozen-lockfile - name: Build sidecar core binary - run: cargo build --manifest-path rust-core/Cargo.toml --release --target x86_64-unknown-linux-gnu --bin openhuman + run: cargo build --manifest-path Cargo.toml --release --target x86_64-unknown-linux-gnu --bin openhuman - name: Stage sidecar for Tauri bundler run: | - mkdir -p src-tauri/binaries - # Workspace root target/ (not rust-core/target/) — see root Cargo.toml [workspace] - cp target/x86_64-unknown-linux-gnu/release/openhuman src-tauri/binaries/openhuman-x86_64-unknown-linux-gnu - chmod +x src-tauri/binaries/openhuman-x86_64-unknown-linux-gnu + mkdir -p app/src-tauri/binaries + # Release artifacts for the root package land in repo root target/ + cp target/x86_64-unknown-linux-gnu/release/openhuman app/src-tauri/binaries/openhuman-x86_64-unknown-linux-gnu + chmod +x app/src-tauri/binaries/openhuman-x86_64-unknown-linux-gnu - name: Build Tauri app + working-directory: app run: | TAURI_CONFIG_OVERRIDE='{"bundle":{"createUpdaterArtifacts":false}}' yarn tauri build -c "$TAURI_CONFIG_OVERRIDE" --bundles none -- --target x86_64-unknown-linux-gnu diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fd68aeb5e..277cec2d5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -79,9 +79,9 @@ jobs: throw new Error(`Invalid release_type: ${releaseType}`); } - const packagePath = 'package.json'; - const tauriPath = 'src-tauri/tauri.conf.json'; - const cargoPath = 'src-tauri/Cargo.toml'; + const packagePath = 'app/package.json'; + const tauriPath = 'app/src-tauri/tauri.conf.json'; + const cargoPath = 'app/src-tauri/Cargo.toml'; const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8')); const match = String(pkg.version || '').match(/^(\d+)\.(\d+)\.(\d+)$/); @@ -119,7 +119,7 @@ jobs: `$1${nextVersion}$3`, ); if (updatedCargo === cargo) { - throw new Error('Failed to update [package].version in src-tauri/Cargo.toml'); + throw new Error('Failed to update [package].version in app/src-tauri/Cargo.toml'); } fs.writeFileSync(cargoPath, updatedCargo); @@ -147,7 +147,7 @@ jobs: VERSION: ${{ steps.bump.outputs.version }} TAG: ${{ steps.bump.outputs.tag }} run: | - git add package.json src-tauri/tauri.conf.json src-tauri/Cargo.toml + git add app/package.json app/src-tauri/tauri.conf.json app/src-tauri/Cargo.toml git commit -m "chore(release): v${VERSION}" git push origin main @@ -244,8 +244,8 @@ jobs: node-version: 24.x cache: yarn - - name: Install Rust stable - uses: dtolnay/rust-toolchain@stable + - name: Install Rust (rust-toolchain.toml) + uses: dtolnay/rust-toolchain@1.93.0 with: targets: ${{ matrix.settings.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }} @@ -260,7 +260,7 @@ jobs: id: cargo-lock-fingerprint shell: bash run: | - echo "hash=$(tail -n +8 src-tauri/Cargo.lock | openssl dgst -sha256 | awk '{print $2}')" >> "$GITHUB_OUTPUT" + echo "hash=$(tail -n +8 Cargo.lock | openssl dgst -sha256 | awk '{print $2}')" >> "$GITHUB_OUTPUT" - name: Cache Cargo registry and git sources uses: actions/cache@v4 @@ -287,7 +287,7 @@ jobs: env: BASE_URL: ${{ vars.BASE_URL }} UPDATER_PUBLIC_KEY: ${{ secrets.UPDATER_PUBLIC_KEY }} - WITH_UPDATER: 'true' + WITH_UPDATER: "true" with: script: | const workspacePath = process.env.GITHUB_WORKSPACE.replace(/\\/g, '/'); @@ -313,12 +313,14 @@ jobs: CORE_DIR="openhuman_core" elif [ -f "rust-core/Cargo.toml" ]; then CORE_DIR="rust-core" + elif [ -f "Cargo.toml" ] && grep -q '^name = "openhuman"' Cargo.toml; then + CORE_DIR="." else - echo "No core Cargo manifest found (expected openhuman_core/Cargo.toml or rust-core/Cargo.toml)" + echo "No core Cargo manifest found (expected root Cargo.toml with openhuman, openhuman_core/Cargo.toml, or rust-core/Cargo.toml)" exit 1 fi - SIDE_CAR_BASE="$(node -e "const fs=require('fs');const c=JSON.parse(fs.readFileSync('src-tauri/tauri.conf.json','utf8'));const b=(c.bundle&&Array.isArray(c.bundle.externalBin)&&c.bundle.externalBin[0])||'binaries/openhuman';process.stdout.write(String(b).split('/').pop());")" + SIDE_CAR_BASE="$(node -e "const fs=require('fs');const c=JSON.parse(fs.readFileSync('app/src-tauri/tauri.conf.json','utf8'));const b=(c.bundle&&Array.isArray(c.bundle.externalBin)&&c.bundle.externalBin[0])||'binaries/openhuman';process.stdout.write(String(b).split('/').pop());")" CORE_BIN_NAME="${SIDE_CAR_BASE}" echo "core_dir=$CORE_DIR" >> "$GITHUB_OUTPUT" @@ -346,9 +348,9 @@ jobs: - name: Stage sidecar for Tauri bundler shell: bash run: | - mkdir -p src-tauri/binaries + mkdir -p app/src-tauri/binaries SOURCE="$CORE_TARGET_DIR/$CORE_BIN_NAME" - DEST="src-tauri/binaries/$SIDECAR_BASE-$MATRIX_TARGET" + DEST="app/src-tauri/binaries/$SIDECAR_BASE-$MATRIX_TARGET" cp "$SOURCE" "$DEST" chmod +x "$DEST" env: @@ -370,9 +372,10 @@ jobs: BASE_URL: ${{ vars.BASE_URL }} TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY || secrets.UPDATER_PRIVATE_KEY }} TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD || secrets.UPDATER_PRIVATE_KEY_PASSWORD }} - WITH_UPDATER: 'true' + WITH_UPDATER: "true" MACOSX_DEPLOYMENT_TARGET: ${{ matrix.settings.platform == 'macos-latest' && '10.15' || '' }} with: + projectPath: app # Tools discovery now uses a JS mock registry (no Rust discovery # binary target), so there is no extra helper executable for Tauri # to copy/sign inside release app bundles. @@ -391,7 +394,7 @@ jobs: if: matrix.settings.platform == 'macos-latest' shell: bash run: | - APP_PATH="src-tauri/target/${{ matrix.settings.target }}/release/bundle/macos/OpenHuman.app" + APP_PATH="target/${{ matrix.settings.target }}/release/bundle/macos/OpenHuman.app" echo "Inspecting bundle at: $APP_PATH" ls -la "$APP_PATH/Contents/MacOS" ls -la "$APP_PATH/Contents/Resources" | grep openhuman || true diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 8d88795ac..2a917b474 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -26,7 +26,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: 24.x - cache: 'yarn' + cache: "yarn" - name: Cache node modules id: yarn-cache @@ -64,8 +64,8 @@ jobs: with: fetch-depth: 1 - - name: Install Rust stable - uses: dtolnay/rust-toolchain@stable + - name: Install Rust (rust-toolchain.toml) + uses: dtolnay/rust-toolchain@1.93.0 with: targets: x86_64-unknown-linux-gnu @@ -91,11 +91,11 @@ jobs: restore-keys: | ${{ runner.os }}-rust-test-cargo- - - name: Test rust-core (openhuman-core) - run: cargo test -p openhuman-core + - name: Test rust-core (openhuman) + run: cargo test -p openhuman - name: Test src-tauri (OpenHuman) - run: cargo test -p OpenHuman + run: cargo test --manifest-path app/src-tauri/Cargo.toml e2e-macos: name: E2E (macOS / Appium) @@ -112,10 +112,10 @@ jobs: uses: actions/setup-node@v4 with: node-version: 24.x - cache: 'yarn' + cache: "yarn" - - name: Install Rust stable - uses: dtolnay/rust-toolchain@stable + - name: Install Rust (rust-toolchain.toml) + uses: dtolnay/rust-toolchain@1.93.0 - name: Install dependencies run: yarn install --frozen-lockfile @@ -124,7 +124,7 @@ jobs: run: cd skills && yarn install --frozen-lockfile - name: Ensure .env exists for E2E build - run: touch .env + run: touch app/.env - name: Install Appium and mac2 driver run: | @@ -134,7 +134,7 @@ jobs: - name: Build E2E app bundle run: yarn test:e2e:build env: - E2E_SKIP_CARGO_CLEAN: '1' + E2E_SKIP_CARGO_CLEAN: "1" - name: Run all E2E flows run: yarn test:e2e:all:flows diff --git a/.github/workflows/typecheck.yml b/.github/workflows/typecheck.yml index 92064cab7..54a17c2ee 100644 --- a/.github/workflows/typecheck.yml +++ b/.github/workflows/typecheck.yml @@ -44,7 +44,7 @@ jobs: run: yarn install --frozen-lockfile - name: Type check TypeScript files - run: npx tsc + run: yarn typecheck env: NODE_ENV: test diff --git a/.gitignore b/.gitignore index 838620ff8..c465bb0da 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ pnpm-debug.log* lerna-debug.log* package-lock.json -yarn.lock node_modules dist @@ -35,7 +34,7 @@ scripts/ci-secrets.local.json *.sln *.sw? references/ -src-tauri/runtime-skill-* +app/src-tauri/runtime-skill-* .mypy_cache .ruff_cache .kotlin diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100644 index e69de29bb..000000000 diff --git a/CLAUDE.md b/CLAUDE.md index e2f279968..778ca0d57 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,520 +1,167 @@ -## Project Summary +# OpenHuman -Cross-platform crypto community communication platform built with **Tauri v2** (React 19 + Rust). Targets desktop (Windows, macOS) and mobile (Android, iOS). Features deep Telegram integration via MTProto, real-time Socket.io communication, V8-based skill execution engine, and an MCP (Model Context Protocol) tool system for AI-driven Telegram interactions. +**AI-powered assistant for crypto communities — React + Tauri v2 desktop app with a Rust core (JSON-RPC / CLI) and sandboxed QuickJS skills.** -## Runtime Scope +This file orients contributors and coding agents. Authoritative narrative architecture: [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md). Frontend layout: [`docs/src/README.md`](docs/src/README.md). Tauri shell: [`docs/src-tauri/README.md`](docs/src-tauri/README.md). -- Tauri host/runtime is desktop-only. -- Always run and validate Tauri codepaths as desktop (`windows`, `macOS`, `linux`). -- Do not add or maintain Android/iOS/web runtime branches inside `src-tauri`. +--- -## App Theme & Design System +## Repository layout -**Design Philosophy**: Premium, sophisticated crypto platform with calm, trustworthy aesthetic. +| Path | Role | +| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`app/`** | Yarn workspace **`openhuman-app`**: Vite + React (`app/src/`), Tauri desktop host (`app/src-tauri/`), Vitest tests | +| **Repo root `src/`** | Rust library **`openhuman_core`** and **`openhuman`** CLI binary (`src/bin/openhuman.rs`) — `core_server`, `openhuman::*` domains, skills runtime (QuickJS / `rquickjs`), MCP routing in the core process | +| **`skills/`** | Skill packages (built into `skills/skills` for bundling) | +| **`Cargo.toml`** (root) | Core crate; `cargo build --bin openhuman` produces the sidecar the UI stages via `app`’s `core:stage` | +| **`docs/`** | Architecture and module guides (numbered pages under `docs/src/`, `docs/src-tauri/`) | -### Color Palette +Commands in documentation assume the **repo root** unless noted: `yarn dev` runs the `app` workspace. -- **Primary**: Ocean blue (`#4A83DD`) optimized for dark backgrounds -- **Sage**: Success green (`#4DC46F`) for growth indicators -- **Amber**: Warning (`#E8A838`) for attention states -- **Coral**: Error (`#F56565`) soft professional red -- **Canvas**: Background layers (`#FAFAF9` to `#D4D4D1`) with subtle warmth -- **Market Colors**: Bullish green, bearish red, Bitcoin orange, Ethereum purple +--- -### Typography +## Runtime scope -- **Primary**: Inter (premium font stack) -- **Display**: Cabinet Grotesk for headings -- **Mono**: JetBrains Mono for code -- **Scale**: Sophisticated sizing with negative letter spacing for elegance +- **Shipped product**: desktop — Windows, macOS, Linux (see [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) “Platform reach”). +- **Tauri host** (`app/src-tauri`): **desktop-only** (`compile_error!` for non-desktop targets). Do not add Android/iOS branches inside `app/src-tauri`. +- **Core binary** (`openhuman`): spawned/staged as a **sidecar**; the Web UI talks to it over HTTP (`core_rpc_relay` + `core_rpc` client), not by re-implementing domain logic in the shell. -### Component System +--- -- **Shadows**: Glow effects, subtle to float depth levels -- **Animations**: Fade-in, slide-in, scale-in with cubic-bezier easing -- **Border Radius**: Smooth system from `xs` (0.25rem) to `5xl` (2rem) -- **Spacing**: Extended scale including custom values (4.5, 13, 15, etc.) - -### Current UI State - -- Uses HashRouter (not BrowserRouter) as seen in `App.tsx:1` -- 153 TypeScript files total in src/ -- Sophisticated Tailwind config with custom color system and animations - -## Commands +## Commands (from repository root) ```bash -# Frontend dev server only (port 1420) +# Frontend + Tauri dev (workspace delegates to app/) yarn dev -# Desktop dev with hot-reload (starts Vite + Tauri) +# Desktop with Tauri (loads env via scripts/load-dotenv.sh) yarn tauri dev -# Desktop dev with enhanced debugging (RUST_BACKTRACE and RUST_LOG enabled) -yarn dev:app +# Production UI build (app workspace) +yarn build -# Production build (TypeScript compile + Vite build + Tauri bundle) -yarn tauri build +# Typecheck / lint / format (app workspace) +yarn typecheck +yarn lint +yarn format +yarn format:check -# Debug build with .app bundle (required for deep link testing on macOS) -# On macOS, openhuman:// only works when running the .app, not `tauri dev` -yarn tauri build --debug --bundles app -yarn macos:dev +# Stage openhuman core binary next to Tauri resources (required for core RPC) +cd app && yarn core:stage -# Android -yarn tauri android dev -yarn tauri android build +# Skills (under skills/) +yarn workspace openhuman-app skills:build +yarn workspace openhuman-app skills:watch -# iOS -yarn tauri ios dev -yarn tauri ios build +# Rust — core library + CLI (repo root) +cargo check --manifest-path Cargo.toml +cargo build --manifest-path Cargo.toml --bin openhuman -# Skills development -yarn skills:build # Build skills in development mode -yarn skills:watch # Watch skills for changes - -# AI Configuration -yarn tools:generate # Discover tools from V8 runtime and generate TOOLS.md - -# Rust checks -cargo check --manifest-path src-tauri/Cargo.toml -cargo clippy --manifest-path src-tauri/Cargo.toml +# Rust — Tauri shell only +cargo check --manifest-path app/src-tauri/Cargo.toml ``` -No test framework is currently configured. **ESLint and Prettier are configured** with Husky pre-commit/pre-push hooks for code quality enforcement. +**Tests**: Vitest in `app/` (`yarn test`, `yarn test:coverage`). Rust tests via `cargo test` at repo root as wired in `app/package.json`. -## Architecture +**Quality**: ESLint + Prettier + Husky in the `app` workspace. -### Provider Chain (App.tsx) +--- -The app wraps in this order: `Redux Provider` → `PersistGate` → `SocketProvider` → `TelegramProvider` → `HashRouter` → `AppRoutes`. **Note**: Now uses HashRouter instead of BrowserRouter. This ordering matters because Socket.io and Telegram providers depend on Redux auth state. +## Frontend (`app/src/`) -### State Management (Redux Toolkit + Persist) +### Provider chain (`app/src/App.tsx`) -State lives in `src/store/` using Redux Toolkit slices: +Order matters for auth and realtime: -- **authSlice** — JWT token, onboarding completion flag (persisted) -- **userSlice** — user profile -- **socketSlice** — connection status, socket ID -- **telegramSlice** — connection/auth status, chats, messages, threads (selectively persisted; loading/error states excluded) -- **aiSlice** — AI system state, memory management, session tracking -- **skillsSlice** — skills catalog, setup status, management state, V8 runtime integration -- **teamSlice** — team management, member invites, permissions +`Redux Provider` → `PersistGate` → **`UserProvider`** → **`SocketProvider`** → **`AIProvider`** → **`SkillProvider`** → **`HashRouter`** → `AppRoutes`. -Redux Persist stores auth and telegram state (storage backend is configurable; default uses localStorage). The telegram slice has a complex nested structure in `src/store/telegram/` with separate files for types, reducers, extraReducers, and thunks. +There is **no** `TelegramProvider` in the current tree; Telegram may appear in UI copy or legacy settings, but MTProto is not an active provider here. -### LocalStorage +### State (`app/src/store/`) -- **Do not use `localStorage` (or `sessionStorage`) for app state or feature logic.** Use Redux (and Redux Persist where needed) instead. -- **Remove any existing `localStorage` usage** when touching related code. User-scoped data (auth, onboarding, Telegram session, socket state) lives in Redux, keyed by user id where applicable. Telegram session is in `telegram.byUser[userId].sessionString`, not localStorage. -- **Exceptions**: Redux-persist may use a localStorage-backed storage adapter by default; that is the persistence layer, not app logic. Any other remaining usage (e.g. deep-link `deepLinkHandled` flag) should be migrated to Redux or similar when that code is modified. -- **General rule**: Avoid adding new `localStorage` or `sessionStorage` usage; prefer Redux and remove existing usage when you work on affected areas. +Redux Toolkit slices include **auth**, **user**, **socket**, **ai**, **skills**, **team**, and related modules. Prefer Redux (and persist where configured) over ad hoc `localStorage` for app state; see project rules for exceptions. -### Service Layer (Singletons) +### Services (`app/src/services/`) -- **mtprotoService** (`src/services/mtprotoService.ts`) — Telegram MTProto client via `telegram` npm package. Session stored in Redux (`telegram.byUser[userId].sessionString`), not localStorage. Auto-retries FLOOD_WAIT up to 60s. -- **socketService** (`src/services/socketService.ts`) — Socket.io client. Auth token passed in socket `auth` object (not query string). Transports: polling first, then WebSocket. Enhanced with Rust-native Socket.io client for persistent connections. -- **apiClient** (`src/services/apiClient.ts`) — HTTP client for REST backend. +Singleton-style modules include **`apiClient`**, **`socketService`**, **`coreRpcClient`** (HTTP bridge to the core process), and domain **`api/*`** clients. There is **no** `mtprotoService` in this tree. -### MCP System (`src/lib/mcp/`) +### MCP (`app/src/lib/mcp/`) -Model Context Protocol implementation for AI tool execution over Socket.io: +Transport, validation, and types for JSON-RPC-style messaging over Socket.io — **not** a large Telegram tool pack. Tooling for agents is driven by the **skills** system and backend; see `agentToolRegistry.ts` and core RPC. -- `transport.ts` — Socket.io JSON-RPC 2.0 transport with 30s timeout -- `telegram/server.ts` — TelegramMCPServer manages 99 tool definitions -- `telegram/tools/` — Individual tool files (one per Telegram API operation) -- Tools use `big-integer` library for Telegram's large integer IDs +### Routing (`app/src/AppRoutes.tsx`) -### Routing (`src/AppRoutes.tsx`) +Hash routes include `/`, `/onboarding`, `/mnemonic`, `/home`, `/intelligence`, `/skills`, `/conversations`, `/invites`, `/agents`, `/settings/*`, plus `DefaultRedirect`. **No** dedicated `/login` route in `AppRoutes` (auth flows use the welcome/onboarding paths). -``` -/ → Welcome (public) -/login → Login (public) -/onboarding → Onboarding (protected, requires auth, not yet onboarded) -/home → Home (protected, requires auth + onboarded) -* → DefaultRedirect (routes based on auth state) -``` +### AI configuration -`PublicRoute` redirects authenticated users away. `ProtectedRoute` enforces auth and optionally onboarding status. +Bundled prompts live under **`src/ai/prompts/`** at the **repository root** (also bundled via `app/src-tauri/tauri.conf.json` `resources`). Loaders under `app/src/lib/ai/` use `?raw` imports, optional remote fetch, and in Tauri **`ai_get_config` / `ai_refresh_config`** for packaged content. -### Deep Link Auth Flow +--- -Web-to-desktop handoff using `openhuman://` URL scheme: +## Tauri shell (`app/src-tauri/`) -1. User authenticates in browser -2. Browser redirects to `openhuman://auth?token=` -3. Tauri catches the deep link, Rust `exchange_token` command calls backend via `reqwest` (bypasses CORS) -4. Backend returns `sessionToken` + user object -5. App stores session in Redux, navigates to onboarding/home +Thin desktop host: window management, daemon health bridging, **core process lifecycle** (`core_process`, `CoreProcessHandle`), and **JSON-RPC relay** to the **`openhuman`** sidecar (`core_rpc_relay`, `core_rpc`). -Key file: `src/utils/desktopDeepLinkListener.ts` (lazy-loaded in `main.tsx`). Uses a `deepLinkHandled` flag to prevent infinite reload loops. Deep links do NOT work in `tauri dev` on macOS — must use built `.app` bundle. +Registered IPC commands (see [`docs/src-tauri/02-commands.md`](docs/src-tauri/02-commands.md)) include **`greet`**, **`write_ai_config_file`**, **`ai_get_config`**, **`ai_refresh_config`**, **`core_rpc_relay`**, **window** commands, and **OpenHuman service / daemon host** helpers (`openhuman_*`). -### Rust Backend (`src-tauri/src/lib.rs`) +Deep link plugin is registered where supported; behavior is platform-specific (see platform notes below). -Enhanced Rust backend with comprehensive skill execution and runtime management: +--- -**Core Commands:** +## Rust core (repo root `src/`) -- `greet` — demo command -- `exchange_token` — CORS-free HTTP POST to backend for token exchange (desktop only) +- **`openhuman/`** — Domain logic (skills, memory, channels, config, …). RPC controllers live in **`rpc.rs`** files per domain; use **`RpcOutcome`** pattern per [`AGENTS.md`](AGENTS.md) / internal rules. +- **`src/openhuman/` module layout**: **New** functionality must live in a **dedicated subdirectory** (its own folder/module, e.g. `openhuman/my_domain/mod.rs` plus related files, or a new subfolder under an existing domain). Do **not** add new standalone `*.rs` files directly at `src/openhuman/` root; place new code in a module directory and declare it from `mod.rs` (or merge into an existing domain folder). +- **`core_server/`** — Transport only: Axum/HTTP, JSON-RPC envelope, CLI parsing, **dispatch** (`core_server::dispatch`) — **no** heavy business logic here. +- **Layering**: Implementation in `openhuman::/`, controllers in `openhuman::/rpc.rs`, routes in `core_server/`. -**Runtime Management:** +Skills runtime uses **QuickJS** (`rquickjs`) in **`src/openhuman/skills/`** (e.g. `qjs_skill_instance.rs`, `qjs_engine.rs`), not V8/deno_core in this repository. -- `discover_skills` — V8 skill discovery and manifest parsing -- `enable_skill` / `disable_skill` — skill lifecycle management -- `get_skill_preferences` / `set_skill_preferences` — skill configuration -- `connect_to_socket` — Rust-native Socket.io connection -- `get_socket_status` — connection status monitoring +--- -**Android Support:** +## App theme & design system -- `RuntimeService` — background service for skill execution -- Notification permissions and foreground service management -- Android logging integration with logcat +**Design intent**: Premium, calm crypto UI — ocean primary (`#4A83DD`), sage / amber / coral semantic colors, Inter + Cabinet Grotesk + JetBrains Mono, Tailwind with custom radii/spacing/shadows. Details: [`docs/DESIGN_GUIDELINES.md`](docs/DESIGN_GUIDELINES.md). -Deep link plugin registered at setup. `register_all()` called only on Windows/Linux (panics on macOS). +--- -### V8 Runtime System (`src-tauri/src/runtime/`) +## Environment variables (Vite) -Advanced JavaScript execution engine for skills using V8 (via deno_core): +Set in `.env` for the **`app`** workspace (`VITE_*` exposed to the client): -**Core Components:** +| Variable | Purpose | +| ------------------------- | ------------------------------------------------------------------------- | +| `VITE_BACKEND_URL` | API base (default in code: production API; see `app/src/utils/config.ts`) | +| `VITE_SENTRY_DSN` | Optional Sentry DSN | +| `VITE_SKILLS_GITHUB_REPO` | Skills catalog GitHub repo slug | -- `v8_engine.rs` — V8 JavaScript runtime initialization and management -- `v8_skill_instance.rs` — Individual skill execution contexts and lifecycle -- `skill_registry.rs` — Skill discovery, registration, and state management -- `manifest.rs` — Skill manifest parsing with platform compatibility checks -- `socket_manager.rs` — Persistent Socket.io connections with reconnection logic -- `cron_scheduler.rs` — Scheduled task execution for time-based skills -- `preferences.rs` — Skill configuration and settings persistence +--- -**Bridge System (`src-tauri/src/runtime/bridge/`):** +## Git workflow -- `skills_bridge.rs` — Skill-to-skill communication and state sharing -- `tauri_bridge.rs` — Frontend-backend IPC and environment access -- `net.rs` — HTTP/fetch operations for skills -- `db.rs` — Database operations and storage management -- `store.rs` — Key-value storage for skill data -- `log_bridge.rs` — Structured logging from skills -- `cron_bridge.rs` — Cron job scheduling and management +- **Public repo**; push to your working branch; PRs target **`main`**. +- Use [`.github/pull_request_template.md`](.github/pull_request_template.md); AI-generated PR text should follow its sections and checklist. -**Quickjs Integration (`src-tauri/src/services/quickjs/`):** +--- -- `service.rs` — High-level client management with V8 integration -- `bootstrap.js` — V8 JavaScript bootstrap environment -- `ops/mod.rs` — Native operations for WebSocket, timers, and async handling -- `storage.rs` — Persistent storage for sessions and data +## Key patterns (concise) -**Platform Support:** +- **`src/openhuman/`**: New features go in a **folder/module**, not new root-level `src/openhuman/*.rs` files (see Rust core section). +- **File size**: Prefer ≤ ~500 lines per source file; split modules when growing. +- **Pre-merge checks** (when touching code): Prettier, ESLint, `tsc --noEmit` in `app/`; `cargo fmt` + `cargo check` for changed Rust (`Cargo.toml` at root and/or `app/src-tauri/Cargo.toml` as appropriate). +- **No dynamic imports** in app code (static `import` only); use try/catch around Tauri APIs where needed. +- **Type-only imports**: `import type` where appropriate. +- **Dual socket / tool sync**: If you change realtime protocol, keep **frontend** (`socketService` / MCP transport) and **core** socket behavior aligned (see [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) dual-socket section). -- Desktop platforms: Full V8 runtime with all features -- Mobile platforms: Error handling with feature availability checks -- Platform-specific skill filtering based on manifest declarations +--- -## Environment Variables +## Platform notes -Set in `.env` (Vite exposes `VITE_*` prefixed vars): +- **macOS deep links**: Often require a built **`.app`** bundle; not only `tauri dev`. See [`docs/telegram-login-desktop.md`](docs/telegram-login-desktop.md) if applicable. +- **`window.__TAURI__`**: Not assumed at module load; guard Tauri usage accordingly. +- **Core sidecar**: Must be staged/built so `core_rpc` can reach the `openhuman` binary (see `scripts/stage-core-sidecar.mjs`). -| Variable | Purpose | -| --------------------------- | ------------------------------------------------------------------- | -| `VITE_BACKEND_URL` | Backend API URL (default: `http://localhost:5005`) | -| `VITE_SENTRY_DSN` | Sentry DSN for error reporting (optional) | -| `VITE_DEBUG` | Debug mode flag | -| `OPENHUMAN_DAEMON_INTERNAL` | Force internal daemon mode (default: false, uses external services) | +--- -Production defaults are in `src/utils/config.ts`. - -## AI Configuration System - -OpenHumanuses an OpenClaw-compliant AI configuration system that automatically injects persona and tool context into every user message for consistent AI behavior. - -### Configuration Files - -All AI configuration lives in the `/ai/` directory: - -- **`/ai/SOUL.md`** - AI personality, voice, tone, and behavior patterns -- **`/ai/TOOLS.md`** - Auto-generated documentation of all available tools (generated via `yarn tools:generate`) -- **`/ai/IDENTITY.md`** - Core identity and values (TODO) -- **`/ai/AGENTS.md`** - Agent roles and specializations (TODO) -- **`/ai/USER.md`** - User adaptation strategies (TODO) -- **`/ai/BOOTSTRAP.md`** - Initialization procedures (TODO) -- **`/ai/MEMORY.md`** - Long-term knowledge and patterns (TODO) - -### Modular Loader System - -```typescript -// Individual loaders with multi-layer caching -loadSoul() → SoulConfig // Personality, voice, behavior -loadTools() → ToolsConfig // Available tools and capabilities - -// Unified loader -loadAIConfig() → AIConfig // Combined SOUL + TOOLS configuration -``` - -**Caching Strategy:** - -- Memory cache (immediate) -- localStorage cache (30min TTL) -- GitHub remote (latest) -- Bundled fallback (reliable) - -**TODO**: Set up public AI configuration repository to eliminate 404 fallback errors - -- Current: AI config loaders try GitHub URLs first (fail with 404), then fallback to bundled files -- Console shows: "Failed to load resource: the server responded with a status of 404" -- Affected: Settings → AI Configuration "Refresh Soul/Tools" buttons -- Files: `src/lib/ai/soul/loader.ts`, `src/lib/ai/tools/loader.ts` - -### Unified Injection System - -Every user message automatically gets AI context injected: - -```typescript -// Unified injection (recommended) -import { injectAll } from '../lib/ai/injector'; -// Individual injections (for specific needs) -import { injectSoul, injectTools } from '../lib/ai/injector'; - -const injectedMessage = await injectAll(userMessage); - -const soulMessage = await injectSoul(userMessage); -const toolsMessage = await injectTools(userMessage); -``` - -**Message Format:** - -``` -[PERSONA_CONTEXT] -I am OpenHuman that incredibly smart, funny friend who loves helping people get stuff done -Personality: Curious & Enthusiastic, Witty & Engaging, Empathetic -Voice: Conversational, Use humor naturally but don't force it -[/PERSONA_CONTEXT] - -[TOOLS_CONTEXT] -4 tools across 3 skills -Categories: Communication (2), Productivity (1), Email (1) -Key skills: telegram, notion, gmail -[/TOOLS_CONTEXT] - -User message: Hello! -``` - -### Dynamic TOOLS.md Generation - -TOOLS.md is automatically generated from the V8 skills runtime: - -```bash -# Discover tools and generate documentation -yarn tools:generate - -# Integration in build pipeline -yarn skills:build && yarn tools:generate && tsc && vite build -``` - -**Process:** - -1. **Discovery**: Spawns Tauri runtime to call `runtime_all_tools()` -2. **Parsing**: Extracts tool definitions with JSON Schema -3. **Formatting**: Generates OpenClaw-compliant markdown -4. **Bundling**: Includes in app for AI context injection - -**Generated Output:** - -- Professional documentation with usage examples -- Environment-specific configurations -- Tool categorization by skill -- Statistics and metadata - -### Integration Points - -AI context injection happens in 4 places: - -1. **`src/pages/Conversations.tsx`** - Main chat interface -2. **`src/store/threadSlice.ts`** - Redux sendMessage thunk -3. **`src/services/api/threadApi.ts`** - API layer -4. **`src/utils/tauriCommands.ts`** - Tauri agent chat - -All use the unified `injectAll()` function for consistency. - -### Settings UI - -View and manage AI configuration in **Settings → AI Configuration**: - -- Live SOUL personality preview -- TOOLS statistics and categories -- Individual refresh buttons -- Source indicators (GitHub vs bundled) -- Combined "Refresh All" functionality - -## Recent Changes - -Key updates from recent commits (cd9ebcd to current): - -### Major Runtime Transition - -- **V8 Runtime Migration** (`99c20ea`, `0f6a092`): Complete transition from QuickJS to V8 - - Replaced QuickJS with V8 (via deno_core) for improved JavaScript execution and WASM support - - Enhanced skill management with V8 runtime including improved performance and compatibility - - New V8 skill instance handling with advanced execution contexts - - Updated dependencies and Cargo.toml to reflect V8 integration - - Platform compatibility checks and enhanced manifest handling - -### Android Platform Support - -- **Full Android Integration** (`ce06cfc`, `a2578b9`): Production-ready mobile platform support - - Complete Android project generation with MainActivity and RuntimeService - - Background service for persistent skill execution on Android - - Notification permission handling and foreground service management - - Android logging integration with logcat for better debugging - - Deep link support configuration in AndroidManifest.xml - -### Enhanced Socket & Runtime Management - -- **Rust-Native Socket.io Client** (`68d397e`): Persistent connection infrastructure - - Native Rust Socket.io implementation for improved reliability - - Enhanced socket connection handling with reconnection logic - - Dynamic backend URL configuration support - - Improved error handling and connection status monitoring - -### Skills System Improvements - -- **Advanced Skill Management** (`e841c86`, `719e6e5`): Enhanced skill lifecycle and configuration - - Skill setup pipeline with contextual Enable/Setup/Configure/Retry buttons - - Platform filtering for skills with manifest-based compatibility checks - - Enhanced skill status derivation and connection indicators - - Environment variable exposure to skills (whitelisted values) - - Improved skill discovery and manifest processing with logging - -### Major Additions - -- **ESLint & Prettier Integration** (`5896966`): Complete code quality toolchain - - ES module syntax for ESLint configuration with enhanced TypeScript support - - Husky pre-commit/pre-push hooks for automatic formatting and linting - - Type-only imports standardization across codebase - - Consolidated import statements and improved code organization - - GitHub workflows updated with Prettier and ESLint checks -- **Advanced Skills System** (`10ec1b3`): Comprehensive skill management platform - - Dynamic skills loading from local directory via Rust integration - - SkillSetupModal with conditional rendering (wizard vs management panel) - - Background GitHub sync for skills catalog updates - - Skills table with setup status indicators and management controls - - Enhanced skill metadata with setup hooks and descriptions -- **Team Management Features** (`10ec1b3`): Multi-user collaboration system - - TeamPanel, TeamMembersPanel, and TeamInvitesPanel components - - Redux state management for teams, members, and invites - - Team API integration with CRUD operations - - Settings modal routing for team management paths - - Role-based permissions and invitation system -- **AI System Enhancements**: Advanced memory and session management - - Hybrid search with encryption for AI memory - - Constitution-based AI behavior with GitHub integration - - Entity graph migration to Neo4j backend - - Session capture and transcript management - - Memory chunking and context formatting -- **Enhanced CI/CD Pipeline** (`b1d7bce`): Production-ready deployment - - XGH_TOKEN authentication for openhumanxyz/openhuman releases - - Python sidecar setup and caching for cross-platform builds - - Tauri configuration updates (com.openhuman.app identifier) - - GitHub Pages deployment with optimized workflows - - Version tagging and environment variable management -- **Device Detection & Download System** (`9d74721`, `b5bccd2`): Enhanced multi-architecture download support - - Optimized asset parsing using Maps for unique architecture links per platform - - Enhanced DownloadScreen.tsx with architecture-specific download options - - Improved device detection for Windows, macOS, Linux, and Android platforms - - Added preference logic for more specific filenames in asset parsing - - Support for multiple architectures (x64, aarch64) with intelligent sorting -- **Version Bump**: Project updated to v0.20.0 (`891517c`) - -### Design System Updates - -- **Settings Modal UI**: Clean 520px white modal contrasting with glass morphism theme -- **Animations**: 200ms entry animations, 250ms panel transitions, chevron hover effects -- **Lottie Animations**: Integrated into onboarding flow (`334673e`) -- **Connection Components**: Added Telegram and Gmail connection indicators -- **Routing**: Switched to HashRouter for better desktop app compatibility -- **Theme**: Implemented sophisticated color system with premium crypto aesthetic - -### Component Structure - -- **200+ TypeScript files** across `src/` directory with comprehensive tooling -- **AI System Architecture** (`src/lib/ai/`): Advanced artificial intelligence platform - - Memory management with encryption, chunking, and hybrid search - - Constitution-based behavior with GitHub integration - - Entity graph with Neo4j backend integration - - Session capture, transcript management, and tool compression - - Provider system with OpenAI integration and custom providers -- **Skills Management System**: Dynamic skill platform with Rust integration - - SkillsGrid.tsx - Skills catalog with setup status and management - - SkillSetupModal.tsx - Conditional wizard/management panel rendering - - SkillProvider.tsx - GitHub sync and local directory integration - - Skills submodule integration with background updates -- **Team Collaboration Features**: Multi-user workspace management - - TeamPanel.tsx - Team overview with member management - - TeamMembersPanel.tsx - Member roles and permissions - - TeamInvitesPanel.tsx - Invitation system with role assignment - - Team API integration with Redux state management -- **Settings Modal System**: Comprehensive configuration interface - - SettingsModal.tsx - Main container with URL routing - - SettingsLayout.tsx - Modal wrapper with createPortal - - Enhanced panels: Billing, Team, Connections, Privacy, Profile - - Hooks: useSettingsNavigation.ts, useSettingsAnimation.ts -- **Download System**: Enhanced multi-platform distribution - - DownloadScreen.tsx - Platform detection with architecture support - - deviceDetection.ts - Comprehensive device/architecture utilities - - GitHub API integration for real-time release assets -- **Code Quality Infrastructure**: ESLint, Prettier, and Husky integration - - Pre-commit/pre-push hooks with TypeScript compilation checks - - Standardized type-only imports and consolidated statements - - GitHub workflow integration with automated quality checks - -## Git Workflow - -- **Repository visibility**: The project is public. -- **Push target**: Pushes should go to your working branch in the public repository (or your fork if your access model requires it). -- **PR target**: Open pull requests against the public upstream repository, targeting the **`main`** branch. -- **PR template required**: Use `.github/pull_request_template.md` for all pull requests. -- **AI tooling rule**: Any AI-generated PR description must follow the template sections in order and keep all checklist items. - -## Key Patterns - -- **MANDATORY: Pre-completion checks**: Before considering ANY task complete, ALWAYS run these checks and fix all errors: - 1. `npx prettier --check .` (formatting) - 2. `npx eslint .` (lint) - 3. `npx tsc --noEmit` (TypeScript) - 4. `cargo fmt --manifest-path src-tauri/Cargo.toml` (Rust formatting, if Rust files were changed) - 5. `cargo check --manifest-path src-tauri/Cargo.toml` (Rust compilation, if Rust files were changed) -- **Code Quality**: ESLint and Prettier enforce code standards with Husky hooks. Use type-only imports (`import type`) and consolidate imports from same modules. -- **Frontend scope**: The frontend (`src/`) is primarily a REST API client to `rust-core/`; Rust code in `src-tauri/` manages the core process lifecycle and bridge surface. -- **Core feature exposure**: Any new feature added in `rust-core/` must be exposed through both the CLI and a REST API so it can be integrated into the UI without backend rewrites. -- **No dynamic imports**: All imports must be static `import` statements at the top of the file. Do not use `await import()` or `import().then()` inside functions or code blocks. Use try/catch around Tauri API calls for non-Tauri environments instead. -- **No localStorage**: Avoid `localStorage` and `sessionStorage`; use Redux (and persist) for app state. Remove any direct usage when working on affected code. -- **AI System Integration**: Use `src/lib/ai/` for memory management, constitution loading, entity queries, and session capture. AI providers abstracted through interface pattern. -- **AI Configuration System**: OpenClaw-compliant AI configuration with dynamic TOOLS.md generation. Use `loadSoul()`, `loadTools()`, `loadAIConfig()` for configuration loading, and `injectAll()` for unified SOUL + TOOLS injection into user messages. -- **V8 Skills Runtime**: Skills execute in V8 JavaScript engine on desktop platforms. Use `SkillProvider` for GitHub sync, `SkillsGrid` for management interface, and Rust runtime commands for lifecycle management. Platform filtering ensures skills only run on supported platforms. -- **Team Collaboration**: Team features in `src/components/settings/panels/Team*`. Use Redux `teamSlice` for state management and `teamApi` for backend operations. -- **Device Detection**: Use `deviceDetection.ts` utilities for platform/architecture detection. Support multiple architectures per platform (x64, aarch64) with intelligent preference logic. -- **GitHub Integration**: Fetch release assets via GitHub API (`fetchLatestRelease()`) and parse by architecture (`parseReleaseAssetsByArchitecture()`). Use Maps for efficient unique architecture tracking. -- **Download System**: Platform-specific file type support (.exe/.msi for Windows, .dmg for macOS, .AppImage/.deb/.rpm for Linux, .apk for Android) with fallback links. -- **Modal System**: Settings modal uses `createPortal` pattern with URL-based routing. Clean white design (not glass morphism) for system settings. Navigate with `/settings` paths for different panels. -- **Component Reuse**: Connection management reuses `connectOptions` array and components from onboarding flow. Maintains consistent UX patterns across features. -- **Redux Integration**: Multiple slices (auth, user, telegram, ai, skills, team) with Redux Persist. Use typed hooks and selectors. State functions accept optional `userId` param. -- **Node polyfills**: Vite config (`vite.config.ts`) polyfills `buffer`, `process`, `util`, `os`, `crypto`, `stream` for the `telegram` package which requires Node APIs. -- **Telegram IDs**: Use `big-integer` library, not native JS numbers (Telegram IDs exceed `Number.MAX_SAFE_INTEGER`). -- **MCP tool files**: Each tool in `src/lib/mcp/telegram/tools/` exports a handler conforming to `TelegramMCPToolHandler` interface. Tool names are typed in `src/lib/mcp/telegram/types.ts`. -- **Tauri IPC**: Frontend calls Rust via `invoke()` from `@tauri-apps/api/core`. Rust commands are registered in `generate_handler![]` macro. Enhanced with runtime management commands for V8 skill execution and Socket.io integration. -- **CORS workaround**: External HTTP requests from the WebView hit CORS. Use Rust `reqwest` via Tauri commands instead of browser `fetch()`. -- **Hash Routing**: Uses HashRouter for desktop app compatibility and deep link handling. -- **Integration Libraries**: Each integration (Telegram, future Gmail, etc.) lives under `src/lib//` with its own `state/`, `services/`, `api/` subdirectories. Domain-specific services belong in the integration folder, not in `src/services/` (which holds only cross-cutting services like socketService, apiClient). -- **Unit Tests**: All unit tests live in `__tests__/` folders co-located with the code they test. Use Jest with TypeScript support. -- **Runtime Platform Differences**: V8 runtime is desktop-only. Mobile platforms use feature detection and graceful degradation. Skills with platform restrictions are filtered during discovery. -- **Socket Management**: Rust-native Socket.io client provides persistent connections with automatic reconnection. Use `connect_to_socket` command instead of frontend-only socket connections for reliability. -- **Dual Socket Codebase**: Socket event handling exists in **both** the TypeScript frontend (`src/services/socketService.ts`, `src/utils/tauriSocket.ts`) and the Rust backend (`src-tauri/src/runtime/socket_manager.rs`). **Any new socket event or protocol change must be implemented in both codebases.** The web frontend handles events directly via Socket.io; the Rust backend handles them over raw WebSocket with Engine.IO/Socket.IO framing. Example: `tool:sync` is emitted from both `src/lib/skills/sync.ts` (web mode) and `socket_manager.rs` (Rust mode, on connect + skill lifecycle changes). - -## Platform Gotchas - -- **macOS deep links**: Require `.app` bundle (not `tauri dev`). Clear WebKit caches when debugging stale content: `rm -rf ~/Library/WebKit/com.openhuman.app ~/Library/Caches/com.openhuman.app` -- **Cargo caching**: May serve stale frontend assets on incremental builds. Run `cargo clean --manifest-path src-tauri/Cargo.toml` if the app shows outdated UI. -- **`window.__TAURI__`**: Not available at module load time. Use static imports and try/catch around Tauri API calls (not around imports). -- **Android background services**: RuntimeService requires notification permissions (API 33+) and foreground service type specification (API 34+). Use Android logging (`android_logger`) for debug output in logcat. -- **V8 runtime limitations**: V8 engine is desktop-only. Android skills should use lightweight alternatives or server-side execution patterns. -- **Socket connections**: Persistent Socket.io connections via Rust backend work better than WebView-based connections on mobile platforms. +_Last aligned with monorepo layout (`app/` + root `src/`), QuickJS skills in `openhuman_core`, and Tauri shell IPC as of repo state._ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 754b2f58c..6650b7654 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -98,7 +98,7 @@ Maintainers will review and may request changes. Once approved, your PR will be - **Imports**: Use static `import`/`import type` at the top of the file. No dynamic `import()` for app code; use try/catch around Tauri API calls in non-Tauri environments instead. - **Code style**: ESLint and Prettier are authoritative. Use type-only imports where appropriate and consolidate imports from the same module. - **Telegram IDs**: Use the `big-integer` library; do not rely on native JavaScript numbers for Telegram IDs. -- **Tauri**: Commands are in Rust under `src-tauri`; frontend uses `invoke()` from `@tauri-apps/api/core`. Handle missing `window.__TAURI__` where the app can run outside Tauri. +- **Tauri**: Commands are in Rust under `app/src-tauri`; frontend uses `invoke()` from `@tauri-apps/api/core`. Handle missing `window.__TAURI__` where the app can run outside Tauri. Install JS deps from the repo root (`yarn install`) so the `app` workspace is linked; most scripts are also available as `yarn