Skip to content

Commit e574fe4

Browse files
authored
Merge pull request #21 from OpenKnots/okcode/build-open-dev
Point Next type imports at dev routes
2 parents c66970d + 542f63b commit e574fe4

21 files changed

Lines changed: 575 additions & 15 deletions

.gitignore

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,9 @@ coverage
1414
storage/*.sqlite*
1515
storage/prompt-bank/*
1616
storage
17-
!storage/README.md
17+
!storage/README.md
18+
19+
# Tauri / Rust
20+
src-tauri/target
21+
src-tauri/gen
22+
src-tauri/Cargo.lock

.secretlintignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
.next/**
22
node_modules/**
33
pnpm-lock.yaml
4+
src-tauri/target/**

docs/phases/PHASES.md

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ App Shell, App Sidebar, Artifact Link, Auth Controls, Border Glow, Chart Area In
259259
- Comprehensive demo mode
260260

261261
**What is notably absent:**
262-
- Desktop application (Tauri) — zero implementation
262+
- Desktop application (Tauri) — scaffold complete, distributable builds not yet produced
263263
- Test coverage — 1 test file with 23 assertions out of 34 modules
264264
- Real embedding models — current vectors are deterministic char-code-based
265265
- Structured logging / observability
@@ -438,32 +438,37 @@ Current state: basic health signals exist (stale pipelines, review debt, weak pr
438438

439439
---
440440

441-
## Phase 16 — Desktop application `NOT STARTED`
441+
## Phase 16 — Desktop application `SUBSTANTIALLY COMPLETE`
442442

443443
**Goal:** Wrap OpenTrust in a native desktop application using Tauri v2.
444444

445-
**Note:** This was originally Phase 8.5 (parallel with memory work). It has been renumbered to reflect that it has zero implementation and is no longer an upstream prerequisite — the memory layer was built without it.
445+
**Note:** This was originally Phase 8.5 (parallel with memory work). Renumbered to reflect actual priority. The Tier 1 scaffold and Tier 2 native integrations are now implemented.
446446

447447
Primary design doc: `docs/DESKTOP-APPLICATION-PLAN.md`
448448

449449
### Tier 1 — Minimal desktop app `[required]`
450-
- [ ] `[required]` Tauri v2 project scaffold (`src-tauri/`)
451-
- [ ] `[required]` Next.js static export configuration (`output: 'export'`)
452-
- [ ] `[required]` Tauri window configuration (title, size, platform targets)
453-
- [ ] `[required]` Sidecar Node process for the memory runtime
454-
- [ ] `[required]` Desktop-appropriate database path resolution (`$APPDATA` / `~/Library/Application Support`)
450+
- [x] `[required]` Tauri v2 project scaffold (`src-tauri/`) — Cargo.toml, build.rs, tauri.conf.json, capabilities, icons
451+
- [x] `[required]` Next.js standalone output configuration (`output: 'standalone'` for sidecar-compatible server.js)
452+
- [x] `[required]` Tauri window configuration (1280×860 default, 900×600 min, centered, resizable)
453+
- [x] `[required]` Sidecar Node process for the memory runtime (port auto-selection, readiness polling, env-based config)
454+
- [x] `[required]` Desktop-appropriate database path resolution via `OPENTRUST_DB_PATH` env + Tauri `app_data_dir()`
455455
- [ ] `[required]` Basic macOS `.dmg` build
456456
- [ ] `[required]` Basic Windows `.msi` / `.exe` build
457457
- [ ] `[required]` Basic Linux `.AppImage` / `.deb` build
458458

459459
### Tier 2 — Native integrations `[optional]`
460-
- [ ] `[optional]` System tray icon with health status indicator
461-
- [ ] `[optional]` Tray menu: open dashboard, run ingestion, check health, quit
460+
- [x] `[optional]` System tray icon with health status indicator
461+
- [x] `[optional]` Tray menu: open dashboard, memory health, quit
462462
- [ ] `[optional]` Native file dialog for database selection / backup export
463-
- [ ] `[optional]` OS notifications for ingestion completion and health alerts
463+
- [x] `[optional]` OS notifications plugin wired (tauri-plugin-notification on Rust + JS)
464464
- [ ] `[optional]` Global keyboard shortcut to open OpenTrust
465465
- [ ] `[optional]` Deep link support (`opentrust://` protocol)
466466

467+
### Cross-cutting desktop support
468+
- [x] Desktop detection utility (`lib/opentrust/desktop.ts``isDesktop()` / `isWeb()`)
469+
- [x] Secretlint ignore for Rust build artifacts (`src-tauri/target/**`)
470+
- [x] Gitignore for Tauri build artifacts (target, gen, Cargo.lock)
471+
467472
### Tier 3 — Distribution `[stretch]`
468473
- [ ] `[stretch]` Auto-update via `tauri-plugin-updater`
469474
- [ ] `[stretch]` Code signing for macOS (Developer ID) and Windows (Authenticode)
@@ -534,7 +539,7 @@ The core local-first evidence platform is complete end-to-end: ingest, normalize
534539

535540
1. **Phase 9 was built before prerequisites were met.** The execution pipeline recommended deferring memory-layer expansion until Tauri, persistence, and reliable run completion were stable. Phase 9 was implemented anyway. The result is solid, and the gating advice should be considered superseded.
536541

537-
2. **Desktop application (originally Phase 8.5) has zero implementation.** It was framed as a parallel workstream that "can proceed now" but no work was done. Renumbered to Phase 16 to reflect its actual priority position.
542+
2. **Desktop application (originally Phase 8.5) now has a working scaffold.** The Tauri v2 project, sidecar architecture, system tray, desktop DB path resolution, and notification plugin are implemented. Distributable builds remain. Renumbered to Phase 16.
538543

539544
3. **Memory table migrations are runtime-based, not file-based.** The Phase 9 implementation plan specified `db/` migration files. The actual implementation uses `ensureMigrated()` in `db.ts`. This works but diverges from the documented approach.
540545

lib/opentrust/db.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,27 @@ import { existsSync, mkdirSync, readFileSync } from "node:fs";
33
import path from "node:path";
44

55
const repoRoot = process.cwd();
6-
const storageDir = path.join(repoRoot, "storage");
7-
const dbPath = path.join(storageDir, "opentrust.sqlite");
6+
7+
/**
8+
* Resolve the database path.
9+
*
10+
* When running as a Tauri desktop app (OPENTRUST_DB_PATH is set by the
11+
* Rust sidecar launcher), use the platform-appropriate Application Support
12+
* / AppData path. Otherwise fall back to the local `storage/` directory
13+
* for development and CLI usage.
14+
*/
15+
function resolveDbPath(): string {
16+
const envPath = process.env.OPENTRUST_DB_PATH;
17+
if (envPath) return envPath;
18+
return path.join(repoRoot, "storage", "opentrust.sqlite");
19+
}
20+
21+
function resolveStorageDir(): string {
22+
return path.dirname(resolveDbPath());
23+
}
24+
25+
const storageDir = resolveStorageDir();
26+
const dbPath = resolveDbPath();
827
const migrationPath = path.join(repoRoot, "db", "0001_init.sql");
928

1029
const globalForDb = globalThis as unknown as {

lib/opentrust/desktop.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* Desktop environment detection and Tauri IPC helpers.
3+
*
4+
* These are safe to import from both server and client code — they guard
5+
* against `window` / `__TAURI_INTERNALS__` not existing.
6+
*/
7+
8+
/** Returns true when running inside the Tauri webview shell. */
9+
export function isDesktop(): boolean {
10+
if (typeof window === "undefined") {
11+
// Server-side: check the env flag set by the sidecar launcher
12+
return process.env.OPENTRUST_DESKTOP === "1";
13+
}
14+
// Client-side: Tauri injects this global
15+
return "__TAURI_INTERNALS__" in window;
16+
}
17+
18+
/** Returns true when running as a normal browser-served web app. */
19+
export function isWeb(): boolean {
20+
return !isDesktop();
21+
}

next.config.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import type { NextConfig } from "next";
22

33
const nextConfig: NextConfig = {
44
serverExternalPackages: ["better-sqlite3", "sqlite-vec"],
5+
// Standalone output produces a self-contained server.js suitable for
6+
// the Tauri sidecar. In development this has no effect on `next dev`.
7+
output: "standalone",
58
};
69

710
export default nextConfig;

package.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
"ingest:cron": "tsx scripts/ingest-cron.ts",
1717
"index:semantic": "tsx scripts/index-semantic.ts",
1818
"secrets:check": "secretlint --secretlintrc .secretlintrc.json \"**/*\"",
19+
"tauri": "tauri",
20+
"tauri:dev": "tauri dev",
21+
"tauri:build": "tauri build",
1922
"prepare": "husky"
2023
},
2124
"dependencies": {
@@ -30,6 +33,10 @@
3033
"@radix-ui/react-dialog": "^1.1.15",
3134
"@tabler/icons-react": "^3.40.0",
3235
"@tanstack/react-table": "^8.21.3",
36+
"@tauri-apps/api": "^2.10.1",
37+
"@tauri-apps/plugin-notification": "^2.3.3",
38+
"@tauri-apps/plugin-process": "^2.3.1",
39+
"@tauri-apps/plugin-shell": "^2.3.5",
3340
"better-sqlite3": "^12.8.0",
3441
"class-variance-authority": "^0.7.1",
3542
"clsx": "^2.1.1",
@@ -53,6 +60,7 @@
5360
"@secretlint/core": "^11.4.0",
5461
"@secretlint/secretlint-rule-preset-recommend": "^11.4.0",
5562
"@tailwindcss/postcss": "^4.2.2",
63+
"@tauri-apps/cli": "^2.10.1",
5664
"@types/better-sqlite3": "^7.6.13",
5765
"@types/node": "^22.19.15",
5866
"@types/react": "^19.2.14",

pnpm-lock.yaml

Lines changed: 164 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
[package]
2+
name = "opentrust"
3+
version = "0.1.0"
4+
description = "OpenTrust — Local-first OpenClaw memory layer"
5+
authors = ["OpenTrust"]
6+
edition = "2021"
7+
8+
[lib]
9+
name = "opentrust_lib"
10+
crate-type = ["staticlib", "cdylib", "rlib"]
11+
12+
[build-dependencies]
13+
tauri-build = { version = "2", features = [] }
14+
15+
[dependencies]
16+
tauri = { version = "2", features = ["tray-icon"] }
17+
tauri-plugin-shell = "2"
18+
tauri-plugin-process = "2"
19+
tauri-plugin-notification = "2"
20+
serde = { version = "1", features = ["derive"] }
21+
serde_json = "1"
22+
reqwest = { version = "0.12", features = ["blocking"] }
23+
tokio = { version = "1", features = ["full"] }
24+
portpicker = "0.1"
25+
26+
[profile.release]
27+
panic = "abort"
28+
codegen-units = 1
29+
lto = true
30+
opt-level = "s"
31+
strip = true

0 commit comments

Comments
 (0)