Ir al contenido
Oleaflyv0.4.6

Set up the Oleafly desktop repository, fetch its pinned sidecars, run the app, and understand the main extension points.

Esta página aún no está disponible en tu idioma.

Oleafly is a Tauri 2 (opens in a new tab) desktop app. Its React and TypeScript frontend talks to Rust over Tauri IPC. Rust owns project files, compilation, secrets, MCP routing, and AI provider requests.

Oleafly/
├── src/ React app shell (stores, Tauri client, UI kit, port adapters)
│ ├── components/ ui (shadcn-style), layout, editor glue, preview panes, ai
│ ├── contributions/ registers rail tabs / commands / AI toolsets into the registry
│ ├── features/ compile, synctex, export
│ ├── lib/ tauri wrappers, github, spellcheck, utils, package shims
│ └── store/ zustand stores
├── packages/ @oleafly/* frontend packages consumed as TS source
│ ├── latex/ latex-intelligence/ ai-core/ ai-tools/ registry/
│ └── editor/ preview/ diagram/ preflight/ pdf-to-latex/ templates/ wysiwyg/
├── crates/
│ └── oleafly-agent/ provider clients, streaming, and agent orchestration
├── src-tauri/
│ ├── src/ Tauri commands, engines, config, Git, MCP, paths, projects
│ ├── binaries/ fetched Tectonic, Biber, and Typst sidecars
│ ├── resources/ templates, dictionaries, TeX data, language servers
│ └── tauri.conf.json
├── scripts/fetch-tectonic.sh
├── scripts/fetch-biber.sh
├── scripts/fetch-typst.sh
├── scripts/fetch-language-servers.mjs
└── docs/

The frontend is a pnpm workspace. Reusable features live in packages/* behind injected ports, and the app shell wires them together. Read Frontend architecture before touching packages/: it covers the port pattern, the contribution registry, and the alias wiring.

Terminal window
pnpm install
./scripts/fetch-tectonic.sh all
./scripts/fetch-biber.sh all
./scripts/fetch-typst.sh all
pnpm language-servers:fetch
pnpm tauri dev

For a single platform, pass its Rust target triple to each shell fetch script. Use rustc -vV to find the host triple. The language-server command selects the current host unless you pass a target through its underlying script.

Terminal window
pnpm tauri dev # run the app with hot reload (frontend) + cargo incremental (backend)
pnpm build # typecheck + build the frontend (tsc -b && vite build)
pnpm tauri build # produce a distributable bundle

Run the relevant local checks before opening a pull request:

Terminal window
pnpm build # frontend typecheck (noUnusedLocals/Parameters on)
pnpm test # vitest across src/ and packages/
pnpm audit --prod --audit-level high # registry-backed npm advisory check
cargo check --workspace --all-targets # Rust workspace compiles
cargo deny --manifest-path src-tauri/Cargo.toml check # Rust advisories, licenses, and sources

The two audit commands require registry/network access. CI records their current results on every code change. An offline local run cannot certify that the dependency graph is advisory-free.

For user-facing changes, also run the end-to-end suite against the real app and compiler. See e2e/README.md (opens in a new tab).

Terminal window
pnpm test:e2e:app # builds + launches the app, runs Playwright, tears down
How a compile travels through the appThe frontend calls compileProject through Tauri IPC. In Rust, DocumentEngine picks the project's engine: Tectonic, latexmk, Typst, or Pandoc with Tectonic. The PDF comes back to the pdf.js viewer as raw binary IPC, and streamed log events become diagnostics in CodeMirror.FrontendRust, src-tauriCompile requestcompileProject()pdf.js viewerShows the PDFCodeMirrorDiagnosticsDocumentEnginePicks the engineTectoniclatexmkTypstPandoc, TectonicTauri IPCPDF bytesStreamed logsHow a compile travels through the appThe frontend calls compileProject through Tauri IPC. In Rust, DocumentEngine picks the project's engine: Tectonic, latexmk, Typst, or Pandoc with Tectonic. The PDF comes back to the pdf.js viewer as raw binary IPC, and streamed log events become diagnostics in CodeMirror.FrontendcompileProject()DocumentEngineIn RustEngineTectonic, latexmk,Typst or Pandocpdf.jsShows the PDFCodeMirrorDiagnosticsTauri IPCPDFLogs
The frontend asks Rust to compile, and DocumentEngine runs the project's engine. The PDF comes back as binary IPC, while streamed logs turn into diagnostics.
  1. The frontend loads the backend project_engine descriptor and its capability flags, then calls compileProject(projectId, mainDoc, offline) through Tauri IPC.
  2. Rust dispatches through DocumentEngine. UI code must not infer engine behavior from a filename.
  3. LaTeX uses bundled Tectonic by default. A project can instead choose pdfLaTeX, XeLaTeX, or LuaLaTeX through latexmk. A complete system TeX installation takes priority over Oleafly’s managed TinyTeX. The shared detector requires the core compilers, latexmk, kpsewhich, and Biber before granting that priority.
  4. Typst runs the exact version the project pins in project.json: the bundled sidecar, a checksum-verified download, or a system typst that reports that version. It compiles the selected .typ main document with human-readable diagnostics and an explicit PDF output path. With Auto compile on, Rust keeps one typst watch process per project instead (src-tauri/src/typst_watch.rs). The desktop repo’s docs/typst-toolchain.md covers resolution, pins, and the matching Tinymist.
  5. Markdown invokes Pandoc directly against .md/.markdown, with an explicit output path and --pdf-engine=<absolute bundled Tectonic path>. Pandoc’s manual explicitly supports a full PDF-engine path. Do not replace this with an implicit system pdflatex, since packaged Oleafly must not depend on an undeclared TeX installation. The process runs with the project root as its working directory so relative images, bibliography files, and CSL files work for both root and nested main documents.

Tauri’s sidecar documentation (opens in a new tab) defines bundle.externalBin inputs with target-triple suffixes and exposes the packaged sidecar under its unsuffixed name at runtime. Oleafly’s Pandoc adapter resolves that packaged Tectonic executable beside the application executable, matching Tauri’s desktop bundle layout. Unit tests cover macOS app-bundle and Cargo debug/release candidates, while the release workflow inspects the staged unsuffixed sibling on every target.

Tectonic, Biber, Typst, and language-server downloads are versioned and checksum-pinned. Their fetch scripts validate archive structure and extract only the reviewed executable or resource paths. CI and release builds use the same scripts.

  1. All engines stream normalized log/error events. Rust returns compile metadata through JSON IPC. The PDF itself is fetched separately as raw binary IPC rather than embedded as base64 in the result.
  2. The frontend renders PDF bytes with pdf.js and publishes normalized diagnostics to CodeMirror.

Engine descriptors model compilation policy plus formatting/source-preflight profiles and feature/export/template-kind sets. Frontend consumers use the fail-closed files-store descriptor rather than guessing from extensions. See the document engine matrix (opens in a new tab).

Typst reports supports_synctex=true and supports_offline=true, with supports_isolated_compile=false. Source and PDF sync runs through the project’s matched Tinymist and needs Tinymist 0.13.30 or later, so typst_toolchain::describe_project lowers supports_synctex to false for a project pinned to Typst 0.11 or 0.12 (typst_sync::supported_for_project). Offline mode blocks Typst package downloads, so a compile then uses only the shared package cache and the project’s typst-packages folder. Isolated compilation stays LaTeX-only: the TikZ figure path refuses Typst projects, and the assistant’s figure tools render Typst snippets, such as a CeTZ canvas or a fletcher diagram, with render_typst_snippet instead. Add engine behavior only after the backend capability becomes truthful. Do not add extension-based UI exceptions.

  • Config: ~/.oleafly/config.json (0600 on Unix). Non-secret preferences live here.
  • Secrets: ~/.oleafly/ai-secrets.json and ~/.oleafly/app-secrets.json, encrypted with the owner-only ~/.oleafly/ai-secrets.key. GitHub and MCP share app-secrets.json. AI provider credentials use ai-secrets.json.
  • Projects: ~/.oleafly/projects/<id>/, plain folders with .git.
  • App log: ~/.oleafly/app.log.
  • Add an AI provider → update crates/oleafly-agent/src/provider.rs, then mirror its display metadata in packages/ai-core/src/providers.ts. The catalog parity test keeps the two lists aligned.
  • Add a Tauri command → declare in src-tauri/src/*.rs, register in src-tauri/src/lib.rs, wrap in src/lib/tauri.ts.
  • Add a document engine → implement DocumentEngine in src-tauri/src/document_engine.rs, expose truthful capabilities, add a checksum-pinned sidecar fetch/smoke path, then consume the descriptor in UI controls.
  • Add a project template → drop a folder with a template.json manifest into src-tauri/resources/templates/ (engine-general template metadata remains planned work).
  • Add a tool for the AI → packages/ai-tools/src/tools.ts. App services it needs go through AiToolsHost in src/lib/ai-tools.ts.
  • Add a rail tab / palette or omnibar command / AI toolset → register it in src/contributions/ (see Frontend architecture).

OAuth device flow runs server-side in Rust (src-tauri/src/github.rs) because the OAuth endpoints aren’t CORS-enabled. The API calls (api.github.com) happen from the frontend.

  • TypeScript: follow what’s already there. No comments unless asked. Respect noUnusedLocals/noUnusedParameters.
  • Rust: idiomatic, small commands, friendly error strings.
  • UI: Tailwind v4 + Geist tokens. Reuse the Button, Tooltip, and Select primitives.

Packaging targets macOS Apple Silicon, Windows x64, Linux x64, and Linux ARM64. Each build fetches and checks its compiler sidecars and bundled language-server resource. Release builds support Apple signing and notarization on macOS and Azure Artifact Signing on Windows. See releasing and user install.

Image preview

AI answers couldn’t load

Try again, or search the documentation.